slavapestov created this revision.
slavapestov added a reviewer: cfe-commits.
slavapestov set the repository for this revision to rL LLVM.

This patch fixes an issue that can come up when Swift and Clang are emitting 
declarations into the same LLVM module.

Objective-C class literals result in the emission of a global variable named 
OBJC_CLASS_$_<ClassName>. Clang and Swift emit this variable with different 
types, resulting in an LLVM assertion firing. This patch changes Clang to be 
more resilient in the case where the global has already been emitted, wrapping 
it in a cast constexpr instead of crashing.

Repository:
  rL LLVM

http://reviews.llvm.org/D13954

Files:
  lib/CodeGen/CGObjCGNU.cpp
  lib/CodeGen/CGObjCMac.cpp
  lib/CodeGen/CGObjCRuntime.h
  lib/CodeGen/CodeGenModule.cpp

Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -2739,7 +2739,9 @@
       std::string str = 
         StringClass.empty() ? "OBJC_CLASS_$_NSConstantString" 
                             : "OBJC_CLASS_$_" + StringClass;
-      GV = getObjCRuntime().GetClassGlobal(str);
+      GV = getObjCRuntime().GetClassGlobal(str,
+                                           /*ForDefinition=*/false,
+                                           /*Weak=*/false);
       // Make sure the result is of the correct type.
       llvm::Type *PTy = llvm::PointerType::getUnqual(Ty);
       V = llvm::ConstantExpr::getBitCast(GV, PTy);
Index: lib/CodeGen/CGObjCRuntime.h
===================================================================
--- lib/CodeGen/CGObjCRuntime.h
+++ lib/CodeGen/CGObjCRuntime.h
@@ -268,8 +268,9 @@
                                   const CodeGen::CGBlockInfo &blockInfo) = 0;
   virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
                                            QualType T) = 0;
-  virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name,
-                                               bool Weak = false) = 0;
+  virtual llvm::Constant *GetClassGlobal(const std::string &Name,
+                                         bool ForDefinition,
+                                         bool Weak) = 0;
 
   struct MessageSendInfo {
     const CGFunctionInfo &CallInfo;
Index: lib/CodeGen/CGObjCMac.cpp
===================================================================
--- lib/CodeGen/CGObjCMac.cpp
+++ lib/CodeGen/CGObjCMac.cpp
@@ -1260,8 +1260,9 @@
 
   /// GetClassGlobal - Return the global variable for the Objective-C
   /// class of the given name.
-  llvm::GlobalVariable *GetClassGlobal(const std::string &Name,
-                                       bool Weak = false) override {
+  llvm::Constant *GetClassGlobal(const std::string &Name,
+                                 bool ForDefinition,
+                                 bool Weak) override {
     llvm_unreachable("CGObjCMac::GetClassGlobal");
   }
 };
@@ -1362,8 +1363,9 @@
   
   /// GetClassGlobal - Return the global variable for the Objective-C
   /// class of the given name.
-  llvm::GlobalVariable *GetClassGlobal(const std::string &Name,
-                                       bool Weak = false) override;
+  llvm::Constant *GetClassGlobal(const std::string &Name,
+                                 bool ForDefinition,
+                                 bool Weak) override;
 
   /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
   /// for the given class reference.
@@ -5686,7 +5688,12 @@
                   llvm::PointerType::getUnqual(ObjCTypes.ImpnfABITy));
   llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
                                                    Values);
-  llvm::GlobalVariable *GV = GetClassGlobal(ClassName, Weak);
+  llvm::GlobalVariable *GV = cast<llvm::GlobalVariable>(
+                               GetClassGlobal(ClassName,
+                                              /*ForDefinition=*/true,
+                                              Weak));
+  if (Init->getType() != GV->getValueType())
+    Init = llvm::ConstantExpr::getBitCast(Init, GV->getValueType());
   GV->setInitializer(Init);
   GV->setSection("__DATA, __objc_data");
   GV->setAlignment(
@@ -5755,7 +5762,7 @@
   llvm::SmallString<64> ObjCClassName(getClassSymbolPrefix());
   llvm::SmallString<64> TClassName;
 
-  llvm::GlobalVariable *SuperClassGV, *IsAGV;
+  llvm::Constant *SuperClassGV, *IsAGV;
 
   // Build the flags for the metaclass.
   bool classIsHidden =
@@ -5777,10 +5784,12 @@
     TClassName = ObjCClassName;
     TClassName += ClassName;
     SuperClassGV = GetClassGlobal(TClassName.str(),
+                                  /*ForDefinition=*/false,
                                   ID->getClassInterface()->isWeakImported());
     TClassName = ObjCMetaClassName;
     TClassName += ClassName;
     IsAGV = GetClassGlobal(TClassName.str(),
+                           /*ForDefinition=*/false,
                            ID->getClassInterface()->isWeakImported());
   } else {
     // Has a root. Current class is not a root.
@@ -5790,13 +5799,15 @@
     TClassName = ObjCMetaClassName ;
     TClassName += Root->getObjCRuntimeNameAsString();
     IsAGV = GetClassGlobal(TClassName.str(),
+                           /*ForDefinition=*/false,
                            Root->isWeakImported());
 
     // work on super class metadata symbol.
     TClassName = ObjCMetaClassName;
     TClassName += ID->getClassInterface()->getSuperClass()->getObjCRuntimeNameAsString();
     SuperClassGV = GetClassGlobal(
                                   TClassName.str(),
+                                  /*ForDefinition=*/false,
                                   ID->getClassInterface()->getSuperClass()->isWeakImported());
   }
   llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
