diff options
| author | David Chisnall <csdavec@swan.ac.uk> | 2012-01-03 23:18:17 +0000 |
|---|---|---|
| committer | David Chisnall <csdavec@swan.ac.uk> | 2012-01-03 23:18:17 +0000 |
| commit | 31640e1606ada8337e1465af8cd4847e6ca6d534 (patch) | |
| tree | 40afbcff0565c55e4232089298c1282fd76fa1b6 /clang/lib | |
| parent | 3e417e7a5cd87161016629f9bb089f4a419a5295 (diff) | |
| download | bcm5719-llvm-31640e1606ada8337e1465af8cd4847e6ca6d534.tar.gz bcm5719-llvm-31640e1606ada8337e1465af8cd4847e6ca6d534.zip | |
Initialise constant Objective-C string isa pointers with a weak reference to the class, so that they are usable in +load methods if the string class has been compiled with clang - if it's been compiled with GCC, the ABI makes this impossible. (GNU runtimes)
llvm-svn: 147493
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/CodeGen/CGObjCGNU.cpp | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 3a591e88ddb..49323c58b10 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -970,12 +970,27 @@ llvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) { if (old != ObjCStrings.end()) return old->getValue(); + StringRef StringClass = CGM.getLangOptions().ObjCConstantStringClass; + + if (StringClass.empty()) StringClass = "NXConstantString"; + + std::string Sym = "_OBJC_CLASS_"; + Sym += StringClass; + + llvm::Constant *isa = TheModule.getNamedGlobal(Sym); + + if (!isa) + isa = new llvm::GlobalVariable(TheModule, IdTy, /* isConstant */false, + llvm::GlobalValue::ExternalWeakLinkage, 0, Sym); + else if (isa->getType() != PtrToIdTy) + isa = llvm::ConstantExpr::getBitCast(isa, PtrToIdTy); + std::vector<llvm::Constant*> Ivars; - Ivars.push_back(NULLPtr); + Ivars.push_back(isa); Ivars.push_back(MakeConstantString(Str)); Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size())); llvm::Constant *ObjCStr = MakeGlobal( - llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL), + llvm::StructType::get(PtrToIdTy, PtrToInt8Ty, IntTy, NULL), Ivars, ".objc_str"); ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty); ObjCStrings[Str] = ObjCStr; @@ -1368,7 +1383,7 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( // anyway; the classes will still work with the GNU runtime, they will just // be ignored. llvm::StructType *ClassTy = llvm::StructType::get( - PtrToInt8Ty, // class_pointer + PtrToInt8Ty, // isa PtrToInt8Ty, // super_class PtrToInt8Ty, // name LongTy, // version @@ -1419,9 +1434,20 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( Elements.push_back(WeakIvarBitmap); // Create an instance of the structure // This is now an externally visible symbol, so that we can speed up class - // messages in the next ABI. - return MakeGlobal(ClassTy, Elements, (isMeta ? "_OBJC_METACLASS_": - "_OBJC_CLASS_") + std::string(Name), llvm::GlobalValue::ExternalLinkage); + // messages in the next ABI. We may already have some weak references to + // this, so check and fix them properly. + std::string ClassSym((isMeta ? "_OBJC_METACLASS_": "_OBJC_CLASS_") + + std::string(Name)); + llvm::GlobalVariable *ClassRef = TheModule.getNamedGlobal(ClassSym); + llvm::Constant *Class = MakeGlobal(ClassTy, Elements, ClassSym, + llvm::GlobalValue::ExternalLinkage); + if (ClassRef) { + ClassRef->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(Class, + ClassRef->getType())); + ClassRef->removeFromParent(); + Class->setName(ClassSym); + } + return Class; } llvm::Constant *CGObjCGNU::GenerateProtocolMethodList( |

