diff options
Diffstat (limited to 'lib/CodeGen/CGObjCMac.cpp')
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 160 |
1 files changed, 147 insertions, 13 deletions
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 205a8f55e9..ce53b5b231 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -14,17 +14,43 @@ #include "CGObjCRuntime.h" #include "CodeGenModule.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/Basic/LangOptions.h" +#include "llvm/Module.h" #include "llvm/Support/IRBuilder.h" using namespace clang; namespace { + +/// ObjCTypesHelper - Helper class that encapsulates lazy +/// construction of varies types used during ObjC generation. +class ObjCTypesHelper { +private: + CodeGen::CodeGenModule &CGM; + + const llvm::StructType *CFStringType; + llvm::Constant *CFConstantStringClassReference; + +public: + const llvm::Type *LongTy; + +public: + ObjCTypesHelper(CodeGen::CodeGenModule &cgm); + ~ObjCTypesHelper(); + + llvm::Constant *getCFConstantStringClassReference(); + const llvm::StructType *getCFStringType(); +}; + class CGObjCMac : public CodeGen::CGObjCRuntime { private: - CodeGen::CodeGenModule &CGM; + CodeGen::CodeGenModule &CGM; + ObjCTypesHelper ObjCTypes; + /// ObjCABI - FIXME: Not sure yet. + unsigned ObjCABI; /// UsedGlobals - list of globals to pack into the llvm.used metadata /// to prevent them from being clobbered. @@ -40,8 +66,7 @@ private: public: CGObjCMac(CodeGen::CodeGenModule &cgm); - virtual llvm::Constant *GenerateConstantString(const char *String, - const size_t length); + virtual llvm::Constant *GenerateConstantString(const std::string &String); virtual llvm::Value *GenerateMessageSend(llvm::IRBuilder<> &Builder, const llvm::Type *ReturnTy, @@ -108,9 +133,32 @@ public: virtual llvm::Function *ModuleInitFunction(); }; } // end anonymous namespace + +/* *** Helper Functions *** */ + +/// getConstantGEP() - Help routine to construct simple GEPs. +static llvm::Constant *getConstantGEP(llvm::Constant *C, + unsigned idx0, + unsigned idx1) { + llvm::Value *Idxs[] = { + llvm::ConstantInt::get(llvm::Type::Int32Ty, idx0), + llvm::ConstantInt::get(llvm::Type::Int32Ty, idx1) + }; + return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2); +} + +/* *** CGObjCMac Public Interface *** */ -CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGM(cgm) { - EmitImageInfo(); +CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) + : CGM(cgm), + ObjCTypes(cgm), + ObjCABI(1) +{ + // FIXME: How does this get set in GCC? And what does it even mean? + if (ObjCTypes.LongTy != CGM.getTypes().ConvertType(CGM.getContext().IntTy)) + ObjCABI = 2; + + EmitImageInfo(); } // This has to perform the lookup every time, since posing and related @@ -127,11 +175,51 @@ llvm::Value *CGObjCMac::GetSelector(llvm::IRBuilder<> &Builder, Selector Sel) { return 0; } -/// Generate an NSConstantString object. -llvm::Constant *CGObjCMac::GenerateConstantString(const char *String, - const size_t length) { - assert(0 && "Cannot generate constant string for Mac runtime."); - return 0; +/// Generate a constant CFString object. +/* + struct __builtin_CFString { + const int *isa; // point to __CFConstantStringClassReference + int flags; + const char *str; + long length; + }; +*/ + +llvm::Constant *CGObjCMac::GenerateConstantString(const std::string &String) { + // FIXME: I have no idea what this constant is (it is a magic + // constant in GCC as well). Most likely the encoding of the string + // and at least one part of it relates to UTF-16. Is this just the + // code for UTF-8? Where is this handled for us? + // See: <rdr://2996215> + unsigned flags = 0x07c8; + + // FIXME: Use some machinery to unique this. We can't reuse the CGM + // one since we put them in a different section. + llvm::Constant *StringC = llvm::ConstantArray::get(String); + llvm::Constant *StringGV = + new llvm::GlobalVariable(StringC->getType(), true, + llvm::GlobalValue::InternalLinkage, + StringC, ".str", &CGM.getModule()); + llvm::Constant *Values[4] = { + ObjCTypes.getCFConstantStringClassReference(), + llvm::ConstantInt::get(llvm::Type::Int32Ty, flags), + getConstantGEP(StringGV, 0, 0), // Decay array -> ptr + llvm::ConstantInt::get(ObjCTypes.LongTy, String.size()) + }; + + llvm::Constant *CFStringC = + llvm::ConstantStruct::get(ObjCTypes.getCFStringType(), + std::vector<llvm::Constant*>(Values, Values+4)); + + llvm::GlobalVariable *CFStringGV = + new llvm::GlobalVariable(CFStringC->getType(), true, + llvm::GlobalValue::InternalLinkage, + CFStringC, "", + &CGM.getModule()); + + CFStringGV->setSection("__DATA, __cfstring"); + + return CFStringGV; } /// Generates a message send where the super is the receiver. This is @@ -249,8 +337,6 @@ void CGObjCMac::EmitImageInfo() { if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly) flags |= eImageInfo_GCOnly; - fprintf(stderr, "flags: %d (%d)\n", flags, CGM.getLangOptions().getGCMode()); - // Emitted as int[2]; llvm::Constant *values[2] = { llvm::ConstantInt::get(llvm::Type::Int32Ty, version), @@ -264,7 +350,11 @@ void CGObjCMac::EmitImageInfo() { "\01L_OBJC_IMAGE_INFO", &CGM.getModule()); - GV->setSection("__OBJC, __image_info,regular"); + if (ObjCABI == 1) { + GV->setSection("__OBJC, __image_info,regular"); + } else { + GV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip"); + } UsedGlobals.push_back(GV); } @@ -291,6 +381,50 @@ void CGObjCMac::FinishModule() { /* *** */ +ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) + : CGM(cgm), + CFStringType(0), + CFConstantStringClassReference(0), + LongTy(CGM.getTypes().ConvertType(CGM.getContext().LongTy)) +{ +} + +ObjCTypesHelper::~ObjCTypesHelper() { +} + +const llvm::StructType *ObjCTypesHelper::getCFStringType() { + if (!CFStringType) { + CFStringType = + llvm::StructType::get(llvm::PointerType::getUnqual(llvm::Type::Int32Ty), + llvm::Type::Int32Ty, + llvm::PointerType::getUnqual(llvm::Type::Int8Ty), + LongTy, + NULL); + + CGM.getModule().addTypeName("struct.__builtin_CFString", CFStringType); + } + + return CFStringType; +} + +llvm::Constant *ObjCTypesHelper::getCFConstantStringClassReference() { + if (!CFConstantStringClassReference) { + llvm::GlobalValue *GV = + new llvm::GlobalVariable(llvm::ArrayType::get(llvm::Type::Int32Ty, 0), + false, + llvm::GlobalValue::ExternalLinkage, + 0, "__CFConstantStringClassReference", + &CGM.getModule()); + + // Decay to pointer. + CFConstantStringClassReference = getConstantGEP(GV, 0, 0); + } + + return CFConstantStringClassReference; +} + +/* *** */ + CodeGen::CGObjCRuntime *CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM){ return new CGObjCMac(CGM); } |