[ORC] Remove hard dependency on libobjc when using MachOPlatform with LLJIT.
authorLang Hames <lhames@gmail.com>
Thu, 5 Mar 2020 05:23:51 +0000 (21:23 -0800)
committerLang Hames <lhames@gmail.com>
Thu, 5 Mar 2020 05:49:28 +0000 (21:49 -0800)
The LLJIT::MachOPlatformSupport class used to unconditionally attempt to
register __objc_selrefs and __objc_classlist sections. If libobjc had not
been loaded this resulted in an assertion, even if no objc sections were
actually present. This patch replaces this unconditional registration with
a check that no objce sections are present if libobjc has not been loaded.
This will allow clients to use MachOPlatform with LLJIT without requiring
libobjc for non-objc code.

llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h
llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp

index 0d07f53dd3fb11bbef8658b82cc9e323794b25a5..f869ebdfbe4e7655971bb606cc1c426e41502318 100644 (file)
@@ -39,6 +39,8 @@ public:
     uint64_t NumPtrs = 0;
   };
 
+  using RawPointerSectionList = std::vector<SectionExtent>;
+
   void setObjCImageInfoAddr(JITTargetAddress ObjCImageInfoAddr) {
     this->ObjCImageInfoAddr = ObjCImageInfoAddr;
   }
@@ -47,20 +49,31 @@ public:
     ModInitSections.push_back(std::move(ModInit));
   }
 
+  const RawPointerSectionList &getModInitsSections() const {
+    return ModInitSections;
+  }
+
   void addObjCSelRefsSection(SectionExtent ObjCSelRefs) {
     ObjCSelRefsSections.push_back(std::move(ObjCSelRefs));
   }
 
+  const RawPointerSectionList &getObjCSelRefsSections() const {
+    return ObjCSelRefsSections;
+  }
+
   void addObjCClassListSection(SectionExtent ObjCClassList) {
     ObjCClassListSections.push_back(std::move(ObjCClassList));
   }
 
+  const RawPointerSectionList &getObjCClassListSections() const {
+    return ObjCClassListSections;
+  }
+
   void runModInits() const;
   void registerObjCSelectors() const;
   Error registerObjCClasses() const;
 
 private:
-  using RawPointerSectionList = std::vector<SectionExtent>;
 
   JITTargetAddress ObjCImageInfoAddr;
   RawPointerSectionList ModInitSections;
index 2ff9e78f82e1c8836e692e43d5294505887a7d95..a847f0ef9421b6582dd565c74916a62e3a6911e9 100644 (file)
@@ -555,18 +555,34 @@ public:
              << "\"\n";
     });
 
-    if (auto InitSeq = MP.getInitializerSequence(JD)) {
+    auto InitSeq = MP.getInitializerSequence(JD);
+    if (!InitSeq)
+      return InitSeq.takeError();
+
+    // If ObjC is not enabled but there are JIT'd ObjC inits then return
+    // an error.
+    if (!objCRegistrationEnabled())
       for (auto &KV : *InitSeq) {
+        if (!KV.second.getObjCSelRefsSections().empty() ||
+            !KV.second.getObjCClassListSections().empty())
+          return make_error<StringError>("JITDylib " + KV.first->getName() +
+                                             " contains objc metadata but objc"
+                                             " is not enabled",
+                                         inconvertibleErrorCode());
+      }
+
+    // Run the initializers.
+    for (auto &KV : *InitSeq) {
+      if (objCRegistrationEnabled()) {
         KV.second.registerObjCSelectors();
         if (auto Err = KV.second.registerObjCClasses()) {
           // FIXME: Roll back registrations on error?
           return Err;
         }
       }
-      for (auto &KV : *InitSeq)
-        KV.second.runModInits();
-    } else
-      return InitSeq.takeError();
+      KV.second.runModInits();
+    }
+
     return Error::success();
   }
 
index b883a81e5d3f94a15d0bd52d44d435e205c46b1c..9a836677ef15b5fd92ce5fc9a513cbcf009ddb63 100644 (file)
@@ -81,7 +81,7 @@ Error enableObjCRegistration(const char *PathToLibObjC) {
   return Error::success();
 }
 
-bool objcRegistrationEnabled() {
+bool objCRegistrationEnabled() {
   return ObjCRegistrationAPIState == ObjCRegistrationAPI::Initialized;
 }
 
@@ -98,7 +98,7 @@ void MachOJITDylibInitializers::runModInits() const {
 }
 
 void MachOJITDylibInitializers::registerObjCSelectors() const {
-  assert(objcRegistrationEnabled() && "ObjC registration not enabled.");
+  assert(objCRegistrationEnabled() && "ObjC registration not enabled.");
 
   for (const auto &ObjCSelRefs : ObjCSelRefsSections) {
     for (uint64_t I = 0; I != ObjCSelRefs.NumPtrs; ++I) {
@@ -112,7 +112,7 @@ void MachOJITDylibInitializers::registerObjCSelectors() const {
 }
 
 Error MachOJITDylibInitializers::registerObjCClasses() const {
-  assert(objcRegistrationEnabled() && "ObjC registration not enabled.");
+  assert(objCRegistrationEnabled() && "ObjC registration not enabled.");
 
   struct ObjCClassCompiled {
     void *Metaclass;