From 71d5a2540a98c81f5bcaeb48805e0e2881f530ef Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sun, 16 Apr 2017 16:01:22 +0000 Subject: Vendor import of llvm trunk r300422: https://llvm.org/svn/llvm-project/llvm/trunk@300422 --- tools/bugpoint/CrashDebugger.cpp | 8 +- tools/bugpoint/ExtractFunction.cpp | 1 + tools/bugpoint/FindBugs.cpp | 6 +- tools/bugpoint/ListReducer.h | 5 +- tools/bugpoint/Miscompilation.cpp | 25 +- tools/bugpoint/ToolRunner.cpp | 67 +- tools/bugpoint/bugpoint.cpp | 3 +- tools/dsymutil/DwarfLinker.cpp | 115 ++-- tools/dsymutil/MachOUtils.cpp | 4 +- tools/gold/gold-plugin.cpp | 99 ++- tools/llc/CMakeLists.txt | 1 + tools/llc/LLVMBuild.txt | 2 +- tools/llc/llc.cpp | 49 ++ tools/lli/OrcLazyJIT.h | 4 +- tools/lli/lli.cpp | 3 +- tools/llvm-ar/llvm-ar.cpp | 25 +- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 5 +- tools/llvm-c-test/echo.cpp | 2 +- tools/llvm-cat/llvm-cat.cpp | 4 +- tools/llvm-cov/CodeCoverage.cpp | 42 +- tools/llvm-cov/CoverageReport.cpp | 69 ++- tools/llvm-cov/CoverageReport.h | 6 +- tools/llvm-cov/CoverageSummaryInfo.h | 13 + tools/llvm-cov/TestingSupport.cpp | 7 +- tools/llvm-cov/gcov.cpp | 2 +- tools/llvm-cxxfilt/llvm-cxxfilt.cpp | 78 ++- tools/llvm-diff/DiffConsumer.cpp | 7 +- tools/llvm-diff/DifferenceEngine.cpp | 16 +- tools/llvm-dwp/llvm-dwp.cpp | 55 +- tools/llvm-extract/llvm-extract.cpp | 35 +- tools/llvm-link/llvm-link.cpp | 23 +- tools/llvm-lto/llvm-lto.cpp | 6 + tools/llvm-lto2/llvm-lto2.cpp | 124 +++- tools/llvm-mc-assemble-fuzzer/CMakeLists.txt | 19 + .../llvm-mc-assemble-fuzzer.cpp | 313 ++++++++++ tools/llvm-mc-disassemble-fuzzer/CMakeLists.txt | 21 + .../llvm-mc-disassemble-fuzzer.cpp | 143 +++++ tools/llvm-mc-fuzzer/CMakeLists.txt | 18 - tools/llvm-mc-fuzzer/llvm-mc-fuzzer.cpp | 159 ----- tools/llvm-mc/llvm-mc.cpp | 2 +- tools/llvm-nm/llvm-nm.cpp | 33 +- tools/llvm-objdump/MachODump.cpp | 532 +++++++++------- tools/llvm-objdump/llvm-objdump.cpp | 104 +++- tools/llvm-objdump/llvm-objdump.h | 17 +- tools/llvm-pdbdump/Analyze.cpp | 164 +++++ tools/llvm-pdbdump/Analyze.h | 30 + tools/llvm-pdbdump/CMakeLists.txt | 6 + tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp | 57 ++ tools/llvm-pdbdump/CompactTypeDumpVisitor.h | 47 ++ tools/llvm-pdbdump/Diff.cpp | 523 ++++++++++++++++ tools/llvm-pdbdump/Diff.h | 45 ++ tools/llvm-pdbdump/LLVMOutputStyle.cpp | 337 +++++----- tools/llvm-pdbdump/LLVMOutputStyle.h | 9 +- tools/llvm-pdbdump/LinePrinter.cpp | 36 +- tools/llvm-pdbdump/LinePrinter.h | 12 +- tools/llvm-pdbdump/PdbYaml.cpp | 117 ++-- tools/llvm-pdbdump/PdbYaml.h | 55 +- tools/llvm-pdbdump/PrettyBuiltinDumper.cpp | 4 + tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp | 229 +++---- tools/llvm-pdbdump/PrettyClassDefinitionDumper.h | 38 +- .../PrettyClassLayoutGraphicalDumper.cpp | 151 +++++ .../PrettyClassLayoutGraphicalDumper.h | 47 ++ tools/llvm-pdbdump/PrettyClassLayoutTextDumper.cpp | 119 ++++ tools/llvm-pdbdump/PrettyClassLayoutTextDumper.h | 44 ++ tools/llvm-pdbdump/PrettyFunctionDumper.cpp | 10 +- tools/llvm-pdbdump/PrettyTypeDumper.cpp | 199 ++++-- tools/llvm-pdbdump/PrettyTypeDumper.h | 4 +- tools/llvm-pdbdump/PrettyTypedefDumper.cpp | 7 +- tools/llvm-pdbdump/PrettyVariableDumper.cpp | 163 +++-- tools/llvm-pdbdump/PrettyVariableDumper.h | 9 +- tools/llvm-pdbdump/StreamUtil.cpp | 136 ++++ tools/llvm-pdbdump/StreamUtil.h | 25 + tools/llvm-pdbdump/YAMLOutputStyle.cpp | 44 +- tools/llvm-pdbdump/YAMLOutputStyle.h | 1 + tools/llvm-pdbdump/YamlSymbolDumper.cpp | 1 + tools/llvm-pdbdump/YamlTypeDumper.cpp | 23 +- tools/llvm-pdbdump/fuzzer/llvm-pdbdump-fuzzer.cpp | 11 +- tools/llvm-pdbdump/llvm-pdbdump.cpp | 327 +++++++--- tools/llvm-pdbdump/llvm-pdbdump.h | 21 +- tools/llvm-profdata/llvm-profdata.cpp | 122 ++-- tools/llvm-readobj/ARMAttributeParser.cpp | 682 --------------------- tools/llvm-readobj/ARMAttributeParser.h | 126 ---- tools/llvm-readobj/CMakeLists.txt | 3 +- tools/llvm-readobj/COFFDumper.cpp | 95 ++- tools/llvm-readobj/ELFDumper.cpp | 60 +- tools/llvm-readobj/LLVMBuild.txt | 2 +- tools/llvm-readobj/MachODumper.cpp | 20 +- tools/llvm-readobj/ObjDumper.h | 12 +- tools/llvm-readobj/WasmDumper.cpp | 177 ++++++ tools/llvm-readobj/llvm-readobj.cpp | 23 +- tools/llvm-shlib/CMakeLists.txt | 2 +- tools/llvm-stress/llvm-stress.cpp | 13 +- tools/llvm-strings/llvm-strings.cpp | 34 +- tools/llvm-symbolizer/llvm-symbolizer.cpp | 5 +- tools/llvm-xray/CMakeLists.txt | 2 + tools/llvm-xray/llvm-xray.cc | 10 +- tools/llvm-xray/xray-account.cc | 96 ++- tools/llvm-xray/xray-color-helper.cc | 198 ++++++ tools/llvm-xray/xray-color-helper.h | 81 +++ tools/llvm-xray/xray-converter.cc | 69 +-- tools/llvm-xray/xray-extract.cc | 244 +------- tools/llvm-xray/xray-extract.h | 58 -- tools/llvm-xray/xray-graph.cc | 529 ++++++++++++++++ tools/llvm-xray/xray-graph.h | 164 +++++ tools/llvm-xray/xray-sleds.h | 32 - tools/lto/lto.cpp | 14 +- tools/msbuild/CMakeLists.txt | 2 +- tools/obj2yaml/CMakeLists.txt | 1 + tools/obj2yaml/dwarf2yaml.cpp | 37 +- tools/obj2yaml/elf2yaml.cpp | 16 +- tools/obj2yaml/macho2yaml.cpp | 17 + tools/obj2yaml/obj2yaml.cpp | 2 + tools/obj2yaml/obj2yaml.h | 3 + tools/obj2yaml/wasm2yaml.cpp | 219 +++++++ tools/opt/GraphPrinters.cpp | 2 +- tools/opt/opt.cpp | 48 +- tools/sancov/coverage-report-server.py | 4 +- tools/sancov/sancov.cc | 40 +- tools/yaml2obj/CMakeLists.txt | 2 +- tools/yaml2obj/yaml2dwarf.cpp | 330 ---------- tools/yaml2obj/yaml2macho.cpp | 32 +- tools/yaml2obj/yaml2obj.cpp | 28 +- tools/yaml2obj/yaml2obj.h | 16 +- tools/yaml2obj/yaml2wasm.cpp | 377 ++++++++++++ 124 files changed, 6278 insertions(+), 3094 deletions(-) create mode 100644 tools/llvm-mc-assemble-fuzzer/CMakeLists.txt create mode 100644 tools/llvm-mc-assemble-fuzzer/llvm-mc-assemble-fuzzer.cpp create mode 100644 tools/llvm-mc-disassemble-fuzzer/CMakeLists.txt create mode 100644 tools/llvm-mc-disassemble-fuzzer/llvm-mc-disassemble-fuzzer.cpp delete mode 100644 tools/llvm-mc-fuzzer/CMakeLists.txt delete mode 100644 tools/llvm-mc-fuzzer/llvm-mc-fuzzer.cpp create mode 100644 tools/llvm-pdbdump/Analyze.cpp create mode 100644 tools/llvm-pdbdump/Analyze.h create mode 100644 tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp create mode 100644 tools/llvm-pdbdump/CompactTypeDumpVisitor.h create mode 100644 tools/llvm-pdbdump/Diff.cpp create mode 100644 tools/llvm-pdbdump/Diff.h create mode 100644 tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.cpp create mode 100644 tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.h create mode 100644 tools/llvm-pdbdump/PrettyClassLayoutTextDumper.cpp create mode 100644 tools/llvm-pdbdump/PrettyClassLayoutTextDumper.h create mode 100644 tools/llvm-pdbdump/StreamUtil.cpp create mode 100644 tools/llvm-pdbdump/StreamUtil.h delete mode 100644 tools/llvm-readobj/ARMAttributeParser.cpp delete mode 100644 tools/llvm-readobj/ARMAttributeParser.h create mode 100644 tools/llvm-readobj/WasmDumper.cpp create mode 100644 tools/llvm-xray/xray-color-helper.cc create mode 100644 tools/llvm-xray/xray-color-helper.h delete mode 100644 tools/llvm-xray/xray-extract.h create mode 100644 tools/llvm-xray/xray-graph.cc create mode 100644 tools/llvm-xray/xray-graph.h delete mode 100644 tools/llvm-xray/xray-sleds.h create mode 100644 tools/obj2yaml/wasm2yaml.cpp delete mode 100644 tools/yaml2obj/yaml2dwarf.cpp create mode 100644 tools/yaml2obj/yaml2wasm.cpp (limited to 'tools') diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp index 0cae0669477f2..2fd8699c5fc8f 100644 --- a/tools/bugpoint/CrashDebugger.cpp +++ b/tools/bugpoint/CrashDebugger.cpp @@ -731,7 +731,8 @@ bool ReduceCrashingInstructions::TestInsts( for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) { Instruction *Inst = &*I++; if (!Instructions.count(Inst) && !isa(Inst) && - !Inst->isEHPad() && !Inst->getType()->isTokenTy()) { + !Inst->isEHPad() && !Inst->getType()->isTokenTy() && + !Inst->isSwiftError()) { if (!Inst->getType()->isVoidTy()) Inst->replaceAllUsesWith(UndefValue::get(Inst->getType())); Inst->eraseFromParent(); @@ -1015,7 +1016,8 @@ static Error ReduceInsts(BugDriver &BD, // TODO: Should this be some kind of interrupted error? return Error::success(); - if (I->isEHPad() || I->getType()->isTokenTy()) + if (I->isEHPad() || I->getType()->isTokenTy() || + I->isSwiftError()) continue; outs() << "Checking instruction: " << *I; @@ -1111,7 +1113,7 @@ static Error DebugACrash(BugDriver &BD, BD.EmitProgressBitcode(BD.getProgram(), "reduced-blocks"); } - if (!DisableSimplifyCFG & !BugpointIsInterrupted) { + if (!DisableSimplifyCFG && !BugpointIsInterrupted) { std::vector Blocks; for (Function &F : *BD.getProgram()) for (BasicBlock &BB : F) diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp index d57613ec5e376..82c61b6e1be7a 100644 --- a/tools/bugpoint/ExtractFunction.cpp +++ b/tools/bugpoint/ExtractFunction.cpp @@ -209,6 +209,7 @@ static void eliminateAliases(GlobalValue *GV) { void llvm::DeleteGlobalInitializer(GlobalVariable *GV) { eliminateAliases(GV); GV->setInitializer(nullptr); + GV->setComdat(nullptr); } // DeleteFunctionBody - "Remove" the function by deleting all of its basic diff --git a/tools/bugpoint/FindBugs.cpp b/tools/bugpoint/FindBugs.cpp index 156f4d0d78fe1..3093169ba8b00 100644 --- a/tools/bugpoint/FindBugs.cpp +++ b/tools/bugpoint/FindBugs.cpp @@ -21,6 +21,7 @@ #include "llvm/Support/raw_ostream.h" #include #include +#include using namespace llvm; Error @@ -39,14 +40,13 @@ BugDriver::runManyPasses(const std::vector &AllPasses) { return E; } - srand(time(nullptr)); - + std::mt19937 randomness(std::random_device{}()); unsigned num = 1; while (1) { // // Step 1: Randomize the order of the optimizer passes. // - std::random_shuffle(PassesToRun.begin(), PassesToRun.end()); + std::shuffle(PassesToRun.begin(), PassesToRun.end(), randomness); // // Step 2: Run optimizer passes on the program and check for success. diff --git a/tools/bugpoint/ListReducer.h b/tools/bugpoint/ListReducer.h index dcfa11d06927f..0f9db022d555e 100644 --- a/tools/bugpoint/ListReducer.h +++ b/tools/bugpoint/ListReducer.h @@ -19,6 +19,7 @@ #include "llvm/Support/raw_ostream.h" #include #include +#include #include namespace llvm { @@ -46,7 +47,7 @@ template struct ListReducer { /// that bugpoint does. Expected reduceList(std::vector &TheList) { std::vector empty; - std::srand(0x6e5ea738); // Seed the random number generator + std::mt19937 randomness(0x6e5ea738); // Seed the random number generator Expected Result = doTest(TheList, empty); if (Error E = Result.takeError()) return std::move(E); @@ -92,7 +93,7 @@ template struct ListReducer { // distribution (improving the speed of convergence). if (ShufflingEnabled && NumOfIterationsWithoutProgress > MaxIterations) { std::vector ShuffledList(TheList); - std::random_shuffle(ShuffledList.begin(), ShuffledList.end()); + std::shuffle(ShuffledList.begin(), ShuffledList.end(), randomness); errs() << "\n\n*** Testing shuffled set...\n\n"; // Check that random shuffle doesn't lose the bug Expected Result = doTest(ShuffledList, empty); diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index 792fab07bf11e..80f4cea234815 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -225,19 +225,22 @@ public: /// output is different. If the DeleteInputs argument is set to true then this /// function deletes both input modules before it returns. /// -static Expected> -testMergedProgram(const BugDriver &BD, std::unique_ptr M1, - std::unique_ptr M2, bool &Broken) { - if (Linker::linkModules(*M1, std::move(M2))) +static Expected> testMergedProgram(const BugDriver &BD, + const Module &M1, + const Module &M2, + bool &Broken) { + // Resulting merge of M1 and M2. + auto Merged = CloneModule(&M1); + if (Linker::linkModules(*Merged, CloneModule(&M2))) // TODO: Shouldn't we thread the error up instead of exiting? exit(1); // Execute the program. - Expected Diff = BD.diffProgram(M1.get(), "", "", false); + Expected Diff = BD.diffProgram(Merged.get(), "", "", false); if (Error E = Diff.takeError()) return std::move(E); Broken = *Diff; - return std::move(M1); + return std::move(Merged); } /// TestFuncs - split functions in a Module into two groups: those that are @@ -335,9 +338,8 @@ ExtractLoops(BugDriver &BD, // extraction. AbstractInterpreter *AI = BD.switchToSafeInterpreter(); bool Failure; - Expected> New = - testMergedProgram(BD, std::move(ToOptimizeLoopExtracted), - std::move(ToNotOptimize), Failure); + Expected> New = testMergedProgram( + BD, *ToOptimizeLoopExtracted, *ToNotOptimize, Failure); if (Error E = New.takeError()) return std::move(E); if (!*New) @@ -726,8 +728,7 @@ static Expected TestOptimizer(BugDriver &BD, std::unique_ptr Test, outs() << " Checking to see if the merged program executes correctly: "; bool Broken; - auto Result = - testMergedProgram(BD, std::move(Optimized), std::move(Safe), Broken); + auto Result = testMergedProgram(BD, *Optimized, *Safe, Broken); if (Error E = Result.takeError()) return std::move(E); if (auto New = std::move(*Result)) { @@ -840,7 +841,7 @@ static void CleanupAndPrepareModules(BugDriver &BD, // Prototype: void *getPointerToNamedFunction(const char* Name) Constant *resolverFunc = Safe->getOrInsertFunction( "getPointerToNamedFunction", Type::getInt8PtrTy(Safe->getContext()), - Type::getInt8PtrTy(Safe->getContext()), (Type *)nullptr); + Type::getInt8PtrTy(Safe->getContext())); // Use the function we just added to get addresses of functions we need. for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) { diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index 4633d64373368..10532ef8395b8 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -355,37 +355,62 @@ Expected CustomExecutor::ExecuteProgram( // Tokenize the CommandLine to the command and the args to allow // defining a full command line as the command instead of just the // executed program. We cannot just pass the whole string after the command -// as a single argument because then program sees only a single +// as a single argument because then the program sees only a single // command line argument (with spaces in it: "foo bar" instead // of "foo" and "bar"). // -// code borrowed from: -// http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html +// Spaces are used as a delimiter; however repeated, leading, and trailing +// whitespace are ignored. Simple escaping is allowed via the '\' +// character, as seen below: +// +// Two consecutive '\' evaluate to a single '\'. +// A space after a '\' evaluates to a space that is not interpreted as a +// delimiter. +// Any other instances of the '\' character are removed. +// +// Example: +// '\\' -> '\' +// '\ ' -> ' ' +// 'exa\mple' -> 'example' +// static void lexCommand(std::string &Message, const std::string &CommandLine, std::string &CmdPath, std::vector &Args) { - std::string Command = ""; - std::string delimiters = " "; - - std::string::size_type lastPos = CommandLine.find_first_not_of(delimiters, 0); - std::string::size_type pos = CommandLine.find_first_of(delimiters, lastPos); - - while (std::string::npos != pos || std::string::npos != lastPos) { - std::string token = CommandLine.substr(lastPos, pos - lastPos); - if (Command == "") - Command = token; - else - Args.push_back(token); - // Skip delimiters. Note the "not_of" - lastPos = CommandLine.find_first_not_of(delimiters, pos); - // Find next "non-delimiter" - pos = CommandLine.find_first_of(delimiters, lastPos); + std::string Token; + std::string Command; + bool FoundPath = false; + + // first argument is the PATH. + // Skip repeated whitespace, leading whitespace and trailing whitespace. + for (std::size_t Pos = 0u; Pos <= CommandLine.size(); ++Pos) { + if ('\\' == CommandLine[Pos]) { + if (Pos + 1 < CommandLine.size()) + Token.push_back(CommandLine[++Pos]); + + continue; + } + if (' ' == CommandLine[Pos] || CommandLine.size() == Pos) { + if (Token.empty()) + continue; + + if (!FoundPath) { + Command = Token; + FoundPath = true; + Token.clear(); + continue; + } + + Args.push_back(Token); + Token.clear(); + continue; + } + Token.push_back(CommandLine[Pos]); } auto Path = sys::findProgramByName(Command); if (!Path) { - Message = std::string("Cannot find '") + Command + "' in PATH: " + - Path.getError().message() + "\n"; + Message = std::string("Cannot find '") + Command + + "' in PATH: " + Path.getError().message() + "\n"; return; } CmdPath = *Path; diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp index a5de953b2b75b..85c1ddd8277d9 100644 --- a/tools/bugpoint/bugpoint.cpp +++ b/tools/bugpoint/bugpoint.cpp @@ -181,7 +181,8 @@ int main(int argc, char **argv) { if (OptLevelO1) Builder.Inliner = createAlwaysInlinerLegacyPass(); else if (OptLevelOs || OptLevelO2) - Builder.Inliner = createFunctionInliningPass(2, OptLevelOs ? 1 : 0); + Builder.Inliner = createFunctionInliningPass( + 2, OptLevelOs ? 1 : 0, false); else Builder.Inliner = createFunctionInliningPass(275); Builder.populateFunctionPassManager(PM); diff --git a/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinker.cpp index f1ec8a6226712..25f1a0f271223 100644 --- a/tools/dsymutil/DwarfLinker.cpp +++ b/tools/dsymutil/DwarfLinker.cpp @@ -197,30 +197,34 @@ public: CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR, StringRef ClangModuleName) - : OrigUnit(OrigUnit), ID(ID), NewUnit(OrigUnit.getVersion(), - OrigUnit.getAddressByteSize(), - OrigUnit.getUnitDIE().getTag()), - LowPc(UINT64_MAX), HighPc(0), RangeAlloc(), Ranges(RangeAlloc), - ClangModuleName(ClangModuleName) { + : OrigUnit(OrigUnit), ID(ID), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(), + Ranges(RangeAlloc), ClangModuleName(ClangModuleName) { Info.resize(OrigUnit.getNumDIEs()); auto CUDie = OrigUnit.getUnitDIE(false); - unsigned Lang = - CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_language) - .getValueOr(0); - HasODR = CanUseODR && (Lang == dwarf::DW_LANG_C_plus_plus || - Lang == dwarf::DW_LANG_C_plus_plus_03 || - Lang == dwarf::DW_LANG_C_plus_plus_11 || - Lang == dwarf::DW_LANG_C_plus_plus_14 || - Lang == dwarf::DW_LANG_ObjC_plus_plus); + if (auto Lang = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_language))) + HasODR = CanUseODR && (*Lang == dwarf::DW_LANG_C_plus_plus || + *Lang == dwarf::DW_LANG_C_plus_plus_03 || + *Lang == dwarf::DW_LANG_C_plus_plus_11 || + *Lang == dwarf::DW_LANG_C_plus_plus_14 || + *Lang == dwarf::DW_LANG_ObjC_plus_plus); + else + HasODR = false; } DWARFUnit &getOrigUnit() const { return OrigUnit; } unsigned getUniqueID() const { return ID; } + void createOutputDIE() { + NewUnit.emplace(OrigUnit.getVersion(), OrigUnit.getAddressByteSize(), + OrigUnit.getUnitDIE().getTag()); + } + DIE *getOutputUnitDIE() const { - return &const_cast(NewUnit).getUnitDie(); + if (NewUnit) + return &const_cast(*NewUnit).getUnitDie(); + return nullptr; } bool hasODR() const { return HasODR; } @@ -329,7 +333,7 @@ private: DWARFUnit &OrigUnit; unsigned ID; std::vector Info; ///< DIE info indexed by DIE index. - DIEUnit NewUnit; + Optional NewUnit; uint64_t StartOffset; uint64_t NextUnitOffset; @@ -359,7 +363,7 @@ private: Optional UnitRangeAttribute; /// @} - /// \brief Location attributes that need to be transfered from th + /// \brief Location attributes that need to be transferred from the /// original debug_loc section to the liked one. They are stored /// along with the PC offset that is to be applied to their /// function's address. @@ -397,7 +401,8 @@ uint64_t CompileUnit::computeNextUnitOffset() { // The root DIE might be null, meaning that the Unit had nothing to // contribute to the linked output. In that case, we will emit the // unit header without any actual DIE. - NextUnitOffset += NewUnit.getUnitDie().getSize(); + if (NewUnit) + NextUnitOffset += NewUnit->getUnitDie().getSize(); return NextUnitOffset; } @@ -843,8 +848,7 @@ void DwarfStreamer::emitLocationsForUnit(const CompileUnit &Unit, DWARFUnit &OrigUnit = Unit.getOrigUnit(); auto OrigUnitDie = OrigUnit.getUnitDIE(false); int64_t UnitPcOffset = 0; - auto OrigLowPc = OrigUnitDie.getAttributeValueAsAddress(dwarf::DW_AT_low_pc); - if (OrigLowPc) + if (auto OrigLowPc = dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc))) UnitPcOffset = int64_t(*OrigLowPc) - Unit.getLowPc(); for (const auto &Attr : Attributes) { @@ -1080,7 +1084,7 @@ void DwarfStreamer::emitCIE(StringRef CIEBytes) { /// \brief Emit a FDE into the debug_frame section. \p FDEBytes /// contains the FDE data without the length, CIE offset and address -/// which will be replaced with the paramter values. +/// which will be replaced with the parameter values. void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize, uint32_t Address, StringRef FDEBytes) { MS->SwitchSection(MC->getObjectFileInfo()->getDwarfFrameSection()); @@ -1558,8 +1562,7 @@ PointerIntPair DeclContextTree::getChildDeclContext( // Do not unique anything inside CU local functions. if ((Context.getTag() == dwarf::DW_TAG_namespace || Context.getTag() == dwarf::DW_TAG_compile_unit) && - !DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_external) - .getValueOr(0)) + !dwarf::toUnsigned(DIE.find(dwarf::DW_AT_external), 0)) return PointerIntPair(nullptr); LLVM_FALLTHROUGH; case dwarf::DW_TAG_member: @@ -1573,8 +1576,7 @@ PointerIntPair DeclContextTree::getChildDeclContext( // created on demand. For example implicitely defined constructors // are ambiguous because of the way we identify contexts, and they // won't be generated everytime everywhere. - if (DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_artificial) - .getValueOr(0)) + if (dwarf::toUnsigned(DIE.find(dwarf::DW_AT_artificial), 0)) return PointerIntPair(nullptr); break; } @@ -1614,12 +1616,9 @@ PointerIntPair DeclContextTree::getChildDeclContext( // namespaces, use these additional data points to make the process // safer. This is disabled for clang modules, because forward // declarations of module-defined types do not have a file and line. - ByteSize = DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_byte_size) - .getValueOr(UINT64_MAX); + ByteSize = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_byte_size), UINT64_MAX); if (Tag != dwarf::DW_TAG_namespace || !Name) { - if (unsigned FileNum = - DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_decl_file) - .getValueOr(0)) { + if (unsigned FileNum = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_file), 0)) { if (const auto *LT = U.getOrigUnit().getContext().getLineTableForUnit( &U.getOrigUnit())) { // FIXME: dsymutil-classic compatibility. I'd rather not @@ -1632,9 +1631,7 @@ PointerIntPair DeclContextTree::getChildDeclContext( // instead of "" would allow more uniquing, but for now, do // it this way to match dsymutil-classic. if (LT->hasFileAtIndex(FileNum)) { - Line = - DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_decl_line) - .getValueOr(0); + Line = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_line), 0); // Cache the resolved paths, because calling realpath is expansive. StringRef ResolvedPath = U.getResolvedPath(FileNum); if (!ResolvedPath.empty()) { @@ -1782,8 +1779,7 @@ static bool analyzeContextInfo(const DWARFDie &DIE, // // We treat non-C++ modules like namespaces for this reason. if (DIE.getTag() == dwarf::DW_TAG_module && ParentIdx == 0 && - DIE.getAttributeValueAsString(dwarf::DW_AT_name, - "") != CU.getClangModuleName()) { + dwarf::toString(DIE.find(dwarf::DW_AT_name), "") != CU.getClangModuleName()) { InImportedModule = true; } @@ -1811,8 +1807,7 @@ static bool analyzeContextInfo(const DWARFDie &DIE, // forward declarations. Info.Prune &= (DIE.getTag() == dwarf::DW_TAG_module) || - DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_declaration) - .getValueOr(0); + dwarf::toUnsigned(DIE.find(dwarf::DW_AT_declaration), 0); // Don't prune it if there is no definition for the DIE. Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset(); @@ -2129,7 +2124,7 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE( std::tie(LowPcOffset, LowPcEndOffset) = getAttributeOffsets(Abbrev, *LowPcIdx, Offset, OrigUnit); - auto LowPc = DIE.getAttributeValueAsAddress(dwarf::DW_AT_low_pc); + auto LowPc = dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc)); assert(LowPc.hasValue() && "low_pc attribute is not an address."); if (!LowPc || !RelocMgr.hasValidRelocation(LowPcOffset, LowPcEndOffset, MyInfo)) @@ -2746,14 +2741,11 @@ DIE *DwarfLinker::DIECloner::cloneDIE( // file might be start address of another function which got moved // independantly by the linker). The computation of the actual // high_pc value is done in cloneAddressAttribute(). - AttrInfo.OrigHighPc = - InputDIE.getAttributeValueAsAddress(dwarf::DW_AT_high_pc).getValueOr(0); + AttrInfo.OrigHighPc = dwarf::toAddress(InputDIE.find(dwarf::DW_AT_high_pc), 0); // Also store the low_pc. It might get relocated in an // inline_subprogram that happens at the beginning of its // inlining function. - AttrInfo.OrigLowPc = - InputDIE.getAttributeValueAsAddress(dwarf::DW_AT_low_pc) - .getValueOr(UINT64_MAX); + AttrInfo.OrigLowPc = dwarf::toAddress(InputDIE.find(dwarf::DW_AT_low_pc), UINT64_MAX); } // Reset the Offset to 0 as we will be working on the local copy of @@ -2872,9 +2864,7 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit, auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange; DWARFUnit &OrigUnit = Unit.getOrigUnit(); auto OrigUnitDie = OrigUnit.getUnitDIE(false); - uint64_t OrigLowPc = - OrigUnitDie.getAttributeValueAsAddress(dwarf::DW_AT_low_pc) - .getValueOr(-1ULL); + uint64_t OrigLowPc = dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc), -1ULL); // Ranges addresses are based on the unit's low_pc. Compute the // offset we need to apply to adapt to the new unit's low_pc. int64_t UnitPcOffset = 0; @@ -2969,7 +2959,7 @@ static void patchStmtList(DIE &Die, DIEInteger Offset) { void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf) { DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE(); - auto StmtList = CUDie.getAttributeValueAsSectionOffset(dwarf::DW_AT_stmt_list); + auto StmtList = dwarf::toSectionOffset(CUDie.find(dwarf::DW_AT_stmt_list)); if (!StmtList) return; @@ -3081,7 +3071,7 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit, if (LineTable.Prologue.Version != 2 || LineTable.Prologue.DefaultIsStmt != DWARF2_LINE_DEFAULT_IS_STMT || LineTable.Prologue.OpcodeBase > 13) - reportWarning("line table paramters mismatch. Cannot emit."); + reportWarning("line table parameters mismatch. Cannot emit."); else { MCDwarfLineTableParams Params; Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase; @@ -3201,10 +3191,8 @@ void DwarfLinker::DIECloner::copyAbbrev( static uint64_t getDwoId(const DWARFDie &CUDie, const DWARFUnit &Unit) { - auto DwoId = CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_dwo_id); - if (DwoId) - return *DwoId; - DwoId = CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_GNU_dwo_id); + auto DwoId = dwarf::toUnsigned(CUDie.find({dwarf::DW_AT_dwo_id, + dwarf::DW_AT_GNU_dwo_id})); if (DwoId) return *DwoId; return 0; @@ -3214,20 +3202,16 @@ bool DwarfLinker::registerModuleReference( const DWARFDie &CUDie, const DWARFUnit &Unit, DebugMap &ModuleMap, unsigned Indent) { std::string PCMfile = - CUDie.getAttributeValueAsString(dwarf::DW_AT_dwo_name, ""); - if (PCMfile.empty()) - PCMfile = - CUDie.getAttributeValueAsString(dwarf::DW_AT_GNU_dwo_name, ""); + dwarf::toString(CUDie.find({dwarf::DW_AT_dwo_name, + dwarf::DW_AT_GNU_dwo_name}), ""); if (PCMfile.empty()) return false; // Clang module DWARF skeleton CUs abuse this for the path to the module. - std::string PCMpath = - CUDie.getAttributeValueAsString(dwarf::DW_AT_comp_dir, ""); + std::string PCMpath = dwarf::toString(CUDie.find(dwarf::DW_AT_comp_dir), ""); uint64_t DwoId = getDwoId(CUDie, Unit); - std::string Name = - CUDie.getAttributeValueAsString(dwarf::DW_AT_name, ""); + std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), ""); if (Name.empty()) { reportWarning("Anonymous module skeleton CU for " + PCMfile); return true; @@ -3378,12 +3362,13 @@ void DwarfLinker::DIECloner::cloneAllCompileUnits( for (auto &CurrentUnit : CompileUnits) { auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE(); CurrentUnit->setStartOffset(Linker.OutputDebugInfoSize); - // Clonse the InputDIE into your Unit DIE in our compile unit since it - // already has a DIE inside of it. - if (!cloneDIE(InputDIE, *CurrentUnit, 0 /* PC offset */, - 11 /* Unit Header size */, 0, - CurrentUnit->getOutputUnitDIE())) - continue; + if (CurrentUnit->getInfo(0).Keep) { + // Clone the InputDIE into your Unit DIE in our compile unit since it + // already has a DIE inside of it. + CurrentUnit->createOutputDIE(); + cloneDIE(InputDIE, *CurrentUnit, 0 /* PC offset */, + 11 /* Unit Header size */, 0, CurrentUnit->getOutputUnitDIE()); + } Linker.OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(); if (Linker.Options.NoOutput) continue; diff --git a/tools/dsymutil/MachOUtils.cpp b/tools/dsymutil/MachOUtils.cpp index 8a730a1d0c8a2..ea6f113e4fae6 100644 --- a/tools/dsymutil/MachOUtils.cpp +++ b/tools/dsymutil/MachOUtils.cpp @@ -220,7 +220,7 @@ getSection(const object::MachOObjectFile &Obj, // The function also tries to find a hole in the address map to fit the __DWARF // segment of \a DwarfSegmentSize size. \a EndAddress is updated to point at the // highest segment address. -// When the __LINKEDIT segment is transfered, its offset and size are set resp. +// When the __LINKEDIT segment is transferred, its offset and size are set resp. // to \a LinkeditOffset and \a LinkeditSize. template static void transferSegmentAndSections( @@ -236,6 +236,8 @@ static void transferSegmentAndSections( if (StringRef("__LINKEDIT") == Segment.segname) { Segment.fileoff = LinkeditOffset; Segment.filesize = LinkeditSize; + // Resize vmsize by rounding to the page size. + Segment.vmsize = alignTo(LinkeditSize, 0x1000); } // Check if the end address of the last segment and our current diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp index 50e102b045953..9b783d19a2834 100644 --- a/tools/gold/gold-plugin.cpp +++ b/tools/gold/gold-plugin.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/Statistic.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/CodeGen/CommandFlags.h" @@ -20,7 +21,9 @@ #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/LTO/Caching.h" #include "llvm/LTO/LTO.h" +#include "llvm/Object/Error.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" @@ -105,8 +108,6 @@ static std::list Modules; static DenseMap FDToLeaderHandle; static StringMap ResInfo; static std::vector Cleanup; -static llvm::TargetOptions TargetOpts; -static size_t MaxTasks; namespace options { enum OutputType { @@ -165,6 +166,12 @@ namespace options { // corresponding bitcode file, will use a path formed by replacing the // bitcode file's path prefix matching oldprefix with newprefix. static std::string thinlto_prefix_replace; + // Option to control the name of modules encoded in the individual index + // files for a distributed backend. This enables the use of minimized + // bitcode files for the thin link, assuming the name of the full bitcode + // file used in the backend differs just in some part of the file suffix. + // If specified, expects a string of the form "oldsuffix:newsuffix". + static std::string thinlto_object_suffix_replace; // Optional path to a directory for caching ThinLTO objects. static std::string cache_dir; // Additional options to pass into the code generator. @@ -207,6 +214,12 @@ namespace options { thinlto_prefix_replace = opt.substr(strlen("thinlto-prefix-replace=")); if (thinlto_prefix_replace.find(';') == std::string::npos) message(LDPL_FATAL, "thinlto-prefix-replace expects 'old;new' format"); + } else if (opt.startswith("thinlto-object-suffix-replace=")) { + thinlto_object_suffix_replace = + opt.substr(strlen("thinlto-object-suffix-replace=")); + if (thinlto_object_suffix_replace.find(';') == std::string::npos) + message(LDPL_FATAL, + "thinlto-object-suffix-replace expects 'old;new' format"); } else if (opt.startswith("cache-dir=")) { cache_dir = opt.substr(strlen("cache-dir=")); } else if (opt.size() == 2 && opt[0] == 'O') { @@ -452,7 +465,7 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, EC == object::object_error::bitcode_section_not_found) *claimed = 0; else - message(LDPL_ERROR, + message(LDPL_FATAL, "LLVM gold plugin has failed to create LTO module: %s", EI.message().c_str()); }); @@ -485,8 +498,6 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, sys::path::filename(Obj->getSourceFileName()).str(); for (auto &Sym : Obj->symbols()) { - uint32_t Symflags = Sym.getFlags(); - cf.syms.push_back(ld_plugin_symbol()); ld_plugin_symbol &sym = cf.syms.back(); sym.version = nullptr; @@ -512,20 +523,20 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, break; } - if (Symflags & object::BasicSymbolRef::SF_Undefined) { + if (Sym.isUndefined()) { sym.def = LDPK_UNDEF; - if (Symflags & object::BasicSymbolRef::SF_Weak) + if (Sym.isWeak()) sym.def = LDPK_WEAKUNDEF; - } else if (Symflags & object::BasicSymbolRef::SF_Common) + } else if (Sym.isCommon()) sym.def = LDPK_COMMON; - else if (Symflags & object::BasicSymbolRef::SF_Weak) + else if (Sym.isWeak()) sym.def = LDPK_WEAKDEF; else sym.def = LDPK_DEF; sym.size = 0; sym.comdat_key = nullptr; - int CI = check(Sym.getComdatIndex()); + int CI = Sym.getComdatIndex(); if (CI != -1) { StringRef C = Obj->getComdatTable()[CI]; sym.comdat_key = strdup(C.str().c_str()); @@ -567,8 +578,35 @@ static const void *getSymbolsAndView(claimed_file &F) { return View; } -static void addModule(LTO &Lto, claimed_file &F, const void *View) { - MemoryBufferRef BufferRef(StringRef((const char *)View, F.filesize), F.name); +/// Parse the thinlto-object-suffix-replace option into the \p OldSuffix and +/// \p NewSuffix strings, if it was specified. +static void getThinLTOOldAndNewSuffix(std::string &OldSuffix, + std::string &NewSuffix) { + assert(options::thinlto_object_suffix_replace.empty() || + options::thinlto_object_suffix_replace.find(";") != StringRef::npos); + StringRef SuffixReplace = options::thinlto_object_suffix_replace; + std::pair Split = SuffixReplace.split(";"); + OldSuffix = Split.first.str(); + NewSuffix = Split.second.str(); +} + +/// Given the original \p Path to an output file, replace any filename +/// suffix matching \p OldSuffix with \p NewSuffix. +static std::string getThinLTOObjectFileName(const std::string Path, + const std::string &OldSuffix, + const std::string &NewSuffix) { + if (OldSuffix.empty() && NewSuffix.empty()) + return Path; + StringRef NewPath = Path; + NewPath.consume_back(OldSuffix); + std::string NewNewPath = NewPath.str() + NewSuffix; + return NewPath.str() + NewSuffix; +} + +static void addModule(LTO &Lto, claimed_file &F, const void *View, + StringRef Filename) { + MemoryBufferRef BufferRef(StringRef((const char *)View, F.filesize), + Filename); Expected> ObjOrErr = InputFile::create(BufferRef); if (!ObjOrErr) @@ -637,7 +675,7 @@ static void recordFile(std::string Filename, bool TempOutFile) { /// indicating whether a temp file should be generated, and an optional task id. /// The new filename generated is returned in \p NewFilename. static void getOutputFileName(SmallString<128> InFilename, bool TempOutFile, - SmallString<128> &NewFilename, int TaskID = -1) { + SmallString<128> &NewFilename, int TaskID) { if (TempOutFile) { std::error_code EC = sys::fs::createTemporaryFile("lto-llvm", "o", NewFilename); @@ -646,7 +684,7 @@ static void getOutputFileName(SmallString<128> InFilename, bool TempOutFile, EC.message().c_str()); } else { NewFilename = InFilename; - if (TaskID >= 0) + if (TaskID > 0) NewFilename += utostr(TaskID); } } @@ -790,19 +828,31 @@ static ld_plugin_status allSymbolsReadHook() { if (options::thinlto_index_only) getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix); + std::string OldSuffix, NewSuffix; + getThinLTOOldAndNewSuffix(OldSuffix, NewSuffix); + // Set for owning string objects used as buffer identifiers. + StringSet<> ObjectFilenames; + for (claimed_file &F : Modules) { if (options::thinlto && !HandleToInputFile.count(F.leader_handle)) HandleToInputFile.insert(std::make_pair( F.leader_handle, llvm::make_unique(F.handle))); const void *View = getSymbolsAndView(F); + // In case we are thin linking with a minimized bitcode file, ensure + // the module paths encoded in the index reflect where the backends + // will locate the full bitcode files for compiling/importing. + std::string Identifier = + getThinLTOObjectFileName(F.name, OldSuffix, NewSuffix); + auto ObjFilename = ObjectFilenames.insert(Identifier); + assert(ObjFilename.second); if (!View) { if (options::thinlto_index_only) // Write empty output files that may be expected by the distributed // build system. - writeEmptyDistributedBuildOutputs(F.name, OldPrefix, NewPrefix); + writeEmptyDistributedBuildOutputs(Identifier, OldPrefix, NewPrefix); continue; } - addModule(*Lto, F, View); + addModule(*Lto, F, View, ObjFilename.first->first()); } SmallString<128> Filename; @@ -813,7 +863,7 @@ static ld_plugin_status allSymbolsReadHook() { Filename = output_name + ".o"; bool SaveTemps = !Filename.empty(); - MaxTasks = Lto->getMaxTasks(); + size_t MaxTasks = Lto->getMaxTasks(); std::vector IsTemporary(MaxTasks); std::vector> Filenames(MaxTasks); @@ -821,21 +871,26 @@ static ld_plugin_status allSymbolsReadHook() { [&](size_t Task) -> std::unique_ptr { IsTemporary[Task] = !SaveTemps; getOutputFileName(Filename, /*TempOutFile=*/!SaveTemps, Filenames[Task], - MaxTasks > 1 ? Task : -1); + Task); int FD; std::error_code EC = sys::fs::openFileForWrite(Filenames[Task], FD, sys::fs::F_None); if (EC) - message(LDPL_FATAL, "Could not open file: %s", EC.message().c_str()); + message(LDPL_FATAL, "Could not open file %s: %s", Filenames[Task].c_str(), + EC.message().c_str()); return llvm::make_unique( llvm::make_unique(FD, true)); }; - auto AddFile = [&](size_t Task, StringRef Path) { Filenames[Task] = Path; }; + auto AddBuffer = [&](size_t Task, std::unique_ptr MB) { + // Note that this requires that the memory buffers provided to AddBuffer are + // backed by a file. + Filenames[Task] = MB->getBufferIdentifier(); + }; NativeObjectCache Cache; if (!options::cache_dir.empty()) - Cache = localCache(options::cache_dir, AddFile); + Cache = check(localCache(options::cache_dir, AddBuffer)); check(Lto->run(AddStream, Cache)); @@ -844,6 +899,8 @@ static ld_plugin_status allSymbolsReadHook() { return LDPS_OK; if (options::thinlto_index_only) { + if (llvm::AreStatisticsEnabled()) + llvm::PrintStatistics(); cleanup_hook(); exit(0); } diff --git a/tools/llc/CMakeLists.txt b/tools/llc/CMakeLists.txt index 5a98122a233e7..4f8181a1b6577 100644 --- a/tools/llc/CMakeLists.txt +++ b/tools/llc/CMakeLists.txt @@ -12,6 +12,7 @@ set(LLVM_LINK_COMPONENTS Support Target TransformUtils + Vectorize ) # Support plugins. diff --git a/tools/llc/LLVMBuild.txt b/tools/llc/LLVMBuild.txt index c1f5cebea859d..014dcac176106 100644 --- a/tools/llc/LLVMBuild.txt +++ b/tools/llc/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Tool name = llc parent = Tools -required_libraries = AsmParser BitReader IRReader MIRParser TransformUtils all-targets +required_libraries = AsmParser BitReader IRReader MIRParser TransformUtils Scalar Vectorize all-targets diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index a76d3249674ff..43f97f112f6bc 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -136,6 +136,16 @@ static cl::opt StartAfter("start-after", static cl::list IncludeDirs("I", cl::desc("include search path")); +static cl::opt PassRemarksWithHotness( + "pass-remarks-with-hotness", + cl::desc("With PGO, include profile count in optimization remarks"), + cl::Hidden); + +static cl::opt + RemarksFilename("pass-remarks-output", + cl::desc("YAML output filename for pass remarks"), + cl::value_desc("filename")); + namespace { static ManagedStatic> RunPassNames; @@ -233,12 +243,29 @@ static void DiagnosticHandler(const DiagnosticInfo &DI, void *Context) { if (DI.getSeverity() == DS_Error) *HasError = true; + if (auto *Remark = dyn_cast(&DI)) + if (!Remark->isEnabled()) + return; + DiagnosticPrinterRawOStream DP(errs()); errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; DI.print(DP); errs() << "\n"; } +static void InlineAsmDiagHandler(const SMDiagnostic &SMD, void *Context, + unsigned LocCookie) { + bool *HasError = static_cast(Context); + if (SMD.getKind() == SourceMgr::DK_Error) + *HasError = true; + + SMD.print(nullptr, errs()); + + // For testing purposes, we print the LocCookie here. + if (LocCookie) + errs() << "note: !srcloc = " << LocCookie << "\n"; +} + // main - Entry point for the llc compiler. // int main(int argc, char **argv) { @@ -267,6 +294,8 @@ int main(int argc, char **argv) { initializeCountingFunctionInserterPass(*Registry); initializeUnreachableBlockElimLegacyPassPass(*Registry); initializeConstantHoistingLegacyPassPass(*Registry); + initializeScalarOpts(*Registry); + initializeVectorization(*Registry); // Register the target printer for --version. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); @@ -278,12 +307,32 @@ int main(int argc, char **argv) { // Set a diagnostic handler that doesn't exit on the first error bool HasError = false; Context.setDiagnosticHandler(DiagnosticHandler, &HasError); + Context.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, &HasError); + + if (PassRemarksWithHotness) + Context.setDiagnosticHotnessRequested(true); + + std::unique_ptr YamlFile; + if (RemarksFilename != "") { + std::error_code EC; + YamlFile = llvm::make_unique(RemarksFilename, EC, + sys::fs::F_None); + if (EC) { + errs() << EC.message() << '\n'; + return 1; + } + Context.setDiagnosticsOutputFile( + llvm::make_unique(YamlFile->os())); + } // Compile the module TimeCompilations times to give better compile time // metrics. for (unsigned I = TimeCompilations; I; --I) if (int RetVal = compileModule(argv, Context)) return RetVal; + + if (YamlFile) + YamlFile->keep(); return 0; } diff --git a/tools/lli/OrcLazyJIT.h b/tools/lli/OrcLazyJIT.h index 05319c345484f..56e7d36d05fb4 100644 --- a/tools/lli/OrcLazyJIT.h +++ b/tools/lli/OrcLazyJIT.h @@ -21,7 +21,7 @@ #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" -#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" namespace llvm { @@ -30,7 +30,7 @@ class OrcLazyJIT { public: typedef orc::JITCompileCallbackManager CompileCallbackMgr; - typedef orc::ObjectLinkingLayer<> ObjLayerT; + typedef orc::RTDyldObjectLinkingLayer<> ObjLayerT; typedef orc::IRCompileLayer CompileLayerT; typedef std::function(std::unique_ptr)> TransformFtor; diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index 0823ff469de6d..f228a36194573 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -606,8 +606,7 @@ int main(int argc, char **argv, char * const *envp) { // If the program doesn't explicitly call exit, we will need the Exit // function later on to make an explicit call, so get the function now. Constant *Exit = Mod->getOrInsertFunction("exit", Type::getVoidTy(Context), - Type::getInt32Ty(Context), - nullptr); + Type::getInt32Ty(Context)); // Run static constructors. if (!ForceInterpreter) { diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index b99a396da62ac..1519464521dd0 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -52,7 +52,7 @@ static StringRef ToolName; // Show the error message and exit. LLVM_ATTRIBUTE_NORETURN static void fail(Twine Error) { - outs() << ToolName << ": " << Error << ".\n"; + errs() << ToolName << ": " << Error << ".\n"; exit(1); } @@ -87,13 +87,14 @@ static cl::opt MRI("M", cl::desc("")); static cl::opt Plugin("plugin", cl::desc("plugin (ignored for compatibility")); namespace { -enum Format { Default, GNU, BSD }; +enum Format { Default, GNU, BSD, DARWIN }; } static cl::opt FormatOpt("format", cl::desc("Archive format to create"), cl::values(clEnumValN(Default, "default", "default"), clEnumValN(GNU, "gnu", "gnu"), + clEnumValN(DARWIN, "darwin", "darwin"), clEnumValN(BSD, "bsd", "bsd"))); static std::string Options; @@ -167,7 +168,7 @@ LLVM_ATTRIBUTE_NORETURN static void show_help(const std::string &msg) { errs() << ToolName << ": " << msg << "\n\n"; cl::PrintHelpMessage(); - std::exit(1); + exit(1); } // Extract the member filename from the command line for the [relpos] argument @@ -376,7 +377,9 @@ static void doExtract(StringRef Name, const object::Archive::Child &C) { sys::fs::perms Mode = ModeOrErr.get(); int FD; - failIfError(sys::fs::openFileForWrite(Name, FD, sys::fs::F_None, Mode), Name); + failIfError(sys::fs::openFileForWrite(sys::path::filename(Name), FD, + sys::fs::F_None, Mode), + Name); { raw_fd_ostream file(FD, false); @@ -462,7 +465,7 @@ static void performReadOperation(ArchiveOperation Operation, return; for (StringRef Name : Members) errs() << Name << " was not found\n"; - std::exit(1); + exit(1); } static void addMember(std::vector &Members, @@ -623,8 +626,9 @@ computeNewArchiveMembers(ArchiveOperation Operation, } static object::Archive::Kind getDefaultForHost() { - return Triple(sys::getProcessTriple()).isOSDarwin() ? object::Archive::K_BSD - : object::Archive::K_GNU; + return Triple(sys::getProcessTriple()).isOSDarwin() + ? object::Archive::K_DARWIN + : object::Archive::K_GNU; } static object::Archive::Kind getKindFromMember(const NewArchiveMember &Member) { @@ -633,7 +637,7 @@ static object::Archive::Kind getKindFromMember(const NewArchiveMember &Member) { if (OptionalObject) return isa(**OptionalObject) - ? object::Archive::K_BSD + ? object::Archive::K_DARWIN : object::Archive::K_GNU; // squelch the error in case we had a non-object file @@ -672,6 +676,11 @@ performWriteOperation(ArchiveOperation Operation, fail("Only the gnu format has a thin mode"); Kind = object::Archive::K_BSD; break; + case DARWIN: + if (Thin) + fail("Only the gnu format has a thin mode"); + Kind = object::Archive::K_DARWIN; + break; } std::pair Result = diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index b84c4a83dee45..abc6fa27a0e05 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -171,7 +171,6 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, STRINGIFY_CODE(MODULE_CODE, GLOBALVAR) STRINGIFY_CODE(MODULE_CODE, FUNCTION) STRINGIFY_CODE(MODULE_CODE, ALIAS) - STRINGIFY_CODE(MODULE_CODE, PURGEVALS) STRINGIFY_CODE(MODULE_CODE, GCNAME) STRINGIFY_CODE(MODULE_CODE, VSTOFFSET) STRINGIFY_CODE(MODULE_CODE, METADATA_VALUES_UNUSED) @@ -312,6 +311,10 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, STRINGIFY_CODE(FS, COMBINED_ORIGINAL_NAME) STRINGIFY_CODE(FS, VERSION) STRINGIFY_CODE(FS, TYPE_TESTS) + STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_VCALLS) + STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_VCALLS) + STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_CONST_VCALL) + STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_CONST_VCALL) } case bitc::METADATA_ATTACHMENT_ID: switch(CodeID) { diff --git a/tools/llvm-c-test/echo.cpp b/tools/llvm-c-test/echo.cpp index 72ff138c74e32..52ce85c577821 100644 --- a/tools/llvm-c-test/echo.cpp +++ b/tools/llvm-c-test/echo.cpp @@ -591,7 +591,7 @@ struct FunCloner { break; } case LLVMPHI: { - // We need to agressively set things here because of loops. + // We need to aggressively set things here because of loops. VMap[Src] = Dst = LLVMBuildPhi(Builder, CloneType(Src), Name); SmallVector Values; diff --git a/tools/llvm-cat/llvm-cat.cpp b/tools/llvm-cat/llvm-cat.cpp index d884970309b44..4d62099094bb8 100644 --- a/tools/llvm-cat/llvm-cat.cpp +++ b/tools/llvm-cat/llvm-cat.cpp @@ -40,7 +40,7 @@ int main(int argc, char **argv) { SmallVector Buffer; BitcodeWriter Writer(Buffer); if (BinaryCat) { - for (std::string InputFilename : InputFilenames) { + for (const auto &InputFilename : InputFilenames) { std::unique_ptr MB = ExitOnErr( errorOrToExpected(MemoryBuffer::getFileOrSTDIN(InputFilename))); std::vector Mods = ExitOnErr(getBitcodeModuleList(*MB)); @@ -49,7 +49,7 @@ int main(int argc, char **argv) { BitcodeMod.getBuffer().end()); } } else { - for (std::string InputFilename : InputFilenames) { + for (const auto &InputFilename : InputFilenames) { SMDiagnostic Err; std::unique_ptr M = parseIRFile(InputFilename, Err, Context); if (!M) { diff --git a/tools/llvm-cov/CodeCoverage.cpp b/tools/llvm-cov/CodeCoverage.cpp index 0a9807ab00334..6179c760d5b20 100644 --- a/tools/llvm-cov/CodeCoverage.cpp +++ b/tools/llvm-cov/CodeCoverage.cpp @@ -15,6 +15,7 @@ #include "CoverageFilters.h" #include "CoverageReport.h" +#include "CoverageSummaryInfo.h" #include "CoverageViewOptions.h" #include "RenderingSupport.h" #include "SourceCoverageView.h" @@ -98,9 +99,6 @@ private: /// \brief If a demangler is available, demangle all symbol names. void demangleSymbols(const CoverageMapping &Coverage); - /// \brief Demangle \p Sym if possible. Otherwise, just return \p Sym. - StringRef getSymbolForHumans(StringRef Sym) const; - /// \brief Write out a source file view to the filesystem. void writeSourceFileView(StringRef SourceFile, CoverageMapping *Coverage, CoveragePrinter *Printer, bool ShowFilenames); @@ -136,10 +134,10 @@ private: /// The architecture the coverage mapping data targets. std::string CoverageArch; - /// A cache for demangled symbol names. - StringMap DemangledNames; + /// A cache for demangled symbols. + DemangleCache DC; - /// Errors and warnings which have not been printed. + /// A lock which guards printing to stderr. std::mutex ErrsLock; /// A container for input source file buffers. @@ -267,7 +265,7 @@ CodeCoverageTool::createFunctionView(const FunctionRecord &Function, return nullptr; auto Expansions = FunctionCoverage.getExpansions(); - auto View = SourceCoverageView::create(getSymbolForHumans(Function.Name), + auto View = SourceCoverageView::create(DC.demangle(Function.Name), SourceBuffer.get(), ViewOpts, std::move(FunctionCoverage)); attachExpansionSubViews(*View, Expansions, Coverage); @@ -293,7 +291,7 @@ CodeCoverageTool::createSourceFileView(StringRef SourceFile, for (const auto *Function : Coverage.getInstantiations(SourceFile)) { std::unique_ptr SubView{nullptr}; - StringRef Funcname = getSymbolForHumans(Function->Name); + StringRef Funcname = DC.demangle(Function->Name); if (Function->ExecutionCount > 0) { auto SubViewCoverage = Coverage.getCoverageForFunction(*Function); @@ -453,14 +451,9 @@ void CodeCoverageTool::demangleSymbols(const CoverageMapping &Coverage) { // Cache the demangled names. unsigned I = 0; for (const auto &Function : Coverage.getCoveredFunctions()) - DemangledNames[Function.Name] = Symbols[I++]; -} - -StringRef CodeCoverageTool::getSymbolForHumans(StringRef Sym) const { - const auto DemangledName = DemangledNames.find(Sym); - if (DemangledName == DemangledNames.end()) - return Sym; - return DemangledName->getValue(); + // On Windows, lines in the demangler's output file end with "\r\n". + // Splitting by '\n' keeps '\r's, so cut them now. + DC.DemangledNames[Function.Name] = Symbols[I++].rtrim(); } void CodeCoverageTool::writeSourceFileView(StringRef SourceFile, @@ -817,22 +810,28 @@ int CodeCoverageTool::show(int argc, const char **argv, int CodeCoverageTool::report(int argc, const char **argv, CommandLineParserType commandLineParser) { + cl::opt ShowFunctionSummaries( + "show-functions", cl::Optional, cl::init(false), + cl::desc("Show coverage summaries for each function")); + auto Err = commandLineParser(argc, argv); if (Err) return Err; - if (ViewOpts.Format == CoverageViewOptions::OutputFormat::HTML) + if (ViewOpts.Format == CoverageViewOptions::OutputFormat::HTML) { error("HTML output for summary reports is not yet supported."); + return 1; + } auto Coverage = load(); if (!Coverage) return 1; CoverageReport Report(ViewOpts, *Coverage.get()); - if (SourceFiles.empty()) + if (!ShowFunctionSummaries) Report.renderFileReports(llvm::outs()); else - Report.renderFunctionReports(SourceFiles, llvm::outs()); + Report.renderFunctionReports(SourceFiles, DC, llvm::outs()); return 0; } @@ -843,6 +842,11 @@ int CodeCoverageTool::export_(int argc, const char **argv, if (Err) return Err; + if (ViewOpts.Format != CoverageViewOptions::OutputFormat::Text) { + error("Coverage data can only be exported as textual JSON."); + return 1; + } + auto Coverage = load(); if (!Coverage) { error("Could not load coverage information"); diff --git a/tools/llvm-cov/CoverageReport.cpp b/tools/llvm-cov/CoverageReport.cpp index e88cb186acd66..c68bb9048df1b 100644 --- a/tools/llvm-cov/CoverageReport.cpp +++ b/tools/llvm-cov/CoverageReport.cpp @@ -118,19 +118,51 @@ raw_ostream::Colors determineCoveragePercentageColor(const T &Info) { : raw_ostream::RED; } -/// \brief Determine the length of the longest common prefix of the strings in -/// \p Strings. -unsigned getLongestCommonPrefixLen(ArrayRef Strings) { - unsigned LCP = Strings[0].size(); - for (unsigned I = 1, E = Strings.size(); LCP > 0 && I < E; ++I) { - unsigned Cursor; - StringRef S = Strings[I]; - for (Cursor = 0; Cursor < LCP && Cursor < S.size(); ++Cursor) - if (Strings[0][Cursor] != S[Cursor]) +/// \brief Get the number of redundant path components in each path in \p Paths. +unsigned getNumRedundantPathComponents(ArrayRef Paths) { + // To start, set the number of redundant path components to the maximum + // possible value. + SmallVector FirstPathComponents{sys::path::begin(Paths[0]), + sys::path::end(Paths[0])}; + unsigned NumRedundant = FirstPathComponents.size(); + + for (unsigned I = 1, E = Paths.size(); NumRedundant > 0 && I < E; ++I) { + StringRef Path = Paths[I]; + for (const auto &Component : + enumerate(make_range(sys::path::begin(Path), sys::path::end(Path)))) { + // Do not increase the number of redundant components: that would remove + // useful parts of already-visited paths. + if (Component.index() >= NumRedundant) break; - LCP = std::min(LCP, Cursor); + + // Lower the number of redundant components when there's a mismatch + // between the first path, and the path under consideration. + if (FirstPathComponents[Component.index()] != Component.value()) { + NumRedundant = Component.index(); + break; + } + } + } + + return NumRedundant; +} + +/// \brief Determine the length of the longest redundant prefix of the paths in +/// \p Paths. +unsigned getRedundantPrefixLen(ArrayRef Paths) { + // If there's at most one path, no path components are redundant. + if (Paths.size() <= 1) + return 0; + + unsigned PrefixLen = 0; + unsigned NumRedundant = getNumRedundantPathComponents(Paths); + auto Component = sys::path::begin(Paths[0]); + for (unsigned I = 0; I < NumRedundant; ++I) { + auto LastComponent = Component; + ++Component; + PrefixLen += Component - LastComponent; } - return LCP; + return PrefixLen; } } // end anonymous namespace @@ -200,12 +232,14 @@ void CoverageReport::render(const FileCoverageSummary &File, } void CoverageReport::render(const FunctionCoverageSummary &Function, + const DemangleCache &DC, raw_ostream &OS) const { auto FuncCoverageColor = determineCoveragePercentageColor(Function.RegionCoverage); auto LineCoverageColor = determineCoveragePercentageColor(Function.LineCoverage); - OS << column(Function.Name, FunctionReportColumns[0], Column::RightTrim) + OS << column(DC.demangle(Function.Name), FunctionReportColumns[0], + Column::RightTrim) << format("%*u", FunctionReportColumns[1], (unsigned)Function.RegionCoverage.NumRegions); Options.colored_ostream(OS, FuncCoverageColor) @@ -230,6 +264,7 @@ void CoverageReport::render(const FunctionCoverageSummary &Function, } void CoverageReport::renderFunctionReports(ArrayRef Files, + const DemangleCache &DC, raw_ostream &OS) { bool isFirst = true; for (StringRef Filename : Files) { @@ -242,7 +277,7 @@ void CoverageReport::renderFunctionReports(ArrayRef Files, std::vector Funcnames; for (const auto &F : Functions) - Funcnames.emplace_back(F.Name); + Funcnames.emplace_back(DC.demangle(F.Name)); adjustColumnWidths({}, Funcnames); OS << "File '" << Filename << "':\n"; @@ -262,12 +297,12 @@ void CoverageReport::renderFunctionReports(ArrayRef Files, ++Totals.ExecutionCount; Totals.RegionCoverage += Function.RegionCoverage; Totals.LineCoverage += Function.LineCoverage; - render(Function, OS); + render(Function, DC, OS); } if (Totals.ExecutionCount) { renderDivider(FunctionReportColumns, OS); OS << "\n"; - render(Totals, OS); + render(Totals, DC, OS); } } } @@ -277,9 +312,7 @@ CoverageReport::prepareFileReports(const coverage::CoverageMapping &Coverage, FileCoverageSummary &Totals, ArrayRef Files) { std::vector FileReports; - unsigned LCP = 0; - if (Files.size() > 1) - LCP = getLongestCommonPrefixLen(Files); + unsigned LCP = getRedundantPrefixLen(Files); for (StringRef Filename : Files) { FileCoverageSummary Summary(Filename.drop_front(LCP)); diff --git a/tools/llvm-cov/CoverageReport.h b/tools/llvm-cov/CoverageReport.h index 7a416497e258e..071be2e21594c 100644 --- a/tools/llvm-cov/CoverageReport.h +++ b/tools/llvm-cov/CoverageReport.h @@ -25,14 +25,16 @@ class CoverageReport { const coverage::CoverageMapping &Coverage; void render(const FileCoverageSummary &File, raw_ostream &OS) const; - void render(const FunctionCoverageSummary &Function, raw_ostream &OS) const; + void render(const FunctionCoverageSummary &Function, const DemangleCache &DC, + raw_ostream &OS) const; public: CoverageReport(const CoverageViewOptions &Options, const coverage::CoverageMapping &Coverage) : Options(Options), Coverage(Coverage) {} - void renderFunctionReports(ArrayRef Files, raw_ostream &OS); + void renderFunctionReports(ArrayRef Files, + const DemangleCache &DC, raw_ostream &OS); /// Prepare file reports for the files specified in \p Files. static std::vector diff --git a/tools/llvm-cov/CoverageSummaryInfo.h b/tools/llvm-cov/CoverageSummaryInfo.h index c04a4d42ccd74..680fc3757686f 100644 --- a/tools/llvm-cov/CoverageSummaryInfo.h +++ b/tools/llvm-cov/CoverageSummaryInfo.h @@ -160,6 +160,19 @@ struct FileCoverageSummary { } }; +/// \brief A cache for demangled symbols. +struct DemangleCache { + StringMap DemangledNames; + + /// \brief Demangle \p Sym if possible. Otherwise, just return \p Sym. + StringRef demangle(StringRef Sym) const { + const auto DemangledName = DemangledNames.find(Sym); + if (DemangledName == DemangledNames.end()) + return Sym; + return DemangledName->getValue(); + } +}; + } // namespace llvm #endif // LLVM_COV_COVERAGESUMMARYINFO_H diff --git a/tools/llvm-cov/TestingSupport.cpp b/tools/llvm-cov/TestingSupport.cpp index 72768f4fd583f..4713d75f17dd4 100644 --- a/tools/llvm-cov/TestingSupport.cpp +++ b/tools/llvm-cov/TestingSupport.cpp @@ -48,13 +48,16 @@ int convertForTestingMain(int argc, const char *argv[]) { // Look for the sections that we are interested in. int FoundSectionCount = 0; SectionRef ProfileNames, CoverageMapping; + auto ObjFormat = OF->getTripleObjectFormat(); for (const auto &Section : OF->sections()) { StringRef Name; if (Section.getName(Name)) return 1; - if (Name == llvm::getInstrProfNameSectionName(false)) { + if (Name == llvm::getInstrProfSectionName(IPSK_name, ObjFormat, + /*AddSegmentInfo=*/false)) { ProfileNames = Section; - } else if (Name == llvm::getInstrProfCoverageSectionName(false)) { + } else if (Name == llvm::getInstrProfSectionName( + IPSK_covmap, ObjFormat, /*AddSegmentInfo=*/false)) { CoverageMapping = Section; } else continue; diff --git a/tools/llvm-cov/gcov.cpp b/tools/llvm-cov/gcov.cpp index 4652fed2a384e..4df7f015fd188 100644 --- a/tools/llvm-cov/gcov.cpp +++ b/tools/llvm-cov/gcov.cpp @@ -74,7 +74,7 @@ static void reportCoverage(StringRef SourceFile, StringRef ObjectDir, } if (DumpGCOV) - GF.dump(); + GF.print(errs()); FileInfo FI(Options); GF.collectLineCounts(FI); diff --git a/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/tools/llvm-cxxfilt/llvm-cxxfilt.cpp index 1e2797ba33343..13024fbeaeaa0 100644 --- a/tools/llvm-cxxfilt/llvm-cxxfilt.cpp +++ b/tools/llvm-cxxfilt/llvm-cxxfilt.cpp @@ -8,29 +8,89 @@ //===----------------------------------------------------------------------===// #include "llvm/Demangle/Demangle.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" #include "llvm/Support/raw_ostream.h" #include #include using namespace llvm; +enum Style { + Auto, ///< auto-detect mangling + GNU, ///< GNU + Lucid, ///< Lucid compiler (lcc) + ARM, + HP, ///< HP compiler (xCC) + EDG, ///< EDG compiler + GNUv3, ///< GNU C++ v3 ABI + Java, ///< Java (gcj) + GNAT ///< ADA copiler (gnat) +}; +static cl::opt