[cfe-commits] r73364 - /cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
Fariborz Jahanian
fjahanian at apple.com
Mon Jun 15 08:07:21 PDT 2009
A test case would be nice.
- Fariborz
On Jun 14, 2009, at 6:09 PM, Chris Lattner wrote:
> Author: lattner
> Date: Sun Jun 14 20:09:11 2009
> New Revision: 73364
>
> URL: http://llvm.org/viewvc/llvm-project?rev=73364&view=rev
> Log:
> "GCC emits an __objc_class_name_{classname} symbol for every class,
> and a corresponding reference to this symbol for every compilation
> unit that references the class. This causes linker errors when you
> try linking a program which references some classes but doesn't
> define them. The attached patch implements this support in clang,
> so you can compile a class with clang, reference it in a file
> compiled with GCC, and have it all work correctly."
>
> Patch by David Chisnall!
>
>
> Modified:
> cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
>
> Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=73364&r1=73363&r2=73364&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Sun Jun 14 20:09:11 2009
> @@ -104,6 +104,7 @@
> std::vector<llvm::Constant*> &V, const std::string &Name="");
> llvm::GlobalVariable *ObjCIvarOffsetVariable(const
> ObjCInterfaceDecl *ID,
> const ObjCIvarDecl *Ivar);
> + void EmitClassRef(const std::string &className);
> public:
> CGObjCGNU(CodeGen::CodeGenModule &cgm);
> virtual llvm::Constant *GenerateConstantString(const
> ObjCStringLiteral *);
> @@ -168,15 +169,31 @@
> } // end anonymous namespace
>
>
> +/// Emits a reference to a dummy variable which is emitted with
> each class.
> +/// This ensures that a linker error will be generated when trying
> to link
> +/// together modules where a referenced class is not defined.
> +void CGObjCGNU::EmitClassRef(const std::string &className){
> + std::string symbolRef = "__objc_class_ref_" + className;
> + // Don't emit two copies of the same symbol
> + if (TheModule.getGlobalVariable(symbolRef)) return;
> + std::string symbolName = "__objc_class_name_" + className;
> + llvm::GlobalVariable *ClassSymbol =
> TheModule.getGlobalVariable(symbolName);
> + if (!ClassSymbol) {
> + ClassSymbol = new llvm::GlobalVariable(LongTy, false,
> + llvm::GlobalValue::ExternalLinkage, 0, symbolName,
> &TheModule);
> + }
> + new llvm::GlobalVariable(ClassSymbol->getType(), true,
> + llvm::GlobalValue::CommonLinkage, ClassSymbol, symbolRef,
> &TheModule);
> +}
>
> static std::string SymbolNameForClass(const std::string &ClassName) {
> - return "___objc_class_name_" + ClassName;
> + return "_OBJC_CLASS_" + ClassName;
> }
>
> static std::string SymbolNameForMethod(const std::string &ClassName,
> const
> std::string &CategoryName, const std::string &MethodName, bool
> isClassMethod)
> {
> - return "._objc_method_" + ClassName +"("+CategoryName+")"+
> + return "_OBJC_METHOD_" + ClassName + "("+CategoryName+")"+
> (isClassMethod ? "+" : "-") + MethodName;
> }
>
> @@ -217,6 +234,7 @@
> llvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder,
> const ObjCInterfaceDecl *OID) {
> llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID-
> >getNameAsString());
> + EmitClassRef(OID->getNameAsString());
> ClassName = Builder.CreateStructGEP(ClassName, 0);
>
> std::vector<const llvm::Type*> Params(1, PtrToInt8Ty);
> @@ -831,14 +849,21 @@
> const ObjCInterfaceDecl * SuperClassDecl =
> OID->getClassInterface()->getSuperClass();
> std::string SuperClassName;
> - if (SuperClassDecl)
> + if (SuperClassDecl) {
> SuperClassName = SuperClassDecl->getNameAsString();
> + EmitClassRef(SuperClassName);
> + }
>
> // Get the class name
> ObjCInterfaceDecl *ClassDecl =
> const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
> std::string ClassName = ClassDecl->getNameAsString();
> -
> + // Emit the symbol that is used to generate linker errors if this
> class is
> + // referenced in other modules but not declared.
> + new llvm::GlobalVariable(LongTy, false,
> llvm::GlobalValue::ExternalLinkage,
> + llvm::ConstantInt::get(LongTy, 0), "__objc_class_name_" +
> ClassName,
> + &TheModule);
> +
> // Get the size of instances.
> int instanceSize =
> Context.getASTObjCImplementationLayout(OID).getSize() / 8;
>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list