diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 2a022657bd9..94b7cf4f95b 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -78,6 +78,11 @@ class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { public: virtual ~TargetLoweringObjectFileMachO() {} + /// emitModuleFlags - Emit the module flags that specify the garbage + /// collection information. + virtual void emitModuleFlags(MCStreamer &Streamer, NamedMDNode *ModFlags, + Mangler *Mang, const TargetMachine &TM) const; + virtual const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const; diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 04fe2208b28..d1151a10d2e 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -29,6 +29,7 @@ namespace llvm { class MCSectionMachO; class MCSymbol; class MCStreamer; + class NamedMDNode; class GlobalValue; class TargetMachine; @@ -53,7 +54,12 @@ public: virtual void emitPersonalityValue(MCStreamer &Streamer, const TargetMachine &TM, const MCSymbol *Sym) const; - + + /// emitModuleFlags - Emit the module flags that the platform cares about. + virtual void emitModuleFlags(MCStreamer &, NamedMDNode *, Mangler *, + const TargetMachine &) const { + } + /// shouldEmitUsedDirectiveFor - This hook allows targets to selectively /// decide not to emit the UsedDirective for some symbols in llvm.used. /// FIXME: REMOVE this (rdar://7071300) @@ -86,9 +92,7 @@ public: const TargetMachine &TM) const { return SectionForGlobal(GV, getKindForGlobal(GV, TM), Mang, TM); } - - - + /// getExplicitSectionGlobal - Targets should implement this method to assign /// a section to globals with an explicit section specfied. The /// implementation of this method can assume that GV->hasSection() is true. diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 241f20097ed..80d90d668de 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -857,6 +857,10 @@ bool AsmPrinter::doFinalization(Module &M) { EmitVisibility(Name, V, false); } + // Emit module flags. + if (NamedMDNode *ModFlags = M.getModuleFlagsMetadata()) + getObjFileLowering().emitModuleFlags(OutStreamer, ModFlags, Mang, TM); + // Finalize debug and EH information. if (DE) { { diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 3a71f4f1267..1b62419aabd 100644 --- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -17,6 +17,7 @@ #include "llvm/DerivedTypes.h" #include "llvm/Function.h" #include "llvm/GlobalVariable.h" +#include "llvm/Module.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -370,6 +371,65 @@ TargetLoweringObjectFileELF::getStaticDtorSection(unsigned Priority) const { // MachO //===----------------------------------------------------------------------===// +/// emitModuleFlags - Emit the module flags that specify the garbage collection +/// information. +void TargetLoweringObjectFileMachO:: +emitModuleFlags(MCStreamer &Streamer, NamedMDNode *ModFlags, + Mangler *Mang, const TargetMachine &TM) const { + StringRef Version("Objective-C Image Info Version"); + StringRef SectionSpec("Objective-C Image Info Section"); + StringRef GC("Objective-C Garbage Collection"); + StringRef GCOnly("Objective-C GC Only"); + + unsigned VersionVal = 0; + unsigned GCFlags = 0; + StringRef Section; + + for (unsigned i = 0, e = ModFlags->getNumOperands(); i != e; ++i) { + MDNode *Flag = ModFlags->getOperand(i); + Value *Behavior = Flag->getOperand(0); + + // Ignore flags with 'Require' behavior. + if (cast(Behavior)->getZExtValue() == Module::Require) + continue; + + Value *Key = Flag->getOperand(1); + Value *Val = Flag->getOperand(2); + + StringRef KeyStr = cast(Key)->getString(); + + if (KeyStr == Version) + VersionVal = cast(Val)->getZExtValue(); + else if (KeyStr == GC || KeyStr == GCOnly) + GCFlags |= cast(Val)->getZExtValue(); + else if (KeyStr == SectionSpec) + Section = cast(Val)->getString(); + } + + // The section is mandatory. If we don't have it, then we don't have image + // info information. + if (Section.empty()) return; + + uint32_t Values[2] = { VersionVal, GCFlags }; + Module *M = ModFlags->getParent(); + Constant *Init = ConstantDataArray::get(M->getContext(), Values); + GlobalVariable *GV = new GlobalVariable(*M, Init->getType(), false, + GlobalValue::InternalLinkage, Init, + "\01L_OBJC_IMAGE_INFO"); + GV->setSection(Section); + + MCSymbol *GVSym = Mang->getSymbol(GV); + SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM); + const MCSection *TheSection = SectionForGlobal(GV, GVKind, Mang, TM); + + Streamer.SwitchSection(TheSection); + Streamer.EmitLabel(GVSym); + + Streamer.EmitIntValue(VersionVal, 4); + Streamer.EmitIntValue(GCFlags, 4); + Streamer.AddBlankLine(); +} + const MCSection *TargetLoweringObjectFileMachO:: getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const {