@@ -5839,6 +5850,7 @@
     TClassName += ID->getClassInterface()->getSuperClass()->getObjCRuntimeNameAsString();
     SuperClassGV = GetClassGlobal(
                                   TClassName.str(),
+                                  /*ForDefinition=*/false,
                                   ID->getClassInterface()->getSuperClass()->isWeakImported());
   }
   GetClassSizeInfo(ID, InstanceStart, InstanceSize);
@@ -5928,8 +5940,9 @@
   llvm::Constant *Values[6];
   Values[0] = GetClassName(OCD->getIdentifier()->getName());
   // meta-class entry symbol
-  llvm::GlobalVariable *ClassGV =
-      GetClassGlobal(ExtClassName.str(), Interface->isWeakImported());
+  llvm::Constant *ClassGV = GetClassGlobal(ExtClassName.str(),
+                                           /*ForDefinition=*/false,
+                                           Interface->isWeakImported());
 
   Values[1] = ClassGV;
   std::vector<llvm::Constant*> Methods;
@@ -6598,8 +6611,10 @@
                       false, CallArgs, Method, ObjCTypes);
 }
 
-llvm::GlobalVariable *
-CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name, bool Weak) {
+llvm::Constant *
+CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name,
+                                       bool ForDefinition,
+                                       bool Weak) {
   llvm::GlobalValue::LinkageTypes L =
       Weak ? llvm::GlobalValue::ExternalWeakLinkage
            : llvm::GlobalValue::ExternalLinkage;
@@ -6611,7 +6626,12 @@
                                   false, L, nullptr, Name);
 
   assert(GV->getLinkage() == L);
-  return GV;
+
+  if (ForDefinition ||
+      GV->getValueType() == ObjCTypes.ClassnfABITy)
+    return GV;
+
+  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ClassnfABIPtrTy);
 }
 
 llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
@@ -6624,7 +6644,9 @@
     std::string ClassName(
       getClassSymbolPrefix() +
       (ID ? ID->getObjCRuntimeNameAsString() : II->getName()).str());
-    llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName, Weak);
+    llvm::Constant *ClassGV = GetClassGlobal(ClassName,
+                                             /*ForDefinition=*/false,
+                                             Weak);
     Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
                                      false, llvm::GlobalValue::PrivateLinkage,
                                      ClassGV, "OBJC_CLASSLIST_REFERENCES_$_");
@@ -6656,8 +6678,9 @@
   if (!Entry) {
     llvm::SmallString<64> ClassName(getClassSymbolPrefix());
     ClassName += ID->getObjCRuntimeNameAsString();
-    llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName.str(),
-                                                   ID->isWeakImported());
+    llvm::Constant *ClassGV = GetClassGlobal(ClassName.str(),
+                                             /*ForDefinition=*/false,
+                                             ID->isWeakImported());
     Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
                                      false, llvm::GlobalValue::PrivateLinkage,
                                      ClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
@@ -6680,8 +6703,9 @@
   if (!Entry) {
     llvm::SmallString<64> MetaClassName(getMetaclassSymbolPrefix());
     MetaClassName += ID->getObjCRuntimeNameAsString();
-    llvm::GlobalVariable *MetaClassGV =
-      GetClassGlobal(MetaClassName.str(), Weak);
+    llvm::Constant *MetaClassGV = GetClassGlobal(MetaClassName.str(),
+                                                 /*ForDefinition=*/false,
+                                                 Weak);
 
     Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
                                      false, llvm::GlobalValue::PrivateLinkage,
@@ -6703,7 +6727,10 @@
   if (ID->isWeakImported()) {
     llvm::SmallString<64> ClassName(getClassSymbolPrefix());
     ClassName += ID->getObjCRuntimeNameAsString();
-    llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName.str(), true);
+    llvm::GlobalVariable *ClassGV = cast<llvm::GlobalVariable>(
+                                      GetClassGlobal(ClassName.str(),
+                                                     /*ForDefinition=*/true,
+                                                     /*Weak=*/true));
     (void)ClassGV;
     assert(ClassGV->hasExternalWeakLinkage());
   }
@@ -6998,11 +7025,15 @@
 
   llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
 
+  llvm::Constant *ClassGV = GetClassGlobal(ClassName.str(),
+                                           /*ForDefinition=*/false,
+                                           /*Weak=*/false);
+
   llvm::Constant *Values[] = {
       llvm::ConstantExpr::getGetElementPtr(VTableGV->getValueType(), VTableGV,
                                            VTableIdx),
       GetClassName(ID->getObjCRuntimeNameAsString()),
-      GetClassGlobal(ClassName.str())};
+      ClassGV};
   llvm::Constant *Init =
     llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
 
Index: lib/CodeGen/CGObjCGNU.cpp
===================================================================
--- lib/CodeGen/CGObjCGNU.cpp
+++ lib/CodeGen/CGObjCGNU.cpp
@@ -560,8 +560,9 @@
     return NULLPtr;
   }
 
-  llvm::GlobalVariable *GetClassGlobal(const std::string &Name,
-                                       bool Weak = false) override {
+  llvm::Constant *GetClassGlobal(const std::string &Name,
+                                 bool ForDefinition,
+                                 bool Weak) override {
     return nullptr;
   }
 };
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to