diff --git a/lib/IRGen/GenConstant.cpp b/lib/IRGen/GenConstant.cpp index f9a6eae9d39..928c491c054 100644 --- a/lib/IRGen/GenConstant.cpp +++ b/lib/IRGen/GenConstant.cpp @@ -22,6 +22,7 @@ #include "GenTuple.h" #include "TypeInfo.h" #include "StructLayout.h" +#include "Callee.h" #include "swift/Basic/Range.h" #include "swift/SIL/SILModule.h" @@ -109,11 +110,67 @@ llvm::Constant *irgen::emitAddrOfConstantString(IRGenModule &IGM, llvm_unreachable("bad string encoding"); } -static llvm::Constant *emitConstantValue(IRGenModule &IGM, SILValue operand) { +namespace { + +/// Fill in the missing values for padding. +void insertPadding(SmallVectorImpl &Elements, + llvm::StructType *sTy) { + // fill in any gaps, which are the explicit padding that swiftc inserts. + for (unsigned i = 0, e = Elements.size(); i != e; ++i) { + auto &elt = Elements[i]; + if (elt == nullptr) { + auto *eltTy = sTy->getElementType(i); + assert(eltTy->isArrayTy() && + eltTy->getArrayElementType()->isIntegerTy(8) && + "Unexpected non-byte-array type for constant struct padding"); + elt = llvm::UndefValue::get(eltTy); + } + } +} + +template +llvm::Constant *emitConstantStructOrTuple(IRGenModule &IGM, InstTy inst, + NextIndexFunc nextIndex) { + auto type = inst->getType(); + auto *sTy = cast(IGM.getTypeInfo(type).getStorageType()); + + SmallVector elts(sTy->getNumElements(), nullptr); + + // run over the Swift initializers, putting them into the struct as + // appropriate. + for (unsigned i = 0, e = inst->getElements().size(); i != e; ++i) { + auto operand = inst->getOperand(i); + Optional index = nextIndex(IGM, type, i); + if (index.hasValue()) { + assert(elts[index.getValue()] == nullptr && + "Unexpected constant struct field overlap"); + + elts[index.getValue()] = emitConstantValue(IGM, operand); + } + } + insertPadding(elts, sTy); + return llvm::ConstantStruct::get(sTy, elts); +} +} // end anonymous namespace + +llvm::Constant *irgen::emitConstantValue(IRGenModule &IGM, SILValue operand) { if (auto *SI = dyn_cast(operand)) { - return emitConstantStruct(IGM, SI); + // The only way to get a struct's stored properties (which we need to map to + // their physical/LLVM index) is to iterate over the properties + // progressively. Fortunately the iteration order matches the order of + // operands in a StructInst. + auto StoredProperties = SI->getStructDecl()->getStoredProperties(); + auto Iter = StoredProperties.begin(); + + return emitConstantStructOrTuple( + IGM, SI, [&Iter](IRGenModule &IGM, SILType Type, unsigned _i) mutable { + (void)_i; + auto *FD = *Iter++; + return irgen::getPhysicalStructFieldIndex(IGM, Type, FD); + }); } else if (auto *TI = dyn_cast(operand)) { - return emitConstantTuple(IGM, TI); + return emitConstantStructOrTuple(IGM, TI, + irgen::getPhysicalTupleElementStructIndex); } else if (auto *ILI = dyn_cast(operand)) { return emitConstantInt(IGM, ILI); } else if (auto *FLI = dyn_cast(operand)) { @@ -164,70 +221,6 @@ static llvm::Constant *emitConstantValue(IRGenModule &IGM, SILValue operand) { } } -namespace { - -/// Fill in the missing values for padding. -void insertPadding(SmallVectorImpl &Elements, - llvm::StructType *sTy) { - // fill in any gaps, which are the explicit padding that swiftc inserts. - for (unsigned i = 0, e = Elements.size(); i != e; ++i) { - auto &elt = Elements[i]; - if (elt == nullptr) { - auto *eltTy = sTy->getElementType(i); - assert(eltTy->isArrayTy() && - eltTy->getArrayElementType()->isIntegerTy(8) && - "Unexpected non-byte-array type for constant struct padding"); - elt = llvm::UndefValue::get(eltTy); - } - } -} - -template -llvm::Constant *emitConstantStructOrTuple(IRGenModule &IGM, InstTy inst, - NextIndexFunc nextIndex) { - auto type = inst->getType(); - auto *sTy = cast(IGM.getTypeInfo(type).getStorageType()); - - SmallVector elts(sTy->getNumElements(), nullptr); - - // run over the Swift initializers, putting them into the struct as - // appropriate. - for (unsigned i = 0, e = inst->getElements().size(); i != e; ++i) { - auto operand = inst->getOperand(i); - Optional index = nextIndex(IGM, type, i); - if (index.hasValue()) { - assert(elts[index.getValue()] == nullptr && - "Unexpected constant struct field overlap"); - - elts[index.getValue()] = emitConstantValue(IGM, operand); - } - } - insertPadding(elts, sTy); - return llvm::ConstantStruct::get(sTy, elts); -} -} // end anonymous namespace - -llvm::Constant *irgen::emitConstantStruct(IRGenModule &IGM, StructInst *SI) { - // The only way to get a struct's stored properties (which we need to map to - // their physical/LLVM index) is to iterate over the properties - // progressively. Fortunately the iteration order matches the order of - // operands in a StructInst. - auto StoredProperties = SI->getStructDecl()->getStoredProperties(); - auto Iter = StoredProperties.begin(); - - return emitConstantStructOrTuple( - IGM, SI, [&Iter](IRGenModule &IGM, SILType Type, unsigned _i) mutable { - (void)_i; - auto *FD = *Iter++; - return irgen::getPhysicalStructFieldIndex(IGM, Type, FD); - }); -} - -llvm::Constant *irgen::emitConstantTuple(IRGenModule &IGM, TupleInst *TI) { - return emitConstantStructOrTuple(IGM, TI, - irgen::getPhysicalTupleElementStructIndex); -} - llvm::Constant *irgen::emitConstantObject(IRGenModule &IGM, ObjectInst *OI, StructLayout *ClassLayout) { auto *sTy = cast(ClassLayout->getType()); diff --git a/lib/IRGen/GenConstant.h b/lib/IRGen/GenConstant.h index 64168937260..a0dac169c37 100644 --- a/lib/IRGen/GenConstant.h +++ b/lib/IRGen/GenConstant.h @@ -37,11 +37,8 @@ llvm::Constant *emitConstantFP(IRGenModule &IGM, FloatLiteralInst *FLI); llvm::Constant *emitAddrOfConstantString(IRGenModule &IGM, StringLiteralInst *SLI); -/// Construct a struct literal from a StructInst containing constant values. -llvm::Constant *emitConstantStruct(IRGenModule &IGM, StructInst *SI); - -/// Construct a struct literal from a TupleInst containing constant values. -llvm::Constant *emitConstantTuple(IRGenModule &IGM, TupleInst *TI); +/// Construct a constant from a SILValue containing constant values. +llvm::Constant *emitConstantValue(IRGenModule &IGM, SILValue value); /// Construct an object (with a HeapObject header) from an ObjectInst /// containing constant values. diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index 1a4caa44778..69614be8932 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -6414,17 +6414,8 @@ void IRGenModule::emitSILStaticInitializers() { continue; } - // Set the IR global's initializer to the constant for this SIL - // struct. - if (auto *SI = dyn_cast(InitValue)) { - IRGlobal->setInitializer(emitConstantStruct(*this, SI)); - continue; - } - - // Set the IR global's initializer to the constant for this SIL - // tuple. - auto *TI = cast(InitValue); - IRGlobal->setInitializer(emitConstantTuple(*this, TI)); + IRGlobal->setInitializer( + emitConstantValue(*this, cast(InitValue))); } }