IRGen: a small refactoring in GenConstant

Just moving a few functions around and make emitConstantValue the main entry point for creating constants.

NFC
This commit is contained in:
Erik Eckstein
2021-02-05 11:56:23 +01:00
parent 65b03f9815
commit 44f07aea2b
3 changed files with 64 additions and 83 deletions

View File

@@ -22,6 +22,7 @@
#include "GenTuple.h" #include "GenTuple.h"
#include "TypeInfo.h" #include "TypeInfo.h"
#include "StructLayout.h" #include "StructLayout.h"
#include "Callee.h"
#include "swift/Basic/Range.h" #include "swift/Basic/Range.h"
#include "swift/SIL/SILModule.h" #include "swift/SIL/SILModule.h"
@@ -109,11 +110,67 @@ llvm::Constant *irgen::emitAddrOfConstantString(IRGenModule &IGM,
llvm_unreachable("bad string encoding"); llvm_unreachable("bad string encoding");
} }
static llvm::Constant *emitConstantValue(IRGenModule &IGM, SILValue operand) { namespace {
/// Fill in the missing values for padding.
void insertPadding(SmallVectorImpl<llvm::Constant *> &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 <typename InstTy, typename NextIndexFunc>
llvm::Constant *emitConstantStructOrTuple(IRGenModule &IGM, InstTy inst,
NextIndexFunc nextIndex) {
auto type = inst->getType();
auto *sTy = cast<llvm::StructType>(IGM.getTypeInfo(type).getStorageType());
SmallVector<llvm::Constant *, 32> 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<unsigned> 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<StructInst>(operand)) { if (auto *SI = dyn_cast<StructInst>(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<TupleInst>(operand)) { } else if (auto *TI = dyn_cast<TupleInst>(operand)) {
return emitConstantTuple(IGM, TI); return emitConstantStructOrTuple(IGM, TI,
irgen::getPhysicalTupleElementStructIndex);
} else if (auto *ILI = dyn_cast<IntegerLiteralInst>(operand)) { } else if (auto *ILI = dyn_cast<IntegerLiteralInst>(operand)) {
return emitConstantInt(IGM, ILI); return emitConstantInt(IGM, ILI);
} else if (auto *FLI = dyn_cast<FloatLiteralInst>(operand)) { } else if (auto *FLI = dyn_cast<FloatLiteralInst>(operand)) {
@@ -164,70 +221,6 @@ static llvm::Constant *emitConstantValue(IRGenModule &IGM, SILValue operand) {
} }
} }
namespace {
/// Fill in the missing values for padding.
void insertPadding(SmallVectorImpl<llvm::Constant *> &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 <typename InstTy, typename NextIndexFunc>
llvm::Constant *emitConstantStructOrTuple(IRGenModule &IGM, InstTy inst,
NextIndexFunc nextIndex) {
auto type = inst->getType();
auto *sTy = cast<llvm::StructType>(IGM.getTypeInfo(type).getStorageType());
SmallVector<llvm::Constant *, 32> 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<unsigned> 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, llvm::Constant *irgen::emitConstantObject(IRGenModule &IGM, ObjectInst *OI,
StructLayout *ClassLayout) { StructLayout *ClassLayout) {
auto *sTy = cast<llvm::StructType>(ClassLayout->getType()); auto *sTy = cast<llvm::StructType>(ClassLayout->getType());

View File

@@ -37,11 +37,8 @@ llvm::Constant *emitConstantFP(IRGenModule &IGM, FloatLiteralInst *FLI);
llvm::Constant *emitAddrOfConstantString(IRGenModule &IGM, llvm::Constant *emitAddrOfConstantString(IRGenModule &IGM,
StringLiteralInst *SLI); StringLiteralInst *SLI);
/// Construct a struct literal from a StructInst containing constant values. /// Construct a constant from a SILValue containing constant values.
llvm::Constant *emitConstantStruct(IRGenModule &IGM, StructInst *SI); llvm::Constant *emitConstantValue(IRGenModule &IGM, SILValue value);
/// Construct a struct literal from a TupleInst containing constant values.
llvm::Constant *emitConstantTuple(IRGenModule &IGM, TupleInst *TI);
/// Construct an object (with a HeapObject header) from an ObjectInst /// Construct an object (with a HeapObject header) from an ObjectInst
/// containing constant values. /// containing constant values.

View File

@@ -6414,17 +6414,8 @@ void IRGenModule::emitSILStaticInitializers() {
continue; continue;
} }
// Set the IR global's initializer to the constant for this SIL IRGlobal->setInitializer(
// struct. emitConstantValue(*this, cast<SingleValueInstruction>(InitValue)));
if (auto *SI = dyn_cast<StructInst>(InitValue)) {
IRGlobal->setInitializer(emitConstantStruct(*this, SI));
continue;
}
// Set the IR global's initializer to the constant for this SIL
// tuple.
auto *TI = cast<TupleInst>(InitValue);
IRGlobal->setInitializer(emitConstantTuple(*this, TI));
} }
} }