diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter/AsmPrinter.cpp')
-rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 65 |
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); |