summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/LTO
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
committerdim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
commit9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch)
treec978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/lib/LTO
parent03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff)
downloadFreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip
FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports all of the features in the current working draft of the upcoming C++ standard, provisionally named C++1y. The code generator's performance is greatly increased, and the loop auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The PowerPC backend has made several major improvements to code generation quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ backends have all seen major feature work. Release notes for llvm and clang can be found here: <http://llvm.org/releases/3.4/docs/ReleaseNotes.html> <http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html> MFC 262121 (by emaste): Update lldb for clang/llvm 3.4 import This commit largely restores the lldb source to the upstream r196259 snapshot with the addition of threaded inferior support and a few bug fixes. Specific upstream lldb revisions restored include: SVN git 181387 779e6ac 181703 7bef4e2 182099 b31044e 182650 f2dcf35 182683 0d91b80 183862 15c1774 183929 99447a6 184177 0b2934b 184948 4dc3761 184954 007e7bc 186990 eebd175 Sponsored by: DARPA, AFRL MFC 262186 (by emaste): Fix mismerge in r262121 A break statement was lost in the merge. The error had no functional impact, but restore it to reduce the diff against upstream. MFC 262303: Pull in r197521 from upstream clang trunk (by rdivacky): Use the integrated assembler by default on FreeBSD/ppc and ppc64. Requested by: jhibbits MFC 262611: Pull in r196874 from upstream llvm trunk: Fix a crash that occurs when PWD is invalid. MCJIT needs to be able to run in hostile environments, even when PWD is invalid. There's no need to crash MCJIT in this case. The obvious fix is to simply leave MCContext's CompilationDir empty when PWD can't be determined. This way, MCJIT clients, and other clients that link with LLVM don't need a valid working directory. If we do want to guarantee valid CompilationDir, that should be done only for clients of getCompilationDir(). This is as simple as checking for an empty string. The only current use of getCompilationDir is EmitGenDwarfInfo, which won't conceivably run with an invalid working dir. However, in the purely hypothetically and untestable case that this happens, the AT_comp_dir will be omitted from the compilation_unit DIE. This should help fix assertions occurring with ports-mgmt/tinderbox, when it is using jails, and sometimes invalidates clang's current working directory. Reported by: decke MFC 262809: Pull in r203007 from upstream clang trunk: Don't produce an alias between destructors with different calling conventions. Fixes pr19007. (Please note that is an LLVM PR identifier, not a FreeBSD one.) This should fix Firefox and/or libxul crashes (due to problems with regparm/stdcall calling conventions) on i386. Reported by: multiple users on freebsd-current PR: bin/187103 MFC 263048: Repair recognition of "CC" as an alias for the C++ compiler, since it was silently broken by upstream for a Windows-specific use-case. Apparently some versions of CMake still rely on this archaic feature... Reported by: rakuco MFC 263049: Garbage collect the old way of adding the libstdc++ include directories in clang's InitHeaderSearch.cpp. This has been superseded by David Chisnall's commit in r255321. Moreover, if libc++ is used, the libstdc++ include directories should not be in the search path at all. These directories are now only used if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/lib/LTO')
-rw-r--r--contrib/llvm/lib/LTO/LTOCodeGenerator.cpp521
-rw-r--r--contrib/llvm/lib/LTO/LTOModule.cpp794
2 files changed, 1315 insertions, 0 deletions
diff --git a/contrib/llvm/lib/LTO/LTOCodeGenerator.cpp b/contrib/llvm/lib/LTO/LTOCodeGenerator.cpp
new file mode 100644
index 0000000..2b3648e
--- /dev/null
+++ b/contrib/llvm/lib/LTO/LTOCodeGenerator.cpp
@@ -0,0 +1,521 @@
+//===-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 "llvm/LTO/LTOCodeGenerator.h"
+#include "llvm/LTO/LTOModule.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Analysis/Passes.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/CodeGen/RuntimeLibcalls.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/TargetLibraryInfo.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/Mangler.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Transforms/ObjCARC.h"
+using namespace llvm;
+
+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) {
+ initializeLTOPasses();
+}
+
+LTOCodeGenerator::~LTOCodeGenerator() {
+ delete TargetMach;
+ delete NativeObjectFile;
+ TargetMach = NULL;
+ NativeObjectFile = NULL;
+
+ Linker.deleteModule();
+
+ 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::setTargetOptions(TargetOptions options) {
+ Options.LessPreciseFPMADOption = options.LessPreciseFPMADOption;
+ Options.NoFramePointerElim = options.NoFramePointerElim;
+ Options.AllowFPOpFusion = options.AllowFPOpFusion;
+ Options.UnsafeFPMath = options.UnsafeFPMath;
+ Options.NoInfsFPMath = options.NoInfsFPMath;
+ Options.NoNaNsFPMath = options.NoNaNsFPMath;
+ Options.HonorSignDependentRoundingFPMathOption =
+ options.HonorSignDependentRoundingFPMathOption;
+ Options.UseSoftFloat = options.UseSoftFloat;
+ Options.FloatABIType = options.FloatABIType;
+ Options.NoZerosInBSS = options.NoZerosInBSS;
+ Options.GuaranteedTailCallOpt = options.GuaranteedTailCallOpt;
+ Options.DisableTailCalls = options.DisableTailCalls;
+ Options.StackAlignmentOverride = options.StackAlignmentOverride;
+ Options.TrapFuncName = options.TrapFuncName;
+ Options.PositionIndependentExecutable = options.PositionIndependentExecutable;
+ Options.EnableSegmentedStacks = options.EnableSegmentedStacks;
+ Options.UseInitArray = options.UseInitArray;
+}
+
+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,
+ bool disableOpt,
+ bool disableInline,
+ bool disableGVNLoadPRE,
+ 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(), disableOpt, disableInline,
+ disableGVNLoadPRE, 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,
+ bool disableOpt,
+ bool disableInline,
+ bool disableGVNLoadPRE,
+ std::string& errMsg) {
+ const char *name;
+ if (!compile_to_file(&name, disableOpt, disableInline, disableGVNLoadPRE,
+ 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;
+
+ 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";
+ }
+
+ TargetMach = march->createTargetMachine(TripleStr, MCpu, FeatureStr, Options,
+ RelocModel, CodeModel::Default,
+ CodeGenOpt::Aggressive);
+ return true;
+}
+
+void LTOCodeGenerator::
+applyRestriction(GlobalValue &GV,
+ const ArrayRef<StringRef> &Libcalls,
+ 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);
+
+ // Conservatively append user-supplied runtime library functions to
+ // llvm.compiler.used. These could be internalized and deleted by
+ // optimizations like -globalopt, causing problems when later optimizations
+ // add new library calls (e.g., llvm.memset => memset and printf => puts).
+ // Leave it to the linker to remove any dead code (e.g. with -dead_strip).
+ if (isa<Function>(GV) &&
+ std::binary_search(Libcalls.begin(), Libcalls.end(), GV.getName()))
+ 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);
+}
+
+static void accumulateAndSortLibcalls(std::vector<StringRef> &Libcalls,
+ const TargetLibraryInfo& TLI,
+ const TargetLowering *Lowering)
+{
+ // TargetLibraryInfo has info on C runtime library calls on the current
+ // target.
+ for (unsigned I = 0, E = static_cast<unsigned>(LibFunc::NumLibFuncs);
+ I != E; ++I) {
+ LibFunc::Func F = static_cast<LibFunc::Func>(I);
+ if (TLI.has(F))
+ Libcalls.push_back(TLI.getName(F));
+ }
+
+ // TargetLowering has info on library calls that CodeGen expects to be
+ // available, both from the C runtime and compiler-rt.
+ if (Lowering)
+ for (unsigned I = 0, E = static_cast<unsigned>(RTLIB::UNKNOWN_LIBCALL);
+ I != E; ++I)
+ if (const char *Name
+ = Lowering->getLibcallName(static_cast<RTLIB::Libcall>(I)))
+ Libcalls.push_back(Name);
+
+ array_pod_sort(Libcalls.begin(), Libcalls.end());
+ Libcalls.erase(std::unique(Libcalls.begin(), Libcalls.end()),
+ Libcalls.end());
+}
+
+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
+ Mangler Mangler(TargetMach);
+ std::vector<const char*> MustPreserveList;
+ SmallPtrSet<GlobalValue*, 8> AsmUsed;
+ std::vector<StringRef> Libcalls;
+ TargetLibraryInfo TLI(Triple(TargetMach->getTargetTriple()));
+ accumulateAndSortLibcalls(Libcalls, TLI, TargetMach->getTargetLowering());
+
+ for (Module::iterator f = mergedModule->begin(),
+ e = mergedModule->end(); f != e; ++f)
+ applyRestriction(*f, Libcalls, MustPreserveList, AsmUsed, Mangler);
+ for (Module::global_iterator v = mergedModule->global_begin(),
+ e = mergedModule->global_end(); v != e; ++v)
+ applyRestriction(*v, Libcalls, MustPreserveList, AsmUsed, Mangler);
+ for (Module::alias_iterator a = mergedModule->alias_begin(),
+ e = mergedModule->alias_end(); a != e; ++a)
+ applyRestriction(*a, Libcalls, 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,
+ bool DisableOpt,
+ bool DisableInline,
+ bool DisableGVNLoadPRE,
+ 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("libLLVMLTO"));
+ CodegenOptions.push_back(strdup(o.first.str().c_str()));
+ }
+}
+
+void LTOCodeGenerator::parseCodeGenDebugOptions() {
+ // if options were requested, set them
+ if (!CodegenOptions.empty())
+ cl::ParseCommandLineOptions(CodegenOptions.size(),
+ const_cast<char **>(&CodegenOptions[0]));
+}
diff --git a/contrib/llvm/lib/LTO/LTOModule.cpp b/contrib/llvm/lib/LTO/LTOModule.cpp
new file mode 100644
index 0000000..65416be
--- /dev/null
+++ b/contrib/llvm/lib/LTO/LTOModule.cpp
@@ -0,0 +1,794 @@
+//===-- 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 "llvm/LTO/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"
+#include "llvm/Transforms/Utils/GlobalStatus.h"
+using namespace llvm;
+
+LTOModule::LTOModule(llvm::Module *m, llvm::TargetMachine *t)
+ : _module(m), _target(t),
+ _context(_target->getMCAsmInfo(), _target->getRegisterInfo(), NULL),
+ _mangler(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, TargetOptions options,
+ std::string &errMsg) {
+ OwningPtr<MemoryBuffer> buffer;
+ if (error_code ec = MemoryBuffer::getFile(path, buffer)) {
+ errMsg = ec.message();
+ return NULL;
+ }
+ return makeLTOModule(buffer.take(), options, errMsg);
+}
+
+LTOModule *LTOModule::makeLTOModule(int fd, const char *path,
+ size_t size, TargetOptions options,
+ std::string &errMsg) {
+ return makeLTOModule(fd, path, size, 0, options, errMsg);
+}
+
+LTOModule *LTOModule::makeLTOModule(int fd, const char *path,
+ size_t map_size,
+ off_t offset,
+ TargetOptions options,
+ 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(), options, errMsg);
+}
+
+LTOModule *LTOModule::makeLTOModule(const void *mem, size_t length,
+ TargetOptions options,
+ std::string &errMsg) {
+ OwningPtr<MemoryBuffer> buffer(makeBuffer(mem, length));
+ if (!buffer)
+ return NULL;
+ return makeLTOModule(buffer.take(), options, errMsg);
+}
+
+LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer,
+ TargetOptions options,
+ std::string &errMsg) {
+ // 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";
+ }
+
+ 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;
+ }
+
+ 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);
+}
+
+static bool canBeHidden(const GlobalValue *GV) {
+ GlobalValue::LinkageTypes L = GV->getLinkage();
+
+ if (L != GlobalValue::LinkOnceODRLinkage)
+ return false;
+
+ if (GV->hasUnnamedAddr())
+ return true;
+
+ GlobalStatus GS;
+ if (GlobalStatus::analyzeGlobal(GV, GS))
+ return false;
+
+ return !GS.IsCompared;
+}
+
+/// 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 (canBeHidden(def))
+ attr |= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN;
+ else if (def->hasExternalLinkage() || def->hasWeakLinkage() ||
+ def->hasLinkOnceLinkage() || def->hasCommonLinkage() ||
+ def->hasLinkerPrivateWeakLinkage())
+ attr |= LTO_SYMBOL_SCOPE_DEFAULT;
+ 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(Context, 0) {}
+
+ 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);
+ }
+ };
+} // 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;
+}
OpenPOWER on IntegriCloud