Skip to content

Commit f22d6d7

Browse files
authored
Merge pull request swiftlang#63532 from nate-chandler/variadic-generics/irgen/tuple_pack_element_addr
[IRGen] Lowered tuple_pack_element_addr.
2 parents 8eebb5b + 7acc339 commit f22d6d7

File tree

2 files changed

+57
-16
lines changed

2 files changed

+57
-16
lines changed

lib/IRGen/GenTuple.cpp

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -73,22 +73,37 @@ namespace {
7373
/// Project a tuple offset from a tuple metadata structure.
7474
static llvm::Value *loadTupleOffsetFromMetadata(IRGenFunction &IGF,
7575
llvm::Value *metadata,
76-
unsigned index) {
76+
llvm::Value *index) {
7777
auto asTuple = IGF.Builder.CreateBitCast(metadata,
7878
IGF.IGM.TupleTypeMetadataPtrTy);
7979

8080
llvm::Value *indices[] = {
81-
IGF.IGM.getSize(Size(0)), // (*tupleType)
82-
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 3), // .Elements
83-
IGF.IGM.getSize(Size(index)), // [index]
84-
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 1) // .Offset
81+
IGF.IGM.getSize(Size(0)), // (*tupleType)
82+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 3), // .Elements
83+
index, // [index]
84+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 1) // .Offset
8585
};
8686
auto slot = IGF.Builder.CreateInBoundsGEP(IGF.IGM.TupleTypeMetadataTy,
8787
asTuple, indices);
8888

89-
return IGF.Builder.CreateLoad(
90-
slot, IGF.IGM.Int32Ty, IGF.IGM.getPointerAlignment(),
91-
metadata->getName() + "." + Twine(index) + ".offset");
89+
Twine name = [&]() -> Twine {
90+
if (auto *constantIndex = dyn_cast<llvm::ConstantInt>(index)) {
91+
return metadata->getName() + "." +
92+
Twine(constantIndex->getValue().getLimitedValue()) + ".offset";
93+
} else {
94+
return metadata->getName() + ".dynamic.offset";
95+
}
96+
}();
97+
98+
return IGF.Builder.CreateLoad(slot, IGF.IGM.Int32Ty,
99+
IGF.IGM.getPointerAlignment(), name);
100+
}
101+
102+
static llvm::Value *loadTupleOffsetFromMetadata(IRGenFunction &IGF,
103+
llvm::Value *metadata,
104+
unsigned index) {
105+
return loadTupleOffsetFromMetadata(IGF, metadata,
106+
IGF.IGM.getSize(Size(index)));
92107
}
93108

94109
/// Adapter for tuple types.
@@ -494,14 +509,12 @@ Address irgen::projectTupleElementAddressByDynamicIndex(IRGenFunction &IGF,
494509
SILType tupleType,
495510
llvm::Value *index,
496511
SILType elementType) {
497-
// TODO: retrieve type metadata (ForLayout) for the tuple type
498-
// and retrieve the field offset for the given index. Consider
499-
// special-casing constant indices if we can reason statically
500-
// about the prior elements. It's probably not necessary to try
501-
// to handle fixed-size tuples specially, because the optimizer
502-
// should ideally be lowering this operation to something static
503-
// in that case.
504-
llvm_unreachable("unimplemented");
512+
auto *metadata = IGF.emitTypeMetadataRefForLayout(tupleType);
513+
514+
llvm::Value *offset = loadTupleOffsetFromMetadata(IGF, metadata, index);
515+
auto *gep =
516+
IGF.emitByteOffsetGEP(tuple.getAddress(), offset, IGF.IGM.OpaqueTy);
517+
return Address(gep, IGF.IGM.OpaqueTy, IGF.IGM.getPointerAlignment());
505518
}
506519

507520
Optional<Size> irgen::getFixedTupleElementOffset(IRGenModule &IGM,

test/IRGen/variadic_generics.sil

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,31 @@ bb0(%pack : $*Pack{Int, repeat each T, Int}, %value : $Int):
106106
%ret = tuple ()
107107
return %ret : $()
108108
}
109+
110+
sil @borrow : $<T> (@in_guaranteed T) -> () {
111+
entry(%addr : $*T):
112+
%ret = tuple ()
113+
return %ret : $()
114+
}
115+
116+
// CHECK-LABEL: define {{.*}}@test_tuple_pack_element_addr_1(
117+
// CHECK-SAME: {{.*}}* nocapture [[TUPLE_ADDR:%[^,]+]], i{{(64|32)}} [[INDEX:%[^,]+]]
118+
// CHECK: [[RESPONSE:%[^,]+]] = call swiftcc %swift.metadata_response @swift_getTupleTypeMetadata
119+
// CHECK: [[UNCAST_METADATA:%[^,]+]] = extractvalue %swift.metadata_response [[RESPONSE]], 0
120+
// CHECK: [[METADATA:%[^,]+]] = bitcast %swift.type* [[UNCAST_METADATA]] to %swift.tuple_type*
121+
// CHECK: [[OFFSET_PTR:%[^,]+]] = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* [[METADATA]], i{{(64|32)}} 0, i32 3, i{{(64|32)}} [[INDEX]]
122+
// CHECK: [[OFFSET:%[^,]+]] = load i32, i32* [[OFFSET_PTR]], align 8
123+
// CHECK: [[CAST_TUPLE_ADDR:%[^,]+]] = bitcast <{ %TSS }>* [[TUPLE_ADDR]] to i8*
124+
// CHECK: [[UNCAST_ELEMENT_ADDR:%[^,]+]] = getelementptr inbounds i8, i8* [[CAST_TUPLE_ADDR]], i32 [[OFFSET]]
125+
// CHECK: [[ELEMENT_ADDR:%[^,]+]] = bitcast i8* [[UNCAST_ELEMENT_ADDR]] to %swift.opaque*
126+
// CHECK: call swiftcc void @borrow(%swift.opaque* noalias nocapture [[ELEMENT_ADDR]], %swift.type* %"\CF\84_1_0")
127+
sil @test_tuple_pack_element_addr_1 : $<T, U> (@inout (String, T, U, Int), Builtin.Word) -> () {
128+
bb0(%tuple : $*(String, T, U, Int), %i : $Builtin.Word):
129+
%index = dynamic_pack_index %i of $Pack{Float, T, U, Float}
130+
%0 = open_pack_element %index of <U_1...> at <Pack{String, T, U, Int}>, shape $U_1, uuid "01234567-89AB-CDEF-0123-000000000004"
131+
%elt = tuple_pack_element_addr %index of %tuple : $*(String, T, U, Int) as $*@pack_element("01234567-89AB-CDEF-0123-000000000004") U_1
132+
%blackhole = function_ref @borrow : $@convention(thin) <T> (@in_guaranteed T) -> ()
133+
apply %blackhole<(@pack_element("01234567-89AB-CDEF-0123-000000000004") U_1)>(%elt) : $@convention(thin) <T> (@in_guaranteed T) -> ()
134+
%ret = tuple ()
135+
return %ret : $()
136+
}

0 commit comments

Comments
 (0)