[cfe-commits] r80591 - in /cfe/trunk: include/clang/Basic/LangOptions.h include/clang/Driver/Options.def lib/CodeGen/CGObjCGNU.cpp lib/Driver/Tools.cpp lib/Lex/PPMacroExpansion.cpp test/CodeGenObjC/constant-strings.m tools/clang-cc/clang-cc.cpp

David Chisnall csdavec at swan.ac.uk
Mon Aug 31 09:41:57 PDT 2009


Author: theraven
Date: Mon Aug 31 11:41:57 2009
New Revision: 80591

URL: http://llvm.org/viewvc/llvm-project?rev=80591&view=rev
Log:
Updated GNU runtime non-fragile ABI.
Added -fconstant-string-class= option.
Added __has_feature() test for non-fragile ABI.


Modified:
    cfe/trunk/include/clang/Basic/LangOptions.h
    cfe/trunk/include/clang/Driver/Options.def
    cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/lib/Lex/PPMacroExpansion.cpp
    cfe/trunk/test/CodeGenObjC/constant-strings.m
    cfe/trunk/tools/clang-cc/clang-cc.cpp

Modified: cfe/trunk/include/clang/Basic/LangOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.h?rev=80591&r1=80590&r2=80591&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.h (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.h Mon Aug 31 11:41:57 2009
@@ -107,6 +107,8 @@
 public:  
   unsigned InstantiationDepth;    // Maximum template instantiation depth.
 
+  const char *ObjCConstantStringClass;
+
   enum GCMode { NonGC, GCOnly, HybridGC };
   enum StackProtectorMode { SSPOff, SSPOn, SSPReq };
   enum VisibilityMode { 
@@ -120,6 +122,7 @@
     GNUMode = ImplicitInt = Digraphs = 0;
     HexFloats = 0;
     GC = ObjC1 = ObjC2 = ObjCNonFragileABI = 0;
+    ObjCConstantStringClass = 0;
     C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0;
     CXXOperatorNames = PascalStrings = WritableStrings = 0;
     Exceptions = NeXTRuntime = Freestanding = NoBuiltin = 0;
@@ -127,7 +130,7 @@
     LaxVectorConversions = 1;
     HeinousExtensions = 0;
     AltiVec = OpenCL = StackProtector = 0;
-    
+
     SymbolVisibility = (unsigned) Default;
     
     // FIXME: The default should be 1.

Modified: cfe/trunk/include/clang/Driver/Options.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.def?rev=80591&r1=80590&r2=80591&view=diff

==============================================================================
--- cfe/trunk/include/clang/Driver/Options.def (original)
+++ cfe/trunk/include/clang/Driver/Options.def Mon Aug 31 11:41:57 2009
@@ -373,6 +373,7 @@
 OPTION("-fcommon", fcommon, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fcompile-resource=", fcompile_resource_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fconstant-cfstrings", fconstant_cfstrings, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fconstant-string-class=", fconstant_string_class_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fcreate-profile", fcreate_profile, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fdebug-pass-arguments", fdebug_pass_arguments, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fdebug-pass-structure", fdebug_pass_structure, Flag, f_Group, INVALID, "", 0, 0, 0)

Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=80591&r1=80590&r2=80591&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Mon Aug 31 11:41:57 2009
@@ -292,10 +292,7 @@
 
 llvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str,
                                               const std::string &Name) {
-  llvm::Constant * ConstStr = llvm::ConstantArray::get(VMContext, Str);
-  ConstStr = new llvm::GlobalVariable(TheModule, ConstStr->getType(), true, 
-                                      llvm::GlobalValue::InternalLinkage,
-                                      ConstStr, Name);
+  llvm::Constant *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
   return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2);
 }
 
@@ -512,11 +509,9 @@
       TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
                                                 MethodSels[i].getAsString(),
                                                 isClassMethodList))) {
-      llvm::Constant *C = 
-        CGM.GetAddrOfConstantCString(MethodSels[i].getAsString());
-      Elements.push_back(llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2));
-      Elements.push_back(
-            llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2));
+      llvm::Constant *C = MakeConstantString(MethodSels[i].getAsString());
+      Elements.push_back(C);
+      Elements.push_back(MethodTypes[i]);
       Method = llvm::ConstantExpr::getBitCast(Method,
           llvm::PointerType::getUnqual(IMPTy));
       Elements.push_back(Method);
