Add LangOptions::NeXTRuntime.
- Wired to -fnext-runtime and -fgnu-runtime options.
- Defaults to GNU, no autoselection for NeXT.
Emit NeXT OBJC_IMAGE_INFO marker.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54651 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index faf6fa9..205a8f5 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 @@
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 @@
} // 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 @@
}
llvm::Function *CGObjCMac::ModuleInitFunction() {
+ // Abuse this interface function as a place to finalize.
+ FinishModule();
+
return NULL;
}
@@ -203,6 +223,74 @@
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);
}