Methods.add(
llvm::ConstantStruct::get(ObjCMethodTy, {C, MethodTypes[i], Method}));
}
- MethodList.add(Methods.finish());
+ Methods.finishAndAddTo(MethodList);
// Create an instance of the structure
return MethodList.finishAndCreateGlobal(".objc_method_list",
Ivar.add(IvarNames[i]);
Ivar.add(IvarTypes[i]);
Ivar.add(IvarOffsets[i]);
- Ivars.add(Ivar.finish());
+ Ivar.finishAndAddTo(Ivars);
}
- IvarList.add(Ivars.finish());
+ Ivars.finishAndAddTo(IvarList);
// Create an instance of the structure
return IvarList.finishAndCreateGlobal(".objc_ivar_list",
auto Method = Methods.beginStruct(ObjCMethodDescTy);
Method.add(MethodNames[i]);
Method.add(MethodTypes[i]);
- Methods.add(Method.finish());
+ Method.finishAndAddTo(Methods);
}
- MethodList.add(Methods.finish());
+ Methods.finishAndAddTo(MethodList);
return MethodList.finishAndCreateGlobal(".objc_method_list",
CGM.getPointerAlign());
}
PtrToInt8Ty);
Elements.add(Ptr);
}
- ProtocolList.add(Elements.finish());
+ Elements.finishAndAddTo(ProtocolList);
return ProtocolList.finishAndCreateGlobal(".objc_protocol_list",
CGM.getPointerAlign());
}
fields.add(NULLPtr);
}
- propertiesArray.add(fields.finish());
+ fields.finishAndAddTo(propertiesArray);
}
- reqPropertiesList.add(reqPropertiesArray.finish());
+ reqPropertiesArray.finishAndAddTo(reqPropertiesList);
PropertyList =
reqPropertiesList.finishAndCreateGlobal(".objc_property_list",
CGM.getPointerAlign());
- optPropertiesList.add(optPropertiesArray.finish());
+ optPropertiesArray.finishAndAddTo(optPropertiesList);
OptionalPropertyList =
optPropertiesList.finishAndCreateGlobal(".objc_property_list",
CGM.getPointerAlign());
PtrTy);
ProtocolElements.add(Ptr);
}
- ProtocolList.add(ProtocolElements.finish());
+ ProtocolElements.finishAndAddTo(ProtocolList);
Elements.add(llvm::ConstantExpr::getBitCast(
ProtocolList.finishAndCreateGlobal(".objc_protocol_list",
CGM.getPointerAlign()),
fields.addInt(Int32Ty, values.size());
auto array = fields.beginArray();
for (auto v : values) array.add(v);
- fields.add(array.finish());
+ array.finishAndAddTo(fields);
llvm::Constant *GS =
fields.finishAndCreateGlobal("", CharUnits::fromQuantity(4));
fields.add(NULLPtr);
fields.add(NULLPtr);
}
- properties.add(fields.finish());
+ fields.finishAndAddTo(properties);
}
- propertyList.add(properties.finish());
+ properties.finishAndAddTo(propertyList);
return propertyList.finishAndCreateGlobal(".objc_property_list",
CGM.getPointerAlign());
auto SelStruct = Selectors.beginStruct(SelStructTy);
SelStruct.add(SelName);
SelStruct.add(SelectorTypeEncoding);
- Selectors.add(SelStruct.finish());
+ SelStruct.finishAndAddTo(Selectors);
// Store the selector alias for later replacement
SelectorAliases.push_back(i->second);
auto SelStruct = Selectors.beginStruct(SelStructTy);
SelStruct.add(NULLPtr);
SelStruct.add(NULLPtr);
- Selectors.add(SelStruct.finish());
+ SelStruct.finishAndAddTo(Selectors);
}
// Number of static selectors
assert(Buffer.empty() && "didn't claim all values out of buffer");
}
- class AggregateBuilder {
+ class AggregateBuilderBase {
protected:
ConstantInitBuilder &Builder;
- AggregateBuilder *Parent;
+ AggregateBuilderBase *Parent;
size_t Begin;
bool Finished = false;
bool Frozen = false;
return Builder.Buffer;
}
- AggregateBuilder(ConstantInitBuilder &builder,
- AggregateBuilder *parent)
+ AggregateBuilderBase(ConstantInitBuilder &builder,
+ AggregateBuilderBase *parent)
: Builder(builder), Parent(parent), Begin(builder.Buffer.size()) {
if (parent) {
assert(!parent->Frozen && "parent already has child builder active");
}
}
- ~AggregateBuilder() {
+ ~AggregateBuilderBase() {
assert(Finished && "didn't claim value from aggregate builder");
}
public:
// Not copyable.
- AggregateBuilder(const AggregateBuilder &) = delete;
- AggregateBuilder &operator=(const AggregateBuilder &) = delete;
+ AggregateBuilderBase(const AggregateBuilderBase &) = delete;
+ AggregateBuilderBase &operator=(const AggregateBuilderBase &) = delete;
// Movable, mostly to allow returning. But we have to write this out
// properly to satisfy the assert in the destructor.
- AggregateBuilder(AggregateBuilder &&other)
+ AggregateBuilderBase(AggregateBuilderBase &&other)
: Builder(other.Builder), Parent(other.Parent), Begin(other.Begin),
Finished(other.Finished), Frozen(other.Frozen) {
other.Finished = false;
}
- AggregateBuilder &operator=(AggregateBuilder &&other) = delete;
+ AggregateBuilderBase &operator=(AggregateBuilderBase &&other) = delete;
void add(llvm::Constant *value) {
assert(!Finished && "cannot add more values after finishing builder");
}
};
+ template <class Impl>
+ class AggregateBuilder : public AggregateBuilderBase {
+ protected:
+ AggregateBuilder(ConstantInitBuilder &builder,
+ AggregateBuilderBase *parent)
+ : AggregateBuilderBase(builder, parent) {}
+
+ Impl &asImpl() { return *static_cast<Impl*>(this); }
+
+ public:
+ /// Given that this builder was created by beginning an array or struct
+ /// component on the given parent builder, finish the array/struct
+ /// component and add it to the parent.
+ ///
+ /// It is an intentional choice that the parent is passed in explicitly
+ /// despite it being redundant with information already kept in the
+ /// builder. This aids in readability by making it easier to find the
+ /// places that add components to a builder, as well as "bookending"
+ /// the sub-builder more explicitly.
+ void finishAndAddTo(AggregateBuilderBase &parent) {
+ assert(Parent == &parent && "adding to non-parent builder");
+ parent.add(asImpl().finishImpl());
+ }
+
+ /// Given that this builder was created by beginning an array or struct
+ /// directly on a ConstantInitBuilder, finish the array/struct and
+ /// create a global variable with it as the initializer.
+ template <class... As>
+ llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) {
+ assert(!Parent && "finishing non-root builder");
+ return Builder.createGlobal(asImpl().finishImpl(),
+ std::forward<As>(args)...);
+ }
+
+ /// Given that this builder was created by beginning an array or struct
+ /// directly on a ConstantInitBuilder, finish the array/struct and
+ /// set it as the initializer of the given global variable.
+ void finishAndSetAsInitializer(llvm::GlobalVariable *global) {
+ assert(!Parent && "finishing non-root builder");
+ return Builder.setGlobalInitializer(global, asImpl().finishImpl());
+ }
+ };
+
ConstantArrayBuilder beginArray(llvm::Type *eltTy = nullptr);
ConstantStructBuilder beginStruct(llvm::StructType *structTy = nullptr);
+private:
llvm::GlobalVariable *createGlobal(llvm::Constant *initializer,
StringRef name,
CharUnits alignment,
GV->setAlignment(alignment.getQuantity());
return GV;
}
+
+ void setGlobalInitializer(llvm::GlobalVariable *GV,
+ llvm::Constant *initializer) {
+ GV->setInitializer(initializer);
+ }
};
/// A helper class of ConstantInitBuilder, used for building constant
/// array initializers.
-class ConstantArrayBuilder : public ConstantInitBuilder::AggregateBuilder {
+class ConstantArrayBuilder
+ : public ConstantInitBuilder::AggregateBuilder<ConstantArrayBuilder> {
llvm::Type *EltTy;
friend class ConstantInitBuilder;
+ template <class Impl> friend class ConstantInitBuilder::AggregateBuilder;
ConstantArrayBuilder(ConstantInitBuilder &builder,
- AggregateBuilder *parent, llvm::Type *eltTy)
+ AggregateBuilderBase *parent, llvm::Type *eltTy)
: AggregateBuilder(builder, parent), EltTy(eltTy) {}
public:
size_t size() const {
return getBuffer().size() - Begin;
}
+private:
/// Form an array constant from the values that have been added to this
/// builder.
- llvm::Constant *finish() {
+ llvm::Constant *finishImpl() {
markFinished();
auto &buffer = getBuffer();
buffer.erase(buffer.begin() + Begin, buffer.end());
return constant;
}
-
- template <class... As>
- llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) {
- assert(!Parent && "finishing non-root builder");
- return Builder.createGlobal(finish(), std::forward<As>(args)...);
- }
};
inline ConstantArrayBuilder
}
inline ConstantArrayBuilder
-ConstantInitBuilder::AggregateBuilder::beginArray(llvm::Type *eltTy) {
+ConstantInitBuilder::AggregateBuilderBase::beginArray(llvm::Type *eltTy) {
return ConstantArrayBuilder(Builder, this, eltTy);
}
/// A helper class of ConstantInitBuilder, used for building constant
/// struct initializers.
-class ConstantStructBuilder : public ConstantInitBuilder::AggregateBuilder {
+class ConstantStructBuilder
+ : public ConstantInitBuilder::AggregateBuilder<ConstantStructBuilder> {
llvm::StructType *Ty;
friend class ConstantInitBuilder;
+ template <class Impl> friend class ConstantInitBuilder::AggregateBuilder;
ConstantStructBuilder(ConstantInitBuilder &builder,
- AggregateBuilder *parent, llvm::StructType *ty)
+ AggregateBuilderBase *parent, llvm::StructType *ty)
: AggregateBuilder(builder, parent), Ty(ty) {}
-public:
+
/// Finish the struct.
- llvm::Constant *finish(bool packed = false) {
+ llvm::Constant *finishImpl() {
markFinished();
auto &buffer = getBuffer();
if (Ty) {
constant = llvm::ConstantStruct::get(Ty, elts);
} else {
- constant = llvm::ConstantStruct::getAnon(elts, packed);
+ constant = llvm::ConstantStruct::getAnon(elts, /*packed*/ false);
}
buffer.erase(buffer.begin() + Begin, buffer.end());
return constant;
}
-
- template <class... As>
- llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) {
- assert(!Parent && "finishing non-root builder");
- return Builder.createGlobal(finish(), std::forward<As>(args)...);
- }
};
inline ConstantStructBuilder
}
inline ConstantStructBuilder
-ConstantInitBuilder::AggregateBuilder::beginStruct(llvm::StructType *structTy) {
+ConstantInitBuilder::AggregateBuilderBase::beginStruct(
+ llvm::StructType *structTy) {
return ConstantStructBuilder(Builder, this, structTy);
}