diff options
-rw-r--r-- | include/llvm/CodeGen/TargetLoweringObjectFileImpl.h | 6 | ||||
-rw-r--r-- | lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 46 | ||||
-rwxr-xr-x | test/MC/COFF/linker-options.ll | 21 |
3 files changed, 73 insertions, 0 deletions
diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index e7098e4..5b22c9c 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -128,6 +128,12 @@ public: virtual const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const; + + /// emitModuleFlags - Emit Obj-C garbage collection and linker options. Only + /// linker option emission is implemented for COFF. + virtual void emitModuleFlags(MCStreamer &Streamer, + ArrayRef<Module::ModuleFlagEntry> ModuleFlags, + Mangler *Mang, const TargetMachine &TM) const; }; } // end namespace llvm diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 3bdca4c..678698a 100644 --- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -782,3 +782,49 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, return getDataSection(); } +void TargetLoweringObjectFileCOFF:: +emitModuleFlags(MCStreamer &Streamer, + ArrayRef<Module::ModuleFlagEntry> ModuleFlags, + Mangler *Mang, const TargetMachine &TM) const { + MDNode *LinkerOptions = 0; + + // Look for the "Linker Options" flag, since it's the only one we support. + for (ArrayRef<Module::ModuleFlagEntry>::iterator + i = ModuleFlags.begin(), e = ModuleFlags.end(); i != e; ++i) { + const Module::ModuleFlagEntry &MFE = *i; + StringRef Key = MFE.Key->getString(); + Value *Val = MFE.Val; + if (Key == "Linker Options") { + LinkerOptions = cast<MDNode>(Val); + break; + } + } + if (!LinkerOptions) + return; + + // Emit the linker options to the linker .drectve section. According to the + // spec, this section is a space-separated string containing flags for linker. + const MCSection *Sec = getDrectveSection(); + Streamer.SwitchSection(Sec); + for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) { + MDNode *MDOptions = cast<MDNode>(LinkerOptions->getOperand(i)); + for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) { + MDString *MDOption = cast<MDString>(MDOptions->getOperand(ii)); + StringRef Op = MDOption->getString(); + // Lead with a space for consistency with our dllexport implementation. + std::string Escaped(" "); + if (Op.find(" ") != StringRef::npos) { + // The PE-COFF spec says args with spaces must be quoted. It doesn't say + // how to escape quotes, but it probably uses this algorithm: + // http://msdn.microsoft.com/en-us/library/17w5ykft(v=vs.85).aspx + // FIXME: Reuse escaping code from Support/Windows/Program.inc + Escaped.push_back('\"'); + Escaped.append(Op); + Escaped.push_back('\"'); + } else { + Escaped.append(Op); + } + Streamer.EmitBytes(Escaped); + } + } +} diff --git a/test/MC/COFF/linker-options.ll b/test/MC/COFF/linker-options.ll new file mode 100755 index 0000000..de11941 --- /dev/null +++ b/test/MC/COFF/linker-options.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -mtriple=i386-pc-win32 -filetype=asm -o - %s | FileCheck %s + +!0 = metadata !{ i32 6, metadata !"Linker Options", + metadata !{ + metadata !{ metadata !"/DEFAULTLIB:msvcrt.lib" }, + metadata !{ metadata !"/DEFAULTLIB:msvcrt.lib", + metadata !"/DEFAULTLIB:secur32.lib" }, + metadata !{ metadata !"/with spaces" } } } + +!llvm.module.flags = !{ !0 } + +define dllexport void @foo() { + ret void +} + +; CHECK: .section .drectve,"r" +; CHECK: .ascii " /DEFAULTLIB:msvcrt.lib" +; CHECK: .ascii " /DEFAULTLIB:msvcrt.lib" +; CHECK: .ascii " /DEFAULTLIB:secur32.lib" +; CHECK: .ascii " \"/with spaces\"" +; CHECK: .ascii " /EXPORT:_foo" |