diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index 4879bcd6a42a5..a3b72381d73fc 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -1112,21 +1112,21 @@ CodeGenAction::loadModule(MemoryBufferRef MBRef) { CompilerInstance &CI = getCompilerInstance(); SourceManager &SM = CI.getSourceManager(); + auto DiagErrors = [&](Error E) -> std::unique_ptr { + unsigned DiagID = + CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0"); + handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) { + CI.getDiagnostics().Report(DiagID) << EIB.message(); + }); + return {}; + }; + // For ThinLTO backend invocations, ensure that the context // merges types based on ODR identifiers. We also need to read // the correct module out of a multi-module bitcode file. if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) { VMContext->enableDebugTypeODRUniquing(); - auto DiagErrors = [&](Error E) -> std::unique_ptr { - unsigned DiagID = - CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0"); - handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) { - CI.getDiagnostics().Report(DiagID) << EIB.message(); - }); - return {}; - }; - Expected> BMsOrErr = getBitcodeModuleList(MBRef); if (!BMsOrErr) return DiagErrors(BMsOrErr.takeError()); @@ -1151,10 +1151,35 @@ CodeGenAction::loadModule(MemoryBufferRef MBRef) { if (loadLinkModules(CI)) return nullptr; + // Handle textual IR and bitcode file with one single module. llvm::SMDiagnostic Err; if (std::unique_ptr M = parseIR(MBRef, Err, *VMContext)) return M; + // If MBRef is a bitcode with multiple modules (e.g., -fsplit-lto-unit + // output), place the extra modules (actually only one, a regular LTO module) + // into LinkModules as if we are using -mlink-bitcode-file. + Expected> BMsOrErr = getBitcodeModuleList(MBRef); + if (BMsOrErr && BMsOrErr->size()) { + std::unique_ptr FirstM; + for (auto &BM : *BMsOrErr) { + Expected> MOrErr = + BM.parseModule(*VMContext); + if (!MOrErr) + return DiagErrors(MOrErr.takeError()); + if (FirstM) + LinkModules.push_back({std::move(*MOrErr), /*PropagateAttrs=*/false, + /*Internalize=*/false, /*LinkFlags=*/{}}); + else + FirstM = std::move(*MOrErr); + } + if (FirstM) + return FirstM; + } + // If BMsOrErr fails, consume the error and use the error message from + // parseIR. + consumeError(BMsOrErr.takeError()); + // Translate from the diagnostic info to the SourceManager location if // available. // TODO: Unify this with ConvertBackendLocation() diff --git a/clang/test/CodeGen/split-lto-unit-input.cpp b/clang/test/CodeGen/split-lto-unit-input.cpp new file mode 100644 index 0000000000000..adfc9ac3e0f44 --- /dev/null +++ b/clang/test/CodeGen/split-lto-unit-input.cpp @@ -0,0 +1,32 @@ +// REQUIRES: x86-registered-target +/// When the input is a -fsplit-lto-unit bitcode file, link the regular LTO file like -mlink-bitcode-file. +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm-bc -flto=thin -flto-unit -fsplit-lto-unit %s -o %t.bc +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-obj %t.bc -o %t.o +// RUN: llvm-nm %t.o | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %t.bc -o - | FileCheck %s --check-prefix=CHECK-IR + +// CHECK: V _ZTI1A +// CHECK-NEXT: V _ZTI1B +// CHECK-NEXT: V _ZTS1A +// CHECK-NEXT: V _ZTS1B +// CHECK-NEXT: V _ZTV1A +// CHECK-NEXT: V _ZTV1B + +// CHECK-IR-DAG: _ZTS1B = linkonce_odr constant +// CHECK-IR-DAG: _ZTS1A = linkonce_odr constant +// CHECK-IR-DAG: _ZTV1B = linkonce_odr unnamed_addr constant +// CHECK-IR-DAG: _ZTI1A = linkonce_odr constant +// CHECK-IR-DAG: _ZTI1B = linkonce_odr constant +// CHECK-IR-DAG: _ZTV1A = linkonce_odr unnamed_addr constant + +struct A { + virtual int c(int i) = 0; +}; + +struct B : A { + virtual int c(int i) { return i; } +}; + +int use() { + return (new B)->c(0); +}