IR: Replace the "Linker Options" module flag with "llvm.linker.options" named metadata.

The new metadata is easier to manipulate than module flags.

Differential Revision: https://reviews.llvm.org/D31349

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305227 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Peter Collingbourne 2017-06-12 20:10:48 +00:00
parent fd2310ef5b
commit 9283a09c18
18 changed files with 113 additions and 114 deletions

View File

@ -5352,40 +5352,6 @@ Some important flag interactions:
- A module with ``Objective-C Garbage Collection`` set to 0 cannot be
merged with a module with ``Objective-C GC Only`` set to 6.
Automatic Linker Flags Module Flags Metadata
--------------------------------------------
Some targets support embedding flags to the linker inside individual object
files. Typically this is used in conjunction with language extensions which
allow source files to explicitly declare the libraries they depend on, and have
these automatically be transmitted to the linker via object files.
These flags are encoded in the IR using metadata in the module flags section,
using the ``Linker Options`` key. The merge behavior for this flag is required
to be ``AppendUnique``, and the value for the key is expected to be a metadata
node which should be a list of other metadata nodes, each of which should be a
list of metadata strings defining linker options.
For example, the following metadata section specifies two separate sets of
linker options, presumably to link against ``libz`` and the ``Cocoa``
framework::
!0 = !{ i32 6, !"Linker Options",
!{
!{ !"-lz" },
!{ !"-framework", !"Cocoa" } } }
!llvm.module.flags = !{ !0 }
The metadata encoding as lists of lists of options, as opposed to a collapsed
list of options, is chosen so that the IR encoding can use multiple option
strings to specify e.g., a single library, while still having that specifier be
preserved as an atomic element that can be recognized by a target specific
assembly writer or object file emitter.
Each individual option is required to be either a valid option for the target's
linker, or an option that is reserved by the target specific assembly writer or
object file emitter. No other aspect of these options is defined by the IR.
C type width Module Flags Metadata
----------------------------------
@ -5422,6 +5388,37 @@ enum is the smallest type which can represent all of its values::
!0 = !{i32 1, !"short_wchar", i32 1}
!1 = !{i32 1, !"short_enum", i32 0}
Automatic Linker Flags Named Metadata
=====================================
Some targets support embedding flags to the linker inside individual object
files. Typically this is used in conjunction with language extensions which
allow source files to explicitly declare the libraries they depend on, and have
these automatically be transmitted to the linker via object files.
These flags are encoded in the IR using named metadata with the name
``!llvm.linker.options``. Each operand is expected to be a metadata node
which should be a list of other metadata nodes, each of which should be a
list of metadata strings defining linker options.
For example, the following metadata section specifies two separate sets of
linker options, presumably to link against ``libz`` and the ``Cocoa``
framework::
!0 = !{ !"-lz" },
!1 = !{ !"-framework", !"Cocoa" } } }
!llvm.linker.options = !{ !0, !1 }
The metadata encoding as lists of lists of options, as opposed to a collapsed
list of options, is chosen so that the IR encoding can use multiple option
strings to specify e.g., a single library, while still having that specifier be
preserved as an atomic element that can be recognized by a target specific
assembly writer or object file emitter.
Each individual option is required to be either a valid option for the target's
linker, or an option that is reserved by the target specific assembly writer or
object file emitter. No other aspect of these options is defined by the IR.
.. _intrinsicglobalvariables:
Intrinsic Global Variables

View File

@ -42,9 +42,8 @@ public:
~TargetLoweringObjectFileELF() override = default;
/// Emit Obj-C garbage collection and linker options.
void emitModuleFlags(MCStreamer &Streamer,
ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
const TargetMachine &TM) const override;
void emitModuleMetadata(MCStreamer &Streamer, Module &M,
const TargetMachine &TM) const override;
void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM,
const MCSymbol *Sym) const override;
@ -99,9 +98,8 @@ public:
void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
/// Emit the module flags that specify the garbage collection information.
void emitModuleFlags(MCStreamer &Streamer,
ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
const TargetMachine &TM) const override;
void emitModuleMetadata(MCStreamer &Streamer, Module &M,
const TargetMachine &TM) const override;
MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
const TargetMachine &TM) const override;
@ -155,9 +153,8 @@ public:
const TargetMachine &TM) const override;
/// Emit Obj-C garbage collection and linker options.
void emitModuleFlags(MCStreamer &Streamer,
ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
const TargetMachine &TM) const override;
void emitModuleMetadata(MCStreamer &Streamer, Module &M,
const TargetMachine &TM) const override;
MCSection *getStaticCtorSection(unsigned Priority,
const MCSymbol *KeySym) const override;

View File

