@@ -73,22 +73,37 @@ namespace {
73
73
// / Project a tuple offset from a tuple metadata structure.
74
74
static llvm::Value *loadTupleOffsetFromMetadata (IRGenFunction &IGF,
75
75
llvm::Value *metadata,
76
- unsigned index) {
76
+ llvm::Value * index) {
77
77
auto asTuple = IGF.Builder .CreateBitCast (metadata,
78
78
IGF.IGM .TupleTypeMetadataPtrTy );
79
79
80
80
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
85
85
};
86
86
auto slot = IGF.Builder .CreateInBoundsGEP (IGF.IGM .TupleTypeMetadataTy ,
87
87
asTuple, indices);
88
88
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)));
92
107
}
93
108
94
109
// / Adapter for tuple types.
@@ -494,14 +509,12 @@ Address irgen::projectTupleElementAddressByDynamicIndex(IRGenFunction &IGF,
494
509
SILType tupleType,
495
510
llvm::Value *index,
496
511
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 ());
505
518
}
506
519
507
520
Optional<Size> irgen::getFixedTupleElementOffset (IRGenModule &IGM,
0 commit comments