From 4b5581530393e647d559360f8c6f229c05aca94f Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 25 Apr 2013 19:34:41 +0000 Subject: [PATCH] [mc-coff] Forward Linker Option flags into the .drectve section Summary: This is modelled on the Mach-O linker options implementation and should support a Clang implementation of #pragma comment(lib/linker). Reviewers: rafael CC: llvm-commits Differential Revision: http://llvm-reviews.chandlerc.com/D724 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180569 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../CodeGen/TargetLoweringObjectFileImpl.h | 6 +++ lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 46 +++++++++++++++++++ test/MC/COFF/linker-options.ll | 21 +++++++++ 3 files changed, 73 insertions(+) create mode 100755 test/MC/COFF/linker-options.ll diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index e7098e48bf0..5b22c9c685a 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 ModuleFlags, + Mangler *Mang, const TargetMachine &TM) const; }; } // end namespace llvm diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 3bdca4c6407..678698ae591 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 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::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(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(LinkerOptions->getOperand(i)); + for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) { + MDString *MDOption = cast(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 00000000000..de119417447 --- /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" -- 2.34.1