diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -3835,6 +3835,11 @@ if (Error Err = parseComdatRecord(Record)) return Err; break; + // FIXME: BitcodeReader should handle {GLOBALVAR, FUNCTION, ALIAS, IFUNC} + // written by ThinLinkBitcodeWriter. See + // `ThinLinkBitcodeWriter::writeSimplifiedModuleInfo` for the format of each + // record + // (https://github.com/llvm/llvm-project/blob/b6a93967d9c11e79802b5e75cec1584d6c8aa472/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp#L4714) case bitc::MODULE_CODE_GLOBALVAR: if (Error Err = parseGlobalVarRecord(Record)) return Err; diff --git a/llvm/test/Bitcode/thinlto-index-disassembled-by-llvm-dis.ll b/llvm/test/Bitcode/thinlto-index-disassembled-by-llvm-dis.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/thinlto-index-disassembled-by-llvm-dis.ll @@ -0,0 +1,30 @@ +; Tests that `llvm-dis` could disassemble ThinLTO minimized bitcode +; (e.g., bitcode generated by `opt --thin-link-bitcode-file=`, +; or `clang -Xclang -fthin-link-bitcode=`) + +; %t.o is the thin-lto ready bitcode, and %t.thinlink.bc is the minimized bitcode. +; RUN: opt -thinlto-bc %s -thin-link-bitcode-file=%t.thinlink.bc -o %t.o + +; With default options, `llvm-dis` returns invalid record for ThinLTO minimized bitcode. +; RUN: not llvm-dis %t.thinlink.bc 2>&1 | FileCheck %s --check-prefix=INVALID-RECORD + +; INVALID-RECORD: Invalid record + +; Tests that `llvm-dis` could disassemble minimized bitcode with `--print-thinlto-index-only`, and verify its content. +; RUN: llvm-dis --print-thinlto-index-only %t.thinlink.bc -o - | FileCheck %s --check-prefix=DIS + +; Tests that `llvm-dis` could disassemble ThinLTO-ready bitcode with `--print-thinlto-index-only`, +; and verify its content. +; RUN: llvm-dis --print-thinlto-index-only %t.o -o - | FileCheck %s --check-prefix=DIS + +; DIS: ^0 = module: (path: "{{.*}}thinlto-index-disassembled-by-llvm-dis.ll.tmp +; DIS: ^1 = gv: (name: "aplusb", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), insts: 2))) ; guid = +; DIS: ^2 = blockcount: 1 + +source_filename = "add.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" +define i32 @aplusb(i32 %a, i32 %b) { + %add = add i32 %b, %a + ret i32 %add +} diff --git a/llvm/tools/llvm-dis/llvm-dis.cpp b/llvm/tools/llvm-dis/llvm-dis.cpp --- a/llvm/tools/llvm-dis/llvm-dis.cpp +++ b/llvm/tools/llvm-dis/llvm-dis.cpp @@ -74,6 +74,11 @@ "then materialize only the metadata"), cl::cat(DisCategory)); +static cl::opt PrintThinLTOIndexOnly( + "print-thinlto-index-only", + cl::desc("Only read thinlto index and print the index as LLVM assembly."), + cl::init(false), cl::Hidden, cl::cat(DisCategory)); + namespace { static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) { @@ -186,12 +191,17 @@ for (size_t I = 0; I < N; ++I) { BitcodeModule MB = IF.Mods[I]; - std::unique_ptr M = ExitOnErr( - MB.getLazyModule(Context, MaterializeMetadata, SetImporting)); - if (MaterializeMetadata) - ExitOnErr(M->materializeMetadata()); - else - ExitOnErr(M->materializeAll()); + + std::unique_ptr M; + + if (!PrintThinLTOIndexOnly) { + M = ExitOnErr( + MB.getLazyModule(Context, MaterializeMetadata, SetImporting)); + if (MaterializeMetadata) + ExitOnErr(M->materializeMetadata()); + else + ExitOnErr(M->materializeAll()); + } BitcodeLTOInfo LTOInfo = ExitOnErr(MB.getLTOInfo()); std::unique_ptr Index; @@ -233,7 +243,8 @@ // All that llvm-dis does is write the assembly to a file. if (!DontPrint) { - M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder); + if (M) + M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder); if (Index) Index->print(Out->os()); }