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)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147493 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Chisnall 2012-01-03 23:18:17 +00:00
Родитель 341b8be2b8
Коммит 78c6fcf819
1 изменённых файлов: 32 добавлений и 6 удалений

Просмотреть файл

@ -970,12 +970,27 @@ llvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) {
if (old != ObjCStrings.end()) if (old != ObjCStrings.end())
return old->getValue(); 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; std::vector<llvm::Constant*> Ivars;
Ivars.push_back(NULLPtr); Ivars.push_back(isa);
Ivars.push_back(MakeConstantString(Str)); Ivars.push_back(MakeConstantString(Str));
Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size())); Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
llvm::Constant *ObjCStr = MakeGlobal( llvm::Constant *ObjCStr = MakeGlobal(
llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL), llvm::StructType::get(PtrToIdTy, PtrToInt8Ty, IntTy, NULL),
Ivars, ".objc_str"); Ivars, ".objc_str");
ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty); ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty);
ObjCStrings[Str] = ObjCStr; ObjCStrings[Str] = ObjCStr;
@ -1368,7 +1383,7 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure(
// anyway; the classes will still work with the GNU runtime, they will just // anyway; the classes will still work with the GNU runtime, they will just
// be ignored. // be ignored.
llvm::StructType *ClassTy = llvm::StructType::get( llvm::StructType *ClassTy = llvm::StructType::get(
PtrToInt8Ty, // class_pointer PtrToInt8Ty, // isa
PtrToInt8Ty, // super_class PtrToInt8Ty, // super_class
PtrToInt8Ty, // name PtrToInt8Ty, // name
LongTy, // version LongTy, // version
@ -1419,9 +1434,20 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure(
Elements.push_back(WeakIvarBitmap); Elements.push_back(WeakIvarBitmap);
// Create an instance of the structure // Create an instance of the structure
// This is now an externally visible symbol, so that we can speed up class // This is now an externally visible symbol, so that we can speed up class
// messages in the next ABI. // messages in the next ABI. We may already have some weak references to
return MakeGlobal(ClassTy, Elements, (isMeta ? "_OBJC_METACLASS_": // this, so check and fix them properly.
"_OBJC_CLASS_") + std::string(Name), llvm::GlobalValue::ExternalLinkage); 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( llvm::Constant *CGObjCGNU::GenerateProtocolMethodList(