[mc-coff] Forward Linker Option flags into the .drectve section
authorReid Kleckner <reid@kleckner.net>
Thu, 25 Apr 2013 19:34:41 +0000 (19:34 +0000)
committerReid Kleckner <reid@kleckner.net>
Thu, 25 Apr 2013 19:34:41 +0000 (19:34 +0000)
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

include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
lib/CodeGen/TargetLoweringObjectFileImpl.cpp
test/MC/COFF/linker-options.ll [new file with mode: 0755]

index e7098e48bf060b7aae4383608b099866c3160d01..5b22c9c685ae600bd1ece1a6491106254de12580 100644 (file)
@@ -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
index 3bdca4c64078283a91551acad415d7acf01abe6d..678698ae5918d13768cc91271c002bddf598f370 100644 (file)
@@ -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 (executable)
index 0000000..de11941
--- /dev/null
@@ -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"