commit 163596a0905cd1508c0c10de41887a92206a0634
Author: Jonathan Schleifer <js@webkeks.org>
Date:   Sat May 12 12:42:18 2012 +0200

    Add -fobjc-direct-class-refs.
    
    This options allows referencing classes directly when using the GNU ABI.
    Clang already emits symbols for all classes and with this option, it is
    actually possible to use those. This is tested with my own runtime, the
    ObjFW runtime, and should also work with the GNUstep runtime.

diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index a795c57..21cff71 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -52,6 +52,7 @@ LANGOPT(ObjC1             , 1, 0, "Objective-C 1")
 LANGOPT(ObjC2             , 1, 0, "Objective-C 2")
 LANGOPT(ObjCNonFragileABI , 1, 0, "Objective-C modern abi")
 LANGOPT(ObjCNonFragileABI2 , 1, 0, "Objective-C enhanced modern abi")
+LANGOPT(ObjCDirectClassRefs , 1, 0, "Direct Objective-C class references")
 BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0, 
                "Objective-C auto-synthesized properties")
 BENIGN_LANGOPT(ObjCInferRelatedResultType , 1, 1, 
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 90933f7..5bb257b 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -396,6 +396,10 @@ def fobjc_default_synthesize_properties : Flag<"-fobjc-default-synthesize-proper
   HelpText<"enable the default synthesis of Objective-C properties">;
 def fobjc_fragile_abi : Flag<"-fobjc-fragile-abi">,
   HelpText<"Use Objective-C's fragile ABI">;
+def fobjc_direct_class_refs : Flag<"-fobjc-direct-class-refs">, Group<f_Group>,
+  HelpText<"Use direct references to classes when using the GNU ABI">;
+def fno_objc_direct_class_refs : Flag<"-fno-objc-direct-class-refs">, Group<f_Group>,
+  HelpText<"Don't use direct references to classes when using the GNU ABI">;
 def pic_level : Separate<"-pic-level">,
   HelpText<"Value for __PIC__">;
 def pie_level : Separate<"-pie-level">,
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index e783eb7..d8c0fec 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -819,8 +819,23 @@ llvm::Value *CGObjCGNU::GetClassNamed(CGBuilderTy &Builder,
   //
   // Libobjc2 contains an LLVM pass that replaces calls to objc_lookup_class
   // with memoized versions or with static references if it's safe to do so.
-  if (!isWeak)
+  if (!isWeak) {
+
     EmitClassRef(Name);
+
+    if (CGM.getLangOpts().ObjCDirectClassRefs) {
+      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;
+    }
+  }
   ClassName = Builder.CreateStructGEP(ClassName, 0);
 
   llvm::Constant *ClassLookupFn =
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 10964ec..d5bd915 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -2413,6 +2413,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     }
   }
 
+  if (Args.hasFlag(options::OPT_fobjc_direct_class_refs,
+                   options::OPT_fno_objc_direct_class_refs,
+                   false)) {
+    CmdArgs.push_back("-fobjc-direct-class-refs");
+  }
+
   // -fobjc-default-synthesize-properties=1 is default. This only has an effect
   // if the nonfragile objc abi is used.
   if (getToolChain().IsObjCDefaultSynthPropertiesDefault()) {
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 3a7efbc..614ed34 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -668,6 +668,8 @@ static void LangOptsToArgs(const LangOptions &Opts, ToArgsList &Res) {
     Res.push_back("-fborland-extensions");
   if (!Opts.ObjCNonFragileABI)
     Res.push_back("-fobjc-fragile-abi");
+  if (Opts.ObjCDirectClassRefs)
+    Res.push_back("-fobjc-direct-class-refs");
   if (Opts.ObjCDefaultSynthProperties)
     Res.push_back("-fobjc-default-synthesize-properties");
   // NoInline is implicit.
@@ -1851,7 +1853,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
     if (Args.hasArg(OPT_fno_objc_infer_related_result_type))
       Opts.ObjCInferRelatedResultType = 0;
   }
-    
+
+  if (Args.hasArg(OPT_fobjc_direct_class_refs))
+    Opts.ObjCDirectClassRefs = 1;
+
+
   if (Args.hasArg(OPT_fgnu89_inline))
     Opts.GNUInline = 1;
 
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 5038868..46baa44 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -626,6 +626,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
            .Case("objc_instancetype", LangOpts.ObjC2)
            .Case("objc_modules", LangOpts.ObjC2 && LangOpts.Modules)
            .Case("objc_nonfragile_abi", LangOpts.ObjCNonFragileABI)
+           .Case("objc_direct_class_refs", LangOpts.ObjCDirectClassRefs)
            .Case("objc_weak_class", LangOpts.ObjCNonFragileABI)
            .Case("ownership_holds", true)
            .Case("ownership_returns", true)
