diff options
Diffstat (limited to 'llvm/tools')
131 files changed, 1826 insertions, 410 deletions
diff --git a/llvm/tools/bugpoint/BugDriver.h b/llvm/tools/bugpoint/BugDriver.h index ca57405..71a5aa1 100644 --- a/llvm/tools/bugpoint/BugDriver.h +++ b/llvm/tools/bugpoint/BugDriver.h @@ -16,6 +16,7 @@ #define LLVM_TOOLS_BUGPOINT_BUGDRIVER_H #include "llvm/IR/ValueMap.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Transforms/Utils/ValueMapper.h" @@ -41,6 +42,10 @@ extern bool DisableSimplifyCFG; /// extern bool BugpointIsInterrupted; +/// Command line options used across files. +extern cl::list<std::string> InputArgv; +extern cl::opt<std::string> OutputPrefix; + class BugDriver { LLVMContext &Context; const char *ToolName; // argv[0] of bugpoint diff --git a/llvm/tools/bugpoint/ExecutionDriver.cpp b/llvm/tools/bugpoint/ExecutionDriver.cpp index 8c6b7fb..96eeb35 100644 --- a/llvm/tools/bugpoint/ExecutionDriver.cpp +++ b/llvm/tools/bugpoint/ExecutionDriver.cpp @@ -13,7 +13,6 @@ #include "BugDriver.h" #include "ToolRunner.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/Program.h" @@ -102,15 +101,13 @@ static cl::opt<std::string> CustomExecCommand( // Anything specified after the --args option are taken as arguments to the // program being debugged. -namespace llvm { -cl::list<std::string> InputArgv("args", cl::Positional, - cl::desc("<program arguments>..."), - cl::PositionalEatsArgs); - -cl::opt<std::string> - OutputPrefix("output-prefix", cl::init("bugpoint"), - cl::desc("Prefix to use for outputs (default: 'bugpoint')")); -} // namespace llvm +cl::list<std::string> llvm::InputArgv("args", cl::Positional, + cl::desc("<program arguments>..."), + cl::PositionalEatsArgs); + +cl::opt<std::string> llvm::OutputPrefix( + "output-prefix", cl::init("bugpoint"), + cl::desc("Prefix to use for outputs (default: 'bugpoint')")); static cl::list<std::string> ToolArgv("tool-args", cl::Positional, cl::desc("<tool arguments>..."), diff --git a/llvm/tools/bugpoint/ExtractFunction.cpp b/llvm/tools/bugpoint/ExtractFunction.cpp index 3206589..31cdd0d 100644 --- a/llvm/tools/bugpoint/ExtractFunction.cpp +++ b/llvm/tools/bugpoint/ExtractFunction.cpp @@ -36,9 +36,6 @@ using namespace llvm; #define DEBUG_TYPE "bugpoint" bool llvm::DisableSimplifyCFG = false; -namespace llvm { -extern cl::opt<std::string> OutputPrefix; -} // namespace llvm static cl::opt<bool> NoDCE("disable-dce", diff --git a/llvm/tools/bugpoint/ListReducer.h b/llvm/tools/bugpoint/ListReducer.h index 06f8ddb2..ceee853 100644 --- a/llvm/tools/bugpoint/ListReducer.h +++ b/llvm/tools/bugpoint/ListReducer.h @@ -32,7 +32,7 @@ template <typename ElTy> struct ListReducer { KeepPrefix // The prefix alone satisfies the predicate }; - virtual ~ListReducer() {} + virtual ~ListReducer() = default; /// This virtual function should be overriden by subclasses to implement the /// test desired. The testcase is only required to test to see if the Kept diff --git a/llvm/tools/bugpoint/Miscompilation.cpp b/llvm/tools/bugpoint/Miscompilation.cpp index a7f1643..dcad126 100644 --- a/llvm/tools/bugpoint/Miscompilation.cpp +++ b/llvm/tools/bugpoint/Miscompilation.cpp @@ -28,11 +28,6 @@ using namespace llvm; -namespace llvm { -extern cl::opt<std::string> OutputPrefix; -extern cl::list<std::string> InputArgv; -} // end namespace llvm - static cl::opt<bool> DisableLoopExtraction( "disable-loop-extraction", cl::desc("Don't extract loops when searching for miscompilations"), diff --git a/llvm/tools/bugpoint/OptimizerDriver.cpp b/llvm/tools/bugpoint/OptimizerDriver.cpp index bf2e8c0..191f87c 100644 --- a/llvm/tools/bugpoint/OptimizerDriver.cpp +++ b/llvm/tools/bugpoint/OptimizerDriver.cpp @@ -34,10 +34,6 @@ using namespace llvm; #define DEBUG_TYPE "bugpoint" -namespace llvm { -extern cl::opt<std::string> OutputPrefix; -} - static cl::opt<std::string> OptCmd("opt-command", cl::init(""), cl::desc("Path to opt. (default: search path " diff --git a/llvm/tools/bugpoint/ToolRunner.h b/llvm/tools/bugpoint/ToolRunner.h index c9da9af..9ff0663 100644 --- a/llvm/tools/bugpoint/ToolRunner.h +++ b/llvm/tools/bugpoint/ToolRunner.h @@ -105,7 +105,7 @@ public: createCustomExecutor(const char *Argv0, std::string &Message, const std::string &ExecCommandLine); - virtual ~AbstractInterpreter() {} + virtual ~AbstractInterpreter() = default; /// compileProgram - Compile the specified program from bitcode to executable /// code. This does not produce any output, it is only used when debugging diff --git a/llvm/tools/dsymutil/BinaryHolder.h b/llvm/tools/dsymutil/BinaryHolder.h index cb5bd95..27d7151 100644 --- a/llvm/tools/dsymutil/BinaryHolder.h +++ b/llvm/tools/dsymutil/BinaryHolder.h @@ -110,7 +110,7 @@ public: std::string Filename; TimestampTy Timestamp; - KeyTy() {} + KeyTy() = default; KeyTy(StringRef Filename, TimestampTy Timestamp) : Filename(Filename.str()), Timestamp(Timestamp) {} }; diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp index b91c27e..1fc5bba 100644 --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -90,7 +90,6 @@ #include <cstdlib> #include <cstring> #include <limits> -#include <map> #include <memory> #include <optional> #include <string> @@ -794,9 +793,10 @@ bool DwarfLinkerForBinary::linkImpl( reportWarning("Could not parse binary Swift module: " + toString(FromInterfaceOrErr.takeError()), Obj->getObjectFilename()); - // Only skip swiftmodules that could be parsed and are - // positively identified as textual. - } else if (*FromInterfaceOrErr) { + // Only skip swiftmodules that could be parsed and are positively + // identified as textual. Do so only when the option allows. + } else if (*FromInterfaceOrErr && + !Options.IncludeSwiftModulesFromInterface) { if (Options.Verbose) outs() << "Skipping compiled textual Swift interface: " << Obj->getObjectFilename() << "\n"; diff --git a/llvm/tools/dsymutil/LinkUtils.h b/llvm/tools/dsymutil/LinkUtils.h index ad5515a..c333a3d 100644 --- a/llvm/tools/dsymutil/LinkUtils.h +++ b/llvm/tools/dsymutil/LinkUtils.h @@ -114,6 +114,13 @@ struct LinkOptions { /// Whether all remarks should be kept or only remarks with valid debug /// locations. bool RemarksKeepAll = true; + + /// Whether or not to copy binary swiftmodules built from textual + /// .swiftinterface files into the dSYM bundle. These typically come only + /// from the SDK (since textual interfaces require library evolution) and + /// thus are a waste of space to copy into the bundle. Turn this on if the + /// swiftmodules are different from those in the SDK. + bool IncludeSwiftModulesFromInterface = false; /// @} LinkOptions() = default; diff --git a/llvm/tools/dsymutil/MachOUtils.cpp b/llvm/tools/dsymutil/MachOUtils.cpp index 362a999..fba6988 100644 --- a/llvm/tools/dsymutil/MachOUtils.cpp +++ b/llvm/tools/dsymutil/MachOUtils.cpp @@ -339,11 +339,11 @@ static bool createDwarfSegment(const MCAssembler& Asm,uint64_t VMAddr, uint64_t if (Alignment > 1) { VMAddr = alignTo(VMAddr, Alignment); FileOffset = alignTo(FileOffset, Alignment); - if (FileOffset > UINT32_MAX) - return error("section " + Sec->getName() + - "'s file offset exceeds 4GB." - " Refusing to produce an invalid Mach-O file."); } + if (FileOffset > UINT32_MAX) + return error("section " + Sec->getName() + + "'s file offset exceeds 4GB." + " Refusing to produce an invalid Mach-O file."); Writer.writeSection(Asm, *Sec, VMAddr, FileOffset, 0, 0, 0); FileOffset += Asm.getSectionAddressSize(*Sec); diff --git a/llvm/tools/dsymutil/Options.td b/llvm/tools/dsymutil/Options.td index ad35e55..571f90c 100644 --- a/llvm/tools/dsymutil/Options.td +++ b/llvm/tools/dsymutil/Options.td @@ -94,7 +94,7 @@ def: Flag<["-"], "s">, Group<grp_general>; def flat: F<"flat">, - HelpText<"Produce a flat dSYM file (not a bundle).">, + HelpText<"Produce a flat dSYM file (not a bundle). Intended for testing and generally unsupported by tools that consume dSYMs.">, Group<grp_general>; def: Flag<["-"], "f">, Alias<flat>, @@ -202,6 +202,14 @@ def remarks_drop_without_debug: Flag<["--", "-"], "remarks-drop-without-debug">, "all remarks are kept.">, Group<grp_general>; +def include_swiftmodules_from_interface: Flag<["--", "-"], "include-swiftmodules-from-interface">, + HelpText<"Whether or not to copy binary swiftmodules built from textual " + ".swiftinterface files into the dSYM bundle. These typically come only " + "from the SDK (since textual interfaces require library evolution) and " + "thus are a waste of space to copy into the bundle. Turn this on if the " + "swiftmodules are different from those in the SDK.">, + Group<grp_general>; + def linker: Separate<["--", "-"], "linker">, MetaVarName<"<DWARF linker type>">, HelpText<"Specify the desired type of DWARF linker. Defaults to 'classic'">, diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp index 913077e..a71c57c 100644 --- a/llvm/tools/dsymutil/dsymutil.cpp +++ b/llvm/tools/dsymutil/dsymutil.cpp @@ -391,6 +391,9 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) { Options.LinkOpts.RemarksKeepAll = !Args.hasArg(OPT_remarks_drop_without_debug); + Options.LinkOpts.IncludeSwiftModulesFromInterface = + Args.hasArg(OPT_include_swiftmodules_from_interface); + if (opt::Arg *BuildVariantSuffix = Args.getLastArg(OPT_build_variant_suffix)) Options.LinkOpts.BuildVariantSuffix = BuildVariantSuffix->getValue(); @@ -870,7 +873,6 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) { "-fat64 flag to force a 64-bit header and silence this " "warning.", FileOffset); - return EXIT_FAILURE; } FileOffset += stat->getSize(); } diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp index 256933d..06045a6 100644 --- a/llvm/tools/gold/gold-plugin.cpp +++ b/llvm/tools/gold/gold-plugin.cpp @@ -36,7 +36,6 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Host.h" #include <list> -#include <map> #include <plugin-api.h> #include <string> #include <system_error> diff --git a/llvm/tools/llc/NewPMDriver.cpp b/llvm/tools/llc/NewPMDriver.cpp index fa82689..6d4989e 100644 --- a/llvm/tools/llc/NewPMDriver.cpp +++ b/llvm/tools/llc/NewPMDriver.cpp @@ -14,8 +14,10 @@ #include "NewPMDriver.h" #include "llvm/Analysis/CGSCCPassManager.h" +#include "llvm/Analysis/RuntimeLibcallInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/CodeGen/CommandFlags.h" +#include "llvm/CodeGen/LibcallLoweringInfo.h" #include "llvm/CodeGen/MIRParser/MIRParser.h" #include "llvm/CodeGen/MIRPrinter.h" #include "llvm/CodeGen/MachineFunctionAnalysis.h" @@ -101,6 +103,13 @@ int llvm::compileModuleWithNewPM( raw_pwrite_stream *OS = &Out->os(); + std::unique_ptr<buffer_ostream> BOS; + if (codegen::getFileType() != CodeGenFileType::AssemblyFile && + !Out->os().supportsSeeking()) { + BOS = std::make_unique<buffer_ostream>(Out->os()); + OS = BOS.get(); + } + // Fetch options from TargetPassConfig CGPassBuilderOption Opt = getCGPassBuilderOption(); Opt.DisableVerify = VK != VerifierKind::InputOutput; @@ -129,6 +138,16 @@ int llvm::compileModuleWithNewPM( SI.registerCallbacks(PIC, &MAM); FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); }); + + MAM.registerPass([&] { + const TargetOptions &Options = Target->Options; + return RuntimeLibraryAnalysis( + M->getTargetTriple(), Target->Options.ExceptionModel, + Target->Options.FloatABIType, Target->Options.EABIVersion, + Options.MCOptions.ABIName, Target->Options.VecLib); + }); + MAM.registerPass([&] { return LibcallLoweringModuleAnalysis(); }); + MAM.registerPass([&] { return MachineModuleAnalysis(MMI); }); ModulePassManager MPM; diff --git a/llvm/tools/llc/NewPMDriver.h b/llvm/tools/llc/NewPMDriver.h index c8a6022..0dbd467 100644 --- a/llvm/tools/llc/NewPMDriver.h +++ b/llvm/tools/llc/NewPMDriver.h @@ -22,7 +22,6 @@ #include "llvm/IR/DiagnosticHandler.h" #include "llvm/Support/CodeGen.h" #include <memory> -#include <vector> namespace llvm { class Module; diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp index 152f7db..613780e 100644 --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -15,6 +15,8 @@ #include "NewPMDriver.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/RuntimeLibcallInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/CodeGen/CommandFlags.h" #include "llvm/CodeGen/LinkAllAsmWriterComponents.h" @@ -45,6 +47,7 @@ #include "llvm/Support/FormattedStream.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/PGOOptions.h" +#include "llvm/Support/Path.h" #include "llvm/Support/PluginLoader.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetSelect.h" @@ -57,11 +60,13 @@ #include "llvm/TargetParser/SubtargetFeature.h" #include "llvm/TargetParser/Triple.h" #include "llvm/Transforms/Utils/Cloning.h" +#include <cassert> #include <memory> #include <optional> using namespace llvm; static codegen::RegisterCodeGenFlags CGF; +static codegen::RegisterSaveStatsFlag SSF; // General options for llc. Other pass-specific options are specified // within the corresponding llc passes, and target-specific options @@ -281,7 +286,8 @@ static void setPGOOptions(TargetMachine &TM) { TM.setPGOOption(PGOOpt); } -static int compileModule(char **, LLVMContext &); +static int compileModule(char **argv, LLVMContext &Context, + std::string &OutputFilename); [[noreturn]] static void reportError(Twine Msg, StringRef Filename = "") { SmallString<256> Prefix; @@ -301,9 +307,7 @@ static int compileModule(char **, LLVMContext &); llvm_unreachable("reportError() should not return"); } -static std::unique_ptr<ToolOutputFile> GetOutputStream(const char *TargetName, - Triple::OSType OS, - const char *ProgName) { +static std::unique_ptr<ToolOutputFile> GetOutputStream(Triple::OSType OS) { // If we don't yet have an output filename, make one. if (OutputFilename.empty()) { if (InputFilename == "-") @@ -352,11 +356,8 @@ static std::unique_ptr<ToolOutputFile> GetOutputStream(const char *TargetName, if (!Binary) OpenFlags |= sys::fs::OF_TextWithCRLF; auto FDOut = std::make_unique<ToolOutputFile>(OutputFilename, EC, OpenFlags); - if (EC) { + if (EC) reportError(EC.message()); - return nullptr; - } - return FDOut; } @@ -437,18 +438,22 @@ int main(int argc, char **argv) { reportError(std::move(E), RemarksFilename); LLVMRemarkFileHandle RemarksFile = std::move(*RemarksFileOrErr); + codegen::MaybeEnableStatistics(); + std::string OutputFilename; + if (InputLanguage != "" && InputLanguage != "ir" && InputLanguage != "mir") reportError("input language must be '', 'IR' or 'MIR'"); // Compile the module TimeCompilations times to give better compile time // metrics. for (unsigned I = TimeCompilations; I; --I) - if (int RetVal = compileModule(argv, Context)) + if (int RetVal = compileModule(argv, Context, OutputFilename)) return RetVal; if (RemarksFile) RemarksFile->keep(); - return 0; + + return codegen::MaybeSaveStatistics(OutputFilename, "llc"); } static bool addPass(PassManagerBase &PM, const char *argv0, StringRef PassName, @@ -480,7 +485,8 @@ static bool addPass(PassManagerBase &PM, const char *argv0, StringRef PassName, return false; } -static int compileModule(char **argv, LLVMContext &Context) { +static int compileModule(char **argv, LLVMContext &Context, + std::string &OutputFilename) { // Load the module to be compiled... SMDiagnostic Err; std::unique_ptr<Module> M; @@ -541,6 +547,12 @@ static int compileModule(char **argv, LLVMContext &Context) { InputFilename); } + if (TheTriple.isX86() && + codegen::getFuseFPOps() != FPOpFusion::FPOpFusionMode::Standard) + WithColor::warning(errs(), argv[0]) + << "X86 backend ignores --fp-contract setting; use IR fast-math " + "flags instead."; + Options.BinutilsVersion = TargetMachine::parseBinutilsVersion(BinutilsVersion); Options.MCOptions.ShowMCEncoding = ShowMCEncoding; @@ -656,14 +668,16 @@ static int compileModule(char **argv, LLVMContext &Context) { Target->Options.FloatABIType = codegen::getFloatABIForCalls(); // Figure out where we are going to send the output. - std::unique_ptr<ToolOutputFile> Out = - GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]); + std::unique_ptr<ToolOutputFile> Out = GetOutputStream(TheTriple.getOS()); if (!Out) return 1; // Ensure the filename is passed down to CodeViewDebug. Target->Options.ObjectFilenameForDebug = Out->outputFilename(); + // Return a copy of the output filename via the output param + OutputFilename = Out->outputFilename(); + // Tell target that this tool is not necessarily used with argument ABI // compliance (i.e. narrow integer argument extensions). Target->Options.VerifyArgABICompliance = 0; @@ -678,7 +692,7 @@ static int compileModule(char **argv, LLVMContext &Context) { } // Add an appropriate TargetLibraryInfo pass for the module's triple. - TargetLibraryInfoImpl TLII(M->getTargetTriple()); + TargetLibraryInfoImpl TLII(M->getTargetTriple(), Target->Options.VecLib); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (DisableSimplifyLibCalls) @@ -714,6 +728,10 @@ static int compileModule(char **argv, LLVMContext &Context) { // Build up all of the passes that we want to do to the module. legacy::PassManager PM; PM.add(new TargetLibraryInfoWrapperPass(TLII)); + PM.add(new RuntimeLibraryInfoWrapper( + M->getTargetTriple(), Target->Options.ExceptionModel, + Target->Options.FloatABIType, Target->Options.EABIVersion, + Options.MCOptions.ABIName, Target->Options.VecLib)); { raw_pwrite_stream *OS = &Out->os(); diff --git a/llvm/tools/lli/lli.cpp b/llvm/tools/lli/lli.cpp index 7fee06b..847ee32 100644 --- a/llvm/tools/lli/lli.cpp +++ b/llvm/tools/lli/lli.cpp @@ -283,7 +283,6 @@ static ExitOnError ExitOnErr; LLVM_ATTRIBUTE_USED static void linkComponents() { errs() << (void *)&llvm_orc_registerEHFrameSectionAllocAction << (void *)&llvm_orc_deregisterEHFrameSectionAllocAction - << (void *)&llvm_orc_registerJITLoaderGDBWrapper << (void *)&llvm_orc_registerJITLoaderGDBAllocAction; } @@ -305,7 +304,7 @@ public: this->CacheDir[this->CacheDir.size() - 1] != '/') this->CacheDir += '/'; } - ~LLIObjectCache() override {} + ~LLIObjectCache() override = default; void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override { const std::string &ModuleID = M->getModuleIdentifier(); @@ -1228,15 +1227,15 @@ static Expected<std::unique_ptr<orc::ExecutorProcessControl>> launchRemote() { std::unique_ptr<char[]> ChildPath, ChildIn, ChildOut; { ChildPath.reset(new char[ChildExecPath.size() + 1]); - std::copy(ChildExecPath.begin(), ChildExecPath.end(), &ChildPath[0]); + llvm::copy(ChildExecPath, &ChildPath[0]); ChildPath[ChildExecPath.size()] = '\0'; std::string ChildInStr = utostr(PipeFD[0][0]); ChildIn.reset(new char[ChildInStr.size() + 1]); - std::copy(ChildInStr.begin(), ChildInStr.end(), &ChildIn[0]); + llvm::copy(ChildInStr, &ChildIn[0]); ChildIn[ChildInStr.size()] = '\0'; std::string ChildOutStr = utostr(PipeFD[1][1]); ChildOut.reset(new char[ChildOutStr.size() + 1]); - std::copy(ChildOutStr.begin(), ChildOutStr.end(), &ChildOut[0]); + llvm::copy(ChildOutStr, &ChildOut[0]); ChildOut[ChildOutStr.size()] = '\0'; } diff --git a/llvm/tools/llvm-c-test/attributes.c b/llvm/tools/llvm-c-test/attributes.c index 088684c..8d1735f 100644 --- a/llvm/tools/llvm-c-test/attributes.c +++ b/llvm/tools/llvm-c-test/attributes.c @@ -20,7 +20,8 @@ int llvm_test_function_attributes(void) { LLVMEnablePrettyStackTrace(); - LLVMModuleRef M = llvm_load_module(LLVMGetGlobalContext(), false, true); + LLVMContextRef C = LLVMContextCreate(); + LLVMModuleRef M = llvm_load_module(C, false, true); LLVMValueRef F = LLVMGetFirstFunction(M); while (F) { @@ -42,6 +43,7 @@ int llvm_test_function_attributes(void) { } LLVMDisposeModule(M); + LLVMContextDispose(C); return 0; } @@ -49,7 +51,8 @@ int llvm_test_function_attributes(void) { int llvm_test_callsite_attributes(void) { LLVMEnablePrettyStackTrace(); - LLVMModuleRef M = llvm_load_module(LLVMGetGlobalContext(), false, true); + LLVMContextRef C = LLVMContextCreate(); + LLVMModuleRef M = llvm_load_module(C, false, true); LLVMValueRef F = LLVMGetFirstFunction(M); while (F) { @@ -81,6 +84,7 @@ int llvm_test_callsite_attributes(void) { } LLVMDisposeModule(M); + LLVMContextDispose(C); return 0; } diff --git a/llvm/tools/llvm-c-test/calc.c b/llvm/tools/llvm-c-test/calc.c index 267397a..2fc0cae 100644 --- a/llvm/tools/llvm-c-test/calc.c +++ b/llvm/tools/llvm-c-test/calc.c @@ -45,6 +45,8 @@ static LLVMValueRef build_from_tokens(char **tokens, int ntokens, int depth = 0; int i; + LLVMContextRef C = LLVMGetBuilderContext(builder); + for (i = 0; i < ntokens; i++) { char tok = tokens[i][0]; switch (tok) { @@ -74,7 +76,7 @@ static LLVMValueRef build_from_tokens(char **tokens, int ntokens, return NULL; } - LLVMTypeRef ty = LLVMInt64Type(); + LLVMTypeRef ty = LLVMInt64TypeInContext(C); off = LLVMBuildGEP2(builder, ty, param, &stack[depth - 1], 1, ""); stack[depth - 1] = LLVMBuildLoad2(builder, ty, off, ""); @@ -94,7 +96,7 @@ static LLVMValueRef build_from_tokens(char **tokens, int ntokens, return NULL; } - stack[depth++] = LLVMConstInt(LLVMInt64Type(), val, 1); + stack[depth++] = LLVMConstInt(LLVMInt64TypeInContext(C), val, 1); break; } } @@ -115,15 +117,17 @@ static void handle_line(char **tokens, int ntokens) { LLVMValueRef param; LLVMValueRef res; - LLVMModuleRef M = LLVMModuleCreateWithName(name); + LLVMContextRef C = LLVMContextCreate(); + LLVMModuleRef M = LLVMModuleCreateWithNameInContext(name, C); - LLVMTypeRef I64ty = LLVMInt64Type(); + LLVMTypeRef I64ty = LLVMInt64TypeInContext(C); LLVMTypeRef I64Ptrty = LLVMPointerType(I64ty, 0); LLVMTypeRef Fty = LLVMFunctionType(I64ty, &I64Ptrty, 1, 0); LLVMValueRef F = LLVMAddFunction(M, name, Fty); - LLVMBuilderRef builder = LLVMCreateBuilder(); - LLVMPositionBuilderAtEnd(builder, LLVMAppendBasicBlock(F, "entry")); + LLVMBuilderRef builder = LLVMCreateBuilderInContext(C); + LLVMPositionBuilderAtEnd(builder, + LLVMAppendBasicBlockInContext(C, F, "entry")); LLVMGetParams(F, ¶m); LLVMSetValueName(param, "in"); @@ -138,6 +142,7 @@ static void handle_line(char **tokens, int ntokens) { LLVMDisposeBuilder(builder); LLVMDisposeModule(M); + LLVMContextDispose(C); } int llvm_calc(void) { diff --git a/llvm/tools/llvm-c-test/debuginfo.c b/llvm/tools/llvm-c-test/debuginfo.c index 9db7aa0..44d1f9c 100644 --- a/llvm/tools/llvm-c-test/debuginfo.c +++ b/llvm/tools/llvm-c-test/debuginfo.c @@ -33,7 +33,8 @@ declare_objc_class(LLVMDIBuilderRef DIB, LLVMMetadataRef File) { int llvm_test_dibuilder(void) { const char *Filename = "debuginfo.c"; - LLVMModuleRef M = LLVMModuleCreateWithName(Filename); + LLVMContextRef C = LLVMContextCreate(); + LLVMModuleRef M = LLVMModuleCreateWithNameInContext(Filename, C); LLVMSetIsNewDbgInfoFormat(M, true); assert(LLVMIsNewDbgInfoFormat(M)); @@ -101,15 +102,16 @@ int llvm_test_dibuilder(void) { LLVMAddNamedMetadataOperand(M, "FooType", LLVMMetadataAsValue(LLVMGetModuleContext(M), StructDbgPtrTy)); - + LLVMTypeRef I64Ty = LLVMInt64TypeInContext(C); LLVMTypeRef FooParamTys[] = { - LLVMInt64Type(), - LLVMInt64Type(), - LLVMVectorType(LLVMInt64Type(), 10), + I64Ty, + I64Ty, + LLVMVectorType(I64Ty, 10), }; - LLVMTypeRef FooFuncTy = LLVMFunctionType(LLVMInt64Type(), FooParamTys, 3, 0); + LLVMTypeRef FooFuncTy = LLVMFunctionType(I64Ty, FooParamTys, 3, 0); LLVMValueRef FooFunction = LLVMAddFunction(M, "foo", FooFuncTy); - LLVMBasicBlockRef FooEntryBlock = LLVMAppendBasicBlock(FooFunction, "entry"); + LLVMBasicBlockRef FooEntryBlock = + LLVMAppendBasicBlockInContext(C, FooFunction, "entry"); LLVMMetadataRef Subscripts[] = { LLVMDIBuilderGetOrCreateSubrange(DIB, 0, 10), @@ -130,9 +132,8 @@ int llvm_test_dibuilder(void) { LLVMDIFlagFwdDecl, "", 0); - LLVMMetadataRef FooParamLocation = - LLVMDIBuilderCreateDebugLocation(LLVMGetGlobalContext(), 42, 0, - ReplaceableFunctionMetadata, NULL); + LLVMMetadataRef FooParamLocation = LLVMDIBuilderCreateDebugLocation( + C, 42, 0, ReplaceableFunctionMetadata, NULL); LLVMMetadataRef FunctionMetadata = LLVMDIBuilderCreateFunction( DIB, File, "foo", 3, "foo", 3, File, 42, NULL, true, true, 42, 0, false); LLVMMetadataReplaceAllUsesWith(ReplaceableFunctionMetadata, FunctionMetadata); @@ -145,24 +146,24 @@ int llvm_test_dibuilder(void) { LLVMDIBuilderCreateParameterVariable(DIB, FunctionMetadata, "a", 1, 1, File, 42, Int64Ty, true, 0); - LLVMDIBuilderInsertDeclareRecordAtEnd( - DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar1, - FooParamExpression, FooParamLocation, FooEntryBlock); + LLVMDIBuilderInsertDeclareRecordAtEnd(DIB, LLVMConstInt(I64Ty, 0, false), + FooParamVar1, FooParamExpression, + FooParamLocation, FooEntryBlock); LLVMMetadataRef FooParamVar2 = LLVMDIBuilderCreateParameterVariable(DIB, FunctionMetadata, "b", 1, 2, File, 42, Int64Ty, true, 0); - LLVMDIBuilderInsertDeclareRecordAtEnd( - DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar2, - FooParamExpression, FooParamLocation, FooEntryBlock); + LLVMDIBuilderInsertDeclareRecordAtEnd(DIB, LLVMConstInt(I64Ty, 0, false), + FooParamVar2, FooParamExpression, + FooParamLocation, FooEntryBlock); LLVMMetadataRef FooParamVar3 = LLVMDIBuilderCreateParameterVariable( DIB, FunctionMetadata, "c", 1, 3, File, 42, VectorTy, true, 0); - LLVMDIBuilderInsertDeclareRecordAtEnd( - DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar3, - FooParamExpression, FooParamLocation, FooEntryBlock); + LLVMDIBuilderInsertDeclareRecordAtEnd(DIB, LLVMConstInt(I64Ty, 0, false), + FooParamVar3, FooParamExpression, + FooParamLocation, FooEntryBlock); LLVMSetSubprogram(FooFunction, FunctionMetadata); @@ -174,14 +175,14 @@ int llvm_test_dibuilder(void) { LLVMMetadataRef FooLexicalBlock = LLVMDIBuilderCreateLexicalBlock(DIB, FunctionMetadata, File, 42, 0); - LLVMBasicBlockRef FooVarBlock = LLVMAppendBasicBlock(FooFunction, "vars"); + LLVMBasicBlockRef FooVarBlock = + LLVMAppendBasicBlockInContext(C, FooFunction, "vars"); LLVMMetadataRef FooVarsLocation = - LLVMDIBuilderCreateDebugLocation(LLVMGetGlobalContext(), 43, 0, - FunctionMetadata, NULL); + LLVMDIBuilderCreateDebugLocation(C, 43, 0, FunctionMetadata, NULL); LLVMMetadataRef FooVar1 = LLVMDIBuilderCreateAutoVariable(DIB, FooLexicalBlock, "d", 1, File, 43, Int64Ty, true, 0, 0); - LLVMValueRef FooVal1 = LLVMConstInt(LLVMInt64Type(), 0, false); + LLVMValueRef FooVal1 = LLVMConstInt(I64Ty, 0, false); LLVMMetadataRef FooVarValueExpr1 = LLVMDIBuilderCreateConstantValueExpression(DIB, 0); @@ -190,7 +191,7 @@ int llvm_test_dibuilder(void) { LLVMMetadataRef FooVar2 = LLVMDIBuilderCreateAutoVariable( DIB, FooLexicalBlock, "e", 1, File, 44, Int64Ty, true, 0, 0); - LLVMValueRef FooVal2 = LLVMConstInt(LLVMInt64Type(), 1, false); + LLVMValueRef FooVal2 = LLVMConstInt(I64Ty, 1, false); LLVMMetadataRef FooVarValueExpr2 = LLVMDIBuilderCreateConstantValueExpression(DIB, 1); @@ -238,8 +239,8 @@ int llvm_test_dibuilder(void) { M, "LargeEnumTest", LLVMMetadataAsValue(LLVMGetModuleContext(M), LargeEnumTest)); - LLVMValueRef FooVal3 = LLVMConstInt(LLVMInt64Type(), 8, false); - LLVMValueRef FooVal4 = LLVMConstInt(LLVMInt64Type(), 4, false); + LLVMValueRef FooVal3 = LLVMConstInt(I64Ty, 8, false); + LLVMValueRef FooVal4 = LLVMConstInt(I64Ty, 4, false); LLVMMetadataRef lo = LLVMValueAsMetadata(FooVal1); LLVMMetadataRef hi = LLVMValueAsMetadata(FooVal2); LLVMMetadataRef strd = LLVMValueAsMetadata(FooVal3); @@ -364,6 +365,43 @@ int llvm_test_dibuilder(void) { assert(AddDbgRecordUnderTheRange == NULL); (void)AddDbgRecordUnderTheRange; + // Test that we can read the first debug record. + LLVMMetadataRef AddDbgRecordFirstDebugLoc = + LLVMDbgRecordGetDebugLoc(AddDbgRecordFirst); + (void)AddDbgRecordFirstDebugLoc; + assert(LLVMDILocationGetLine(AddDbgRecordFirstDebugLoc) == 43); + assert(LLVMDbgRecordGetKind(AddDbgRecordFirst) == LLVMDbgRecordValue); + LLVMValueRef AddDbgRecordFirstValue = + LLVMDbgVariableRecordGetValue(AddDbgRecordFirst, 0); + (void)AddDbgRecordFirstValue; + assert(LLVMGetValueKind(AddDbgRecordFirstValue) == LLVMConstantIntValueKind); + assert(LLVMConstIntGetZExtValue(AddDbgRecordFirstValue) == 0); + LLVMMetadataRef AddDbgRecordFirstVariable = + LLVMDbgVariableRecordGetVariable(AddDbgRecordFirst); + (void)AddDbgRecordFirstVariable; + assert(LLVMGetMetadataKind(AddDbgRecordFirstVariable) == + LLVMDILocalVariableMetadataKind); + // TODO: For now, there is no way to get the name. + LLVMMetadataRef AddDbgRecordFirstVariableScope = + LLVMDIVariableGetScope(AddDbgRecordFirstVariable); + (void)AddDbgRecordFirstVariableScope; + assert(LLVMGetMetadataKind(AddDbgRecordFirstVariableScope) == + LLVMDILexicalBlockMetadataKind); + LLVMMetadataRef AddDbgRecordFirstVariableFile = + LLVMDIScopeGetFile(AddDbgRecordFirstVariableScope); + (void)AddDbgRecordFirstVariableFile; + assert(LLVMGetMetadataKind(AddDbgRecordFirstVariableFile) == + LLVMDIFileMetadataKind); + unsigned FileLen = 0; + assert(strcmp(LLVMDIFileGetFilename(AddDbgRecordFirstVariableFile, &FileLen), + "debuginfo.c") == 0); + (void)FileLen; + LLVMMetadataRef AddDbgRecordFirstExpr = + LLVMDbgVariableRecordGetExpression(AddDbgRecordFirst); + assert(LLVMGetMetadataKind(AddDbgRecordFirstExpr) == + LLVMDIExpressionMetadataKind); + (void)AddDbgRecordFirstExpr; + char *MStr = LLVMPrintModuleToString(M); puts(MStr); LLVMDisposeMessage(MStr); @@ -371,13 +409,14 @@ int llvm_test_dibuilder(void) { LLVMDisposeBuilder(Builder); LLVMDisposeDIBuilder(DIB); LLVMDisposeModule(M); + LLVMContextDispose(C); return 0; } int llvm_get_di_tag(void) { - LLVMModuleRef M = LLVMModuleCreateWithName("Mod"); - LLVMContextRef Context = LLVMGetModuleContext(M); + LLVMContextRef Context = LLVMContextCreate(); + LLVMModuleRef M = LLVMModuleCreateWithNameInContext("Mod", Context); const char String[] = "foo"; LLVMMetadataRef StringMD = @@ -400,12 +439,14 @@ int llvm_get_di_tag(void) { LLVMDisposeDIBuilder(Builder); LLVMDisposeModule(M); + LLVMContextDispose(Context); return 0; } int llvm_di_type_get_name(void) { - LLVMModuleRef M = LLVMModuleCreateWithName("Mod"); + LLVMContextRef C = LLVMContextCreate(); + LLVMModuleRef M = LLVMModuleCreateWithNameInContext("Mod", C); LLVMDIBuilderRef Builder = LLVMCreateDIBuilder(M); const char Filename[] = "metadata.c"; @@ -425,13 +466,15 @@ int llvm_di_type_get_name(void) { LLVMDisposeDIBuilder(Builder); LLVMDisposeModule(M); + LLVMContextDispose(C); return 0; } int llvm_add_globaldebuginfo(void) { const char *Filename = "debuginfo.c"; - LLVMModuleRef M = LLVMModuleCreateWithName(Filename); + LLVMContextRef C = LLVMContextCreate(); + LLVMModuleRef M = LLVMModuleCreateWithNameInContext(Filename, C); LLVMDIBuilderRef Builder = LLVMCreateDIBuilder(M); LLVMMetadataRef File = LLVMDIBuilderCreateFile(Builder, Filename, strlen(Filename), ".", 1); @@ -447,13 +490,12 @@ int llvm_add_globaldebuginfo(void) { Builder, File, "global", 6, "", 0, File, 1, Int64TypeDef, true, GlobalVarValueExpr, NULL, 0); - LLVMTypeRef RecType = - LLVMStructCreateNamed(LLVMGetModuleContext(M), "struct"); + LLVMTypeRef RecType = LLVMStructCreateNamed(C, "struct"); LLVMValueRef Global = LLVMAddGlobal(M, RecType, "global"); LLVMGlobalAddDebugInfo(Global, GVE); // use AddMetadata to add twice - int kindId = LLVMGetMDKindID("dbg", 3); + int kindId = LLVMGetMDKindIDInContext(C, "dbg", 3); LLVMGlobalAddMetadata(Global, kindId, GVE); size_t numEntries; LLVMValueMetadataEntry *ME = LLVMGlobalCopyAllMetadata(Global, &numEntries); @@ -463,6 +505,7 @@ int llvm_add_globaldebuginfo(void) { LLVMDisposeValueMetadataEntries(ME); LLVMDisposeDIBuilder(Builder); LLVMDisposeModule(M); + LLVMContextDispose(C); return 0; } diff --git a/llvm/tools/llvm-c-test/diagnostic.c b/llvm/tools/llvm-c-test/diagnostic.c index 0f9b48b..49b37cd 100644 --- a/llvm/tools/llvm-c-test/diagnostic.c +++ b/llvm/tools/llvm-c-test/diagnostic.c @@ -45,7 +45,7 @@ static void diagnosticHandler(LLVMDiagnosticInfoRef DI, void *C) { static int handlerCalled = 0; int llvm_test_diagnostic_handler(void) { - LLVMContextRef C = LLVMGetGlobalContext(); + LLVMContextRef C = LLVMContextCreate(); LLVMContextSetDiagnosticHandler(C, diagnosticHandler, &handlerCalled); if (LLVMContextGetDiagnosticHandler(C) != diagnosticHandler) { @@ -69,7 +69,7 @@ int llvm_test_diagnostic_handler(void) { LLVMModuleRef M; - int Ret = LLVMGetBitcodeModule2(MB, &M); + int Ret = LLVMGetBitcodeModuleInContext2(C, MB, &M); if (Ret) LLVMDisposeMemoryBuffer(MB); @@ -79,5 +79,6 @@ int llvm_test_diagnostic_handler(void) { fprintf(stderr, "Diagnostic handler was not called while loading module\n"); } + LLVMContextDispose(C); return 0; } diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp index 026d815..bd640cd 100644 --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -986,9 +986,10 @@ struct FunCloner { for (unsigned i = 0; i < NumMaskElts; i++) { int Val = LLVMGetMaskValue(Src, i); if (Val == LLVMGetUndefMaskElem()) { - MaskElts.push_back(LLVMGetUndef(LLVMInt64Type())); + MaskElts.push_back(LLVMGetUndef(LLVMInt64TypeInContext(Ctx))); } else { - MaskElts.push_back(LLVMConstInt(LLVMInt64Type(), Val, true)); + MaskElts.push_back( + LLVMConstInt(LLVMInt64TypeInContext(Ctx), Val, true)); } } LLVMValueRef Mask = LLVMConstVector(MaskElts.data(), NumMaskElts); @@ -1115,7 +1116,8 @@ struct FunCloner { if (Name != VName) report_fatal_error("Basic block name mismatch"); - LLVMBasicBlockRef BB = LLVMAppendBasicBlock(Fun, Name); + LLVMContextRef Ctx = LLVMGetModuleContext(M); + LLVMBasicBlockRef BB = LLVMAppendBasicBlockInContext(Ctx, Fun, Name); return BBMap[Src] = BB; } diff --git a/llvm/tools/llvm-c-test/metadata.c b/llvm/tools/llvm-c-test/metadata.c index 4fe8c00..6dd18d1 100644 --- a/llvm/tools/llvm-c-test/metadata.c +++ b/llvm/tools/llvm-c-test/metadata.c @@ -19,37 +19,41 @@ #include <string.h> int llvm_add_named_metadata_operand(void) { - LLVMModuleRef M = LLVMModuleCreateWithName("Mod"); - LLVMValueRef Int = LLVMConstInt(LLVMInt32Type(), 0, 0); + LLVMContextRef C = LLVMContextCreate(); + LLVMModuleRef M = LLVMModuleCreateWithNameInContext("Mod", C); + LLVMValueRef Int = LLVMConstInt(LLVMInt32TypeInContext(C), 0, 0); // This used to trigger an assertion - LLVMAddNamedMetadataOperand(M, "name", LLVMMDNode(&Int, 1)); + LLVMAddNamedMetadataOperand(M, "name", LLVMMDNodeInContext(C, &Int, 1)); LLVMDisposeModule(M); + LLVMContextDispose(C); return 0; } int llvm_set_metadata(void) { - LLVMBuilderRef Builder = LLVMCreateBuilder(); + LLVMContextRef C = LLVMContextCreate(); + LLVMBuilderRef Builder = LLVMCreateBuilderInContext(C); // This used to trigger an assertion LLVMValueRef Return = LLVMBuildRetVoid(Builder); const char Name[] = "kind"; - LLVMValueRef Int = LLVMConstInt(LLVMInt32Type(), 0, 0); - LLVMSetMetadata(Return, LLVMGetMDKindID(Name, strlen(Name)), - LLVMMDNode(&Int, 1)); + LLVMValueRef Int = LLVMConstInt(LLVMInt32TypeInContext(C), 0, 0); + LLVMSetMetadata(Return, LLVMGetMDKindIDInContext(C, Name, strlen(Name)), + LLVMMDNodeInContext(C, &Int, 1)); LLVMDisposeBuilder(Builder); LLVMDeleteInstruction(Return); + LLVMContextDispose(C); return 0; } int llvm_replace_md_operand(void) { - LLVMModuleRef M = LLVMModuleCreateWithName("Mod"); - LLVMContextRef Context = LLVMGetModuleContext(M); + LLVMContextRef Context = LLVMContextCreate(); + LLVMModuleRef M = LLVMModuleCreateWithNameInContext("Mod", Context); const char String1[] = "foo"; LLVMMetadataRef String1MD = @@ -71,17 +75,18 @@ int llvm_replace_md_operand(void) { (void)String; LLVMDisposeModule(M); + LLVMContextDispose(Context); return 0; } int llvm_is_a_value_as_metadata(void) { - LLVMModuleRef M = LLVMModuleCreateWithName("Mod"); - LLVMContextRef Context = LLVMGetModuleContext(M); + LLVMContextRef Context = LLVMContextCreate(); + LLVMModuleRef M = LLVMModuleCreateWithNameInContext("Mod", Context); { - LLVMValueRef Int = LLVMConstInt(LLVMInt32Type(), 0, 0); - LLVMValueRef NodeMD = LLVMMDNode(&Int, 1); + LLVMValueRef Int = LLVMConstInt(LLVMInt32TypeInContext(Context), 0, 0); + LLVMValueRef NodeMD = LLVMMDNodeInContext(Context, &Int, 1); assert(LLVMIsAValueAsMetadata(NodeMD) == NodeMD); (void)NodeMD; } @@ -96,5 +101,8 @@ int llvm_is_a_value_as_metadata(void) { (void)Value; } + LLVMDisposeModule(M); + LLVMContextDispose(Context); + return 0; } diff --git a/llvm/tools/llvm-c-test/module.c b/llvm/tools/llvm-c-test/module.c index 9698f09..daa97bb 100644 --- a/llvm/tools/llvm-c-test/module.c +++ b/llvm/tools/llvm-c-test/module.c @@ -61,19 +61,22 @@ LLVMModuleRef llvm_load_module(LLVMContextRef C, bool Lazy, bool New) { } int llvm_module_dump(bool Lazy, bool New) { - LLVMModuleRef M = llvm_load_module(LLVMGetGlobalContext(), Lazy, New); + LLVMContextRef C = LLVMContextCreate(); + LLVMModuleRef M = llvm_load_module(C, Lazy, New); char *irstr = LLVMPrintModuleToString(M); puts(irstr); LLVMDisposeMessage(irstr); LLVMDisposeModule(M); + LLVMContextDispose(C); return 0; } int llvm_module_list_functions(void) { - LLVMModuleRef M = llvm_load_module(LLVMGetGlobalContext(), false, false); + LLVMContextRef C = LLVMContextCreate(); + LLVMModuleRef M = llvm_load_module(C, false, false); LLVMValueRef f; f = LLVMGetFirstFunction(M); @@ -109,12 +112,14 @@ int llvm_module_list_functions(void) { } LLVMDisposeModule(M); + LLVMContextDispose(C); return 0; } int llvm_module_list_globals(void) { - LLVMModuleRef M = llvm_load_module(LLVMGetGlobalContext(), false, false); + LLVMContextRef C = LLVMContextCreate(); + LLVMModuleRef M = llvm_load_module(C, false, false); LLVMValueRef g; g = LLVMGetFirstGlobal(M); @@ -132,6 +137,7 @@ int llvm_module_list_globals(void) { } LLVMDisposeModule(M); + LLVMContextDispose(C); return 0; } diff --git a/llvm/tools/llvm-c-test/object.c b/llvm/tools/llvm-c-test/object.c index 53ffb1a..8948f23 100644 --- a/llvm/tools/llvm-c-test/object.c +++ b/llvm/tools/llvm-c-test/object.c @@ -19,7 +19,6 @@ int llvm_object_list_sections(void) { LLVMMemoryBufferRef MB; - LLVMBinaryRef O; LLVMSectionIteratorRef sect; char *outBufferErr = NULL; @@ -30,7 +29,8 @@ int llvm_object_list_sections(void) { } char *outBinaryErr = NULL; - O = LLVMCreateBinary(MB, LLVMGetGlobalContext(), &outBinaryErr); + LLVMContextRef C = LLVMContextCreate(); + LLVMBinaryRef O = LLVMCreateBinary(MB, C, &outBinaryErr); if (!O || outBinaryErr) { fprintf(stderr, "Error reading object: %s\n", outBinaryErr); free(outBinaryErr); @@ -50,13 +50,13 @@ int llvm_object_list_sections(void) { LLVMDisposeBinary(O); LLVMDisposeMemoryBuffer(MB); + LLVMContextDispose(C); return 0; } int llvm_object_list_symbols(void) { LLVMMemoryBufferRef MB; - LLVMBinaryRef O; LLVMSectionIteratorRef sect; LLVMSymbolIteratorRef sym; @@ -68,7 +68,8 @@ int llvm_object_list_symbols(void) { } char *outBinaryErr = NULL; - O = LLVMCreateBinary(MB, LLVMGetGlobalContext(), &outBinaryErr); + LLVMContextRef C = LLVMContextCreate(); + LLVMBinaryRef O = LLVMCreateBinary(MB, C, &outBinaryErr); if (!O || outBinaryErr) { fprintf(stderr, "Error reading object: %s\n", outBinaryErr); free(outBinaryErr); @@ -92,6 +93,7 @@ int llvm_object_list_symbols(void) { LLVMDisposeBinary(O); LLVMDisposeMemoryBuffer(MB); + LLVMContextDispose(C); return 0; } diff --git a/llvm/tools/llvm-cas/CMakeLists.txt b/llvm/tools/llvm-cas/CMakeLists.txt new file mode 100644 index 0000000..e9d40cb --- /dev/null +++ b/llvm/tools/llvm-cas/CMakeLists.txt @@ -0,0 +1,17 @@ +set(LLVM_TARGET_DEFINITIONS Options.td) +tablegen(LLVM Options.inc -gen-opt-parser-defs) +add_public_tablegen_target(LLVMCASToolTableGen) + +set(LLVM_LINK_COMPONENTS + Support + CAS + Option + ) + +add_llvm_tool(llvm-cas + llvm-cas.cpp + + DEPENDS + ${tablegen_deps} + LLVMCASToolTableGen + ) diff --git a/llvm/tools/llvm-cas/Options.td b/llvm/tools/llvm-cas/Options.td new file mode 100644 index 0000000..5ae64c1 --- /dev/null +++ b/llvm/tools/llvm-cas/Options.td @@ -0,0 +1,63 @@ +include "llvm/Option/OptParser.td" + +class F<string name> : Flag<["--", "-"], name>; + +def grp_action : OptionGroup<"Actions">, HelpText<"llvm-cas actions">; + +def help : F<"help">, HelpText<"Prints this help output">; +def : Flag<["-"], "h">, Alias<help>, HelpText<"Alias for --help">; + +// Tool actions + +def cas_dump : F<"dump">, HelpText<"Dump internal contents">, Group<grp_action>; +def cat_node_data : F<"cat-node-data">, + HelpText<"Cat node data">, + Group<grp_action>; +def make_blob : F<"make-blob">, HelpText<"Make blob">, Group<grp_action>; +def make_node : F<"make-node">, HelpText<"Make node">, Group<grp_action>; +def ls_node_refs : F<"ls-node-refs">, + HelpText<"List node refs">, + Group<grp_action>; +def import : F<"import">, + HelpText<"Import objects from another CAS">, + Group<grp_action>; +def put_cache_key : F<"put-cache-key">, + HelpText<"Set a value for a cache key">, + Group<grp_action>; +def get_cache_result : F<"get-cache-result">, + HelpText<"Get the result value from a cache key">, + Group<grp_action>; +def validate : F<"validate">, + HelpText<"Validate ObjectStore">, + Group<grp_action>; +def validate_object : F<"validate-object">, + HelpText<"Validate the object for CASID">, + Group<grp_action>; +def validate_if_needed : F<"validate-if-needed">, + HelpText<"Validate cas contents if needed">, + Group<grp_action>; +def prune : F<"prune">, HelpText<"Prune local cas storage">, Group<grp_action>; + +// Tool options + +def cas_path : Separate<["-", "--"], "cas">, + MetaVarName<"<path>">, + HelpText<"Path to CAS on disk">; + +def upstream_cas : Separate<["-", "--"], "upstream-cas">, + MetaVarName<"<path>">, + HelpText<"Path to another upstream CAS">; + +def data : Separate<["-", "--"], "data">, + MetaVarName<"<path>">, + HelpText<"Path to data or '-' for stdin">; + +def check_hash : F<"check-hash">, + HelpText<"Check all hashes during validation">; + +def allow_recovery : F<"allow-recovery">, + HelpText<"Allow recovery of CAS data">; + +def force : F<"force">, HelpText<"Force validation even if unnecessary">; + +def in_process : F<"in-process">, HelpText<"Validation in-process">; diff --git a/llvm/tools/llvm-cas/llvm-cas.cpp b/llvm/tools/llvm-cas/llvm-cas.cpp new file mode 100644 index 0000000..e72ee47 --- /dev/null +++ b/llvm/tools/llvm-cas/llvm-cas.cpp @@ -0,0 +1,405 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file A utility for operating on LLVM CAS. +/// +//===----------------------------------------------------------------------===// + +#include "llvm/CAS/ActionCache.h" +#include "llvm/CAS/BuiltinUnifiedCASDatabases.h" +#include "llvm/CAS/ObjectStore.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/InitLLVM.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; +using namespace llvm::cas; + +namespace { +enum ID { + OPT_INVALID = 0, // This is not an option ID. +#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__), +#include "Options.inc" +#undef OPTION +}; + +#define OPTTABLE_STR_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE + +using namespace llvm::opt; +static constexpr opt::OptTable::Info InfoTable[] = { +#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), +#include "Options.inc" +#undef OPTION +}; + +class LLVMCASOptTable : public opt::GenericOptTable { +public: + LLVMCASOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} +}; + +enum class CommandKind { + Invalid, + Dump, + CatNodeData, + MakeBlob, + MakeNode, + ListObjectReferences, + Import, + PutCacheKey, + GetCacheResult, + Validate, + ValidateObject, + ValidateIfNeeded, + Prune, +}; + +struct CommandOptions { + CommandKind Command = CommandKind::Invalid; + std::vector<std::string> Inputs; + std::string CASPath; + std::string UpstreamCASPath; + std::string DataPath; + bool CheckHash; + bool AllowRecovery; + bool Force; + bool InProcess; + + static CommandKind getCommandKind(opt::Arg &A) { + switch (A.getOption().getID()) { + case OPT_cas_dump: + return CommandKind::Dump; + case OPT_cat_node_data: + return CommandKind::CatNodeData; + case OPT_make_blob: + return CommandKind::MakeBlob; + case OPT_make_node: + return CommandKind::MakeNode; + case OPT_ls_node_refs: + return CommandKind::ListObjectReferences; + case OPT_import: + return CommandKind::Import; + case OPT_put_cache_key: + return CommandKind::PutCacheKey; + case OPT_get_cache_result: + return CommandKind::GetCacheResult; + case OPT_validate: + return CommandKind::Validate; + case OPT_validate_object: + return CommandKind::ValidateObject; + case OPT_validate_if_needed: + return CommandKind::ValidateIfNeeded; + case OPT_prune: + return CommandKind::Prune; + } + return CommandKind::Invalid; + } + + // Command requires input. + static bool requiresInput(CommandKind Kind) { + return Kind != CommandKind::ValidateIfNeeded && + Kind != CommandKind::Validate && Kind != CommandKind::MakeBlob && + Kind != CommandKind::MakeNode && Kind != CommandKind::Dump && + Kind != CommandKind::Prune; + } +}; +} // namespace + +static int dump(ObjectStore &CAS); +static int listObjectReferences(ObjectStore &CAS, const CASID &ID); +static int catNodeData(ObjectStore &CAS, const CASID &ID); +static int makeBlob(ObjectStore &CAS, StringRef DataPath); +static int makeNode(ObjectStore &CAS, ArrayRef<std::string> References, + StringRef DataPath); +static int import(ObjectStore &FromCAS, ObjectStore &ToCAS, + ArrayRef<std::string> Objects); +static int putCacheKey(ObjectStore &CAS, ActionCache &AC, + ArrayRef<std::string> Objects); +static int getCacheResult(ObjectStore &CAS, ActionCache &AC, const CASID &ID); +static int validateObject(ObjectStore &CAS, const CASID &ID); +static int validate(ObjectStore &CAS, ActionCache &AC, bool CheckHash); +static int validateIfNeeded(StringRef Path, bool CheckHash, bool Force, + bool AllowRecovery, bool InProcess, + const char *Argv0); +static int prune(cas::ObjectStore &CAS); + +static Expected<CommandOptions> parseOptions(int Argc, char **Argv) { + BumpPtrAllocator Alloc; + StringSaver Saver(Alloc); + SmallVector<const char *> ExpanedArgs; + if (!cl::expandResponseFiles(Argc, Argv, nullptr, Saver, ExpanedArgs)) + return createStringError("cannot expand response file"); + + LLVMCASOptTable T; + unsigned MI, MC; + opt::InputArgList Args = T.ParseArgs(ExpanedArgs, MI, MC); + + for (auto *Arg : Args.filtered(OPT_UNKNOWN)) { + llvm::errs() << "ignoring unknown option: " << Arg->getSpelling() << '\n'; + } + + if (Args.hasArg(OPT_help)) { + T.printHelp( + outs(), + (std::string(Argv[0]) + " [action] [options] <input files>").c_str(), + "llvm-cas tool that performs CAS actions.", false); + exit(0); + } + + CommandOptions Opts; + for (auto *A : Args.filtered(OPT_grp_action)) + Opts.Command = CommandOptions::getCommandKind(*A); + + if (Opts.Command == CommandKind::Invalid) + return createStringError("no command action is specified"); + + for (auto *File : Args.filtered(OPT_INPUT)) + Opts.Inputs.push_back(File->getValue()); + Opts.CASPath = Args.getLastArgValue(OPT_cas_path); + Opts.UpstreamCASPath = Args.getLastArgValue(OPT_upstream_cas); + Opts.DataPath = Args.getLastArgValue(OPT_data); + Opts.CheckHash = Args.hasArg(OPT_check_hash); + Opts.AllowRecovery = Args.hasArg(OPT_allow_recovery); + Opts.Force = Args.hasArg(OPT_force); + Opts.InProcess = Args.hasArg(OPT_in_process); + + // Validate options. + if (Opts.CASPath.empty()) + return createStringError("missing --cas <path>"); + + if (Opts.Inputs.empty() && CommandOptions::requiresInput(Opts.Command)) + return createStringError("missing <input> to operate on"); + + return Opts; +} + +int main(int Argc, char **Argv) { + InitLLVM X(Argc, Argv); + + ExitOnError ExitOnErr; + auto Opts = ExitOnErr(parseOptions(Argc, Argv)); + + if (Opts.Command == CommandKind::ValidateIfNeeded) + return validateIfNeeded(Opts.CASPath, Opts.CheckHash, Opts.Force, + Opts.AllowRecovery, Opts.InProcess, Argv[0]); + + auto [CAS, AC] = ExitOnErr(createOnDiskUnifiedCASDatabases(Opts.CASPath)); + assert(CAS); + + if (Opts.Command == CommandKind::Dump) + return dump(*CAS); + + if (Opts.Command == CommandKind::Validate) + return validate(*CAS, *AC, Opts.CheckHash); + + if (Opts.Command == CommandKind::MakeBlob) + return makeBlob(*CAS, Opts.DataPath); + + if (Opts.Command == CommandKind::MakeNode) + return makeNode(*CAS, Opts.Inputs, Opts.DataPath); + + if (Opts.Command == CommandKind::Prune) + return prune(*CAS); + + if (Opts.Command == CommandKind::Import) { + if (Opts.UpstreamCASPath.empty()) + ExitOnErr(createStringError("missing '-upstream-cas'")); + + auto [UpstreamCAS, _] = + ExitOnErr(createOnDiskUnifiedCASDatabases(Opts.UpstreamCASPath)); + return import(*UpstreamCAS, *CAS, Opts.Inputs); + } + + if (Opts.Command == CommandKind::PutCacheKey || + Opts.Command == CommandKind::GetCacheResult) { + if (!AC) + ExitOnErr(createStringError("no action-cache available")); + } + + if (Opts.Command == CommandKind::PutCacheKey) + return putCacheKey(*CAS, *AC, Opts.Inputs); + + // Remaining commands need exactly one CAS object. + if (Opts.Inputs.size() > 1) + ExitOnErr(createStringError("too many <object>s, expected 1")); + CASID ID = ExitOnErr(CAS->parseID(Opts.Inputs.front())); + + if (Opts.Command == CommandKind::GetCacheResult) + return getCacheResult(*CAS, *AC, ID); + + if (Opts.Command == CommandKind::ListObjectReferences) + return listObjectReferences(*CAS, ID); + + if (Opts.Command == CommandKind::CatNodeData) + return catNodeData(*CAS, ID); + + assert(Opts.Command == CommandKind::ValidateObject); + return validateObject(*CAS, ID); +} + +static Expected<std::unique_ptr<MemoryBuffer>> openBuffer(StringRef DataPath) { + if (DataPath.empty()) + return createStringError("--data missing"); + return errorOrToExpected(DataPath == "-" + ? llvm::MemoryBuffer::getSTDIN() + : llvm::MemoryBuffer::getFile(DataPath)); +} + +int dump(ObjectStore &CAS) { + ExitOnError ExitOnErr("llvm-cas: dump: "); + CAS.print(llvm::outs()); + return 0; +} + +int makeBlob(ObjectStore &CAS, StringRef DataPath) { + ExitOnError ExitOnErr("llvm-cas: make-blob: "); + std::unique_ptr<MemoryBuffer> Buffer = ExitOnErr(openBuffer(DataPath)); + + ObjectProxy Blob = ExitOnErr(CAS.createProxy({}, Buffer->getBuffer())); + llvm::outs() << Blob.getID() << "\n"; + return 0; +} + +int catNodeData(ObjectStore &CAS, const CASID &ID) { + ExitOnError ExitOnErr("llvm-cas: cat-node-data: "); + llvm::outs() << ExitOnErr(CAS.getProxy(ID)).getData(); + return 0; +} + +int listObjectReferences(ObjectStore &CAS, const CASID &ID) { + ExitOnError ExitOnErr("llvm-cas: ls-node-refs: "); + + ObjectProxy Object = ExitOnErr(CAS.getProxy(ID)); + ExitOnErr(Object.forEachReference([&](ObjectRef Ref) -> Error { + llvm::outs() << CAS.getID(Ref) << "\n"; + return Error::success(); + })); + + return 0; +} + +static int makeNode(ObjectStore &CAS, ArrayRef<std::string> Objects, + StringRef DataPath) { + std::unique_ptr<MemoryBuffer> Data = + ExitOnError("llvm-cas: make-node: data: ")(openBuffer(DataPath)); + + SmallVector<ObjectRef> IDs; + for (StringRef Object : Objects) { + ExitOnError ObjectErr("llvm-cas: make-node: ref: "); + std::optional<ObjectRef> ID = + CAS.getReference(ObjectErr(CAS.parseID(Object))); + if (!ID) + ObjectErr(createStringError("unknown object '" + Object + "'")); + IDs.push_back(*ID); + } + + ExitOnError ExitOnErr("llvm-cas: make-node: "); + ObjectProxy Object = ExitOnErr(CAS.createProxy(IDs, Data->getBuffer())); + llvm::outs() << Object.getID() << "\n"; + return 0; +} + +static int import(ObjectStore &FromCAS, ObjectStore &ToCAS, + ArrayRef<std::string> Objects) { + ExitOnError ExitOnErr("llvm-cas: import: "); + + for (StringRef Object : Objects) { + CASID ID = ExitOnErr(FromCAS.parseID(Object)); + auto Ref = FromCAS.getReference(ID); + if (!Ref) + ExitOnErr(createStringError("input not found: " + ID.toString())); + + auto Imported = ExitOnErr(ToCAS.importObject(FromCAS, *Ref)); + llvm::outs() << ToCAS.getID(Imported).toString() << "\n"; + } + return 0; +} + +static int putCacheKey(ObjectStore &CAS, ActionCache &AC, + ArrayRef<std::string> Objects) { + ExitOnError ExitOnErr("llvm-cas: put-cache-key: "); + + if (Objects.size() % 2 != 0) + ExitOnErr(createStringError("expected pairs of inputs")); + while (!Objects.empty()) { + CASID Key = ExitOnErr(CAS.parseID(Objects[0])); + CASID Result = ExitOnErr(CAS.parseID(Objects[1])); + Objects = Objects.drop_front(2); + ExitOnErr(AC.put(Key, Result)); + } + return 0; +} + +static int getCacheResult(ObjectStore &CAS, ActionCache &AC, const CASID &ID) { + ExitOnError ExitOnErr("llvm-cas: get-cache-result: "); + + auto Result = ExitOnErr(AC.get(ID)); + if (!Result) { + outs() << "result not found\n"; + return 1; + } + outs() << *Result << "\n"; + return 0; +} + +int validateObject(ObjectStore &CAS, const CASID &ID) { + ExitOnError ExitOnErr("llvm-cas: validate-object: "); + ExitOnErr(CAS.validateObject(ID)); + outs() << ID << ": validated successfully\n"; + return 0; +} + +int validate(ObjectStore &CAS, ActionCache &AC, bool CheckHash) { + ExitOnError ExitOnErr("llvm-cas: validate: "); + ExitOnErr(CAS.validate(CheckHash)); + ExitOnErr(AC.validate()); + outs() << "validated successfully\n"; + return 0; +} + +int validateIfNeeded(StringRef Path, bool CheckHash, bool Force, + bool AllowRecovery, bool InProcess, const char *Argv0) { + ExitOnError ExitOnErr("llvm-cas: validate-if-needed: "); + std::string ExecStorage; + std::optional<StringRef> Exec; + if (!InProcess) { + ExecStorage = sys::fs::getMainExecutable(Argv0, (void *)validateIfNeeded); + Exec = ExecStorage; + } + ValidationResult Result = ExitOnErr(validateOnDiskUnifiedCASDatabasesIfNeeded( + Path, CheckHash, AllowRecovery, Force, Exec)); + switch (Result) { + case ValidationResult::Valid: + outs() << "validated successfully\n"; + break; + case ValidationResult::Recovered: + outs() << "recovered from invalid data\n"; + break; + case ValidationResult::Skipped: + outs() << "validation skipped\n"; + break; + } + return 0; +} + +static int prune(cas::ObjectStore &CAS) { + ExitOnError ExitOnErr("llvm-cas: prune: "); + ExitOnErr(CAS.pruneStorageData()); + return 0; +} diff --git a/llvm/tools/llvm-cfi-verify/lib/GraphBuilder.h b/llvm/tools/llvm-cfi-verify/lib/GraphBuilder.h index 55e628a..4ee3e7c 100644 --- a/llvm/tools/llvm-cfi-verify/lib/GraphBuilder.h +++ b/llvm/tools/llvm-cfi-verify/lib/GraphBuilder.h @@ -37,7 +37,6 @@ #include "llvm/Support/raw_ostream.h" #include <functional> -#include <set> using Instr = llvm::cfi_verify::FileAnalysis::Instr; diff --git a/llvm/tools/llvm-config/llvm-config.cpp b/llvm/tools/llvm-config/llvm-config.cpp index 020b1b5..5300c5c 100644 --- a/llvm/tools/llvm-config/llvm-config.cpp +++ b/llvm/tools/llvm-config/llvm-config.cpp @@ -24,6 +24,7 @@ #include "llvm/Config/config.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" @@ -232,6 +233,7 @@ Options:\n\ --link-static Link the component libraries statically.\n\ --obj-root Print the object root used to build LLVM.\n\ --prefix Print the installation prefix.\n\ + --quote-paths Quote and escape paths when needed.\n\ --shared-mode Print how the provided components can be collectively linked (`shared` or `static`).\n\ --system-libs System Libraries needed to link against LLVM components.\n\ --targets-built List of all targets currently built.\n\ @@ -324,7 +326,7 @@ int main(int argc, char **argv) { // information. std::string ActivePrefix, ActiveBinDir, ActiveIncludeDir, ActiveLibDir, ActiveCMakeDir; - std::string ActiveIncludeOption; + std::vector<std::string> ActiveIncludeOptions; if (IsInDevelopmentTree) { ActiveIncludeDir = std::string(LLVM_SRC_ROOT) + "/include"; ActivePrefix = CurrentExecPrefix; @@ -350,8 +352,8 @@ int main(int argc, char **argv) { } // We need to include files from both the source and object trees. - ActiveIncludeOption = - ("-I" + ActiveIncludeDir + " " + "-I" + ActiveObjRoot + "/include"); + ActiveIncludeOptions.push_back(ActiveIncludeDir); + ActiveIncludeOptions.push_back(ActiveObjRoot + "/include"); } else { ActivePrefix = CurrentExecPrefix; { @@ -370,7 +372,7 @@ int main(int argc, char **argv) { sys::path::make_absolute(ActivePrefix, Path); ActiveCMakeDir = std::string(Path); } - ActiveIncludeOption = "-I" + ActiveIncludeDir; + ActiveIncludeOptions.push_back(ActiveIncludeDir); } /// We only use `shared library` mode in cases where the static library form @@ -399,7 +401,9 @@ int main(int argc, char **argv) { llvm::replace(ActiveBinDir, '/', '\\'); llvm::replace(ActiveLibDir, '/', '\\'); llvm::replace(ActiveCMakeDir, '/', '\\'); - llvm::replace(ActiveIncludeOption, '/', '\\'); + llvm::replace(ActiveIncludeDir, '/', '\\'); + for (auto &Include : ActiveIncludeOptions) + llvm::replace(Include, '/', '\\'); } SharedDir = ActiveBinDir; StaticDir = ActiveLibDir; @@ -501,6 +505,32 @@ int main(int argc, char **argv) { }; raw_ostream &OS = outs(); + + // Check if we want quoting and escaping. + bool QuotePaths = std::any_of(&argv[0], &argv[argc], [](const char *Arg) { + return StringRef(Arg) == "--quote-paths"; + }); + + auto MaybePrintQuoted = [&](StringRef Str) { + if (QuotePaths) + sys::printArg(OS, Str, /*Quote=*/false); // only add quotes if necessary + else + OS << Str; + }; + + // Render include paths and associated flags + auto RenderFlags = [&](StringRef Flags) { + bool First = true; + for (auto &Include : ActiveIncludeOptions) { + if (!First) + OS << ' '; + std::string FlagsStr = "-I" + Include; + MaybePrintQuoted(FlagsStr); + First = false; + } + OS << ' ' << Flags << '\n'; + }; + for (int i = 1; i != argc; ++i) { StringRef Arg = argv[i]; @@ -509,24 +539,32 @@ int main(int argc, char **argv) { if (Arg == "--version") { OS << PACKAGE_VERSION << '\n'; } else if (Arg == "--prefix") { - OS << ActivePrefix << '\n'; + MaybePrintQuoted(ActivePrefix); + OS << '\n'; } else if (Arg == "--bindir") { - OS << ActiveBinDir << '\n'; + MaybePrintQuoted(ActiveBinDir); + OS << '\n'; } else if (Arg == "--includedir") { - OS << ActiveIncludeDir << '\n'; + MaybePrintQuoted(ActiveIncludeDir); + OS << '\n'; } else if (Arg == "--libdir") { - OS << ActiveLibDir << '\n'; + MaybePrintQuoted(ActiveLibDir); + OS << '\n'; } else if (Arg == "--cmakedir") { - OS << ActiveCMakeDir << '\n'; + MaybePrintQuoted(ActiveCMakeDir); + OS << '\n'; } else if (Arg == "--cppflags") { - OS << ActiveIncludeOption << ' ' << LLVM_CPPFLAGS << '\n'; + RenderFlags(LLVM_CPPFLAGS); } else if (Arg == "--cflags") { - OS << ActiveIncludeOption << ' ' << LLVM_CFLAGS << '\n'; + RenderFlags(LLVM_CFLAGS); } else if (Arg == "--cxxflags") { - OS << ActiveIncludeOption << ' ' << LLVM_CXXFLAGS << '\n'; + RenderFlags(LLVM_CXXFLAGS); } else if (Arg == "--ldflags") { - OS << ((HostTriple.isWindowsMSVCEnvironment()) ? "-LIBPATH:" : "-L") - << ActiveLibDir << ' ' << LLVM_LDFLAGS << '\n'; + std::string LDFlags = + HostTriple.isWindowsMSVCEnvironment() ? "-LIBPATH:" : "-L"; + LDFlags += ActiveLibDir; + MaybePrintQuoted(LDFlags); + OS << ' ' << LLVM_LDFLAGS << '\n'; } else if (Arg == "--system-libs") { PrintSystemLibs = true; } else if (Arg == "--libs") { @@ -580,7 +618,8 @@ int main(int argc, char **argv) { } else if (Arg == "--shared-mode") { PrintSharedMode = true; } else if (Arg == "--obj-root") { - OS << ActivePrefix << '\n'; + MaybePrintQuoted(ActivePrefix); + OS << '\n'; } else if (Arg == "--ignore-libllvm") { LinkDyLib = false; LinkMode = BuiltSharedLibs ? LinkModeShared : LinkModeAuto; @@ -590,6 +629,8 @@ int main(int argc, char **argv) { LinkMode = LinkModeStatic; } else if (Arg == "--help") { usage(false); + } else if (Arg == "--quote-paths") { + // Was already handled above this loop. } else { usage(); } @@ -682,26 +723,30 @@ int main(int argc, char **argv) { auto PrintForLib = [&](const StringRef &Lib) { const bool Shared = LinkMode == LinkModeShared; + std::string LibFileName; if (PrintLibNames) { - OS << GetComponentLibraryFileName(Lib, Shared); + LibFileName = GetComponentLibraryFileName(Lib, Shared); } else if (PrintLibFiles) { - OS << GetComponentLibraryPath(Lib, Shared); + LibFileName = GetComponentLibraryPath(Lib, Shared); } else if (PrintLibs) { // On Windows, output full path to library without parameters. // Elsewhere, if this is a typical library name, include it using -l. if (HostTriple.isWindowsMSVCEnvironment()) { - OS << GetComponentLibraryPath(Lib, Shared); + LibFileName = GetComponentLibraryPath(Lib, Shared); } else { + LibFileName = "-l"; StringRef LibName; if (GetComponentLibraryNameSlice(Lib, LibName)) { // Extract library name (remove prefix and suffix). - OS << "-l" << LibName; + LibFileName += LibName; } else { // Lib is already a library name without prefix and suffix. - OS << "-l" << Lib; + LibFileName += Lib; } } } + if (!LibFileName.empty()) + MaybePrintQuoted(LibFileName); }; if (LinkMode == LinkModeShared && LinkDyLib) diff --git a/llvm/tools/llvm-cov/CoverageExporter.h b/llvm/tools/llvm-cov/CoverageExporter.h index 751e55d..ba946a1 100644 --- a/llvm/tools/llvm-cov/CoverageExporter.h +++ b/llvm/tools/llvm-cov/CoverageExporter.h @@ -37,7 +37,7 @@ protected: : Coverage(CoverageMapping), Options(Options), OS(OS) {} public: - virtual ~CoverageExporter(){}; + virtual ~CoverageExporter() = default; /// Render the CoverageMapping object. virtual void renderRoot(const CoverageFilters &IgnoreFilters) = 0; diff --git a/llvm/tools/llvm-cov/CoverageFilters.h b/llvm/tools/llvm-cov/CoverageFilters.h index 5345b0c..3cee23a 100644 --- a/llvm/tools/llvm-cov/CoverageFilters.h +++ b/llvm/tools/llvm-cov/CoverageFilters.h @@ -28,7 +28,7 @@ struct FunctionRecord; /// Matches specific functions that pass the requirement of this filter. class CoverageFilter { public: - virtual ~CoverageFilter() {} + virtual ~CoverageFilter() = default; /// Return true if the function passes the requirements of this filter. virtual bool matches(const coverage::CoverageMapping &CM, diff --git a/llvm/tools/llvm-cov/SourceCoverageView.h b/llvm/tools/llvm-cov/SourceCoverageView.h index 43fb890a..bde187e 100644 --- a/llvm/tools/llvm-cov/SourceCoverageView.h +++ b/llvm/tools/llvm-cov/SourceCoverageView.h @@ -122,7 +122,7 @@ public: static std::unique_ptr<CoveragePrinter> create(const CoverageViewOptions &Opts); - virtual ~CoveragePrinter() {} + virtual ~CoveragePrinter() = default; /// @name File Creation Interface /// @{ @@ -288,7 +288,7 @@ public: create(StringRef SourceName, const MemoryBuffer &File, const CoverageViewOptions &Options, CoverageData &&CoverageInfo); - virtual ~SourceCoverageView() {} + virtual ~SourceCoverageView() = default; /// Return the source name formatted for the host OS. std::string getSourceName() const; diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp index c94d385..bdef099 100644 --- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp +++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp @@ -955,8 +955,8 @@ void SourceCoverageViewHTML::renderLine(raw_ostream &OS, LineRef L, // 2. Escape all of the snippets. - for (unsigned I = 0, E = Snippets.size(); I < E; ++I) - Snippets[I] = escape(Snippets[I], getOptions()); + for (std::string &Snippet : Snippets) + Snippet = escape(Snippet, getOptions()); // 3. Use \p WrappedSegment to set the highlight for snippet 0. Use segment // 1 to set the highlight for snippet 2, segment 2 to set the highlight for diff --git a/llvm/tools/llvm-diff/lib/DiffConsumer.h b/llvm/tools/llvm-diff/lib/DiffConsumer.h index 08c3afc..d4f339b 100644 --- a/llvm/tools/llvm-diff/lib/DiffConsumer.h +++ b/llvm/tools/llvm-diff/lib/DiffConsumer.h @@ -49,7 +49,7 @@ class StringRef; virtual void logd(const DiffLogBuilder &Log) = 0; protected: - virtual ~Consumer() {} + virtual ~Consumer() = default; }; class DiffConsumer : public Consumer { diff --git a/llvm/tools/llvm-diff/lib/DifferenceEngine.h b/llvm/tools/llvm-diff/lib/DifferenceEngine.h index 436a355..01fd0d95 100644 --- a/llvm/tools/llvm-diff/lib/DifferenceEngine.h +++ b/llvm/tools/llvm-diff/lib/DifferenceEngine.h @@ -17,7 +17,6 @@ #include "DiffConsumer.h" #include "DiffLog.h" #include "llvm/ADT/StringRef.h" -#include <utility> namespace llvm { class Function; @@ -54,7 +53,7 @@ namespace llvm { virtual bool operator()(const Value *L, const Value *R) = 0; protected: - virtual ~Oracle() {} + virtual ~Oracle() = default; }; DifferenceEngine(Consumer &consumer) diff --git a/llvm/tools/llvm-diff/llvm-diff.cpp b/llvm/tools/llvm-diff/llvm-diff.cpp index 2126b91..45b8ed9 100644 --- a/llvm/tools/llvm-diff/llvm-diff.cpp +++ b/llvm/tools/llvm-diff/llvm-diff.cpp @@ -20,11 +20,9 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/WithColor.h" +#include "llvm/Support/raw_ostream.h" #include <string> -#include <utility> - using namespace llvm; diff --git a/llvm/tools/llvm-dis/llvm-dis.cpp b/llvm/tools/llvm-dis/llvm-dis.cpp index 35c54096..90ae3ef 100644 --- a/llvm/tools/llvm-dis/llvm-dis.cpp +++ b/llvm/tools/llvm-dis/llvm-dis.cpp @@ -101,13 +101,26 @@ static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) { } } class CommentWriter : public AssemblyAnnotationWriter { +private: + bool canSafelyAccessUses(const Value &V) { + // Can't safely access uses, if module not materialized. + const GlobalValue *GV = dyn_cast<GlobalValue>(&V); + return !GV || (GV->getParent() && GV->getParent()->isMaterialized()); + } + public: void emitFunctionAnnot(const Function *F, formatted_raw_ostream &OS) override { + if (!canSafelyAccessUses(*F)) + return; + OS << "; [#uses=" << F->getNumUses() << ']'; // Output # uses OS << '\n'; } void printInfoComment(const Value &V, formatted_raw_ostream &OS) override { + if (!canSafelyAccessUses(V)) + return; + bool Padded = false; if (!V.getType()->isVoidTy()) { OS.PadToColumn(50); diff --git a/llvm/tools/llvm-dwarfdump/CMakeLists.txt b/llvm/tools/llvm-dwarfdump/CMakeLists.txt index aeb1b8f..7a0adf3 100644 --- a/llvm/tools/llvm-dwarfdump/CMakeLists.txt +++ b/llvm/tools/llvm-dwarfdump/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + BinaryFormat DebugInfoDWARF DebugInfoDWARFLowLevel AllTargetsDescs diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index 11eb58e..6f120f9 100644 --- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -14,6 +14,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVectorExtras.h" #include "llvm/ADT/StringSet.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" @@ -242,6 +243,15 @@ static opt<bool> cat(DwarfDumpCategory)); static alias ShowParentsAlias("p", desc("Alias for --show-parents."), aliasopt(ShowParents), cl::NotHidden); + +static list<std::string> FilterChildTag( + "filter-child-tag", + desc("When --show-children is specified, show only DIEs with the " + "specified DWARF tags."), + value_desc("list of DWARF tags"), cat(DwarfDumpCategory)); +static alias FilterChildTagAlias("t", desc("Alias for --filter-child-tag."), + aliasopt(FilterChildTag), cl::NotHidden); + static opt<bool> ShowForm("show-form", desc("Show DWARF form types after the DWARF attribute types."), @@ -330,6 +340,13 @@ static cl::extrahelp /// @} //===----------------------------------------------------------------------===// +static llvm::SmallVector<unsigned> +makeTagVector(const list<std::string> &TagStrings) { + return llvm::map_to_vector(TagStrings, [](const std::string &Tag) { + return llvm::dwarf::getTag(Tag); + }); +} + static void error(Error Err) { if (!Err) return; @@ -356,6 +373,7 @@ static DIDumpOptions getDumpOpts(DWARFContext &C) { DumpOpts.ShowAddresses = !Diff; DumpOpts.ShowChildren = ShowChildren; DumpOpts.ShowParents = ShowParents; + DumpOpts.FilterChildTag = makeTagVector(FilterChildTag); DumpOpts.ShowForm = ShowForm; DumpOpts.SummarizeTypes = SummarizeTypes; DumpOpts.Verbose = Verbose; diff --git a/llvm/tools/llvm-dwp/Opts.td b/llvm/tools/llvm-dwp/Opts.td index 46593bc..d4474ac 100644 --- a/llvm/tools/llvm-dwp/Opts.td +++ b/llvm/tools/llvm-dwp/Opts.td @@ -16,3 +16,18 @@ def continueOnCuIndexOverflow_EQ : Joined<["-", "--"], "continue-on-cu-index-ove "\t\ttruncated but valid DWP file, discarding any DWO files that would not fit within \n" "\t\tthe 32 bit/4GB limits of the format.">, Values<"continue,soft-stop">; + +def dwarf64StringOffsets : Flag<["-", "--"], "dwarf64-str-offsets-promotion">; +def dwarf64StringOffsets_EQ + : Joined<["-", "--"], "dwarf64-str-offsets-promotion=">, + HelpText<"default = enabled, This allows .debug_str tables to exceed the " + "4GB limit\n" + "and have any DWARF32 .debug_str_offsets tables converted to " + "DWARF64 only for tables\n" + "that require 64 bit string offsets. = disabled, This setting " + "doesn't convert DWARF32\n" + ".debug_str_offsets tables in .dwo files to DWARF64 in the .dwp " + "file. = always, This\n" + "forces all .debug_str_offsets tables to be emitted as DWARF64. " + "This is used for testing.">, + Values<"disabled,enabled,always">; diff --git a/llvm/tools/llvm-dwp/llvm-dwp.cpp b/llvm/tools/llvm-dwp/llvm-dwp.cpp index 31bad2d..2892450 100644 --- a/llvm/tools/llvm-dwp/llvm-dwp.cpp +++ b/llvm/tools/llvm-dwp/llvm-dwp.cpp @@ -125,6 +125,9 @@ int llvm_dwp_main(int argc, char **argv, const llvm::ToolContext &) { llvm::BumpPtrAllocator A; llvm::StringSaver Saver{A}; OnCuIndexOverflow OverflowOptValue = OnCuIndexOverflow::HardStop; + Dwarf64StrOffsetsPromotion Dwarf64StrOffsetsValue = + Dwarf64StrOffsetsPromotion::Disabled; + opt::InputArgList Args = Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) { llvm::errs() << Msg << '\n'; @@ -161,6 +164,27 @@ int llvm_dwp_main(int argc, char **argv, const llvm::ToolContext &) { } } + if (Arg *Arg = Args.getLastArg(OPT_dwarf64StringOffsets, + OPT_dwarf64StringOffsets_EQ)) { + if (Arg->getOption().matches(OPT_dwarf64StringOffsets)) { + Dwarf64StrOffsetsValue = Dwarf64StrOffsetsPromotion::Enabled; + } else { + std::string OptValue = Arg->getValue(); + if (OptValue == "disabled") { + Dwarf64StrOffsetsValue = Dwarf64StrOffsetsPromotion::Disabled; + } else if (OptValue == "enabled") { + Dwarf64StrOffsetsValue = Dwarf64StrOffsetsPromotion::Enabled; + } else if (OptValue == "always") { + Dwarf64StrOffsetsValue = Dwarf64StrOffsetsPromotion::Always; + } else { + llvm::errs() + << "invalid value for --dwarf64-str-offsets-promotion. Valid " + "values are one of: \"enabled\", \"disabled\" or \"always\".\n"; + exit(1); + } + } + } + for (const llvm::opt::Arg *A : Args.filtered(OPT_execFileNames)) ExecFilenames.emplace_back(A->getValue()); @@ -274,7 +298,8 @@ int llvm_dwp_main(int argc, char **argv, const llvm::ToolContext &) { if (!MS) return error("no object streamer for target " + TripleName, Context); - if (auto Err = write(*MS, DWOFilenames, OverflowOptValue)) { + if (auto Err = + write(*MS, DWOFilenames, OverflowOptValue, Dwarf64StrOffsetsValue)) { logAllUnhandledErrors(std::move(Err), WithColor::error()); return 1; } diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp index 2c13dd5..0e73ada 100644 --- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp @@ -112,7 +112,7 @@ namespace { // Use X19 as the loop counter register since it's a callee-saved register // that's available for temporary use. -constexpr const MCPhysReg kDefaultLoopCounterReg = AArch64::X19; +constexpr MCPhysReg kDefaultLoopCounterReg = AArch64::X19; class ExegesisAArch64Target : public ExegesisTarget { public: diff --git a/llvm/tools/llvm-exegesis/lib/Analysis.cpp b/llvm/tools/llvm-exegesis/lib/Analysis.cpp index fb84328..f3bf9690 100644 --- a/llvm/tools/llvm-exegesis/lib/Analysis.cpp +++ b/llvm/tools/llvm-exegesis/lib/Analysis.cpp @@ -446,7 +446,7 @@ void Analysis::printClusterRawHtml(const BenchmarkClustering::ClusterId &Id, } // namespace exegesis -static constexpr const char kHtmlHead[] = R"( +static constexpr char kHtmlHead[] = R"( <head> <title>llvm-exegesis Analysis Results</title> <style> diff --git a/llvm/tools/llvm-exegesis/lib/Assembler.cpp b/llvm/tools/llvm-exegesis/lib/Assembler.cpp index fd7924d..163f141 100644 --- a/llvm/tools/llvm-exegesis/lib/Assembler.cpp +++ b/llvm/tools/llvm-exegesis/lib/Assembler.cpp @@ -44,8 +44,8 @@ namespace llvm { namespace exegesis { -static constexpr const char ModuleID[] = "ExegesisInfoTest"; -static constexpr const char FunctionID[] = "foo"; +static constexpr char ModuleID[] = "ExegesisInfoTest"; +static constexpr char FunctionID[] = "foo"; static const Align kFunctionAlignment(4096); // Fills the given basic block with register setup code, and returns true if diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp index 1823a53..c6164b6 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp @@ -21,9 +21,9 @@ #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" -static constexpr const char kIntegerPrefix[] = "i_0x"; -static constexpr const char kDoublePrefix[] = "f_"; -static constexpr const char kInvalidOperand[] = "INVALID"; +static constexpr char kIntegerPrefix[] = "i_0x"; +static constexpr char kDoublePrefix[] = "f_"; +static constexpr char kInvalidOperand[] = "INVALID"; namespace llvm { @@ -202,7 +202,7 @@ struct CustomMappingTraits<std::map<exegesis::ValidationEvent, int64_t>> { Io.setError("Key is not a valid validation event"); return; } - Io.mapRequired(KeyStr.str().c_str(), VI[*Key]); + Io.mapRequired(KeyStr, VI[*Key]); } static void output(IO &Io, std::map<exegesis::ValidationEvent, int64_t> &VI) { @@ -245,8 +245,8 @@ template <> struct SequenceElementTraits<exegesis::RegisterValue> { }; template <> struct ScalarTraits<exegesis::RegisterValue> { - static constexpr const unsigned kRadix = 16; - static constexpr const bool kSigned = false; + static constexpr unsigned kRadix = 16; + static constexpr bool kSigned = false; static void output(const exegesis::RegisterValue &RV, void *Ctx, raw_ostream &Out) { diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp index 1fd0a15..a86be13 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -27,7 +27,6 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" -#include "llvm/Support/SystemZ/zOSSupport.h" #include <cmath> #include <memory> #include <string> @@ -155,7 +154,7 @@ private: #ifdef LLVM_ON_UNIX // See "Exit Status for Commands": // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html - constexpr const int kSigOffset = 128; + constexpr int kSigOffset = 128; return make_error<SnippetSignal>(CRC.RetCode - kSigOffset); #else // The exit code of the process on windows is not meaningful as a @@ -877,7 +876,7 @@ Error BenchmarkRunner::getValidationCountersToRun( return Error::success(); } -BenchmarkRunner::FunctionExecutor::~FunctionExecutor() {} +BenchmarkRunner::FunctionExecutor::~FunctionExecutor() = default; } // namespace exegesis } // namespace llvm diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h index e688b81..16d3c9c 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h @@ -73,8 +73,8 @@ public: // Scratch space to run instructions that touch memory. struct ScratchSpace { - static constexpr const size_t kAlignment = 1024; - static constexpr const size_t kSize = 1 << 20; // 1MB. + static constexpr size_t kAlignment = 1024; + static constexpr size_t kSize = 1 << 20; // 1MB. ScratchSpace() : UnalignedPtr(std::make_unique<char[]>(kSize + kAlignment)), AlignedPtr( diff --git a/llvm/tools/llvm-exegesis/lib/Clustering.h b/llvm/tools/llvm-exegesis/lib/Clustering.h index 9d6c110..2b0f5b4 100644 --- a/llvm/tools/llvm-exegesis/lib/Clustering.h +++ b/llvm/tools/llvm-exegesis/lib/Clustering.h @@ -67,11 +67,11 @@ public: ClusterId(size_t Id, bool IsUnstable = false) : Id_(Id), IsUnstable_(IsUnstable) {} - static constexpr const size_t kMaxValid = + static constexpr size_t kMaxValid = (std::numeric_limits<size_t>::max() >> 1) - 4; - static constexpr const size_t kNoise = kMaxValid + 1; - static constexpr const size_t kError = kMaxValid + 2; - static constexpr const size_t kUndef = kMaxValid + 3; + static constexpr size_t kNoise = kMaxValid + 1; + static constexpr size_t kError = kMaxValid + 2; + static constexpr size_t kUndef = kMaxValid + 3; size_t Id_ : (std::numeric_limits<size_t>::digits - 1); size_t IsUnstable_ : 1; diff --git a/llvm/tools/llvm-exegesis/lib/Error.cpp b/llvm/tools/llvm-exegesis/lib/Error.cpp index 2908df2..9024ba5 100644 --- a/llvm/tools/llvm-exegesis/lib/Error.cpp +++ b/llvm/tools/llvm-exegesis/lib/Error.cpp @@ -10,7 +10,6 @@ #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX #ifdef LLVM_ON_UNIX -#include "llvm/Support/SystemZ/zOSSupport.h" #include <string.h> #endif // LLVM_ON_UNIX diff --git a/llvm/tools/llvm-exegesis/lib/Error.h b/llvm/tools/llvm-exegesis/lib/Error.h index 9b71fe8..c899023 100644 --- a/llvm/tools/llvm-exegesis/lib/Error.h +++ b/llvm/tools/llvm-exegesis/lib/Error.h @@ -81,7 +81,7 @@ private: struct PerfCounterNotFullyEnabled : public ErrorInfo<PerfCounterNotFullyEnabled> { static char ID; - PerfCounterNotFullyEnabled() {} + PerfCounterNotFullyEnabled() = default; void log(raw_ostream &OS) const override; diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp index 66c770d..b544ae7 100644 --- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp +++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp @@ -8,7 +8,6 @@ #include "MCInstrDescView.h" -#include <iterator> #include <tuple> #include "llvm/ADT/STLExtras.h" @@ -120,7 +119,7 @@ Instruction::create(const MCInstrInfo &InstrInfo, Operand.IsDef = (OpIndex < Description->getNumDefs()); Operand.IsEarlyClobber = (Description->getOperandConstraint(OpIndex, MCOI::EARLY_CLOBBER) != -1); - // TODO(gchatelet): Handle isLookupPtrRegClass. + // TODO(gchatelet): Handle LookupRegClassByHwMode. if (OpInfo.RegClass >= 0) Operand.Tracker = &RATC.getRegisterClass(OpInfo.RegClass); int TiedToIndex = Description->getOperandConstraint(OpIndex, MCOI::TIED_TO); diff --git a/llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp index 79a585e..aa40913 100644 --- a/llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp @@ -350,7 +350,5 @@ ParallelSnippetGenerator::generateCodeTemplates( return Result; } -constexpr const size_t ParallelSnippetGenerator::kMinNumDifferentAddresses; - } // namespace exegesis } // namespace llvm diff --git a/llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.h b/llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.h index 8a6b856..d3c85c0 100644 --- a/llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.h +++ b/llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.h @@ -28,7 +28,7 @@ public: generateCodeTemplates(InstructionTemplate Variant, const BitVector &ForbiddenRegisters) const override; - static constexpr const size_t kMinNumDifferentAddresses = 6; + static constexpr size_t kMinNumDifferentAddresses = 6; private: // Instantiates memory operands within a snippet. diff --git a/llvm/tools/llvm-exegesis/lib/PerfHelper.h b/llvm/tools/llvm-exegesis/lib/PerfHelper.h index 4a825b2..744e3c2 100644 --- a/llvm/tools/llvm-exegesis/lib/PerfHelper.h +++ b/llvm/tools/llvm-exegesis/lib/PerfHelper.h @@ -21,7 +21,6 @@ #include <cstdint> #include <functional> -#include <memory> #ifdef _MSC_VER typedef int pid_t; diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp index ea830bd..6eeb07f 100644 --- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -819,6 +819,15 @@ void ExegesisRISCVTarget::fillMemoryOperands(InstructionTemplate &IT, assert(MemOp.isReg() && "Memory operand expected to be register"); + unsigned Opcode = I.getOpcode(); + if (Opcode == RISCV::C_LDSP || Opcode == RISCV::C_LWSP || + Opcode == RISCV::C_SDSP || Opcode == RISCV::C_SWSP) { + IT.getValueFor(I.Operands[0]) = MCOperand::createReg(RISCV::X2); + // Force base register to SP (X2) + IT.getValueFor(MemOp) = MCOperand::createReg(RISCV::X2); + return; + } + IT.getValueFor(MemOp) = MCOperand::createReg(Reg); } @@ -855,10 +864,17 @@ Error ExegesisRISCVTarget::randomizeTargetMCOperand( // 5-bit unsigned immediate value. AssignedValue = MCOperand::createImm(randomIndex(31)); break; + case RISCVOp::OPERAND_SIMM12_LO: + case RISCVOp::OPERAND_UIMM20_LUI: + case RISCVOp::OPERAND_UIMM20_AUIPC: + case RISCVOp::OPERAND_BARE_SIMM32: + AssignedValue = MCOperand::createImm(0); + break; default: if (OperandType >= RISCVOp::OPERAND_FIRST_RISCV_IMM && OperandType <= RISCVOp::OPERAND_LAST_RISCV_IMM) AssignedValue = MCOperand::createImm(0); + break; } return Error::success(); } diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp index 707e6ee..71b2d71 100644 --- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp @@ -142,7 +142,12 @@ static void appendCodeTemplates(const LLVMState &State, return; ET.fillMemoryOperands(Variant, ScratchMemoryRegister, 0); - Variant.getValueFor(DefOp) = MCOperand::createReg(ScratchMemoryRegister); + + // Only force the def register to ScratchMemoryRegister if the target + // hasn't assigned a value yet. + MCOperand &DefVal = Variant.getValueFor(DefOp); + if (!DefVal.isValid()) + DefVal = MCOperand::createReg(ScratchMemoryRegister); CodeTemplate CT; CT.Execution = ExecutionModeBit; diff --git a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp index 7023f1b..86d4e19 100644 --- a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp @@ -21,9 +21,17 @@ #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Program.h" +#define DEBUG_TYPE "snippet-generator" + namespace llvm { namespace exegesis { +static cl::opt<unsigned> + RandomGeneratorSeed("random-generator-seed", + cl::desc("The seed value to use for the random number " + "generator when generating snippets."), + cl::init(0)); + std::vector<CodeTemplate> getSingleton(CodeTemplate &&CT) { std::vector<CodeTemplate> Result; Result.push_back(std::move(CT)); @@ -188,7 +196,11 @@ generateUnconstrainedCodeTemplates(const InstructionTemplate &Variant, std::mt19937 &randomGenerator() { static std::random_device RandomDevice; - static std::mt19937 RandomGenerator(RandomDevice()); + unsigned RandomSeed = RandomGeneratorSeed.getNumOccurrences() + ? RandomGeneratorSeed + : RandomDevice(); + LLVM_DEBUG(dbgs() << "Using random seed " << RandomSeed << ".\n"); + static std::mt19937 RandomGenerator(RandomSeed); return RandomGenerator; } diff --git a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h index 770e4e8..1ef0beb 100644 --- a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h +++ b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h @@ -25,7 +25,6 @@ #include "llvm/MC/MCInst.h" #include "llvm/Support/Error.h" #include <cstdlib> -#include <memory> #include <vector> namespace llvm { diff --git a/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp b/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp index 80f5ce4..37dcc7c 100644 --- a/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp +++ b/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp @@ -131,7 +131,7 @@ private: } // namespace -SnippetRepetitor::~SnippetRepetitor() {} +SnippetRepetitor::~SnippetRepetitor() = default; std::unique_ptr<const SnippetRepetitor> SnippetRepetitor::Create(Benchmark::RepetitionModeE Mode, diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h index 572d1085..52ee980 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h @@ -32,8 +32,8 @@ namespace exegesis { class SubprocessMemory { public: - static constexpr const size_t AuxiliaryMemoryOffset = 1; - static constexpr const size_t AuxiliaryMemorySize = 4096; + static constexpr size_t AuxiliaryMemoryOffset = 1; + static constexpr size_t AuxiliaryMemorySize = 4096; // Gets the thread ID for the calling thread. static long getCurrentTID(); diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp index fc5f82f..2ad6c5a 100644 --- a/llvm/tools/llvm-exegesis/lib/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/Target.cpp @@ -23,7 +23,7 @@ cl::OptionCategory Options("llvm-exegesis options"); cl::OptionCategory BenchmarkOptions("llvm-exegesis benchmark options"); cl::OptionCategory AnalysisOptions("llvm-exegesis analysis options"); -ExegesisTarget::~ExegesisTarget() {} // anchor. +ExegesisTarget::~ExegesisTarget() = default; // anchor. static ExegesisTarget *FirstTarget = nullptr; @@ -215,7 +215,7 @@ const PfmCountersInfo &ExegesisTarget::getDummyPfmCounters() const { return PfmCountersInfo::Dummy; } -ExegesisTarget::SavedState::~SavedState() {} // anchor. +ExegesisTarget::SavedState::~SavedState() = default; // anchor. namespace { diff --git a/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h b/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h index ef47b7f..74a18da 100644 --- a/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h +++ b/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h @@ -30,7 +30,7 @@ public: ExecutionMode, ValCounters) {} ~UopsBenchmarkRunner() override; - static constexpr const size_t kMinNumDifferentAddresses = 6; + static constexpr size_t kMinNumDifferentAddresses = 6; private: Expected<std::vector<BenchmarkMeasure>> diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp index b4437f7..3f2b911 100644 --- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp @@ -28,7 +28,6 @@ #include "llvm/TargetParser/Host.h" #include <memory> -#include <string> #include <vector> #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && \ !defined(_M_ARM64EC) @@ -278,9 +277,9 @@ static Expected<std::vector<CodeTemplate>> generateLEATemplatesCommon( assert(X86II::getMemoryOperandNo(Instr.Description.TSFlags) == 1 && "invalid LEA"); - constexpr const int kDestOp = 0; - constexpr const int kBaseOp = 1; - constexpr const int kIndexOp = 3; + constexpr int kDestOp = 0; + constexpr int kBaseOp = 1; + constexpr int kIndexOp = 3; auto PossibleDestRegs = Instr.Operands[kDestOp].getRegisterAliasing().sourceBits(); remove(PossibleDestRegs, ForbiddenRegisters); @@ -548,7 +547,7 @@ private: void initStack(unsigned Bytes); - static constexpr const unsigned kF80Bytes = 10; // 80 bits. + static constexpr unsigned kF80Bytes = 10; // 80 bits. APInt Constant_; std::vector<MCInst> Instructions; @@ -864,13 +863,13 @@ const MCPhysReg ExegesisX86Target::kUnavailableRegistersSSE[12] = { // We're using one of R8-R15 because these registers are never hardcoded in // instructions (e.g. MOVS writes to EDI, ESI, EDX), so they have less // conflicts. -constexpr const MCPhysReg kDefaultLoopCounterReg = X86::R8; +constexpr MCPhysReg kDefaultLoopCounterReg = X86::R8; } // namespace void ExegesisX86Target::addTargetSpecificPasses(PassManagerBase &PM) const { // Lowers FP pseudo-instructions, e.g. ABS_Fp32 -> ABS_F. - PM.add(createX86FloatingPointStackifierPass()); + PM.add(createX86FPStackifierLegacyPass()); } MCRegister ExegesisX86Target::getScratchMemoryRegister(const Triple &TT) const { @@ -1110,9 +1109,9 @@ std::vector<MCInst> ExegesisX86Target::setRegTo(const MCSubtargetInfo &STI, #ifdef __linux__ #ifdef __arm__ -static constexpr const uintptr_t VAddressSpaceCeiling = 0xC0000000; +static constexpr uintptr_t VAddressSpaceCeiling = 0xC0000000; #else -static constexpr const uintptr_t VAddressSpaceCeiling = 0x0000800000000000; +static constexpr uintptr_t VAddressSpaceCeiling = 0x0000800000000000; #endif void generateRoundToNearestPage(unsigned int Register, diff --git a/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp b/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp index 05b6562..9dc6c76 100644 --- a/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp +++ b/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp @@ -27,7 +27,6 @@ #include <cstdint> #include <limits> #include <memory> -#include <vector> #include <poll.h> #include <sys/mman.h> diff --git a/llvm/tools/llvm-gpu-loader/amdhsa.cpp b/llvm/tools/llvm-gpu-loader/amdhsa.cpp index 5715058..fa9ee18 100644 --- a/llvm/tools/llvm-gpu-loader/amdhsa.cpp +++ b/llvm/tools/llvm-gpu-loader/amdhsa.cpp @@ -26,7 +26,6 @@ #include <cstdlib> #include <cstring> #include <thread> -#include <tuple> #include <utility> // The implicit arguments of COV5 AMDGPU kernels. diff --git a/llvm/tools/llvm-ifs/ErrorCollector.cpp b/llvm/tools/llvm-ifs/ErrorCollector.cpp index 04daa84..7417060 100644 --- a/llvm/tools/llvm-ifs/ErrorCollector.cpp +++ b/llvm/tools/llvm-ifs/ErrorCollector.cpp @@ -11,7 +11,6 @@ #include "llvm/Support/Error.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" -#include <vector> using namespace llvm; using namespace llvm::ifs; diff --git a/llvm/tools/llvm-ifs/llvm-ifs.cpp b/llvm/tools/llvm-ifs/llvm-ifs.cpp index e12016c..1244bfb 100644 --- a/llvm/tools/llvm-ifs/llvm-ifs.cpp +++ b/llvm/tools/llvm-ifs/llvm-ifs.cpp @@ -34,7 +34,6 @@ #include "llvm/TextAPI/TextAPIReader.h" #include "llvm/TextAPI/TextAPIWriter.h" #include <optional> -#include <set> #include <string> #include <vector> diff --git a/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp b/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp index 7402782..7b8d3f0 100644 --- a/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp +++ b/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp @@ -395,9 +395,7 @@ public: /// FIXME: Use --target option to get target info directly, avoiding the need /// to parse machine functions for pre-training operations. bool initializeVocabularyForLayout(const Module &M) { - for (const Function &F : M) { - if (F.isDeclaration()) - continue; + for (const Function &F : M.getFunctionDefs()) { MachineFunction *MF = MMI.getMachineFunction(F); if (!MF) @@ -431,9 +429,7 @@ public: std::string Relationships; raw_string_ostream RelOS(Relationships); - for (const Function &F : M) { - if (F.isDeclaration()) - continue; + for (const Function &F : M.getFunctionDefs()) { MachineFunction *MF = MMI.getMachineFunction(F); if (!MF) { @@ -532,9 +528,7 @@ public: return; } - for (const Function &F : M) { - if (F.isDeclaration()) - continue; + for (const Function &F : M.getFunctionDefs()) { MachineFunction *MF = MMI.getMachineFunction(F); if (!MF) { diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp index 8d33ae1..2cffca2 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp @@ -44,7 +44,6 @@ ExitOnError ExitOnErr; LLVM_ATTRIBUTE_USED void linkComponents() { errs() << (void *)&llvm_orc_registerEHFrameSectionAllocAction << (void *)&llvm_orc_deregisterEHFrameSectionAllocAction - << (void *)&llvm_orc_registerJITLoaderGDBWrapper << (void *)&llvm_orc_registerJITLoaderGDBAllocAction; } diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp index 79216e8..b8de817 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp @@ -17,17 +17,15 @@ #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX, LLVM_ENABLE_THREADS #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h" #include "llvm/ExecutionEngine/Orc/COFFPlatform.h" -#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h" #include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h" #include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupportPlugin.h" +#include "llvm/ExecutionEngine/Orc/Debugging/ELFDebugObjectPlugin.h" #include "llvm/ExecutionEngine/Orc/Debugging/PerfSupportPlugin.h" #include "llvm/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.h" #include "llvm/ExecutionEngine/Orc/EHFrameRegistrationPlugin.h" #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h" -#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h" #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" -#include "llvm/ExecutionEngine/Orc/GetDylibInterface.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h" #include "llvm/ExecutionEngine/Orc/JITLinkReentryTrampolines.h" @@ -348,7 +346,6 @@ static LLVM_ATTRIBUTE_USED void linkComponents() { errs() << "Linking in runtime functions\n" << (void *)&llvm_orc_registerEHFrameSectionAllocAction << '\n' << (void *)&llvm_orc_deregisterEHFrameSectionAllocAction << '\n' - << (void *)&llvm_orc_registerJITLoaderGDBWrapper << '\n' << (void *)&llvm_orc_registerJITLoaderGDBAllocAction << '\n' << (void *)&llvm_orc_registerJITLoaderPerfStart << '\n' << (void *)&llvm_orc_registerJITLoaderPerfEnd << '\n' @@ -776,6 +773,7 @@ createSharedMemoryManager(SimpleRemoteEPC &SREPC) { SlabSize, SREPC, SAs); } +#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS static void setupEPCRemoteMemoryManager(SimpleRemoteEPC::Setup &S) { switch (UseMemMgr) { case MemMgr::Default: @@ -789,6 +787,7 @@ static void setupEPCRemoteMemoryManager(SimpleRemoteEPC::Setup &S) { break; } } +#endif static Expected<MaterializationUnit::Interface> getTestObjectFileInterface(Session &S, MemoryBufferRef O) { @@ -1295,9 +1294,16 @@ Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err) } else if (TT.isOSBinFormatELF()) { if (!NoExec) ObjLayer.addPlugin(ExitOnErr(EHFrameRegistrationPlugin::Create(ES))); - if (DebuggerSupport) - ObjLayer.addPlugin(std::make_unique<DebugObjectManagerPlugin>( - ES, ExitOnErr(createJITLoaderGDBRegistrar(this->ES)), true, true)); + if (DebuggerSupport) { + Error TargetSymErr = Error::success(); + auto Plugin = + std::make_unique<ELFDebugObjectPlugin>(ES, true, true, TargetSymErr); + if (!TargetSymErr) + ObjLayer.addPlugin(std::move(Plugin)); + else + logAllUnhandledErrors(std::move(TargetSymErr), errs(), + "Debugger support not available: "); + } } if (auto MainJDOrErr = ES.createJITDylib("main")) diff --git a/llvm/tools/llvm-libtool-darwin/DependencyInfo.h b/llvm/tools/llvm-libtool-darwin/DependencyInfo.h index 784ec3f..80bad8f 100644 --- a/llvm/tools/llvm-libtool-darwin/DependencyInfo.h +++ b/llvm/tools/llvm-libtool-darwin/DependencyInfo.h @@ -18,7 +18,7 @@ public: explicit DependencyInfo(std::string DependencyInfoPath) : DependencyInfoPath(DependencyInfoPath) {} - virtual ~DependencyInfo(){}; + virtual ~DependencyInfo() = default; virtual void addMissingInput(llvm::StringRef Path) { NotFounds.insert(Path.str()); diff --git a/llvm/tools/llvm-lto/llvm-lto.cpp b/llvm/tools/llvm-lto/llvm-lto.cpp index 09f7142..30f2e53 100644 --- a/llvm/tools/llvm-lto/llvm-lto.cpp +++ b/llvm/tools/llvm-lto/llvm-lto.cpp @@ -45,14 +45,13 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/WithColor.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetOptions.h" #include <algorithm> #include <cassert> #include <cstdint> #include <cstdlib> -#include <map> #include <memory> #include <string> #include <system_error> diff --git a/llvm/tools/llvm-mc/Disassembler.h b/llvm/tools/llvm-mc/Disassembler.h index dd8525d..76cee9e 100644 --- a/llvm/tools/llvm-mc/Disassembler.h +++ b/llvm/tools/llvm-mc/Disassembler.h @@ -14,8 +14,6 @@ #ifndef LLVM_TOOLS_LLVM_MC_DISASSEMBLER_H #define LLVM_TOOLS_LLVM_MC_DISASSEMBLER_H -#include <string> - namespace llvm { class MemoryBuffer; diff --git a/llvm/tools/llvm-mca/CodeRegionGenerator.cpp b/llvm/tools/llvm-mca/CodeRegionGenerator.cpp index f7f929e..1469071 100644 --- a/llvm/tools/llvm-mca/CodeRegionGenerator.cpp +++ b/llvm/tools/llvm-mca/CodeRegionGenerator.cpp @@ -26,7 +26,7 @@ namespace llvm { namespace mca { // This virtual dtor serves as the anchor for the CodeRegionGenerator class. -CodeRegionGenerator::~CodeRegionGenerator() {} +CodeRegionGenerator::~CodeRegionGenerator() = default; Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions( const std::unique_ptr<MCInstPrinter> &IP, bool SkipFailures) { diff --git a/llvm/tools/llvm-mca/CodeRegionGenerator.h b/llvm/tools/llvm-mca/CodeRegionGenerator.h index a48c67a..c30f67a 100644 --- a/llvm/tools/llvm-mca/CodeRegionGenerator.h +++ b/llvm/tools/llvm-mca/CodeRegionGenerator.h @@ -151,7 +151,7 @@ protected: bool SkipFailures) = 0; public: - CodeRegionGenerator() {} + CodeRegionGenerator() = default; virtual ~CodeRegionGenerator(); }; diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp index 3d7f33c..8aa843b 100644 --- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp +++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp @@ -811,12 +811,12 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr, .Case("boot_application", COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION) .Case("console", COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI) - .Cases("efi_application", "efi-app", + .Cases({"efi_application", "efi-app"}, COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION) - .Cases("efi_boot_service_driver", "efi-bsd", + .Cases({"efi_boot_service_driver", "efi-bsd"}, COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) .Case("efi_rom", COFF::IMAGE_SUBSYSTEM_EFI_ROM) - .Cases("efi_runtime_driver", "efi-rtd", + .Cases({"efi_runtime_driver", "efi-rtd"}, COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) .Case("native", COFF::IMAGE_SUBSYSTEM_NATIVE) .Case("posix", COFF::IMAGE_SUBSYSTEM_POSIX_CUI) diff --git a/llvm/tools/llvm-objdump/OtoolOpts.td b/llvm/tools/llvm-objdump/OtoolOpts.td index dc7a5b4..706d9e0 100644 --- a/llvm/tools/llvm-objdump/OtoolOpts.td +++ b/llvm/tools/llvm-objdump/OtoolOpts.td @@ -14,7 +14,7 @@ def G : Flag<["-"], "G">, HelpText<"print data-in-code table">; def h : Flag<["-"], "h">, HelpText<"print mach header">; def I : Flag<["-"], "I">, HelpText<"print indirect symbol table">; def j : Flag<["-"], "j">, HelpText<"print opcode bytes">; -def l : Flag<["-"], "l">, HelpText<"print load commnads">; +def l : Flag<["-"], "l">, HelpText<"print load commands">; def L : Flag<["-"], "L">, HelpText<"print used shared libraries">; def mcpu_EQ : Joined<["-"], "mcpu=">, HelpText<"select cpu for disassembly">; def o : Flag<["-"], "o">, HelpText<"print Objective-C segment">; diff --git a/llvm/tools/llvm-objdump/SourcePrinter.cpp b/llvm/tools/llvm-objdump/SourcePrinter.cpp index b0ff89d..a4891a3 100644 --- a/llvm/tools/llvm-objdump/SourcePrinter.cpp +++ b/llvm/tools/llvm-objdump/SourcePrinter.cpp @@ -50,11 +50,6 @@ void InlinedFunction::dump(raw_ostream &OS) const { void InlinedFunction::printElementLine(raw_ostream &OS, object::SectionedAddress Addr, bool IsEnd) const { - bool LiveIn = !IsEnd && Range.LowPC == Addr.Address; - bool LiveOut = IsEnd && Range.HighPC == Addr.Address; - if (!(LiveIn || LiveOut)) - return; - uint32_t CallFile, CallLine, CallColumn, CallDiscriminator; InlinedFuncDie.getCallerFrame(CallFile, CallLine, CallColumn, CallDiscriminator); @@ -126,8 +121,41 @@ void LiveElementPrinter::addInlinedFunction(DWARFDie FuncDie, DWARFUnit *U = InlinedFuncDie.getDwarfUnit(); const char *InlinedFuncName = InlinedFuncDie.getName(DINameKind::LinkageName); DWARFAddressRange Range{FuncLowPC, FuncHighPC, SectionIndex}; + // Add the new element to the main vector. LiveElements.emplace_back(std::make_unique<InlinedFunction>( InlinedFuncName, U, FuncDie, InlinedFuncDie, Range)); + + LiveElement *LE = LiveElements.back().get(); + // Map the element's low address (LowPC) to its pointer for fast range start + // lookup. + LiveElementsByAddress[FuncLowPC].push_back(LE); + // Map the element's high address (HighPC) to its pointer for fast range end + // lookup. + LiveElementsByEndAddress[FuncHighPC].push_back(LE); + // Map the pointer to its DWARF discovery index for deterministic + // ordering. + ElementPtrToIndex[LE] = LiveElements.size() - 1; +} + +/// Registers the most recently added LiveVariable into all data structures. +void LiveElementPrinter::registerNewVariable() { + assert( + !LiveElements.empty() && + "registerNewVariable called before element was added to LiveElements."); + LiveVariable *CurrentVar = + static_cast<LiveVariable *>(LiveElements.back().get()); + assert(ElementPtrToIndex.count(CurrentVar) == 0 && + "Element already registered!"); + + // Map from a LiveElement pointer to its index in the LiveElements. + ElementPtrToIndex[CurrentVar] = LiveElements.size() - 1; + + if (const std::optional<DWARFAddressRange> &Range = + CurrentVar->getLocExpr().Range) { + // Add the variable to address-based maps. + LiveElementsByAddress[Range->LowPC].push_back(CurrentVar); + LiveElementsByEndAddress[Range->HighPC].push_back(CurrentVar); + } } void LiveElementPrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) { @@ -160,6 +188,9 @@ void LiveElementPrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) { LiveElements.emplace_back( std::make_unique<LiveVariable>(WholeFuncExpr, VarName, U, FuncDie)); } + + // Register the new variable with all data structures. + registerNewVariable(); } } @@ -205,14 +236,52 @@ unsigned LiveElementPrinter::moveToFirstVarColumn(formatted_raw_ostream &OS) { return FirstUnprintedLogicalColumn; } -unsigned LiveElementPrinter::findFreeColumn() { - for (unsigned ColIdx = 0; ColIdx < ActiveCols.size(); ++ColIdx) - if (!ActiveCols[ColIdx].isActive()) - return ColIdx; +unsigned LiveElementPrinter::getOrCreateColumn(unsigned ElementIdx) { + // Check if the element already has an assigned column. + auto it = ElementToColumn.find(ElementIdx); + if (it != ElementToColumn.end()) + return it->second; + + unsigned ColIdx; + if (!FreeCols.empty()) { + // Get the smallest available index from the set. + ColIdx = *FreeCols.begin(); + // Remove the index from the set. + FreeCols.erase(FreeCols.begin()); + } else { + // No free columns, so create a new one. + ColIdx = ActiveCols.size(); + ActiveCols.emplace_back(); + } - size_t OldSize = ActiveCols.size(); - ActiveCols.grow(std::max<size_t>(OldSize * 2, 1)); - return OldSize; + // Assign the element to the column and update the map. + ElementToColumn[ElementIdx] = ColIdx; + ActiveCols[ColIdx].ElementIdx = ElementIdx; + return ColIdx; +} + +void LiveElementPrinter::freeColumn(unsigned ColIdx) { + unsigned ElementIdx = ActiveCols[ColIdx].ElementIdx; + + // Clear the column's data. + ActiveCols[ColIdx].clear(); + + // Remove the element's entry from the map and add the column to the free + // list. + ElementToColumn.erase(ElementIdx); + FreeCols.insert(ColIdx); +} + +std::vector<unsigned> +LiveElementPrinter::getSortedActiveElementIndices() const { + // Get all element indices that currently have an assigned column. + std::vector<unsigned> Indices; + for (const auto &Pair : ElementToColumn) + Indices.push_back(Pair.first); + + // Sort by the DWARF discovery order. + llvm::stable_sort(Indices); + return Indices; } void LiveElementPrinter::dump() const { @@ -239,57 +308,112 @@ void LiveElementPrinter::addCompileUnit(DWARFDie D) { void LiveElementPrinter::update(object::SectionedAddress ThisAddr, object::SectionedAddress NextAddr, bool IncludeDefinedVars) { - // Do not create live ranges when debug-inlined-funcs option is provided with - // line format option. + // Exit early if only printing function limits. if (DbgInlinedFunctions == DFLimitsOnly) return; - // First, check variables which have already been assigned a column, so - // that we don't change their order. - SmallSet<unsigned, 8> CheckedElementIdxs; + // Free columns identified in the previous cycle. + for (unsigned ColIdx : ColumnsToFreeNextCycle) + freeColumn(ColIdx); + ColumnsToFreeNextCycle.clear(); + + // Update status of active columns and collect those to free next cycle. for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) { if (!ActiveCols[ColIdx].isActive()) continue; - CheckedElementIdxs.insert(ActiveCols[ColIdx].ElementIdx); const std::unique_ptr<LiveElement> &LE = LiveElements[ActiveCols[ColIdx].ElementIdx]; ActiveCols[ColIdx].LiveIn = LE->liveAtAddress(ThisAddr); ActiveCols[ColIdx].LiveOut = LE->liveAtAddress(NextAddr); - std::string Name = Demangle ? demangle(LE->getName()) : LE->getName(); - LLVM_DEBUG(dbgs() << "pass 1, " << ThisAddr.Address << "-" - << NextAddr.Address << ", " << Name << ", Col " << ColIdx - << ": LiveIn=" << ActiveCols[ColIdx].LiveIn - << ", LiveOut=" << ActiveCols[ColIdx].LiveOut << "\n"); - if (!ActiveCols[ColIdx].LiveIn && !ActiveCols[ColIdx].LiveOut) + LLVM_DEBUG({ + std::string Name = Demangle ? demangle(LE->getName()) : LE->getName(); + dbgs() << "pass 1, " << ThisAddr.Address << "-" << NextAddr.Address + << ", " << Name << ", Col " << ColIdx + << ": LiveIn=" << ActiveCols[ColIdx].LiveIn + << ", LiveOut=" << ActiveCols[ColIdx].LiveOut << "\n"; + }); + + // If element is fully dead, deactivate column immediately. + if (!ActiveCols[ColIdx].LiveIn && !ActiveCols[ColIdx].LiveOut) { ActiveCols[ColIdx].ElementIdx = Column::NullElementIdx; + continue; + } + + // Mark for cleanup in the next cycle if range ends here. + if (ActiveCols[ColIdx].LiveIn && !ActiveCols[ColIdx].LiveOut) + ColumnsToFreeNextCycle.push_back(ColIdx); } // Next, look for variables which don't already have a column, but which - // are now live. + // are now live (those starting at ThisAddr or NextAddr). if (IncludeDefinedVars) { - for (unsigned ElementIdx = 0, End = LiveElements.size(); ElementIdx < End; - ++ElementIdx) { - if (CheckedElementIdxs.count(ElementIdx)) + // Collect all elements starting at ThisAddr and NextAddr. + std::vector<std::pair<unsigned, LiveElement *>> NewLiveElements; + auto CollectNewElements = [&](const auto &It) { + if (It == LiveElementsByAddress.end()) + return; + + const std::vector<LiveElement *> &ElementList = It->second; + for (LiveElement *LE : ElementList) { + auto IndexIt = ElementPtrToIndex.find(LE); + assert(IndexIt != ElementPtrToIndex.end() && + "LiveElement in address map but missing from index map!"); + + // Get the element index for sorting and column management. + unsigned ElementIdx = IndexIt->second; + // Skip elements that already have a column. + if (ElementToColumn.count(ElementIdx)) + continue; + + bool LiveIn = LE->liveAtAddress(ThisAddr); + bool LiveOut = LE->liveAtAddress(NextAddr); + if (!LiveIn && !LiveOut) + continue; + + NewLiveElements.emplace_back(ElementIdx, LE); + } + }; + + // Collect elements starting at ThisAddr. + CollectNewElements(LiveElementsByAddress.find(ThisAddr.Address)); + // Collect elements starting at NextAddr (the address immediately + // following the instruction). + CollectNewElements(LiveElementsByAddress.find(NextAddr.Address)); + // Sort elements by DWARF discovery order for deterministic column + // assignment. + llvm::stable_sort(NewLiveElements, [](const auto &A, const auto &B) { + return A.first < B.first; + }); + + // Assign columns in deterministic order. + for (const auto &ElementPair : NewLiveElements) { + unsigned ElementIdx = ElementPair.first; + // Skip if element was already added from the first range. + if (ElementToColumn.count(ElementIdx)) continue; - const std::unique_ptr<LiveElement> &LE = LiveElements[ElementIdx]; + LiveElement *LE = ElementPair.second; bool LiveIn = LE->liveAtAddress(ThisAddr); bool LiveOut = LE->liveAtAddress(NextAddr); - if (!LiveIn && !LiveOut) - continue; - unsigned ColIdx = findFreeColumn(); - std::string Name = Demangle ? demangle(LE->getName()) : LE->getName(); - LLVM_DEBUG(dbgs() << "pass 2, " << ThisAddr.Address << "-" - << NextAddr.Address << ", " << Name << ", Col " - << ColIdx << ": LiveIn=" << LiveIn - << ", LiveOut=" << LiveOut << "\n"); - ActiveCols[ColIdx].ElementIdx = ElementIdx; + // Assign or create a column. + unsigned ColIdx = getOrCreateColumn(ElementIdx); + LLVM_DEBUG({ + std::string Name = Demangle ? demangle(LE->getName()) : LE->getName(); + dbgs() << "pass 2, " << ThisAddr.Address << "-" << NextAddr.Address + << ", " << Name << ", Col " << ColIdx << ": LiveIn=" << LiveIn + << ", LiveOut=" << LiveOut << "\n"; + }); + ActiveCols[ColIdx].LiveIn = LiveIn; ActiveCols[ColIdx].LiveOut = LiveOut; ActiveCols[ColIdx].MustDrawLabel = true; + + // Mark for cleanup next cycle if range ends here. + if (ActiveCols[ColIdx].LiveIn && !ActiveCols[ColIdx].LiveOut) + ColumnsToFreeNextCycle.push_back(ColIdx); } } } @@ -360,7 +484,13 @@ void LiveElementPrinter::printAfterOtherLine(formatted_raw_ostream &OS, void LiveElementPrinter::printBetweenInsts(formatted_raw_ostream &OS, bool MustPrint) { bool PrintedSomething = false; - for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) { + // Get all active elements, sorted by discovery order. + std::vector<unsigned> SortedElementIndices = getSortedActiveElementIndices(); + // The outer loop iterates over the deterministic DWARF discovery order. + for (unsigned ElementIdx : SortedElementIndices) { + // Look up the physical column index (ColIdx) assigned to this + // element. We use .at() because we are certain the element is active. + unsigned ColIdx = ElementToColumn.at(ElementIdx); if (ActiveCols[ColIdx].isActive() && ActiveCols[ColIdx].MustDrawLabel) { // First we need to print the live range markers for any active // columns to the left of this one. @@ -375,8 +505,7 @@ void LiveElementPrinter::printBetweenInsts(formatted_raw_ostream &OS, OS << " "; } - const std::unique_ptr<LiveElement> &LE = - LiveElements[ActiveCols[ColIdx].ElementIdx]; + const std::unique_ptr<LiveElement> &LE = LiveElements[ElementIdx]; // Then print the variable name and location of the new live range, // with box drawing characters joining it to the live range line. OS << getLineChar(ActiveCols[ColIdx].LiveIn ? LineChar::LabelCornerActive @@ -438,22 +567,40 @@ void LiveElementPrinter::printAfterInst(formatted_raw_ostream &OS) { } } -void LiveElementPrinter::printStartLine(formatted_raw_ostream &OS, - object::SectionedAddress Addr) { - // Print a line to idenfity the start of an inlined function if line format - // is specified. - if (DbgInlinedFunctions == DFLimitsOnly) - for (const std::unique_ptr<LiveElement> &LE : LiveElements) - LE->printElementLine(OS, Addr, false); -} +void LiveElementPrinter::printBoundaryLine(formatted_raw_ostream &OS, + object::SectionedAddress Addr, + bool IsEnd) { + // Only print the start/end line for inlined functions if DFLimitsOnly is + // enabled. + if (DbgInlinedFunctions != DFLimitsOnly) + return; -void LiveElementPrinter::printEndLine(formatted_raw_ostream &OS, - object::SectionedAddress Addr) { - // Print a line to idenfity the end of an inlined function if line format is - // specified. - if (DbgInlinedFunctions == DFLimitsOnly) - for (const std::unique_ptr<LiveElement> &LE : LiveElements) - LE->printElementLine(OS, Addr, true); + // Select the appropriate map based on whether we are checking the start + // (LowPC) or end (HighPC) address. + const auto &AddressMap = + IsEnd ? LiveElementsByEndAddress : LiveElementsByAddress; + + // Use the map to find all elements that start/end at the given address. + std::vector<unsigned> ElementIndices; + auto It = AddressMap.find(Addr.Address); + if (It != AddressMap.end()) { + for (LiveElement *LE : It->second) { + // Look up the element index from the pointer. + auto IndexIt = ElementPtrToIndex.find(LE); + assert(IndexIt != ElementPtrToIndex.end() && + "LiveElement found in address map but missing index!"); + ElementIndices.push_back(IndexIt->second); + } + } + + // Sort the indices to ensure deterministic output order (by DWARF discovery + // order). + llvm::stable_sort(ElementIndices); + + for (unsigned ElementIdx : ElementIndices) { + LiveElement *LE = LiveElements[ElementIdx].get(); + LE->printElementLine(OS, Addr, IsEnd); + } } bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) { diff --git a/llvm/tools/llvm-objdump/SourcePrinter.h b/llvm/tools/llvm-objdump/SourcePrinter.h index 5c131a0..ad3ea12 100644 --- a/llvm/tools/llvm-objdump/SourcePrinter.h +++ b/llvm/tools/llvm-objdump/SourcePrinter.h @@ -9,13 +9,16 @@ #ifndef LLVM_TOOLS_LLVM_OBJDUMP_SOURCEPRINTER_H #define LLVM_TOOLS_LLVM_OBJDUMP_SOURCEPRINTER_H +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringSet.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/Symbolize/Symbolize.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/FormattedStream.h" +#include <set> #include <unordered_map> #include <vector> @@ -34,7 +37,7 @@ public: LiveElement(const char *Name, DWARFUnit *Unit, const DWARFDie FuncDie) : Name(Name), Unit(Unit), FuncDie(FuncDie) {} - virtual ~LiveElement() {}; + virtual ~LiveElement() = default; const char *getName() const { return Name; } virtual bool liveAtAddress(object::SectionedAddress Addr) const = 0; @@ -78,6 +81,7 @@ public: bool liveAtAddress(object::SectionedAddress Addr) const override; void print(raw_ostream &OS, const MCRegisterInfo &MRI) const override; void dump(raw_ostream &OS) const override; + const DWARFLocationExpression &getLocExpr() const { return LocExpr; } }; /// Helper class for printing source locations for variables and inlined @@ -95,17 +99,39 @@ class LiveElementPrinter { static constexpr unsigned NullElementIdx = std::numeric_limits<unsigned>::max(); + + // Clear the column's data. + void clear() { + ElementIdx = NullElementIdx; + LiveIn = false; + LiveOut = false; + MustDrawLabel = false; + } }; - // All live elements we know about in the object/image file. + // Vector that owns all LiveElement objects for memory management. std::vector<std::unique_ptr<LiveElement>> LiveElements; - - // The columns we are currently drawing. - IndexedMap<Column> ActiveCols; + // Map for fast lookup of live elements by their starting address (LowPC). + llvm::MapVector<uint64_t, std::vector<LiveElement *>> LiveElementsByAddress; + // Map for fast lookup of live elements by their ending address (HighPC). + llvm::MapVector<uint64_t, std::vector<LiveElement *>> + LiveElementsByEndAddress; + // Map from a LiveElement pointer to its index in the LiveElements vector. + llvm::DenseMap<LiveElement *, unsigned> ElementPtrToIndex; + // Map from a live element index to column index for efficient lookup. + llvm::DenseMap<unsigned, unsigned> ElementToColumn; + // Vector of columns currently used for printing live ranges. + std::vector<Column> ActiveCols; + // Set of available column indices kept sorted for efficient reuse. + std::set<unsigned> FreeCols; + // Vector of available column indices that can be reused. + std::vector<unsigned> ColumnsToFreeNextCycle; const MCRegisterInfo &MRI; const MCSubtargetInfo &STI; + void registerNewVariable(); + void addInlinedFunction(DWARFDie FuncDie, DWARFDie InlinedFuncDie); void addVariable(DWARFDie FuncDie, DWARFDie VarDie); @@ -122,11 +148,19 @@ class LiveElementPrinter { // put live element lines. Pick a less overloaded word. unsigned moveToFirstVarColumn(formatted_raw_ostream &OS); - unsigned findFreeColumn(); + // Get an existing column for a live element, or find a free one. + unsigned getOrCreateColumn(unsigned ElementIdx); + + // Free a column when its element is no longer live. + void freeColumn(unsigned ColIdx); + + // Returns the indices of all currently active elements, sorted by their DWARF + // discovery order. + std::vector<unsigned> getSortedActiveElementIndices() const; public: LiveElementPrinter(const MCRegisterInfo &MRI, const MCSubtargetInfo &STI) - : ActiveCols(Column()), MRI(MRI), STI(STI) {} + : MRI(MRI), STI(STI) {} void dump() const; @@ -170,10 +204,9 @@ public: /// Print the live element ranges to the right of a disassembled instruction. void printAfterInst(formatted_raw_ostream &OS); - /// Print a line to idenfity the start of a live element. - void printStartLine(formatted_raw_ostream &OS, object::SectionedAddress Addr); - /// Print a line to idenfity the end of a live element. - void printEndLine(formatted_raw_ostream &OS, object::SectionedAddress Addr); + /// Print a line to idenfity the start/end of a live element. + void printBoundaryLine(formatted_raw_ostream &OS, + object::SectionedAddress Addr, bool IsEnd); }; class SourcePrinter { diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 3ec644a..38c3f31 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -688,7 +688,7 @@ public: LiveElementPrinter &LEP) { if (SP && (PrintSource || PrintLines)) SP->printSourceLine(OS, Address, ObjectFilename, LEP); - LEP.printStartLine(OS, Address); + LEP.printBoundaryLine(OS, Address, false); LEP.printBetweenInsts(OS, false); printRawData(Bytes, Address.Address, OS, STI); @@ -941,7 +941,7 @@ public: LiveElementPrinter &LEP) override { if (SP && (PrintSource || PrintLines)) SP->printSourceLine(OS, Address, ObjectFilename, LEP); - LEP.printStartLine(OS, Address); + LEP.printBoundaryLine(OS, Address, false); LEP.printBetweenInsts(OS, false); size_t Start = OS.tell(); @@ -996,7 +996,7 @@ public: LiveElementPrinter &LEP) override { if (SP && (PrintSource || PrintLines)) SP->printSourceLine(OS, Address, ObjectFilename, LEP); - LEP.printStartLine(OS, Address); + LEP.printBoundaryLine(OS, Address, false); LEP.printBetweenInsts(OS, false); size_t Start = OS.tell(); @@ -1035,7 +1035,7 @@ public: LiveElementPrinter &LEP) override { if (SP && (PrintSource || PrintLines)) SP->printSourceLine(OS, Address, ObjectFilename, LEP); - LEP.printStartLine(OS, Address); + LEP.printBoundaryLine(OS, Address, false); LEP.printBetweenInsts(OS, false); size_t Start = OS.tell(); @@ -2601,7 +2601,7 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj, object::SectionedAddress NextAddr = { SectionAddr + Index + VMAAdjustment + Size, Section.getIndex()}; - LEP.printEndLine(FOS, NextAddr); + LEP.printBoundaryLine(FOS, NextAddr, true); Index += Size; } diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h index 3525be9..bac8589 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.h +++ b/llvm/tools/llvm-objdump/llvm-objdump.h @@ -84,7 +84,7 @@ protected: public: Dumper(const object::ObjectFile &O); - virtual ~Dumper() {} + virtual ~Dumper() = default; void reportUniqueWarning(Error Err); void reportUniqueWarning(const Twine &Msg); diff --git a/llvm/tools/llvm-offload-wrapper/llvm-offload-wrapper.cpp b/llvm/tools/llvm-offload-wrapper/llvm-offload-wrapper.cpp index d65b4025..cda59b6 100644 --- a/llvm/tools/llvm-offload-wrapper/llvm-offload-wrapper.cpp +++ b/llvm/tools/llvm-offload-wrapper/llvm-offload-wrapper.cpp @@ -64,7 +64,7 @@ static Error wrapImages(ArrayRef<ArrayRef<char>> BuffersToWrap) { LLVMContext Context; Module M("offload.wrapper.module", Context); - M.setTargetTriple(Triple()); + M.setTargetTriple(llvm::Triple(TheTriple)); switch (Kind) { case llvm::object::OFK_OpenMP: diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp index b2362ec..d836d98 100644 --- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp +++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp @@ -68,7 +68,7 @@ DumpOutputStyle::DumpOutputStyle(InputFile &File) RefTracker.reset(new TypeReferenceTracker(File)); } -DumpOutputStyle::~DumpOutputStyle() {} +DumpOutputStyle::~DumpOutputStyle() = default; PDBFile &DumpOutputStyle::getPdb() { return File.pdb(); } object::COFFObjectFile &DumpOutputStyle::getObj() { return File.obj(); } diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.h b/llvm/tools/llvm-pdbutil/DumpOutputStyle.h index 6714a6a..ea4a47f 100644 --- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.h +++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.h @@ -29,7 +29,7 @@ class TypeReferenceTracker; struct StatCollection { struct Stat { - Stat() {} + Stat() = default; Stat(uint32_t Count, uint32_t Size) : Count(Count), Size(Size) {} uint32_t Count = 0; uint32_t Size = 0; diff --git a/llvm/tools/llvm-pdbutil/OutputStyle.h b/llvm/tools/llvm-pdbutil/OutputStyle.h index 8cc9016..a09fb82 100644 --- a/llvm/tools/llvm-pdbutil/OutputStyle.h +++ b/llvm/tools/llvm-pdbutil/OutputStyle.h @@ -17,7 +17,7 @@ namespace pdb { class OutputStyle { public: - virtual ~OutputStyle() {} + virtual ~OutputStyle() = default; virtual Error dump() = 0; }; diff --git a/llvm/tools/llvm-pdbutil/PdbYaml.cpp b/llvm/tools/llvm-pdbutil/PdbYaml.cpp index fac1d89..4131292 100644 --- a/llvm/tools/llvm-pdbutil/PdbYaml.cpp +++ b/llvm/tools/llvm-pdbutil/PdbYaml.cpp @@ -22,6 +22,7 @@ using namespace llvm::pdb; using namespace llvm::pdb::yaml; using namespace llvm::yaml; +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::CoffSectionHeader) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbDbiModuleInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList) @@ -135,6 +136,49 @@ void MappingTraits<msf::SuperBlock>::mapping(IO &IO, msf::SuperBlock &SB) { IO.mapOptional("BlockMapAddr", SB.BlockMapAddr, u32(0U)); } +CoffSectionHeader::CoffSectionHeader() = default; + +CoffSectionHeader::CoffSectionHeader(const object::coff_section &Section) + : Name(Section.Name), VirtualSize(Section.VirtualSize), + VirtualAddress(Section.VirtualAddress), + SizeOfRawData(Section.SizeOfRawData), + PointerToRawData(Section.PointerToRawData), + PointerToRelocations(Section.PointerToRelocations), + PointerToLinenumbers(Section.PointerToLinenumbers), + NumberOfRelocations(Section.NumberOfRelocations), + NumberOfLinenumbers(Section.NumberOfLinenumbers), + Characteristics(Section.Characteristics) {} + +object::coff_section CoffSectionHeader::toCoffSection() const { + object::coff_section Sec; + std::memset(Sec.Name, 0, COFF::NameSize); + std::memcpy(Sec.Name, Name.data(), + std::min(static_cast<size_t>(COFF::NameSize), Name.size())); + Sec.VirtualSize = VirtualSize; + Sec.VirtualAddress = VirtualAddress; + Sec.SizeOfRawData = SizeOfRawData; + Sec.PointerToRawData = PointerToRawData; + Sec.PointerToRelocations = PointerToRelocations; + Sec.PointerToLinenumbers = PointerToLinenumbers; + Sec.NumberOfRelocations = NumberOfRelocations; + Sec.NumberOfLinenumbers = NumberOfLinenumbers; + Sec.Characteristics = Characteristics; + return Sec; +} + +void MappingTraits<CoffSectionHeader>::mapping(IO &IO, CoffSectionHeader &Obj) { + IO.mapRequired("Name", Obj.Name); + IO.mapOptional("VirtualSize", Obj.VirtualSize); + IO.mapOptional("VirtualAddress", Obj.VirtualAddress); + IO.mapOptional("SizeOfRawData", Obj.SizeOfRawData); + IO.mapOptional("PointerToRawData", Obj.PointerToRawData); + IO.mapOptional("PointerToRelocations", Obj.PointerToRelocations); + IO.mapOptional("PointerToLinenumbers", Obj.PointerToLinenumbers); + IO.mapOptional("NumberOfRelocations", Obj.NumberOfRelocations); + IO.mapOptional("NumberOfLinenumbers", Obj.NumberOfLinenumbers); + IO.mapOptional("Characteristics", Obj.Characteristics); +} + void MappingTraits<StreamBlockList>::mapping(IO &IO, StreamBlockList &SB) { IO.mapRequired("Stream", SB.Blocks); } @@ -163,6 +207,7 @@ void MappingTraits<PdbDbiStream>::mapping(IO &IO, PdbDbiStream &Obj) { IO.setContext(&Obj.FakeHeader); } IO.mapOptional("Modules", Obj.ModInfos); + IO.mapOptional("SectionHeaders", Obj.SectionHeaders); } void MappingTraits<PdbTpiStream>::mapping(IO &IO, diff --git a/llvm/tools/llvm-pdbutil/PdbYaml.h b/llvm/tools/llvm-pdbutil/PdbYaml.h index d5111a9e..8746675 100644 --- a/llvm/tools/llvm-pdbutil/PdbYaml.h +++ b/llvm/tools/llvm-pdbutil/PdbYaml.h @@ -18,6 +18,7 @@ #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/Object/COFF.h" #include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h" #include "llvm/ObjectYAML/CodeViewYAMLSymbols.h" #include "llvm/ObjectYAML/CodeViewYAMLTypes.h" @@ -40,6 +41,24 @@ struct MSFHeaders { uint64_t FileSize = 0; }; +struct CoffSectionHeader { + CoffSectionHeader(); + CoffSectionHeader(const object::coff_section &Section); + + object::coff_section toCoffSection() const; + + StringRef Name; + uint32_t VirtualSize = 0; + uint32_t VirtualAddress = 0; + uint32_t SizeOfRawData = 0; + uint32_t PointerToRawData = 0; + uint32_t PointerToRelocations = 0; + uint32_t PointerToLinenumbers = 0; + uint16_t NumberOfRelocations = 0; + uint16_t NumberOfLinenumbers = 0; + uint32_t Characteristics = 0; +}; + struct StreamBlockList { std::vector<uint32_t> Blocks; }; @@ -82,6 +101,7 @@ struct PdbDbiStream { std::vector<PdbDbiModuleInfo> ModInfos; COFF::header FakeHeader; + std::vector<CoffSectionHeader> SectionHeaders; }; struct PdbTpiStream { @@ -113,6 +133,7 @@ struct PdbObject { } } +LLVM_YAML_DECLARE_MAPPING_TRAITS_PRIVATE(pdb::yaml::CoffSectionHeader) LLVM_YAML_DECLARE_MAPPING_TRAITS_PRIVATE(pdb::yaml::PdbObject) LLVM_YAML_DECLARE_MAPPING_TRAITS_PRIVATE(pdb::yaml::MSFHeaders) LLVM_YAML_DECLARE_MAPPING_TRAITS_PRIVATE(msf::SuperBlock) diff --git a/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h b/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h index 50c8f5d..9e492a4 100644 --- a/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h +++ b/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h @@ -15,8 +15,6 @@ #include "llvm/DebugInfo/PDB/PDBSymbolData.h" #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" -#include <memory> - namespace llvm { class BitVector; diff --git a/llvm/tools/llvm-pdbutil/PrettyCompilandDumper.cpp b/llvm/tools/llvm-pdbutil/PrettyCompilandDumper.cpp index b347cfd..902a1d7 100644 --- a/llvm/tools/llvm-pdbutil/PrettyCompilandDumper.cpp +++ b/llvm/tools/llvm-pdbutil/PrettyCompilandDumper.cpp @@ -32,8 +32,6 @@ #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" -#include <utility> - using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/tools/llvm-pdbutil/StreamUtil.h b/llvm/tools/llvm-pdbutil/StreamUtil.h index 9d6030c..6b8c13f 100644 --- a/llvm/tools/llvm-pdbutil/StreamUtil.h +++ b/llvm/tools/llvm-pdbutil/StreamUtil.h @@ -35,7 +35,7 @@ enum class StreamPurpose { struct StreamInfo { public: - StreamInfo() {} + StreamInfo() = default; uint32_t getModuleIndex() const { return *ModuleIndex; } StreamPurpose getPurpose() const { return Purpose; } diff --git a/llvm/tools/llvm-pdbutil/YAMLOutputStyle.cpp b/llvm/tools/llvm-pdbutil/YAMLOutputStyle.cpp index ecb4c21..8fe7f60 100644 --- a/llvm/tools/llvm-pdbutil/YAMLOutputStyle.cpp +++ b/llvm/tools/llvm-pdbutil/YAMLOutputStyle.cpp @@ -285,6 +285,24 @@ Error YAMLOutputStyle::dumpDbiStream() { } } } + + if (opts::pdb2yaml::DumpSectionHeaders) { + for (const auto &Section : DS.getSectionHeaders()) { + yaml::CoffSectionHeader Hdr; + Hdr.Name = Section.Name; + Hdr.VirtualSize = Section.VirtualSize; + Hdr.VirtualAddress = Section.VirtualAddress; + Hdr.SizeOfRawData = Section.SizeOfRawData; + Hdr.PointerToRawData = Section.PointerToRawData; + Hdr.PointerToRelocations = Section.PointerToRelocations; + Hdr.PointerToLinenumbers = Section.PointerToLinenumbers; + Hdr.NumberOfRelocations = Section.NumberOfRelocations; + Hdr.NumberOfLinenumbers = Section.NumberOfLinenumbers; + Hdr.Characteristics = Section.Characteristics; + Obj.DbiStream->SectionHeaders.emplace_back(Hdr); + } + } + return Error::success(); } diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp index a5b8e8b..befd331 100644 --- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -716,6 +716,10 @@ cl::list<ModuleSubsection> DumpModuleSubsections( cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"), cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand)); +cl::opt<bool> DumpSectionHeaders("section-headers", + cl::desc("Dump section headers."), + cl::cat(FileOptions), + cl::sub(PdbToYamlSubcommand)); cl::list<std::string> InputFilename(cl::Positional, cl::desc("<input PDB file>"), cl::Required, @@ -865,6 +869,20 @@ static void yamlToPdb(StringRef Path) { } } + std::vector<object::coff_section> Sections; + if (!Dbi.SectionHeaders.empty()) { + for (const auto &Hdr : Dbi.SectionHeaders) + Sections.emplace_back(Hdr.toCoffSection()); + + DbiBuilder.createSectionMap(Sections); + ExitOnErr(DbiBuilder.addDbgStream( + pdb::DbgHeaderType::SectionHdr, + // FIXME: Downcasting to an ArrayRef<uint8_t> should use a helper + // function in LLVM + ArrayRef<uint8_t>{(const uint8_t *)Sections.data(), + Sections.size() * sizeof(object::coff_section)})); + } + auto &TpiBuilder = Builder.getTpiBuilder(); const auto &Tpi = YamlObj.TpiStream.value_or(DefaultTpiStream); TpiBuilder.setVersionHeader(Tpi.Version); @@ -1541,6 +1559,7 @@ int main(int Argc, const char **Argv) { opts::pdb2yaml::DumpModules = true; opts::pdb2yaml::DumpModuleFiles = true; opts::pdb2yaml::DumpModuleSyms = true; + opts::pdb2yaml::DumpSectionHeaders = true; opts::pdb2yaml::DumpModuleSubsections.push_back( opts::ModuleSubsection::All); } @@ -1551,6 +1570,9 @@ int main(int Argc, const char **Argv) { if (opts::pdb2yaml::DumpModules) opts::pdb2yaml::DbiStream = true; + + if (opts::pdb2yaml::DumpSectionHeaders) + opts::pdb2yaml::DbiStream = true; } llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded); diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.h b/llvm/tools/llvm-pdbutil/llvm-pdbutil.h index b8c8033..73ff2fe 100644 --- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.h +++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.h @@ -201,6 +201,7 @@ extern llvm::cl::opt<bool> DumpModules; extern llvm::cl::opt<bool> DumpModuleFiles; extern llvm::cl::list<ModuleSubsection> DumpModuleSubsections; extern llvm::cl::opt<bool> DumpModuleSyms; +extern llvm::cl::opt<bool> DumpSectionHeaders; } // namespace pdb2yaml namespace explain { diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp index 9b853e2..e186c5a 100644 --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -2929,9 +2929,9 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) { continue; } - for (size_t I = 0, E = Func.Counts.size(); I < E; ++I) { - FuncMax = std::max(FuncMax, Func.Counts[I]); - FuncSum += Func.Counts[I]; + for (uint64_t Count : Func.Counts) { + FuncMax = std::max(FuncMax, Count); + FuncSum += Count; } if (FuncMax < ShowValueCutoff) { diff --git a/llvm/tools/llvm-profgen/MissingFrameInferrer.cpp b/llvm/tools/llvm-profgen/MissingFrameInferrer.cpp index 7ebca23..d692de7 100644 --- a/llvm/tools/llvm-profgen/MissingFrameInferrer.cpp +++ b/llvm/tools/llvm-profgen/MissingFrameInferrer.cpp @@ -14,7 +14,6 @@ #include "llvm/ADT/Statistic.h" #include <algorithm> #include <cstdint> -#include <iterator> #include <queue> #include <sys/types.h> diff --git a/llvm/tools/llvm-profgen/Options.h b/llvm/tools/llvm-profgen/Options.h index f94cf91..b2c941f 100644 --- a/llvm/tools/llvm-profgen/Options.h +++ b/llvm/tools/llvm-profgen/Options.h @@ -22,6 +22,7 @@ extern cl::opt<bool> ShowDetailedWarning; extern cl::opt<bool> InferMissingFrames; extern cl::opt<bool> EnableCSPreInliner; extern cl::opt<bool> UseContextCostForPreInliner; +extern cl::opt<bool> LoadFunctionFromSymbol; } // end namespace llvm diff --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp index 183b248..1dc5932 100644 --- a/llvm/tools/llvm-profgen/PerfReader.cpp +++ b/llvm/tools/llvm-profgen/PerfReader.cpp @@ -1284,6 +1284,7 @@ void PerfScriptReader::warnInvalidRange() { uint64_t TotalRangeNum = 0; uint64_t InstNotBoundary = 0; uint64_t UnmatchedRange = 0; + uint64_t RecoveredRange = 0; uint64_t RangeCrossFunc = 0; uint64_t BogusRange = 0; @@ -1309,6 +1310,9 @@ void PerfScriptReader::warnInvalidRange() { continue; } + if (FRange->Func->NameStatus != DwarfNameStatus::Matched) + RecoveredRange += I.second; + if (EndAddress >= FRange->EndAddress) { RangeCrossFunc += I.second; WarnInvalidRange(StartAddress, EndAddress, RangeCrossFuncMsg); @@ -1328,6 +1332,9 @@ void PerfScriptReader::warnInvalidRange() { emitWarningSummary( UnmatchedRange, TotalRangeNum, "of samples are from ranges that do not belong to any functions."); + emitWarningSummary(RecoveredRange, TotalRangeNum, + "of samples are from ranges that belong to functions " + "recovered from symbol table."); emitWarningSummary( RangeCrossFunc, TotalRangeNum, "of samples are from ranges that do cross function boundaries."); diff --git a/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/llvm/tools/llvm-profgen/ProfileGenerator.cpp index 3b875c5..33931f3 100644 --- a/llvm/tools/llvm-profgen/ProfileGenerator.cpp +++ b/llvm/tools/llvm-profgen/ProfileGenerator.cpp @@ -503,8 +503,11 @@ ProfileGenerator::getTopLevelFunctionProfile(FunctionId FuncName) { void ProfileGenerator::generateProfile() { collectProfiledFunctions(); - if (Binary->usePseudoProbes()) + if (Binary->usePseudoProbes()) { Binary->decodePseudoProbe(); + if (LoadFunctionFromSymbol) + Binary->loadSymbolsFromPseudoProbe(); + } if (SampleCounters) { if (Binary->usePseudoProbes()) { @@ -732,6 +735,14 @@ ProfileGeneratorBase::getCalleeNameForAddress(uint64_t TargetAddress) { if (!FRange || !FRange->IsFuncEntry) return StringRef(); + // DWARF and symbol table may have mismatching function names. Instead, we'll + // try to use its pseudo probe name first. + if (Binary->usePseudoProbes()) { + auto FuncName = Binary->findPseudoProbeName(FRange->Func); + if (FuncName.size()) + return FunctionSamples::getCanonicalFnName(FuncName); + } + return FunctionSamples::getCanonicalFnName(FRange->getFuncName()); } @@ -919,6 +930,8 @@ void CSProfileGenerator::generateProfile() { Binary->decodePseudoProbe(); if (InferMissingFrames) initializeMissingFrameInferrer(); + if (LoadFunctionFromSymbol) + Binary->loadSymbolsFromPseudoProbe(); } if (SampleCounters) { diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp index 94728ce..aa16b66 100644 --- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp +++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp @@ -37,6 +37,14 @@ cl::opt<bool> ShowSourceLocations("show-source-locations", cl::desc("Print source locations."), cl::cat(ProfGenCategory)); +cl::opt<bool> LoadFunctionFromSymbol( + "load-function-from-symbol", cl::init(true), + cl::desc( + "Gather additional binary function info from symbols (e.g. .symtab) in " + "case dwarf info is incomplete. Only support binaries in ELF format " + "with pseudo probe, for other formats, this flag will be a no-op."), + cl::cat(ProfGenCategory)); + static cl::opt<bool> ShowCanonicalFnName("show-canonical-fname", cl::desc("Print canonical function name."), @@ -187,7 +195,7 @@ ProfiledBinary::ProfiledBinary(const StringRef ExeBinPath, load(); } -ProfiledBinary::~ProfiledBinary() {} +ProfiledBinary::~ProfiledBinary() = default; void ProfiledBinary::warnNoFuncEntry() { uint64_t NoFuncEntryNum = 0; @@ -257,6 +265,9 @@ void ProfiledBinary::load() { if (ShowDisassemblyOnly) decodePseudoProbe(Obj); + if (LoadFunctionFromSymbol && UsePseudoProbes) + loadSymbolsFromSymtab(Obj); + // Disassemble the text sections. disassemble(Obj); @@ -461,6 +472,13 @@ void ProfiledBinary::decodePseudoProbe(const ObjectFile *Obj) { } else { for (auto *F : ProfiledFunctions) { GuidFilter.insert(Function::getGUIDAssumingExternalLinkage(F->FuncName)); + // DWARF name might be broken when a DWARF32 .debug_str.dwo section + // execeeds 4GB. We expect symbol table to contain the correct function + // names which matches the pseudo probe. Adding back all the GUIDs if + // possible. + auto AltGUIDs = AlternativeFunctionGUIDs.equal_range(F); + for (const auto &[_, Func] : make_range(AltGUIDs)) + GuidFilter.insert(Func); for (auto &Range : F->Ranges) { auto GUIDs = StartAddrToSymMap.equal_range(Range.first); for (const auto &[StartAddr, Func] : make_range(GUIDs)) @@ -522,7 +540,9 @@ void ProfiledBinary::setIsFuncEntry(FuncRange *FuncRange, // Set IsFuncEntry to ture if there is only one range in the function or the // RangeSymName from ELF is equal to its DWARF-based function name. if (FuncRange->Func->Ranges.size() == 1 || - (!FuncRange->IsFuncEntry && FuncRange->getFuncName() == RangeSymName)) + (!FuncRange->IsFuncEntry && + (FuncRange->getFuncName() == RangeSymName || + FuncRange->Func->NameStatus != DwarfNameStatus::Matched))) FuncRange->IsFuncEntry = true; } @@ -604,13 +624,14 @@ bool ProfiledBinary::dissassembleSymbol(std::size_t SI, ArrayRef<uint8_t> Bytes, // Record potential call targets for tail frame inference later-on. if (InferMissingFrames && FRange) { uint64_t Target = 0; - MIA->evaluateBranch(Inst, Address, Size, Target); + [[maybe_unused]] bool Err = + MIA->evaluateBranch(Inst, Address, Size, Target); if (MCDesc.isCall()) { // Indirect call targets are unknown at this point. Recording the // unknown target (zero) for further LBR-based refinement. MissingContextInferrer->CallEdges[Address].insert(Target); } else if (MCDesc.isUnconditionalBranch()) { - assert(Target && + assert(Err && "target should be known for unconditional direct branch"); // Any inter-function unconditional jump is considered tail call at // this point. This is not 100% accurate and could further be @@ -820,6 +841,100 @@ void ProfiledBinary::populateSymbolAddressList(const ObjectFile *Obj) { } } +void ProfiledBinary::loadSymbolsFromSymtab(const ObjectFile *Obj) { + // Load binary functions from symbol table when Debug info is incomplete. + // Strip the internal suffixes which are not reflected in the DWARF info. + const SmallVector<StringRef, 10> Suffixes( + {// Internal suffixes from CoroSplit pass + ".cleanup", ".destroy", ".resume", + // Internal suffixes from Bolt + ".cold", ".warm", + // Compiler/LTO internal + ".llvm.", ".part.", ".isra.", ".constprop.", ".lto_priv."}); + StringRef FileName = Obj->getFileName(); + // Only apply this to ELF binary. e.g. COFF file format doesn't have `size` + // field in the symbol table. + bool IsELFObject = isa<ELFObjectFileBase>(Obj); + if (!IsELFObject) + return; + for (const SymbolRef &Symbol : Obj->symbols()) { + const SymbolRef::Type Type = unwrapOrError(Symbol.getType(), FileName); + const uint64_t StartAddr = unwrapOrError(Symbol.getAddress(), FileName); + const StringRef Name = unwrapOrError(Symbol.getName(), FileName); + uint64_t Size = 0; + if (LLVM_LIKELY(IsELFObject)) { + ELFSymbolRef ElfSymbol(Symbol); + Size = ElfSymbol.getSize(); + } + + if (Size == 0 || Type != SymbolRef::ST_Function) + continue; + + const uint64_t EndAddr = StartAddr + Size; + const StringRef SymName = + FunctionSamples::getCanonicalFnName(Name, Suffixes); + assert(StartAddr < EndAddr && StartAddr >= getPreferredBaseAddress() && + "Function range is invalid."); + + auto Range = findFuncRange(StartAddr); + if (!Range) { + assert(findFuncRange(EndAddr - 1) == nullptr && + "Function range overlaps with existing functions."); + // Function from symbol table not found previously in DWARF, store ranges. + auto Ret = BinaryFunctions.emplace(SymName, BinaryFunction()); + auto &Func = Ret.first->second; + if (Ret.second) { + Func.FuncName = Ret.first->first; + HashBinaryFunctions[Function::getGUIDAssumingExternalLinkage(SymName)] = + &Func; + } + + Func.NameStatus = DwarfNameStatus::Missing; + Func.Ranges.emplace_back(StartAddr, EndAddr); + + auto R = StartAddrToFuncRangeMap.emplace(StartAddr, FuncRange()); + FuncRange &FRange = R.first->second; + + FRange.Func = &Func; + FRange.StartAddress = StartAddr; + FRange.EndAddress = EndAddr; + + } else if (SymName != Range->getFuncName()) { + // Function range already found from DWARF, but the symbol name from + // symbol table is inconsistent with debug info. Log this discrepancy and + // the alternative function GUID. + if (ShowDetailedWarning) + WithColor::warning() + << "Conflicting name for symbol " << Name << " with range (" + << format("%8" PRIx64, StartAddr) << ", " + << format("%8" PRIx64, EndAddr) << ")" + << ", but the DWARF symbol " << Range->getFuncName() + << " indicates an overlapping range (" + << format("%8" PRIx64, Range->StartAddress) << ", " + << format("%8" PRIx64, Range->EndAddress) << ")\n"; + + assert(StartAddr == Range->StartAddress && EndAddr == Range->EndAddress && + "Mismatched function range"); + + Range->Func->NameStatus = DwarfNameStatus::Mismatch; + AlternativeFunctionGUIDs.emplace( + Range->Func, Function::getGUIDAssumingExternalLinkage(SymName)); + + } else if (StartAddr != Range->StartAddress && + EndAddr != Range->EndAddress) { + // Function already found in DWARF, but the address range from symbol + // table conflicts/overlaps with the debug info. + WithColor::warning() << "Conflicting range for symbol " << Name + << " with range (" << format("%8" PRIx64, StartAddr) + << ", " << format("%8" PRIx64, EndAddr) << ")" + << ", but the DWARF symbol " << Range->getFuncName() + << " indicates another range (" + << format("%8" PRIx64, Range->StartAddress) << ", " + << format("%8" PRIx64, Range->EndAddress) << ")\n"; + } + } +} + void ProfiledBinary::loadSymbolsFromDWARFUnit(DWARFUnit &CompilationUnit) { for (const auto &DieInfo : CompilationUnit.dies()) { llvm::DWARFDie Die(&CompilationUnit, &DieInfo); @@ -1034,6 +1149,58 @@ void ProfiledBinary::computeInlinedContextSizeForFunc( } } +void ProfiledBinary::loadSymbolsFromPseudoProbe() { + if (!UsePseudoProbes) + return; + + const AddressProbesMap &Address2ProbesMap = getAddress2ProbesMap(); + for (auto *Func : ProfiledFunctions) { + if (Func->NameStatus != DwarfNameStatus::Mismatch) + continue; + for (auto &[StartAddr, EndAddr] : Func->Ranges) { + auto Range = findFuncRangeForStartAddr(StartAddr); + if (!Range->IsFuncEntry) + continue; + const auto &Probe = Address2ProbesMap.find(StartAddr, EndAddr); + if (Probe.begin() != Probe.end()) { + const MCDecodedPseudoProbeInlineTree *InlineTreeNode = + Probe.begin()->get().getInlineTreeNode(); + while (!InlineTreeNode->isTopLevelFunc()) + InlineTreeNode = static_cast<MCDecodedPseudoProbeInlineTree *>( + InlineTreeNode->Parent); + + auto TopLevelProbes = InlineTreeNode->getProbes(); + [[maybe_unused]] auto TopProbe = TopLevelProbes.begin(); + assert(TopProbe != TopLevelProbes.end() && + TopProbe->getAddress() >= StartAddr && + TopProbe->getAddress() < EndAddr && + "Top level pseudo probe does not match function range"); + + const auto *ProbeDesc = getFuncDescForGUID(InlineTreeNode->Guid); + auto Ret = PseudoProbeNames.emplace(Func, ProbeDesc->FuncName); + if (!Ret.second && Ret.first->second != ProbeDesc->FuncName && + ShowDetailedWarning) + WithColor::warning() + << "Mismatched pseudo probe names in function " << Func->FuncName + << " at range: (" << format("%8" PRIx64, StartAddr) << ", " + << format("%8" PRIx64, EndAddr) << "). " + << "The previously found pseudo probe name is " + << Ret.first->second << " but it conflicts with name " + << ProbeDesc->FuncName + << " This likely indicates a DWARF error that produces " + "conflicting symbols at the same starting address.\n"; + } + } + } +} + +StringRef ProfiledBinary::findPseudoProbeName(const BinaryFunction *Func) { + auto ProbeName = PseudoProbeNames.find(Func); + if (ProbeName == PseudoProbeNames.end()) + return StringRef(); + return ProbeName->second; +} + void ProfiledBinary::inferMissingFrames( const SmallVectorImpl<uint64_t> &Context, SmallVectorImpl<uint64_t> &NewContext) { diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.h b/llvm/tools/llvm-profgen/ProfiledBinary.h index 5a814b7..1a83f82 100644 --- a/llvm/tools/llvm-profgen/ProfiledBinary.h +++ b/llvm/tools/llvm-profgen/ProfiledBinary.h @@ -72,10 +72,22 @@ enum SpecialFrameAddr { using RangesTy = std::vector<std::pair<uint64_t, uint64_t>>; +enum DwarfNameStatus { + // Dwarf name matches with the symbol table (or symbol table just doesn't have + // this entry) + Matched = 0, + // Dwarf name is missing, but we fixed it with the name from symbol table + Missing = 1, + // Symbol table has different names on this. Log these GUIDs in + // AlternativeFunctionGUIDs + Mismatch = 2, +}; + struct BinaryFunction { StringRef FuncName; // End of range is an exclusive bound. RangesTy Ranges; + DwarfNameStatus NameStatus = DwarfNameStatus::Matched; uint64_t getFuncSize() { uint64_t Sum = 0; @@ -231,6 +243,14 @@ class ProfiledBinary { // GUID to symbol start address map DenseMap<uint64_t, uint64_t> SymbolStartAddrs; + // Binary function to GUID mapping that stores the alternative names in symbol + // table, despite the original name from DWARF info + std::unordered_multimap<const BinaryFunction *, uint64_t> + AlternativeFunctionGUIDs; + + // Mapping of profiled binary function to its pseudo probe name + std::unordered_map<const BinaryFunction *, StringRef> PseudoProbeNames; + // These maps are for temporary use of warning diagnosis. DenseSet<int64_t> AddrsWithMultipleSymbols; DenseSet<std::pair<uint64_t, uint64_t>> AddrsWithInvalidInstruction; @@ -356,6 +376,9 @@ class ProfiledBinary { // Create symbol to its start address mapping. void populateSymbolAddressList(const object::ObjectFile *O); + // Load functions from its symbol table (when DWARF info is missing). + void loadSymbolsFromSymtab(const object::ObjectFile *O); + // A function may be spilt into multiple non-continuous address ranges. We use // this to set whether start a function range is the real entry of the // function and also set false to the non-function label. @@ -599,6 +622,10 @@ public: void computeInlinedContextSizeForFunc(const BinaryFunction *Func); + void loadSymbolsFromPseudoProbe(); + + StringRef findPseudoProbeName(const BinaryFunction *Func); + const MCDecodedPseudoProbe *getCallProbeForAddr(uint64_t Address) const { return ProbeDecoder.getCallProbeForAddr(Address); } diff --git a/llvm/tools/llvm-rc/ResourceFileWriter.h b/llvm/tools/llvm-rc/ResourceFileWriter.h index 82d3e3b..a13af45 100644 --- a/llvm/tools/llvm-rc/ResourceFileWriter.h +++ b/llvm/tools/llvm-rc/ResourceFileWriter.h @@ -19,6 +19,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Endian.h" +#include <map> + namespace llvm { class MemoryBuffer; diff --git a/llvm/tools/llvm-rc/ResourceScriptStmt.h b/llvm/tools/llvm-rc/ResourceScriptStmt.h index a81e384f..84da9be 100644 --- a/llvm/tools/llvm-rc/ResourceScriptStmt.h +++ b/llvm/tools/llvm-rc/ResourceScriptStmt.h @@ -242,9 +242,9 @@ public: virtual raw_ostream &log(raw_ostream &OS) const { return OS << "Base statement\n"; }; - RCResource() {} + RCResource() = default; RCResource(uint16_t Flags) : MemoryFlags(Flags) {} - virtual ~RCResource() {} + virtual ~RCResource() = default; virtual Error visit(Visitor *) const { llvm_unreachable("This is unable to call methods from Visitor base"); @@ -290,7 +290,7 @@ class OptionalStmtList : public OptionalStmt { std::vector<std::unique_ptr<OptionalStmt>> Statements; public: - OptionalStmtList() {} + OptionalStmtList() = default; raw_ostream &log(raw_ostream &OS) const override; void addStmt(std::unique_ptr<OptionalStmt> Stmt) { @@ -510,7 +510,7 @@ public: virtual raw_ostream &log(raw_ostream &OS) const { return OS << "Base menu definition\n"; } - virtual ~MenuDefinition() {} + virtual ~MenuDefinition() = default; virtual uint16_t getResFlags() const { return 0; } virtual MenuDefKind getKind() const { return MkBase; } @@ -818,7 +818,7 @@ public: enum StmtKind { StBase = 0, StBlock = 1, StValue = 2 }; virtual raw_ostream &log(raw_ostream &OS) const { return OS << "VI stmt\n"; } - virtual ~VersionInfoStmt() {} + virtual ~VersionInfoStmt() = default; virtual StmtKind getKind() const { return StBase; } static bool classof(const VersionInfoStmt *S) { diff --git a/llvm/tools/llvm-rc/ResourceScriptToken.cpp b/llvm/tools/llvm-rc/ResourceScriptToken.cpp index 0070037..046a1bf 100644 --- a/llvm/tools/llvm-rc/ResourceScriptToken.cpp +++ b/llvm/tools/llvm-rc/ResourceScriptToken.cpp @@ -26,11 +26,11 @@ using namespace llvm; using Kind = RCToken::Kind; // Checks if Representation is a correct description of an RC integer. -// It should be a 32-bit unsigned integer, either decimal, octal (0[0-7]+), -// or hexadecimal (0x[0-9a-f]+). It might be followed by a single 'L' -// character (that is the difference between our representation and -// StringRef's one). If Representation is correct, 'true' is returned and -// the return value is put back in Num. +// It should be a 32-bit unsigned integer, either decimal or hexadecimal +// (0x[0-9a-f]+). For Windres mode, it can also be octal (0[0-7]+). +// It might be followed by a single 'L' character (that is the difference +// between our representation and StringRef's one). If Representation is +// correct, 'true' is returned and the return value is put back in Num. static bool rcGetAsInteger(StringRef Representation, uint32_t &Num) { size_t Length = Representation.size(); if (Length == 0) @@ -95,7 +95,8 @@ namespace { class Tokenizer { public: - Tokenizer(StringRef Input) : Data(Input), DataLength(Input.size()), Pos(0) {} + Tokenizer(StringRef Input, bool IsWindres) + : Data(Input), DataLength(Input.size()), Pos(0), IsWindres(IsWindres) {} Expected<std::vector<RCToken>> run(); @@ -128,6 +129,7 @@ private: // character. bool canStartInt() const; bool canContinueInt() const; + void trimIntString(StringRef &Str) const; bool canStartString() const; @@ -153,6 +155,7 @@ private: StringRef Data; size_t DataLength, Pos; + bool IsWindres; }; void Tokenizer::skipCurrentLine() { @@ -187,7 +190,12 @@ Expected<std::vector<RCToken>> Tokenizer::run() { if (TokenKind == Kind::LineComment || TokenKind == Kind::StartComment) continue; - RCToken Token(TokenKind, Data.take_front(Pos).drop_front(TokenStart)); + StringRef Contents = Data.take_front(Pos).drop_front(TokenStart); + + if (TokenKind == Kind::Int) + trimIntString(Contents); + + RCToken Token(TokenKind, Contents); if (TokenKind == Kind::Identifier) { processIdentifier(Token); } else if (TokenKind == Kind::Int) { @@ -366,12 +374,30 @@ void Tokenizer::processIdentifier(RCToken &Token) const { Token = RCToken(Kind::BlockEnd, Name); } +void Tokenizer::trimIntString(StringRef &Str) const { + if (!IsWindres) { + // For compatibility with rc.exe, strip leading zeros that make the + // integer literal interpreted as octal. + // + // We do rely on Stringref::getAsInteger for autodetecting between + // decimal and hexadecimal literals, but we want to avoid interpreting + // literals as octal. + // + // This omits the leading zeros from the RCToken's value string entirely, + // which also has a visible effect when dumping the tokenizer output. + // Alternatively, we could store the IsWindres flag in RCToken and defer + // the trimming to RCToken::intValue. + while (Str.size() >= 2 && Str[0] == '0' && std::isdigit(Str[1])) + Str = Str.drop_front(1); + } +} + } // anonymous namespace namespace llvm { -Expected<std::vector<RCToken>> tokenizeRC(StringRef Input) { - return Tokenizer(Input).run(); +Expected<std::vector<RCToken>> tokenizeRC(StringRef Input, bool IsWindres) { + return Tokenizer(Input, IsWindres).run(); } } // namespace llvm diff --git a/llvm/tools/llvm-rc/ResourceScriptToken.h b/llvm/tools/llvm-rc/ResourceScriptToken.h index 3dcdfaf..4c839a0 100644 --- a/llvm/tools/llvm-rc/ResourceScriptToken.h +++ b/llvm/tools/llvm-rc/ResourceScriptToken.h @@ -28,7 +28,6 @@ #include "llvm/Support/Error.h" #include <cstdint> -#include <map> #include <vector> namespace llvm { @@ -76,7 +75,7 @@ private: // Tokens returned by this function hold only references to the parts // of the Input. Memory buffer containing Input cannot be freed, // modified or reallocated. -Expected<std::vector<RCToken>> tokenizeRC(StringRef Input); +Expected<std::vector<RCToken>> tokenizeRC(StringRef Input, bool IsWindres); } // namespace llvm diff --git a/llvm/tools/llvm-rc/ResourceScriptTokenList.def b/llvm/tools/llvm-rc/ResourceScriptTokenList.def index 6ee13b2..98af23c 100644 --- a/llvm/tools/llvm-rc/ResourceScriptTokenList.def +++ b/llvm/tools/llvm-rc/ResourceScriptTokenList.def @@ -14,7 +14,7 @@ // Long tokens. They might consist of more than one character. TOKEN(Invalid) // Invalid token. Should not occur in a valid script. -TOKEN(Int) // Integer (decimal, octal or hexadecimal). +TOKEN(Int) // Integer (decimal or hexadecimal, and possibly octal for windres). TOKEN(String) // String value. TOKEN(Identifier) // Script identifier (resource name or type). TOKEN(LineComment) // Beginning of single-line comment. diff --git a/llvm/tools/llvm-rc/ResourceVisitor.h b/llvm/tools/llvm-rc/ResourceVisitor.h index a121a0a..1815c6b 100644 --- a/llvm/tools/llvm-rc/ResourceVisitor.h +++ b/llvm/tools/llvm-rc/ResourceVisitor.h @@ -55,7 +55,7 @@ public: virtual Error visitVersionStmt(const VersionStmt *) = 0; virtual Error visitMenuStmt(const MenuStmt *) = 0; - virtual ~Visitor() {} + virtual ~Visitor() = default; }; } // namespace rc diff --git a/llvm/tools/llvm-rc/llvm-rc.cpp b/llvm/tools/llvm-rc/llvm-rc.cpp index f623342..38bf03f 100644 --- a/llvm/tools/llvm-rc/llvm-rc.cpp +++ b/llvm/tools/llvm-rc/llvm-rc.cpp @@ -619,7 +619,8 @@ void doRc(std::string Src, std::string Dest, RcOptions &Opts, StringRef Contents = FileContents->getBuffer(); std::string FilteredContents = filterCppOutput(Contents); - std::vector<RCToken> Tokens = ExitOnErr(tokenizeRC(FilteredContents)); + std::vector<RCToken> Tokens = + ExitOnErr(tokenizeRC(FilteredContents, Opts.IsWindres)); if (Opts.BeVerbose) { const Twine TokenNames[] = { diff --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp index c6e409c..32e3d05 100644 --- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp +++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp @@ -1404,6 +1404,12 @@ bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF, FpSZ += 8; int SavSZ = (IntSZ + FpSZ + 8 * 8 * RF.H() + 0xf) & ~0xf; int LocSZ = (RF.FrameSize() << 4) - SavSZ; + bool Homing = RF.H(); + + if (RF.H() && RF.RegI() == 0 && RF.RegF() == 0 && RF.CR() != 1) { + LocSZ += SavSZ; + Homing = false; + } if (RF.CR() == 2 || RF.CR() == 3) { SW.startLine() << "mov x29, sp\n"; @@ -1419,18 +1425,11 @@ bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF, } else if ((RF.CR() != 3 && RF.CR() != 2 && LocSZ > 0) || LocSZ > 512) { SW.startLine() << format("sub sp, sp, #%d\n", LocSZ); } - if (RF.H()) { + if (Homing) { SW.startLine() << format("stp x6, x7, [sp, #%d]\n", SavSZ - 16); SW.startLine() << format("stp x4, x5, [sp, #%d]\n", SavSZ - 32); SW.startLine() << format("stp x2, x3, [sp, #%d]\n", SavSZ - 48); - if (RF.RegI() > 0 || RF.RegF() > 0 || RF.CR() == 1) { - SW.startLine() << format("stp x0, x1, [sp, #%d]\n", SavSZ - 64); - } else { - // This case isn't documented; if neither RegI nor RegF nor CR=1 - // have decremented the stack pointer by SavSZ, we need to do it here - // (as the final stack adjustment of LocSZ excludes SavSZ). - SW.startLine() << format("stp x0, x1, [sp, #-%d]!\n", SavSZ); - } + SW.startLine() << format("stp x0, x1, [sp, #%d]\n", SavSZ - 64); } int FloatRegs = RF.RegF() > 0 ? RF.RegF() + 1 : 0; for (int I = (FloatRegs + 1) / 2 - 1; I >= 0; I--) { @@ -1457,10 +1456,14 @@ bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF, // The last register, an odd register without a pair if (RF.CR() == 1) { if (I == 0) { // If this is the only register pair - // CR=1 combined with RegI=1 doesn't map to a documented case; - // it doesn't map to any regular unwind info opcode, and the - // actual unwinder doesn't support it. - SW.startLine() << "INVALID!\n"; + // CR=1 combined with RegI=1 maps to a special case; there's + // no unwind info opcode that saves a GPR together with LR + // with writeback to sp (no save_lrpair_x). + // Instead, this case expands to two instructions; a preceding + // (in prologue execution order) "sub sp, sp, #16", followed + // by a regular "stp x19, lr, [sp]" (save_lrpair). + SW.startLine() << format("stp x%d, lr, [sp]\n", 19); + SW.startLine() << format("sub sp, sp, #%d\n", SavSZ); } else SW.startLine() << format("stp x%d, lr, [sp, #%d]\n", 19 + 2 * I, 16 * I); @@ -1478,9 +1481,6 @@ bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF, 19 + 2 * I + 1, 16 * I); } } - // CR=2 is yet undocumented, see - // https://github.com/MicrosoftDocs/cpp-docs/pull/4202 for upstream - // progress on getting it documented. if (RF.CR() == 2) SW.startLine() << "pacibsp\n"; SW.startLine() << "end\n"; diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp index 73115fb..55e106d 100644 --- a/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -2330,8 +2330,7 @@ void COFFDumper::printResourceDirectoryTable( std::vector<UTF16> EndianCorrectedNameString; if (llvm::sys::IsBigEndianHost) { EndianCorrectedNameString.resize(RawEntryNameString.size() + 1); - std::copy(RawEntryNameString.begin(), RawEntryNameString.end(), - EndianCorrectedNameString.begin() + 1); + llvm::copy(RawEntryNameString, EndianCorrectedNameString.begin() + 1); EndianCorrectedNameString[0] = UNI_UTF16_BYTE_ORDER_MARK_SWAPPED; RawEntryNameString = ArrayRef(EndianCorrectedNameString); } diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 6f09da5..2b5bc63 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -61,7 +61,6 @@ #include "llvm/Support/RISCVAttributeParser.h" #include "llvm/Support/RISCVAttributes.h" #include "llvm/Support/ScopedPrinter.h" -#include "llvm/Support/SystemZ/zOSSupport.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <array> diff --git a/llvm/tools/llvm-readobj/MachODumper.cpp b/llvm/tools/llvm-readobj/MachODumper.cpp index 0a23ad7..6ba3262 100644 --- a/llvm/tools/llvm-readobj/MachODumper.cpp +++ b/llvm/tools/llvm-readobj/MachODumper.cpp @@ -110,17 +110,20 @@ const EnumEntry<uint32_t> MachOHeaderFileTypes[] = { { "KextBundle", MachO::MH_KEXT_BUNDLE }, }; +// clang-format off const EnumEntry<uint32_t> MachOHeaderCpuTypes[] = { - { "Any" , static_cast<uint32_t>(MachO::CPU_TYPE_ANY) }, - { "X86" , MachO::CPU_TYPE_X86 }, - { "X86-64" , MachO::CPU_TYPE_X86_64 }, - { "Mc98000" , MachO::CPU_TYPE_MC98000 }, - { "Arm" , MachO::CPU_TYPE_ARM }, - { "Arm64" , MachO::CPU_TYPE_ARM64 }, - { "Sparc" , MachO::CPU_TYPE_SPARC }, - { "PowerPC" , MachO::CPU_TYPE_POWERPC }, - { "PowerPC64" , MachO::CPU_TYPE_POWERPC64 }, + { "Any" , static_cast<uint32_t>(MachO::CPU_TYPE_ANY) }, + { "X86" , MachO::CPU_TYPE_X86 }, + { "X86-64" , MachO::CPU_TYPE_X86_64 }, + { "Mc98000" , MachO::CPU_TYPE_MC98000 }, + { "Arm" , MachO::CPU_TYPE_ARM }, + { "Arm64" , MachO::CPU_TYPE_ARM64 }, + { "Arm64 (ILP32)", MachO::CPU_TYPE_ARM64_32 }, + { "Sparc" , MachO::CPU_TYPE_SPARC }, + { "PowerPC" , MachO::CPU_TYPE_POWERPC }, + { "PowerPC64" , MachO::CPU_TYPE_POWERPC64 }, }; +// clang-format on const EnumEntry<uint32_t> MachOHeaderCpuSubtypesX86[] = { LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_I386_ALL), @@ -166,6 +169,10 @@ const EnumEntry<uint32_t> MachOHeaderCpuSubtypesARM[] = { LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7EM), }; +const EnumEntry<uint32_t> MachOHeaderCpuSubtypesARM64_32[] = { + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64_32_V8), +}; + const EnumEntry<uint32_t> MachOHeaderCpuSubtypesARM64[] = { LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64_ALL), LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64_V8), @@ -453,9 +460,13 @@ void MachODumper::printFileHeaders(const MachHeader &Header) { case MachO::CPU_TYPE_ARM64: W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesARM64)); break; + case MachO::CPU_TYPE_ARM64_32: + W.printEnum("CpuSubType", subtype, + ArrayRef(MachOHeaderCpuSubtypesARM64_32)); + break; case MachO::CPU_TYPE_POWERPC64: default: - W.printHex("CpuSubtype", subtype); + W.printHex("CpuSubType", subtype); } W.printEnum("FileType", Header.filetype, ArrayRef(MachOHeaderFileTypes)); W.printNumber("NumOfLoadCommands", Header.ncmds); diff --git a/llvm/tools/llvm-readobj/ObjDumper.cpp b/llvm/tools/llvm-readobj/ObjDumper.cpp index 0b59dd4..1d19357 100644 --- a/llvm/tools/llvm-readobj/ObjDumper.cpp +++ b/llvm/tools/llvm-readobj/ObjDumper.cpp @@ -21,7 +21,6 @@ #include "llvm/Support/Error.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/ScopedPrinter.h" -#include "llvm/Support/SystemZ/zOSSupport.h" #include "llvm/Support/raw_ostream.h" #include <map> @@ -41,7 +40,7 @@ ObjDumper::ObjDumper(ScopedPrinter &Writer, StringRef ObjName) : W(Writer) { }; } -ObjDumper::~ObjDumper() {} +ObjDumper::~ObjDumper() = default; void ObjDumper::reportUniqueWarning(Error Err) const { reportUniqueWarning(toString(std::move(Err))); diff --git a/llvm/tools/llvm-readtapi/DiffEngine.h b/llvm/tools/llvm-readtapi/DiffEngine.h index 7ab57d4..b350ceef 100644 --- a/llvm/tools/llvm-readtapi/DiffEngine.h +++ b/llvm/tools/llvm-readtapi/DiffEngine.h @@ -39,7 +39,7 @@ enum DiffAttrKind { class AttributeDiff { public: AttributeDiff(DiffAttrKind Kind) : Kind(Kind){}; - virtual ~AttributeDiff(){}; + virtual ~AttributeDiff() = default; DiffAttrKind getKind() const { return Kind; } private: diff --git a/llvm/tools/llvm-reduce/CMakeLists.txt b/llvm/tools/llvm-reduce/CMakeLists.txt index c8673b4..cf6701a 100644 --- a/llvm/tools/llvm-reduce/CMakeLists.txt +++ b/llvm/tools/llvm-reduce/CMakeLists.txt @@ -60,6 +60,7 @@ add_llvm_tool(llvm-reduce deltas/ReduceRegisterMasks.cpp deltas/ReduceRegisterDefs.cpp deltas/ReduceRegisterUses.cpp + deltas/ReduceSinkDefsToUses.cpp deltas/ReduceTargetFeaturesAttr.cpp deltas/ReduceUsingSimplifyCFG.cpp deltas/RunIRPasses.cpp diff --git a/llvm/tools/llvm-reduce/DeltaManager.cpp b/llvm/tools/llvm-reduce/DeltaManager.cpp index 9b13202..769e8a0 100644 --- a/llvm/tools/llvm-reduce/DeltaManager.cpp +++ b/llvm/tools/llvm-reduce/DeltaManager.cpp @@ -45,6 +45,7 @@ #include "deltas/ReduceRegisterDefs.h" #include "deltas/ReduceRegisterMasks.h" #include "deltas/ReduceRegisterUses.h" +#include "deltas/ReduceSinkDefsToUses.h" #include "deltas/ReduceSpecialGlobals.h" #include "deltas/ReduceTargetFeaturesAttr.h" #include "deltas/ReduceUsingSimplifyCFG.h" diff --git a/llvm/tools/llvm-reduce/DeltaPasses.def b/llvm/tools/llvm-reduce/DeltaPasses.def index 845b106..1ec7354 100644 --- a/llvm/tools/llvm-reduce/DeltaPasses.def +++ b/llvm/tools/llvm-reduce/DeltaPasses.def @@ -59,6 +59,7 @@ DELTA_PASS_IR("atomic-ordering", reduceAtomicOrderingDeltaPass, "Reducing Atomic DELTA_PASS_IR("syncscopes", reduceAtomicSyncScopesDeltaPass, "Reducing Atomic Sync Scopes") DELTA_PASS_IR("instruction-flags", reduceInstructionFlagsDeltaPass, "Reducing Instruction Flags") DELTA_PASS_IR("inline-call-sites", reduceInlineCallSitesDeltaPass, "Inlining callsites") +DELTA_PASS_IR("sink-defs-to-uses", reduceSinkDefsToUsesDeltaPass, "Sinking defs to uses") #ifndef DELTA_PASS_MIR #define DELTA_PASS_MIR(NAME, FUNC, DESC) diff --git a/llvm/tools/llvm-reduce/TestRunner.h b/llvm/tools/llvm-reduce/TestRunner.h index 930c324..0218dad 100644 --- a/llvm/tools/llvm-reduce/TestRunner.h +++ b/llvm/tools/llvm-reduce/TestRunner.h @@ -16,7 +16,6 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" #include "llvm/Target/TargetMachine.h" -#include <vector> namespace llvm { diff --git a/llvm/tools/llvm-reduce/deltas/ReduceSinkDefsToUses.cpp b/llvm/tools/llvm-reduce/deltas/ReduceSinkDefsToUses.cpp new file mode 100644 index 0000000..454a6e4 --- /dev/null +++ b/llvm/tools/llvm-reduce/deltas/ReduceSinkDefsToUses.cpp @@ -0,0 +1,61 @@ +//===- ReduceSinkDefsToUses.cpp - Specialized Delta Pass ------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Try to move defs to be next to their uses +// +//===----------------------------------------------------------------------===// + +#include "ReduceSinkDefsToUses.h" +#include "Utils.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Instructions.h" + +using namespace llvm; + +static bool shouldPreserveUsePosition(const Instruction &I) { + return isa<AllocaInst>(I) || isa<PHINode>(I) || I.isEHPad(); +} + +static bool shouldPreserveDefPosition(const Instruction &I) { + return shouldPreserveUsePosition(I) || I.isTerminator(); +} + +static void sinkDefsToUsesInFunction(Oracle &O, Function &F) { + DominatorTree DT(F); + + for (BasicBlock &BB : F) { + for (Instruction &UseInst : make_early_inc_range(reverse(BB))) { + if (shouldPreserveUsePosition(UseInst)) + continue; + + for (Value *UseOp : UseInst.operands()) { + Instruction *DefInst = dyn_cast<Instruction>(UseOp); + if (!DefInst || shouldPreserveDefPosition(*DefInst)) + continue; + + if (!all_of(DefInst->users(), [&](const User *DefUser) { + return DefUser == &UseInst || + DT.dominates(&UseInst, cast<Instruction>(DefUser)); + })) { + continue; + } + + if (!O.shouldKeep()) + DefInst->moveBeforePreserving(UseInst.getIterator()); + } + } + } +} + +void llvm::reduceSinkDefsToUsesDeltaPass(Oracle &O, ReducerWorkItem &WorkItem) { + Module &M = WorkItem.getModule(); + for (Function &F : M) { + if (!F.isDeclaration()) + sinkDefsToUsesInFunction(O, F); + } +} diff --git a/llvm/tools/llvm-reduce/deltas/ReduceSinkDefsToUses.h b/llvm/tools/llvm-reduce/deltas/ReduceSinkDefsToUses.h new file mode 100644 index 0000000..422d0ea --- /dev/null +++ b/llvm/tools/llvm-reduce/deltas/ReduceSinkDefsToUses.h @@ -0,0 +1,18 @@ +//===- ReduceSinkDefsToUses.h - Specialized Delta Pass ----------*- C++- *-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_SINKDEFSTOUSES_H +#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_SINKDEFSTOUSES_H + +#include "Delta.h" + +namespace llvm { +void reduceSinkDefsToUsesDeltaPass(Oracle &O, ReducerWorkItem &WorkItem); +} // namespace llvm + +#endif diff --git a/llvm/tools/llvm-stress/llvm-stress.cpp b/llvm/tools/llvm-stress/llvm-stress.cpp index 133812e..2fe5d6b 100644 --- a/llvm/tools/llvm-stress/llvm-stress.cpp +++ b/llvm/tools/llvm-stress/llvm-stress.cpp @@ -40,7 +40,6 @@ #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" -#include <algorithm> #include <cassert> #include <cstddef> #include <cstdint> diff --git a/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp b/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp index 0cf8c5c..0b606af 100644 --- a/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp +++ b/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp @@ -113,19 +113,20 @@ static void reportNumberOfEntries(const TargetLibraryInfo &TLI, // Assume this gets called after initialize(), so we have the above line of // output as a header. So, for example, no need to repeat the triple. - for (unsigned FI = 0; FI != LibFunc::NumLibFuncs; ++FI) { + for (unsigned FI = LibFunc::Begin_LibFunc; FI != LibFunc::End_LibFunc; ++FI) { if (TLI.has(static_cast<LibFunc>(FI))) ++NumAvailable; } - outs() << "TLI knows " << LibFunc::NumLibFuncs << " symbols, " << NumAvailable - << " available for '" << TargetTriple << "'\n"; + outs() << "TLI knows " << (LibFunc::End_LibFunc - LibFunc::Begin_LibFunc) + << " symbols, " << NumAvailable << " available for '" << TargetTriple + << "'\n"; } static void dumpTLIEntries(const TargetLibraryInfo &TLI) { // Assume this gets called after initialize(), so we have the above line of // output as a header. So, for example, no need to repeat the triple. - for (unsigned FI = 0; FI != LibFunc::NumLibFuncs; ++FI) { + for (unsigned FI = LibFunc::Begin_LibFunc; FI != LibFunc::End_LibFunc; ++FI) { LibFunc LF = static_cast<LibFunc>(FI); bool IsAvailable = TLI.has(LF); StringRef FuncName = TargetLibraryInfo::getStandardName(LF); @@ -316,7 +317,8 @@ int main(int argc, char *argv[]) { unsigned TLIandSDKboth = 0; unsigned TLIandSDKneither = 0; - for (unsigned FI = 0; FI != LibFunc::NumLibFuncs; ++FI) { + for (unsigned FI = LibFunc::Begin_LibFunc; FI != LibFunc::End_LibFunc; + ++FI) { LibFunc LF = static_cast<LibFunc>(FI); StringRef TLIName = TLI.getStandardName(LF); @@ -344,7 +346,7 @@ int main(int argc, char *argv[]) { assert(TLIandSDKboth + TLIandSDKneither + TLIdoesSDKdoesnt + TLIdoesntSDKdoes == - LibFunc::NumLibFuncs); + LibFunc::End_LibFunc - LibFunc::Begin_LibFunc); (void) TLIandSDKneither; outs() << "<< Total TLI yes SDK no: " << TLIdoesSDKdoesnt << "\n>> Total TLI no SDK yes: " << TLIdoesntSDKdoes diff --git a/llvm/tools/llvm-xray/trie-node.h b/llvm/tools/llvm-xray/trie-node.h index b42b029..f96be59 100644 --- a/llvm/tools/llvm-xray/trie-node.h +++ b/llvm/tools/llvm-xray/trie-node.h @@ -15,7 +15,6 @@ #define LLVM_TOOLS_LLVM_XRAY_STACK_TRIE_H #include <forward_list> -#include <numeric> #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" diff --git a/llvm/tools/llvm-xray/xray-extract.cpp b/llvm/tools/llvm-xray/xray-extract.cpp index 70fe011..5ff8dc1 100644 --- a/llvm/tools/llvm-xray/xray-extract.cpp +++ b/llvm/tools/llvm-xray/xray-extract.cpp @@ -57,7 +57,7 @@ static void exportAsYAML(const InstrumentationMap &Map, raw_ostream &OS, // First we translate the sleds into the YAMLXRaySledEntry objects in a deque. std::vector<YAMLXRaySledEntry> YAMLSleds; auto Sleds = Map.sleds(); - YAMLSleds.reserve(std::distance(Sleds.begin(), Sleds.end())); + YAMLSleds.reserve(llvm::size(Sleds)); for (const auto &Sled : Sleds) { auto FuncId = Map.getFunctionId(Sled.Function); if (!FuncId) diff --git a/llvm/tools/llvm-xray/xray-graph.h b/llvm/tools/llvm-xray/xray-graph.h index fd96449..bf25f8d 100644 --- a/llvm/tools/llvm-xray/xray-graph.h +++ b/llvm/tools/llvm-xray/xray-graph.h @@ -86,7 +86,7 @@ public: }; GraphT G; - using VertexIdentifier = typename decltype(G)::VertexIdentifier; + using VertexIdentifier = decltype(G)::VertexIdentifier; using EdgeIdentifier = decltype(G)::EdgeIdentifier; /// Use a Map to store the Function stack for each thread whilst building the diff --git a/llvm/tools/lto/lto.cpp b/llvm/tools/lto/lto.cpp index 467a4da..513d057 100644 --- a/llvm/tools/lto/lto.cpp +++ b/llvm/tools/lto/lto.cpp @@ -24,6 +24,7 @@ #include "llvm/LTO/legacy/LTOCodeGenerator.h" #include "llvm/LTO/legacy/LTOModule.h" #include "llvm/LTO/legacy/ThinLTOCodeGenerator.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" @@ -44,6 +45,29 @@ static cl::opt<bool> EnableFreestanding( "lto-freestanding", cl::init(false), cl::desc("Enable Freestanding (disable builtins / TLI) during LTO")); +static cl::opt<std::string> ThinLTOCacheDir( + "legacy-thinlto-cache-dir", + cl::desc("Experimental option, enable ThinLTO caching. Note: the cache " + "currently does not take the mcmodel setting into account, so you " + "might get false hits if different mcmodels are used in different " + "builds using the same cache directory.")); + +static cl::opt<int> ThinLTOCachePruningInterval( + "legacy-thinlto-cache-pruning-interval", cl::init(1200), + cl::desc("Set ThinLTO cache pruning interval (seconds).")); + +static cl::opt<uint64_t> ThinLTOCacheMaxSizeBytes( + "legacy-thinlto-cache-max-size-bytes", + cl::desc("Set ThinLTO cache pruning directory maximum size in bytes.")); + +static cl::opt<int> ThinLTOCacheMaxSizeFiles( + "legacy-thinlto-cache-max-size-files", cl::init(1000000), + cl::desc("Set ThinLTO cache pruning directory maximum number of files.")); + +static cl::opt<unsigned> ThinLTOCacheEntryExpiration( + "legacy-thinlto-cache-entry-expiration", cl::init(604800) /* 1w */, + cl::desc("Set ThinLTO cache entry expiration time (seconds).")); + #ifdef NDEBUG static bool VerifyByDefault = false; #else @@ -543,6 +567,25 @@ thinlto_code_gen_t thinlto_create_codegen(void) { assert(CGOptLevelOrNone); CodeGen->setCodeGenOptLevel(*CGOptLevelOrNone); } + if (!ThinLTOCacheDir.empty()) { + auto Err = llvm::sys::fs::create_directories(ThinLTOCacheDir); + if (Err) + report_fatal_error(Twine("Unable to create thinLTO cache directory: ") + + Err.message()); + bool result; + Err = llvm::sys::fs::is_directory(ThinLTOCacheDir, result); + if (Err || !result) + report_fatal_error(Twine("Unable to get status of thinLTO cache path or " + "path is not a directory: ") + + Err.message()); + CodeGen->setCacheDir(ThinLTOCacheDir); + + CodeGen->setCachePruningInterval(ThinLTOCachePruningInterval); + CodeGen->setCacheEntryExpiration(ThinLTOCacheEntryExpiration); + CodeGen->setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles); + CodeGen->setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes); + } + return wrap(CodeGen); } diff --git a/llvm/tools/obj2yaml/macho2yaml.cpp b/llvm/tools/obj2yaml/macho2yaml.cpp index 0022012..f78ec8f 100644 --- a/llvm/tools/obj2yaml/macho2yaml.cpp +++ b/llvm/tools/obj2yaml/macho2yaml.cpp @@ -15,7 +15,6 @@ #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" -#include "llvm/Support/SystemZ/zOSSupport.h" #include <string.h> // for memcpy diff --git a/llvm/tools/opt-viewer/optrecord.py b/llvm/tools/opt-viewer/optrecord.py index b9244fd..07e2102 100644 --- a/llvm/tools/opt-viewer/optrecord.py +++ b/llvm/tools/opt-viewer/optrecord.py @@ -344,6 +344,8 @@ def find_opt_files(*dirs_or_files): d for d in subdirs if not os.path.ismount(os.path.join(dir, d)) ] for file in files: - if fnmatch.fnmatch(file, "*.opt.yaml*"): + if fnmatch.fnmatch(file, "*.opt.yaml*") or fnmatch.fnmatch( + file, "*.opt.ld.yaml*" + ): all.append(os.path.join(dir, file)) return all diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp index a383415..eaa1d8f 100644 --- a/llvm/tools/opt/NewPMDriver.cpp +++ b/llvm/tools/opt/NewPMDriver.cpp @@ -18,8 +18,10 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/CGSCCPassManager.h" +#include "llvm/Analysis/RuntimeLibcallInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Bitcode/BitcodeWriterPass.h" +#include "llvm/CodeGen/LibcallLoweringInfo.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/LLVMContext.h" @@ -409,14 +411,25 @@ bool llvm::runPassPipeline( P->CSAction = PGOOptions::CSIRUse; } } - if (TM) - TM->setPGOOption(P); LoopAnalysisManager LAM; FunctionAnalysisManager FAM; CGSCCAnalysisManager CGAM; ModuleAnalysisManager MAM; + if (TM) { + TM->setPGOOption(P); + + MAM.registerPass([&] { + const TargetOptions &Options = TM->Options; + return RuntimeLibraryAnalysis(M.getTargetTriple(), Options.ExceptionModel, + Options.FloatABIType, Options.EABIVersion, + Options.MCOptions.ABIName, Options.VecLib); + }); + + MAM.registerPass([&] { return LibcallLoweringModuleAnalysis(); }); + } + PassInstrumentationCallbacks PIC; PrintPassOptions PrintPassOpts; PrintPassOpts.Verbose = DebugPM == DebugLogging::Verbose; @@ -507,7 +520,7 @@ bool llvm::runPassPipeline( false, "", nullptr, DebugifyMode::OriginalDebugInfo, &DebugInfoBeforePass, VerifyDIPreserveExport)); if (EnableProfcheck) - MPM.addPass(createModuleToFunctionPassAdaptor(ProfileVerifierPass())); + MPM.addPass(ProfileVerifierPass()); // Add any relevant output pass at the end of the pipeline. switch (OK) { diff --git a/llvm/tools/opt/optdriver.cpp b/llvm/tools/opt/optdriver.cpp index f70db31..ac318e6 100644 --- a/llvm/tools/opt/optdriver.cpp +++ b/llvm/tools/opt/optdriver.cpp @@ -17,6 +17,7 @@ #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/RegionPass.h" +#include "llvm/Analysis/RuntimeLibcallInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/AsmParser/Parser.h" @@ -36,6 +37,7 @@ #include "llvm/InitializePasses.h" #include "llvm/LinkAllIR.h" #include "llvm/LinkAllPasses.h" +#include "llvm/MC/MCTargetOptionsCommandFlags.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Passes/PassPlugin.h" #include "llvm/Remarks/HotnessThresholdParser.h" @@ -64,6 +66,7 @@ using namespace llvm; using namespace opt_tool; static codegen::RegisterCodeGenFlags CFG; +static codegen::RegisterSaveStatsFlag SSF; // The OptimizationList is automatically populated with registered Passes by the // PassNameParser. @@ -512,6 +515,10 @@ optMain(int argc, char **argv, } LLVMRemarkFileHandle RemarksFile = std::move(*RemarksFileOrErr); + codegen::MaybeEnableStatistics(); + + StringRef ABIName = mc::getABIName(); // FIXME: Handle module flag. + // Load the input module... auto SetDataLayout = [&](StringRef IRTriple, StringRef IRLayout) -> std::optional<std::string> { @@ -534,15 +541,16 @@ optMain(int argc, char **argv, // the IR, we should default to an empty (default) DataLayout. if (TripleStr.empty()) return std::nullopt; - // Otherwise we infer the DataLayout from the target machine. - Expected<std::unique_ptr<TargetMachine>> ExpectedTM = - codegen::createTargetMachineForTriple(TripleStr, GetCodeGenOptLevel()); - if (!ExpectedTM) { - errs() << argv[0] << ": warning: failed to infer data layout: " - << toString(ExpectedTM.takeError()) << "\n"; + + Triple TT(TripleStr); + + std::string Str = TT.computeDataLayout(ABIName); + if (Str.empty()) { + errs() << argv[0] + << ": warning: failed to infer data layout from target triple\n"; return std::nullopt; } - return (*ExpectedTM)->createDataLayout().getStringRepresentation(); + return Str; }; std::unique_ptr<Module> M; if (NoUpgradeDebugInfo) @@ -649,6 +657,13 @@ optMain(int argc, char **argv, return 1; } + TargetOptions CodeGenFlagsOptions; + const TargetOptions *Options = TM ? &TM->Options : &CodeGenFlagsOptions; + if (!TM) { + CodeGenFlagsOptions = + codegen::InitTargetOptionsFromCodeGenFlags(ModuleTriple); + } + // Override function attributes based on CPUStr, FeaturesStr, and command line // flags. codegen::setFunctionAttributes(CPUStr, FeaturesStr, *M); @@ -667,7 +682,7 @@ optMain(int argc, char **argv, } // Add an appropriate TargetLibraryInfo pass for the module's triple. - TargetLibraryInfoImpl TLII(ModuleTriple); + TargetLibraryInfoImpl TLII(ModuleTriple, Options->VecLib); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (DisableSimplifyLibCalls) @@ -742,15 +757,15 @@ optMain(int argc, char **argv, // The user has asked to use the new pass manager and provided a pipeline // string. Hand off the rest of the functionality to the new code for that // layer. - return runPassPipeline( - argv[0], *M, TM.get(), &TLII, Out.get(), ThinLinkOut.get(), - RemarksFile.get(), Pipeline, PluginList, PassBuilderCallbacks, - OK, VK, /* ShouldPreserveAssemblyUseListOrder */ false, - /* ShouldPreserveBitcodeUseListOrder */ true, EmitSummaryIndex, - EmitModuleHash, EnableDebugify, VerifyDebugInfoPreserve, - EnableProfileVerification, UnifiedLTO) - ? 0 - : 1; + if (!runPassPipeline( + argv[0], *M, TM.get(), &TLII, Out.get(), ThinLinkOut.get(), + RemarksFile.get(), Pipeline, PluginList, PassBuilderCallbacks, OK, + VK, /* ShouldPreserveAssemblyUseListOrder */ false, + /* ShouldPreserveBitcodeUseListOrder */ true, EmitSummaryIndex, + EmitModuleHash, EnableDebugify, VerifyDebugInfoPreserve, + EnableProfileVerification, UnifiedLTO)) + return 1; + return codegen::MaybeSaveStatistics(OutputFilename, "opt"); } if (OptLevelO0 || OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || @@ -791,6 +806,9 @@ optMain(int argc, char **argv, (VerifyDebugInfoPreserve && !VerifyEachDebugInfoPreserve); Passes.add(new TargetLibraryInfoWrapperPass(TLII)); + Passes.add(new RuntimeLibraryInfoWrapper( + ModuleTriple, Options->ExceptionModel, Options->FloatABIType, + Options->EABIVersion, Options->MCOptions.ABIName, Options->VecLib)); // Add internal analysis passes from the target machine. Passes.add(createTargetTransformInfoWrapperPass(TM ? TM->getTargetIRAnalysis() @@ -928,5 +946,5 @@ optMain(int argc, char **argv, if (ThinLinkOut) ThinLinkOut->keep(); - return 0; + return codegen::MaybeSaveStatistics(OutputFilename, "opt"); } |
