r332957 - Revert r332955 "GNUstep Objective-C ABI version 2"
Bjorn Pettersson via cfe-commits
cfe-commits at lists.llvm.org
Tue May 22 01:16:45 PDT 2018
Author: bjope
Date: Tue May 22 01:16:45 2018
New Revision: 332957
URL: http://llvm.org/viewvc/llvm-project?rev=332957&view=rev
Log:
Revert r332955 "GNUstep Objective-C ABI version 2"
Reverted due to buildbot failures.
Seems like isnumber() is some Apple addition to cctype.
Removed:
cfe/trunk/test/CodeGenObjC/forward-declare-protocol-gnu.m
cfe/trunk/test/CodeGenObjC/gnu-init.m
cfe/trunk/test/CodeGenObjC/gnustep2-category.m
cfe/trunk/test/CodeGenObjC/gnustep2-class.m
cfe/trunk/test/CodeGenObjC/gnustep2-ivar-offset.m
cfe/trunk/test/CodeGenObjC/gnustep2-proto.m
Modified:
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
cfe/trunk/lib/Driver/ToolChains/Clang.cpp
cfe/trunk/lib/Frontend/InitPreprocessor.cpp
cfe/trunk/test/CodeGenObjC/constant-strings.m
cfe/trunk/test/CodeGenObjC/gnu-empty-protocol-v3.m
cfe/trunk/test/CodeGenObjC/ivar-type-encoding.m
cfe/trunk/test/Preprocessor/init.c
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=332957&r1=332956&r2=332957&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Tue May 22 01:16:45 2018
@@ -1620,14 +1620,6 @@ public:
bool isUTF32() const { return Kind == UTF32; }
bool isPascal() const { return IsPascal; }
- bool containsNonAscii() const {
- StringRef Str = getString();
- for (unsigned i = 0, e = Str.size(); i != e; ++i)
- if (!isASCII(Str[i]))
- return true;
- return false;
- }
-
bool containsNonAsciiOrNull() const {
StringRef Str = getString();
for (unsigned i = 0, e = Str.size(); i != e; ++i)
Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=332957&r1=332956&r2=332957&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Tue May 22 01:16:45 2018
@@ -193,8 +193,6 @@ def err_drv_mg_requires_m_or_mm : Error<
"option '-MG' requires '-M' or '-MM'">;
def err_drv_unknown_objc_runtime : Error<
"unknown or ill-formed Objective-C runtime '%0'">;
-def err_drv_gnustep_objc_runtime_incompatible_binary : Error<
- "GNUstep Objective-C runtime version %0 incompatible with target binary format">;
def err_drv_emit_llvm_link : Error<
"-emit-llvm cannot be used when linking">;
def err_drv_optimization_remark_pattern : Error<
Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=332957&r1=332956&r2=332957&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Tue May 22 01:16:45 2018
@@ -35,23 +35,11 @@
#include "llvm/IR/Module.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ConvertUTF.h"
-#include <cctype>
using namespace clang;
using namespace CodeGen;
namespace {
-
-std::string SymbolNameForMethod( StringRef ClassName,
- StringRef CategoryName, const Selector MethodName,
- bool isClassMethod) {
- std::string MethodNameColonStripped = MethodName.getAsString();
- std::replace(MethodNameColonStripped.begin(), MethodNameColonStripped.end(),
- ':', '_');
- return (Twine(isClassMethod ? "_c_" : "_i_") + ClassName + "_" +
- CategoryName + "_" + MethodNameColonStripped).str();
-}
-
/// Class that lazily initialises the runtime function. Avoids inserting the
/// types and the function declaration into a module if they're not used, and
/// avoids constructing the type more than once if it's used more than once.
@@ -126,10 +114,6 @@ protected:
/// Pointer to i8 - LLVM type of char*, for all of the places where the
/// runtime needs to deal with C strings.
llvm::PointerType *PtrToInt8Ty;
- /// struct objc_protocol type
- llvm::StructType *ProtocolTy;
- /// Protocol * type.
- llvm::PointerType *ProtocolPtrTy;
/// Instance Method Pointer type. This is a pointer to a function that takes,
/// at a minimum, an object and a selector, and is the generic type for
/// Objective-C methods. Due to differences between variadic / non-variadic
@@ -172,29 +156,11 @@ protected:
llvm::IntegerType *Int32Ty;
/// 64-bit integer type, to save us needing to look it up every time it's used.
llvm::IntegerType *Int64Ty;
- /// The type of struct objc_property.
- llvm::StructType *PropertyMetadataTy;
/// Metadata kind used to tie method lookups to message sends. The GNUstep
/// runtime provides some LLVM passes that can use this to do things like
/// automatic IMP caching and speculative inlining.
unsigned msgSendMDKind;
- /// Helper to check if we are targeting a specific runtime version or later.
- bool isRuntime(ObjCRuntime::Kind kind, unsigned major, unsigned minor=0) {
- const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime;
- return (R.getKind() == kind) &&
- (R.getVersion() >= VersionTuple(major, minor));
- }
-
- std::string SymbolForProtocol(StringRef Name) {
- return (StringRef("._OBJC_PROTOCOL_") + Name).str();
- }
-
- std::string SymbolForProtocolRef(StringRef Name) {
- return (StringRef("._OBJC_REF_PROTOCOL_") + Name).str();
- }
-
-
/// Helper function that generates a constant string and returns a pointer to
/// the start of the string. The result of this function can be used anywhere
/// where the C code specifies const char*.
@@ -208,28 +174,39 @@ protected:
/// string value. This allows the linker to combine the strings between
/// different modules. Used for EH typeinfo names, selector strings, and a
/// few other things.
- llvm::Constant *ExportUniqueString(const std::string &Str,
- const std::string &prefix,
- bool Private=false) {
- std::string name = prefix + Str;
- auto *ConstStr = TheModule.getGlobalVariable(name);
+ llvm::Constant *ExportUniqueString(const std::string &Str, StringRef Prefix) {
+ std::string Name = Prefix.str() + Str;
+ auto *ConstStr = TheModule.getGlobalVariable(Name);
if (!ConstStr) {
llvm::Constant *value = llvm::ConstantDataArray::getString(VMContext,Str);
- auto *GV = new llvm::GlobalVariable(TheModule, value->getType(), true,
- llvm::GlobalValue::LinkOnceODRLinkage, value, name);
- if (Private)
- GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- ConstStr = GV;
+ ConstStr = new llvm::GlobalVariable(TheModule, value->getType(), true,
+ llvm::GlobalValue::LinkOnceODRLinkage,
+ value, Name);
}
return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
ConstStr, Zeros);
}
+ /// Generates a global structure, initialized by the elements in the vector.
+ /// The element types must match the types of the structure elements in the
+ /// first argument.
+ llvm::GlobalVariable *MakeGlobal(llvm::Constant *C,
+ CharUnits Align,
+ StringRef Name="",
+ llvm::GlobalValue::LinkageTypes linkage
+ =llvm::GlobalValue::InternalLinkage) {
+ auto GV = new llvm::GlobalVariable(TheModule, C->getType(), false,
+ linkage, C, Name);
+ GV->setAlignment(Align.getQuantity());
+ return GV;
+ }
+
/// Returns a property name and encoding string.
llvm::Constant *MakePropertyEncodingString(const ObjCPropertyDecl *PD,
const Decl *Container) {
- assert(!isRuntime(ObjCRuntime::GNUstep, 2));
- if (isRuntime(ObjCRuntime::GNUstep, 1, 6)) {
+ const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime;
+ if ((R.getKind() == ObjCRuntime::GNUstep) &&
+ (R.getVersion() >= VersionTuple(1, 6))) {
std::string NameAndAttributes;
std::string TypeStr =
CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
@@ -245,7 +222,7 @@ protected:
/// Push the property attributes into two structure fields.
void PushPropertyAttributes(ConstantStructBuilder &Fields,
- const ObjCPropertyDecl *property, bool isSynthesized=true, bool
+ ObjCPropertyDecl *property, bool isSynthesized=true, bool
isDynamic=true) {
int attrs = property->getPropertyAttributes();
// For read-only properties, clear the copy and retain flags
@@ -272,46 +249,6 @@ protected:
Fields.addInt(Int8Ty, 0);
}
- virtual ConstantArrayBuilder PushPropertyListHeader(ConstantStructBuilder &Fields,
- int count) {
- // int count;
- Fields.addInt(IntTy, count);
- // int size; (only in GNUstep v2 ABI.
- if (isRuntime(ObjCRuntime::GNUstep, 2)) {
- llvm::DataLayout td(&TheModule);
- Fields.addInt(IntTy, td.getTypeSizeInBits(PropertyMetadataTy) /
- CGM.getContext().getCharWidth());
- }
- // struct objc_property_list *next;
- Fields.add(NULLPtr);
- // struct objc_property properties[]
- return Fields.beginArray(PropertyMetadataTy);
- }
- virtual void PushProperty(ConstantArrayBuilder &PropertiesArray,
- const ObjCPropertyDecl *property,
- const Decl *OCD,
- bool isSynthesized=true, bool
- isDynamic=true) {
- auto Fields = PropertiesArray.beginStruct(PropertyMetadataTy);
- ASTContext &Context = CGM.getContext();
- Fields.add(MakePropertyEncodingString(property, OCD));
- PushPropertyAttributes(Fields, property, isSynthesized, isDynamic);
- auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) {
- if (accessor) {
- std::string TypeStr = Context.getObjCEncodingForMethodDecl(accessor);
- llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
- Fields.add(MakeConstantString(accessor->getSelector().getAsString()));
- Fields.add(TypeEncoding);
- } else {
- Fields.add(NULLPtr);
- Fields.add(NULLPtr);
- }
- };
- addPropertyMethod(property->getGetterMethodDecl());
- addPropertyMethod(property->getSetterMethodDecl());
- Fields.finishAndAddTo(PropertiesArray);
- }
-
/// Ensures that the value has the required type, by inserting a bitcast if
/// required. This function lets us avoid inserting bitcasts that are
/// redundant.
@@ -331,8 +268,7 @@ protected:
/// LLVM context.
llvm::LLVMContext &VMContext;
-protected:
-
+private:
/// Placeholder for the class. Lots of things refer to the class before we've
/// actually emitted it. We use this alias as a placeholder, and then replace
/// it with a pointer to the class structure before finally emitting the
@@ -416,7 +352,6 @@ private:
/// Function used for non-object declared property setters.
LazyRuntimeFunction SetStructPropertyFn;
-protected:
/// The version of the runtime that this class targets. Must match the
/// version in the runtime.
int RuntimeVersion;
@@ -427,18 +362,14 @@ protected:
/// Objective-C 1 property structures when targeting the GCC runtime or it
/// will abort.
const int ProtocolVersion;
- /// The version of the class ABI. This value is used in the class structure
- /// and indicates how various fields should be interpreted.
- const int ClassABIVersion;
+
/// Generates an instance variable list structure. This is a structure
/// containing a size and an array of structures containing instance variable
/// metadata. This is used purely for introspection in the fragile ABI. In
/// the non-fragile ABI, it's used for instance variable fixup.
- virtual llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
- ArrayRef<llvm::Constant *> IvarTypes,
- ArrayRef<llvm::Constant *> IvarOffsets,
- ArrayRef<llvm::Constant *> IvarAlign,
- ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership);
+ llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
+ ArrayRef<llvm::Constant *> IvarTypes,
+ ArrayRef<llvm::Constant *> IvarOffsets);
/// Generates a method list structure. This is a structure containing a size
/// and an array of structures containing method metadata.
@@ -447,20 +378,20 @@ protected:
/// pointer allowing them to be chained together in a linked list.
llvm::Constant *GenerateMethodList(StringRef ClassName,
StringRef CategoryName,
- ArrayRef<const ObjCMethodDecl*> Methods,
+ ArrayRef<Selector> MethodSels,
+ ArrayRef<llvm::Constant *> MethodTypes,
bool isClassMethodList);
/// Emits an empty protocol. This is used for \@protocol() where no protocol
/// is found. The runtime will (hopefully) fix up the pointer to refer to the
/// real protocol.
- virtual llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName);
+ llvm::Constant *GenerateEmptyProtocol(const std::string &ProtocolName);
/// Generates a list of property metadata structures. This follows the same
/// pattern as method and instance variable metadata lists.
- llvm::Constant *GeneratePropertyList(const Decl *Container,
- const ObjCContainerDecl *OCD,
- bool isClassProperty=false,
- bool protocolOptionalProperties=false);
+ llvm::Constant *GeneratePropertyList(const ObjCImplementationDecl *OID,
+ SmallVectorImpl<Selector> &InstanceMethodSels,
+ SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes);
/// Generates a list of referenced protocols. Classes, categories, and
/// protocols all use this structure.
@@ -491,42 +422,22 @@ protected:
/// Generates a method list. This is used by protocols to define the required
/// and optional methods.
- virtual llvm::Constant *GenerateProtocolMethodList(
- ArrayRef<const ObjCMethodDecl*> Methods);
- /// Emits optional and required method lists.
- template<class T>
- void EmitProtocolMethodList(T &&Methods, llvm::Constant *&Required,
- llvm::Constant *&Optional) {
- SmallVector<const ObjCMethodDecl*, 16> RequiredMethods;
- SmallVector<const ObjCMethodDecl*, 16> OptionalMethods;
- for (const auto *I : Methods)
- if (I->isOptional())
- OptionalMethods.push_back(I);
- else
- RequiredMethods.push_back(I);
- Required = GenerateProtocolMethodList(RequiredMethods);
- Optional = GenerateProtocolMethodList(OptionalMethods);
- }
+ llvm::Constant *GenerateProtocolMethodList(
+ ArrayRef<llvm::Constant *> MethodNames,
+ ArrayRef<llvm::Constant *> MethodTypes);
/// Returns a selector with the specified type encoding. An empty string is
/// used to return an untyped selector (with the types field set to NULL).
- virtual llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
+ llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
const std::string &TypeEncoding);
- /// Returns the name of ivar offset variables. In the GNUstep v1 ABI, this
- /// contains the class and ivar names, in the v2 ABI this contains the type
- /// encoding as well.
- virtual std::string GetIVarOffsetVariableName(const ObjCInterfaceDecl *ID,
- const ObjCIvarDecl *Ivar) {
- const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
- + '.' + Ivar->getNameAsString();
- return Name;
- }
/// Returns the variable used to store the offset of an instance variable.
llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar);
/// Emits a reference to a class. This allows the linker to object if there
/// is no class of the matching name.
+
+protected:
void EmitClassRef(const std::string &className);
/// Emits a pointer to the named class
@@ -565,7 +476,7 @@ protected:
public:
CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
- unsigned protocolClassVersion, unsigned classABI=1);
+ unsigned protocolClassVersion);
ConstantAddress GenerateConstantString(const StringLiteral *) override;
@@ -588,14 +499,6 @@ public:
Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;
llvm::Value *GetSelector(CodeGenFunction &CGF,
const ObjCMethodDecl *Method) override;
- virtual llvm::Constant *GetConstantSelector(Selector Sel,
- const std::string &TypeEncoding) {
- llvm_unreachable("Runtime unable to generate constant selector");
- }
- llvm::Constant *GetConstantSelector(const ObjCMethodDecl *M) {
- return GetConstantSelector(M->getSelector(),
- CGM.getContext().getObjCEncodingForMethodDecl(M));
- }
llvm::Constant *GetEHType(QualType T) override;
llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
@@ -795,10 +698,7 @@ class CGObjCGNUstep : public CGObjCGNU {
}
public:
- CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 9, 3, 1) {}
- CGObjCGNUstep(CodeGenModule &Mod, unsigned ABI, unsigned ProtocolABI,
- unsigned ClassABI) :
- CGObjCGNU(Mod, ABI, ProtocolABI, ClassABI) {
+ CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNU(Mod, 9, 3) {
const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime;
llvm::StructType *SlotStructTy =
@@ -807,7 +707,7 @@ class CGObjCGNUstep : public CGObjCGNU {
// Slot_t objc_msg_lookup_sender(id *receiver, SEL selector, id sender);
SlotLookupFn.init(&CGM, "objc_msg_lookup_sender", SlotTy, PtrToIdTy,
SelectorTy, IdTy);
- // Slot_t objc_slot_lookup_super(struct objc_super*, SEL);
+ // Slot_t objc_msg_lookup_super(struct objc_super*, SEL);
SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy,
PtrToObjCSuperTy, SelectorTy);
// If we're in ObjC++ mode, then we want to make
@@ -884,951 +784,6 @@ class CGObjCGNUstep : public CGObjCGNU {
}
};
-/// GNUstep Objective-C ABI version 2 implementation.
-/// This is the ABI that provides a clean break with the legacy GCC ABI and
-/// cleans up a number of things that were added to work around 1980s linkers.
-class CGObjCGNUstep2 : public CGObjCGNUstep {
- /// The section for selectors.
- static constexpr const char *const SelSection = "__objc_selectors";
- /// The section for classes.
- static constexpr const char *const ClsSection = "__objc_classes";
- /// The section for references to classes.
- static constexpr const char *const ClsRefSection = "__objc_class_refs";
- /// The section for categories.
- static constexpr const char *const CatSection = "__objc_cats";
- /// The section for protocols.
- static constexpr const char *const ProtocolSection = "__objc_protocols";
- /// The section for protocol references.
- static constexpr const char *const ProtocolRefSection = "__objc_protocol_refs";
- /// The section for class aliases
- static constexpr const char *const ClassAliasSection = "__objc_class_aliases";
- /// The section for constexpr constant strings
- static constexpr const char *const ConstantStringSection = "__objc_constant_string";
- /// The GCC ABI superclass message lookup function. Takes a pointer to a
- /// structure describing the receiver and the class, and a selector as
- /// arguments. Returns the IMP for the corresponding method.
- LazyRuntimeFunction MsgLookupSuperFn;
- /// A flag indicating if we've emitted at least one protocol.
- /// If we haven't, then we need to emit an empty protocol, to ensure that the
- /// __start__objc_protocols and __stop__objc_protocols sections exist.
- bool EmittedProtocol = false;
- /// A flag indicating if we've emitted at least one protocol reference.
- /// If we haven't, then we need to emit an empty protocol, to ensure that the
- /// __start__objc_protocol_refs and __stop__objc_protocol_refs sections
- /// exist.
- bool EmittedProtocolRef = false;
- /// A flag indicating if we've emitted at least one class.
- /// If we haven't, then we need to emit an empty protocol, to ensure that the
- /// __start__objc_classes and __stop__objc_classes sections / exist.
- bool EmittedClass = false;
- /// Generate the name of a symbol for a reference to a class. Accesses to
- /// classes should be indirected via this.
- std::string SymbolForClassRef(StringRef Name, bool isWeak) {
- if (isWeak)
- return (StringRef("._OBJC_WEAK_REF_CLASS_") + Name).str();
- else
- return (StringRef("._OBJC_REF_CLASS_") + Name).str();
- }
- /// Generate the name of a class symbol.
- std::string SymbolForClass(StringRef Name) {
- return (StringRef("._OBJC_CLASS_") + Name).str();
- }
- void CallRuntimeFunction(CGBuilderTy &B, StringRef FunctionName,
- ArrayRef<llvm::Value*> Args) {
- SmallVector<llvm::Type *,8> Types;
- for (auto *Arg : Args)
- Types.push_back(Arg->getType());
- llvm::FunctionType *FT = llvm::FunctionType::get(B.getVoidTy(), Types,
- false);
- llvm::Value *Fn = CGM.CreateRuntimeFunction(FT, FunctionName);
- B.CreateCall(Fn, Args);
- }
-
- ConstantAddress GenerateConstantString(const StringLiteral *SL) override {
-
- auto Str = SL->getString();
- CharUnits Align = CGM.getPointerAlign();
-
- // Look for an existing one
- llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
- if (old != ObjCStrings.end())
- return ConstantAddress(old->getValue(), Align);
-
- bool isNonASCII = SL->containsNonAscii();
-
- auto LiteralLength = SL->getLength();
-
- if ((CGM.getTarget().getPointerWidth(0) == 64) &&
- (LiteralLength < 9) && !isNonASCII) {
- // Tiny strings are only used on 64-bit platforms. They store 8 7-bit
- // ASCII characters in the high 56 bits, followed by a 4-bit length and a
- // 3-bit tag (which is always 4).
- uint64_t str = 0;
- // Fill in the characters
- for (unsigned i=0 ; i<LiteralLength ; i++)
- str |= ((uint64_t)SL->getCodeUnit(i)) << ((64 - 4 - 3) - (i*7));
- // Fill in the length
- str |= LiteralLength << 3;
- // Set the tag
- str |= 4;
- auto *ObjCStr = llvm::ConstantExpr::getIntToPtr(
- llvm::ConstantInt::get(Int64Ty, str), IdTy);
- ObjCStrings[Str] = ObjCStr;
- return ConstantAddress(ObjCStr, Align);
- }
-
- StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass;
-
- if (StringClass.empty()) StringClass = "NSConstantString";
-
- std::string Sym = SymbolForClass(StringClass);
-
- llvm::Constant *isa = TheModule.getNamedGlobal(Sym);
-
- if (!isa)
- isa = new llvm::GlobalVariable(TheModule, IdTy, /* isConstant */false,
- llvm::GlobalValue::ExternalLinkage, nullptr, Sym);
- else if (isa->getType() != PtrToIdTy)
- isa = llvm::ConstantExpr::getBitCast(isa, PtrToIdTy);
-
- // struct
- // {
- // Class isa;
- // uint32_t flags;
- // uint32_t length; // Number of codepoints
- // uint32_t size; // Number of bytes
- // uint32_t hash;
- // const char *data;
- // };
-
- ConstantInitBuilder Builder(CGM);
- auto Fields = Builder.beginStruct();
- Fields.add(isa);
- // For now, all non-ASCII strings are represented as UTF-16. As such, the
- // number of bytes is simply double the number of UTF-16 codepoints. In
- // ASCII strings, the number of bytes is equal to the number of non-ASCII
- // codepoints.
- if (isNonASCII) {
- unsigned NumU8CodeUnits = Str.size();
- // A UTF-16 representation of a unicode string contains at most the same
- // number of code units as a UTF-8 representation. Allocate that much
- // space, plus one for the final null character.
- SmallVector<llvm::UTF16, 128> ToBuf(NumU8CodeUnits + 1);
- const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)Str.data();
- llvm::UTF16 *ToPtr = &ToBuf[0];
- (void)llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumU8CodeUnits,
- &ToPtr, ToPtr + NumU8CodeUnits, llvm::strictConversion);
- uint32_t StringLength = ToPtr - &ToBuf[0];
- // Add null terminator
- *ToPtr = 0;
- // Flags: 2 indicates UTF-16 encoding
- Fields.addInt(Int32Ty, 2);
- // Number of UTF-16 codepoints
- Fields.addInt(Int32Ty, StringLength);
- // Number of bytes
- Fields.addInt(Int32Ty, StringLength * 2);
- // Hash. Not currently initialised by the compiler.
- Fields.addInt(Int32Ty, 0);
- // pointer to the data string.
- auto Arr = llvm::makeArrayRef(&ToBuf[0], ToPtr+1);
- auto *C = llvm::ConstantDataArray::get(VMContext, Arr);
- auto *Buffer = new llvm::GlobalVariable(TheModule, C->getType(),
- /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, C, ".str");
- Buffer->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- Fields.add(Buffer);
- } else {
- // Flags: 0 indicates ASCII encoding
- Fields.addInt(Int32Ty, 0);
- // Number of UTF-16 codepoints, each ASCII byte is a UTF-16 codepoint
- Fields.addInt(Int32Ty, Str.size());
- // Number of bytes
- Fields.addInt(Int32Ty, Str.size());
- // Hash. Not currently initialised by the compiler.
- Fields.addInt(Int32Ty, 0);
- // Data pointer
- Fields.add(MakeConstantString(Str));
- }
- std::string StringName;
- bool isNamed = !isNonASCII;
- if (isNamed) {
- StringName = ".objc_str_";
- for (int i=0,e=Str.size() ; i<e ; ++i) {
- char c = Str[i];
- if (isalpha(c) || isnumber(c))
- StringName += c;
- else if (c == ' ')
- StringName += '_';
- else {
- isNamed = false;
- break;
- }
- }
- }
- auto *ObjCStrGV =
- Fields.finishAndCreateGlobal(
- isNamed ? StringRef(StringName) : ".objc_string",
- Align, false, isNamed ? llvm::GlobalValue::LinkOnceODRLinkage
- : llvm::GlobalValue::PrivateLinkage);
- ObjCStrGV->setSection(ConstantStringSection);
- if (isNamed) {
- ObjCStrGV->setComdat(TheModule.getOrInsertComdat(StringName));
- ObjCStrGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- }
- llvm::Constant *ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStrGV, IdTy);
- ObjCStrings[Str] = ObjCStr;
- ConstantStrings.push_back(ObjCStr);
- return ConstantAddress(ObjCStr, Align);
- }
-
- void PushProperty(ConstantArrayBuilder &PropertiesArray,
- const ObjCPropertyDecl *property,
- const Decl *OCD,
- bool isSynthesized=true, bool
- isDynamic=true) override {
- // struct objc_property
- // {
- // const char *name;
- // const char *attributes;
- // const char *type;
- // SEL getter;
- // SEL setter;
- // };
- auto Fields = PropertiesArray.beginStruct(PropertyMetadataTy);
- ASTContext &Context = CGM.getContext();
- Fields.add(MakeConstantString(property->getNameAsString()));
- std::string TypeStr =
- CGM.getContext().getObjCEncodingForPropertyDecl(property, OCD);
- Fields.add(MakeConstantString(TypeStr));
- std::string typeStr;
- Context.getObjCEncodingForType(property->getType(), typeStr);
- Fields.add(MakeConstantString(typeStr));
- auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) {
- if (accessor) {
- std::string TypeStr = Context.getObjCEncodingForMethodDecl(accessor);
- Fields.add(GetConstantSelector(accessor->getSelector(), TypeStr));
- } else {
- Fields.add(NULLPtr);
- }
- };
- addPropertyMethod(property->getGetterMethodDecl());
- addPropertyMethod(property->getSetterMethodDecl());
- Fields.finishAndAddTo(PropertiesArray);
- }
-
- llvm::Constant *
- GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods) override {
- // struct objc_protocol_method_description
- // {
- // SEL selector;
- // const char *types;
- // };
- llvm::StructType *ObjCMethodDescTy =
- llvm::StructType::get(CGM.getLLVMContext(),
- { PtrToInt8Ty, PtrToInt8Ty });
- ASTContext &Context = CGM.getContext();
- ConstantInitBuilder Builder(CGM);
- // struct objc_protocol_method_description_list
- // {
- // int count;
- // int size;
- // struct objc_protocol_method_description methods[];
- // };
- auto MethodList = Builder.beginStruct();
- // int count;
- MethodList.addInt(IntTy, Methods.size());
- // int size; // sizeof(struct objc_method_description)
- llvm::DataLayout td(&TheModule);
- MethodList.addInt(IntTy, td.getTypeSizeInBits(ObjCMethodDescTy) /
- CGM.getContext().getCharWidth());
- // struct objc_method_description[]
- auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
- for (auto *M : Methods) {
- auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
- Method.add(CGObjCGNU::GetConstantSelector(M));
- Method.add(GetTypeString(Context.getObjCEncodingForMethodDecl(M, true)));
- Method.finishAndAddTo(MethodArray);
- }
- MethodArray.finishAndAddTo(MethodList);
- return MethodList.finishAndCreateGlobal(".objc_protocol_method_list",
- CGM.getPointerAlign());
- }
-
- llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
- llvm::Value *cmd, MessageSendInfo &MSI) override {
- // Don't access the slot unless we're trying to cache the result.
- CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *lookupArgs[] = {CGObjCGNU::EnforceType(Builder, ObjCSuper,
- PtrToObjCSuperTy).getPointer(), cmd};
- return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs);
- }
-
- llvm::GlobalVariable *GetClassVar(StringRef Name, bool isWeak=false) {
- std::string SymbolName = SymbolForClassRef(Name, isWeak);
- auto *ClassSymbol = TheModule.getNamedGlobal(SymbolName);
- if (ClassSymbol)
- return ClassSymbol;
- ClassSymbol = new llvm::GlobalVariable(TheModule,
- IdTy, false, llvm::GlobalValue::ExternalLinkage,
- nullptr, SymbolName);
- // If this is a weak symbol, then we are creating a valid definition for
- // the symbol, pointing to a weak definition of the real class pointer. If
- // this is not a weak reference, then we are expecting another compilation
- // unit to provide the real indirection symbol.
- if (isWeak)
- ClassSymbol->setInitializer(new llvm::GlobalVariable(TheModule,
- Int8Ty, false, llvm::GlobalValue::ExternalWeakLinkage,
- nullptr, SymbolForClass(Name)));
- assert(ClassSymbol->getName() == SymbolName);
- return ClassSymbol;
- }
- llvm::Value *GetClassNamed(CodeGenFunction &CGF,
- const std::string &Name,
- bool isWeak) override {
- return CGF.Builder.CreateLoad(Address(GetClassVar(Name, isWeak),
- CGM.getPointerAlign()));
- }
- int32_t FlagsForOwnership(Qualifiers::ObjCLifetime Ownership) {
- // typedef enum {
- // ownership_invalid = 0,
- // ownership_strong = 1,
- // ownership_weak = 2,
- // ownership_unsafe = 3
- // } ivar_ownership;
- int Flag;
- switch (Ownership) {
- case Qualifiers::OCL_Strong:
- Flag = 1;
- break;
- case Qualifiers::OCL_Weak:
- Flag = 2;
- break;
- case Qualifiers::OCL_ExplicitNone:
- Flag = 3;
- break;
- case Qualifiers::OCL_None:
- case Qualifiers::OCL_Autoreleasing:
- assert(Ownership != Qualifiers::OCL_Autoreleasing);
- Flag = 0;
- }
- return Flag;
- }
- llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
- ArrayRef<llvm::Constant *> IvarTypes,
- ArrayRef<llvm::Constant *> IvarOffsets,
- ArrayRef<llvm::Constant *> IvarAlign,
- ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership) override {
- llvm_unreachable("Method should not be called!");
- }
-
- llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName) override {
- std::string Name = SymbolForProtocol(ProtocolName);
- auto *GV = TheModule.getGlobalVariable(Name);
- if (!GV) {
- // Emit a placeholder symbol.
- GV = new llvm::GlobalVariable(TheModule, ProtocolTy, false,
- llvm::GlobalValue::ExternalLinkage, nullptr, Name);
- GV->setAlignment(CGM.getPointerAlign().getQuantity());
- }
- return llvm::ConstantExpr::getBitCast(GV, ProtocolPtrTy);
- }
-
- /// Existing protocol references.
- llvm::StringMap<llvm::Constant*> ExistingProtocolRefs;
-
- llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
- const ObjCProtocolDecl *PD) override {
- auto Name = PD->getNameAsString();
- auto *&Ref = ExistingProtocolRefs[Name];
- if (!Ref) {
- auto *&Protocol = ExistingProtocols[Name];
- if (!Protocol)
- Protocol = GenerateProtocolRef(PD);
- std::string RefName = SymbolForProtocolRef(Name);
- assert(!TheModule.getGlobalVariable(RefName));
- // Emit a reference symbol.
- auto GV = new llvm::GlobalVariable(TheModule, ProtocolPtrTy,
- false, llvm::GlobalValue::ExternalLinkage,
- llvm::ConstantExpr::getBitCast(Protocol, ProtocolPtrTy), RefName);
- GV->setSection(ProtocolRefSection);
- GV->setAlignment(CGM.getPointerAlign().getQuantity());
- Ref = GV;
- }
- EmittedProtocolRef = true;
- return CGF.Builder.CreateAlignedLoad(Ref, CGM.getPointerAlign());
- }
-
- llvm::Constant *GenerateProtocolList(ArrayRef<llvm::Constant*> Protocols) {
- llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(ProtocolPtrTy,
- Protocols.size());
- llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
- Protocols);
- ConstantInitBuilder builder(CGM);
- auto ProtocolBuilder = builder.beginStruct();
- ProtocolBuilder.addNullPointer(PtrTy);
- ProtocolBuilder.addInt(SizeTy, Protocols.size());
- ProtocolBuilder.add(ProtocolArray);
- return ProtocolBuilder.finishAndCreateGlobal(".objc_protocol_list",
- CGM.getPointerAlign(), false, llvm::GlobalValue::InternalLinkage);
- }
-
- void GenerateProtocol(const ObjCProtocolDecl *PD) override {
- // Do nothing - we only emit referenced protocols.
- }
- llvm::Constant *GenerateProtocolRef(const ObjCProtocolDecl *PD) {
- std::string ProtocolName = PD->getNameAsString();
- auto *&Protocol = ExistingProtocols[ProtocolName];
- if (Protocol)
- return Protocol;
-
- EmittedProtocol = true;
-
- // Use the protocol definition, if there is one.
- if (const ObjCProtocolDecl *Def = PD->getDefinition())
- PD = Def;
-
- SmallVector<llvm::Constant*, 16> Protocols;
- for (const auto *PI : PD->protocols())
- Protocols.push_back(
- llvm::ConstantExpr::getBitCast(GenerateProtocolRef(PI),
- ProtocolPtrTy));
- llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
-
- // Collect information about methods
- llvm::Constant *InstanceMethodList, *OptionalInstanceMethodList;
- llvm::Constant *ClassMethodList, *OptionalClassMethodList;
- EmitProtocolMethodList(PD->instance_methods(), InstanceMethodList,
- OptionalInstanceMethodList);
- EmitProtocolMethodList(PD->class_methods(), ClassMethodList,
- OptionalClassMethodList);
-
- auto SymName = SymbolForProtocol(ProtocolName);
- auto *OldGV = TheModule.getGlobalVariable(SymName);
- // The isa pointer must be set to a magic number so the runtime knows it's
- // the correct layout.
- ConstantInitBuilder builder(CGM);
- auto ProtocolBuilder = builder.beginStruct();
- ProtocolBuilder.add(llvm::ConstantExpr::getIntToPtr(
- llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
- ProtocolBuilder.add(MakeConstantString(ProtocolName));
- ProtocolBuilder.add(ProtocolList);
- ProtocolBuilder.add(InstanceMethodList);
- ProtocolBuilder.add(ClassMethodList);
- ProtocolBuilder.add(OptionalInstanceMethodList);
- ProtocolBuilder.add(OptionalClassMethodList);
- // Required instance properties
- ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, false, false));
- // Optional instance properties
- ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, false, true));
- // Required class properties
- ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, true, false));
- // Optional class properties
- ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, true, true));
-
- auto *GV = ProtocolBuilder.finishAndCreateGlobal(SymName,
- CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage);
- GV->setSection(ProtocolSection);
- GV->setComdat(TheModule.getOrInsertComdat(SymName));
- if (OldGV) {
- OldGV->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GV,
- OldGV->getType()));
- OldGV->removeFromParent();
- GV->setName(SymName);
- }
- Protocol = GV;
- return GV;
- }
- llvm::Constant *EnforceType(llvm::Constant *Val, llvm::Type *Ty) {
- if (Val->getType() == Ty)
- return Val;
- return llvm::ConstantExpr::getBitCast(Val, Ty);
- }
- llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
- const std::string &TypeEncoding) override {
- return GetConstantSelector(Sel, TypeEncoding);
- }
- llvm::Constant *GetTypeString(llvm::StringRef TypeEncoding) {
- if (TypeEncoding.empty())
- return NULLPtr;
- std::string MangledTypes = TypeEncoding;
- std::replace(MangledTypes.begin(), MangledTypes.end(),
- '@', '\1');
- std::string TypesVarName = ".objc_sel_types_" + MangledTypes;
- auto *TypesGlobal = TheModule.getGlobalVariable(TypesVarName);
- if (!TypesGlobal) {
- llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
- TypeEncoding);
- auto *GV = new llvm::GlobalVariable(TheModule, Init->getType(),
- true, llvm::GlobalValue::LinkOnceODRLinkage, Init, TypesVarName);
- GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- TypesGlobal = GV;
- }
- return llvm::ConstantExpr::getGetElementPtr(TypesGlobal->getValueType(),
- TypesGlobal, Zeros);
- }
- llvm::Constant *GetConstantSelector(Selector Sel,
- const std::string &TypeEncoding) override {
- // @ is used as a special character in symbol names (used for symbol
- // versioning), so mangle the name to not include it. Replace it with a
- // character that is not a valid type encoding character (and, being
- // non-printable, never will be!)
- std::string MangledTypes = TypeEncoding;
- std::replace(MangledTypes.begin(), MangledTypes.end(),
- '@', '\1');
- auto SelVarName = (StringRef(".objc_selector_") + Sel.getAsString() + "_" +
- MangledTypes).str();
- if (auto *GV = TheModule.getNamedGlobal(SelVarName))
- return EnforceType(GV, SelectorTy);
- ConstantInitBuilder builder(CGM);
- auto SelBuilder = builder.beginStruct();
- SelBuilder.add(ExportUniqueString(Sel.getAsString(), ".objc_sel_name_",
- true));
- SelBuilder.add(GetTypeString(TypeEncoding));
- auto *GV = SelBuilder.finishAndCreateGlobal(SelVarName,
- CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage);
- GV->setComdat(TheModule.getOrInsertComdat(SelVarName));
- GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- GV->setSection(SelSection);
- auto *SelVal = EnforceType(GV, SelectorTy);
- return SelVal;
- }
- std::pair<llvm::Constant*,llvm::Constant*>
- GetSectionBounds(StringRef Section) {
- auto *Start = new llvm::GlobalVariable(TheModule, PtrTy,
- /*isConstant*/false,
- llvm::GlobalValue::ExternalLinkage, nullptr, StringRef("__start_") +
- Section);
- Start->setVisibility(llvm::GlobalValue::HiddenVisibility);
- auto *Stop = new llvm::GlobalVariable(TheModule, PtrTy,
- /*isConstant*/false,
- llvm::GlobalValue::ExternalLinkage, nullptr, StringRef("__stop_") +
- Section);
- Stop->setVisibility(llvm::GlobalValue::HiddenVisibility);
- return { Start, Stop };
- }
- llvm::Function *ModuleInitFunction() override {
- llvm::Function *LoadFunction = llvm::Function::Create(
- llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false),
- llvm::GlobalValue::LinkOnceODRLinkage, ".objcv2_load_function",
- &TheModule);
- LoadFunction->setVisibility(llvm::GlobalValue::HiddenVisibility);
- LoadFunction->setComdat(TheModule.getOrInsertComdat(".objcv2_load_function"));
-
- llvm::BasicBlock *EntryBB =
- llvm::BasicBlock::Create(VMContext, "entry", LoadFunction);
- CGBuilderTy B(CGM, VMContext);
- B.SetInsertPoint(EntryBB);
- ConstantInitBuilder builder(CGM);
- auto InitStructBuilder = builder.beginStruct();
- InitStructBuilder.addInt(Int64Ty, 0);
- auto addSection = [&](const char *section) {
- auto bounds = GetSectionBounds(section);
- InitStructBuilder.add(bounds.first);
- InitStructBuilder.add(bounds.second);
- };
- addSection(SelSection);
- addSection(ClsSection);
- addSection(ClsRefSection);
- addSection(CatSection);
- addSection(ProtocolSection);
- addSection(ProtocolRefSection);
- addSection(ClassAliasSection);
- addSection(ConstantStringSection);
- auto *InitStruct = InitStructBuilder.finishAndCreateGlobal(".objc_init",
- CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage);
- InitStruct->setVisibility(llvm::GlobalValue::HiddenVisibility);
- InitStruct->setComdat(TheModule.getOrInsertComdat(".objc_init"));
-
- CallRuntimeFunction(B, "__objc_load", {InitStruct});;
- B.CreateRetVoid();
- // Make sure that the optimisers don't delete this function.
- CGM.addCompilerUsedGlobal(LoadFunction);
- // FIXME: Currently ELF only!
- // We have to do this by hand, rather than with @llvm.ctors, so that the
- // linker can remove the duplicate invocations.
- auto *InitVar = new llvm::GlobalVariable(TheModule, LoadFunction->getType(),
- /*isConstant*/true, llvm::GlobalValue::LinkOnceAnyLinkage,
- LoadFunction, ".objc_ctor");
- // Check that this hasn't been renamed. This shouldn't happen, because
- // this function should be called precisely once.
- assert(InitVar->getName() == ".objc_ctor");
- InitVar->setSection(".ctors");
- InitVar->setVisibility(llvm::GlobalValue::HiddenVisibility);
- InitVar->setComdat(TheModule.getOrInsertComdat(".objc_ctor"));
- CGM.addCompilerUsedGlobal(InitVar);
- for (auto *C : Categories) {
- auto *Cat = cast<llvm::GlobalVariable>(C->stripPointerCasts());
- Cat->setSection(CatSection);
- CGM.addUsedGlobal(Cat);
- }
- // Add a null value fore each special section so that we can always
- // guarantee that the _start and _stop symbols will exist and be
- // meaningful.
- auto createNullGlobal = [&](StringRef Name, ArrayRef<llvm::Constant*> Init,
- StringRef Section) {
- auto nullBuilder = builder.beginStruct();
- for (auto *F : Init)
- nullBuilder.add(F);
- auto GV = nullBuilder.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
- false, llvm::GlobalValue::LinkOnceODRLinkage);
- GV->setSection(Section);
- GV->setComdat(TheModule.getOrInsertComdat(Name));
- GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- CGM.addUsedGlobal(GV);
- return GV;
- };
- createNullGlobal(".objc_null_selector", {NULLPtr, NULLPtr}, SelSection);
- if (Categories.empty())
- createNullGlobal(".objc_null_category", {NULLPtr, NULLPtr,
- NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr}, CatSection);
- if (!EmittedClass) {
- createNullGlobal(".objc_null_cls_init_ref", NULLPtr, ClsSection);
- createNullGlobal(".objc_null_class_ref", { NULLPtr, NULLPtr },
- ClsRefSection);
- }
- if (!EmittedProtocol)
- createNullGlobal(".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr,
- NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr,
- NULLPtr}, ProtocolSection);
- if (!EmittedProtocolRef)
- createNullGlobal(".objc_null_protocol_ref", {NULLPtr}, ProtocolRefSection);
- if (!ClassAliases.empty())
- for (auto clsAlias : ClassAliases)
- createNullGlobal(std::string(".objc_class_alias") +
- clsAlias.second, { MakeConstantString(clsAlias.second),
- GetClassVar(clsAlias.first) }, ClassAliasSection);
- else
- createNullGlobal(".objc_null_class_alias", { NULLPtr, NULLPtr },
- ClassAliasSection);
- if (ConstantStrings.empty()) {
- auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0);
- createNullGlobal(".objc_null_constant_string", { NULLPtr, i32Zero,
- i32Zero, i32Zero, i32Zero, NULLPtr }, ConstantStringSection);
- }
- ConstantStrings.clear();
- Categories.clear();
- Classes.clear();
- return nullptr;//CGObjCGNU::ModuleInitFunction();
- }
- /// In the v2 ABI, ivar offset variables use the type encoding in their name
- /// to trigger linker failures if the types don't match.
- std::string GetIVarOffsetVariableName(const ObjCInterfaceDecl *ID,
- const ObjCIvarDecl *Ivar) override {
- std::string TypeEncoding;
- CGM.getContext().getObjCEncodingForType(Ivar->getType(), TypeEncoding);
- // Prevent the @ from being interpreted as a symbol version.
- std::replace(TypeEncoding.begin(), TypeEncoding.end(),
- '@', '\1');
- const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
- + '.' + Ivar->getNameAsString() + '.' + TypeEncoding;
- return Name;
- }
- llvm::Value *EmitIvarOffset(CodeGenFunction &CGF,
- const ObjCInterfaceDecl *Interface,
- const ObjCIvarDecl *Ivar) override {
- const std::string Name = GetIVarOffsetVariableName(Ivar->getContainingInterface(), Ivar);
- llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
- if (!IvarOffsetPointer)
- IvarOffsetPointer = new llvm::GlobalVariable(TheModule, IntTy, false,
- llvm::GlobalValue::ExternalLinkage, nullptr, Name);
- CharUnits Align = CGM.getIntAlign();
- llvm::Value *Offset = CGF.Builder.CreateAlignedLoad(IvarOffsetPointer, Align);
- if (Offset->getType() != PtrDiffTy)
- Offset = CGF.Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
- return Offset;
- }
- void GenerateClass(const ObjCImplementationDecl *OID) override {
- ASTContext &Context = CGM.getContext();
-
- // Get the class name
- ObjCInterfaceDecl *classDecl =
- const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
- std::string className = classDecl->getNameAsString();
- auto *classNameConstant = MakeConstantString(className);
-
- ConstantInitBuilder builder(CGM);
- auto metaclassFields = builder.beginStruct();
- // struct objc_class *isa;
- metaclassFields.addNullPointer(PtrTy);
- // struct objc_class *super_class;
- metaclassFields.addNullPointer(PtrTy);
- // const char *name;
- metaclassFields.add(classNameConstant);
- // long version;
- metaclassFields.addInt(LongTy, 0);
- // unsigned long info;
- // objc_class_flag_meta
- metaclassFields.addInt(LongTy, 1);
- // long instance_size;
- // Setting this to zero is consistent with the older ABI, but it might be
- // more sensible to set this to sizeof(struct objc_class)
- metaclassFields.addInt(LongTy, 0);
- // struct objc_ivar_list *ivars;
- metaclassFields.addNullPointer(PtrTy);
- // struct objc_method_list *methods
- // FIXME: Almost identical code is copied and pasted below for the
- // class, but refactoring it cleanly requires C++14 generic lambdas.
- if (OID->classmeth_begin() == OID->classmeth_end())
- metaclassFields.addNullPointer(PtrTy);
- else {
- SmallVector<ObjCMethodDecl*, 16> ClassMethods;
- ClassMethods.insert(ClassMethods.begin(), OID->classmeth_begin(),
- OID->classmeth_end());
- metaclassFields.addBitCast(
- GenerateMethodList(className, "", ClassMethods, true),
- PtrTy);
- }
- // void *dtable;
- metaclassFields.addNullPointer(PtrTy);
- // IMP cxx_construct;
- metaclassFields.addNullPointer(PtrTy);
- // IMP cxx_destruct;
- metaclassFields.addNullPointer(PtrTy);
- // struct objc_class *subclass_list
- metaclassFields.addNullPointer(PtrTy);
- // struct objc_class *sibling_class
- metaclassFields.addNullPointer(PtrTy);
- // struct objc_protocol_list *protocols;
- metaclassFields.addNullPointer(PtrTy);
- // struct reference_list *extra_data;
- metaclassFields.addNullPointer(PtrTy);
- // long abi_version;
- metaclassFields.addInt(LongTy, 0);
- // struct objc_property_list *properties
- metaclassFields.add(GeneratePropertyList(OID, classDecl, /*isClassProperty*/true));
-
- auto *metaclass = metaclassFields.finishAndCreateGlobal("._OBJC_METACLASS_"
- + className, CGM.getPointerAlign());
-
- auto classFields = builder.beginStruct();
- // struct objc_class *isa;
- classFields.add(metaclass);
- // struct objc_class *super_class;
- // Get the superclass name.
- const ObjCInterfaceDecl * SuperClassDecl =
- OID->getClassInterface()->getSuperClass();
- if (SuperClassDecl) {
- auto SuperClassName = SymbolForClass(SuperClassDecl->getNameAsString());
- llvm::Constant *SuperClass = TheModule.getNamedGlobal(SuperClassName);
- if (!SuperClass)
- {
- SuperClass = new llvm::GlobalVariable(TheModule, PtrTy, false,
- llvm::GlobalValue::ExternalLinkage, nullptr, SuperClassName);
- }
- classFields.add(llvm::ConstantExpr::getBitCast(SuperClass, PtrTy));
- } else
- classFields.addNullPointer(PtrTy);
- // const char *name;
- classFields.add(classNameConstant);
- // long version;
- classFields.addInt(LongTy, 0);
- // unsigned long info;
- // !objc_class_flag_meta
- classFields.addInt(LongTy, 0);
- // long instance_size;
- int superInstanceSize = !SuperClassDecl ? 0 :
- Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize().getQuantity();
- // Instance size is negative for classes that have not yet had their ivar
- // layout calculated.
- classFields.addInt(LongTy,
- 0 - (Context.getASTObjCImplementationLayout(OID).getSize().getQuantity() -
- superInstanceSize));
-
- if (classDecl->all_declared_ivar_begin() == nullptr)
- classFields.addNullPointer(PtrTy);
- else {
- int ivar_count = 0;
- for (const ObjCIvarDecl *IVD = classDecl->all_declared_ivar_begin(); IVD;
- IVD = IVD->getNextIvar()) ivar_count++;
- llvm::DataLayout td(&TheModule);
- // struct objc_ivar_list *ivars;
- ConstantInitBuilder b(CGM);
- auto ivarListBuilder = b.beginStruct();
- // int count;
- ivarListBuilder.addInt(IntTy, ivar_count);
- // size_t size;
- llvm::StructType *ObjCIvarTy = llvm::StructType::get(
- PtrToInt8Ty,
- PtrToInt8Ty,
- PtrToInt8Ty,
- Int32Ty,
- Int32Ty);
- ivarListBuilder.addInt(SizeTy, td.getTypeSizeInBits(ObjCIvarTy) /
- CGM.getContext().getCharWidth());
- // struct objc_ivar ivars[]
- auto ivarArrayBuilder = ivarListBuilder.beginArray();
- CodeGenTypes &Types = CGM.getTypes();
- for (const ObjCIvarDecl *IVD = classDecl->all_declared_ivar_begin(); IVD;
- IVD = IVD->getNextIvar()) {
- auto ivarTy = IVD->getType();
- auto ivarBuilder = ivarArrayBuilder.beginStruct();
- // const char *name;
- ivarBuilder.add(MakeConstantString(IVD->getNameAsString()));
- // const char *type;
- std::string TypeStr;
- //Context.getObjCEncodingForType(ivarTy, TypeStr, IVD, true);
- Context.getObjCEncodingForMethodParameter(Decl::OBJC_TQ_None, ivarTy, TypeStr, true);
- ivarBuilder.add(MakeConstantString(TypeStr));
- // int *offset;
- uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
- uint64_t Offset = BaseOffset - superInstanceSize;
- llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset);
- std::string OffsetName = GetIVarOffsetVariableName(classDecl, IVD);
- llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
- if (OffsetVar)
- OffsetVar->setInitializer(OffsetValue);
- else
- OffsetVar = new llvm::GlobalVariable(TheModule, IntTy,
- false, llvm::GlobalValue::ExternalLinkage,
- OffsetValue, OffsetName);
- auto ivarVisibility =
- (IVD->getAccessControl() == ObjCIvarDecl::Private ||
- IVD->getAccessControl() == ObjCIvarDecl::Package ||
- classDecl->getVisibility() == HiddenVisibility) ?
- llvm::GlobalValue::HiddenVisibility :
- llvm::GlobalValue::DefaultVisibility;
- OffsetVar->setVisibility(ivarVisibility);
- ivarBuilder.add(OffsetVar);
- // Ivar size
- ivarBuilder.addInt(Int32Ty,
- td.getTypeSizeInBits(Types.ConvertType(ivarTy)) /
- CGM.getContext().getCharWidth());
- // Alignment will be stored as a base-2 log of the alignment.
- int align = llvm::Log2_32(Context.getTypeAlignInChars(ivarTy).getQuantity());
- // Objects that require more than 2^64-byte alignment should be impossible!
- assert(align < 64);
- // uint32_t flags;
- // Bits 0-1 are ownership.
- // Bit 2 indicates an extended type encoding
- // Bits 3-8 contain log2(aligment)
- ivarBuilder.addInt(Int32Ty,
- (align << 3) | (1<<2) |
- FlagsForOwnership(ivarTy.getQualifiers().getObjCLifetime()));
- ivarBuilder.finishAndAddTo(ivarArrayBuilder);
- }
- ivarArrayBuilder.finishAndAddTo(ivarListBuilder);
- auto ivarList = ivarListBuilder.finishAndCreateGlobal(".objc_ivar_list",
- CGM.getPointerAlign(), /*constant*/ false,
- llvm::GlobalValue::PrivateLinkage);
- classFields.add(ivarList);
- }
- // struct objc_method_list *methods
- SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
- InstanceMethods.insert(InstanceMethods.begin(), OID->instmeth_begin(),
- OID->instmeth_end());
- for (auto *propImpl : OID->property_impls())
- if (propImpl->getPropertyImplementation() ==
- ObjCPropertyImplDecl::Synthesize) {
- ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
- auto addIfExists = [&](const ObjCMethodDecl* OMD) {
- if (OMD)
- InstanceMethods.push_back(OMD);
- };
- addIfExists(prop->getGetterMethodDecl());
- addIfExists(prop->getSetterMethodDecl());
- }
-
- if (InstanceMethods.size() == 0)
- classFields.addNullPointer(PtrTy);
- else
- classFields.addBitCast(
- GenerateMethodList(className, "", InstanceMethods, false),
- PtrTy);
- // void *dtable;
- classFields.addNullPointer(PtrTy);
- // IMP cxx_construct;
- classFields.addNullPointer(PtrTy);
- // IMP cxx_destruct;
- classFields.addNullPointer(PtrTy);
- // struct objc_class *subclass_list
- classFields.addNullPointer(PtrTy);
- // struct objc_class *sibling_class
- classFields.addNullPointer(PtrTy);
- // struct objc_protocol_list *protocols;
- SmallVector<llvm::Constant*, 16> Protocols;
- for (const auto *I : classDecl->protocols())
- Protocols.push_back(
- llvm::ConstantExpr::getBitCast(GenerateProtocolRef(I),
- ProtocolPtrTy));
- if (Protocols.empty())
- classFields.addNullPointer(PtrTy);
- else
- classFields.add(GenerateProtocolList(Protocols));
- // struct reference_list *extra_data;
- classFields.addNullPointer(PtrTy);
- // long abi_version;
- classFields.addInt(LongTy, 0);
- // struct objc_property_list *properties
- classFields.add(GeneratePropertyList(OID, classDecl));
-
- auto *classStruct =
- classFields.finishAndCreateGlobal(SymbolForClass(className),
- CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage);
-
- if (CGM.getTriple().isOSBinFormatCOFF()) {
- auto Storage = llvm::GlobalValue::DefaultStorageClass;
- if (OID->getClassInterface()->hasAttr<DLLImportAttr>())
- Storage = llvm::GlobalValue::DLLImportStorageClass;
- else if (OID->getClassInterface()->hasAttr<DLLExportAttr>())
- Storage = llvm::GlobalValue::DLLExportStorageClass;
- cast<llvm::GlobalValue>(classStruct)->setDLLStorageClass(Storage);
- }
-
- auto *classRefSymbol = GetClassVar(className);
- classRefSymbol->setSection(ClsRefSection);
- classRefSymbol->setInitializer(llvm::ConstantExpr::getBitCast(classStruct, IdTy));
-
-
- // Resolve the class aliases, if they exist.
- // FIXME: Class pointer aliases shouldn't exist!
- if (ClassPtrAlias) {
- ClassPtrAlias->replaceAllUsesWith(
- llvm::ConstantExpr::getBitCast(classStruct, IdTy));
- ClassPtrAlias->eraseFromParent();
- ClassPtrAlias = nullptr;
- }
- if (auto Placeholder =
- TheModule.getNamedGlobal(SymbolForClass(className)))
- if (Placeholder != classStruct) {
- Placeholder->replaceAllUsesWith(
- llvm::ConstantExpr::getBitCast(classStruct, Placeholder->getType()));
- Placeholder->eraseFromParent();
- classStruct->setName(SymbolForClass(className));
- }
- if (MetaClassPtrAlias) {
- MetaClassPtrAlias->replaceAllUsesWith(
- llvm::ConstantExpr::getBitCast(metaclass, IdTy));
- MetaClassPtrAlias->eraseFromParent();
- MetaClassPtrAlias = nullptr;
- }
- assert(classStruct->getName() == SymbolForClass(className));
-
- auto classInitRef = new llvm::GlobalVariable(TheModule,
- classStruct->getType(), false, llvm::GlobalValue::ExternalLinkage,
- classStruct, "._OBJC_INIT_CLASS_" + className);
- classInitRef->setSection(ClsSection);
- CGM.addUsedGlobal(classInitRef);
-
- EmittedClass = true;
- }
- public:
- CGObjCGNUstep2(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 10, 4, 2) {
- MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy,
- PtrToObjCSuperTy, SelectorTy);
- // struct objc_property
- // {
- // const char *name;
- // const char *attributes;
- // const char *type;
- // SEL getter;
- // SEL setter;
- // }
- PropertyMetadataTy =
- llvm::StructType::get(CGM.getLLVMContext(),
- { PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
- }
-
-};
-
/// Support for the ObjFW runtime.
class CGObjCObjFW: public CGObjCGNU {
protected:
@@ -1923,12 +878,22 @@ void CGObjCGNU::EmitClassRef(const std::
llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef);
}
+static std::string SymbolNameForMethod( StringRef ClassName,
+ StringRef CategoryName, const Selector MethodName,
+ bool isClassMethod) {
+ std::string MethodNameColonStripped = MethodName.getAsString();
+ std::replace(MethodNameColonStripped.begin(), MethodNameColonStripped.end(),
+ ':', '_');
+ return (Twine(isClassMethod ? "_c_" : "_i_") + ClassName + "_" +
+ CategoryName + "_" + MethodNameColonStripped).str();
+}
+
CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
- unsigned protocolClassVersion, unsigned classABI)
+ unsigned protocolClassVersion)
: CGObjCRuntime(cgm), TheModule(CGM.getModule()),
VMContext(cgm.getLLVMContext()), ClassPtrAlias(nullptr),
MetaClassPtrAlias(nullptr), RuntimeVersion(runtimeABIVersion),
- ProtocolVersion(protocolClassVersion), ClassABIVersion(classABI) {
+ ProtocolVersion(protocolClassVersion) {
msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend");
@@ -1946,8 +911,6 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm,
Int8Ty = llvm::Type::getInt8Ty(VMContext);
// C string type. Used in lots of places.
PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
- ProtocolPtrTy = llvm::PointerType::getUnqual(
- Types.ConvertType(CGM.getContext().getObjCProtoType()));
Zeros[0] = llvm::ConstantInt::get(LongTy, 0);
Zeros[1] = Zeros[0];
@@ -1979,31 +942,6 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm,
IdTy = PtrToInt8Ty;
}
PtrToIdTy = llvm::PointerType::getUnqual(IdTy);
- ProtocolTy = llvm::StructType::get(IdTy,
- PtrToInt8Ty, // name
- PtrToInt8Ty, // protocols
- PtrToInt8Ty, // instance methods
- PtrToInt8Ty, // class methods
- PtrToInt8Ty, // optional instance methods
- PtrToInt8Ty, // optional class methods
- PtrToInt8Ty, // properties
- PtrToInt8Ty);// optional properties
-
- // struct objc_property_gsv1
- // {
- // const char *name;
- // char attributes;
- // char attributes2;
- // char unused1;
- // char unused2;
- // const char *getter_name;
- // const char *getter_types;
- // const char *setter_name;
- // const char *setter_types;
- // }
- PropertyMetadataTy = llvm::StructType::get(CGM.getLLVMContext(), {
- PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty,
- PtrToInt8Ty, PtrToInt8Ty });
ObjCSuperTy = llvm::StructType::get(IdTy, IdTy);
PtrToObjCSuperTy = llvm::PointerType::getUnqual(ObjCSuperTy);
@@ -2265,7 +1203,7 @@ ConstantAddress CGObjCGNU::GenerateConst
StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass;
- if (StringClass.empty()) StringClass = "NSConstantString";
+ if (StringClass.empty()) StringClass = "NXConstantString";
std::string Sym = "_OBJC_CLASS_";
Sym += StringClass;
@@ -2326,67 +1264,54 @@ CGObjCGNU::GenerateMessageSendSuper(Code
MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
llvm::Value *ReceiverClass = nullptr;
- bool isV2ABI = isRuntime(ObjCRuntime::GNUstep, 2);
- if (isV2ABI) {
- ReceiverClass = GetClassNamed(CGF,
- Class->getSuperClass()->getNameAsString(), /*isWeak*/false);
+ if (isCategoryImpl) {
+ llvm::Constant *classLookupFunction = nullptr;
if (IsClassMessage) {
- // Load the isa pointer of the superclass is this is a class method.
- ReceiverClass = Builder.CreateBitCast(ReceiverClass,
- llvm::PointerType::getUnqual(IdTy));
- ReceiverClass =
- Builder.CreateAlignedLoad(ReceiverClass, CGF.getPointerAlign());
+ classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+ IdTy, PtrTy, true), "objc_get_meta_class");
+ } else {
+ classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+ IdTy, PtrTy, true), "objc_get_class");
}
- ReceiverClass = EnforceType(Builder, ReceiverClass, IdTy);
+ ReceiverClass = Builder.CreateCall(classLookupFunction,
+ MakeConstantString(Class->getNameAsString()));
} else {
- if (isCategoryImpl) {
- llvm::Constant *classLookupFunction = nullptr;
- if (IsClassMessage) {
- classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
- IdTy, PtrTy, true), "objc_get_meta_class");
- } else {
- classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
- IdTy, PtrTy, true), "objc_get_class");
+ // Set up global aliases for the metaclass or class pointer if they do not
+ // already exist. These will are forward-references which will be set to
+ // pointers to the class and metaclass structure created for the runtime
+ // load function. To send a message to super, we look up the value of the
+ // super_class pointer from either the class or metaclass structure.
+ if (IsClassMessage) {
+ if (!MetaClassPtrAlias) {
+ MetaClassPtrAlias = llvm::GlobalAlias::create(
+ IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
+ ".objc_metaclass_ref" + Class->getNameAsString(), &TheModule);
}
- ReceiverClass = Builder.CreateCall(classLookupFunction,
- MakeConstantString(Class->getNameAsString()));
+ ReceiverClass = MetaClassPtrAlias;
} else {
- // Set up global aliases for the metaclass or class pointer if they do not
- // already exist. These will are forward-references which will be set to
- // pointers to the class and metaclass structure created for the runtime
- // load function. To send a message to super, we look up the value of the
- // super_class pointer from either the class or metaclass structure.
- if (IsClassMessage) {
- if (!MetaClassPtrAlias) {
- MetaClassPtrAlias = llvm::GlobalAlias::create(
- IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
- ".objc_metaclass_ref" + Class->getNameAsString(), &TheModule);
- }
- ReceiverClass = MetaClassPtrAlias;
- } else {
- if (!ClassPtrAlias) {
- ClassPtrAlias = llvm::GlobalAlias::create(
- IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
- ".objc_class_ref" + Class->getNameAsString(), &TheModule);
- }
- ReceiverClass = ClassPtrAlias;
- }
- }
- // Cast the pointer to a simplified version of the class structure
- llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy);
- ReceiverClass = Builder.CreateBitCast(ReceiverClass,
- llvm::PointerType::getUnqual(CastTy));
- // Get the superclass pointer
- ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1);
- // Load the superclass pointer
- ReceiverClass =
- Builder.CreateAlignedLoad(ReceiverClass, CGF.getPointerAlign());
- }
+ if (!ClassPtrAlias) {
+ ClassPtrAlias = llvm::GlobalAlias::create(
+ IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
+ ".objc_class_ref" + Class->getNameAsString(), &TheModule);
+ }
+ ReceiverClass = ClassPtrAlias;
+ }
+ }
+ // Cast the pointer to a simplified version of the class structure
+ llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy);
+ ReceiverClass = Builder.CreateBitCast(ReceiverClass,
+ llvm::PointerType::getUnqual(CastTy));
+ // Get the superclass pointer
+ ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1);
+ // Load the superclass pointer
+ ReceiverClass =
+ Builder.CreateAlignedLoad(ReceiverClass, CGF.getPointerAlign());
// Construct the structure used to look up the IMP
llvm::StructType *ObjCSuperTy =
llvm::StructType::get(Receiver->getType(), IdTy);
- Address ObjCSuper = CGF.CreateTempAlloca(ObjCSuperTy,
+ // FIXME: Is this really supposed to be a dynamic alloca?
+ Address ObjCSuper = Address(Builder.CreateAlloca(ObjCSuperTy),
CGF.getPointerAlign());
Builder.CreateStore(Receiver,
@@ -2567,16 +1492,17 @@ CGObjCGNU::GenerateMessageSend(CodeGenFu
llvm::Constant *CGObjCGNU::
GenerateMethodList(StringRef ClassName,
StringRef CategoryName,
- ArrayRef<const ObjCMethodDecl*> Methods,
+ ArrayRef<Selector> MethodSels,
+ ArrayRef<llvm::Constant *> MethodTypes,
bool isClassMethodList) {
- if (Methods.empty())
+ if (MethodSels.empty())
return NULLPtr;
ConstantInitBuilder Builder(CGM);
auto MethodList = Builder.beginStruct();
MethodList.addNullPointer(CGM.Int8PtrTy);
- MethodList.addInt(Int32Ty, Methods.size());
+ MethodList.addInt(Int32Ty, MethodTypes.size());
// Get the method structure type.
llvm::StructType *ObjCMethodTy =
@@ -2585,48 +1511,20 @@ GenerateMethodList(StringRef ClassName,
PtrToInt8Ty, // Method types
IMPTy // Method pointer
});
- bool isV2ABI = isRuntime(ObjCRuntime::GNUstep, 2);
- if (isV2ABI) {
- // size_t size;
- llvm::DataLayout td(&TheModule);
- MethodList.addInt(SizeTy, td.getTypeSizeInBits(ObjCMethodTy) /
- CGM.getContext().getCharWidth());
- ObjCMethodTy =
- llvm::StructType::get(CGM.getLLVMContext(), {
- IMPTy, // Method pointer
- PtrToInt8Ty, // Selector
- PtrToInt8Ty // Extended type encoding
- });
- } else {
- ObjCMethodTy =
- llvm::StructType::get(CGM.getLLVMContext(), {
- PtrToInt8Ty, // Really a selector, but the runtime creates it us.
- PtrToInt8Ty, // Method types
- IMPTy // Method pointer
- });
- }
- auto MethodArray = MethodList.beginArray();
- ASTContext &Context = CGM.getContext();
- for (const auto *OMD : Methods) {
+ auto Methods = MethodList.beginArray();
+ for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
llvm::Constant *FnPtr =
TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
- OMD->getSelector(),
+ MethodSels[i],
isClassMethodList));
assert(FnPtr && "Can't generate metadata for method that doesn't exist");
- auto Method = MethodArray.beginStruct(ObjCMethodTy);
- if (isV2ABI) {
- Method.addBitCast(FnPtr, IMPTy);
- Method.add(GetConstantSelector(OMD->getSelector(),
- Context.getObjCEncodingForMethodDecl(OMD)));
- Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(OMD, true)));
- } else {
- Method.add(MakeConstantString(OMD->getSelector().getAsString()));
- Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(OMD)));
- Method.addBitCast(FnPtr, IMPTy);
- }
- Method.finishAndAddTo(MethodArray);
+ auto Method = Methods.beginStruct(ObjCMethodTy);
+ Method.add(MakeConstantString(MethodSels[i].getAsString()));
+ Method.add(MethodTypes[i]);
+ Method.addBitCast(FnPtr, IMPTy);
+ Method.finishAndAddTo(Methods);
}
- MethodArray.finishAndAddTo(MethodList);
+ Methods.finishAndAddTo(MethodList);
// Create an instance of the structure
return MethodList.finishAndCreateGlobal(".objc_method_list",
@@ -2637,9 +1535,7 @@ GenerateMethodList(StringRef ClassName,
llvm::Constant *CGObjCGNU::
GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
ArrayRef<llvm::Constant *> IvarTypes,
- ArrayRef<llvm::Constant *> IvarOffsets,
- ArrayRef<llvm::Constant *> IvarAlign,
- ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership) {
+ ArrayRef<llvm::Constant *> IvarOffsets) {
if (IvarNames.empty())
return NULLPtr;
@@ -2754,7 +1650,7 @@ llvm::Constant *CGObjCGNU::GenerateClass
// gc_object_type
Elements.add(NULLPtr);
// abi_version
- Elements.addInt(LongTy, ClassABIVersion);
+ Elements.addInt(LongTy, 1);
// ivar_offsets
Elements.add(IvarOffsets);
// properties
@@ -2783,22 +1679,22 @@ llvm::Constant *CGObjCGNU::GenerateClass
}
llvm::Constant *CGObjCGNU::
-GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods) {
+GenerateProtocolMethodList(ArrayRef<llvm::Constant *> MethodNames,
+ ArrayRef<llvm::Constant *> MethodTypes) {
// Get the method structure type.
llvm::StructType *ObjCMethodDescTy =
llvm::StructType::get(CGM.getLLVMContext(), { PtrToInt8Ty, PtrToInt8Ty });
- ASTContext &Context = CGM.getContext();
ConstantInitBuilder Builder(CGM);
auto MethodList = Builder.beginStruct();
- MethodList.addInt(IntTy, Methods.size());
- auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
- for (auto *M : Methods) {
- auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
- Method.add(MakeConstantString(M->getSelector().getAsString()));
- Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(M)));
- Method.finishAndAddTo(MethodArray);
+ MethodList.addInt(IntTy, MethodNames.size());
+ auto Methods = MethodList.beginArray(ObjCMethodDescTy);
+ for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) {
+ auto Method = Methods.beginStruct(ObjCMethodDescTy);
+ Method.add(MethodNames[i]);
+ Method.add(MethodTypes[i]);
+ Method.finishAndAddTo(Methods);
}
- MethodArray.finishAndAddTo(MethodList);
+ Methods.finishAndAddTo(MethodList);
return MethodList.finishAndCreateGlobal(".objc_method_list",
CGM.getPointerAlign());
}
@@ -2832,19 +1728,16 @@ CGObjCGNU::GenerateProtocolList(ArrayRef
llvm::Value *CGObjCGNU::GenerateProtocolRef(CodeGenFunction &CGF,
const ObjCProtocolDecl *PD) {
- llvm::Constant *&protocol = ExistingProtocols[PD->getNameAsString()];
- if (!protocol)
- GenerateProtocol(PD);
+ llvm::Value *protocol = ExistingProtocols[PD->getNameAsString()];
llvm::Type *T =
CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType());
return CGF.Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T));
}
llvm::Constant *
-CGObjCGNU::GenerateEmptyProtocol(StringRef ProtocolName) {
+CGObjCGNU::GenerateEmptyProtocol(const std::string &ProtocolName) {
llvm::Constant *ProtocolList = GenerateProtocolList({});
- llvm::Constant *MethodList = GenerateProtocolMethodList({});
- MethodList = llvm::ConstantExpr::getBitCast(MethodList, PtrToInt8Ty);
+ llvm::Constant *MethodList = GenerateProtocolMethodList({}, {});
// Protocols are objects containing lists of the methods implemented and
// protocols adopted.
ConstantInitBuilder Builder(CGM);
@@ -2863,11 +1756,12 @@ CGObjCGNU::GenerateEmptyProtocol(StringR
Elements.add(MethodList); /* .optional_class_methods */
Elements.add(NULLPtr); /* .properties */
Elements.add(NULLPtr); /* .optional_properties */
- return Elements.finishAndCreateGlobal(SymbolForProtocol(ProtocolName),
+ return Elements.finishAndCreateGlobal(".objc_protocol",
CGM.getPointerAlign());
}
void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
+ ASTContext &Context = CGM.getContext();
std::string ProtocolName = PD->getNameAsString();
// Use the protocol definition, if there is one.
@@ -2877,31 +1771,51 @@ void CGObjCGNU::GenerateProtocol(const O
SmallVector<std::string, 16> Protocols;
for (const auto *PI : PD->protocols())
Protocols.push_back(PI->getNameAsString());
- SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
- SmallVector<const ObjCMethodDecl*, 16> OptionalInstanceMethods;
- for (const auto *I : PD->instance_methods())
- if (I->isOptional())
- OptionalInstanceMethods.push_back(I);
- else
- InstanceMethods.push_back(I);
+ SmallVector<llvm::Constant*, 16> InstanceMethodNames;
+ SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
+ SmallVector<llvm::Constant*, 16> OptionalInstanceMethodNames;
+ SmallVector<llvm::Constant*, 16> OptionalInstanceMethodTypes;
+ for (const auto *I : PD->instance_methods()) {
+ std::string TypeStr = Context.getObjCEncodingForMethodDecl(I);
+ if (I->getImplementationControl() == ObjCMethodDecl::Optional) {
+ OptionalInstanceMethodNames.push_back(
+ MakeConstantString(I->getSelector().getAsString()));
+ OptionalInstanceMethodTypes.push_back(MakeConstantString(TypeStr));
+ } else {
+ InstanceMethodNames.push_back(
+ MakeConstantString(I->getSelector().getAsString()));
+ InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
+ }
+ }
// Collect information about class methods:
- SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
- SmallVector<const ObjCMethodDecl*, 16> OptionalClassMethods;
- for (const auto *I : PD->class_methods())
- if (I->isOptional())
- OptionalClassMethods.push_back(I);
- else
- ClassMethods.push_back(I);
+ SmallVector<llvm::Constant*, 16> ClassMethodNames;
+ SmallVector<llvm::Constant*, 16> ClassMethodTypes;
+ SmallVector<llvm::Constant*, 16> OptionalClassMethodNames;
+ SmallVector<llvm::Constant*, 16> OptionalClassMethodTypes;
+ for (const auto *I : PD->class_methods()) {
+ std::string TypeStr = Context.getObjCEncodingForMethodDecl(I);
+ if (I->getImplementationControl() == ObjCMethodDecl::Optional) {
+ OptionalClassMethodNames.push_back(
+ MakeConstantString(I->getSelector().getAsString()));
+ OptionalClassMethodTypes.push_back(MakeConstantString(TypeStr));
+ } else {
+ ClassMethodNames.push_back(
+ MakeConstantString(I->getSelector().getAsString()));
+ ClassMethodTypes.push_back(MakeConstantString(TypeStr));
+ }
+ }
llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
llvm::Constant *InstanceMethodList =
- GenerateProtocolMethodList(InstanceMethods);
+ GenerateProtocolMethodList(InstanceMethodNames, InstanceMethodTypes);
llvm::Constant *ClassMethodList =
- GenerateProtocolMethodList(ClassMethods);
+ GenerateProtocolMethodList(ClassMethodNames, ClassMethodTypes);
llvm::Constant *OptionalInstanceMethodList =
- GenerateProtocolMethodList(OptionalInstanceMethods);
+ GenerateProtocolMethodList(OptionalInstanceMethodNames,
+ OptionalInstanceMethodTypes);
llvm::Constant *OptionalClassMethodList =
- GenerateProtocolMethodList(OptionalClassMethods);
+ GenerateProtocolMethodList(OptionalClassMethodNames,
+ OptionalClassMethodTypes);
// Property metadata: name, attributes, isSynthesized, setter name, setter
// types, getter name, getter types.
@@ -2909,10 +1823,78 @@ void CGObjCGNU::GenerateProtocol(const O
// simplify the runtime library by allowing it to use the same data
// structures for protocol metadata everywhere.
- llvm::Constant *PropertyList =
- GeneratePropertyList(nullptr, PD, false, false);
- llvm::Constant *OptionalPropertyList =
- GeneratePropertyList(nullptr, PD, false, true);
+ llvm::Constant *PropertyList;
+ llvm::Constant *OptionalPropertyList;
+ {
+ llvm::StructType *propertyMetadataTy =
+ llvm::StructType::get(CGM.getLLVMContext(),
+ { PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty,
+ PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
+
+ unsigned numReqProperties = 0, numOptProperties = 0;
+ for (auto property : PD->instance_properties()) {
+ if (property->isOptional())
+ numOptProperties++;
+ else
+ numReqProperties++;
+ }
+
+ ConstantInitBuilder reqPropertyListBuilder(CGM);
+ auto reqPropertiesList = reqPropertyListBuilder.beginStruct();
+ reqPropertiesList.addInt(IntTy, numReqProperties);
+ reqPropertiesList.add(NULLPtr);
+ auto reqPropertiesArray = reqPropertiesList.beginArray(propertyMetadataTy);
+
+ ConstantInitBuilder optPropertyListBuilder(CGM);
+ auto optPropertiesList = optPropertyListBuilder.beginStruct();
+ optPropertiesList.addInt(IntTy, numOptProperties);
+ optPropertiesList.add(NULLPtr);
+ auto optPropertiesArray = optPropertiesList.beginArray(propertyMetadataTy);
+
+ // Add all of the property methods need adding to the method list and to the
+ // property metadata list.
+ for (auto *property : PD->instance_properties()) {
+ auto &propertiesArray =
+ (property->isOptional() ? optPropertiesArray : reqPropertiesArray);
+ auto fields = propertiesArray.beginStruct(propertyMetadataTy);
+
+ fields.add(MakePropertyEncodingString(property, nullptr));
+ PushPropertyAttributes(fields, property);
+
+ if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
+ std::string typeStr = Context.getObjCEncodingForMethodDecl(getter);
+ llvm::Constant *typeEncoding = MakeConstantString(typeStr);
+ InstanceMethodTypes.push_back(typeEncoding);
+ fields.add(MakeConstantString(getter->getSelector().getAsString()));
+ fields.add(typeEncoding);
+ } else {
+ fields.add(NULLPtr);
+ fields.add(NULLPtr);
+ }
+ if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
+ std::string typeStr = Context.getObjCEncodingForMethodDecl(setter);
+ llvm::Constant *typeEncoding = MakeConstantString(typeStr);
+ InstanceMethodTypes.push_back(typeEncoding);
+ fields.add(MakeConstantString(setter->getSelector().getAsString()));
+ fields.add(typeEncoding);
+ } else {
+ fields.add(NULLPtr);
+ fields.add(NULLPtr);
+ }
+
+ fields.finishAndAddTo(propertiesArray);
+ }
+
+ reqPropertiesArray.finishAndAddTo(reqPropertiesList);
+ PropertyList =
+ reqPropertiesList.finishAndCreateGlobal(".objc_property_list",
+ CGM.getPointerAlign());
+
+ optPropertiesArray.finishAndAddTo(optPropertiesList);
+ OptionalPropertyList =
+ optPropertiesList.finishAndCreateGlobal(".objc_property_list",
+ CGM.getPointerAlign());
+ }
// Protocols are objects containing lists of the methods implemented and
// protocols adopted.
@@ -2923,7 +1905,8 @@ void CGObjCGNU::GenerateProtocol(const O
Elements.add(
llvm::ConstantExpr::getIntToPtr(
llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
- Elements.add(MakeConstantString(ProtocolName));
+ Elements.add(
+ MakeConstantString(ProtocolName, ".objc_protocol_name"));
Elements.add(ProtocolList);
Elements.add(InstanceMethodList);
Elements.add(ClassMethodList);
@@ -2938,6 +1921,8 @@ void CGObjCGNU::GenerateProtocol(const O
}
void CGObjCGNU::GenerateProtocolHolderCategory() {
// Collect information about instance methods
+ SmallVector<Selector, 1> MethodSels;
+ SmallVector<llvm::Constant*, 1> MethodTypes;
ConstantInitBuilder Builder(CGM);
auto Elements = Builder.beginStruct();
@@ -2948,10 +1933,10 @@ void CGObjCGNU::GenerateProtocolHolderCa
Elements.add(MakeConstantString(ClassName));
// Instance method list
Elements.addBitCast(GenerateMethodList(
- ClassName, CategoryName, {}, false), PtrTy);
+ ClassName, CategoryName, MethodSels, MethodTypes, false), PtrTy);
// Class method list
Elements.addBitCast(GenerateMethodList(
- ClassName, CategoryName, {}, true), PtrTy);
+ ClassName, CategoryName, MethodSels, MethodTypes, true), PtrTy);
// Protocol list
ConstantInitBuilder ProtocolListBuilder(CGM);
@@ -3019,9 +2004,25 @@ llvm::Constant *CGObjCGNU::MakeBitField(
}
void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
- const ObjCInterfaceDecl *Class = OCD->getClassInterface();
- std::string ClassName = Class->getNameAsString();
+ std::string ClassName = OCD->getClassInterface()->getNameAsString();
std::string CategoryName = OCD->getNameAsString();
+ // Collect information about instance methods
+ SmallVector<Selector, 16> InstanceMethodSels;
+ SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
+ for (const auto *I : OCD->instance_methods()) {
+ InstanceMethodSels.push_back(I->getSelector());
+ std::string TypeStr = CGM.getContext().getObjCEncodingForMethodDecl(I);
+ InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
+ }
+
+ // Collect information about class methods
+ SmallVector<Selector, 16> ClassMethodSels;
+ SmallVector<llvm::Constant*, 16> ClassMethodTypes;
+ for (const auto *I : OCD->class_methods()) {
+ ClassMethodSels.push_back(I->getSelector());
+ std::string TypeStr = CGM.getContext().getObjCEncodingForMethodDecl(I);
+ ClassMethodTypes.push_back(MakeConstantString(TypeStr));
+ }
// Collect the names of referenced protocols
SmallVector<std::string, 16> Protocols;
@@ -3036,125 +2037,84 @@ void CGObjCGNU::GenerateCategory(const O
Elements.add(MakeConstantString(CategoryName));
Elements.add(MakeConstantString(ClassName));
// Instance method list
- SmallVector<ObjCMethodDecl*, 16> InstanceMethods;
- InstanceMethods.insert(InstanceMethods.begin(), OCD->instmeth_begin(),
- OCD->instmeth_end());
Elements.addBitCast(
- GenerateMethodList(ClassName, CategoryName, InstanceMethods, false),
+ GenerateMethodList(ClassName, CategoryName, InstanceMethodSels,
+ InstanceMethodTypes, false),
PtrTy);
// Class method list
-
- SmallVector<ObjCMethodDecl*, 16> ClassMethods;
- ClassMethods.insert(ClassMethods.begin(), OCD->classmeth_begin(),
- OCD->classmeth_end());
Elements.addBitCast(
- GenerateMethodList(ClassName, CategoryName, ClassMethods, true),
+ GenerateMethodList(ClassName, CategoryName, ClassMethodSels,
+ ClassMethodTypes, true),
PtrTy);
// Protocol list
Elements.addBitCast(GenerateProtocolList(Protocols), PtrTy);
- if (isRuntime(ObjCRuntime::GNUstep, 2)) {
- const ObjCCategoryDecl *Category =
- Class->FindCategoryDeclaration(OCD->getIdentifier());
- if (Category) {
- // Instance properties
- Elements.addBitCast(GeneratePropertyList(OCD, Category, false), PtrTy);
- // Class properties
- Elements.addBitCast(GeneratePropertyList(OCD, Category, true), PtrTy);
- } else {
- Elements.addNullPointer(PtrTy);
- Elements.addNullPointer(PtrTy);
- }
- }
-
Categories.push_back(llvm::ConstantExpr::getBitCast(
- Elements.finishAndCreateGlobal(
- std::string(".objc_category_")+ClassName+CategoryName,
- CGM.getPointerAlign()),
+ Elements.finishAndCreateGlobal("", CGM.getPointerAlign()),
PtrTy));
}
-llvm::Constant *CGObjCGNU::GeneratePropertyList(const Decl *Container,
- const ObjCContainerDecl *OCD,
- bool isClassProperty,
- bool protocolOptionalProperties) {
-
- SmallVector<const ObjCPropertyDecl *, 16> Properties;
- llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
- bool isProtocol = isa<ObjCProtocolDecl>(OCD);
+llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OID,
+ SmallVectorImpl<Selector> &InstanceMethodSels,
+ SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes) {
ASTContext &Context = CGM.getContext();
-
- std::function<void(const ObjCProtocolDecl *Proto)> collectProtocolProperties
- = [&](const ObjCProtocolDecl *Proto) {
- for (const auto *P : Proto->protocols())
- collectProtocolProperties(P);
- for (const auto *PD : Proto->properties()) {
- if (isClassProperty != PD->isClassProperty())
- continue;
- // Skip any properties that are declared in protocols that this class
- // conforms to but are not actually implemented by this class.
- if (!isProtocol && !Context.getObjCPropertyImplDeclForPropertyDecl(PD, Container))
- continue;
- if (!PropertySet.insert(PD->getIdentifier()).second)
- continue;
- Properties.push_back(PD);
- }
- };
-
- if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
- for (const ObjCCategoryDecl *ClassExt : OID->known_extensions())
- for (auto *PD : ClassExt->properties()) {
- if (isClassProperty != PD->isClassProperty())
- continue;
- PropertySet.insert(PD->getIdentifier());
- Properties.push_back(PD);
- }
-
- for (const auto *PD : OCD->properties()) {
- if (isClassProperty != PD->isClassProperty())
- continue;
- // If we're generating a list for a protocol, skip optional / required ones
- // when generating the other list.
- if (isProtocol && (protocolOptionalProperties != PD->isOptional()))
- continue;
- // Don't emit duplicate metadata for properties that were already in a
- // class extension.
- if (!PropertySet.insert(PD->getIdentifier()).second)
- continue;
-
- Properties.push_back(PD);
- }
-
- if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
- for (const auto *P : OID->all_referenced_protocols())
- collectProtocolProperties(P);
- else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD))
- for (const auto *P : CD->protocols())
- collectProtocolProperties(P);
-
- auto numProperties = Properties.size();
-
- if (numProperties == 0)
- return NULLPtr;
+ // Property metadata: name, attributes, attributes2, padding1, padding2,
+ // setter name, setter types, getter name, getter types.
+ llvm::StructType *propertyMetadataTy =
+ llvm::StructType::get(CGM.getLLVMContext(),
+ { PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty,
+ PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
+
+ unsigned numProperties = 0;
+ for (auto *propertyImpl : OID->property_impls()) {
+ (void) propertyImpl;
+ numProperties++;
+ }
ConstantInitBuilder builder(CGM);
auto propertyList = builder.beginStruct();
- auto properties = PushPropertyListHeader(propertyList, numProperties);
+ propertyList.addInt(IntTy, numProperties);
+ propertyList.add(NULLPtr);
+ auto properties = propertyList.beginArray(propertyMetadataTy);
// Add all of the property methods need adding to the method list and to the
// property metadata list.
- for (auto *property : Properties) {
- bool isSynthesized = false;
- bool isDynamic = false;
- if (!isProtocol) {
- auto *propertyImpl = Context.getObjCPropertyImplDeclForPropertyDecl(property, Container);
- if (propertyImpl) {
- isSynthesized = (propertyImpl->getPropertyImplementation() ==
- ObjCPropertyImplDecl::Synthesize);
- isDynamic = (propertyImpl->getPropertyImplementation() ==
- ObjCPropertyImplDecl::Dynamic);
+ for (auto *propertyImpl : OID->property_impls()) {
+ auto fields = properties.beginStruct(propertyMetadataTy);
+ ObjCPropertyDecl *property = propertyImpl->getPropertyDecl();
+ bool isSynthesized = (propertyImpl->getPropertyImplementation() ==
+ ObjCPropertyImplDecl::Synthesize);
+ bool isDynamic = (propertyImpl->getPropertyImplementation() ==
+ ObjCPropertyImplDecl::Dynamic);
+
+ fields.add(MakePropertyEncodingString(property, OID));
+ PushPropertyAttributes(fields, property, isSynthesized, isDynamic);
+ if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
+ std::string TypeStr = Context.getObjCEncodingForMethodDecl(getter);
+ llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
+ if (isSynthesized) {
+ InstanceMethodTypes.push_back(TypeEncoding);
+ InstanceMethodSels.push_back(getter->getSelector());
}
+ fields.add(MakeConstantString(getter->getSelector().getAsString()));
+ fields.add(TypeEncoding);
+ } else {
+ fields.add(NULLPtr);
+ fields.add(NULLPtr);
}
- PushProperty(properties, property, Container, isSynthesized, isDynamic);
+ if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
+ std::string TypeStr = Context.getObjCEncodingForMethodDecl(setter);
+ llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
+ if (isSynthesized) {
+ InstanceMethodTypes.push_back(TypeEncoding);
+ InstanceMethodSels.push_back(setter->getSelector());
+ }
+ fields.add(MakeConstantString(setter->getSelector().getAsString()));
+ fields.add(TypeEncoding);
+ } else {
+ fields.add(NULLPtr);
+ fields.add(NULLPtr);
+ }
+ fields.finishAndAddTo(properties);
}
properties.finishAndAddTo(propertyList);
@@ -3207,8 +2167,6 @@ void CGObjCGNU::GenerateClass(const ObjC
SmallVector<llvm::Constant*, 16> IvarNames;
SmallVector<llvm::Constant*, 16> IvarTypes;
SmallVector<llvm::Constant*, 16> IvarOffsets;
- SmallVector<llvm::Constant*, 16> IvarAligns;
- SmallVector<Qualifiers::ObjCLifetime, 16> IvarOwnership;
ConstantInitBuilder IvarOffsetBuilder(CGM);
auto IvarOffsetValues = IvarOffsetBuilder.beginArray(PtrToIntTy);
@@ -3231,8 +2189,6 @@ void CGObjCGNU::GenerateClass(const ObjC
std::string TypeStr;
Context.getObjCEncodingForType(IVD->getType(), TypeStr, IVD);
IvarTypes.push_back(MakeConstantString(TypeStr));
- IvarAligns.push_back(llvm::ConstantInt::get(IntTy,
- Context.getTypeSize(IVD->getType())));
// Get the offset
uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
uint64_t Offset = BaseOffset;
@@ -3243,7 +2199,6 @@ void CGObjCGNU::GenerateClass(const ObjC
// Create the direct offset value
std::string OffsetName = "__objc_ivar_offset_value_" + ClassName +"." +
IVD->getNameAsString();
-
llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
if (OffsetVar) {
OffsetVar->setInitializer(OffsetValue);
@@ -3252,13 +2207,14 @@ void CGObjCGNU::GenerateClass(const ObjC
// copy.
OffsetVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
} else
- OffsetVar = new llvm::GlobalVariable(TheModule, Int32Ty,
+ OffsetVar = new llvm::GlobalVariable(TheModule, IntTy,
false, llvm::GlobalValue::ExternalLinkage,
- OffsetValue, OffsetName);
+ OffsetValue,
+ "__objc_ivar_offset_value_" + ClassName +"." +
+ IVD->getNameAsString());
IvarOffsets.push_back(OffsetValue);
IvarOffsetValues.add(OffsetVar);
Qualifiers::ObjCLifetime lt = IVD->getType().getQualifiers().getObjCLifetime();
- IvarOwnership.push_back(lt);
switch (lt) {
case Qualifiers::OCL_Strong:
StrongIvars.push_back(true);
@@ -3280,30 +2236,25 @@ void CGObjCGNU::GenerateClass(const ObjC
CGM.getPointerAlign());
// Collect information about instance methods
- SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
- InstanceMethods.insert(InstanceMethods.begin(), OID->instmeth_begin(),
- OID->instmeth_end());
-
- SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
- ClassMethods.insert(ClassMethods.begin(), OID->classmeth_begin(),
- OID->classmeth_end());
-
- // Collect the same information about synthesized properties, which don't
- // show up in the instance method lists.
- for (auto *propertyImpl : OID->property_impls())
- if (propertyImpl->getPropertyImplementation() ==
- ObjCPropertyImplDecl::Synthesize) {
- ObjCPropertyDecl *property = propertyImpl->getPropertyDecl();
- auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) {
- if (accessor)
- InstanceMethods.push_back(accessor);
- };
- addPropertyMethod(property->getGetterMethodDecl());
- addPropertyMethod(property->getSetterMethodDecl());
- }
-
- llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl);
-
+ SmallVector<Selector, 16> InstanceMethodSels;
+ SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
+ for (const auto *I : OID->instance_methods()) {
+ InstanceMethodSels.push_back(I->getSelector());
+ std::string TypeStr = Context.getObjCEncodingForMethodDecl(I);
+ InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
+ }
+
+ llvm::Constant *Properties = GeneratePropertyList(OID, InstanceMethodSels,
+ InstanceMethodTypes);
+
+ // Collect information about class methods
+ SmallVector<Selector, 16> ClassMethodSels;
+ SmallVector<llvm::Constant*, 16> ClassMethodTypes;
+ for (const auto *I : OID->class_methods()) {
+ ClassMethodSels.push_back(I->getSelector());
+ std::string TypeStr = Context.getObjCEncodingForMethodDecl(I);
+ ClassMethodTypes.push_back(MakeConstantString(TypeStr));
+ }
// Collect the names of referenced protocols
SmallVector<std::string, 16> Protocols;
for (const auto *I : ClassDecl->protocols())
@@ -3320,11 +2271,11 @@ void CGObjCGNU::GenerateClass(const ObjC
SmallVector<llvm::Constant*, 1> empty;
// Generate the method and instance variable lists
llvm::Constant *MethodList = GenerateMethodList(ClassName, "",
- InstanceMethods, false);
+ InstanceMethodSels, InstanceMethodTypes, false);
llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "",
- ClassMethods, true);
+ ClassMethodSels, ClassMethodTypes, true);
llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
- IvarOffsets, IvarAligns, IvarOwnership);
+ IvarOffsets);
// Irrespective of whether we are compiling for a fragile or non-fragile ABI,
// we emit a symbol containing the offset for each ivar in the class. This
// allows code compiled for the non-Fragile ABI to inherit from code compiled
@@ -3337,13 +2288,14 @@ void CGObjCGNU::GenerateClass(const ObjC
// the offset (third field in ivar structure)
llvm::Type *IndexTy = Int32Ty;
llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
- llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 2 : 1), nullptr,
- llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 3 : 2) };
+ llvm::ConstantInt::get(IndexTy, 1), nullptr,
+ llvm::ConstantInt::get(IndexTy, 2) };
unsigned ivarIndex = 0;
for (const ObjCIvarDecl *IVD = ClassDecl->all_declared_ivar_begin(); IVD;
IVD = IVD->getNextIvar()) {
- const std::string Name = GetIVarOffsetVariableName(ClassDecl, IVD);
+ const std::string Name = "__objc_ivar_offset_" + ClassName + '.'
+ + IVD->getNameAsString();
offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, ivarIndex);
// Get the correct ivar field
llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
@@ -3357,10 +2309,12 @@ void CGObjCGNU::GenerateClass(const ObjC
// different modules will use this one, rather than their private
// copy.
offset->setLinkage(llvm::GlobalValue::ExternalLinkage);
- } else
+ } else {
// Add a new alias if there isn't one already.
- new llvm::GlobalVariable(TheModule, offsetValue->getType(),
+ offset = new llvm::GlobalVariable(TheModule, offsetValue->getType(),
false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name);
+ (void) offset; // Silence dead store warning.
+ }
++ivarIndex;
}
llvm::Constant *ZeroPtr = llvm::ConstantInt::get(IntPtrTy, 0);
@@ -3368,8 +2322,8 @@ void CGObjCGNU::GenerateClass(const ObjC
//Generate metaclass for class methods
llvm::Constant *MetaClassStruct = GenerateClassStructure(
NULLPtr, NULLPtr, 0x12L, ClassName.c_str(), nullptr, Zeros[0],
- NULLPtr, ClassMethodList, NULLPtr, NULLPtr,
- GeneratePropertyList(OID, ClassDecl, true), ZeroPtr, ZeroPtr, true);
+ GenerateIvarList(empty, empty, empty), ClassMethodList, NULLPtr, NULLPtr,
+ NULLPtr, ZeroPtr, ZeroPtr, true);
CGM.setGVProperties(cast<llvm::GlobalValue>(MetaClassStruct),
OID->getClassInterface());
@@ -3807,7 +2761,8 @@ void CGObjCGNU::EmitGCMemmoveCollectable
llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar) {
- const std::string Name = GetIVarOffsetVariableName(ID, Ivar);
+ const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
+ + '.' + Ivar->getNameAsString();
// Emit the variable and initialize it with what we think the correct value
// is. This allows code compiled with non-fragile ivars to work correctly
// when linked against code which isn't (most of the time).
@@ -3916,11 +2871,8 @@ llvm::Value *CGObjCGNU::EmitIvarOffset(C
CGObjCRuntime *
clang::CodeGen::CreateGNUObjCRuntime(CodeGenModule &CGM) {
- auto Runtime = CGM.getLangOpts().ObjCRuntime;
- switch (Runtime.getKind()) {
+ switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
case ObjCRuntime::GNUstep:
- if (Runtime.getVersion() >= VersionTuple(2, 0))
- return new CGObjCGNUstep2(CGM);
return new CGObjCGNUstep(CGM);
case ObjCRuntime::GCC:
Modified: cfe/trunk/lib/Driver/ToolChains/Clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains/Clang.cpp?rev=332957&r1=332956&r2=332957&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains/Clang.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChains/Clang.cpp Tue May 22 01:16:45 2018
@@ -4852,13 +4852,6 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(co
getToolChain().getDriver().Diag(diag::err_drv_unknown_objc_runtime)
<< value;
}
- if ((runtime.getKind() == ObjCRuntime::GNUstep) &&
- (runtime.getVersion() >= VersionTuple(2, 0)))
- if (!getToolChain().getTriple().isOSBinFormatELF()) {
- getToolChain().getDriver().Diag(
- diag::err_drv_gnustep_objc_runtime_incompatible_binary)
- << runtime.getVersion().getMajor();
- }
runtimeArg->render(args, cmdArgs);
return runtime;
@@ -4952,7 +4945,7 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(co
// Legacy behaviour is to target the gnustep runtime if we are in
// non-fragile mode or the GCC runtime in fragile mode.
if (isNonFragile)
- runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(2, 0));
+ runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(1, 6));
else
runtime = ObjCRuntime(ObjCRuntime::GCC, VersionTuple());
}
Modified: cfe/trunk/lib/Frontend/InitPreprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/InitPreprocessor.cpp?rev=332957&r1=332956&r2=332957&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/InitPreprocessor.cpp (original)
+++ cfe/trunk/lib/Frontend/InitPreprocessor.cpp Tue May 22 01:16:45 2018
@@ -645,19 +645,6 @@ static void InitializePredefinedMacros(c
if (LangOpts.ObjCRuntime.isNeXTFamily())
Builder.defineMacro("__NEXT_RUNTIME__");
- if (LangOpts.ObjCRuntime.getKind() == ObjCRuntime::GNUstep) {
- auto version = LangOpts.ObjCRuntime.getVersion();
- std::string versionString = "1";
- // Don't rely on the tuple argument, because we can be asked to target
- // later ABIs than we actually support, so clamp these values to those
- // currently supported
- if (version >= VersionTuple(2, 0))
- Builder.defineMacro("__OBJC_GNUSTEP_RUNTIME_ABI__", "20");
- else
- Builder.defineMacro("__OBJC_GNUSTEP_RUNTIME_ABI__",
- "1" + Twine(std::min(8U, version.getMinor().getValueOr(0))));
- }
-
if (LangOpts.ObjCRuntime.getKind() == ObjCRuntime::ObjFW) {
VersionTuple tuple = LangOpts.ObjCRuntime.getVersion();
Modified: cfe/trunk/test/CodeGenObjC/constant-strings.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/constant-strings.m?rev=332957&r1=332956&r2=332957&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/constant-strings.m (original)
+++ cfe/trunk/test/CodeGenObjC/constant-strings.m Tue May 22 01:16:45 2018
@@ -14,18 +14,5 @@
// RUN: %clang_cc1 -triple x86_64-macho -fobjc-runtime=gcc -fconstant-string-class NSConstantString -emit-llvm -o %t %s
// RUN: FileCheck --check-prefix=CHECK-GNU-WITH-CLASS < %t %s
// CHECK-GNU-WITH-CLASS: NSConstantString
-//
-// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -fobjc-runtime=gnustep-2.0 -emit-llvm -o %t %s
-// RUN: FileCheck --check-prefix=CHECK-GNUSTEP2 < %t %s
-
-// CHECK-GNUSTEP2: @._OBJC_CLASS_NSConstantString = external global i8*
-// CHECK-GNUSTEP2: @0 = private unnamed_addr constant [13 x i8] c"Hello World!\00", align 1
-// CHECK-GNUSTEP2: @.objc_string = private global { i8**, i32, i32, i32, i32, i8* } { i8** @._OBJC_CLASS_NSConstantString, i32 0, i32 12, i32 12, i32 0, i8* getelementptr inbounds ([13 x i8], [13 x i8]* @0, i64 0, i64 0) }, section "__objc_constant_string", align 8
-// CHECK-GNUSTEP2: @b = global i8* inttoptr (i64 -3340545023602065388 to i8*), align 8
-// CHECK-GNUSTEP2: @.objc_str_Hello_World = linkonce_odr hidden global { i8**, i32, i32, i32, i32, i8* } { i8** @._OBJC_CLASS_NSConstantString, i32 0, i32 11, i32 11, i32 0, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @1, i64 0, i64 0) }, section "__objc_constant_string", comdat, align 8
-// CHECK-GNUSTEP2: @c =
-// CHECK-SAME-GNUSTEP2: @.objc_str_Hello_World
-//
id a = @"Hello World!";
-id b = @"hi";
-id c = @"Hello World";
+
Removed: cfe/trunk/test/CodeGenObjC/forward-declare-protocol-gnu.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/forward-declare-protocol-gnu.m?rev=332956&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/forward-declare-protocol-gnu.m (original)
+++ cfe/trunk/test/CodeGenObjC/forward-declare-protocol-gnu.m (removed)
@@ -1,11 +0,0 @@
-// RUN: %clang -S -emit-llvm %s -o - -x objective-c -fobjc-runtime=gnustep-1.5 | FileCheck %s
-
-// Regression test: check that we don't crash when referencing a forward-declared protocol.
- at protocol P;
-
-Protocol *getProtocol(void)
-{
- return @protocol(P);
-}
-
-// CHECK: @.objc_protocol
Modified: cfe/trunk/test/CodeGenObjC/gnu-empty-protocol-v3.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/gnu-empty-protocol-v3.m?rev=332957&r1=332956&r2=332957&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/gnu-empty-protocol-v3.m (original)
+++ cfe/trunk/test/CodeGenObjC/gnu-empty-protocol-v3.m Tue May 22 01:16:45 2018
@@ -9,18 +9,17 @@ __attribute__((objc_root_class))
@implementation Z
@end
-
// CHECK: @.objc_protocol_list = internal global { i8*, i32, [0 x i8*] } zeroinitializer, align 4
// CHECK: @.objc_method_list = internal global { i32, [0 x { i8*, i8* }] } zeroinitializer, align 4
// CHECK: @.objc_protocol_name = private unnamed_addr constant [2 x i8] c"X\00", align 1
-// CHECK: @._OBJC_PROTOCOL_X = internal global { i8*, i8*, { i8*, i32, [0 x i8*] }*, i8*, i8*, i8*, i8*, i8*, i8* } {
+// CHECK: @.objc_protocol = internal global { i8*, i8*, { i8*, i32, [0 x i8*] }*, { i32, [0 x { i8*, i8* }] }*, { i32, [0 x { i8*, i8* }] }*, { i32, [0 x { i8*, i8* }] }*, { i32, [0 x { i8*, i8* }] }*, i8*, i8* } {
// CHECK-SAME: i8* inttoptr (i32 3 to i8*),
// CHECK-SAME: i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.objc_protocol_name, i32 0, i32 0),
-// CHECK-SAME: { i8*, i32, [0 x i8*] }* @.objc_protocol_list
-// CHECK-SAME: { i32, [0 x { i8*, i8* }] }* @.objc_method_list
-// CHECK-SAME: { i32, [0 x { i8*, i8* }] }* @.objc_method_list
-// CHECK-SAME: { i32, [0 x { i8*, i8* }] }* @.objc_method_list
-// CHECK-SAME: { i32, [0 x { i8*, i8* }] }* @.objc_method_list
-// CHECK-SAME: i8* null
+// CHECK-SAME: { i8*, i32, [0 x i8*] }* @.objc_protocol_list,
+// CHECK-SAME: { i32, [0 x { i8*, i8* }] }* @.objc_method_list,
+// CHECK-SAME: { i32, [0 x { i8*, i8* }] }* @.objc_method_list,
+// CHECK-SAME: { i32, [0 x { i8*, i8* }] }* @.objc_method_list,
+// CHECK-SAME: { i32, [0 x { i8*, i8* }] }* @.objc_method_list,
+// CHECK-SAME: i8* null,
// CHECK-SAME: i8* null
// CHECK-SAME: }, align 4
Removed: cfe/trunk/test/CodeGenObjC/gnu-init.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/gnu-init.m?rev=332956&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/gnu-init.m (original)
+++ cfe/trunk/test/CodeGenObjC/gnu-init.m (removed)
@@ -1,69 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s -check-prefix=CHECK-NEW
-// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-1.8 -o - %s | FileCheck %s -check-prefix=CHECK-OLD
-
-// Almost minimal Objective-C file, check that it emits calls to the correct
-// runtime entry points.
- at interface X @end
- at implementation X @end
-
-
-// Check that we emit a class ref
-// CHECK-NEW: @._OBJC_REF_CLASS_X
-// CHECK-NEW-SAME: section "__objc_class_refs"
-
-// Check that we get a class ref to the defined class.
-// CHECK-NEW: @._OBJC_INIT_CLASS_X = global
-// CHECK-NEW-SAME* @._OBJC_CLASS_X, section "__objc_classes"
-
-// Check that we emit the section start and end symbols as hidden globals.
-// CHECK-NEW: @__start___objc_selectors = external hidden global i8*
-// CHECK-NEW: @__stop___objc_selectors = external hidden global i8*
-// CHECK-NEW: @__start___objc_classes = external hidden global i8*
-// CHECK-NEW: @__stop___objc_classes = external hidden global i8*
-// CHECK-NEW: @__start___objc_class_refs = external hidden global i8*
-// CHECK-NEW: @__stop___objc_class_refs = external hidden global i8*
-// CHECK-NEW: @__start___objc_cats = external hidden global i8*
-// CHECK-NEW: @__stop___objc_cats = external hidden global i8*
-// CHECK-NEW: @__start___objc_protocols = external hidden global i8*
-// CHECK-NEW: @__stop___objc_protocols = external hidden global i8*
-// CHECK-NEW: @__start___objc_protocol_refs = external hidden global i8*
-// CHECK-NEW: @__stop___objc_protocol_refs = external hidden global i8*
-// CHECK-NEW: @__start___objc_class_aliases = external hidden global i8*
-// CHECK-NEW: @__stop___objc_class_aliases = external hidden global i8*
-// CHECK-NEW: @__start___objc_constant_string = external hidden global i8*
-// CHECK-NEW: @__stop___objc_constant_string = external hidden global i8*
-
-// Check that we emit the init structure correctly, including in a comdat.
-// CHECK-NEW: @.objc_init = linkonce_odr hidden global { i64, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8** } { i64 0, i8** @__start___objc_selectors, i8** @__stop___objc_selectors, i8** @__start___objc_classes, i8** @__stop___objc_classes, i8** @__start___objc_class_refs, i8** @__stop___objc_class_refs, i8** @__start___objc_cats, i8** @__stop___objc_cats, i8** @__start___objc_protocols, i8** @__stop___objc_protocols, i8** @__start___objc_protocol_refs, i8** @__stop___objc_protocol_refs, i8** @__start___objc_class_aliases, i8** @__stop___objc_class_aliases, i8** @__start___objc_constant_string, i8** @__stop___objc_constant_string }, comdat, align 8
-
-// Check that the load function is manually inserted into .ctors.
-// CHECK-NEW: @.objc_ctor = linkonce hidden constant void ()* @.objcv2_load_function, section ".ctors", comdat
-
-
-// Make sure that we provide null versions of everything so the __start /
-// __stop symbols work.
-// CHECK-NEW: @.objc_null_selector = linkonce_odr hidden global { i8*, i8* } zeroinitializer, section "__objc_selectors", comdat, align 8
-// CHECK-NEW: @.objc_null_category = linkonce_odr hidden global { i8*, i8*, i8*, i8*, i8*, i8*, i8* } zeroinitializer, section "__objc_cats", comdat, align 8
-// CHECK-NEW: @.objc_null_protocol = linkonce_odr hidden global { i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8* } zeroinitializer, section "__objc_protocols", comdat, align 8
-// CHECK-NEW: @.objc_null_protocol_ref = linkonce_odr hidden global { i8* } zeroinitializer, section "__objc_protocol_refs", comdat, align 8
-// CHECK-NEW: @.objc_null_class_alias = linkonce_odr hidden global { i8*, i8* } zeroinitializer, section "__objc_class_aliases", comdat, align 8
-// CHECK-NEW: @.objc_null_constant_string = linkonce_odr hidden global { i8*, i32, i32, i32, i32, i8* } zeroinitializer, section "__objc_constant_string", comdat, align 8
-// Make sure that the null symbols are not going to be removed, even by linking.
-// CHECK-NEW: @llvm.used = appending global [7 x i8*] [i8* bitcast ({ { i8*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }** @._OBJC_INIT_CLASS_X to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_selector to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_category to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_protocol to i8*), i8* bitcast ({ i8* }* @.objc_null_protocol_ref to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_class_alias to i8*), i8* bitcast ({ i8*, i32, i32, i32, i32, i8* }* @.objc_null_constant_string to i8*)], section "llvm.metadata"
-// Make sure that the load function and the reference to it are marked as used.
-// CHECK-NEW: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast (void ()* @.objcv2_load_function to i8*), i8* bitcast (void ()** @.objc_ctor to i8*)], section "llvm.metadata"
-
-// Check that we emit the load function in a comdat and that it does the right thing.
-// CHECK-NEW: define linkonce_odr hidden void @.objcv2_load_function() comdat {
-// CHECK-NEW-NEXT: entry:
-// CHECK-NEW-NEXT: call void @__objc_load(
-// CHECK-NEW-SAME: @.objc_init
-// CHECK-NEW-NEXT: ret void
-
-// CHECK-OLD: @4 = internal global { i64, i64, i8*, { i64, { i8*, i8* }*, i16, i16, [4 x i8*] }* } { i64 9, i64 32, i8* getelementptr inbounds ([103 x i8], [103 x i8]* @.objc_source_file_name, i64 0, i64 0), { i64, { i8*, i8* }*, i16, i16, [4 x i8*] }* @3 }, align 8
-// CHECK-OLD: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @.objc_load_function, i8* null }]
-
-// CHECK-OLD: define internal void @.objc_load_function() {
-// CHECK-OLD-NEXT: entry:
-// CHECK-OLD-NEXT: call void ({ i64, i64, i8*, { i64, { i8*, i8* }*, i16, i16, [4 x i8*] }* }*, ...) @__objc_exec_class({ i64, i64, i8*, { i64, { i8*, i8* }*, i16, i16, [4 x i8*] }* }* @4)
-
Removed: cfe/trunk/test/CodeGenObjC/gnustep2-category.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/gnustep2-category.m?rev=332956&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/gnustep2-category.m (original)
+++ cfe/trunk/test/CodeGenObjC/gnustep2-category.m (removed)
@@ -1,26 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s
-
-
-// Check that we have a method list that refers to the correct thing method:
-// CHECK: internal global { i8*, i32, i64, [1 x { i8* (i8*, i8*, ...)*, i8*, i8* }] } { i8* null, i32 1, i64 24,
-// CHECK-SAME: @_i_X_Cat_x
-// CHECK-SAME: @".objc_selector_x_i16\010:8"
-
-// Check that we emit the correct encoding for the property (somewhere)
-// CHECK: c"Ti,R\00"
-
-// Check that we emit a single-element property list of the correct form.
-// CHECK: internal global { i32, i32, i8*, [1 x { i8*, i8*, i8*, i8*, i8* }] }
-
-// CHECK: @.objc_category_XCat = internal global { i8*, i8*, i8*, i8*, i8*, i8*, i8* }
-// CHECK-SAME: section "__objc_cats", align 8
-
- at interface X @end
-
- at interface X (Cat)
- at property (readonly) int x;
- at end
-
- at implementation X (Cat)
-- (int)x { return 12; }
- at end
Removed: cfe/trunk/test/CodeGenObjC/gnustep2-class.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/gnustep2-class.m?rev=332956&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/gnustep2-class.m (original)
+++ cfe/trunk/test/CodeGenObjC/gnustep2-class.m (removed)
@@ -1,55 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s
-
- at interface Super @end
-
- at interface X : Super
-{
- int ivar1;
- id ivar2;
-}
- at property (readonly) int x;
- at property id y;
- at end
-
- at implementation X
- at synthesize y;
-
-- (int)x { return 12; }
-+ (int)clsMeth { return 42; }
-- (id)meth { return ivar2; }
- at end
-
-// Check that we get an ivar offset variable for the synthesised ivar.
-// CHECK: @"__objc_ivar_offset_X.y.\01" = hidden global i32 16
-//
-// Check that we get a sensible metaclass method list.
-// CHECK: internal global { i8*, i32, i64, [1 x { i8* (i8*, i8*, ...)*, i8*, i8* }] }
-// CHECK-SAME: @_c_X__clsMeth
-
-// Check that we get a metaclass and that it is not an exposed symbol:
-// CHECK: @._OBJC_METACLASS_X = internal global
-
-// Check that we get a reference to the superclass symbol:
-// CHECK: @._OBJC_CLASS_Super = external global i8*
-
-// Check that we get an ivar list with all three ivars, in the correct order
-// CHECK: private global { i32, i64, [3 x { i8*, i8*, i32*, i32, i32 }] }
-// CHECK-SAME: @__objc_ivar_offset_X.ivar1.i
-// CHECK-SAME: @"__objc_ivar_offset_X.ivar2.\01"
-// CHECK-SAME: @"__objc_ivar_offset_X.y.\01"
-
-// Check that we get some plausible property metadata.
-// CHECK: private unnamed_addr constant [5 x i8] c"Ti,R\00", align 1
-// CHECK: private unnamed_addr constant [6 x i8] c"T@,Vy\00", align 1
-// CHECK: = internal global { i32, i32, i8*, [2 x { i8*, i8*, i8*, i8*, i8* }] } { i32 2, i32 40, i8* null,
-
-// Check that we get a class structure.
-// CHECK: @._OBJC_CLASS_X = global { { i8*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }*, i8*, i8*, i64, i64, i64, { i32, i64, [3 x { i8*, i8*, i32*, i32, i32 }] }*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, { i32, i32, i8*, [2 x { i8*, i8*, i8*, i8*, i8* }] }* }
-// CHECK-SAME: @._OBJC_METACLASS_X
-// CHECK-SAME: @._OBJC_CLASS_Super
-
-// And check that we get a pointer to it in the right place
-// CHECK: @._OBJC_REF_CLASS_X = global
-// CHECK-SAME: @._OBJC_CLASS_X
-// CHECK-SAMEsection "__objc_class_refs"
-
Removed: cfe/trunk/test/CodeGenObjC/gnustep2-ivar-offset.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/gnustep2-ivar-offset.m?rev=332956&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/gnustep2-ivar-offset.m (original)
+++ cfe/trunk/test/CodeGenObjC/gnustep2-ivar-offset.m (removed)
@@ -1,28 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s
-
-
- at class NSString;
-
- at interface ANObject {
- at public
-// Public ivars have default visibility
-// CHECK: @"__objc_ivar_offset_ANObject.isa.\01" = global i32 0
- struct objc_object *isa;
- at private
-// Private and package ivars should have hidden linkage.
-// Check that in the GNUstep v2 ABI, instance variable offset names include
-// type encodings (with @ mangled to \01 to avoid collisions with ELF symbol
-// versions).
-// CHECK: private unnamed_addr constant [12 x i8] c"@\22NSString\22\00"
-// CHECK: @"__objc_ivar_offset_ANObject._stringIvar.\01" = hidden global i32 8
- NSString *_stringIvar;
- at package
-// CHECK: @__objc_ivar_offset_ANObject._intIvar.i = hidden global i32 16
- int _intIvar;
-}
- at end
- at implementation ANObject @end
-
-// Check that the ivar metadata contains 3 entries of the correct form and correctly sets the size.
-// CHECK: @.objc_ivar_list = private global { i32, i64, [3 x { i8*, i8*, i32*, i32, i32 }] } { i32 3, i64 32,
-// Check that we're emitting the extended type encoding for the string ivar.
Removed: cfe/trunk/test/CodeGenObjC/gnustep2-proto.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/gnustep2-proto.m?rev=332956&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/gnustep2-proto.m (original)
+++ cfe/trunk/test/CodeGenObjC/gnustep2-proto.m (removed)
@@ -1,39 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s
-
- at protocol X
- at optional
-- (id)x;
- at required
-+ (void*)y;
- at property int reqProp;
- at optional
- at property int optProp;
- at end
-
-// Check that we get some plausible-looking method lists.
-// CHECK: internal global { i32, i32, [2 x { i8*, i8* }] } { i32 2, i32 16,
-// CHECK-SAME: @".objc_selector_reqProp_i16\010:8"
-// CHECK-SAME: @".objc_selector_setReqProp:_v20\010:8i16"
-// CHECK: internal global { i32, i32, [3 x { i8*, i8* }] } { i32 3, i32 16,
-// CHECK-SAME: @".objc_selector_x_\0116\010:8"
-// CHECK-SAME: @".objc_selector_optProp_i16\010:8"
-// CHECK-SAME: @".objc_selector_setOptProp:_v20\010:8i16"
-
-
-// Check that we're emitting the protocol and a correctly initialised
-// indirection variable.
-// CHECK: @._OBJC_PROTOCOL_X = global
-// CHECK-SAME: , section "__objc_protocols", comdat, align 8
-// CHECK: @._OBJC_REF_PROTOCOL_X = global
-// CHECK-SAME: @._OBJC_PROTOCOL_X
-// CHECK-SAME: , section "__objc_protocol_refs", align 8
-
-
-// Check that we load from the indirection variable on protocol references.
-// CHECK: define i8* @x()
-// CHECK: = load
-// CHECK-SAME: @._OBJC_REF_PROTOCOL_X, align 8
-void *x()
-{
- return @protocol(X);
-}
Modified: cfe/trunk/test/CodeGenObjC/ivar-type-encoding.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/ivar-type-encoding.m?rev=332957&r1=332956&r2=332957&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/ivar-type-encoding.m (original)
+++ cfe/trunk/test/CodeGenObjC/ivar-type-encoding.m Tue May 22 01:16:45 2018
@@ -29,10 +29,10 @@ int main() {
return 0;
}
-// CHECK: = private unnamed_addr constant [12 x i8] c"_stringIvar\00"
-// CHECK: = private unnamed_addr constant [12 x i8] c"@\22NSString\22\00"
-// CHECK: = private unnamed_addr constant [9 x i8] c"_intIvar\00"
-// CHECK: = private unnamed_addr constant [2 x i8] c"i\00"
+// CHECK: @0 = private unnamed_addr constant [12 x i8] c"_stringIvar\00"
+// CHECK: @1 = private unnamed_addr constant [12 x i8] c"@\22NSString\22\00"
+// CHECK: @2 = private unnamed_addr constant [9 x i8] c"_intIvar\00"
+// CHECK: @3 = private unnamed_addr constant [2 x i8] c"i\00"
@interface Class1 {
int : 3;
Modified: cfe/trunk/test/Preprocessor/init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/init.c?rev=332957&r1=332956&r2=332957&view=diff
==============================================================================
--- cfe/trunk/test/Preprocessor/init.c (original)
+++ cfe/trunk/test/Preprocessor/init.c Tue May 22 01:16:45 2018
@@ -9002,13 +9002,6 @@
// RUN: %clang_cc1 -x c++ -triple sparc-rtems-elf -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GNUSOURCE %s
// GNUSOURCE:#define _GNU_SOURCE 1
//
-// Check that the GNUstep Objective-C ABI defines exist and are clamped at the
-// highest supported version.
-// RUN: %clang_cc1 -x objective-c -triple i386-unknown-freebsd -fobjc-runtime=gnustep-1.9 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GNUSTEP1 %s
-// GNUSTEP1:#define __OBJC_GNUSTEP_RUNTIME_ABI__ 18
-// RUN: %clang_cc1 -x objective-c -triple i386-unknown-freebsd -fobjc-runtime=gnustep-2.5 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GNUSTEP2 %s
-// GNUSTEP2:#define __OBJC_GNUSTEP_RUNTIME_ABI__ 20
-//
// RUN: %clang_cc1 -x c++ -std=c++98 -fno-rtti -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix NORTTI %s
// NORTTI: #define __GXX_ABI_VERSION {{.*}}
// NORTTI-NOT:#define __GXX_RTTI
More information about the cfe-commits
mailing list