1 //===- LTO.cpp ------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "LTO.h" 10 #include "Config.h" 11 #include "Driver.h" 12 #include "InputFiles.h" 13 #include "Symbols.h" 14 15 #include "lld/Common/ErrorHandler.h" 16 #include "lld/Common/Strings.h" 17 #include "lld/Common/TargetOptionsCommandFlags.h" 18 #include "llvm/LTO/LTO.h" 19 #include "llvm/Support/FileSystem.h" 20 #include "llvm/Support/Path.h" 21 #include "llvm/Support/raw_ostream.h" 22 #include "llvm/Transforms/ObjCARC.h" 23 24 using namespace lld; 25 using namespace lld::macho; 26 using namespace llvm; 27 using namespace llvm::sys; 28 29 static lto::Config createConfig() { 30 lto::Config c; 31 c.Options = initTargetOptionsFromCodeGenFlags(); 32 c.CodeModel = getCodeModelFromCMModel(); 33 c.CPU = getCPUStr(); 34 c.MAttrs = getMAttrs(); 35 c.UseNewPM = config->ltoNewPassManager; 36 c.PreCodeGenPassesHook = [](legacy::PassManager &pm) { 37 pm.add(createObjCARCContractPass()); 38 }; 39 return c; 40 } 41 42 BitcodeCompiler::BitcodeCompiler() { 43 auto backend = 44 lto::createInProcessThinBackend(heavyweight_hardware_concurrency()); 45 ltoObj = std::make_unique<lto::LTO>(createConfig(), backend); 46 } 47 48 void BitcodeCompiler::add(BitcodeFile &f) { 49 ArrayRef<lto::InputFile::Symbol> objSyms = f.obj->symbols(); 50 std::vector<lto::SymbolResolution> resols; 51 resols.reserve(objSyms.size()); 52 53 // Provide a resolution to the LTO API for each symbol. 54 auto symIt = f.symbols.begin(); 55 for (const lto::InputFile::Symbol &objSym : objSyms) { 56 resols.emplace_back(); 57 lto::SymbolResolution &r = resols.back(); 58 Symbol *sym = *symIt++; 59 60 // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile 61 // reports two symbols for module ASM defined. Without this check, lld 62 // flags an undefined in IR with a definition in ASM as prevailing. 63 // Once IRObjectFile is fixed to report only one symbol this hack can 64 // be removed. 65 r.Prevailing = !objSym.isUndefined() && sym->getFile() == &f; 66 67 // Un-define the symbol so that we don't get duplicate symbol errors when we 68 // load the ObjFile emitted by LTO compilation. 69 if (r.Prevailing) 70 replaceSymbol<Undefined>(sym, sym->getName(), sym->getFile(), 71 RefState::Strong); 72 73 // TODO: set the other resolution configs properly 74 r.VisibleToRegularObj = true; 75 } 76 checkError(ltoObj->add(std::move(f.obj), resols)); 77 } 78 79 // Merge all the bitcode files we have seen, codegen the result 80 // and return the resulting ObjectFile(s). 81 std::vector<ObjFile *> BitcodeCompiler::compile() { 82 unsigned maxTasks = ltoObj->getMaxTasks(); 83 buf.resize(maxTasks); 84 85 checkError(ltoObj->run([&](size_t task) { 86 return std::make_unique<lto::NativeObjectStream>( 87 std::make_unique<raw_svector_ostream>(buf[task])); 88 })); 89 90 if (config->saveTemps) { 91 if (!buf[0].empty()) 92 saveBuffer(buf[0], config->outputFile + ".lto.o"); 93 for (unsigned i = 1; i != maxTasks; ++i) 94 saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.o"); 95 } 96 97 if (!config->ltoObjPath.empty()) 98 fs::create_directories(config->ltoObjPath); 99 100 std::vector<ObjFile *> ret; 101 for (unsigned i = 0; i != maxTasks; ++i) { 102 if (buf[i].empty()) { 103 continue; 104 } 105 SmallString<261> filePath("/tmp/lto.tmp"); 106 uint32_t modTime = 0; 107 if (!config->ltoObjPath.empty()) { 108 filePath = config->ltoObjPath; 109 path::append(filePath, Twine(i) + "." + 110 getArchitectureName(config->target.Arch) + 111 ".lto.o"); 112 saveBuffer(buf[i], filePath); 113 modTime = getModTime(filePath); 114 } 115 ret.push_back(make<ObjFile>( 116 MemoryBufferRef(buf[i], saver.save(filePath.str())), modTime, "")); 117 } 118 119 return ret; 120 } 121