@@ -570,10 +565,8 @@
   std::vector<llvm::Constant*> Elements;
   for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
     Elements.clear();
-    Elements.push_back( llvm::ConstantExpr::getGetElementPtr(IvarNames[i],
-          Zeros, 2));
-    Elements.push_back( llvm::ConstantExpr::getGetElementPtr(IvarTypes[i],
-          Zeros, 2));
+    Elements.push_back(IvarNames[i]);
+    Elements.push_back(IvarTypes[i]);
     Elements.push_back(IvarOffsets[i]);
     Ivars.push_back(llvm::ConstantStruct::get(ObjCIvarTy, Elements));
   }
@@ -659,10 +652,8 @@
   std::vector<llvm::Constant*> Elements;
   for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) {
     Elements.clear();
-    Elements.push_back(llvm::ConstantExpr::getGetElementPtr(MethodNames[i],
-          Zeros, 2)); 
-    Elements.push_back(
-          llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2));
+    Elements.push_back(MethodNames[i]); 
+    Elements.push_back(MethodTypes[i]);
     Methods.push_back(llvm::ConstantStruct::get(ObjCMethodDescTy, Elements));
   }
   llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy,
@@ -758,8 +749,8 @@
     std::string TypeStr;
     Context.getObjCEncodingForMethodDecl(*iter, TypeStr);
     InstanceMethodNames.push_back(
-        CGM.GetAddrOfConstantCString((*iter)->getSelector().getAsString()));
-    InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
+        MakeConstantString((*iter)->getSelector().getAsString()));
+    InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
   }
   // Collect information about class methods:
   llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames;
@@ -770,8 +761,8 @@
     std::string TypeStr;
     Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
     ClassMethodNames.push_back(
-        CGM.GetAddrOfConstantCString((*iter)->getSelector().getAsString()));
-    ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
+        MakeConstantString((*iter)->getSelector().getAsString()));
+    ClassMethodTypes.push_back(MakeConstantString(TypeStr));
   }
 
   llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
@@ -813,7 +804,7 @@
     InstanceMethodSels.push_back((*iter)->getSelector());
     std::string TypeStr;
     CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
-    InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
+    InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
   }
 
   // Collect information about class methods
@@ -825,7 +816,7 @@
     ClassMethodSels.push_back((*iter)->getSelector());
     std::string TypeStr;
     CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
-    ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
+    ClassMethodTypes.push_back(MakeConstantString(TypeStr));
   }
 
   // Collect the names of referenced protocols
@@ -901,18 +892,16 @@
   for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(),
       endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) {
       // Store the name
-      IvarNames.push_back(CGM.GetAddrOfConstantCString((*iter)
-                                                         ->getNameAsString()));
+      IvarNames.push_back(MakeConstantString((*iter)->getNameAsString()));
       // Get the type encoding for this ivar
       std::string TypeStr;
       Context.getObjCEncodingForType((*iter)->getType(), TypeStr);
-      IvarTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
+      IvarTypes.push_back(MakeConstantString(TypeStr));
       // Get the offset
       uint64_t Offset;
       if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
-		Offset = ComputeIvarBaseOffset(CGM, ClassDecl, *iter) -
-			superInstanceSize;
-        ObjCIvarOffsetVariable(ClassDecl, *iter);
+        Offset = ComputeIvarBaseOffset(CGM, ClassDecl, *iter) -
+            superInstanceSize;
       } else {
         Offset = ComputeIvarBaseOffset(CGM, ClassDecl, *iter);
       }
@@ -929,7 +918,7 @@
     InstanceMethodSels.push_back((*iter)->getSelector());
     std::string TypeStr;
     Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
-    InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
+    InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
   }
   for (ObjCImplDecl::propimpl_iterator 
          iter = OID->propimpl_begin(), endIter = OID->propimpl_end();
@@ -939,13 +928,13 @@
       InstanceMethodSels.push_back(getter->getSelector());
       std::string TypeStr;
       Context.getObjCEncodingForMethodDecl(getter,TypeStr);
-      InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
+      InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
     }
     if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
       InstanceMethodSels.push_back(setter->getSelector());
       std::string TypeStr;
       Context.getObjCEncodingForMethodDecl(setter,TypeStr);
