aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Driver/clang.cpp17
-rw-r--r--include/clang/Basic/LangOptions.h6
-rw-r--r--lib/Basic/Targets.cpp5
-rw-r--r--lib/CodeGen/CGObjCMac.cpp88
-rw-r--r--lib/CodeGen/CodeGenModule.cpp6
-rw-r--r--lib/CodeGen/CodeGenModule.h2
-rw-r--r--lib/CodeGen/ModuleBuilder.cpp3
7 files changed, 117 insertions, 10 deletions
diff --git a/Driver/clang.cpp b/Driver/clang.cpp
index c55aa17eb2..089faf1255 100644
--- a/Driver/clang.cpp
+++ b/Driver/clang.cpp
@@ -373,6 +373,14 @@ static llvm::cl::opt<bool>
Exceptions("fexceptions",
llvm::cl::desc("Enable support for exception handling."));
+static llvm::cl::opt<bool>
+GNURuntime("fgnu-runtime",
+ llvm::cl::desc("Generate output compatible with the standard GNU Objective-C runtime."));
+
+static llvm::cl::opt<bool>
+NeXTRuntime("fnext-runtime",
+ llvm::cl::desc("Generate output compatible with the NeXT runtime."));
+
// FIXME: add:
// -ansi
// -trigraphs
@@ -439,6 +447,15 @@ static void InitializeLanguageStandard(LangOptions &Options, LangKind LK) {
Options.WritableStrings = WritableStrings;
Options.LaxVectorConversions = LaxVectorConversions;
Options.Exceptions = Exceptions;
+
+ if (NeXTRuntime) {
+ Options.NeXTRuntime = 1;
+ } else if (GNURuntime) {
+ Options.NeXTRuntime = 0;
+ } else {
+ // FIXME: Should autoselect based on platform.
+ Options.NeXTRuntime = 0;
+ }
}
static llvm::cl::opt<bool>
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index 7756a2ab5b..c07fdfe47c 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -43,7 +43,9 @@ struct LangOptions {
unsigned WritableStrings : 1; // Allow writable strings
unsigned LaxVectorConversions : 1;
unsigned Exceptions : 1; // Support exception handling.
-
+
+ unsigned NeXTRuntime : 1; // Use NeXT runtime.
+
private:
unsigned GC : 2; // Objective-C Garbage Collection modes. We declare
// this enum as unsigned because MSVC insists on making enums
@@ -58,7 +60,7 @@ public:
GC = ObjC1 = ObjC2 = 0;
C99 = Microsoft = CPlusPlus = CPlusPlus0x = NoExtensions = 0;
CXXOperatorNames = PascalStrings = Boolean = WritableStrings = 0;
- LaxVectorConversions = Exceptions = 0;
+ LaxVectorConversions = Exceptions = NeXTRuntime = 0;
}
GCMode getGCMode() const { return (GCMode) GC; }
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 214dfb16de..bc35d7fe8e 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -53,7 +53,7 @@ public:
Define(Defs, "linux");
#endif
- if (1) {// -fobjc-gc controls this.
+ if (1) { // FIXME: -fobjc-gc controls this.
Define(Defs, "__weak", "");
Define(Defs, "__strong", "");
} else {
@@ -67,6 +67,9 @@ public:
if (0) // darwin_pascal_strings
Define(Defs, "__PASCAL_STRINGS__");
+
+ if (0) // FIXME: -fnext-runtime controls this
+ Define(Defs, "__NEXT_RUNTIME__");
}
};
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index faf6fa94fc..205a8f55e9 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -12,7 +12,11 @@
//===----------------------------------------------------------------------===//
#include "CGObjCRuntime.h"
+
+#include "CodeGenModule.h"
#include "clang/AST/Decl.h"
+#include "clang/Basic/LangOptions.h"
+
#include "llvm/Support/IRBuilder.h"
using namespace clang;
@@ -22,6 +26,18 @@ class CGObjCMac : public CodeGen::CGObjCRuntime {
private:
CodeGen::CodeGenModule &CGM;
+ /// UsedGlobals - list of globals to pack into the llvm.used metadata
+ /// to prevent them from being clobbered.
+ std::vector<llvm::GlobalValue*> UsedGlobals;
+
+ /// EmitImageInfo - Emit the image info marker used to encode some module
+ /// level information.
+ void EmitImageInfo();
+
+ /// FinishModule - Write out global data structures at the end of
+ /// processing a translation unit.
+ void FinishModule();
+
public:
CGObjCMac(CodeGen::CodeGenModule &cgm);
virtual llvm::Constant *GenerateConstantString(const char *String,
@@ -94,6 +110,7 @@ public:
} // end anonymous namespace
CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGM(cgm) {
+ EmitImageInfo();
}
// This has to perform the lookup every time, since posing and related
@@ -186,6 +203,9 @@ void CGObjCMac::GenerateClass(
}
llvm::Function *CGObjCMac::ModuleInitFunction() {
+ // Abuse this interface function as a place to finalize.
+ FinishModule();
+
return NULL;
}
@@ -203,6 +223,74 @@ llvm::Function *CGObjCMac::MethodPreamble(
return 0;
}
+/* *** Private Interface *** */
+
+/// EmitImageInfo - Emit the image info marker used to encode some module
+/// level information.
+///
+/// See: <rdr://4810609&4810587&4810587>
+/// struct IMAGE_INFO {
+/// unsigned version;
+/// unsigned flags;
+/// };
+enum ImageInfoFlags {
+ eImageInfo_FixAndContinue = (1 << 0), // FIXME: Not sure what this implies
+ eImageInfo_GarbageCollected = (1 << 1),
+ eImageInfo_GCOnly = (1 << 2)
+};
+
+void CGObjCMac::EmitImageInfo() {
+ unsigned version = 0; // Version is unused?
+ unsigned flags = 0;
+
+ // FIXME: Fix and continue?
+ if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
+ flags |= eImageInfo_GarbageCollected;
+ if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
+ flags |= eImageInfo_GCOnly;
+
+ fprintf(stderr, "flags: %d (%d)\n", flags, CGM.getLangOptions().getGCMode());
+
+ // Emitted as int[2];
+ llvm::Constant *values[2] = {
+ llvm::ConstantInt::get(llvm::Type::Int32Ty, version),
+ llvm::ConstantInt::get(llvm::Type::Int32Ty, flags)
+ };
+ llvm::ArrayType *AT = llvm::ArrayType::get(llvm::Type::Int32Ty, 2);
+ llvm::GlobalValue *GV =
+ new llvm::GlobalVariable(AT, true,
+ llvm::GlobalValue::InternalLinkage,
+ llvm::ConstantArray::get(AT, values, 2),
+ "\01L_OBJC_IMAGE_INFO",
+ &CGM.getModule());
+
+ GV->setSection("__OBJC, __image_info,regular");
+
+ UsedGlobals.push_back(GV);
+}
+
+void CGObjCMac::FinishModule() {
+ std::vector<llvm::Constant*> Used;
+
+ llvm::Type *I8Ptr = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
+ for (std::vector<llvm::GlobalValue*>::iterator i = UsedGlobals.begin(),
+ e = UsedGlobals.end(); i != e; ++i) {
+ Used.push_back(llvm::ConstantExpr::getBitCast(*i, I8Ptr));
+ }
+
+ llvm::ArrayType *AT = llvm::ArrayType::get(I8Ptr, Used.size());
+ llvm::GlobalValue *GV =
+ new llvm::GlobalVariable(AT, false,
+ llvm::GlobalValue::AppendingLinkage,
+ llvm::ConstantArray::get(AT, Used),
+ "llvm.used",
+ &CGM.getModule());
+
+ GV->setSection("llvm.metadata");
+}
+
+/* *** */
+
CodeGen::CGObjCRuntime *CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM){
return new CGObjCMac(CGM);
}
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 347f4d24f9..fb873c2a67 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -30,15 +30,13 @@ using namespace CodeGen;
CodeGenModule::CodeGenModule(ASTContext &C, const LangOptions &LO,
llvm::Module &M, const llvm::TargetData &TD,
- Diagnostic &diags, bool GenerateDebugInfo,
- bool UseMacObjCRuntime)
+ Diagnostic &diags, bool GenerateDebugInfo)
: Context(C), Features(LO), TheModule(M), TheTargetData(TD), Diags(diags),
Types(C, M, TD), Runtime(0), MemCpyFn(0), MemMoveFn(0), MemSetFn(0),
CFConstantStringClassRef(0) {
if (Features.ObjC1) {
- // TODO: Make this selectable at runtime
- if (UseMacObjCRuntime) {
+ if (Features.NeXTRuntime) {
Runtime = CreateMacObjCRuntime(*this);
} else {
Runtime = CreateGNUObjCRuntime(*this);
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 0b313c4205..3f30cd3283 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -105,7 +105,7 @@ class CodeGenModule {
public:
CodeGenModule(ASTContext &C, const LangOptions &Features, llvm::Module &M,
const llvm::TargetData &TD, Diagnostic &Diags,
- bool GenerateDebugInfo, bool UseMacObjCRuntime);
+ bool GenerateDebugInfo);
~CodeGenModule();
diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp
index 7c43943eac..affef35f28 100644
--- a/lib/CodeGen/ModuleBuilder.cpp
+++ b/lib/CodeGen/ModuleBuilder.cpp
@@ -59,8 +59,7 @@ namespace {
M->setDataLayout(Ctx->Target.getTargetDescription());
TD.reset(new llvm::TargetData(Ctx->Target.getTargetDescription()));
Builder.reset(new CodeGen::CodeGenModule(Context, Features, *M, *TD,
- Diags, GenerateDebugInfo,
- false));
+ Diags, GenerateDebugInfo));
}
virtual void HandleTopLevelDecl(Decl *D) {