Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lld/COFF/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ enum class ExportSource {
ModuleDefinition,
};

enum class EmitKind { Obj, LLVM };
enum class EmitKind { Obj, LLVM, ASM };

// Represents an /export option.
struct Export {
Expand Down
2 changes: 2 additions & 0 deletions lld/COFF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1859,6 +1859,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
config->emit = EmitKind::Obj;
else if (s == "llvm")
config->emit = EmitKind::LLVM;
else if (s == "asm")
config->emit = EmitKind::ASM;
else
error("/lldemit: unknown option: " + s);
}
Expand Down
16 changes: 11 additions & 5 deletions lld/COFF/LTO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ lto::Config BitcodeCompiler::createConfig() {
WriteBitcodeToFile(m, *os, false);
return false;
};
} else if (ctx.config.emit == EmitKind::ASM) {
c.CGFileType = CodeGenFileType::AssemblyFile;
c.Options.MCOptions.AsmVerbose = true;
}

if (ctx.config.saveTemps)
Expand Down Expand Up @@ -213,6 +216,8 @@ std::vector<InputFile *> BitcodeCompiler::compile() {
pruneCache(ctx.config.ltoCache, ctx.config.ltoCachePolicy, files);

std::vector<InputFile *> ret;
bool emitASM = ctx.config.emit == EmitKind::ASM;
const char *Ext = emitASM ? ".s" : ".obj";
for (unsigned i = 0; i != maxTasks; ++i) {
StringRef bitcodeFilePath;
// Get the native object contents either from the cache or from memory. Do
Expand All @@ -235,20 +240,21 @@ std::vector<InputFile *> BitcodeCompiler::compile() {
if (bitcodeFilePath == "ld-temp.o") {
ltoObjName =
saver().save(Twine(ctx.config.outputFile) + ".lto" +
(i == 0 ? Twine("") : Twine('.') + Twine(i)) + ".obj");
(i == 0 ? Twine("") : Twine('.') + Twine(i)) + Ext);
} else {
StringRef directory = sys::path::parent_path(bitcodeFilePath);
StringRef baseName = sys::path::filename(bitcodeFilePath);
StringRef baseName = sys::path::stem(bitcodeFilePath);
StringRef outputFileBaseName = sys::path::filename(ctx.config.outputFile);
SmallString<64> path;
sys::path::append(path, directory,
outputFileBaseName + ".lto." + baseName);
outputFileBaseName + ".lto." + baseName + Ext);
sys::path::remove_dots(path, true);
ltoObjName = saver().save(path.str());
}
if (ctx.config.saveTemps)
if (ctx.config.saveTemps || emitASM)
saveBuffer(buf[i].second, ltoObjName);
ret.push_back(make<ObjFile>(ctx, MemoryBufferRef(objBuf, ltoObjName)));
if (!emitASM)
ret.push_back(make<ObjFile>(ctx, MemoryBufferRef(objBuf, ltoObjName)));
}

return ret;
Expand Down
28 changes: 28 additions & 0 deletions lld/test/COFF/lto-emit-asm.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
; REQUIRES: x86
; RUN: llvm-as %s -o %t.obj

; RUN: lld-link /lldemit:asm /dll /noentry /include:f1 /include:f2 %t.obj /opt:lldltopartitions=1 /out:%t.1p /lldsavetemps
; RUN: cat %t.1p.lto.s | FileCheck %s
; RUN: llvm-dis %t.1p.0.4.opt.bc -o - | FileCheck --check-prefix=OPT %s

; RUN: lld-link /lldemit:asm /dll /noentry /include:f1 /include:f2 %t.obj /opt:lldltopartitions=2 /out:%t.2p
; RUN: cat %t.2p.lto.s %t.2p.lto.1.s | FileCheck %s

target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc"

;; Note: we also check for the presence of comments; /lldemit:asm output should be verbose.

; CHECK-DAG: # -- Begin function f1
; CHECK-DAG: f1:
; OPT: define void @f1()
define void @f1() {
ret void
}

; CHECK-DAG: # -- Begin function f2
; CHECK-DAG: f2:
; OPT: define void @f2()
define void @f2() {
ret void
}
8 changes: 4 additions & 4 deletions lld/test/COFF/pdb-thinlto.ll
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ declare void @foo()

; CHECK: Modules
; CHECK: ============================================================
; CHECK: Mod 0000 | `{{.*}}main.exe.lto.main.bc`:
; CHECK: Obj: `{{.*}}main.exe.lto.main.bc`:
; CHECK: Mod 0001 | `{{.*}}main.exe.lto.foo.bc`:
; CHECK: Obj: `{{.*}}main.exe.lto.foo.bc`:
; CHECK: Mod 0000 | `{{.*}}main.exe.lto.main.obj`:
; CHECK: Obj: `{{.*}}main.exe.lto.main.obj`:
; CHECK: Mod 0001 | `{{.*}}main.exe.lto.foo.obj`:
; CHECK: Obj: `{{.*}}main.exe.lto.foo.obj`:
; CHECK: Mod 0002 | `* Linker *`: