summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/ConstantInitBuilder.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2017-03-06 19:04:16 +0000
committerJohn McCall <rjmccall@apple.com>2017-03-06 19:04:16 +0000
commit262f96225279ce684c816ca9b0e35732c9320b11 (patch)
treecd7bd552d4360419b4bee975b51294e0c038cfbf /clang/lib/CodeGen/ConstantInitBuilder.cpp
parent692b2f88d3e99a231bd6f14f359b682cdf94d61e (diff)
downloadbcm5719-llvm-262f96225279ce684c816ca9b0e35732c9320b11.tar.gz
bcm5719-llvm-262f96225279ce684c816ca9b0e35732c9320b11.zip
Further fixes and improvements to the ConstantInitBuilder API.
llvm-svn: 297050
Diffstat (limited to 'clang/lib/CodeGen/ConstantInitBuilder.cpp')
-rw-r--r--clang/lib/CodeGen/ConstantInitBuilder.cpp101
1 files changed, 95 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/ConstantInitBuilder.cpp b/clang/lib/CodeGen/ConstantInitBuilder.cpp
index d1a707b3239..7f8d8098503 100644
--- a/clang/lib/CodeGen/ConstantInitBuilder.cpp
+++ b/clang/lib/CodeGen/ConstantInitBuilder.cpp
@@ -19,6 +19,51 @@
using namespace clang;
using namespace CodeGen;
+llvm::Type *ConstantInitFuture::getType() const {
+ assert(Data && "dereferencing null future");
+ if (Data.is<llvm::Constant*>()) {
+ return Data.get<llvm::Constant*>()->getType();
+ } else {
+ return Data.get<ConstantInitBuilderBase*>()->Buffer[0]->getType();
+ }
+}
+
+void ConstantInitFuture::abandon() {
+ assert(Data && "abandoning null future");
+ if (auto builder = Data.dyn_cast<ConstantInitBuilderBase*>()) {
+ builder->abandon(0);
+ }
+ Data = nullptr;
+}
+
+void ConstantInitFuture::installInGlobal(llvm::GlobalVariable *GV) {
+ assert(Data && "installing null future");
+ if (Data.is<llvm::Constant*>()) {
+ GV->setInitializer(Data.get<llvm::Constant*>());
+ } else {
+ auto &builder = *Data.get<ConstantInitBuilderBase*>();
+ assert(builder.Buffer.size() == 1);
+ builder.setGlobalInitializer(GV, builder.Buffer[0]);
+ builder.Buffer.clear();
+ Data = nullptr;
+ }
+}
+
+ConstantInitFuture
+ConstantInitBuilderBase::createFuture(llvm::Constant *initializer) {
+ assert(Buffer.empty() && "buffer not current empty");
+ Buffer.push_back(initializer);
+ return ConstantInitFuture(this);
+}
+
+// Only used in this file.
+inline ConstantInitFuture::ConstantInitFuture(ConstantInitBuilderBase *builder)
+ : Data(builder) {
+ assert(!builder->Frozen);
+ assert(builder->Buffer.size() == 1);
+ assert(builder->Buffer[0] != nullptr);
+}
+
llvm::GlobalVariable *
ConstantInitBuilderBase::createGlobal(llvm::Constant *initializer,
const llvm::Twine &name,
@@ -53,8 +98,27 @@ void ConstantInitBuilderBase::resolveSelfReferences(llvm::GlobalVariable *GV) {
llvm::Constant *resolvedReference =
llvm::ConstantExpr::getInBoundsGetElementPtr(
GV->getValueType(), GV, entry.Indices);
- entry.Dummy->replaceAllUsesWith(resolvedReference);
- entry.Dummy->eraseFromParent();
+ auto dummy = entry.Dummy;
+ dummy->replaceAllUsesWith(resolvedReference);
+ dummy->eraseFromParent();
+ }
+ SelfReferences.clear();
+}
+
+void ConstantInitBuilderBase::abandon(size_t newEnd) {
+ // Remove all the entries we've added.
+ Buffer.erase(Buffer.begin() + newEnd, Buffer.end());
+
+ // If we're abandoning all the way to the beginning, destroy
+ // all the self-references, because we might not get another
+ // opportunity.
+ if (newEnd == 0) {
+ for (auto &entry : SelfReferences) {
+ auto dummy = entry.Dummy;
+ dummy->replaceAllUsesWith(llvm::UndefValue::get(dummy->getType()));
+ dummy->eraseFromParent();
+ }
+ SelfReferences.clear();
}
}
@@ -115,6 +179,27 @@ void ConstantAggregateBuilderBase::getGEPIndicesTo(
position - Begin));
}
+ConstantAggregateBuilderBase::PlaceholderPosition
+ConstantAggregateBuilderBase::addPlaceholderWithSize(llvm::Type *type) {
+ // Bring the offset up to the last field.
+ CharUnits offset = getNextOffsetFromGlobal();
+
+ // Create the placeholder.
+ auto position = addPlaceholder();
+
+ // Advance the offset past that field.
+ auto &layout = Builder.CGM.getDataLayout();
+ if (!Packed)
+ offset = offset.alignTo(CharUnits::fromQuantity(
+ layout.getABITypeAlignment(type)));
+ offset += CharUnits::fromQuantity(layout.getTypeStoreSize(type));
+
+ CachedOffsetEnd = Builder.Buffer.size();
+ CachedOffsetFromGlobal = offset;
+
+ return position;
+}
+
CharUnits ConstantAggregateBuilderBase::getOffsetFromGlobalTo(size_t end) const{
size_t cacheEnd = CachedOffsetEnd;
assert(cacheEnd <= end);
@@ -144,8 +229,9 @@ CharUnits ConstantAggregateBuilderBase::getOffsetFromGlobalTo(size_t end) const{
assert(element != nullptr &&
"cannot compute offset when a placeholder is present");
llvm::Type *elementType = element->getType();
- offset = offset.alignTo(CharUnits::fromQuantity(
- layout.getABITypeAlignment(elementType)));
+ if (!Packed)
+ offset = offset.alignTo(CharUnits::fromQuantity(
+ layout.getABITypeAlignment(elementType)));
offset += CharUnits::fromQuantity(layout.getTypeStoreSize(elementType));
} while (++cacheEnd != end);
}
@@ -176,14 +262,17 @@ ConstantAggregateBuilderBase::finishStruct(llvm::StructType *ty) {
markFinished();
auto &buffer = getBuffer();
- assert(Begin < buffer.size() && "didn't add any struct elements?");
auto elts = llvm::makeArrayRef(buffer).slice(Begin);
+ if (ty == nullptr && elts.empty())
+ ty = llvm::StructType::get(Builder.CGM.getLLVMContext(), {}, Packed);
+
llvm::Constant *constant;
if (ty) {
+ assert(ty->isPacked() == Packed);
constant = llvm::ConstantStruct::get(ty, elts);
} else {
- constant = llvm::ConstantStruct::getAnon(elts, /*packed*/ false);
+ constant = llvm::ConstantStruct::getAnon(elts, Packed);
}
buffer.erase(buffer.begin() + Begin, buffer.end());
OpenPOWER on IntegriCloud