aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/AsmPrinter/AsmPrinter.cpp')
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 82860c2657..1b15cdcc81 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -930,6 +930,71 @@ bool AsmPrinter::doFinalization(Module &M) {
if (const MCSection *S = MAI->getNonexecutableStackSection(OutContext))
OutStreamer.SwitchSection(S);
+ // If we have module flags, then emit them.
+ NamedMDNode *ModFlags = M.getNamedMetadata("llvm.module.flags");
+ if (ModFlags) {
+ const char *ObjCGCName = "Objective-C Garbage Collection";
+ const char *ObjCGCOnlyName = "Objective-C GC Only";
+ const char *ObjCImageInfoVersion = "Objective-C Image Info Version";
+ const char *ObjCImageInfoSec = "Objective-C Image Info Section";
+
+ MDNode *GC = 0;
+ MDNode *GCOnly = 0;
+ MDNode *ImageInfoVersion = 0;
+ MDNode *ImageInfoSec = 0;
+
+ for (unsigned I = 0, E = ModFlags->getNumOperands(); I != E; ++I) {
+ MDNode *MD = ModFlags->getOperand(I);
+ unsigned Behavior = cast<ConstantInt>(MD->getOperand(0))->getZExtValue();
+ (void) Behavior;
+ MDString *Str = cast<MDString>(MD->getOperand(1));
+
+ if (Str->getString() == ObjCImageInfoVersion) {
+ assert(Behavior == 1 && "Invalid behavior for module flag!");
+ ImageInfoVersion = MD;
+ } else if (Str->getString() == ObjCGCName) {
+ assert((Behavior == 1 || Behavior == 3) &&
+ "Invalid behavior for module flag!");
+ GC = MD;
+ } else if (Str->getString() == ObjCGCOnlyName) {
+ if (Behavior == 2) continue; // Ignore the 'require' clause.
+ GCOnly = MD;
+ } else if (Str->getString() == ObjCImageInfoSec) {
+ assert(Behavior == 1 && "Invalid behavior for module flag!");
+ ImageInfoSec = MD;
+ }
+ }
+
+ if (ImageInfoVersion || GC || GCOnly || ImageInfoSec) {
+ // FIXME: Duh!
+ unsigned version = 0;
+ unsigned flags = 0;
+
+ version =
+ cast<ConstantInt>(ImageInfoVersion->getOperand(2))->getZExtValue();
+ if (GC)
+ flags |= cast<ConstantInt>(GC->getOperand(2))->getZExtValue();
+ if (GCOnly)
+ flags |= cast<ConstantInt>(GCOnly->getOperand(2))->getZExtValue();
+
+ Type *Int32Ty = Type::getInt32Ty(M.getContext());
+ Constant *values[2] = {
+ ConstantInt::get(Int32Ty, version),
+ ConstantInt::get(Int32Ty, flags)
+ };
+ ArrayType *AT = ArrayType::get(Int32Ty, 2);
+ StringRef Sec = cast<MDString>(ImageInfoSec->getOperand(2))->getString();
+
+ GlobalVariable *GV =
+ cast<GlobalVariable>(M.getOrInsertGlobal("L_OBJC_IMAGE_INFO", AT));
+ GV->setConstant(true);
+ GV->setSection(Sec);
+ GV->setInitializer(ConstantArray::get(AT, values));
+
+ EmitGlobalVariable(GV);
+ }
+ }
+
// Allow the target to emit any magic that it wants at the end of the file,
// after everything else has gone out.
EmitEndOfAsmFile(M);