@ -158,7 +158,7 @@ public:
private:
/// Parse metadata from the module
// FIXME: it only parses "Linker Options" metadata at the moment
// FIXME: it only parses "llvm.linker.options" metadata at the moment
void parseMetadata();
/// Parse the symbols from the module and model-level ASM and add them to

View File

@ -70,10 +70,9 @@ public:
virtual void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM,
const MCSymbol *Sym) const;
/// Emit the module flags that the platform cares about.
virtual void emitModuleFlags(MCStreamer &Streamer,
ArrayRef<Module::ModuleFlagEntry> Flags,
const TargetMachine &TM) const {}
/// Emit the module-level metadata that the platform cares about.
virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M,
const TargetMachine &TM) const {}
/// Given a constant with the SectionKind, return a section that it should be
/// placed in.

View File

@ -2608,6 +2608,16 @@ Error BitcodeReader::materializeMetadata() {
if (Error Err = MDLoader->parseModuleMetadata())
return Err;
}
// Upgrade "Linker Options" module flag to "llvm.linker.options" module-level
// metadata.
if (Metadata *Val = TheModule->getModuleFlag("Linker Options")) {
NamedMDNode *LinkerOpts =
TheModule->getOrInsertNamedMetadata("llvm.linker.options");
for (const MDOperand &MDOptions : cast<MDNode>(Val)->operands())
LinkerOpts->addOperand(cast<MDNode>(MDOptions));
}
DeferredMetadataInfo.clear();
return Error::success();
}

View File