-      InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
+      InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
     }
   }
 
@@ -958,7 +947,7 @@
     ClassMethodSels.push_back((*iter)->getSelector());
     std::string TypeStr;
     Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
-    ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
+    ClassMethodTypes.push_back(MakeConstantString(TypeStr));
   }
   // Collect the names of referenced protocols
   llvm::SmallVector<std::string, 16> Protocols;
@@ -985,6 +974,43 @@
       ClassMethodSels, ClassMethodTypes, true);
   llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
       IvarOffsets);
+  // Irrespective of whether we are compiling for a fragile or non-fragile ABI, 
+  // we emit a symbol containing the offset for each ivar in the class.  This
+  // allows code compiled for the non-Fragile ABI to inherit from code compiled
+  // for the legacy ABI, without causing problems.  The converse is also
+  // possible, but causes all ivar accesses to be fragile.
+  int i = 0;
+  // Offset pointer for getting at the correct field in the ivar list when
+  // setting up the alias.  These are: The base address for the global, the
+  // ivar array (second field), the ivar in this list (set for each ivar), and
+  // the offset (third field in ivar structure)
+  const llvm::Type *IndexTy = llvm::Type::getInt32Ty(VMContext);
+  llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
+      llvm::ConstantInt::get(IndexTy, 1), 0, 
+      llvm::ConstantInt::get(IndexTy, 2) };
+
+  for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(),
+      endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) {
+      const std::string Name = "__objc_ivar_offset_" + ClassName + '.'
+          +(*iter)->getNameAsString();
+      offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, i++);
+      // Get the correct ivar field
+      llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
+              IvarList, offsetPointerIndexes, 4);
+      // Get the existing alias, if one exists.
+      llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name);
+      if (offset) {
+          offset->setInitializer(offsetValue);
+          // If this is the real definition, change its linkage type so that
+          // different modules will use this one, rather than their private
+          // copy.
+          offset->setLinkage(llvm::GlobalValue::ExternalLinkage);
+      } else {
+          // Add a new alias if there isn't one already.
+          offset = new llvm::GlobalVariable(TheModule, offsetValue->getType(),
+                  false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name);
+      }
+  }
   //Generate metaclass for class methods
   llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
       NULLPtr, 0x2L, /*name*/"", 0, Zeros[0], GenerateIvarList(
@@ -1045,8 +1071,11 @@
     llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
         ConstantStrings.size() + 1);
     ConstantStrings.push_back(NULLPtr);
-    Elements.push_back(MakeConstantString("NSConstantString",
-          ".objc_static_class_name"));
+
+    const char *StringClass = CGM.getLangOptions().ObjCConstantStringClass;
+    if (!StringClass) StringClass = "NXConstantString";
+    Elements.push_back(MakeConstantString(StringClass,
+                ".objc_static_class_name"));
     Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy,
        ConstantStrings));
     llvm::StructType *StaticsListTy = 
@@ -1581,15 +1610,29 @@
   // Emit the variable and initialize it with what we think the correct value
   // is.  This allows code compiled with non-fragile ivars to work correctly
   // when linked against code which isn't (most of the time).
-  llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
-  if (!IvarOffsetGV) {
+  llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
+  if (!IvarOffsetPointer) {
     uint64_t Offset = ComputeIvarBaseOffset(CGM, ID, Ivar);
     llvm::ConstantInt *OffsetGuess =
       llvm::ConstantInt::get(LongTy, Offset, "ivar");
-    IvarOffsetGV = new llvm::GlobalVariable(TheModule, LongTy, false,
-        llvm::GlobalValue::WeakAnyLinkage, OffsetGuess, Name);
+    // Don't emit the guess in non-PIC code because the linker will not be able
+    // to replace it with the real version for a library.  In non-PIC code you
+    // must compile with the fragile ABI if you want to use ivars from a
+    // GCC-compiled class.  
+    if (CGM.getLangOptions().PICLevel) {
+      llvm::GlobalVariable *IvarOffsetGV = new llvm::GlobalVariable(TheModule,
+            llvm::Type::getInt32Ty(VMContext), false,
+            llvm::GlobalValue::PrivateLinkage, OffsetGuess, Name+".guess");
+      IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
+            IvarOffsetGV->getType(), false, llvm::GlobalValue::LinkOnceAnyLinkage,
+            IvarOffsetGV, Name);
+    } else {
+      IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
+              llvm::PointerType::getUnqual(llvm::Type::getInt32Ty(VMContext)),
+              false, llvm::GlobalValue::ExternalLinkage, 0, Name);
+    }
   }
