Skip to content

Commit

Permalink
IR: Replace the "Linker Options" module flag with "llvm.linker.option…
Browse files Browse the repository at this point in the history
…s" named metadata.

The new metadata is easier to manipulate than module flags.

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

llvm-svn: 305227
  • Loading branch information
pcc committed Jun 12, 2017
1 parent 30b2c6b commit 89061b2
Show file tree
Hide file tree
Showing 32 changed files with 141 additions and 168 deletions.
10 changes: 5 additions & 5 deletions clang/lib/CodeGen/CodeGenModule.cpp
Expand Up @@ -1243,7 +1243,7 @@ void CodeGenModule::AddDependentLib(StringRef Lib) {
/// \brief Add link options implied by the given module, including modules
/// it depends on, using a postorder walk.
static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod,
SmallVectorImpl<llvm::Metadata *> &Metadata,
SmallVectorImpl<llvm::MDNode *> &Metadata,
llvm::SmallPtrSet<Module *, 16> &Visited) {
// Import this module's parent.
if (Mod->Parent && Visited.insert(Mod->Parent).second) {
Expand Down Expand Up @@ -1331,7 +1331,7 @@ void CodeGenModule::EmitModuleLinkOptions() {
// Add link options for all of the imported modules in reverse topological
// order. We don't do anything to try to order import link flags with respect
// to linker options inserted by things like #pragma comment().
SmallVector<llvm::Metadata *, 16> MetadataArgs;
SmallVector<llvm::MDNode *, 16> MetadataArgs;
Visited.clear();
for (Module *M : LinkModules)
if (Visited.insert(M).second)
Expand All @@ -1340,9 +1340,9 @@ void CodeGenModule::EmitModuleLinkOptions() {
LinkerOptionsMetadata.append(MetadataArgs.begin(), MetadataArgs.end());

// Add the linker options metadata flag.
getModule().addModuleFlag(llvm::Module::AppendUnique, "Linker Options",
llvm::MDNode::get(getLLVMContext(),
LinkerOptionsMetadata));
auto *NMD = getModule().getOrInsertNamedMetadata("llvm.linker.options");
for (auto *MD : LinkerOptionsMetadata)
NMD->addOperand(MD);
}

void CodeGenModule::EmitDeferred() {
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/CodeGen/CodeGenModule.h
Expand Up @@ -429,7 +429,7 @@ class CodeGenModule : public CodeGenTypeCache {
llvm::SmallPtrSet<clang::Module *, 16> EmittedModuleInitializers;

/// \brief A vector of metadata strings.
SmallVector<llvm::Metadata *, 16> LinkerOptionsMetadata;
SmallVector<llvm::MDNode *, 16> LinkerOptionsMetadata;

/// @name Cache for Objective-C runtime types
/// @{
Expand Down Expand Up @@ -1058,13 +1058,14 @@ class CodeGenModule : public CodeGenTypeCache {

void RefreshTypeCacheForClass(const CXXRecordDecl *Class);

/// \brief Appends Opts to the "Linker Options" metadata value.
/// \brief Appends Opts to the "llvm.linker.options" metadata value.
void AppendLinkerOptions(StringRef Opts);

/// \brief Appends a detect mismatch command to the linker options.
void AddDetectMismatch(StringRef Name, StringRef Value);

/// \brief Appends a dependent lib to the "Linker Options" metadata value.
/// \brief Appends a dependent lib to the "llvm.linker.options" metadata
/// value.
void AddDependentLib(StringRef Lib);

llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD);
Expand Down
8 changes: 2 additions & 6 deletions clang/test/CodeGen/dependent-lib.c
Expand Up @@ -3,14 +3,10 @@
// RUN: %clang_cc1 %s --dependent-lib=msvcrt -triple x86_64-pc-win32 -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 %s --dependent-lib=msvcrt -triple i686-pc-linux -emit-llvm -o - | FileCheck -check-prefix LINUX %s

// CHECK: !llvm.module.flags = !{{{.*}}}
// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]}
// CHECK: ![[link_opts]] = !{![[msvcrt:[0-9]+]]}
// CHECK: !llvm.linker.options = !{![[msvcrt:[0-9]+]]}
// CHECK: ![[msvcrt]] = !{!"/DEFAULTLIB:msvcrt.lib"}

// LINUX: !llvm.module.flags = !{{{.*}}}
// LINUX: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]}
// LINUX: ![[link_opts]] = !{![[msvcrt:[0-9]+]]}
// LINUX: !llvm.linker.options = !{![[msvcrt:[0-9]+]]}
// LINUX: ![[msvcrt]] = !{!"-lmsvcrt"}

int f();
4 changes: 1 addition & 3 deletions clang/test/CodeGen/linker-option.c
@@ -1,8 +1,6 @@
// RUN: %clang_cc1 %s --linker-option=/include:foo -triple i686-pc-win32 -emit-llvm -o - | FileCheck %s

// CHECK: !llvm.module.flags = !{{{.*}}}
// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]}
// CHECK: ![[link_opts]] = !{![[msvcrt:[0-9]+]]}
// CHECK: !llvm.linker.options = !{![[msvcrt:[0-9]+]]}
// CHECK: ![[msvcrt]] = !{!"/include:foo"}

int f();
4 changes: 1 addition & 3 deletions clang/test/CodeGen/pragma-comment.c
Expand Up @@ -14,9 +14,7 @@
#pragma comment(linker," /bar=" BAR)
#pragma comment(linker," /foo=\"foo bar\"")

// CHECK: !llvm.module.flags = !{{{.*}}}
// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]}
// CHECK: ![[link_opts]] = !{![[msvcrt:[0-9]+]], ![[kernel32:[0-9]+]], ![[USER32:[0-9]+]], ![[space:[0-9]+]], ![[bar:[0-9]+]], ![[foo:[0-9]+]]}
// CHECK: !llvm.linker.options = !{![[msvcrt:[0-9]+]], ![[kernel32:[0-9]+]], ![[USER32:[0-9]+]], ![[space:[0-9]+]], ![[bar:[0-9]+]], ![[foo:[0-9]+]]}
// CHECK: ![[msvcrt]] = !{!"/DEFAULTLIB:msvcrt.lib"}
// CHECK: ![[kernel32]] = !{!"/DEFAULTLIB:kernel32.lib"}
// CHECK: ![[USER32]] = !{!"/DEFAULTLIB:USER32.LIB"}
Expand Down
4 changes: 1 addition & 3 deletions clang/test/CodeGen/pragma-detect_mismatch.c
Expand Up @@ -6,8 +6,6 @@
#define BAR "2"
#pragma detect_mismatch("test2", BAR)

// CHECK: !llvm.module.flags = !{{{.*}}}
// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]}
// CHECK: ![[link_opts]] = !{![[test:[0-9]+]], ![[test2:[0-9]+]]}
// CHECK: !llvm.linker.options = !{![[test:[0-9]+]], ![[test2:[0-9]+]]}
// CHECK: ![[test]] = !{!"/FAILIFMISMATCH:\22test=1\22"}
// CHECK: ![[test2]] = !{!"/FAILIFMISMATCH:\22test2=2\22"}
4 changes: 1 addition & 3 deletions clang/test/CodeGenCXX/ms-thread_local.cpp
Expand Up @@ -27,7 +27,5 @@ A f() {
return c;
}

// CHECK: !llvm.module.flags = !{{{.*}}}
// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]}
// CHECK: ![[link_opts]] = !{![[dyn_tls_init:[0-9]+]]}
// CHECK: !llvm.linker.options = !{![[dyn_tls_init:[0-9]+]]}
// CHECK: ![[dyn_tls_init]] = !{!"/include:___dyn_tls_init@12"}
5 changes: 2 additions & 3 deletions clang/test/CodeGenObjC/availability-cf-link-guard.m
Expand Up @@ -37,9 +37,8 @@ void use_at_available() {
// CHECK_NO_GUARD-NOT: __clang_at_available_requires_core_foundation_framework
// CHECK_NO_GUARD-NOT: CFBundleGetVersionNumber

// CHECK_LINK_OPT: !"Linker Options", ![[OPTS:[0-9]+]]
// CHECK_LINK_OPT: ![[OPTS]] = !{![[FRAMEWORK:[0-9]+]]
// CHECK_LINK_OPT: !llvm.linker.options = !{![[FRAMEWORK:[0-9]+]]
// CHECK_LINK_OPT: ![[FRAMEWORK]] = !{!"-framework", !"CoreFoundation"}

// CHECK_NO_GUARD-NOT: "Linker Options"
// CHECK_NO_GUARD-NOT: !llvm.linker.options
// CHECK_NO_GUARD-NOT: CoreFoundation
6 changes: 2 additions & 4 deletions clang/test/Modules/autolink.m
Expand Up @@ -36,9 +36,7 @@ int use_autolink_sub3() {

// NOTE: "autolink_sub" is intentionally not linked.

// CHECK: !llvm.module.flags = !{{{.*}}}
// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[AUTOLINK_OPTIONS:[0-9]+]]}
// CHECK: ![[AUTOLINK_OPTIONS]] = !{![[AUTOLINK_PCH:[0-9]+]], ![[AUTOLINK_FRAMEWORK:[0-9]+]], ![[AUTOLINK:[0-9]+]], ![[DEPENDSONMODULE:[0-9]+]], ![[MODULE:[0-9]+]], ![[NOUMBRELLA:[0-9]+]]}
// CHECK: !llvm.linker.options = !{![[AUTOLINK_PCH:[0-9]+]], ![[AUTOLINK_FRAMEWORK:[0-9]+]], ![[AUTOLINK:[0-9]+]], ![[DEPENDSONMODULE:[0-9]+]], ![[MODULE:[0-9]+]], ![[NOUMBRELLA:[0-9]+]]}
// CHECK: ![[AUTOLINK_PCH]] = !{!"{{(\\01|-l|/DEFAULTLIB:)}}autolink_from_pch{{(\.lib)?}}"}
// CHECK: ![[AUTOLINK_FRAMEWORK]] = !{!"-framework", !"autolink_framework"}
// CHECK: ![[AUTOLINK]] = !{!"{{(\\01|-l|/DEFAULTLIB:)}}autolink{{(\.lib)?}}"}
Expand All @@ -47,4 +45,4 @@ int use_autolink_sub3() {
// CHECK: ![[NOUMBRELLA]] = !{!"-framework", !"NoUmbrella"}

// CHECK-AUTOLINK-DISABLED: !llvm.module.flags
// CHECK-AUTOLINK-DISABLED-NOT: "Linker Options"
// CHECK-AUTOLINK-DISABLED-NOT: !llvm.linker.options
6 changes: 2 additions & 4 deletions clang/test/Modules/autolinkTBD.m
Expand Up @@ -8,10 +8,8 @@ int f() {
return foo();
}

// CHECK: !llvm.module.flags = !{{{.*}}}
// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[AUTOLINK_OPTIONS:[0-9]+]]}
// CHECK: ![[AUTOLINK_OPTIONS]] = !{![[AUTOLINK_FRAMEWORK:[0-9]+]]}
// CHECK: !llvm.linker.options = !{![[AUTOLINK_FRAMEWORK:[0-9]+]]}
// CHECK: ![[AUTOLINK_FRAMEWORK]] = !{!"-framework", !"AutolinkTBD"}

// CHECK-AUTOLINK-DISABLED: !llvm.module.flags
// CHECK-AUTOLINK-DISABLED-NOT: "Linker Options"
// CHECK-AUTOLINK-DISABLED-NOT: !llvm.linker.options
3 changes: 1 addition & 2 deletions clang/test/Modules/module-impl-with-link.c
@@ -1,7 +1,6 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -fmodule-name=Clib %s -I %S/Inputs/module-impl-with-link -emit-llvm -o - | FileCheck %s
#include "foo.h"
// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[LINK_OPTIONS:[0-9]+]]}
// Make sure we don't generate linker option for module Clib since this TU is
// an implementation of Clib.
// CHECK: ![[LINK_OPTIONS]] = !{}
// CHECK: !llvm.linker.options = !{}
7 changes: 2 additions & 5 deletions lld/test/COFF/Inputs/constant-export.ll
Expand Up @@ -3,8 +3,5 @@ target triple = "i686-unknown-windows-msvc18.0.0"

@__CFConstantStringClassReference = common global [32 x i32] zeroinitializer, align 4

!llvm.module.flags = !{!0}

!0 = !{i32 6, !"Linker Options", !1}
!1 = !{!2}
!2 = !{!" -export:___CFConstantStringClassReference,CONSTANT"}
!llvm.linker.options = !{!0}
!0 = !{!" -export:___CFConstantStringClassReference,CONSTANT"}
7 changes: 2 additions & 5 deletions lld/test/COFF/include-lto.ll
Expand Up @@ -17,8 +17,5 @@ define i32 @foo() {
ret i32 0
}

!llvm.module.flags = !{!0}

!0 = !{i32 6, !"Linker Options", !1}
!1 = !{!2}
!2 = !{!"/INCLUDE:foo"}
!llvm.linker.options = !{!0}
!0 = !{!"/INCLUDE:foo"}
7 changes: 2 additions & 5 deletions lld/test/COFF/lto-linker-opts.ll
Expand Up @@ -4,8 +4,5 @@
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc"

!llvm.module.flags = !{!0}

!0 = !{i32 6, !"Linker Options", !1}
!1 = !{!2}
!2 = !{!"/DEFAULTLIB:ret42.lib"}
!llvm.linker.options = !{!0}
!0 = !{!"/DEFAULTLIB:ret42.lib"}
65 changes: 31 additions & 34 deletions llvm/docs/LangRef.rst
Expand Up @@ -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
----------------------------------

Expand Down Expand Up @@ -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
Expand Down
15 changes: 6 additions & 9 deletions llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
Expand Up @@ -42,9 +42,8 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
~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;
Expand Down Expand Up @@ -99,9 +98,8 @@ class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile {
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;
Expand Down Expand Up @@ -155,9 +153,8 @@ class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile {
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;
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/LTO/legacy/LTOModule.h
Expand Up @@ -158,7 +158,7 @@ struct LTOModule {

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
Expand Down
7 changes: 3 additions & 4 deletions llvm/include/llvm/Target/TargetLoweringObjectFile.h
Expand Up @@ -70,10 +70,9 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
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.
Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/Bitcode/Reader/BitcodeReader.cpp
Expand Up @@ -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();
}
Expand Down
6 changes: 1 addition & 5 deletions llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
Expand Up @@ -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>();
Expand Down

0 comments on commit 89061b2

Please sign in to comment.