diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2013-09-24 23:52:22 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2013-09-24 23:52:22 +0000 |
commit | cc48854d5d51a2d7557f1040a61f160ad86c9729 (patch) | |
tree | 8b1852fb26b556df1366f94f1ab652b995a0ab36 /tools/lto | |
parent | 85509802eba15c82ff486f512a0b559699dc6999 (diff) | |
download | external_llvm-cc48854d5d51a2d7557f1040a61f160ad86c9729.zip external_llvm-cc48854d5d51a2d7557f1040a61f160ad86c9729.tar.gz external_llvm-cc48854d5d51a2d7557f1040a61f160ad86c9729.tar.bz2 |
Move LTO support library to a component, allowing it to be tested
more reliably across platforms. Patch by Tom Roeder!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191343 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/lto')
-rw-r--r-- | tools/lto/CMakeLists.txt | 4 | ||||
-rw-r--r-- | tools/lto/LTOCodeGenerator.cpp | 458 | ||||
-rw-r--r-- | tools/lto/LTOCodeGenerator.h | 130 | ||||
-rw-r--r-- | tools/lto/LTOModule.cpp | 908 | ||||
-rw-r--r-- | tools/lto/LTOModule.h | 190 | ||||
-rw-r--r-- | tools/lto/Makefile | 2 | ||||
-rw-r--r-- | tools/lto/lto.cpp | 27 |
7 files changed, 27 insertions, 1692 deletions
diff --git a/tools/lto/CMakeLists.txt b/tools/lto/CMakeLists.txt index c71aac1..8b26ddd 100644 --- a/tools/lto/CMakeLists.txt +++ b/tools/lto/CMakeLists.txt @@ -1,14 +1,12 @@ set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} - ipo scalaropts linker bitreader bitwriter mcdisassembler vectorize) + ipo scalaropts linker bitreader bitwriter lto mcdisassembler vectorize) add_definitions( -DLLVM_VERSION_INFO=\"${PACKAGE_VERSION}\" ) set(SOURCES - LTOCodeGenerator.cpp LTODisassembler.cpp lto.cpp - LTOModule.cpp ) if( NOT WIN32 AND LLVM_ENABLE_PIC ) diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp deleted file mode 100644 index 19e8c4c..0000000 --- a/tools/lto/LTOCodeGenerator.cpp +++ /dev/null @@ -1,458 +0,0 @@ -//===-LTOCodeGenerator.cpp - LLVM Link Time Optimizer ---------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the Link Time Optimization library. This library is -// intended to be used by linker to optimize code at link time. -// -//===----------------------------------------------------------------------===// - -#include "LTOCodeGenerator.h" -#include "LTOModule.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Config/config.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/InitializePasses.h" -#include "llvm/Linker.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/SubtargetFeature.h" -#include "llvm/PassManager.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Signals.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/system_error.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" -#include "llvm/Transforms/ObjCARC.h" -using namespace llvm; - -static cl::opt<bool> -DisableOpt("disable-opt", cl::init(false), - cl::desc("Do not run any optimization passes")); - -static cl::opt<bool> -DisableInline("disable-inlining", cl::init(false), - cl::desc("Do not run the inliner pass")); - -static cl::opt<bool> -DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false), - cl::desc("Do not run the GVN load PRE pass")); - -const char* LTOCodeGenerator::getVersionString() { -#ifdef LLVM_VERSION_INFO - return PACKAGE_NAME " version " PACKAGE_VERSION ", " LLVM_VERSION_INFO; -#else - return PACKAGE_NAME " version " PACKAGE_VERSION; -#endif -} - -LTOCodeGenerator::LTOCodeGenerator() - : Context(getGlobalContext()), Linker(new Module("ld-temp.o", Context)), - TargetMach(NULL), EmitDwarfDebugInfo(false), ScopeRestrictionsDone(false), - CodeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC), NativeObjectFile(NULL) { - InitializeAllTargets(); - InitializeAllTargetMCs(); - InitializeAllAsmPrinters(); - initializeLTOPasses(); -} - -LTOCodeGenerator::~LTOCodeGenerator() { - delete TargetMach; - delete NativeObjectFile; - delete Linker.getModule(); - - for (std::vector<char *>::iterator I = CodegenOptions.begin(), - E = CodegenOptions.end(); - I != E; ++I) - free(*I); -} - -// Initialize LTO passes. Please keep this funciton in sync with -// PassManagerBuilder::populateLTOPassManager(), and make sure all LTO -// passes are initialized. -// -void LTOCodeGenerator::initializeLTOPasses() { - PassRegistry &R = *PassRegistry::getPassRegistry(); - - initializeInternalizePassPass(R); - initializeIPSCCPPass(R); - initializeGlobalOptPass(R); - initializeConstantMergePass(R); - initializeDAHPass(R); - initializeInstCombinerPass(R); - initializeSimpleInlinerPass(R); - initializePruneEHPass(R); - initializeGlobalDCEPass(R); - initializeArgPromotionPass(R); - initializeJumpThreadingPass(R); - initializeSROAPass(R); - initializeSROA_DTPass(R); - initializeSROA_SSAUpPass(R); - initializeFunctionAttrsPass(R); - initializeGlobalsModRefPass(R); - initializeLICMPass(R); - initializeGVNPass(R); - initializeMemCpyOptPass(R); - initializeDCEPass(R); - initializeCFGSimplifyPassPass(R); -} - -bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) { - bool ret = Linker.linkInModule(mod->getLLVVMModule(), &errMsg); - - const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs(); - for (int i = 0, e = undefs.size(); i != e; ++i) - AsmUndefinedRefs[undefs[i]] = 1; - - return !ret; -} - -void LTOCodeGenerator::setDebugInfo(lto_debug_model debug) { - switch (debug) { - case LTO_DEBUG_MODEL_NONE: - EmitDwarfDebugInfo = false; - return; - - case LTO_DEBUG_MODEL_DWARF: - EmitDwarfDebugInfo = true; - return; - } - llvm_unreachable("Unknown debug format!"); -} - -void LTOCodeGenerator::setCodePICModel(lto_codegen_model model) { - switch (model) { - case LTO_CODEGEN_PIC_MODEL_STATIC: - case LTO_CODEGEN_PIC_MODEL_DYNAMIC: - case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: - CodeModel = model; - return; - } - llvm_unreachable("Unknown PIC model!"); -} - -bool LTOCodeGenerator::writeMergedModules(const char *path, - std::string &errMsg) { - if (!determineTarget(errMsg)) - return false; - - // mark which symbols can not be internalized - applyScopeRestrictions(); - - // create output file - std::string ErrInfo; - tool_output_file Out(path, ErrInfo, sys::fs::F_Binary); - if (!ErrInfo.empty()) { - errMsg = "could not open bitcode file for writing: "; - errMsg += path; - return false; - } - - // write bitcode to it - WriteBitcodeToFile(Linker.getModule(), Out.os()); - Out.os().close(); - - if (Out.os().has_error()) { - errMsg = "could not write bitcode file: "; - errMsg += path; - Out.os().clear_error(); - return false; - } - - Out.keep(); - return true; -} - -bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) { - // make unique temp .o file to put generated object file - SmallString<128> Filename; - int FD; - error_code EC = sys::fs::createTemporaryFile("lto-llvm", "o", FD, Filename); - if (EC) { - errMsg = EC.message(); - return false; - } - - // generate object file - tool_output_file objFile(Filename.c_str(), FD); - - bool genResult = generateObjectFile(objFile.os(), errMsg); - objFile.os().close(); - if (objFile.os().has_error()) { - objFile.os().clear_error(); - sys::fs::remove(Twine(Filename)); - return false; - } - - objFile.keep(); - if (!genResult) { - sys::fs::remove(Twine(Filename)); - return false; - } - - NativeObjectPath = Filename.c_str(); - *name = NativeObjectPath.c_str(); - return true; -} - -const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) { - const char *name; - if (!compile_to_file(&name, errMsg)) - return NULL; - - // remove old buffer if compile() called twice - delete NativeObjectFile; - - // read .o file into memory buffer - OwningPtr<MemoryBuffer> BuffPtr; - if (error_code ec = MemoryBuffer::getFile(name, BuffPtr, -1, false)) { - errMsg = ec.message(); - sys::fs::remove(NativeObjectPath); - return NULL; - } - NativeObjectFile = BuffPtr.take(); - - // remove temp files - sys::fs::remove(NativeObjectPath); - - // return buffer, unless error - if (NativeObjectFile == NULL) - return NULL; - *length = NativeObjectFile->getBufferSize(); - return NativeObjectFile->getBufferStart(); -} - -bool LTOCodeGenerator::determineTarget(std::string &errMsg) { - if (TargetMach != NULL) - return true; - - // if options were requested, set them - if (!CodegenOptions.empty()) - cl::ParseCommandLineOptions(CodegenOptions.size(), - const_cast<char **>(&CodegenOptions[0])); - - std::string TripleStr = Linker.getModule()->getTargetTriple(); - if (TripleStr.empty()) - TripleStr = sys::getDefaultTargetTriple(); - llvm::Triple Triple(TripleStr); - - // create target machine from info for merged modules - const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); - if (march == NULL) - return false; - - // The relocation model is actually a static member of TargetMachine and - // needs to be set before the TargetMachine is instantiated. - Reloc::Model RelocModel = Reloc::Default; - switch (CodeModel) { - case LTO_CODEGEN_PIC_MODEL_STATIC: - RelocModel = Reloc::Static; - break; - case LTO_CODEGEN_PIC_MODEL_DYNAMIC: - RelocModel = Reloc::PIC_; - break; - case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: - RelocModel = Reloc::DynamicNoPIC; - break; - } - - // 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. - if (MCpu.empty() && Triple.isOSDarwin()) { - if (Triple.getArch() == llvm::Triple::x86_64) - MCpu = "core2"; - else if (Triple.getArch() == llvm::Triple::x86) - MCpu = "yonah"; - } - TargetOptions Options; - LTOModule::getTargetOptions(Options); - TargetMach = march->createTargetMachine(TripleStr, MCpu, FeatureStr, Options, - RelocModel, CodeModel::Default, - CodeGenOpt::Aggressive); - return true; -} - -void LTOCodeGenerator:: -applyRestriction(GlobalValue &GV, - std::vector<const char*> &MustPreserveList, - SmallPtrSet<GlobalValue*, 8> &AsmUsed, - Mangler &Mangler) { - SmallString<64> Buffer; - Mangler.getNameWithPrefix(Buffer, &GV, false); - - if (GV.isDeclaration()) - return; - if (MustPreserveSymbols.count(Buffer)) - MustPreserveList.push_back(GV.getName().data()); - if (AsmUndefinedRefs.count(Buffer)) - AsmUsed.insert(&GV); -} - -static void findUsedValues(GlobalVariable *LLVMUsed, - SmallPtrSet<GlobalValue*, 8> &UsedValues) { - if (LLVMUsed == 0) return; - - ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer()); - for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) - if (GlobalValue *GV = - dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts())) - UsedValues.insert(GV); -} - -void LTOCodeGenerator::applyScopeRestrictions() { - if (ScopeRestrictionsDone) - return; - Module *mergedModule = Linker.getModule(); - - // Start off with a verification pass. - PassManager passes; - passes.add(createVerifierPass()); - - // mark which symbols can not be internalized - MCContext MContext(TargetMach->getMCAsmInfo(), TargetMach->getRegisterInfo(), - NULL); - Mangler Mangler(MContext, TargetMach); - std::vector<const char*> MustPreserveList; - SmallPtrSet<GlobalValue*, 8> AsmUsed; - - for (Module::iterator f = mergedModule->begin(), - e = mergedModule->end(); f != e; ++f) - applyRestriction(*f, MustPreserveList, AsmUsed, Mangler); - for (Module::global_iterator v = mergedModule->global_begin(), - e = mergedModule->global_end(); v != e; ++v) - applyRestriction(*v, MustPreserveList, AsmUsed, Mangler); - for (Module::alias_iterator a = mergedModule->alias_begin(), - e = mergedModule->alias_end(); a != e; ++a) - applyRestriction(*a, MustPreserveList, AsmUsed, Mangler); - - GlobalVariable *LLVMCompilerUsed = - mergedModule->getGlobalVariable("llvm.compiler.used"); - findUsedValues(LLVMCompilerUsed, AsmUsed); - if (LLVMCompilerUsed) - LLVMCompilerUsed->eraseFromParent(); - - if (!AsmUsed.empty()) { - llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(Context); - std::vector<Constant*> asmUsed2; - for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = AsmUsed.begin(), - e = AsmUsed.end(); i !=e; ++i) { - GlobalValue *GV = *i; - Constant *c = ConstantExpr::getBitCast(GV, i8PTy); - asmUsed2.push_back(c); - } - - llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size()); - LLVMCompilerUsed = - new llvm::GlobalVariable(*mergedModule, ATy, false, - llvm::GlobalValue::AppendingLinkage, - llvm::ConstantArray::get(ATy, asmUsed2), - "llvm.compiler.used"); - - LLVMCompilerUsed->setSection("llvm.metadata"); - } - - passes.add(createInternalizePass(MustPreserveList)); - - // apply scope restrictions - passes.run(*mergedModule); - - ScopeRestrictionsDone = true; -} - -/// Optimize merged modules using various IPO passes -bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, - std::string &errMsg) { - if (!this->determineTarget(errMsg)) - return false; - - Module *mergedModule = Linker.getModule(); - - // Mark which symbols can not be internalized - this->applyScopeRestrictions(); - - // Instantiate the pass manager to organize the passes. - PassManager passes; - - // Start off with a verification pass. - passes.add(createVerifierPass()); - - // Add an appropriate DataLayout instance for this module... - passes.add(new DataLayout(*TargetMach->getDataLayout())); - TargetMach->addAnalysisPasses(passes); - - // Enabling internalize here would use its AllButMain variant. It - // keeps only main if it exists and does nothing for libraries. Instead - // we create the pass ourselves with the symbol list provided by the linker. - if (!DisableOpt) - PassManagerBuilder().populateLTOPassManager(passes, - /*Internalize=*/false, - !DisableInline, - DisableGVNLoadPRE); - - // Make sure everything is still good. - passes.add(createVerifierPass()); - - PassManager codeGenPasses; - - codeGenPasses.add(new DataLayout(*TargetMach->getDataLayout())); - TargetMach->addAnalysisPasses(codeGenPasses); - - formatted_raw_ostream Out(out); - - // If the bitcode files contain ARC code and were compiled with optimization, - // the ObjCARCContractPass must be run, so do it unconditionally here. - codeGenPasses.add(createObjCARCContractPass()); - - if (TargetMach->addPassesToEmitFile(codeGenPasses, Out, - TargetMachine::CGFT_ObjectFile)) { - errMsg = "target file type not supported"; - return false; - } - - // Run our queue of passes all at once now, efficiently. - passes.run(*mergedModule); - - // Run the code generator, and write assembly file - codeGenPasses.run(*mergedModule); - - return true; -} - -/// setCodeGenDebugOptions - Set codegen debugging options to aid in debugging -/// LTO problems. -void LTOCodeGenerator::setCodeGenDebugOptions(const char *options) { - for (std::pair<StringRef, StringRef> o = getToken(options); - !o.first.empty(); o = getToken(o.second)) { - // ParseCommandLineOptions() expects argv[0] to be program name. Lazily add - // that. - if (CodegenOptions.empty()) - CodegenOptions.push_back(strdup("libLTO")); - CodegenOptions.push_back(strdup(o.first.str().c_str())); - } -} diff --git a/tools/lto/LTOCodeGenerator.h b/tools/lto/LTOCodeGenerator.h deleted file mode 100644 index 0263362..0000000 --- a/tools/lto/LTOCodeGenerator.h +++ /dev/null @@ -1,130 +0,0 @@ -//===-LTOCodeGenerator.h - LLVM Link Time Optimizer -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares the LTOCodeGenerator class. -// -// LTO compilation consists of three phases: Pre-IPO, IPO and Post-IPO. -// -// The Pre-IPO phase compiles source code into bitcode file. The resulting -// bitcode files, along with object files and libraries, will be fed to the -// linker to through the IPO and Post-IPO phases. By using obj-file extension, -// the resulting bitcode file disguises itself as an object file, and therefore -// obviates the need of writing a special set of the make-rules only for LTO -// compilation. -// -// The IPO phase perform inter-procedural analyses and optimizations, and -// the Post-IPO consists two sub-phases: intra-procedural scalar optimizations -// (SOPT), and intra-procedural target-dependent code generator (CG). -// -// As of this writing, we don't separate IPO and the Post-IPO SOPT. They -// are intermingled together, and are driven by a single pass manager (see -// PassManagerBuilder::populateLTOPassManager()). -// -// The "LTOCodeGenerator" is the driver for the IPO and Post-IPO stages. -// The "CodeGenerator" here is bit confusing. Don't confuse the "CodeGenerator" -// with the machine specific code generator. -// -//===----------------------------------------------------------------------===// - -#ifndef LTO_CODE_GENERATOR_H -#define LTO_CODE_GENERATOR_H - -#include "llvm-c/lto.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/Linker.h" -#include <string> -#include <vector> - -namespace llvm { - class LLVMContext; - class GlobalValue; - class Mangler; - class MemoryBuffer; - class TargetMachine; - class raw_ostream; -} - -//===----------------------------------------------------------------------===// -/// LTOCodeGenerator - C++ class which implements the opaque lto_code_gen_t -/// type. -/// -struct LTOCodeGenerator { - static const char *getVersionString(); - - LTOCodeGenerator(); - ~LTOCodeGenerator(); - - // Merge given module, return true on success. - bool addModule(struct LTOModule*, std::string &errMsg); - - void setDebugInfo(lto_debug_model); - void setCodePICModel(lto_codegen_model); - - void setCpu(const char *mCpu) { MCpu = mCpu; } - - void addMustPreserveSymbol(const char *sym) { MustPreserveSymbols[sym] = 1; } - - // To pass options to the driver and optimization passes. These options are - // not necessarily for debugging purpose (The function name is misleading). - // This function should be called before LTOCodeGenerator::compilexxx(), - // and LTOCodeGenerator::writeMergedModules(). - // - void setCodeGenDebugOptions(const char *opts); - - // Write the merged module to the file specified by the given path. - // Return true on success. - bool writeMergedModules(const char *path, std::string &errMsg); - - // Compile the merged module into a *single* object file; the path to object - // file is returned to the caller via argument "name". Return true on - // success. - // - // NOTE that it is up to the linker to remove the intermediate object file. - // Do not try to remove the object file in LTOCodeGenerator's destructor - // as we don't who (LTOCodeGenerator or the obj file) will last longer. - // - bool compile_to_file(const char **name, std::string &errMsg); - - // As with compile_to_file(), this function compiles the merged module into - // single object file. Instead of returning the object-file-path to the caller - // (linker), it brings the object to a buffer, and return the buffer to the - // caller. This function should delete intermediate object file once its content - // is brought to memory. Return NULL is the compilation was not successful. - // - const void *compile(size_t *length, std::string &errMsg); - -private: - void initializeLTOPasses(); - - bool generateObjectFile(llvm::raw_ostream &out, std::string &errMsg); - void applyScopeRestrictions(); - void applyRestriction(llvm::GlobalValue &GV, - std::vector<const char*> &MustPreserveList, - llvm::SmallPtrSet<llvm::GlobalValue*, 8> &AsmUsed, - llvm::Mangler &Mangler); - bool determineTarget(std::string &errMsg); - - typedef llvm::StringMap<uint8_t> StringSet; - - llvm::LLVMContext &Context; - llvm::Linker Linker; - llvm::TargetMachine *TargetMach; - bool EmitDwarfDebugInfo; - bool ScopeRestrictionsDone; - lto_codegen_model CodeModel; - StringSet MustPreserveSymbols; - StringSet AsmUndefinedRefs; - llvm::MemoryBuffer *NativeObjectFile; - std::vector<char *> CodegenOptions; - std::string MCpu; - std::string NativeObjectPath; -}; - -#endif // LTO_CODE_GENERATOR_H diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp deleted file mode 100644 index 87e3573..0000000 --- a/tools/lto/LTOModule.cpp +++ /dev/null @@ -1,908 +0,0 @@ -//===-- LTOModule.cpp - LLVM Link Time Optimizer --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the Link Time Optimization library. This library is -// intended to be used by linker to optimize code at link time. -// -//===----------------------------------------------------------------------===// - -#include "LTOModule.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCTargetAsmParser.h" -#include "llvm/MC/SubtargetFeature.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/system_error.h" -#include "llvm/Target/TargetRegisterInfo.h" -using namespace llvm; - -static cl::opt<bool> -EnableFPMAD("enable-fp-mad", - cl::desc("Enable less precise MAD instructions to be generated"), - cl::init(false)); - -static cl::opt<bool> -DisableFPElim("disable-fp-elim", - cl::desc("Disable frame pointer elimination optimization"), - cl::init(false)); - -static cl::opt<bool> -EnableUnsafeFPMath("enable-unsafe-fp-math", - cl::desc("Enable optimizations that may decrease FP precision"), - cl::init(false)); - -static cl::opt<bool> -EnableNoInfsFPMath("enable-no-infs-fp-math", - cl::desc("Enable FP math optimizations that assume no +-Infs"), - cl::init(false)); - -static cl::opt<bool> -EnableNoNaNsFPMath("enable-no-nans-fp-math", - cl::desc("Enable FP math optimizations that assume no NaNs"), - cl::init(false)); - -static cl::opt<bool> -EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math", - cl::Hidden, - cl::desc("Force codegen to assume rounding mode can change dynamically"), - cl::init(false)); - -static cl::opt<bool> -GenerateSoftFloatCalls("soft-float", - cl::desc("Generate software floating point library calls"), - cl::init(false)); - -static cl::opt<llvm::FloatABI::ABIType> -FloatABIForCalls("float-abi", - cl::desc("Choose float ABI type"), - cl::init(FloatABI::Default), - cl::values( - clEnumValN(FloatABI::Default, "default", - "Target default float ABI type"), - clEnumValN(FloatABI::Soft, "soft", - "Soft float ABI (implied by -soft-float)"), - clEnumValN(FloatABI::Hard, "hard", - "Hard float ABI (uses FP registers)"), - clEnumValEnd)); - -static cl::opt<llvm::FPOpFusion::FPOpFusionMode> -FuseFPOps("fp-contract", - cl::desc("Enable aggresive formation of fused FP ops"), - cl::init(FPOpFusion::Standard), - cl::values( - clEnumValN(FPOpFusion::Fast, "fast", - "Fuse FP ops whenever profitable"), - clEnumValN(FPOpFusion::Standard, "on", - "Only fuse 'blessed' FP ops."), - clEnumValN(FPOpFusion::Strict, "off", - "Only fuse FP ops when the result won't be effected."), - clEnumValEnd)); - -static cl::opt<bool> -DontPlaceZerosInBSS("nozero-initialized-in-bss", - cl::desc("Don't place zero-initialized symbols into bss section"), - cl::init(false)); - -static cl::opt<bool> -EnableGuaranteedTailCallOpt("tailcallopt", - cl::desc("Turn fastcc calls into tail calls by (potentially) changing ABI."), - cl::init(false)); - -static cl::opt<bool> -DisableTailCalls("disable-tail-calls", - cl::desc("Never emit tail calls"), - cl::init(false)); - -static cl::opt<unsigned> -OverrideStackAlignment("stack-alignment", - cl::desc("Override default stack alignment"), - cl::init(0)); - -static cl::opt<std::string> -TrapFuncName("trap-func", cl::Hidden, - cl::desc("Emit a call to trap function rather than a trap instruction"), - cl::init("")); - -static cl::opt<bool> -EnablePIE("enable-pie", - cl::desc("Assume the creation of a position independent executable."), - cl::init(false)); - -static cl::opt<bool> -SegmentedStacks("segmented-stacks", - cl::desc("Use segmented stacks if possible."), - cl::init(false)); - -static cl::opt<bool> -UseInitArray("use-init-array", - cl::desc("Use .init_array instead of .ctors."), - cl::init(false)); - -LTOModule::LTOModule(llvm::Module *m, llvm::TargetMachine *t) - : _module(m), _target(t), - _context(_target->getMCAsmInfo(), _target->getRegisterInfo(), NULL), - _mangler(_context, t) {} - -/// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM -/// bitcode. -bool LTOModule::isBitcodeFile(const void *mem, size_t length) { - return sys::fs::identify_magic(StringRef((const char *)mem, length)) == - sys::fs::file_magic::bitcode; -} - -bool LTOModule::isBitcodeFile(const char *path) { - sys::fs::file_magic type; - if (sys::fs::identify_magic(path, type)) - return false; - return type == sys::fs::file_magic::bitcode; -} - -/// isBitcodeFileForTarget - Returns 'true' if the file (or memory contents) is -/// LLVM bitcode for the specified triple. -bool LTOModule::isBitcodeFileForTarget(const void *mem, size_t length, - const char *triplePrefix) { - MemoryBuffer *buffer = makeBuffer(mem, length); - if (!buffer) - return false; - return isTargetMatch(buffer, triplePrefix); -} - -bool LTOModule::isBitcodeFileForTarget(const char *path, - const char *triplePrefix) { - OwningPtr<MemoryBuffer> buffer; - if (MemoryBuffer::getFile(path, buffer)) - return false; - return isTargetMatch(buffer.take(), triplePrefix); -} - -/// isTargetMatch - Returns 'true' if the memory buffer is for the specified -/// target triple. -bool LTOModule::isTargetMatch(MemoryBuffer *buffer, const char *triplePrefix) { - std::string Triple = getBitcodeTargetTriple(buffer, getGlobalContext()); - delete buffer; - return strncmp(Triple.c_str(), triplePrefix, strlen(triplePrefix)) == 0; -} - -/// makeLTOModule - Create an LTOModule. N.B. These methods take ownership of -/// the buffer. -LTOModule *LTOModule::makeLTOModule(const char *path, std::string &errMsg) { - OwningPtr<MemoryBuffer> buffer; - if (error_code ec = MemoryBuffer::getFile(path, buffer)) { - errMsg = ec.message(); - return NULL; - } - return makeLTOModule(buffer.take(), errMsg); -} - -LTOModule *LTOModule::makeLTOModule(int fd, const char *path, - size_t size, std::string &errMsg) { - return makeLTOModule(fd, path, size, 0, errMsg); -} - -LTOModule *LTOModule::makeLTOModule(int fd, const char *path, - size_t map_size, - off_t offset, - std::string &errMsg) { - OwningPtr<MemoryBuffer> buffer; - if (error_code ec = - MemoryBuffer::getOpenFileSlice(fd, path, buffer, map_size, offset)) { - errMsg = ec.message(); - return NULL; - } - return makeLTOModule(buffer.take(), errMsg); -} - -LTOModule *LTOModule::makeLTOModule(const void *mem, size_t length, - std::string &errMsg) { - OwningPtr<MemoryBuffer> buffer(makeBuffer(mem, length)); - if (!buffer) - return NULL; - return makeLTOModule(buffer.take(), errMsg); -} - -void LTOModule::getTargetOptions(TargetOptions &Options) { - Options.LessPreciseFPMADOption = EnableFPMAD; - Options.NoFramePointerElim = DisableFPElim; - Options.AllowFPOpFusion = FuseFPOps; - Options.UnsafeFPMath = EnableUnsafeFPMath; - Options.NoInfsFPMath = EnableNoInfsFPMath; - Options.NoNaNsFPMath = EnableNoNaNsFPMath; - Options.HonorSignDependentRoundingFPMathOption = - EnableHonorSignDependentRoundingFPMath; - Options.UseSoftFloat = GenerateSoftFloatCalls; - if (FloatABIForCalls != FloatABI::Default) - Options.FloatABIType = FloatABIForCalls; - Options.NoZerosInBSS = DontPlaceZerosInBSS; - Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt; - Options.DisableTailCalls = DisableTailCalls; - Options.StackAlignmentOverride = OverrideStackAlignment; - Options.TrapFuncName = TrapFuncName; - Options.PositionIndependentExecutable = EnablePIE; - Options.EnableSegmentedStacks = SegmentedStacks; - Options.UseInitArray = UseInitArray; -} - -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; -} - -/// makeBuffer - Create a MemoryBuffer from a memory range. -MemoryBuffer *LTOModule::makeBuffer(const void *mem, size_t length) { - const char *startPtr = (const char*)mem; - return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), "", false); -} - -/// objcClassNameFromExpression - Get string that the data pointer points to. -bool -LTOModule::objcClassNameFromExpression(const Constant *c, std::string &name) { - if (const ConstantExpr *ce = dyn_cast<ConstantExpr>(c)) { - Constant *op = ce->getOperand(0); - if (GlobalVariable *gvn = dyn_cast<GlobalVariable>(op)) { - Constant *cn = gvn->getInitializer(); - if (ConstantDataArray *ca = dyn_cast<ConstantDataArray>(cn)) { - if (ca->isCString()) { - name = ".objc_class_name_" + ca->getAsCString().str(); - return true; - } - } - } - } - return false; -} - -/// addObjCClass - Parse i386/ppc ObjC class data structure. -void LTOModule::addObjCClass(const GlobalVariable *clgv) { - const ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); - if (!c) return; - - // second slot in __OBJC,__class is pointer to superclass name - std::string superclassName; - if (objcClassNameFromExpression(c->getOperand(1), superclassName)) { - NameAndAttributes info; - StringMap<NameAndAttributes>::value_type &entry = - _undefines.GetOrCreateValue(superclassName); - if (!entry.getValue().name) { - const char *symbolName = entry.getKey().data(); - info.name = symbolName; - info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; - info.isFunction = false; - info.symbol = clgv; - entry.setValue(info); - } - } - - // third slot in __OBJC,__class is pointer to class name - std::string className; - if (objcClassNameFromExpression(c->getOperand(2), className)) { - StringSet::value_type &entry = _defines.GetOrCreateValue(className); - entry.setValue(1); - - NameAndAttributes info; - info.name = entry.getKey().data(); - info.attributes = LTO_SYMBOL_PERMISSIONS_DATA | - LTO_SYMBOL_DEFINITION_REGULAR | LTO_SYMBOL_SCOPE_DEFAULT; - info.isFunction = false; - info.symbol = clgv; - _symbols.push_back(info); - } -} - -/// addObjCCategory - Parse i386/ppc ObjC category data structure. -void LTOModule::addObjCCategory(const GlobalVariable *clgv) { - const ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); - if (!c) return; - - // second slot in __OBJC,__category is pointer to target class name - std::string targetclassName; - if (!objcClassNameFromExpression(c->getOperand(1), targetclassName)) - return; - - NameAndAttributes info; - StringMap<NameAndAttributes>::value_type &entry = - _undefines.GetOrCreateValue(targetclassName); - - if (entry.getValue().name) - return; - - const char *symbolName = entry.getKey().data(); - info.name = symbolName; - info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; - info.isFunction = false; - info.symbol = clgv; - entry.setValue(info); -} - -/// addObjCClassRef - Parse i386/ppc ObjC class list data structure. -void LTOModule::addObjCClassRef(const GlobalVariable *clgv) { - std::string targetclassName; - if (!objcClassNameFromExpression(clgv->getInitializer(), targetclassName)) - return; - - NameAndAttributes info; - StringMap<NameAndAttributes>::value_type &entry = - _undefines.GetOrCreateValue(targetclassName); - if (entry.getValue().name) - return; - - const char *symbolName = entry.getKey().data(); - info.name = symbolName; - info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; - info.isFunction = false; - info.symbol = clgv; - entry.setValue(info); -} - -/// addDefinedDataSymbol - Add a data symbol as defined to the list. -void LTOModule::addDefinedDataSymbol(const GlobalValue *v) { - // Add to list of defined symbols. - addDefinedSymbol(v, false); - - if (!v->hasSection() /* || !isTargetDarwin */) - return; - - // Special case i386/ppc ObjC data structures in magic sections: - // The issue is that the old ObjC object format did some strange - // contortions to avoid real linker symbols. For instance, the - // ObjC class data structure is allocated statically in the executable - // that defines that class. That data structures contains a pointer to - // its superclass. But instead of just initializing that part of the - // struct to the address of its superclass, and letting the static and - // dynamic linkers do the rest, the runtime works by having that field - // instead point to a C-string that is the name of the superclass. - // At runtime the objc initialization updates that pointer and sets - // it to point to the actual super class. As far as the linker - // knows it is just a pointer to a string. But then someone wanted the - // linker to issue errors at build time if the superclass was not found. - // So they figured out a way in mach-o object format to use an absolute - // symbols (.objc_class_name_Foo = 0) and a floating reference - // (.reference .objc_class_name_Bar) to cause the linker into erroring when - // a class was missing. - // The following synthesizes the implicit .objc_* symbols for the linker - // from the ObjC data structures generated by the front end. - - // special case if this data blob is an ObjC class definition - if (v->getSection().compare(0, 15, "__OBJC,__class,") == 0) { - if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { - addObjCClass(gv); - } - } - - // special case if this data blob is an ObjC category definition - else if (v->getSection().compare(0, 18, "__OBJC,__category,") == 0) { - if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { - addObjCCategory(gv); - } - } - - // special case if this data blob is the list of referenced classes - else if (v->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0) { - if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { - addObjCClassRef(gv); - } - } -} - -/// addDefinedFunctionSymbol - Add a function symbol as defined to the list. -void LTOModule::addDefinedFunctionSymbol(const Function *f) { - // add to list of defined symbols - addDefinedSymbol(f, true); -} - -/// addDefinedSymbol - Add a defined symbol to the list. -void LTOModule::addDefinedSymbol(const GlobalValue *def, bool isFunction) { - // ignore all llvm.* symbols - if (def->getName().startswith("llvm.")) - return; - - // string is owned by _defines - SmallString<64> Buffer; - _mangler.getNameWithPrefix(Buffer, def, false); - - // set alignment part log2() can have rounding errors - uint32_t align = def->getAlignment(); - uint32_t attr = align ? countTrailingZeros(def->getAlignment()) : 0; - - // set permissions part - if (isFunction) { - attr |= LTO_SYMBOL_PERMISSIONS_CODE; - } else { - const GlobalVariable *gv = dyn_cast<GlobalVariable>(def); - if (gv && gv->isConstant()) - attr |= LTO_SYMBOL_PERMISSIONS_RODATA; - else - attr |= LTO_SYMBOL_PERMISSIONS_DATA; - } - - // set definition part - if (def->hasWeakLinkage() || def->hasLinkOnceLinkage() || - def->hasLinkerPrivateWeakLinkage()) - attr |= LTO_SYMBOL_DEFINITION_WEAK; - else if (def->hasCommonLinkage()) - attr |= LTO_SYMBOL_DEFINITION_TENTATIVE; - else - attr |= LTO_SYMBOL_DEFINITION_REGULAR; - - // set scope part - if (def->hasHiddenVisibility()) - attr |= LTO_SYMBOL_SCOPE_HIDDEN; - else if (def->hasProtectedVisibility()) - attr |= LTO_SYMBOL_SCOPE_PROTECTED; - else if (def->hasExternalLinkage() || def->hasWeakLinkage() || - def->hasLinkOnceLinkage() || def->hasCommonLinkage() || - def->hasLinkerPrivateWeakLinkage()) - attr |= LTO_SYMBOL_SCOPE_DEFAULT; - else if (def->hasLinkOnceODRAutoHideLinkage()) - attr |= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN; - else - attr |= LTO_SYMBOL_SCOPE_INTERNAL; - - StringSet::value_type &entry = _defines.GetOrCreateValue(Buffer); - entry.setValue(1); - - // fill information structure - NameAndAttributes info; - StringRef Name = entry.getKey(); - info.name = Name.data(); - assert(info.name[Name.size()] == '\0'); - info.attributes = attr; - info.isFunction = isFunction; - info.symbol = def; - - // add to table of symbols - _symbols.push_back(info); -} - -/// addAsmGlobalSymbol - Add a global symbol from module-level ASM to the -/// defined list. -void LTOModule::addAsmGlobalSymbol(const char *name, - lto_symbol_attributes scope) { - StringSet::value_type &entry = _defines.GetOrCreateValue(name); - - // only add new define if not already defined - if (entry.getValue()) - return; - - entry.setValue(1); - - NameAndAttributes &info = _undefines[entry.getKey().data()]; - - if (info.symbol == 0) { - // FIXME: This is trying to take care of module ASM like this: - // - // module asm ".zerofill __FOO, __foo, _bar_baz_qux, 0" - // - // but is gross and its mother dresses it funny. Have the ASM parser give us - // more details for this type of situation so that we're not guessing so - // much. - - // fill information structure - info.name = entry.getKey().data(); - info.attributes = - LTO_SYMBOL_PERMISSIONS_DATA | LTO_SYMBOL_DEFINITION_REGULAR | scope; - info.isFunction = false; - info.symbol = 0; - - // add to table of symbols - _symbols.push_back(info); - return; - } - - if (info.isFunction) - addDefinedFunctionSymbol(cast<Function>(info.symbol)); - else - addDefinedDataSymbol(info.symbol); - - _symbols.back().attributes &= ~LTO_SYMBOL_SCOPE_MASK; - _symbols.back().attributes |= scope; -} - -/// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to the -/// undefined list. -void LTOModule::addAsmGlobalSymbolUndef(const char *name) { - StringMap<NameAndAttributes>::value_type &entry = - _undefines.GetOrCreateValue(name); - - _asm_undefines.push_back(entry.getKey().data()); - - // we already have the symbol - if (entry.getValue().name) - return; - - uint32_t attr = LTO_SYMBOL_DEFINITION_UNDEFINED;; - attr |= LTO_SYMBOL_SCOPE_DEFAULT; - NameAndAttributes info; - info.name = entry.getKey().data(); - info.attributes = attr; - info.isFunction = false; - info.symbol = 0; - - entry.setValue(info); -} - -/// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet to a -/// list to be resolved later. -void -LTOModule::addPotentialUndefinedSymbol(const GlobalValue *decl, bool isFunc) { - // ignore all llvm.* symbols - if (decl->getName().startswith("llvm.")) - return; - - // ignore all aliases - if (isa<GlobalAlias>(decl)) - return; - - SmallString<64> name; - _mangler.getNameWithPrefix(name, decl, false); - - StringMap<NameAndAttributes>::value_type &entry = - _undefines.GetOrCreateValue(name); - - // we already have the symbol - if (entry.getValue().name) - return; - - NameAndAttributes info; - - info.name = entry.getKey().data(); - - if (decl->hasExternalWeakLinkage()) - info.attributes = LTO_SYMBOL_DEFINITION_WEAKUNDEF; - else - info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; - - info.isFunction = isFunc; - info.symbol = decl; - - entry.setValue(info); -} - -namespace { - class RecordStreamer : public MCStreamer { - public: - enum State { NeverSeen, Global, Defined, DefinedGlobal, Used }; - - private: - StringMap<State> Symbols; - - void markDefined(const MCSymbol &Symbol) { - State &S = Symbols[Symbol.getName()]; - switch (S) { - case DefinedGlobal: - case Global: - S = DefinedGlobal; - break; - case NeverSeen: - case Defined: - case Used: - S = Defined; - break; - } - } - void markGlobal(const MCSymbol &Symbol) { - State &S = Symbols[Symbol.getName()]; - switch (S) { - case DefinedGlobal: - case Defined: - S = DefinedGlobal; - break; - - case NeverSeen: - case Global: - case Used: - S = Global; - break; - } - } - void markUsed(const MCSymbol &Symbol) { - State &S = Symbols[Symbol.getName()]; - switch (S) { - case DefinedGlobal: - case Defined: - case Global: - break; - - case NeverSeen: - case Used: - S = Used; - break; - } - } - - // FIXME: mostly copied for the obj streamer. - void AddValueSymbols(const MCExpr *Value) { - switch (Value->getKind()) { - case MCExpr::Target: - // FIXME: What should we do in here? - break; - - case MCExpr::Constant: - break; - - case MCExpr::Binary: { - const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value); - AddValueSymbols(BE->getLHS()); - AddValueSymbols(BE->getRHS()); - break; - } - - case MCExpr::SymbolRef: - markUsed(cast<MCSymbolRefExpr>(Value)->getSymbol()); - break; - - case MCExpr::Unary: - AddValueSymbols(cast<MCUnaryExpr>(Value)->getSubExpr()); - break; - } - } - - public: - typedef StringMap<State>::const_iterator const_iterator; - - const_iterator begin() { - return Symbols.begin(); - } - - const_iterator end() { - return Symbols.end(); - } - - RecordStreamer(MCContext &Context) - : MCStreamer(SK_RecordStreamer, Context) {} - - virtual void EmitInstruction(const MCInst &Inst) { - // Scan for values. - for (unsigned i = Inst.getNumOperands(); i--; ) - if (Inst.getOperand(i).isExpr()) - AddValueSymbols(Inst.getOperand(i).getExpr()); - } - virtual void EmitLabel(MCSymbol *Symbol) { - Symbol->setSection(*getCurrentSection().first); - markDefined(*Symbol); - } - virtual void EmitDebugLabel(MCSymbol *Symbol) { - EmitLabel(Symbol); - } - virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { - // FIXME: should we handle aliases? - markDefined(*Symbol); - } - virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { - if (Attribute == MCSA_Global) - markGlobal(*Symbol); - return true; - } - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size , unsigned ByteAlignment) { - markDefined(*Symbol); - } - virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) { - markDefined(*Symbol); - } - - virtual void EmitBundleAlignMode(unsigned AlignPow2) {} - virtual void EmitBundleLock(bool AlignToEnd) {} - virtual void EmitBundleUnlock() {} - - // Noop calls. - virtual void ChangeSection(const MCSection *Section, - const MCExpr *Subsection) {} - virtual void InitToTextSection() {} - virtual void InitSections() {} - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {} - virtual void EmitThumbFunc(MCSymbol *Func) {} - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} - virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {} - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) {} - virtual void EmitCOFFSymbolStorageClass(int StorageClass) {} - virtual void EmitCOFFSymbolType(int Type) {} - virtual void EndCOFFSymbolDef() {} - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) {} - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) {} - virtual void EmitBytes(StringRef Data) {} - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) {} - virtual void EmitULEB128Value(const MCExpr *Value) {} - virtual void EmitSLEB128Value(const MCExpr *Value) {} - virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, - unsigned ValueSize, - unsigned MaxBytesToEmit) {} - virtual void EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit) {} - virtual bool EmitValueToOffset(const MCExpr *Offset, - unsigned char Value ) { return false; } - virtual void EmitFileDirective(StringRef Filename) {} - virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, - const MCSymbol *LastLabel, - const MCSymbol *Label, - unsigned PointerSize) {} - virtual void FinishImpl() {} - virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { - RecordProcEnd(Frame); - } - - static bool classof(const MCStreamer *S) { - return S->getKind() == SK_RecordStreamer; - } - }; -} // end anonymous namespace - -/// addAsmGlobalSymbols - Add global symbols from module-level ASM to the -/// defined or undefined lists. -bool LTOModule::addAsmGlobalSymbols(std::string &errMsg) { - const std::string &inlineAsm = _module->getModuleInlineAsm(); - if (inlineAsm.empty()) - return false; - - OwningPtr<RecordStreamer> Streamer(new RecordStreamer(_context)); - MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(inlineAsm); - SourceMgr SrcMgr; - SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); - OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, - _context, *Streamer, - *_target->getMCAsmInfo())); - const Target &T = _target->getTarget(); - OwningPtr<MCInstrInfo> MCII(T.createMCInstrInfo()); - OwningPtr<MCSubtargetInfo> - STI(T.createMCSubtargetInfo(_target->getTargetTriple(), - _target->getTargetCPU(), - _target->getTargetFeatureString())); - OwningPtr<MCTargetAsmParser> TAP(T.createMCAsmParser(*STI, *Parser.get(), *MCII)); - if (!TAP) { - errMsg = "target " + std::string(T.getName()) + - " does not define AsmParser."; - return true; - } - - Parser->setTargetParser(*TAP); - if (Parser->Run(false)) - return true; - - for (RecordStreamer::const_iterator i = Streamer->begin(), - e = Streamer->end(); i != e; ++i) { - StringRef Key = i->first(); - RecordStreamer::State Value = i->second; - if (Value == RecordStreamer::DefinedGlobal) - addAsmGlobalSymbol(Key.data(), LTO_SYMBOL_SCOPE_DEFAULT); - else if (Value == RecordStreamer::Defined) - addAsmGlobalSymbol(Key.data(), LTO_SYMBOL_SCOPE_INTERNAL); - else if (Value == RecordStreamer::Global || - Value == RecordStreamer::Used) - addAsmGlobalSymbolUndef(Key.data()); - } - - return false; -} - -/// isDeclaration - Return 'true' if the global value is a declaration. -static bool isDeclaration(const GlobalValue &V) { - if (V.hasAvailableExternallyLinkage()) - return true; - - if (V.isMaterializable()) - return false; - - return V.isDeclaration(); -} - -/// parseSymbols - Parse the symbols from the module and model-level ASM and add -/// them to either the defined or undefined lists. -bool LTOModule::parseSymbols(std::string &errMsg) { - // add functions - for (Module::iterator f = _module->begin(), e = _module->end(); f != e; ++f) { - if (isDeclaration(*f)) - addPotentialUndefinedSymbol(f, true); - else - addDefinedFunctionSymbol(f); - } - - // add data - for (Module::global_iterator v = _module->global_begin(), - e = _module->global_end(); v != e; ++v) { - if (isDeclaration(*v)) - addPotentialUndefinedSymbol(v, false); - else - addDefinedDataSymbol(v); - } - - // add asm globals - if (addAsmGlobalSymbols(errMsg)) - return true; - - // add aliases - for (Module::alias_iterator a = _module->alias_begin(), - e = _module->alias_end(); a != e; ++a) { - if (isDeclaration(*a->getAliasedGlobal())) - // Is an alias to a declaration. - addPotentialUndefinedSymbol(a, false); - else - addDefinedDataSymbol(a); - } - - // make symbols for all undefines - for (StringMap<NameAndAttributes>::iterator u =_undefines.begin(), - e = _undefines.end(); u != e; ++u) { - // If this symbol also has a definition, then don't make an undefine because - // it is a tentative definition. - if (_defines.count(u->getKey())) continue; - NameAndAttributes info = u->getValue(); - _symbols.push_back(info); - } - - return false; -} diff --git a/tools/lto/LTOModule.h b/tools/lto/LTOModule.h deleted file mode 100644 index 902e9c5..0000000 --- a/tools/lto/LTOModule.h +++ /dev/null @@ -1,190 +0,0 @@ -//===-LTOModule.h - LLVM Link Time Optimizer ------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares the LTOModule class. -// -//===----------------------------------------------------------------------===// - -#ifndef LTO_MODULE_H -#define LTO_MODULE_H - -#include "llvm-c/lto.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/IR/Module.h" -#include "llvm/MC/MCContext.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetMachine.h" -#include <string> -#include <vector> - -// Forward references to llvm classes. -namespace llvm { - class Function; - class GlobalValue; - class MemoryBuffer; - class TargetOptions; - class Value; -} - -//===----------------------------------------------------------------------===// -/// LTOModule - C++ class which implements the opaque lto_module_t type. -/// -struct LTOModule { -private: - typedef llvm::StringMap<uint8_t> StringSet; - - struct NameAndAttributes { - const char *name; - uint32_t attributes; - bool isFunction; - const llvm::GlobalValue *symbol; - }; - - llvm::OwningPtr<llvm::Module> _module; - llvm::OwningPtr<llvm::TargetMachine> _target; - std::vector<NameAndAttributes> _symbols; - - // _defines and _undefines only needed to disambiguate tentative definitions - StringSet _defines; - llvm::StringMap<NameAndAttributes> _undefines; - std::vector<const char*> _asm_undefines; - llvm::MCContext _context; - - // Use mangler to add GlobalPrefix to names to match linker names. - llvm::Mangler _mangler; - - LTOModule(llvm::Module *m, llvm::TargetMachine *t); -public: - /// isBitcodeFile - Returns 'true' if the file or memory contents is LLVM - /// bitcode. - static bool isBitcodeFile(const void *mem, size_t length); - static bool isBitcodeFile(const char *path); - - /// isBitcodeFileForTarget - Returns 'true' if the file or memory contents - /// is LLVM bitcode for the specified triple. - static bool isBitcodeFileForTarget(const void *mem, - size_t length, - const char *triplePrefix); - static bool isBitcodeFileForTarget(const char *path, - const char *triplePrefix); - - /// makeLTOModule - Create an LTOModule. N.B. These methods take ownership - /// of the buffer. - static LTOModule *makeLTOModule(const char* path, - std::string &errMsg); - static LTOModule *makeLTOModule(int fd, const char *path, - size_t size, std::string &errMsg); - static LTOModule *makeLTOModule(int fd, const char *path, - size_t map_size, - off_t offset, - std::string& errMsg); - static LTOModule *makeLTOModule(const void *mem, size_t length, - std::string &errMsg); - - /// getTargetTriple - Return the Module's target triple. - const char *getTargetTriple() { - return _module->getTargetTriple().c_str(); - } - - /// setTargetTriple - Set the Module's target triple. - void setTargetTriple(const char *triple) { - _module->setTargetTriple(triple); - } - - /// getSymbolCount - Get the number of symbols - uint32_t getSymbolCount() { - return _symbols.size(); - } - - /// getSymbolAttributes - Get the attributes for a symbol at the specified - /// index. - lto_symbol_attributes getSymbolAttributes(uint32_t index) { - if (index < _symbols.size()) - return lto_symbol_attributes(_symbols[index].attributes); - return lto_symbol_attributes(0); - } - - /// getSymbolName - Get the name of the symbol at the specified index. - const char *getSymbolName(uint32_t index) { - if (index < _symbols.size()) - return _symbols[index].name; - return NULL; - } - - /// getLLVVMModule - Return the Module. - llvm::Module *getLLVVMModule() { return _module.get(); } - - /// getAsmUndefinedRefs - - const std::vector<const char*> &getAsmUndefinedRefs() { - return _asm_undefines; - } - - /// getTargetOptions - Fill the TargetOptions object with the options - /// specified on the command line. - static void getTargetOptions(llvm::TargetOptions &Options); - -private: - /// parseSymbols - Parse the symbols from the module and model-level ASM and - /// add them to either the defined or undefined lists. - bool parseSymbols(std::string &errMsg); - - /// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet - /// to a list to be resolved later. - void addPotentialUndefinedSymbol(const llvm::GlobalValue *dcl, bool isFunc); - - /// addDefinedSymbol - Add a defined symbol to the list. - void addDefinedSymbol(const llvm::GlobalValue *def, bool isFunction); - - /// addDefinedFunctionSymbol - Add a function symbol as defined to the list. - void addDefinedFunctionSymbol(const llvm::Function *f); - - /// addDefinedDataSymbol - Add a data symbol as defined to the list. - void addDefinedDataSymbol(const llvm::GlobalValue *v); - - /// addAsmGlobalSymbols - Add global symbols from module-level ASM to the - /// defined or undefined lists. - bool addAsmGlobalSymbols(std::string &errMsg); - - /// addAsmGlobalSymbol - Add a global symbol from module-level ASM to the - /// defined list. - void addAsmGlobalSymbol(const char *, lto_symbol_attributes scope); - - /// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to - /// the undefined list. - void addAsmGlobalSymbolUndef(const char *); - - /// addObjCClass - Parse i386/ppc ObjC class data structure. - void addObjCClass(const llvm::GlobalVariable *clgv); - - /// addObjCCategory - Parse i386/ppc ObjC category data structure. - void addObjCCategory(const llvm::GlobalVariable *clgv); - - /// addObjCClassRef - Parse i386/ppc ObjC class list data structure. - void addObjCClassRef(const llvm::GlobalVariable *clgv); - - /// objcClassNameFromExpression - Get string that the data pointer points - /// to. - bool objcClassNameFromExpression(const llvm::Constant* c, std::string &name); - - /// isTargetMatch - Returns 'true' if the memory buffer is for the specified - /// target triple. - static bool isTargetMatch(llvm::MemoryBuffer *memBuffer, - const char *triplePrefix); - - /// makeLTOModule - Create an LTOModule (private version). N.B. This - /// method takes ownership of the buffer. - static LTOModule *makeLTOModule(llvm::MemoryBuffer *buffer, - std::string &errMsg); - - /// makeBuffer - Create a MemoryBuffer from a memory range. - static llvm::MemoryBuffer *makeBuffer(const void *mem, size_t length); -}; - -#endif // LTO_MODULE_H diff --git a/tools/lto/Makefile b/tools/lto/Makefile index 56c67df..672fef4 100644 --- a/tools/lto/Makefile +++ b/tools/lto/Makefile @@ -10,7 +10,7 @@ LEVEL := ../.. LIBRARYNAME := LTO LINK_COMPONENTS := all-targets ipo scalaropts linker bitreader bitwriter \ - mcdisassembler vectorize + lto mcdisassembler vectorize LINK_LIBS_IN_SHARED := 1 SHARED_LIBRARY := 1 diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index db7147c..441bc77 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -13,15 +13,33 @@ //===----------------------------------------------------------------------===// #include "llvm-c/lto.h" -#include "LTOCodeGenerator.h" -#include "LTOModule.h" +#include "llvm/LTO/LTOCodeGenerator.h" +#include "llvm/LTO/LTOModule.h" #include "llvm-c/Core.h" +#include "llvm-c/Target.h" // Holds most recent error string. // *** Not thread safe *** static std::string sLastErrorString; +// Holds the initialization state of the LTO module. +// *** Not thread safe *** +static bool initialized = false; + +// Initialize the configured targets if they have not been initialized. +static void lto_initialize() { + if (!initialized) { + LLVMInitializeAllTargetInfos(); + LLVMInitializeAllTargets(); + LLVMInitializeAllTargetMCs(); + LLVMInitializeAllAsmParsers(); + LLVMInitializeAllAsmPrinters(); + LLVMInitializeAllDisassemblers(); + initialized = true; + } +} + /// lto_get_version - Returns a printable string. extern const char* lto_get_version() { return LTOCodeGenerator::getVersionString(); @@ -63,12 +81,14 @@ lto_module_is_object_file_in_memory_for_target(const void* mem, /// lto_module_create - Loads an object file from disk. Returns NULL on error /// (check lto_get_error_message() for details). lto_module_t lto_module_create(const char* path) { + lto_initialize(); return LTOModule::makeLTOModule(path, sLastErrorString); } /// lto_module_create_from_fd - Loads an object file from disk. Returns NULL on /// error (check lto_get_error_message() for details). lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) { + lto_initialize(); return LTOModule::makeLTOModule(fd, path, size, sLastErrorString); } @@ -78,12 +98,14 @@ lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path, size_t file_size, size_t map_size, off_t offset) { + lto_initialize(); return LTOModule::makeLTOModule(fd, path, map_size, offset, sLastErrorString); } /// lto_module_create_from_memory - Loads an object file from memory. Returns /// NULL on error (check lto_get_error_message() for details). lto_module_t lto_module_create_from_memory(const void* mem, size_t length) { + lto_initialize(); return LTOModule::makeLTOModule(mem, length, sLastErrorString); } @@ -127,6 +149,7 @@ lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod, /// lto_codegen_create - Instantiates a code generator. Returns NULL if there /// is an error. lto_code_gen_t lto_codegen_create(void) { + lto_initialize(); return new LTOCodeGenerator(); } |