1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[COFF] Move per-global .drective emission from AsmPrinter to TLOFCOFF

This changes the order of output sections and the output assembly, but
is otherwise NFC.

It simplifies the TLOF interface by removing two COFF-only methods.
This commit is contained in:
Reid Kleckner 2020-09-18 13:43:13 -07:00
parent ea70c5e0ce
commit e747f6900b
7 changed files with 119 additions and 138 deletions

View File

@ -167,12 +167,6 @@ public:
MCSection *getStaticDtorSection(unsigned Priority,
const MCSymbol *KeySym) const override;
void emitLinkerFlagsForGlobal(raw_ostream &OS,
const GlobalValue *GV) const override;
void emitLinkerFlagsForUsed(raw_ostream &OS,
const GlobalValue *GV) const override;
const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
const GlobalValue *RHS,
const TargetMachine &TM) const override;
@ -182,6 +176,9 @@ public:
MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
const Constant *C,
Align &Alignment) const override;
private:
void emitLinkerDirectives(MCStreamer &Streamer, Module &M) const;
};
class TargetLoweringObjectFileWasm : public TargetLoweringObjectFile {

View File

@ -208,12 +208,6 @@ public:
return nullptr;
}
virtual void emitLinkerFlagsForGlobal(raw_ostream &OS,
const GlobalValue *GV) const {}
virtual void emitLinkerFlagsForUsed(raw_ostream &OS,
const GlobalValue *GV) const {}
/// If supported, return the section to use for the llvm.commandline
/// metadata. Otherwise, return nullptr.
virtual MCSection *getSectionForCommandLines() const {

View File

@ -1720,51 +1720,6 @@ bool AsmPrinter::doFinalization(Module &M) {
if (MCSection *S = MAI->getNonexecutableStackSection(OutContext))
OutStreamer->SwitchSection(S);
if (TM.getTargetTriple().isOSBinFormatCOFF()) {
// 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);
OS.flush();
if (!Flags.empty()) {
OutStreamer->SwitchSection(TLOF.getDrectveSection());
OutStreamer->emitBytes(Flags);
}
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->stripPointerCasts());
// Global symbols with internal or private 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->hasLocalLinkage())
continue;
raw_string_ostream OS(Flags);
TLOF.emitLinkerFlagsForUsed(OS, GV);
OS.flush();
if (!Flags.empty()) {
OutStreamer->SwitchSection(TLOF.getDrectveSection());
OutStreamer->emitBytes(Flags);
}
Flags.clear();
}
}
}
}
if (TM.Options.EmitAddrsig) {
// Emit address-significance attributes for all globals.
OutStreamer->emitAddrsig();

View File

@ -1551,21 +1551,7 @@ MCSection *TargetLoweringObjectFileCOFF::getSectionForJumpTable(
void TargetLoweringObjectFileCOFF::emitModuleMetadata(MCStreamer &Streamer,
Module &M) 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.
MCSection *Sec = getDrectveSection();
Streamer.SwitchSection(Sec);
for (const auto *Option : LinkerOptions->operands()) {
for (const auto &Piece : cast<MDNode>(Option)->operands()) {
// Lead with a space for consistency with our dllexport implementation.
std::string Directive(" ");
Directive.append(std::string(cast<MDString>(Piece)->getString()));
Streamer.emitBytes(Directive);
}
}
}
emitLinkerDirectives(Streamer, M);
unsigned Version = 0;
unsigned Flags = 0;
@ -1588,6 +1574,65 @@ void TargetLoweringObjectFileCOFF::emitModuleMetadata(MCStreamer &Streamer,
emitCGProfile(Streamer, M);
}
void TargetLoweringObjectFileCOFF::emitLinkerDirectives(
MCStreamer &Streamer, Module &M) 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.
MCSection *Sec = getDrectveSection();
Streamer.SwitchSection(Sec);
for (const auto *Option : LinkerOptions->operands()) {
for (const auto &Piece : cast<MDNode>(Option)->operands()) {
// Lead with a space for consistency with our dllexport implementation.
std::string Directive(" ");
Directive.append(std::string(cast<MDString>(Piece)->getString()));
Streamer.emitBytes(Directive);
}
}
}
// Emit /EXPORT: flags for each exported global as necessary.
std::string Flags;
for (const GlobalValue &GV : M.global_values()) {
raw_string_ostream OS(Flags);
emitLinkerFlagsForGlobalCOFF(OS, &GV, getTargetTriple(), getMangler());
OS.flush();
if (!Flags.empty()) {
Streamer.SwitchSection(getDrectveSection());
Streamer.emitBytes(Flags);
}
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->stripPointerCasts());
// Global symbols with internal or private 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->hasLocalLinkage())
continue;
raw_string_ostream OS(Flags);
emitLinkerFlagsForUsedCOFF(OS, GV, getTargetTriple(), getMangler());
OS.flush();
if (!Flags.empty()) {
Streamer.SwitchSection(getDrectveSection());
Streamer.emitBytes(Flags);
}
Flags.clear();
}
}
}
}
void TargetLoweringObjectFileCOFF::Initialize(MCContext &Ctx,
const TargetMachine &TM) {
TargetLoweringObjectFile::Initialize(Ctx, TM);
@ -1665,16 +1710,6 @@ MCSection *TargetLoweringObjectFileCOFF::getStaticDtorSection(
cast<MCSectionCOFF>(StaticDtorSection));
}
void TargetLoweringObjectFileCOFF::emitLinkerFlagsForGlobal(
raw_ostream &OS, const GlobalValue *GV) const {
emitLinkerFlagsForGlobalCOFF(OS, GV, getTargetTriple(), getMangler());
}
void TargetLoweringObjectFileCOFF::emitLinkerFlagsForUsed(
raw_ostream &OS, const GlobalValue *GV) const {
emitLinkerFlagsForUsedCOFF(OS, GV, getTargetTriple(), getMangler());
}
const MCExpr *TargetLoweringObjectFileCOFF::lowerRelativeReference(
const GlobalValue *LHS, const GlobalValue *RHS,
const TargetMachine &TM) const {

View File

@ -13,9 +13,9 @@ define void @f1(i32 %a1, i32 %a2) {
}
; CHECK: .lcomm .L_MergedGlobals,8,4
; CHECK: .section .drectve,"yn"
; CHECK: .ascii " /EXPORT:y,DATA"
; CHECK: .globl x
; CHECK: .set x, .L_MergedGlobals
; CHECK: .globl y
; CHECK: .set y, .L_MergedGlobals+4
; CHECK: .section .drectve,"yn"
; CHECK: .ascii " /EXPORT:y,DATA"

View File

@ -61,45 +61,13 @@ define weak_odr dllexport void @weak1() {
@WeakVar3 = weak_odr dllexport global i32 0, align 4
; CHECK: .globl alias
; CHECK: .set alias, notExported
@alias = dllexport alias void(), void()* @notExported
; CHECK: .globl aliasNotExported
; CHECK: .set aliasNotExported, f1
@aliasNotExported = alias void(), void()* @f1
; CHECK: .globl alias2
; CHECK: .set alias2, f1
@alias2 = dllexport alias void(), void()* @f1
; CHECK: .globl alias3
; CHECK: .set alias3, notExported
@alias3 = dllexport alias void(), void()* @notExported
; CHECK: .weak weak_alias
; CHECK: .set weak_alias, f1
@weak_alias = weak_odr dllexport alias void(), void()* @f1
@blob = global [6 x i8] c"\B8*\00\00\00\C3", section ".text", align 16
@blob_alias = dllexport alias i32 (), bitcast ([6 x i8]* @blob to i32 ()*)
@exportedButNotDefinedVariable = external dllexport global i32
declare dllexport void @exportedButNotDefinedFunction()
define void @foo() {
entry:
store i32 4, i32* @exportedButNotDefinedVariable, align 4
call void @exportedButNotDefinedFunction()
ret void
}
; Verify items that should not be exported do not appear in the export table.
; We use a separate check prefix to avoid confusion between -NOT and -SAME.
; NOTEXPORTED: .section .drectve
; NOTEXPORTED-NOT: notExported
; NOTEXPORTED-NOT: aliasNotExported
; NOTEXPORTED-NOT: exportedButNotDefinedVariable
; NOTEXPORTED-NOT: exportedButNotDefinedFunction
; NOTEXPORTED-NOT: :notExported
; NOTEXPORTED-NOT: :aliasNotExported
; NOTEXPORTED-NOT: :exportedButNotDefinedVariable
; NOTEXPORTED-NOT: :exportedButNotDefinedFunction
; CHECK: .section .drectve
; WIN32: .ascii " /EXPORT:f1"
@ -134,3 +102,35 @@ entry:
; MINGW: .ascii " -export:alias3"
; MINGW: .ascii " -export:weak_alias"
; MINGW: .ascii " -export:blob_alias"
; CHECK: .globl alias
; CHECK: .set alias, notExported
@alias = dllexport alias void(), void()* @notExported
; CHECK: .globl aliasNotExported
; CHECK: .set aliasNotExported, f1
@aliasNotExported = alias void(), void()* @f1
; CHECK: .globl alias2
; CHECK: .set alias2, f1
@alias2 = dllexport alias void(), void()* @f1
; CHECK: .globl alias3
; CHECK: .set alias3, notExported
@alias3 = dllexport alias void(), void()* @notExported
; CHECK: .weak weak_alias
; CHECK: .set weak_alias, f1
@weak_alias = weak_odr dllexport alias void(), void()* @f1
@blob = global [6 x i8] c"\B8*\00\00\00\C3", section ".text", align 16
@blob_alias = dllexport alias i32 (), bitcast ([6 x i8]* @blob to i32 ()*)
@exportedButNotDefinedVariable = external dllexport global i32
declare dllexport void @exportedButNotDefinedFunction()
define void @foo() {
entry:
store i32 4, i32* @exportedButNotDefinedVariable, align 4
call void @exportedButNotDefinedFunction()
ret void
}

View File

@ -82,27 +82,11 @@ define weak_odr dllexport void @weak1() {
@WeakVar2 = weak_odr dllexport unnamed_addr constant i32 1
; CHECK: .globl _alias
; CHECK: .set _alias, _notExported
@alias = dllexport alias void(), void()* @notExported
; CHECK: .globl _alias2
; CHECK: .set _alias2, _f1
@alias2 = dllexport alias void(), void()* @f1
; CHECK: .globl _alias3
; CHECK: .set _alias3, _notExported
@alias3 = dllexport alias void(), void()* @notExported
; CHECK: .weak _weak_alias
; CHECK: .set _weak_alias, _f1
@weak_alias = weak_odr dllexport alias void(), void()* @f1
; Verify items that should not be exported do not appear in the export table.
; We use a separate check prefix to avoid confusion between -NOT and -SAME.
; NOTEXPORTED: .section .drectve
; NOTEXPORTED-NOT: notExported
; NOTEXPORTED-NOT: notDefined
; NOTEXPORTED-NOT: :notExported
; NOTEXPORTED-NOT: :notDefined
; CHECK: .section .drectve
; CHECK-CL: .ascii " /EXPORT:_f1"
@ -139,3 +123,19 @@ define weak_odr dllexport void @weak1() {
; CHECK-GCC: .ascii " -export:alias2"
; CHECK-GCC: .ascii " -export:alias3"
; CHECK-GCC: .ascii " -export:weak_alias"
; CHECK: .globl _alias
; CHECK: .set _alias, _notExported
@alias = dllexport alias void(), void()* @notExported
; CHECK: .globl _alias2
; CHECK: .set _alias2, _f1
@alias2 = dllexport alias void(), void()* @f1
; CHECK: .globl _alias3
; CHECK: .set _alias3, _notExported
@alias3 = dllexport alias void(), void()* @notExported
; CHECK: .weak _weak_alias
; CHECK: .set _weak_alias, _f1
@weak_alias = weak_odr dllexport alias void(), void()* @f1