]> granicus.if.org Git - clang/commitdiff
Add the ObjFW runtime. Patch by Jonathan Schleifer!
authorJohn McCall <rjmccall@apple.com>
Thu, 12 Jul 2012 02:07:58 +0000 (02:07 +0000)
committerJohn McCall <rjmccall@apple.com>
Thu, 12 Jul 2012 02:07:58 +0000 (02:07 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160102 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/ObjCRuntime.h
lib/Basic/ObjCRuntime.cpp
lib/CodeGen/CGException.cpp
lib/CodeGen/CGObjCGNU.cpp
lib/CodeGen/CGObjCMac.cpp
lib/CodeGen/CodeGenModule.cpp
test/CodeGenObjC/objfw.m [new file with mode: 0644]

index 228135d09493c27dfec7b2b52590b59990f3a0c9..da3ecca0f8d13f86e148581811c19795e0ead7ee 100644 (file)
@@ -46,7 +46,10 @@ public:
     GCC,
 
     /// 'gnustep' is the modern non-fragile GNUstep runtime.
-   GNUstep 
+    GNUstep,
+
+    /// 'objfw' is the Objective-C runtime included in ObjFW
+    ObjFW
   };
 
 private:
@@ -76,6 +79,7 @@ public:
     case GCC: return false;
     case MacOSX: return true;
     case GNUstep: return true;
+    case ObjFW: return false;
     case iOS: return true;
     }
     llvm_unreachable("bad kind");
@@ -109,6 +113,7 @@ public:
       return false;
     case GCC:
     case GNUstep:
+    case ObjFW:
       return true;
     }
     llvm_unreachable("bad kind");
@@ -134,6 +139,7 @@ public:
 
     case GCC: return false;
     case GNUstep: return getVersion() >= VersionTuple(1, 6);
+    case ObjFW: return false; // XXX: this will change soon
     }
     llvm_unreachable("bad kind");
   }
@@ -159,6 +165,7 @@ public:
     // should imply a "maximal" runtime or something?
     case GCC: return true;
     case GNUstep: return true;
+    case ObjFW: return true;
     }
     llvm_unreachable("bad kind");
   }
@@ -174,6 +181,7 @@ public:
     case iOS: return getVersion() >= VersionTuple(5);
     case GCC: return false;
     case GNUstep: return false;
+    case ObjFW: return false;
     }
     llvm_unreachable("bad kind");
   }
@@ -186,6 +194,7 @@ public:
     case FragileMacOSX: return false;
     case GCC: return true;
     case GNUstep: return true;
+    case ObjFW: return true;
     }
     llvm_unreachable("bad kind");
   }
@@ -197,6 +206,7 @@ public:
     case FragileMacOSX: return false;
     case GCC: return true;
     case GNUstep: return true;
+    case ObjFW: return true;
     }
     llvm_unreachable("bad kind");
   }