@ -1286,11 +1286,7 @@ bool AsmPrinter::doFinalization(Module &M) {
const TargetLoweringObjectFile &TLOF = getObjFileLowering();
// Emit module flags.
SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
M.getModuleFlagsMetadata(ModuleFlags);
if (!ModuleFlags.empty())
TLOF.emitModuleFlags(*OutStreamer, ModuleFlags, TM);
TLOF.emitModuleMetadata(*OutStreamer, M, TM);
if (TM.getTargetTriple().isOSBinFormatELF()) {
MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();

View File

@ -61,9 +61,11 @@
using namespace llvm;
using namespace dwarf;
static void GetObjCImageInfo(ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
unsigned &Version, unsigned &Flags,
static void GetObjCImageInfo(Module &M, unsigned &Version, unsigned &Flags,
StringRef &Section) {
SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
M.getModuleFlagsMetadata(ModuleFlags);
for (const auto &MFE: ModuleFlags) {
// Ignore flags with 'Require' behaviour.
if (MFE.Behavior == Module::Require)
@ -88,14 +90,13 @@ static void GetObjCImageInfo(ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
// ELF
//===----------------------------------------------------------------------===//
void TargetLoweringObjectFileELF::emitModuleFlags(
MCStreamer &Streamer, ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
const TargetMachine &TM) const {
void TargetLoweringObjectFileELF::emitModuleMetadata(
MCStreamer &Streamer, Module &M, const TargetMachine &TM) const {
unsigned Version = 0;
unsigned Flags = 0;
StringRef Section;
GetObjCImageInfo(ModuleFlags, Version, Flags, Section);
GetObjCImageInfo(M, Version, Flags, Section);
if (Section.empty())
return;
@ -618,20 +619,10 @@ void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx,
}
}
/// emitModuleFlags - Perform code emission for module flags.
void TargetLoweringObjectFileMachO::emitModuleFlags(
MCStreamer &Streamer, ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
const TargetMachine &TM) const {
MDNode *LinkerOptions = nullptr;
for (const auto &MFE : ModuleFlags) {
StringRef Key = MFE.Key->getString();
if (Key == "Linker Options")
LinkerOptions = cast<MDNode>(MFE.Val);
}
void TargetLoweringObjectFileMachO::emitModuleMetadata(
MCStreamer &Streamer, Module &M, const TargetMachine &TM) const {
// Emit the linker options if present.
if (LinkerOptions) {
if (auto *LinkerOptions = M.getNamedMetadata("llvm.linker.options")) {
for (const auto &Option : LinkerOptions->operands()) {
SmallVector<std::string, 4> StrOptions;
for (const auto &Piece : cast<MDNode>(Option)->operands())
@ -643,7 +634,8 @@ void TargetLoweringObjectFileMachO::emitModuleFlags(
unsigned VersionVal = 0;
unsigned ImageInfoFlags = 0;
StringRef SectionVal;
GetObjCImageInfo(ModuleFlags, VersionVal, ImageInfoFlags, SectionVal);
GetObjCImageInfo(M, VersionVal, ImageInfoFlags, SectionVal);
// The section is mandatory. If we don't have it, then we don't have GC info.
if (SectionVal.empty())
@ -1159,18 +1151,9 @@ MCSection *TargetLoweringObjectFileCOFF::getSectionForJumpTable(
COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID);
}
void TargetLoweringObjectFileCOFF::emitModuleFlags(
MCStreamer &Streamer, ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
const TargetMachine &TM) const {
MDNode *LinkerOptions = nullptr;
for (const auto &MFE : ModuleFlags) {
StringRef Key = MFE.Key->getString();
if (Key == "Linker Options")
LinkerOptions = cast<MDNode>(MFE.Val);
}
if (LinkerOptions) {
void TargetLoweringObjectFileCOFF::emitModuleMetadata(
MCStreamer &Streamer, Module &M, const TargetMachine &TM) const {
if (NamedMDNode *LinkerOptions = M.getNamedMetadata("llvm.linker.options")) {
// Emit the linker options to the linker .drectve section. According to the
// spec, this section is a space-separated string containing flags for
// linker.
@ -1190,7 +1173,7 @@ void TargetLoweringObjectFileCOFF::emitModuleFlags(
unsigned Flags = 0;
StringRef Section;
GetObjCImageInfo(ModuleFlags, Version, Flags, Section);
GetObjCImageInfo(M, Version, Flags, Section);
if (Section.empty())
return;

View File

@ -1330,6 +1330,14 @@ Verifier::visitModuleFlag(const MDNode *Op,
= mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2));
Assert(Value, "wchar_size metadata requires constant integer argument");
}
if (ID->getString() == "Linker Options") {
// If the llvm.linker.options named metadata exists, we assume that the
// bitcode reader has upgraded the module flag. Otherwise the flag might
// have been created by a client directly.
Assert(M.getNamedMetadata("llvm.linker.options"),
"'Linker Options' named metadata no longer supported");
}
}
/// Return true if this attribute kind only applies to functions.

View File

@ -637,10 +637,10 @@ void LTOModule::parseMetadata() {
raw_string_ostream OS(LinkerOpts);
// Linker Options
if (Metadata *Val = getModule().getModuleFlag("Linker Options")) {
MDNode *LinkerOptions = cast<MDNode>(Val);
if (NamedMDNode *LinkerOptions =
getModule().getNamedMetadata("llvm.linker.options")) {
for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) {
MDNode *MDOptions = cast<MDNode>(LinkerOptions->getOperand(i));
MDNode *MDOptions = LinkerOptions->getOperand(i);
for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) {
MDString *MDOption = cast<MDString>(MDOptions->getOperand(ii));
OS << " " << MDOption->getString();

View File

@ -109,9 +109,9 @@ Error Builder::addModule(Module *M) {
if (TT.isOSBinFormatCOFF()) {
if (auto E = M->materializeMetadata())
return E;
if (Metadata *Val = M->getModuleFlag("Linker Options")) {
MDNode *LinkerOptions = cast<MDNode>(Val);
for (const MDOperand &MDOptions : LinkerOptions->operands())
if (NamedMDNode *LinkerOptions =
M->getNamedMetadata("llvm.linker.options")) {
for (MDNode *MDOptions : LinkerOptions->operands())
for (const MDOperand &MDOption : cast<MDNode>(MDOptions)->operands())
COFFLinkerOptsOS << " " << cast<MDString>(MDOption)->getString();
}

View File

@ -0,0 +1,15 @@
; RUN: llvm-as -disable-verify < %s | llvm-dis | FileCheck %s
; RUN: not llvm-as < %s 2>&1 | FileCheck --check-prefix=ERROR %s
; CHECK: !llvm.linker.options = !{!2, !3}
; CHECK: !2 = !{!"/DEFAULTLIB:libcmtd.lib"}
; CHECK: !3 = !{!"/DEFAULTLIB:oldnames.lib"}
; ERROR: 'Linker Options' named metadata no longer supported
!0 = !{i32 6, !"Linker Options", !1}
!1 = !{!2, !3}
!2 = !{!"/DEFAULTLIB:libcmtd.lib"}
!3 = !{!"/DEFAULTLIB:oldnames.lib"}
!llvm.module.flags = !{!0}

View File

@ -65,7 +65,7 @@ attributes #1 = { nounwind readnone }
!llvm.dbg.cu = !{!2, !11}
!llvm.ident = !{!13, !13}
!llvm.module.flags = !{!14, !18, !19, !20}
!llvm.module.flags = !{!18, !19, !20}
!0 = !DIGlobalVariableExpression(var: !1)
!1 = distinct !DIGlobalVariable(name: "a", linkageName: "\01?a@@3TYYSTYPE@@A", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true)
@ -81,10 +81,6 @@ attributes #1 = { nounwind readnone }
!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !12, producer: "clang version 5.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4)
!12 = !DIFile(filename: "b.cpp", directory: "C:\5Csrc\5Cllvm-project\5Cbuild", checksumkind: CSK_MD5, checksum: "9cfd390d8827beab36769147bb037abc")
!13 = !{!"clang version 5.0.0 "}
!14 = !{i32 6, !"Linker Options", !15}
!15 = !{!16, !17}
!16 = !{!"/DEFAULTLIB:libcmt.lib"}
!17 = !{!"/DEFAULTLIB:oldnames.lib"}
!18 = !{i32 2, !"CodeView", i32 1}
!19 = !{i32 2, !"Debug Info Version", i32 3}
!20 = !{i32 1, !"PIC Level", i32 2}

View File

@ -39,12 +39,11 @@ define void @main(i32* %i.i) !dbg !16 {
ret void
}
!llvm.module.flags = !{!0, !1, !2}
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!4}
!0 = !{i32 2, !"CodeView", i32 1}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = !{i32 6, !"Linker Options", !{}}
!4 = distinct !DICompileUnit(language: DW_LANG_D, file: !5, producer: "LDC (http://wiki.dlang.org/LDC)", isOptimized: false, runtimeVersion: 1, emissionKind: FullDebug)
!5 = !DIFile(filename: "opover2.d", directory: "C:\5CLDC\5Cninja-ldc\5C..\5Cldc\5Ctests\5Cd2\5Cdmd-testsuite\5Crunnable")
!6 = !DILocation(line: 302, column: 9, scope: !7, inlinedAt: !15)

View File

@ -6,8 +6,8 @@ target triple = "x86_64-unknown-linux-gnu"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
; CHECK-NOT: linker opts:
!0 = !{i32 6, !"Linker Options", !{!{!"/include:foo"}}}
!llvm.module.flags = !{ !0 }
!0 = !{!"/include:foo"}
!llvm.linker.options = !{ !0 }
@g1 = global i32 0

View File

@ -9,8 +9,8 @@ target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
source_filename = "src.c"
; CHECK: linker opts: /include:foo
!0 = !{i32 6, !"Linker Options", !{!{!"/include:foo"}}}
!llvm.module.flags = !{ !0 }
!0 = !{!"/include:foo"}
!llvm.linker.options = !{ !0 }
; CHECK: D------X _fun
define i32 @fun() {

View File

@ -13,7 +13,7 @@ entry:
attributes #0 = { nounwind sspstrong "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !7, !8}
!llvm.module.flags = !{!7, !8}
!llvm.ident = !{!9}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 4.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
@ -35,10 +35,6 @@ attributes #0 = { nounwind sspstrong "correctly-rounded-divide-sqrt-fp-math"="fa
; CHECK-NOT: .short 4412 # Record kind: S_COMPILE3
!1 = !DIFile(filename: "D:\5Csrc\5Cscopes\5Cfoo.cpp", directory: "D:\5Csrc\5Cscopes\5Cclang")
!2 = !{}
!3 = !{i32 6, !"Linker Options", !4}
!4 = !{!5, !6}
!5 = !{!"/DEFAULTLIB:libcmtd.lib"}
!6 = !{!"/DEFAULTLIB:oldnames.lib"}
!7 = !{i32 2, !"CodeView", i32 1}
!8 = !{i32 2, !"Debug Info Version", i32 3}
!9 = !{!"clang version 4.0.0 "}

View File

@ -1,8 +1,10 @@
; RUN: llc -O0 -mtriple=i386-pc-win32 -filetype=asm -o - %s | FileCheck %s
!0 = !{i32 6, !"Linker Options", !{!{!"/DEFAULTLIB:msvcrt.lib"}, !{!"/DEFAULTLIB:msvcrt.lib", !"/DEFAULTLIB:secur32.lib"}, !{!"/DEFAULTLIB:\22C:\5Cpath to\5Casan_rt.lib\22"}, !{!"\22/with spaces\22"}}}
!llvm.module.flags = !{ !0 }
!0 = !{!"/DEFAULTLIB:msvcrt.lib"}
!1 = !{!"/DEFAULTLIB:msvcrt.lib", !"/DEFAULTLIB:secur32.lib"}
!2 = !{!"/DEFAULTLIB:\22C:\5Cpath to\5Casan_rt.lib\22"}
!3 = !{!"\22/with spaces\22"}
!llvm.linker.options = !{!0, !1, !2, !3}
define dllexport void @foo() {
ret void

View File

@ -27,6 +27,7 @@
; CHECK-OBJ: ]
; CHECK-OBJ: }
!0 = !{i32 6, !"Linker Options", !{!{!"-lz"}, !{!"-framework", !"Cocoa"}, !{!"-lmath"}}}
!llvm.module.flags = !{ !0 }
!0 = !{!"-lz"}
!1 = !{!"-framework", !"Cocoa"}
!2 = !{!"-lmath"}
!llvm.linker.options = !{!0, !1, !2}