From: John McCall Date: Thu, 12 Jul 2012 02:07:58 +0000 (+0000) Subject: Add the ObjFW runtime. Patch by Jonathan Schleifer! X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f7226fbe677a9c7578fa0613491ed15c6dc6a5e1;p=clang Add the ObjFW runtime. Patch by Jonathan Schleifer! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160102 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h index 228135d094..da3ecca0f8 100644 --- a/include/clang/Basic/ObjCRuntime.h +++ b/include/clang/Basic/ObjCRuntime.h @@ -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"); } diff --git a/lib/Basic/ObjCRuntime.cpp b/lib/Basic/ObjCRuntime.cpp index f52677b512..9bd433a064 100644 --- a/lib/Basic/ObjCRuntime.cpp +++ b/lib/Basic/ObjCRuntime.cpp @@ -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; } diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index 2fdc74ce6d..ba9c2967cd 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -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; diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 686fb051b7..9993f448f7 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -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: diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 4781d87a6b..864b4ebe1f 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -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"); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index bba3e7c5f7..22ac115484 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -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 index 0000000000..98e3fb0265 --- /dev/null +++ b/test/CodeGenObjC/objfw.m @@ -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