index f52677b5122c0f45c5352173d16144608c09531d..9bd433a0649b604ac2ca50d1b601285812542953 100644 (file)
@@ -32,6 +32,7 @@ raw_ostream &clang::operator<<(raw_ostream &out, const ObjCRuntime &value) {
   case ObjCRuntime::iOS: out << "ios"; break;
   case ObjCRuntime::GNUstep: out << "gnustep"; break;
   case ObjCRuntime::GCC: out << "gcc"; break;
+  case ObjCRuntime::ObjFW: out << "objfw"; break;
   }
   if (value.getVersion() > VersionTuple(0)) {
     out << '-' << value.getVersion();
@@ -68,6 +69,8 @@ bool ObjCRuntime::tryParse(StringRef input) {
     kind = ObjCRuntime::GNUstep;
   } else if (runtimeName == "gcc") {
     kind = ObjCRuntime::GCC;
+  } else if (runtimeName == "objfw") {
+    kind = ObjCRuntime::ObjFW;
   } else {
     return true;
   }
index 2fdc74ce6d0960ac60ba264cc614ccce37e253c9..ba9c2967cd3d5b8e73267c92a5a4682085aeb7c5 100644 (file)
@@ -188,6 +188,7 @@ static const EHPersonality &getObjCPersonality(const LangOptions &L) {
     return EHPersonality::NeXT_ObjC;
   case ObjCRuntime::GNUstep:
   case ObjCRuntime::GCC:
+  case ObjCRuntime::ObjFW:
     return EHPersonality::GNU_ObjC;
   }
   llvm_unreachable("bad runtime kind");
@@ -219,6 +220,7 @@ static const EHPersonality &getObjCXXPersonality(const LangOptions &L) {
   // The GCC runtime's personality function inherently doesn't support
   // mixed EH.  Use the C++ personality just to avoid returning null.
   case ObjCRuntime::GCC:
+  case ObjCRuntime::ObjFW: // XXX: this will change soon
     return EHPersonality::GNU_ObjC;
   case ObjCRuntime::GNUstep:
     return EHPersonality::GNU_ObjCXX;
index 686fb051b706f5decc19a55af3b4292b5ac384ea..9993f448f7b04d98723e939d9fac86ac89b07568 100644 (file)
@@ -99,8 +99,8 @@ class LazyRuntimeFunction {
 
 
 /// GNU Objective-C runtime code generation.  This class implements the parts of
-/// Objective-C support that are specific to the GNU family of runtimes (GCC and
-/// GNUstep).
+/// Objective-C support that are specific to the GNU family of runtimes (GCC,
+/// GNUstep and ObjFW).
 class CGObjCGNU : public CGObjCRuntime {
 protected:
   /// The LLVM module into which output is inserted
@@ -397,11 +397,11 @@ private:
       const ObjCIvarDecl *Ivar);
   /// Emits a reference to a class.  This allows the linker to object if there
   /// is no class of the matching name.
+protected:
   void EmitClassRef(const std::string &className);
   /// Emits a pointer to the named class
-  llvm::Value *GetClassNamed(CGBuilderTy &Builder, const std::string &Name,
-                             bool isWeak);
-protected:
+  virtual llvm::Value *GetClassNamed(CGBuilderTy &Builder,
+                                     const std::string &Name, bool isWeak);
   /// Looks up the method for sending a message to the specified object.  This
   /// mechanism differs between the GCC and GNU runtimes, so this method must be
   /// overridden in subclasses.
@@ -653,6 +653,30 @@ class CGObjCGNUstep : public CGObjCGNU {
     }
 };
 
+/// Class used when targeting the ObjFW runtime.
+class CGObjCObjFW: public CGObjCGCC {
+  virtual llvm::Value *GetClassNamed(CGBuilderTy &Builder,
+                                     const std::string &Name, bool isWeak) {
+    if (isWeak)
+      return CGObjCGNU::GetClassNamed(Builder, Name, isWeak);
+
+    EmitClassRef(Name);
+
+    std::string SymbolName = "_OBJC_CLASS_" + Name;
+
+    llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(SymbolName);
+
+    if (!ClassSymbol)
+      ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false,
+                                             llvm::GlobalValue::ExternalLinkage,
+                                             0, SymbolName);
+
+    return ClassSymbol;
+  }
+
+public:
+  CGObjCObjFW(CodeGenModule &Mod): CGObjCGCC(Mod) {}
+};
 } // end anonymous namespace
 
 
@@ -2672,6 +2696,9 @@ clang::CodeGen::CreateGNUObjCRuntime(CodeGenModule &CGM) {
   case ObjCRuntime::GCC:
     return new CGObjCGCC(CGM);
 
+  case ObjCRuntime::ObjFW:
+    return new CGObjCObjFW(CGM);
+
   case ObjCRuntime::FragileMacOSX:
   case ObjCRuntime::MacOSX:
   case ObjCRuntime::iOS:
index 4781d87a6b30a9abdb1e96619ab7f322af71a879..864b4ebe1f1e71b8c8d3407360eb22a926ec12fb 100644 (file)
@@ -6391,6 +6391,7 @@ CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
 
   case ObjCRuntime::GNUstep:
   case ObjCRuntime::GCC:
+  case ObjCRuntime::ObjFW:
     llvm_unreachable("these runtimes are not Mac runtimes");
   }
   llvm_unreachable("bad runtime");
index bba3e7c5f755c0937add64eaa5461f4d7765ee17..22ac1154840e5581ce91e2b07f3f9d58ae6354c4 100644 (file)
@@ -140,6 +140,7 @@ void CodeGenModule::createObjCRuntime() {
   switch (LangOpts.ObjCRuntime.getKind()) {
   case ObjCRuntime::GNUstep:
   case ObjCRuntime::GCC:
+  case ObjCRuntime::ObjFW:
     ObjCRuntime = CreateGNUObjCRuntime(*this);
     return;
 
diff --git a/test/CodeGenObjC/objfw.m b/test/CodeGenObjC/objfw.m
new file mode 100644 (file)
index 0000000..98e3fb0
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fobjc-runtime=objfw -emit-llvm -o - %s | FileCheck %s
+
+// Test the ObjFW runtime.
+
+@interface Test0
++ (void) test;
+@end
+void test0(void) {
+  [Test0 test];
+}
+// CHECK:    define void @test0()
+// CHECK:      [[T0:%.*]] = call i8* (i8*, i8*, ...)* (i8*, i8*)* @objc_msg_lookup(i8* bitcast (i64* @_OBJC_CLASS_Test0 to i8*),
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* (i8*, i8*, ...)* [[T0]] to void (i8*, i8*)*
+// CHECK-NEXT: call void [[T1]](i8* bitcast (i64* @_OBJC_CLASS_Test0 to i8*), 
+// CHECK-NEXT: ret void