llvm.org GIT mirror llvm / c543215
[ThinLTO]LTO]Legacy] Fix dependent libraries support by adding querying of the IRSymtab Dependent libraries support for the legacy api was committed in a broken state (see: https://reviews.llvm.org/D60274). This was missed due to the painful nature of having to integrate the changes into a linker in order to test. This change implements support for dependent libraries in the legacy LTO api: - I have removed the current api function, which returns a single string, and added functions to access each dependent library specifier individually. - To reduce the testing pain, I have made the api functions as thin as possible to maximize coverage from llvm-lto. - When doing ThinLTO the system linker will load the modules lazily when scanning the input files. Unfortunately, when modules are lazily loaded there is no access to module level named metadata. To fix this I have added api functions that allow querying the IRSymtab for the dependent libraries. I hope to expand the api in the future so that, eventually, all the information needed by a client linker during scan can be retrieved from the IRSymtab. Differential Revision: https://reviews.llvm.org/D62935 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363140 91177308-0d34-0410-b5e6-96231b3b80d8 Ben Dunbobbin 2 months ago
9 changed file(s) with 168 addition(s) and 28 deletion(s). Raw diff Collapse all Expand all
1616 #include "llvm/ADT/StringMap.h"
1717 #include "llvm/ADT/StringSet.h"
1818 #include "llvm/IR/Module.h"
19 #include "llvm/LTO/LTO.h"
1920 #include "llvm/Object/IRObjectFile.h"
2021 #include "llvm/Object/ModuleSymbolTable.h"
2122 #include "llvm/Target/TargetMachine.h"
154155
155156 StringRef getLinkerOpts() { return LinkerOpts; }
156157
157 StringRef getDependentLibraries() { return DependentLibraries; }
158
159158 const std::vector &getAsmUndefinedRefs() { return _asm_undefines; }
159
160 static lto::InputFile *createInputFile(const void *buffer, size_t buffer_size,
161 const char *path, std::string &out_error);
162
163 static size_t getDependentLibraryCount(lto::InputFile *input);
164
165 static const char *getDependentLibrary(lto::InputFile *input, size_t index, size_t *size);
160166
161167 private:
162168 /// Parse metadata from the module
163169 // FIXME: it only parses "llvm.linker.options" metadata at the moment
170 // FIXME: can't access metadata in lazily loaded modules
164171 void parseMetadata();
165172
166173 /// Parse the symbols from the module and model-level ASM and add them to
297297 lto_module_get_linkeropts(lto_module_t mod);
298298
299299 /**
300 * Returns the module's dependent library specifiers.
301 *
302 * \since LTO_API_VERSION=24
303 */
304 extern const char*
305 lto_module_get_dependent_libraries(lto_module_t mod);
306
307 /**
308300 * Diagnostic severity.
309301 *
310302 * \since LTO_API_VERSION=7
853845 extern void thinlto_codegen_set_cache_size_files(thinlto_code_gen_t cg,
854846 unsigned max_size_files);
855847
856
848 /** Opaque reference to an LTO input file */
849 typedef struct LLVMOpaqueLTOInput *lto_input_t;
850
851 /**
852 * Creates an LTO input file from a buffer. The path
853 * argument is used for diagnotics as this function
854 * otherwise does not know which file the given buffer
855 * is associated with.
856 *
857 * \since LTO_API_VERSION=24
858 */
859 extern lto_input_t lto_input_create(const void *buffer,
860 size_t buffer_size,
861 const char *path);
862
863 /**
864 * Frees all memory internally allocated by the LTO input file.
865 * Upon return the lto_module_t is no longer valid.
866 *
867 * \since LTO_API_VERSION=24
868 */
869 extern void lto_input_dispose(lto_input_t input);
870
871 /**
872 * Returns the number of dependent library specifiers
873 * for the given LTO input file.
874 *
875 * \since LTO_API_VERSION=24
876 */
877 extern unsigned lto_input_get_num_dependent_libraries(lto_input_t input);
878
879 /**
880 * Returns the ith dependent library specifier
881 * for the given LTO input file. The returned
882 * string is not null-terminated.
883 *
884 * \since LTO_API_VERSION=24
885 */
886 extern const char * lto_input_get_dependent_library(lto_input_t input,
887 size_t index,
888 size_t *size);
857889
858890 /**
859891 * @} // endgroup LLVMCTLTO_CACHING
644644 continue;
645645 emitLinkerFlagsForGlobalCOFF(OS, Sym.symbol, TT, M);
646646 }
647
648 // Dependent Libraries
649 raw_string_ostream OSD(DependentLibraries);
650 if (NamedMDNode *DependentLibraries = getModule().getNamedMetadata("llvm.dependent-libraries"))
651 for (MDNode *N : DependentLibraries->operands())
652 OSD << " " << cast(N->getOperand(0))->getString();
653 }
647 }
648
649 lto::InputFile *LTOModule::createInputFile(const void *buffer,
650 size_t buffer_size, const char *path,
651 std::string &outErr) {
652 StringRef Data((const char *)buffer, buffer_size);
653 MemoryBufferRef BufferRef(Data, path);
654
655 Expected> ObjOrErr =
656 lto::InputFile::create(BufferRef);
657
658 if (ObjOrErr)
659 return ObjOrErr->release();
660
661 outErr = std::string(path) +
662 ": Could not read LTO input file: " + toString(ObjOrErr.takeError());
663 return nullptr;
664 }
665
666 size_t LTOModule::getDependentLibraryCount(lto::InputFile *input) {
667 return input->getDependentLibraries().size();
668 }
669
670 const char *LTOModule::getDependentLibrary(lto::InputFile *input, size_t index,
671 size_t *size) {
672 StringRef S = input->getDependentLibraries()[index];
673 *size = S.size();
674 return S.data();
675 }
0 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
1
2 !llvm.dependent-libraries = !{!0, !1, !0}
3
4 !0 = !{!"foo"}
5 !1 = !{!"b a r"}
0 ; RUN: rm -rf %t && mkdir -p %t
1 ; RUN: llvm-as -o %t/1.bc %s
2 ; RUN: llvm-as -o %t/2.bc %S/Inputs/list-dependent-libraries.ll
3 ; RUN: llvm-lto -list-dependent-libraries-only %t/1.bc %t/2.bc | FileCheck %s
4 ; REQUIRES: default_triple
5
6 ; CHECK: 1.bc:
7 ; CHECK-NEXT: wibble
8 ; CHECK: 2.bc:
9 ; CHECK-NEXT: foo
10 ; CHECK-NEXT: b a r
11 ; CHECK-NEXT: foo
12
13 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
14
15 !llvm.dependent-libraries = !{!0}
16
17 !0 = !{!"wibble"}
33 ; RUN: not llvm-lto --list-symbols-only %S/Inputs/empty.bc 2>&1 | FileCheck %s --check-prefix=CHECK-LIST
44 ; CHECK-LIST: llvm-lto: error loading file '{{.*}}/Inputs/empty.bc': The file was not recognized as a valid object file
55
6 ; RUN: not llvm-lto --list-dependent-libraries-only %S/Inputs/empty.bc 2>&1 | FileCheck %s --check-prefix=CHECK-LIBS
7 ; CHECK-LIBS: llvm-lto: {{.*}}/Inputs/empty.bc: Could not read LTO input file: The file was not recognized as a valid object file
8
69 ; RUN: not llvm-lto --thinlto %S/Inputs/empty.bc 2>&1 | FileCheck %s --check-prefix=CHECK-THIN
710 ; CHECK-THIN: llvm-lto: error loading file '{{.*}}/Inputs/empty.bc': Invalid bitcode signature
203203 "list-symbols-only", cl::init(false),
204204 cl::desc("Instead of running LTO, list the symbols in each IR file"));
205205
206 static cl::opt ListDependentLibrariesOnly(
207 "list-dependent-libraries-only", cl::init(false),
208 cl::desc("Instead of running LTO, list the dependent libraries in each IR file"));
209
206210 static cl::opt SetMergedModule(
207211 "set-merged-module", cl::init(false),
208212 cl::desc("Use the first input module as the merged module"));
371375 }
372376 }
373377
378 static std::unique_ptr loadFile(StringRef Filename) {
379 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename.str() +
380 "': ");
381 return ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
382 }
383
384 static void listDependentLibraries() {
385 for (auto &Filename : InputFilenames) {
386 auto Buffer = loadFile(Filename);
387 std::string E;
388 std::unique_ptr Input(LTOModule::createInputFile(
389 Buffer->getBufferStart(), Buffer->getBufferSize(), Filename.c_str(),
390 E));
391 if (!Input)
392 error(E);
393
394 // List the dependent libraries.
395 outs() << Filename << ":\n";
396 for (size_t I = 0, C = LTOModule::getDependentLibraryCount(Input.get());
397 I != C; ++I) {
398 size_t L = 0;
399 const char *S = LTOModule::getDependentLibrary(Input.get(), I, &L);
400 assert(S);
401 outs() << StringRef(S, L) << "\n";
402 }
403 }
404 }
405
374406 /// Create a combined index file from the input IR files and write it.
375407 ///
376408 /// This is meant to enable testing of ThinLTO combined index generation,
446478 ExitOnError ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex +
447479 "': ");
448480 return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex));
449 }
450
451 static std::unique_ptr loadFile(StringRef Filename) {
452 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename.str() +
453 "': ");
454 return ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
455481 }
456482
457483 static std::unique_ptr loadInputFile(MemoryBufferRef Buffer) {
853879 return 0;
854880 }
855881
882 if (ListDependentLibrariesOnly) {
883 listDependentLibraries();
884 return 0;
885 }
886
856887 if (IndexStats) {
857888 printIndexStats();
858889 return 0;
1717 #include "llvm/IR/DiagnosticInfo.h"
1818 #include "llvm/IR/DiagnosticPrinter.h"
1919 #include "llvm/IR/LLVMContext.h"
20 #include "llvm/LTO/LTO.h"
2021 #include "llvm/LTO/legacy/LTOCodeGenerator.h"
2122 #include "llvm/LTO/legacy/LTOModule.h"
2223 #include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
322323
323324 const char* lto_module_get_linkeropts(lto_module_t mod) {
324325 return unwrap(mod)->getLinkerOpts().data();
325 }
326
327 const char* lto_module_get_dependent_libraries(lto_module_t mod) {
328 return unwrap(mod)->getDependentLibraries().data();
329326 }
330327
331328 void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg,
634631 sLastErrorString = "Unknown PIC model";
635632 return true;
636633 }
634
635 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(lto::InputFile, lto_input_t)
636
637 lto_input_t lto_input_create(const void *buffer, size_t buffer_size, const char *path) {
638 return wrap(LTOModule::createInputFile(buffer, buffer_size, path, sLastErrorString));
639 }
640
641 void lto_input_dispose(lto_input_t input) {
642 delete unwrap(input);
643 }
644
645 extern unsigned lto_input_get_num_dependent_libraries(lto_input_t input) {
646 return LTOModule::getDependentLibraryCount(unwrap(input));
647 }
648
649 extern const char *lto_input_get_dependent_library(lto_input_t input,
650 size_t index,
651 size_t *size) {
652 return LTOModule::getDependentLibrary(unwrap(input), index, size);
653 }
7171 thinlto_module_get_num_object_files
7272 thinlto_module_get_object_file
7373 thinlto_set_generated_objects_dir
74 lto_input_create
75 lto_input_destroy
76 lto_input_get_num_dependent_libraries
77 lto_input_get_dependent_library