1616
1717#include " llvm/IR/Constants.h"
1818
19+ #include " BitPatternReader.h"
20+ #include " Explosion.h"
1921#include " GenConstant.h"
22+ #include " GenEnum.h"
2023#include " GenIntegerLiteral.h"
2124#include " GenStruct.h"
2225#include " GenTuple.h"
@@ -115,43 +118,83 @@ llvm::Constant *irgen::emitAddrOfConstantString(IRGenModule &IGM,
115118namespace {
116119
117120// / Fill in the missing values for padding.
118- void insertPadding (SmallVectorImpl<llvm::Constant * > &Elements ,
121+ void insertPadding (SmallVectorImpl<Explosion > &elements ,
119122 llvm::StructType *sTy ) {
120123 // fill in any gaps, which are the explicit padding that swiftc inserts.
121- for (unsigned i = 0 , e = Elements.size (); i != e; ++i) {
122- auto &elt = Elements[i];
123- if (elt == nullptr ) {
124+ for (unsigned i = 0 , e = elements.size (); i != e; ++i) {
125+ if (elements[i].empty ()) {
124126 auto *eltTy = sTy ->getElementType (i);
125127 assert (eltTy->isArrayTy () &&
126128 eltTy->getArrayElementType ()->isIntegerTy (8 ) &&
127129 " Unexpected non-byte-array type for constant struct padding" );
128- elt = llvm::UndefValue::get (eltTy);
130+ elements[i]. add ( llvm::UndefValue::get (eltTy) );
129131 }
130132 }
131133}
132134
135+ // / Creates a struct which contains all values of `explosions`.
136+ // /
137+ // / If all explosions have a single element and those elements match the
138+ // / elements of `structTy`, it uses this type as result type.
139+ // / Otherwise, it creates an anonymous struct. This can be the case for enums.
140+ llvm::Constant *createStructFromExplosion (SmallVectorImpl<Explosion> &explosions,
141+ llvm::StructType *structTy) {
142+ assert (explosions.size () == structTy->getNumElements ());
143+ bool canUseStructType = true ;
144+ llvm::SmallVector<llvm::Constant *, 32 > values;
145+ unsigned idx = 0 ;
146+ for (auto &elmt : explosions) {
147+ if (elmt.size () != 1 )
148+ canUseStructType = false ;
149+ for (llvm::Value *v : elmt.claimAll ()) {
150+ if (v->getType () != structTy->getElementType (idx))
151+ canUseStructType = false ;
152+ values.push_back (cast<llvm::Constant>(v));
153+ }
154+ idx++;
155+ }
156+ if (canUseStructType) {
157+ return llvm::ConstantStruct::get (structTy, values);
158+ } else {
159+ return llvm::ConstantStruct::getAnon (values, /* Packed=*/ true );
160+ }
161+ }
162+
163+ void initWithEmptyExplosions (SmallVectorImpl<Explosion> &explosions,
164+ unsigned count) {
165+ for (unsigned i = 0 ; i < count; i++) {
166+ explosions.push_back (Explosion ());
167+ }
168+ }
169+
133170template <typename InstTy, typename NextIndexFunc>
134- llvm::Constant * emitConstantStructOrTuple (IRGenModule &IGM, InstTy inst,
135- NextIndexFunc nextIndex) {
171+ Explosion emitConstantStructOrTuple (IRGenModule &IGM, InstTy inst,
172+ NextIndexFunc nextIndex, bool flatten ) {
136173 auto type = inst->getType ();
137174 auto *sTy = cast<llvm::StructType>(IGM.getTypeInfo (type).getStorageType ());
138175
139- SmallVector<llvm::Constant *, 32 > elts (sTy ->getNumElements (), nullptr );
176+ SmallVector<Explosion, 32 > elements;
177+ initWithEmptyExplosions (elements, sTy ->getNumElements ());
140178
141- // run over the Swift initializers, putting them into the struct as
142- // appropriate.
143179 for (unsigned i = 0 , e = inst->getElements ().size (); i != e; ++i) {
144180 auto operand = inst->getOperand (i);
145181 Optional<unsigned > index = nextIndex (IGM, type, i);
146182 if (index.has_value ()) {
147- assert (elts[index.value ()] == nullptr &&
183+ unsigned idx = index.value ();
184+ assert (elements[idx].empty () &&
148185 " Unexpected constant struct field overlap" );
149-
150- elts[index.value ()] = emitConstantValue (IGM, operand);
186+ elements[idx] = emitConstantValue (IGM, operand, flatten);
187+ }
188+ }
189+ if (flatten) {
190+ Explosion out;
191+ for (auto &elmt : elements) {
192+ out.add (elmt.claimAll ());
151193 }
194+ return out;
152195 }
153- insertPadding (elts , sTy );
154- return llvm::ConstantStruct::get ( sTy , elts );
196+ insertPadding (elements , sTy );
197+ return createStructFromExplosion (elements, sTy );
155198}
156199} // end anonymous namespace
157200
@@ -181,7 +224,36 @@ static BuiltinInst *getOffsetSubtract(const TupleExtractInst *TE, SILModule &M)
181224 return BI;
182225}
183226
184- llvm::Constant *irgen::emitConstantValue (IRGenModule &IGM, SILValue operand) {
227+ static bool isPowerOfTwo (unsigned x) {
228+ return (x & -x) == x;
229+ }
230+
231+ // / Replace i24, i40, i48 and i56 constants in `e` with the corresponding byte values.
232+ // / Such unaligned integer constants are not correctly layed out in the data section.
233+ static Explosion replaceUnalignedIntegerValues (IRGenModule &IGM, Explosion e) {
234+ Explosion out;
235+ while (!e.empty ()) {
236+ llvm::Value *v = e.claimNext ();
237+
238+ if (auto *constInt = dyn_cast<llvm::ConstantInt>(v)) {
239+ unsigned size = constInt->getBitWidth ();
240+ if (size % 8 == 0 && !isPowerOfTwo (size)) {
241+ BitPatternReader reader (constInt->getValue (), IGM.Triple .isLittleEndian ());
242+ while (size > 0 ) {
243+ APInt byte = reader.read (8 );
244+ out.add (llvm::ConstantInt::get (IGM.getLLVMContext (), byte));
245+ size -= 8 ;
246+ }
247+ continue ;
248+ }
249+ }
250+ out.add (v);
251+ }
252+ return out;
253+ }
254+
255+ Explosion irgen::emitConstantValue (IRGenModule &IGM, SILValue operand,
256+ bool flatten) {
185257 if (auto *SI = dyn_cast<StructInst>(operand)) {
186258 // The only way to get a struct's stored properties (which we need to map to
187259 // their physical/LLVM index) is to iterate over the properties
@@ -195,64 +267,83 @@ llvm::Constant *irgen::emitConstantValue(IRGenModule &IGM, SILValue operand) {
195267 (void )_i;
196268 auto *FD = *Iter++;
197269 return irgen::getPhysicalStructFieldIndex (IGM, Type, FD);
198- });
270+ }, flatten );
199271 } else if (auto *TI = dyn_cast<TupleInst>(operand)) {
200272 return emitConstantStructOrTuple (IGM, TI,
201- irgen::getPhysicalTupleElementStructIndex);
273+ irgen::getPhysicalTupleElementStructIndex,
274+ flatten);
275+ } else if (auto *ei = dyn_cast<EnumInst>(operand)) {
276+ Explosion data;
277+ if (ei->hasOperand ()) {
278+ data = emitConstantValue (IGM, ei->getOperand (), /* flatten=*/ true );
279+ }
280+ // Use `emitValueInjection` to create the enum constant.
281+ // Usually this method creates code in the current function. But if all
282+ // arguments to the enum are constant, the builder never has to emit an
283+ // instruction. Instead it can constant fold everything and just returns
284+ // the final constant.
285+ Explosion out;
286+ IRBuilder builder (IGM.getLLVMContext (), false );
287+ getEnumImplStrategy (IGM, ei->getType ())
288+ .emitValueInjection (IGM, builder, ei->getElement (), data, out);
289+ return replaceUnalignedIntegerValues (IGM, std::move (out));
202290 } else if (auto *ILI = dyn_cast<IntegerLiteralInst>(operand)) {
203291 return emitConstantInt (IGM, ILI);
204292 } else if (auto *FLI = dyn_cast<FloatLiteralInst>(operand)) {
205293 return emitConstantFP (IGM, FLI);
206294 } else if (auto *SLI = dyn_cast<StringLiteralInst>(operand)) {
207295 return emitAddrOfConstantString (IGM, SLI);
208296 } else if (auto *BI = dyn_cast<BuiltinInst>(operand)) {
297+ auto args = BI->getArguments ();
209298 switch (IGM.getSILModule ().getBuiltinInfo (BI->getName ()).ID ) {
210299 case BuiltinValueKind::ZeroInitializer:
211300 return emitConstantZero (IGM, BI);
212301 case BuiltinValueKind::PtrToInt: {
213- llvm::Constant *ptr = emitConstantValue (IGM, BI-> getArguments () [0 ]);
302+ auto *ptr = emitConstantValue (IGM, args [0 ]). claimNextConstant ( );
214303 return llvm::ConstantExpr::getPtrToInt (ptr, IGM.IntPtrTy );
215304 }
216305 case BuiltinValueKind::ZExtOrBitCast: {
217- llvm::Constant *value = emitConstantValue (IGM, BI->getArguments ()[0 ]);
218- return llvm::ConstantExpr::getZExtOrBitCast (value, IGM.getStorageType (BI->getType ()));
306+ auto *val = emitConstantValue (IGM, args[0 ]).claimNextConstant ();
307+ return llvm::ConstantExpr::getZExtOrBitCast (val,
308+ IGM.getStorageType (BI->getType ()));
219309 }
220310 case BuiltinValueKind::StringObjectOr: {
221311 // It is a requirement that the or'd bits in the left argument are
222312 // initialized with 0. Therefore the or-operation is equivalent to an
223313 // addition. We need an addition to generate a valid relocation.
224- llvm::Constant *rhs = emitConstantValue (IGM, BI-> getArguments () [1 ]);
225- if (auto *TE = dyn_cast<TupleExtractInst>(BI-> getArguments () [0 ])) {
314+ auto *rhs = emitConstantValue (IGM, args [1 ]). claimNextConstant ( );
315+ if (auto *TE = dyn_cast<TupleExtractInst>(args [0 ])) {
226316 // Handle StringObjectOr(tuple_extract(usub_with_overflow(x, offset)), bits)
227317 // This pattern appears in UTF8 String literal construction.
228318 // Generate the equivalent: add(x, sub(bits - offset)
229319 BuiltinInst *SubtrBI = getOffsetSubtract (TE, IGM.getSILModule ());
230320 assert (SubtrBI && " unsupported argument of StringObjectOr" );
231- auto *ptr = emitConstantValue (IGM, SubtrBI->getArguments ()[0 ]);
232- auto *offset = emitConstantValue (IGM, SubtrBI->getArguments ()[1 ]);
321+ auto subArgs = SubtrBI->getArguments ();
322+ auto *ptr = emitConstantValue (IGM, subArgs[0 ]).claimNextConstant ();
323+ auto *offset = emitConstantValue (IGM, subArgs[1 ]).claimNextConstant ();
233324 auto *totalOffset = llvm::ConstantExpr::getSub (rhs, offset);
234325 return llvm::ConstantExpr::getAdd (ptr, totalOffset);
235326 }
236- llvm::Constant *lhs = emitConstantValue (IGM, BI-> getArguments () [0 ]);
327+ auto *lhs = emitConstantValue (IGM, args [0 ]). claimNextConstant ( );
237328 return llvm::ConstantExpr::getAdd (lhs, rhs);
238329 }
239330 default :
240331 llvm_unreachable (" unsupported builtin for constant expression" );
241332 }
242333 } else if (auto *VTBI = dyn_cast<ValueToBridgeObjectInst>(operand)) {
243- auto *val = emitConstantValue (IGM, VTBI->getOperand ());
334+ auto *val = emitConstantValue (IGM, VTBI->getOperand ()). claimNextConstant () ;
244335 auto *sTy = IGM.getTypeInfo (VTBI->getType ()).getStorageType ();
245336 return llvm::ConstantExpr::getIntToPtr (val, sTy );
246337
247338 } else if (auto *CFI = dyn_cast<ConvertFunctionInst>(operand)) {
248- return emitConstantValue (IGM, CFI->getOperand ());
339+ return emitConstantValue (IGM, CFI->getOperand ()). claimNextConstant () ;
249340
250341 } else if (auto *T2TFI = dyn_cast<ThinToThickFunctionInst>(operand)) {
251342 SILType type = operand->getType ();
252343 auto *sTy = cast<llvm::StructType>(IGM.getTypeInfo (type).getStorageType ());
253344
254345 auto *function = llvm::ConstantExpr::getBitCast (
255- emitConstantValue (IGM, T2TFI->getCallee ()),
346+ emitConstantValue (IGM, T2TFI->getCallee ()). claimNextConstant () ,
256347 sTy ->getTypeAtIndex ((unsigned )0 ));
257348
258349 auto *context = llvm::ConstantExpr::getBitCast (
@@ -287,7 +378,9 @@ llvm::Constant *irgen::emitConstantValue(IRGenModule &IGM, SILValue operand) {
287378llvm::Constant *irgen::emitConstantObject (IRGenModule &IGM, ObjectInst *OI,
288379 StructLayout *ClassLayout) {
289380 auto *sTy = cast<llvm::StructType>(ClassLayout->getType ());
290- SmallVector<llvm::Constant *, 32 > elts (sTy ->getNumElements (), nullptr );
381+
382+ SmallVector<Explosion, 32 > elements;
383+ initWithEmptyExplosions (elements, sTy ->getNumElements ());
291384
292385 unsigned NumElems = OI->getAllElements ().size ();
293386 assert (NumElems == ClassLayout->getElements ().size ());
@@ -297,9 +390,11 @@ llvm::Constant *irgen::emitConstantObject(IRGenModule &IGM, ObjectInst *OI,
297390 SILValue Val = OI->getAllElements ()[i];
298391 const ElementLayout &EL = ClassLayout->getElements ()[i];
299392 if (!EL.isEmpty ()) {
300- unsigned EltIdx = EL.getStructIndex ();
301- assert (EltIdx != 0 && " the first element is the object header" );
302- elts[EltIdx] = emitConstantValue (IGM, Val);
393+ unsigned idx = EL.getStructIndex ();
394+ assert (idx != 0 && " the first element is the object header" );
395+ assert (elements[idx].empty () &&
396+ " Unexpected constant struct field overlap" );
397+ elements[idx] = emitConstantValue (IGM, Val);
303398 }
304399 }
305400 // Construct the object header.
@@ -322,14 +417,14 @@ llvm::Constant *irgen::emitConstantObject(IRGenModule &IGM, ObjectInst *OI,
322417 /* initializer*/ nullptr , " $ss19__EmptyArrayStorageCN" );
323418 IGM.swiftStaticArrayMetadata = var;
324419 }
325- elts [0 ] = llvm::ConstantStruct::get (ObjectHeaderTy, {
420+ elements [0 ]. add ( llvm::ConstantStruct::get (ObjectHeaderTy, {
326421 IGM.swiftStaticArrayMetadata ,
327- llvm::ConstantExpr::getPtrToInt (IGM.swiftImmortalRefCount , IGM.IntPtrTy )});
422+ llvm::ConstantExpr::getPtrToInt (IGM.swiftImmortalRefCount , IGM.IntPtrTy )})) ;
328423 } else {
329- elts [0 ] = llvm::Constant::getNullValue (ObjectHeaderTy);
424+ elements [0 ]. add ( llvm::Constant::getNullValue (ObjectHeaderTy) );
330425 }
331- insertPadding (elts , sTy );
332- return llvm::ConstantStruct::get ( sTy , elts );
426+ insertPadding (elements , sTy );
427+ return createStructFromExplosion (elements, sTy );
333428}
334429
335430void ConstantAggregateBuilderBase::addUniqueHash (StringRef data) {
0 commit comments