LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, std::string &errMsg) { static bool Initialized = false; if (!Initialized) { InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmParsers(); Initialized = true; } // parse bitcode buffer OwningPtr<Module> m(ParseBitcodeFile(buffer, getGlobalContext(), // @LOCALMOD &errMsg)); if (!m) { delete buffer; return NULL; } std::string TripleStr = m->getTargetTriple(); // @LOCALMOD-BEGIN // Pretend that we are ARM for name mangling and assembly conventions. // https://code.google.com/p/nativeclient/issues/detail?id=2554 if (TripleStr == "le32-unknown-nacl") { TripleStr = "armv7a-none-nacl-gnueabi"; } // @LOCALMOD-END if (TripleStr.empty()) TripleStr = sys::getDefaultTargetTriple(); llvm::Triple Triple(TripleStr); // find machine architecture for this module const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); if (!march) return NULL; // construct LTOModule, hand over ownership of module and target SubtargetFeatures Features; Features.getDefaultSubtargetFeatures(Triple); std::string FeatureStr = Features.getString(); // Set a default CPU for Darwin triples. std::string CPU; if (Triple.isOSDarwin()) { if (Triple.getArch() == llvm::Triple::x86_64) CPU = "core2"; else if (Triple.getArch() == llvm::Triple::x86) CPU = "yonah"; } TargetOptions Options; getTargetOptions(Options); TargetMachine *target = march->createTargetMachine(TripleStr, CPU, FeatureStr, Options); LTOModule *Ret = new LTOModule(m.take(), target); if (Ret->parseSymbols(errMsg)) { delete Ret; return NULL; } return Ret; }
LTOModule *LTOModule::makeLTOModule(std::unique_ptr<MemoryBuffer> Buffer, TargetOptions options, std::string &errMsg) { ErrorOr<Module *> MOrErr = getLazyBitcodeModule(Buffer.get(), getGlobalContext()); if (std::error_code EC = MOrErr.getError()) { errMsg = EC.message(); return nullptr; } std::unique_ptr<Module> M(MOrErr.get()); std::string TripleStr = M->getTargetTriple(); if (TripleStr.empty()) TripleStr = sys::getDefaultTargetTriple(); llvm::Triple Triple(TripleStr); // find machine architecture for this module const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); if (!march) return nullptr; // construct LTOModule, hand over ownership of module and target SubtargetFeatures Features; Features.getDefaultSubtargetFeatures(Triple); std::string FeatureStr = Features.getString(); // Set a default CPU for Darwin triples. std::string CPU; if (Triple.isOSDarwin()) { if (Triple.getArch() == llvm::Triple::x86_64) CPU = "core2"; else if (Triple.getArch() == llvm::Triple::x86) CPU = "yonah"; else if (Triple.getArch() == llvm::Triple::arm64 || Triple.getArch() == llvm::Triple::aarch64) CPU = "cyclone"; } TargetMachine *target = march->createTargetMachine(TripleStr, CPU, FeatureStr, options); M->materializeAllPermanently(true); M->setDataLayout(target->getDataLayout()); std::unique_ptr<object::IRObjectFile> IRObj( new object::IRObjectFile(std::move(Buffer), std::move(M))); LTOModule *Ret = new LTOModule(std::move(IRObj), target); if (Ret->parseSymbols(errMsg)) { delete Ret; return nullptr; } Ret->parseMetadata(); return Ret; }
LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, std::string &errMsg) { static bool Initialized = false; if (!Initialized) { InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmParsers(); Initialized = true; } // parse bitcode buffer OwningPtr<Module> m(getLazyBitcodeModule(buffer, getGlobalContext(), &errMsg)); if (!m) { delete buffer; return NULL; } std::string TripleStr = m->getTargetTriple(); if (TripleStr.empty()) TripleStr = sys::getDefaultTargetTriple(); llvm::Triple Triple(TripleStr); // find machine architecture for this module const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); if (!march) return NULL; // construct LTOModule, hand over ownership of module and target SubtargetFeatures Features; Features.getDefaultSubtargetFeatures(Triple); std::string FeatureStr = Features.getString(); // Set a default CPU for Darwin triples. std::string CPU; if (Triple.isOSDarwin()) { if (Triple.getArch() == llvm::Triple::x86_64) CPU = "core2"; else if (Triple.getArch() == llvm::Triple::x86) CPU = "yonah"; } TargetOptions Options; getTargetOptions(Options); TargetMachine *target = march->createTargetMachine(TripleStr, CPU, FeatureStr, Options); LTOModule *Ret = new LTOModule(m.take(), target); if (Ret->parseSymbols(errMsg)) { delete Ret; return NULL; } return Ret; }
LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, TargetOptions options, std::string &errMsg) { // parse bitcode buffer ErrorOr<Module *> ModuleOrErr = getLazyBitcodeModule(buffer, getGlobalContext()); if (error_code EC = ModuleOrErr.getError()) { errMsg = EC.message(); delete buffer; return NULL; } OwningPtr<Module> m(ModuleOrErr.get()); std::string TripleStr = m->getTargetTriple(); if (TripleStr.empty()) TripleStr = sys::getDefaultTargetTriple(); llvm::Triple Triple(TripleStr); // find machine architecture for this module const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); if (!march) return NULL; // construct LTOModule, hand over ownership of module and target SubtargetFeatures Features; Features.getDefaultSubtargetFeatures(Triple); std::string FeatureStr = Features.getString(); // Set a default CPU for Darwin triples. std::string CPU; if (Triple.isOSDarwin()) { if (Triple.getArch() == llvm::Triple::x86_64) CPU = "core2"; else if (Triple.getArch() == llvm::Triple::x86) CPU = "yonah"; } TargetMachine *target = march->createTargetMachine(TripleStr, CPU, FeatureStr, options); m->materializeAllPermanently(); LTOModule *Ret = new LTOModule(m.take(), target); if (Ret->parseSymbols(errMsg)) { delete Ret; return NULL; } Ret->parseMetadata(); return Ret; }
LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, std::string &errMsg) { static bool Initialized = false; if (!Initialized) { InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmParsers(); Initialized = true; } // parse bitcode buffer OwningPtr<Module> m(getLazyBitcodeModule(buffer, getGlobalContext(), &errMsg)); if (!m) { delete buffer; return NULL; } std::string Triple = m->getTargetTriple(); if (Triple.empty()) Triple = sys::getDefaultTargetTriple(); // find machine architecture for this module const Target *march = TargetRegistry::lookupTarget(Triple, errMsg); if (!march) return NULL; // construct LTOModule, hand over ownership of module and target SubtargetFeatures Features; Features.getDefaultSubtargetFeatures(llvm::Triple(Triple)); std::string FeatureStr = Features.getString(); std::string CPU; TargetMachine *target = march->createTargetMachine(Triple, CPU, FeatureStr); LTOModule *Ret = new LTOModule(m.take(), target); if (Ret->ParseSymbols(errMsg)) { delete Ret; return NULL; } return Ret; }
LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, TargetOptions options, std::string &errMsg) { // parse bitcode buffer ErrorOr<Module *> ModuleOrErr = getLazyBitcodeModule(buffer, getGlobalContext()); if (std::error_code EC = ModuleOrErr.getError()) { errMsg = EC.message(); delete buffer; return nullptr; } std::unique_ptr<Module> m(ModuleOrErr.get()); std::string TripleStr = m->getTargetTriple(); if (TripleStr.empty()) TripleStr = sys::getDefaultTargetTriple(); llvm::Triple Triple(TripleStr); // find machine architecture for this module const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); if (!march) return nullptr; // construct LTOModule, hand over ownership of module and target SubtargetFeatures Features; Features.getDefaultSubtargetFeatures(Triple); std::string FeatureStr = Features.getString(); // Set a default CPU for Darwin triples. std::string CPU; if (Triple.isOSDarwin()) { if (Triple.getArch() == llvm::Triple::x86_64) CPU = "core2"; else if (Triple.getArch() == llvm::Triple::x86) CPU = "yonah"; else if (Triple.getArch() == llvm::Triple::arm64 || Triple.getArch() == llvm::Triple::aarch64) CPU = "cyclone"; } TargetMachine *target = march->createTargetMachine(TripleStr, CPU, FeatureStr, options); m->materializeAllPermanently(); LTOModule *Ret = new LTOModule(m.release(), target); // We need a MCContext set up in order to get mangled names of private // symbols. It is a bit odd that we need to report uses and definitions // of private symbols, but it does look like ld64 expects to be informed // of at least the ones with an 'l' prefix. MCContext &Context = Ret->_context; const TargetLoweringObjectFile &TLOF = target->getTargetLowering()->getObjFileLowering(); const_cast<TargetLoweringObjectFile &>(TLOF).Initialize(Context, *target); if (Ret->parseSymbols(errMsg)) { delete Ret; return nullptr; } Ret->parseMetadata(); return Ret; }
/// claim_file_hook - called by gold to see whether this file is one that /// our plugin can handle. We'll try to open it and register all the symbols /// with add_symbol if possible. static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, int *claimed) { LTOModule *M; const void *view; std::unique_ptr<MemoryBuffer> buffer; if (get_view) { if (get_view(file->handle, &view) != LDPS_OK) { (*message)(LDPL_ERROR, "Failed to get a view of %s", file->name); return LDPS_ERR; } } else { int64_t offset = 0; // Gold has found what might be IR part-way inside of a file, such as // an .a archive. if (file->offset) { offset = file->offset; } if (std::error_code ec = MemoryBuffer::getOpenFileSlice( file->fd, file->name, buffer, file->filesize, offset)) { (*message)(LDPL_ERROR, ec.message().c_str()); return LDPS_ERR; } view = buffer->getBufferStart(); } if (!LTOModule::isBitcodeFile(view, file->filesize)) return LDPS_OK; std::string Error; M = LTOModule::makeLTOModule(view, file->filesize, TargetOpts, Error); if (!M) { (*message)(LDPL_ERROR, "LLVM gold plugin has failed to create LTO module: %s", Error.c_str()); return LDPS_OK; } *claimed = 1; Modules.resize(Modules.size() + 1); claimed_file &cf = Modules.back(); if (!options::triple.empty()) M->setTargetTriple(options::triple.c_str()); cf.handle = file->handle; unsigned sym_count = M->getSymbolCount(); cf.syms.reserve(sym_count); for (unsigned i = 0; i != sym_count; ++i) { lto_symbol_attributes attrs = M->getSymbolAttributes(i); if ((attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL) continue; cf.syms.push_back(ld_plugin_symbol()); ld_plugin_symbol &sym = cf.syms.back(); sym.name = strdup(M->getSymbolName(i)); sym.version = NULL; int scope = attrs & LTO_SYMBOL_SCOPE_MASK; bool CanBeHidden = scope == LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN; if (!CanBeHidden) CannotBeHidden.insert(sym.name); switch (scope) { case LTO_SYMBOL_SCOPE_HIDDEN: sym.visibility = LDPV_HIDDEN; break; case LTO_SYMBOL_SCOPE_PROTECTED: sym.visibility = LDPV_PROTECTED; break; case 0: // extern case LTO_SYMBOL_SCOPE_DEFAULT: case LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN: sym.visibility = LDPV_DEFAULT; break; default: (*message)(LDPL_ERROR, "Unknown scope attribute: %d", scope); return LDPS_ERR; } int definition = attrs & LTO_SYMBOL_DEFINITION_MASK; sym.comdat_key = NULL; switch (definition) { case LTO_SYMBOL_DEFINITION_REGULAR: sym.def = LDPK_DEF; break; case LTO_SYMBOL_DEFINITION_UNDEFINED: sym.def = LDPK_UNDEF; break; case LTO_SYMBOL_DEFINITION_TENTATIVE: sym.def = LDPK_COMMON; break; case LTO_SYMBOL_DEFINITION_WEAK: sym.comdat_key = sym.name; sym.def = LDPK_WEAKDEF; break; case LTO_SYMBOL_DEFINITION_WEAKUNDEF: sym.def = LDPK_WEAKUNDEF; break; default: (*message)(LDPL_ERROR, "Unknown definition attribute: %d", definition); return LDPS_ERR; } sym.size = 0; sym.resolution = LDPR_UNKNOWN; } cf.syms.reserve(cf.syms.size()); if (!cf.syms.empty()) { if ((*add_symbols)(cf.handle, cf.syms.size(), &cf.syms[0]) != LDPS_OK) { (*message)(LDPL_ERROR, "Unable to add symbols!"); return LDPS_ERR; } } if (CodeGen) { std::string Error; if (!CodeGen->addModule(M, Error)) { (*message)(LDPL_ERROR, "Error linking module: %s", Error.c_str()); return LDPS_ERR; } } delete M; return LDPS_OK; }
LTOModule *LTOModule::makeLTOModule(MemoryBufferRef Buffer, TargetOptions options, std::string &errMsg, LLVMContext *Context) { std::unique_ptr<LLVMContext> OwnedContext; if (!Context) { OwnedContext = llvm::make_unique<LLVMContext>(); Context = OwnedContext.get(); } ErrorOr<MemoryBufferRef> MBOrErr = IRObjectFile::findBitcodeInMemBuffer(Buffer); if (std::error_code EC = MBOrErr.getError()) { errMsg = EC.message(); return nullptr; } ErrorOr<Module *> MOrErr = parseBitcodeFile(*MBOrErr, *Context); if (std::error_code EC = MOrErr.getError()) { errMsg = EC.message(); return nullptr; } std::unique_ptr<Module> M(MOrErr.get()); std::string TripleStr = M->getTargetTriple(); if (TripleStr.empty()) TripleStr = sys::getDefaultTargetTriple(); llvm::Triple Triple(TripleStr); // find machine architecture for this module const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); if (!march) return nullptr; // construct LTOModule, hand over ownership of module and target SubtargetFeatures Features; Features.getDefaultSubtargetFeatures(Triple); std::string FeatureStr = Features.getString(); // Set a default CPU for Darwin triples. std::string CPU; if (Triple.isOSDarwin()) { if (Triple.getArch() == llvm::Triple::x86_64) CPU = "core2"; else if (Triple.getArch() == llvm::Triple::x86) CPU = "yonah"; else if (Triple.getArch() == llvm::Triple::aarch64) CPU = "cyclone"; } TargetMachine *target = march->createTargetMachine(TripleStr, CPU, FeatureStr, options); M->setDataLayout(target->getSubtargetImpl()->getDataLayout()); std::unique_ptr<object::IRObjectFile> IRObj( new object::IRObjectFile(Buffer, std::move(M))); LTOModule *Ret; if (OwnedContext) Ret = new LTOModule(std::move(IRObj), target, std::move(OwnedContext)); else Ret = new LTOModule(std::move(IRObj), target); if (Ret->parseSymbols(errMsg)) { delete Ret; return nullptr; } Ret->parseMetadata(); return Ret; }
LTOModule *LTOModule::makeLTOModule(MemoryBufferRef Buffer, TargetOptions options, std::string &errMsg, LLVMContext *Context) { std::unique_ptr<LLVMContext> OwnedContext; if (!Context) { OwnedContext = llvm::make_unique<LLVMContext>(); Context = OwnedContext.get(); } // If we own a context, we know this is being used only for symbol // extraction, not linking. Be lazy in that case. std::unique_ptr<Module> M = parseBitcodeFileImpl( Buffer, *Context, /* ShouldBeLazy */ static_cast<bool>(OwnedContext), errMsg); if (!M) return nullptr; std::string TripleStr = M->getTargetTriple(); if (TripleStr.empty()) TripleStr = sys::getDefaultTargetTriple(); llvm::Triple Triple(TripleStr); // find machine architecture for this module const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); if (!march) return nullptr; // construct LTOModule, hand over ownership of module and target SubtargetFeatures Features; Features.getDefaultSubtargetFeatures(Triple); std::string FeatureStr = Features.getString(); // Set a default CPU for Darwin triples. std::string CPU; if (Triple.isOSDarwin()) { if (Triple.getArch() == llvm::Triple::x86_64) CPU = "core2"; else if (Triple.getArch() == llvm::Triple::x86) CPU = "yonah"; else if (Triple.getArch() == llvm::Triple::aarch64) CPU = "cyclone"; } TargetMachine *target = march->createTargetMachine(TripleStr, CPU, FeatureStr, options); M->setDataLayout(*target->getDataLayout()); std::unique_ptr<object::IRObjectFile> IRObj( new object::IRObjectFile(Buffer, std::move(M))); LTOModule *Ret; if (OwnedContext) Ret = new LTOModule(std::move(IRObj), target, std::move(OwnedContext)); else Ret = new LTOModule(std::move(IRObj), target); if (Ret->parseSymbols(errMsg)) { delete Ret; return nullptr; } Ret->parseMetadata(); return Ret; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n"); if (OptLevel < '0' || OptLevel > '3') { errs() << argv[0] << ": optimization level must be between 0 and 3\n"; return 1; } // Initialize the configured targets. InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); InitializeAllAsmParsers(); // set up the TargetOptions for the machine TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); if (ListSymbolsOnly) return listSymbols(argv[0], Options); unsigned BaseArg = 0; LTOCodeGenerator CodeGen; if (UseDiagnosticHandler) CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr); switch (RelocModel) { case Reloc::Static: CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_STATIC); break; case Reloc::PIC_: CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC); break; case Reloc::DynamicNoPIC: CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC); break; default: CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DEFAULT); } CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF); CodeGen.setTargetOptions(Options); llvm::StringSet<llvm::MallocAllocator> DSOSymbolsSet; for (unsigned i = 0; i < DSOSymbols.size(); ++i) DSOSymbolsSet.insert(DSOSymbols[i]); std::vector<std::string> KeptDSOSyms; for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) { std::string error; std::unique_ptr<LTOModule> Module( LTOModule::createFromFile(InputFilenames[i].c_str(), Options, error)); if (!error.empty()) { errs() << argv[0] << ": error loading file '" << InputFilenames[i] << "': " << error << "\n"; return 1; } LTOModule *LTOMod = Module.get(); // We use the first input module as the destination module when // SetMergedModule is true. if (SetMergedModule && i == BaseArg) { // Transfer ownership to the code generator. CodeGen.setModule(Module.release()); } else if (!CodeGen.addModule(Module.get())) { // Print a message here so that we know addModule() did not abort. errs() << argv[0] << ": error adding file '" << InputFilenames[i] << "'\n"; return 1; } unsigned NumSyms = LTOMod->getSymbolCount(); for (unsigned I = 0; I < NumSyms; ++I) { StringRef Name = LTOMod->getSymbolName(I); if (!DSOSymbolsSet.count(Name)) continue; lto_symbol_attributes Attrs = LTOMod->getSymbolAttributes(I); unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK; if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN) KeptDSOSyms.push_back(Name); } } // Add all the exported symbols to the table of symbols to preserve. for (unsigned i = 0; i < ExportedSymbols.size(); ++i) CodeGen.addMustPreserveSymbol(ExportedSymbols[i].c_str()); // Add all the dso symbols to the table of symbols to expose. for (unsigned i = 0; i < KeptDSOSyms.size(); ++i) CodeGen.addMustPreserveSymbol(KeptDSOSyms[i].c_str()); // Set cpu and attrs strings for the default target/subtarget. CodeGen.setCpu(MCPU.c_str()); CodeGen.setOptLevel(OptLevel - '0'); std::string attrs; for (unsigned i = 0; i < MAttrs.size(); ++i) { if (i > 0) attrs.append(","); attrs.append(MAttrs[i]); } if (!attrs.empty()) CodeGen.setAttr(attrs.c_str()); if (!OutputFilename.empty()) { std::string ErrorInfo; std::unique_ptr<MemoryBuffer> Code = CodeGen.compile( DisableInline, DisableGVNLoadPRE, DisableLTOVectorization, ErrorInfo); if (!Code) { errs() << argv[0] << ": error compiling the code: " << ErrorInfo << "\n"; return 1; } std::error_code EC; raw_fd_ostream FileStream(OutputFilename, EC, sys::fs::F_None); if (EC) { errs() << argv[0] << ": error opening the file '" << OutputFilename << "': " << EC.message() << "\n"; return 1; } FileStream.write(Code->getBufferStart(), Code->getBufferSize()); } else { std::string ErrorInfo; const char *OutputName = nullptr; if (!CodeGen.compile_to_file(&OutputName, DisableInline, DisableGVNLoadPRE, DisableLTOVectorization, ErrorInfo)) { errs() << argv[0] << ": error compiling the code: " << ErrorInfo << "\n"; return 1; } outs() << "Wrote native object file '" << OutputName << "'\n"; } return 0; }