diff options
| author | Saleem Abdulrasool <compnerd@compnerd.org> | 2018-01-20 00:28:02 +0000 |
|---|---|---|
| committer | Saleem Abdulrasool <compnerd@compnerd.org> | 2018-01-20 00:28:02 +0000 |
| commit | 99f479abcf2c9b36daad04eb91cd0aafa659bb1d (patch) | |
| tree | 331bb5b7a64e0b50fc139438a3ab4277080f188f /llvm/lib/CodeGen | |
| parent | 08bd14803cf6a89700db914b68affe98879f4049 (diff) | |
| download | bcm5719-llvm-99f479abcf2c9b36daad04eb91cd0aafa659bb1d.tar.gz bcm5719-llvm-99f479abcf2c9b36daad04eb91cd0aafa659bb1d.zip | |
CodeGen: handle llvm.used properly for COFF
`llvm.used` contains a list of pointers to named values which the
compiler, assembler, and linker are required to treat as if there is a
reference that they cannot see. Ensure that the symbols are preserved
by adding an explicit `-include` reference to the linker command.
llvm-svn: 323017
Diffstat (limited to 'llvm/lib/CodeGen')
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 30 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 5 |
2 files changed, 35 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 2a20c64e82c..87d91377dc9 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1434,6 +1434,7 @@ bool AsmPrinter::doFinalization(Module &M) { // Emit /EXPORT: flags for each exported global as necessary. const auto &TLOF = getObjFileLowering(); std::string Flags; + for (const GlobalValue &GV : M.global_values()) { raw_string_ostream OS(Flags); TLOF.emitLinkerFlagsForGlobal(OS, &GV); @@ -1444,6 +1445,35 @@ bool AsmPrinter::doFinalization(Module &M) { } Flags.clear(); } + + // Emit /INCLUDE: flags for each used global as necessary. + if (const auto *LU = M.getNamedGlobal("llvm.used")) { + assert(LU->hasInitializer() && + "expected llvm.used to have an initializer"); + assert(isa<ArrayType>(LU->getValueType()) && + "expected llvm.used to be an array type"); + if (const auto *A = cast<ConstantArray>(LU->getInitializer())) { + for (const Value *Op : A->operands()) { + const auto *GV = + cast<GlobalValue>(Op->stripPointerCastsNoFollowAliases()); + // Global symbols with internal linkage are not visible to the linker, + // and thus would cause an error when the linker tried to preserve the + // symbol due to the `/include:` directive. + if (GV->hasInternalLinkage()) + continue; + + raw_string_ostream OS(Flags); + TLOF.emitLinkerFlagsForUsed(OS, GV); + OS.flush(); + + if (!Flags.empty()) { + OutStreamer->SwitchSection(TLOF.getDrectveSection()); + OutStreamer->EmitBytes(Flags); + } + Flags.clear(); + } + } + } } // Allow the target to emit any magic that it wants at the end of the file, diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index bdc4bc0302b..0e90df901fd 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1250,6 +1250,11 @@ void TargetLoweringObjectFileCOFF::emitLinkerFlagsForGlobal( emitLinkerFlagsForGlobalCOFF(OS, GV, getTargetTriple(), getMangler()); } +void TargetLoweringObjectFileCOFF::emitLinkerFlagsForUsed( + raw_ostream &OS, const GlobalValue *GV) const { + emitLinkerFlagsForUsedCOFF(OS, GV, getTargetTriple(), getMangler()); +} + //===----------------------------------------------------------------------===// // Wasm //===----------------------------------------------------------------------===// |

