[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