Refactor ConstantInitBuilder to allow other frontends to more
easily extend the aggregate-builder API. Stupid missing language
features.
Also add APIs for constructing a relative reference and computing
the offset of a position from the start of the initializer.
llvm-svn: 296979
diff --git a/clang/lib/CodeGen/ConstantInitBuilder.cpp b/clang/lib/CodeGen/ConstantInitBuilder.cpp
index 772391e..d1a707b 100644
--- a/clang/lib/CodeGen/ConstantInitBuilder.cpp
+++ b/clang/lib/CodeGen/ConstantInitBuilder.cpp
@@ -20,12 +20,12 @@
using namespace CodeGen;
llvm::GlobalVariable *
-ConstantInitBuilder::createGlobal(llvm::Constant *initializer,
- const llvm::Twine &name,
- CharUnits alignment,
- bool constant,
- llvm::GlobalValue::LinkageTypes linkage,
- unsigned addressSpace) {
+ConstantInitBuilderBase::createGlobal(llvm::Constant *initializer,
+ const llvm::Twine &name,
+ CharUnits alignment,
+ bool constant,
+ llvm::GlobalValue::LinkageTypes linkage,
+ unsigned addressSpace) {
auto GV = new llvm::GlobalVariable(CGM.getModule(),
initializer->getType(),
constant,
@@ -40,15 +40,15 @@
return GV;
}
-void ConstantInitBuilder::setGlobalInitializer(llvm::GlobalVariable *GV,
- llvm::Constant *initializer) {
+void ConstantInitBuilderBase::setGlobalInitializer(llvm::GlobalVariable *GV,
+ llvm::Constant *initializer){
GV->setInitializer(initializer);
if (!SelfReferences.empty())
resolveSelfReferences(GV);
}
-void ConstantInitBuilder::resolveSelfReferences(llvm::GlobalVariable *GV) {
+void ConstantInitBuilderBase::resolveSelfReferences(llvm::GlobalVariable *GV) {
for (auto &entry : SelfReferences) {
llvm::Constant *resolvedReference =
llvm::ConstantExpr::getInBoundsGetElementPtr(
@@ -58,13 +58,31 @@
}
}
-void ConstantInitBuilder::AggregateBuilderBase::addSize(CharUnits size) {
+void ConstantAggregateBuilderBase::addSize(CharUnits size) {
add(Builder.CGM.getSize(size));
}
llvm::Constant *
-ConstantInitBuilder::AggregateBuilderBase::getAddrOfCurrentPosition(
- llvm::Type *type) {
+ConstantAggregateBuilderBase::getRelativeOffset(llvm::IntegerType *offsetType,
+ llvm::Constant *target) {
+ // Compute the address of the relative-address slot.
+ auto base = getAddrOfCurrentPosition(offsetType);
+
+ // Subtract.
+ base = llvm::ConstantExpr::getPtrToInt(base, Builder.CGM.IntPtrTy);
+ target = llvm::ConstantExpr::getPtrToInt(target, Builder.CGM.IntPtrTy);
+ llvm::Constant *offset = llvm::ConstantExpr::getSub(target, base);
+
+ // Truncate to the relative-address type if necessary.
+ if (Builder.CGM.IntPtrTy != offsetType) {
+ offset = llvm::ConstantExpr::getTrunc(offset, offsetType);
+ }
+
+ return offset;
+}
+
+llvm::Constant *
+ConstantAggregateBuilderBase::getAddrOfCurrentPosition(llvm::Type *type) {
// Make a global variable. We will replace this with a GEP to this
// position after installing the initializer.
auto dummy =
@@ -77,7 +95,7 @@
return dummy;
}
-void ConstantInitBuilder::AggregateBuilderBase::getGEPIndicesTo(
+void ConstantAggregateBuilderBase::getGEPIndicesTo(
llvm::SmallVectorImpl<llvm::Constant*> &indices,
size_t position) const {
// Recurse on the parent builder if present.
@@ -97,22 +115,64 @@
position - Begin));
}
-llvm::Constant *ConstantArrayBuilder::finishImpl() {
+CharUnits ConstantAggregateBuilderBase::getOffsetFromGlobalTo(size_t end) const{
+ size_t cacheEnd = CachedOffsetEnd;
+ assert(cacheEnd <= end);
+
+ // Fast path: if the cache is valid, just use it.
+ if (cacheEnd == end) {
+ return CachedOffsetFromGlobal;
+ }
+
+ // If the cached range ends before the index at which the current
+ // aggregate starts, recurse for the parent.
+ CharUnits offset;
+ if (cacheEnd < Begin) {
+ assert(cacheEnd == 0);
+ assert(Parent && "Begin != 0 for root builder");
+ cacheEnd = Begin;
+ offset = Parent->getOffsetFromGlobalTo(Begin);
+ } else {
+ offset = CachedOffsetFromGlobal;
+ }
+
+ // Perform simple layout on the elements in cacheEnd..<end.
+ if (cacheEnd != end) {
+ auto &layout = Builder.CGM.getDataLayout();
+ do {
+ llvm::Constant *element = Builder.Buffer[cacheEnd];
+ assert(element != nullptr &&
+ "cannot compute offset when a placeholder is present");
+ llvm::Type *elementType = element->getType();
+ offset = offset.alignTo(CharUnits::fromQuantity(
+ layout.getABITypeAlignment(elementType)));
+ offset += CharUnits::fromQuantity(layout.getTypeStoreSize(elementType));
+ } while (++cacheEnd != end);
+ }
+
+ // Cache and return.
+ CachedOffsetEnd = cacheEnd;
+ CachedOffsetFromGlobal = offset;
+ return offset;
+}
+
+llvm::Constant *ConstantAggregateBuilderBase::finishArray(llvm::Type *eltTy) {
markFinished();
auto &buffer = getBuffer();
assert((Begin < buffer.size() ||
- (Begin == buffer.size() && EltTy))
+ (Begin == buffer.size() && eltTy))
&& "didn't add any array elements without element type");
auto elts = llvm::makeArrayRef(buffer).slice(Begin);
- auto eltTy = EltTy ? EltTy : elts[0]->getType();
+ if (!eltTy) eltTy = elts[0]->getType();
auto type = llvm::ArrayType::get(eltTy, elts.size());
auto constant = llvm::ConstantArray::get(type, elts);
buffer.erase(buffer.begin() + Begin, buffer.end());
return constant;
}
-llvm::Constant *ConstantStructBuilder::finishImpl() {
+llvm::Constant *
+ConstantAggregateBuilderBase::finishStruct(llvm::StructType *ty) {
markFinished();
auto &buffer = getBuffer();
@@ -120,8 +180,8 @@
auto elts = llvm::makeArrayRef(buffer).slice(Begin);
llvm::Constant *constant;
- if (Ty) {
- constant = llvm::ConstantStruct::get(Ty, elts);
+ if (ty) {
+ constant = llvm::ConstantStruct::get(ty, elts);
} else {
constant = llvm::ConstantStruct::getAnon(elts, /*packed*/ false);
}