-  return IvarOffsetGV;
+  return IvarOffsetPointer;
 }
 
 LValue CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
@@ -1622,10 +1665,10 @@
 llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
                          const ObjCInterfaceDecl *Interface,
                          const ObjCIvarDecl *Ivar) {
-  if (CGF.getContext().getLangOptions().ObjCNonFragileABI) {
+  if (CGM.getLangOptions().ObjCNonFragileABI) {
     Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar);
-    return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),
-                                  false, "ivar");
+    return CGF.Builder.CreateLoad(CGF.Builder.CreateLoad(
+                ObjCIvarOffsetVariable(Interface, Ivar), false, "ivar"));
   }
   uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar);
   return llvm::ConstantInt::get(LongTy, Offset, "ivar");

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=80591&r1=80590&r2=80591&view=diff

==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Mon Aug 31 11:41:57 2009
@@ -484,6 +484,11 @@
   if (Args.hasArg(options::OPT__relocatable_pch, true))
     CmdArgs.push_back("--relocatable-pch");
                       
+   if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
+     CmdArgs.push_back("-fconstant-string-class");
+     CmdArgs.push_back(A->getValue(Args));
+   }
+
   // Forward -f options which we can pass directly.
   Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
   Args.AddLastArg(CmdArgs, options::OPT_ffreestanding);

Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=80591&r1=80590&r2=80591&view=diff

==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Mon Aug 31 11:41:57 2009
@@ -484,6 +484,9 @@
   case 6:
     if (II->isStr("blocks")) return LangOpts.Blocks;
     return false;
+  case 19:
+    if (II->isStr("objc_nonfragile_abi")) return LangOpts.ObjCNonFragileABI;
+    return false;
   case 22:
     if (II->isStr("attribute_overloadable")) return true;
     return false;

Modified: cfe/trunk/test/CodeGenObjC/constant-strings.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/constant-strings.m?rev=80591&r1=80590&r2=80591&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenObjC/constant-strings.m (original)
+++ cfe/trunk/test/CodeGenObjC/constant-strings.m Mon Aug 31 11:41:57 2009
@@ -1,4 +1,6 @@
-// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s
+// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s &&
+// RUN: clang-cc -fgnu-runtime -emit-llvm -o %t %s && grep NXConstantString %t | count 1 &&
+// RUN: clang-cc -fgnu-runtime -fconstant-string-class=NSConstantString -emit-llvm -o %t %s && grep NSConstantString %t | count 1
 
 id a = @"Hello World!";
 

Modified: cfe/trunk/tools/clang-cc/clang-cc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/clang-cc.cpp?rev=80591&r1=80590&r2=80591&view=diff

==============================================================================
--- cfe/trunk/tools/clang-cc/clang-cc.cpp (original)
+++ cfe/trunk/tools/clang-cc/clang-cc.cpp Mon Aug 31 11:41:57 2009
@@ -361,6 +361,12 @@
                 llvm::cl::desc("Use GC exclusively for Objective-C related "
                                "memory management"));
 
+static llvm::cl::opt<std::string>
+ObjCConstantStringClass("fconstant-string-class",
+                llvm::cl::value_desc("class name"),
+                llvm::cl::desc("Specify the class to use for constant "
+                               "Objective-C string objects."));
+
 static llvm::cl::opt<bool>
 ObjCEnableGC("fobjc-gc",
              llvm::cl::desc("Enable Objective-C garbage collection"));
@@ -818,6 +824,9 @@
   else if (GNURuntime)
     Options.NeXTRuntime = 0;
 
+  if (!ObjCConstantStringClass.empty())
+    Options.ObjCConstantStringClass = ObjCConstantStringClass.c_str();
+
   if (ObjCNonFragileABI)
     Options.ObjCNonFragileABI = 1;
 





More information about the cfe-commits mailing list