aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/tools')
-rw-r--r--contrib/llvm-project/llvm/tools/bugpoint/BugDriver.cpp2
-rw-r--r--contrib/llvm-project/llvm/tools/bugpoint/BugDriver.h9
-rw-r--r--contrib/llvm-project/llvm/tools/bugpoint/CrashDebugger.cpp59
-rw-r--r--contrib/llvm-project/llvm/tools/bugpoint/ExtractFunction.cpp1
-rw-r--r--contrib/llvm-project/llvm/tools/bugpoint/OptimizerDriver.cpp2
-rw-r--r--contrib/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp2
-rw-r--r--contrib/llvm-project/llvm/tools/bugpoint/ToolRunner.h2
-rw-r--r--contrib/llvm-project/llvm/tools/bugpoint/bugpoint.cpp50
-rw-r--r--contrib/llvm-project/llvm/tools/llc/llc.cpp38
-rw-r--r--contrib/llvm-project/llvm/tools/lli/ExecutionUtils.h4
-rw-r--r--contrib/llvm-project/llvm/tools/lli/lli.cpp189
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp36
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp16
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-cov/CoverageReport.cpp1
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-cov/llvm-cov.cpp2
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp19
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-cxxmap/llvm-cxxmap.cpp2
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-debuginfo-analyzer/README.txt224
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp48
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp297
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-dwarfutil/Error.h2
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-dwarfutil/Options.h1
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-dwarfutil/Options.td5
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp12
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-dwp/Opts.td13
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp86
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp7
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-lto2/llvm-lto2.cpp35
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-mc/Disassembler.cpp2
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp2
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp11
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.h33
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp45
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h81
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp4
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h6
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp18
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.h11
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp4
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-mca/Views/TimelineView.cpp4
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp11
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp96
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp5
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td36
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp5
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp35
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp130
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objdump/ELFDump.h2
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp38
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td6
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp50
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.h4
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objdump/WasmDump.cpp19
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp326
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.h7
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp318
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h100
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp1
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp3
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp1
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-pdbutil/PrettyCompilandDumper.cpp1
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp301
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp98
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp896
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h1
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-readobj/Opts.td1
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp11
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp8
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtil.cpp109
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-size/llvm-size.cpp3
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp14
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp2
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp55
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp58
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h7
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp4
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-xray/xray-account.cpp2
-rw-r--r--contrib/llvm-project/llvm/tools/llvm-xray/xray-graph.cpp2
-rw-r--r--contrib/llvm-project/llvm/tools/opt/AnalysisWrappers.cpp71
-rw-r--r--contrib/llvm-project/llvm/tools/opt/BreakpointPrinter.cpp71
-rw-r--r--contrib/llvm-project/llvm/tools/opt/BreakpointPrinter.h24
-rw-r--r--contrib/llvm-project/llvm/tools/opt/NewPMDriver.cpp51
-rw-r--r--contrib/llvm-project/llvm/tools/opt/NewPMDriver.h8
-rw-r--r--contrib/llvm-project/llvm/tools/opt/opt.cpp109
84 files changed, 2911 insertions, 1574 deletions
diff --git a/contrib/llvm-project/llvm/tools/bugpoint/BugDriver.cpp b/contrib/llvm-project/llvm/tools/bugpoint/BugDriver.cpp
index 942028cad80b..32c747fdd516 100644
--- a/contrib/llvm-project/llvm/tools/bugpoint/BugDriver.cpp
+++ b/contrib/llvm-project/llvm/tools/bugpoint/BugDriver.cpp
@@ -21,9 +21,9 @@
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Host.h"
#include <memory>
using namespace llvm;
diff --git a/contrib/llvm-project/llvm/tools/bugpoint/BugDriver.h b/contrib/llvm-project/llvm/tools/bugpoint/BugDriver.h
index b7c9edc5b812..9fb0880b9cd0 100644
--- a/contrib/llvm-project/llvm/tools/bugpoint/BugDriver.h
+++ b/contrib/llvm-project/llvm/tools/bugpoint/BugDriver.h
@@ -101,15 +101,6 @@ public:
/// input.
Error debugMiscompilation();
- /// debugPassMiscompilation - This method is called when the specified pass
- /// miscompiles Program as input. It tries to reduce the testcase to
- /// something that smaller that still miscompiles the program.
- /// ReferenceOutput contains the filename of the file containing the output we
- /// are to match.
- ///
- bool debugPassMiscompilation(const PassInfo *ThePass,
- const std::string &ReferenceOutput);
-
/// compileSharedObject - This method creates a SharedObject from a given
/// BitcodeFile for debugging a code generator.
///
diff --git a/contrib/llvm-project/llvm/tools/bugpoint/CrashDebugger.cpp b/contrib/llvm-project/llvm/tools/bugpoint/CrashDebugger.cpp
index c90e1afd8ca4..0ca8fa28c4af 100644
--- a/contrib/llvm-project/llvm/tools/bugpoint/CrashDebugger.cpp
+++ b/contrib/llvm-project/llvm/tools/bugpoint/CrashDebugger.cpp
@@ -70,6 +70,18 @@ cl::opt<bool> VerboseErrors("verbose-errors",
cl::init(false));
}
+static bool isValidModule(std::unique_ptr<Module> &M,
+ bool ExitOnFailure = true) {
+ if (!llvm::verifyModule(*M.get(), &llvm::errs()))
+ return true;
+
+ if (ExitOnFailure) {
+ llvm::errs() << "verify failed!\n";
+ exit(1);
+ }
+ return false;
+}
+
namespace llvm {
class ReducePassList : public ListReducer<std::string> {
BugDriver &BD;
@@ -368,6 +380,10 @@ bool ReduceCrashingFunctionAttributes::TestFuncAttrs(
if (F->hasFnAttribute(Attribute::OptimizeNone))
F->addFnAttr(Attribute::NoInline);
+ // If modifying the attribute list leads to invalid IR, revert the change
+ if (!isValidModule(M, /*ExitOnFailure=*/false))
+ return false;
+
// Try running on the hacked up program...
if (TestFn(BD, M.get())) {
BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
@@ -510,14 +526,7 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock *> &BBs) {
ToProcess.clear();
}
// Verify we didn't break anything
- std::vector<std::string> Passes;
- Passes.push_back("verify");
- std::unique_ptr<Module> New = BD.runPassesOn(M.get(), Passes);
- if (!New) {
- errs() << "verify failed!\n";
- exit(1);
- }
- M = std::move(New);
+ isValidModule(M);
// Try running on the hacked up program...
if (TestFn(BD, M.get())) {
@@ -618,14 +627,7 @@ bool ReduceCrashingConditionals::TestBlocks(
ToProcess.clear();
}
// Verify we didn't break anything
- std::vector<std::string> Passes;
- Passes.push_back("verify");
- std::unique_ptr<Module> New = BD.runPassesOn(M.get(), Passes);
- if (!New) {
- errs() << "verify failed!\n";
- exit(1);
- }
- M = std::move(New);
+ isValidModule(M);
// Try running on the hacked up program...
if (TestFn(BD, M.get())) {
@@ -711,14 +713,7 @@ bool ReduceSimplifyCFG::TestBlocks(std::vector<const BasicBlock *> &BBs) {
simplifyCFG(&*BBIt++, TTI);
}
// Verify we didn't break anything
- std::vector<std::string> Passes;
- Passes.push_back("verify");
- std::unique_ptr<Module> New = BD.runPassesOn(M.get(), Passes);
- if (!New) {
- errs() << "verify failed!\n";
- exit(1);
- }
- M = std::move(New);
+ isValidModule(M);
// Try running on the hacked up program...
if (TestFn(BD, M.get())) {
@@ -797,9 +792,7 @@ bool ReduceCrashingInstructions::TestInsts(
}
// Verify that this is still valid.
- legacy::PassManager Passes;
- Passes.add(createVerifierPass(/*FatalErrors=*/false));
- Passes.run(*M);
+ isValidModule(M, /*ExitOnFailure=*/false);
// Try running on the hacked up program...
if (TestFn(BD, M.get())) {
@@ -869,9 +862,7 @@ bool ReduceCrashingMetadata::TestInsts(std::vector<Instruction *> &Insts) {
}
// Verify that this is still valid.
- legacy::PassManager Passes;
- Passes.add(createVerifierPass(/*FatalErrors=*/false));
- Passes.run(*M);
+ isValidModule(M, /*ExitOnFailure=*/false);
// Try running on the hacked up program...
if (TestFn(BD, M.get())) {
@@ -944,9 +935,7 @@ bool ReduceCrashingNamedMD::TestNamedMDs(std::vector<std::string> &NamedMDs) {
NamedMD->eraseFromParent();
// Verify that this is still valid.
- legacy::PassManager Passes;
- Passes.add(createVerifierPass(/*FatalErrors=*/false));
- Passes.run(*M);
+ isValidModule(M, /*ExitOnFailure=*/false);
// Try running on the hacked up program...
if (TestFn(BD, M.get())) {
@@ -1009,9 +998,7 @@ bool ReduceCrashingNamedMDOps::TestNamedMDOps(
}
// Verify that this is still valid.
- legacy::PassManager Passes;
- Passes.add(createVerifierPass(/*FatalErrors=*/false));
- Passes.run(*M);
+ isValidModule(M, /*ExitOnFailure=*/false);
// Try running on the hacked up program...
if (TestFn(BD, M.get())) {
diff --git a/contrib/llvm-project/llvm/tools/bugpoint/ExtractFunction.cpp b/contrib/llvm-project/llvm/tools/bugpoint/ExtractFunction.cpp
index 5047aa35d7e7..dd9a82c32035 100644
--- a/contrib/llvm-project/llvm/tools/bugpoint/ExtractFunction.cpp
+++ b/contrib/llvm-project/llvm/tools/bugpoint/ExtractFunction.cpp
@@ -133,7 +133,6 @@ BugDriver::performFinalCleanups(std::unique_ptr<Module> M,
I->setLinkage(GlobalValue::ExternalLinkage);
std::vector<std::string> CleanupPasses;
- CleanupPasses.push_back("globaldce");
if (MayModifySemantics)
CleanupPasses.push_back("deadarghaX0r");
diff --git a/contrib/llvm-project/llvm/tools/bugpoint/OptimizerDriver.cpp b/contrib/llvm-project/llvm/tools/bugpoint/OptimizerDriver.cpp
index 1197528d0dd3..f7239f5dc61b 100644
--- a/contrib/llvm-project/llvm/tools/bugpoint/OptimizerDriver.cpp
+++ b/contrib/llvm-project/llvm/tools/bugpoint/OptimizerDriver.cpp
@@ -207,7 +207,7 @@ bool BugDriver::runPasses(Module &Program,
Args.push_back(OptArgs[i]);
// Pin to legacy PM since bugpoint has lots of infra and hacks revolving
// around the legacy PM.
- Args.push_back("-enable-new-pm=0");
+ Args.push_back("-bugpoint-enable-legacy-pm");
Args.push_back("-disable-symbolication");
Args.push_back("-o");
Args.push_back(OutputFilename);
diff --git a/contrib/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp b/contrib/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp
index 352588f01ac8..c6733aecd31d 100644
--- a/contrib/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp
+++ b/contrib/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp
@@ -612,7 +612,7 @@ static bool IsARMArchitecture(std::vector<StringRef> Args) {
++I;
if (I == Args.size())
break;
- if (Args[I].startswith_insensitive("arm"))
+ if (Args[I].starts_with_insensitive("arm"))
return true;
}
diff --git a/contrib/llvm-project/llvm/tools/bugpoint/ToolRunner.h b/contrib/llvm-project/llvm/tools/bugpoint/ToolRunner.h
index f6b5f26c7a66..c9da9afba0e4 100644
--- a/contrib/llvm-project/llvm/tools/bugpoint/ToolRunner.h
+++ b/contrib/llvm-project/llvm/tools/bugpoint/ToolRunner.h
@@ -16,11 +16,11 @@
#ifndef LLVM_TOOLS_BUGPOINT_TOOLRUNNER_H
#define LLVM_TOOLS_BUGPOINT_TOOLRUNNER_H
-#include "llvm/ADT/Triple.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SystemUtils.h"
+#include "llvm/TargetParser/Triple.h"
#include <exception>
#include <vector>
diff --git a/contrib/llvm-project/llvm/tools/bugpoint/bugpoint.cpp b/contrib/llvm-project/llvm/tools/bugpoint/bugpoint.cpp
index 0305f6463858..e49efdfe7c8e 100644
--- a/contrib/llvm-project/llvm/tools/bugpoint/bugpoint.cpp
+++ b/contrib/llvm-project/llvm/tools/bugpoint/bugpoint.cpp
@@ -30,7 +30,6 @@
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Valgrind.h"
#include "llvm/Transforms/IPO/AlwaysInliner.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
// Enable this macro to debug bugpoint itself.
//#define DEBUG_BUGPOINT 1
@@ -66,24 +65,6 @@ static cl::opt<bool>
static cl::list<const PassInfo *, bool, PassNameParser>
PassList(cl::desc("Passes available:"));
-static cl::opt<bool>
- OptLevelO1("O1", cl::desc("Optimization level 1. Identical to 'opt -O1'"));
-
-static cl::opt<bool>
- OptLevelO2("O2", cl::desc("Optimization level 2. Identical to 'opt -O2'"));
-
-static cl::opt<bool> OptLevelOs(
- "Os",
- cl::desc(
- "Like -O2 with extra optimizations for size. Similar to clang -Os"));
-
-static cl::opt<bool>
-OptLevelOz("Oz",
- cl::desc("Like -Os but reduces code size further. Similar to clang -Oz"));
-
-static cl::opt<bool>
- OptLevelO3("O3", cl::desc("Optimization level 3. Identical to 'opt -O3'"));
-
static cl::opt<std::string>
OverrideTriple("mtriple", cl::desc("Override target triple for module"));
@@ -110,26 +91,6 @@ public:
};
}
-// This routine adds optimization passes based on selected optimization level,
-// OptLevel.
-//
-// OptLevel - Optimization Level
-static void AddOptimizationPasses(legacy::FunctionPassManager &FPM,
- unsigned OptLevel,
- unsigned SizeLevel) {
- PassManagerBuilder Builder;
- Builder.OptLevel = OptLevel;
- Builder.SizeLevel = SizeLevel;
-
- if (OptLevel > 1)
- Builder.Inliner = createFunctionInliningPass(OptLevel, SizeLevel, false);
- else
- Builder.Inliner = createAlwaysInlinerLegacyPass();
-
- Builder.populateFunctionPassManager(FPM);
- Builder.populateModulePassManager(FPM);
-}
-
#define HANDLE_EXTENSION(Ext) \
llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
#include "llvm/Support/Extension.def"
@@ -195,17 +156,6 @@ int main(int argc, char **argv) {
AddToDriver PM(D);
- if (OptLevelO1)
- AddOptimizationPasses(PM, 1, 0);
- else if (OptLevelO2)
- AddOptimizationPasses(PM, 2, 0);
- else if (OptLevelO3)
- AddOptimizationPasses(PM, 3, 0);
- else if (OptLevelOs)
- AddOptimizationPasses(PM, 2, 1);
- else if (OptLevelOz)
- AddOptimizationPasses(PM, 2, 2);
-
for (const PassInfo *PI : PassList)
D.addPass(std::string(PI->getPassArgument()));
diff --git a/contrib/llvm-project/llvm/tools/llc/llc.cpp b/contrib/llvm-project/llvm/tools/llc/llc.cpp
index f2dae67040ff..8934130f9913 100644
--- a/contrib/llvm-project/llvm/tools/llc/llc.cpp
+++ b/contrib/llvm-project/llvm/tools/llc/llc.cpp
@@ -14,7 +14,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/CodeGen/LinkAllAsmWriterComponents.h"
@@ -36,7 +35,6 @@
#include "llvm/IRReader/IRReader.h"
#include "llvm/InitializePasses.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
-#include "llvm/MC/SubtargetFeature.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Pass.h"
#include "llvm/Remarks/HotnessThresholdParser.h"
@@ -44,7 +42,6 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/SourceMgr.h"
@@ -54,6 +51,9 @@
#include "llvm/Support/WithColor.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/SubtargetFeature.h"
+#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include <memory>
#include <optional>
@@ -107,10 +107,6 @@ static cl::opt<std::string>
"regardless of binutils support"));
static cl::opt<bool>
-NoIntegratedAssembler("no-integrated-as", cl::Hidden,
- cl::desc("Disable integrated assembler"));
-
-static cl::opt<bool>
PreserveComments("preserve-as-comments", cl::Hidden,
cl::desc("Preserve Comments in outputted assembly"),
cl::init(true));
@@ -366,7 +362,7 @@ int main(int argc, char **argv) {
initializeScalarizeMaskedMemIntrinLegacyPassPass(*Registry);
initializeExpandReductionsPass(*Registry);
initializeExpandVectorPredicationPass(*Registry);
- initializeHardwareLoopsPass(*Registry);
+ initializeHardwareLoopsLegacyPass(*Registry);
initializeTransformUtils(*Registry);
initializeReplaceWithVeclibLegacyPass(*Registry);
initializeTLSVariableHoistLegacyPassPass(*Registry);
@@ -496,9 +492,27 @@ static int compileModule(char **argv, LLVMContext &Context) {
TargetOptions Options;
auto InitializeOptions = [&](const Triple &TheTriple) {
Options = codegen::InitTargetOptionsFromCodeGenFlags(TheTriple);
+
+ if (Options.XCOFFReadOnlyPointers) {
+ if (!TheTriple.isOSAIX())
+ reportError("-mxcoff-roptr option is only supported on AIX",
+ InputFilename);
+
+ // Since the storage mapping class is specified per csect,
+ // without using data sections, it is less effective to use read-only
+ // pointers. Using read-only pointers may cause other RO variables in the
+ // same csect to become RW when the linker acts upon `-bforceimprw`;
+ // therefore, we require that separate data sections are used in the
+ // presence of ReadOnlyPointers. We respect the setting of data-sections
+ // since we have not found reasons to do otherwise that overcome the user
+ // surprise of not respecting the setting.
+ if (!Options.DataSections)
+ reportError("-mxcoff-roptr option must be used with -data-sections",
+ InputFilename);
+ }
+
Options.BinutilsVersion =
TargetMachine::parseBinutilsVersion(BinutilsVersion);
- Options.DisableIntegratedAS = NoIntegratedAssembler;
Options.MCOptions.ShowMCEncoding = ShowMCEncoding;
Options.MCOptions.AsmVerbose = AsmVerbose;
Options.MCOptions.PreserveAsmComments = PreserveComments;
@@ -680,13 +694,17 @@ static int compileModule(char **argv, LLVMContext &Context) {
if (!MIR) {
WithColor::warning(errs(), argv[0])
<< "run-pass is for .mir file only.\n";
+ delete MMIWP;
return 1;
}
- TargetPassConfig &TPC = *LLVMTM.createPassConfig(PM);
+ TargetPassConfig *PTPC = LLVMTM.createPassConfig(PM);
+ TargetPassConfig &TPC = *PTPC;
if (TPC.hasLimitedCodeGenPipeline()) {
WithColor::warning(errs(), argv[0])
<< "run-pass cannot be used with "
<< TPC.getLimitedCodeGenPipelineReason(" and ") << ".\n";
+ delete PTPC;
+ delete MMIWP;
return 1;
}
diff --git a/contrib/llvm-project/llvm/tools/lli/ExecutionUtils.h b/contrib/llvm-project/llvm/tools/lli/ExecutionUtils.h
index fcd1db05cca3..6bf9cd58e031 100644
--- a/contrib/llvm-project/llvm/tools/lli/ExecutionUtils.h
+++ b/contrib/llvm-project/llvm/tools/lli/ExecutionUtils.h
@@ -48,8 +48,8 @@ private:
std::unique_ptr<ToolOutputFile> TestOut;
template <typename T> void expose(orc::SymbolStringPtr Name, T *Handler) {
- BuiltinFunctions[Name] = JITEvaluatedSymbol(
- pointerToJITTargetAddress(Handler), JITSymbolFlags::Exported);
+ BuiltinFunctions[Name] = {orc::ExecutorAddr::fromPtr(Handler),
+ JITSymbolFlags::Exported};
}
static std::unique_ptr<ToolOutputFile> createToolOutput();
diff --git a/contrib/llvm-project/llvm/tools/lli/lli.cpp b/contrib/llvm-project/llvm/tools/lli/lli.cpp
index c9b77e23ba07..3b5250d56707 100644
--- a/contrib/llvm-project/llvm/tools/lli/lli.cpp
+++ b/contrib/llvm-project/llvm/tools/lli/lli.cpp
@@ -15,7 +15,6 @@
#include "ExecutionUtils.h"
#include "ForwardingMemoryManager.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
@@ -26,17 +25,13 @@
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
-#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
-#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
-#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
#include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h"
#include "llvm/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
-#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h"
#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
@@ -68,6 +63,7 @@
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Instrumentation.h"
#include <cerrno>
#include <optional>
@@ -236,20 +232,22 @@ namespace {
cl::desc("Do not resolve lli process symbols in JIT'd code"),
cl::init(false));
- enum class LLJITPlatform { Inactive, DetectHost, ORC, GenericIR };
-
- cl::opt<LLJITPlatform>
- Platform("lljit-platform", cl::desc("Platform to use with LLJIT"),
- cl::init(LLJITPlatform::DetectHost),
- cl::values(clEnumValN(LLJITPlatform::DetectHost, "DetectHost",
- "Select based on JIT target triple"),
- clEnumValN(LLJITPlatform::ORC, "ORC",
- "Use ORCPlatform with the ORC runtime"),
- clEnumValN(LLJITPlatform::GenericIR, "GenericIR",
- "Use LLJITGenericIRPlatform"),
- clEnumValN(LLJITPlatform::Inactive, "Inactive",
- "Disable platform support explicitly")),
- cl::Hidden);
+ enum class LLJITPlatform { Inactive, Auto, ExecutorNative, GenericIR };
+
+ cl::opt<LLJITPlatform> Platform(
+ "lljit-platform", cl::desc("Platform to use with LLJIT"),
+ cl::init(LLJITPlatform::Auto),
+ cl::values(clEnumValN(LLJITPlatform::Auto, "Auto",
+ "Like 'ExecutorNative' if ORC runtime "
+ "provided, otherwise like 'GenericIR'"),
+ clEnumValN(LLJITPlatform::ExecutorNative, "ExecutorNative",
+ "Use the native platform for the executor."
+ "Requires -orc-runtime"),
+ clEnumValN(LLJITPlatform::GenericIR, "GenericIR",
+ "Use LLJITGenericIRPlatform"),
+ clEnumValN(LLJITPlatform::Inactive, "Inactive",
+ "Disable platform support explicitly")),
+ cl::Hidden);
enum class DumpKind {
NoDump,
@@ -663,10 +661,6 @@ int main(int argc, char **argv, char * const *envp) {
#endif
}
- std::unique_ptr<orc::ExecutorProcessControl> EPC =
- RemoteMCJIT ? ExitOnErr(launchRemote())
- : ExitOnErr(orc::SelfExecutorProcessControl::Create());
-
if (!RemoteMCJIT) {
// If the program doesn't explicitly call exit, we will need the Exit
// function later on to make an explicit call, so get the function now.
@@ -712,6 +706,7 @@ int main(int argc, char **argv, char * const *envp) {
abort();
} else {
// else == "if (RemoteMCJIT)"
+ std::unique_ptr<orc::ExecutorProcessControl> EPC = ExitOnErr(launchRemote());
// Remote target MCJIT doesn't (yet) support static constructors. No reason
// it couldn't. This is a limitation of the LLI implementation, not the
@@ -829,6 +824,20 @@ loadModule(StringRef Path, orc::ThreadSafeContext TSCtx) {
return orc::ThreadSafeModule(std::move(M), std::move(TSCtx));
}
+int mingw_noop_main(void) {
+ // Cygwin and MinGW insert calls from the main function to the runtime
+ // function __main. The __main function is responsible for setting up main's
+ // environment (e.g. running static constructors), however this is not needed
+ // when running under lli: the executor process will have run non-JIT ctors,
+ // and ORC will take care of running JIT'd ctors. To avoid a missing symbol
+ // error we just implement __main as a no-op.
+ //
+ // FIXME: Move this to ORC-RT (and the ORC-RT substitution library once it
+ // exists). That will allow it to work out-of-process, and for all
+ // ORC tools (the problem isn't lli specific).
+ return 0;
+}
+
int runOrcJIT(const char *ProgName) {
// Start setting up the JIT environment.
@@ -867,6 +876,9 @@ int runOrcJIT(const char *ProgName) {
.setRelocationModel(codegen::getExplicitRelocModel())
.setCodeModel(codegen::getExplicitCodeModel());
+ // Link process symbols unless NoProcessSymbols is set.
+ Builder.setLinkProcessSymbolsByDefault(!NoProcessSymbols);
+
// FIXME: Setting a dummy call-through manager in non-lazy mode prevents the
// JIT builder to instantiate a default (which would fail with an error for
// unsupported architectures).
@@ -874,7 +886,8 @@ int runOrcJIT(const char *ProgName) {
auto ES = std::make_unique<orc::ExecutionSession>(
ExitOnErr(orc::SelfExecutorProcessControl::Create()));
Builder.setLazyCallthroughManager(
- std::make_unique<orc::LazyCallThroughManager>(*ES, 0, nullptr));
+ std::make_unique<orc::LazyCallThroughManager>(*ES, orc::ExecutorAddr(),
+ nullptr));
Builder.setExecutionSession(std::move(ES));
}
@@ -907,17 +920,15 @@ int runOrcJIT(const char *ProgName) {
// Set up LLJIT platform.
LLJITPlatform P = Platform;
- if (P == LLJITPlatform::DetectHost) {
- if (JITLinker == JITLinkerKind::JITLink && !OrcRuntime.empty() &&
- (TT->isOSBinFormatMachO() || TT->isOSBinFormatELF()))
- P = LLJITPlatform::ORC;
- else
- P = LLJITPlatform::GenericIR;
- }
+ if (P == LLJITPlatform::Auto)
+ P = OrcRuntime.empty() ? LLJITPlatform::GenericIR
+ : LLJITPlatform::ExecutorNative;
+
switch (P) {
- case LLJITPlatform::ORC:
- Builder.setPlatformSetUp(orc::setUpOrcPlatform);
+ case LLJITPlatform::ExecutorNative: {
+ Builder.setPlatformSetUp(orc::ExecutorNativePlatform(OrcRuntime));
break;
+ }
case LLJITPlatform::GenericIR:
// Nothing to do: LLJITBuilder will use this by default.
break;
@@ -936,22 +947,35 @@ int runOrcJIT(const char *ProgName) {
Builder.setObjectLinkingLayerCreator([&EPC, &P](orc::ExecutionSession &ES,
const Triple &TT) {
auto L = std::make_unique<orc::ObjectLinkingLayer>(ES, EPC->getMemMgr());
- if (P != LLJITPlatform::ORC) {
+ if (P != LLJITPlatform::ExecutorNative)
L->addPlugin(std::make_unique<orc::EHFrameRegistrationPlugin>(
ES, ExitOnErr(orc::EPCEHFrameRegistrar::Create(ES))));
- L->addPlugin(std::make_unique<orc::DebugObjectManagerPlugin>(
- ES, ExitOnErr(orc::createJITLoaderGDBRegistrar(ES))));
- }
return L;
});
}
+ // Enable debugging of JIT'd code (only works on JITLink for ELF and MachO).
+ Builder.setEnableDebuggerSupport(true);
+
auto J = ExitOnErr(Builder.create());
auto *ObjLayer = &J->getObjLinkingLayer();
- if (auto *RTDyldObjLayer = dyn_cast<orc::RTDyldObjectLinkingLayer>(ObjLayer))
+ if (auto *RTDyldObjLayer = dyn_cast<orc::RTDyldObjectLinkingLayer>(ObjLayer)) {
RTDyldObjLayer->registerJITEventListener(
*JITEventListener::createGDBRegistrationListener());
+#if LLVM_USE_OPROFILE
+ RTDyldObjLayer->registerJITEventListener(
+ *JITEventListener::createOProfileJITEventListener());
+#endif
+#if LLVM_USE_INTEL_JITEVENTS
+ RTDyldObjLayer->registerJITEventListener(
+ *JITEventListener::createIntelJITEventListener());
+#endif
+#if LLVM_USE_PERF
+ RTDyldObjLayer->registerJITEventListener(
+ *JITEventListener::createPerfJITEventListener());
+#endif
+ }
if (PerModuleLazy)
J->setPartitionFunction(orc::CompileOnDemandLayer::compileWholeModule);
@@ -971,48 +995,22 @@ int runOrcJIT(const char *ProgName) {
return TSM;
});
- orc::MangleAndInterner Mangle(J->getExecutionSession(), J->getDataLayout());
-
- // Unless they've been explicitly disabled, make process symbols available to
- // JIT'd code.
- if (!NoProcessSymbols)
- J->getMainJITDylib().addGenerator(
- ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
- J->getDataLayout().getGlobalPrefix(),
- [MainName = Mangle("main")](const orc::SymbolStringPtr &Name) {
- return Name != MainName;
- })));
-
- if (GenerateBuiltinFunctions.size() > 0)
+ if (GenerateBuiltinFunctions.size() > 0) {
+ // Add LLI builtins.
+ orc::MangleAndInterner Mangle(J->getExecutionSession(), J->getDataLayout());
J->getMainJITDylib().addGenerator(
std::make_unique<LLIBuiltinFunctionGenerator>(GenerateBuiltinFunctions,
Mangle));
-
- if (P == LLJITPlatform::ORC) {
- if (auto *OLL = llvm::dyn_cast<llvm::orc::ObjectLinkingLayer>(ObjLayer)) {
- auto &ES = J->getExecutionSession();
- if (TT->isOSBinFormatMachO()) {
- if (auto P = llvm::orc::MachOPlatform::Create(
- ES, *OLL, J->getMainJITDylib(), OrcRuntime.c_str()))
- ES.setPlatform(std::move(*P));
- else
- ExitOnErr(P.takeError());
- } else if (TT->isOSBinFormatELF()) {
- if (auto P = llvm::orc::ELFNixPlatform::Create(
- ES, *OLL, J->getMainJITDylib(), OrcRuntime.c_str()))
- ES.setPlatform(std::move(*P));
- else
- ExitOnErr(P.takeError());
- } else {
- errs() << "No ORC platform support\n";
- exit(1);
- }
- } else {
- errs() << "ORC platform requires JITLink\n";
- exit(1);
- }
}
+ // If this is a Mingw or Cygwin executor then we need to alias __main to
+ // orc_rt_int_void_return_0.
+ if (J->getTargetTriple().isOSCygMing())
+ ExitOnErr(J->getProcessSymbolsJITDylib()->define(
+ orc::absoluteSymbols({{J->mangleAndIntern("__main"),
+ {orc::ExecutorAddr::fromPtr(mingw_noop_main),
+ JITSymbolFlags::Exported}}})));
+
// Regular modules are greedy: They materialize as a whole and trigger
// materialization for all required symbols recursively. Lazy modules go
// through partitioning and they replace outgoing calls with reexport stubs
@@ -1060,8 +1058,7 @@ int runOrcJIT(const char *ProgName) {
assert(EAIdx != 0 && "ExtraArchive should have index > 0");
auto JDItr = std::prev(IdxToDylib.lower_bound(EAIdx));
auto &JD = *JDItr->second;
- JD.addGenerator(ExitOnErr(orc::StaticLibraryDefinitionGenerator::Load(
- J->getObjLinkingLayer(), EAItr->c_str(), *TT)));
+ ExitOnErr(J->linkStaticLibraryInto(JD, EAItr->c_str()));
}
}
@@ -1181,3 +1178,41 @@ Expected<std::unique_ptr<orc::ExecutorProcessControl>> launchRemote() {
llvm::orc::SimpleRemoteEPC::Setup(), PipeFD[1][0], PipeFD[0][1]);
#endif
}
+
+// For MinGW environments, manually export the __chkstk function from the lli
+// executable.
+//
+// Normally, this function is provided by compiler-rt builtins or libgcc.
+// It is named "_alloca" on i386, "___chkstk_ms" on x86_64, and "__chkstk" on
+// arm/aarch64. In MSVC configurations, it's named "__chkstk" in all
+// configurations.
+//
+// When Orc tries to resolve symbols at runtime, this succeeds in MSVC
+// configurations, somewhat by accident/luck; kernelbase.dll does export a
+// symbol named "__chkstk" which gets found by Orc, even if regular applications
+// never link against that function from that DLL (it's linked in statically
+// from a compiler support library).
+//
+// The MinGW specific symbol names aren't available in that DLL though.
+// Therefore, manually export the relevant symbol from lli, to let it be
+// found at runtime during tests.
+//
+// For real JIT uses, the real compiler support libraries should be linked
+// in, somehow; this is a workaround to let tests pass.
+//
+// TODO: Move this into libORC at some point, see
+// https://github.com/llvm/llvm-project/issues/56603.
+#ifdef __MINGW32__
+// This is a MinGW version of #pragma comment(linker, "...") that doesn't
+// require compiling with -fms-extensions.
+#if defined(__i386__)
+static __attribute__((section(".drectve"), used)) const char export_chkstk[] =
+ "-export:_alloca";
+#elif defined(__x86_64__)
+static __attribute__((section(".drectve"), used)) const char export_chkstk[] =
+ "-export:___chkstk_ms";
+#else
+static __attribute__((section(".drectve"), used)) const char export_chkstk[] =
+ "-export:__chkstk";
+#endif
+#endif
diff --git a/contrib/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp b/contrib/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp
index 12f3196a9844..d21650d146a9 100644
--- a/contrib/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -13,20 +13,11 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ArchiveWriter.h"
-#include "llvm/Object/COFFImportFile.h"
-#include "llvm/Object/ELFObjectFile.h"
-#include "llvm/Object/IRObjectFile.h"
-#include "llvm/Object/MachO.h"
-#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolicFile.h"
-#include "llvm/Object/TapiFile.h"
-#include "llvm/Object/Wasm.h"
-#include "llvm/Object/XCOFFObjectFile.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
@@ -34,8 +25,8 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LLVMDriver.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
@@ -45,6 +36,8 @@
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/Triple.h"
#include "llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h"
#include "llvm/ToolDrivers/llvm-lib/LibDriver.h"
@@ -646,31 +639,12 @@ static bool shouldCreateArchive(ArchiveOperation Op) {
llvm_unreachable("Missing entry in covered switch.");
}
-static bool is64BitSymbolicFile(SymbolicFile &Obj) {
- if (auto *IRObj = dyn_cast<IRObjectFile>(&Obj))
- return Triple(IRObj->getTargetTriple()).isArch64Bit();
- if (isa<COFFObjectFile>(Obj) || isa<COFFImportFile>(Obj))
- return false;
- if (XCOFFObjectFile *XCOFFObj = dyn_cast<XCOFFObjectFile>(&Obj))
- return XCOFFObj->is64Bit();
- if (isa<WasmObjectFile>(Obj))
- return false;
- if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj))
- return Tapi->is64Bit();
- if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))
- return MachO->is64Bit();
- if (ELFObjectFileBase *ElfO = dyn_cast<ELFObjectFileBase>(&Obj))
- return ElfO->getBytesInAddress() == 8;
-
- fail("unsupported file format");
-}
-
static bool isValidInBitMode(Binary &Bin) {
if (BitMode == BitModeTy::Bit32_64 || BitMode == BitModeTy::Any)
return true;
if (SymbolicFile *SymFile = dyn_cast<SymbolicFile>(&Bin)) {
- bool Is64Bit = is64BitSymbolicFile(*SymFile);
+ bool Is64Bit = SymFile->is64Bit();
if ((Is64Bit && (BitMode == BitModeTy::Bit32)) ||
(!Is64Bit && (BitMode == BitModeTy::Bit64)))
return false;
@@ -1452,7 +1426,7 @@ static int ranlib_main(int argc, char **argv) {
return 0;
}
-int llvm_ar_main(int argc, char **argv) {
+int llvm_ar_main(int argc, char **argv, const llvm::ToolContext &) {
InitLLVM X(argc, argv);
ToolName = argv[0];
diff --git a/contrib/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp b/contrib/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
index 7b71d5ad4554..02448dcd31a1 100644
--- a/contrib/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -22,7 +22,6 @@
#include "SourceCoverageView.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Debuginfod/BuildIDFetcher.h"
#include "llvm/Debuginfod/Debuginfod.h"
#include "llvm/Debuginfod/HTTPClient.h"
@@ -42,6 +41,7 @@
#include "llvm/Support/Threading.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/TargetParser/Triple.h"
#include <functional>
#include <map>
@@ -185,6 +185,8 @@ private:
std::unique_ptr<SpecialCaseList> NameAllowlist;
std::unique_ptr<object::BuildIDFetcher> BIDFetcher;
+
+ bool CheckBinaryIDs;
};
}
@@ -439,9 +441,10 @@ std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
if (modifiedTimeGT(ObjectFilename, PGOFilename))
warning("profile data may be out of date - object is newer",
ObjectFilename);
- auto CoverageOrErr =
- CoverageMapping::load(ObjectFilenames, PGOFilename, CoverageArches,
- ViewOpts.CompilationDirectory, BIDFetcher.get());
+ auto FS = vfs::getRealFileSystem();
+ auto CoverageOrErr = CoverageMapping::load(
+ ObjectFilenames, PGOFilename, *FS, CoverageArches,
+ ViewOpts.CompilationDirectory, BIDFetcher.get(), CheckBinaryIDs);
if (Error E = CoverageOrErr.takeError()) {
error("Failed to load coverage: " + toString(std::move(E)));
return nullptr;
@@ -760,6 +763,10 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
"compilation-dir", cl::init(""),
cl::desc("Directory used as a base for relative coverage mapping paths"));
+ cl::opt<bool> CheckBinaryIDs(
+ "check-binary-ids", cl::desc("Fail if an object couldn't be found for a "
+ "binary ID in the profile"));
+
auto commandLineParser = [&, this](int argc, const char **argv) -> int {
cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
ViewOpts.Debug = DebugDump;
@@ -769,6 +776,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
} else {
BIDFetcher = std::make_unique<object::BuildIDFetcher>(DebugFileDirectory);
}
+ this->CheckBinaryIDs = CheckBinaryIDs;
if (!CovFilename.empty())
ObjectFilenames.emplace_back(CovFilename);
diff --git a/contrib/llvm-project/llvm/tools/llvm-cov/CoverageReport.cpp b/contrib/llvm-project/llvm/tools/llvm-cov/CoverageReport.cpp
index be042aa9e027..cb0b184e103c 100644
--- a/contrib/llvm-project/llvm/tools/llvm-cov/CoverageReport.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-cov/CoverageReport.cpp
@@ -13,6 +13,7 @@
#include "CoverageReport.h"
#include "RenderingSupport.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ThreadPool.h"
diff --git a/contrib/llvm-project/llvm/tools/llvm-cov/llvm-cov.cpp b/contrib/llvm-project/llvm/tools/llvm-cov/llvm-cov.cpp
index 45de2afb0855..5ada55789b24 100644
--- a/contrib/llvm-project/llvm/tools/llvm-cov/llvm-cov.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-cov/llvm-cov.cpp
@@ -59,7 +59,7 @@ int main(int argc, const char **argv) {
InitLLVM X(argc, argv);
// If argv[0] is or ends with 'gcov', always be gcov compatible
- if (sys::path::stem(argv[0]).endswith_insensitive("gcov"))
+ if (sys::path::stem(argv[0]).ends_with_insensitive("gcov"))
return gcovMain(argc, argv);
// Check if we are invoking a specific tool command.
diff --git a/contrib/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/contrib/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
index 06f0a25c0dff..2bbd57f14d99 100644
--- a/contrib/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
@@ -7,16 +7,18 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Demangle/Demangle.h"
+#include "llvm/Demangle/StringViewExtras.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LLVMDriver.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/Triple.h"
#include <cstdlib>
#include <iostream>
@@ -70,10 +72,11 @@ static void error(const Twine &Message) {
}
static std::string demangle(const std::string &Mangled) {
- const char *DecoratedStr = Mangled.c_str();
+ using llvm::itanium_demangle::starts_with;
+ std::string_view DecoratedStr = Mangled;
if (StripUnderscore)
if (DecoratedStr[0] == '_')
- ++DecoratedStr;
+ DecoratedStr.remove_prefix(1);
std::string Result;
if (nonMicrosoftDemangle(DecoratedStr, Result))
@@ -83,11 +86,11 @@ static std::string demangle(const std::string &Mangled) {
char *Undecorated = nullptr;
if (Types)
- Undecorated = itaniumDemangle(DecoratedStr, nullptr, nullptr, nullptr);
+ Undecorated = itaniumDemangle(DecoratedStr);
- if (!Undecorated && strncmp(DecoratedStr, "__imp_", 6) == 0) {
+ if (!Undecorated && starts_with(DecoratedStr, "__imp_")) {
Prefix = "import thunk for ";
- Undecorated = itaniumDemangle(DecoratedStr + 6, nullptr, nullptr, nullptr);
+ Undecorated = itaniumDemangle(DecoratedStr.substr(6));
}
Result = Undecorated ? Prefix + Undecorated : Mangled;
@@ -145,7 +148,7 @@ static void demangleLine(llvm::raw_ostream &OS, StringRef Mangled, bool Split) {
OS.flush();
}
-int llvm_cxxfilt_main(int argc, char **argv) {
+int llvm_cxxfilt_main(int argc, char **argv, const llvm::ToolContext &) {
InitLLVM X(argc, argv);
BumpPtrAllocator A;
StringSaver Saver(A);
diff --git a/contrib/llvm-project/llvm/tools/llvm-cxxmap/llvm-cxxmap.cpp b/contrib/llvm-project/llvm/tools/llvm-cxxmap/llvm-cxxmap.cpp
index 1e18e379f23c..6a5646965df2 100644
--- a/contrib/llvm-project/llvm/tools/llvm-cxxmap/llvm-cxxmap.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-cxxmap/llvm-cxxmap.cpp
@@ -14,12 +14,12 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ProfileData/SymbolRemappingReader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/SymbolRemappingReader.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/contrib/llvm-project/llvm/tools/llvm-debuginfo-analyzer/README.txt b/contrib/llvm-project/llvm/tools/llvm-debuginfo-analyzer/README.txt
new file mode 100644
index 000000000000..e6c20db7cd71
--- /dev/null
+++ b/contrib/llvm-project/llvm/tools/llvm-debuginfo-analyzer/README.txt
@@ -0,0 +1,224 @@
+//===- llvm/tools/llvm-debuginfo-analyzer/README.txt ----------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains notes collected during the development, review and test.
+// It describes limitations, know issues and future work.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Remove the use of macros in 'LVReader.h' that describe the bumpallocators.
+//===----------------------------------------------------------------------===//
+https://reviews.llvm.org/D137933#inline-1389904
+
+Use a standard (or LLVM) map with typeinfo (would need a specialization
+to expose equality and hasher) for the allocators and the creation
+functions could be a function template.
+
+//===----------------------------------------------------------------------===//
+// Use a lit test instead of a unit test for the logical readers.
+//===----------------------------------------------------------------------===//
+https://reviews.llvm.org/D125783#inline-1324376
+
+As the DebugInfoLogicalView library is sufficiently exposed via the
+llvm-debuginfo-analyzer tool, follow the LLVM general approach and
+use LIT tests to validate the logical readers.
+
+Convert the unitests:
+ llvm-project/llvm/unittests/DebugInfo/LogicalView/CodeViewReaderTest.cpp
+ llvm-project/llvm/unittests/DebugInfo/LogicalView/ELFReaderTest.cpp
+
+into LIT tests:
+ llvm-project/llvm/test/DebugInfo/LogicalView/CodeViewReader.test
+ llvm-project/llvm/test/DebugInfo/LogicalView/ELFReader.test
+
+//===----------------------------------------------------------------------===//
+// Eliminate calls to 'getInputFileDirectory()' in the unit tests.
+//===----------------------------------------------------------------------===//
+https://reviews.llvm.org/D125783#inline-1324359
+
+Rewrite the unittests 'LFReaderTest' and 'CodeViewReaderTest'to eliminate
+the call:
+
+ getInputFileDirectory()
+
+as use of that call is discouraged.
+
+See: Use a lit test instead of a unit test for the logical readers.
+
+//===----------------------------------------------------------------------===//
+// Fix mismatch between %d/%x format strings and uint64_t type.
+//===----------------------------------------------------------------------===//
+https://reviews.llvm.org/D137400
+https://github.com/llvm/llvm-project/issues/58758
+
+Incorrect printing of uint64_t on 32-bit platforms.
+Add the PRIx64 specifier to the printing code (format()).
+
+//===----------------------------------------------------------------------===//
+// Remove 'LVScope::Children' container.
+//===----------------------------------------------------------------------===//
+https://reviews.llvm.org/D137933#inline-1373902
+
+Use a chaining iterator over the other containers rather than keep a
+separate container 'Children' that mirrors their contents.
+
+//===----------------------------------------------------------------------===//
+// Use TableGen for command line options.
+//===----------------------------------------------------------------------===//
+https://reviews.llvm.org/D125777#inline-1291801
+
+The current trend is to use TableGen for command-line options in tools.
+Change command line options to use tablegen as many other LLVM tools.
+
+//===----------------------------------------------------------------------===//
+// LVDoubleMap to return optional<ValueType> instead of null pointer.
+//===----------------------------------------------------------------------===//
+https://reviews.llvm.org/D125783#inline-1294164
+
+The more idiomatic LLVM way to handle this would be to have 'find '
+return Optional<ValueType>.
+
+//===----------------------------------------------------------------------===//
+// Pass references instead of pointers (Comparison functions).
+//===----------------------------------------------------------------------===//
+https://reviews.llvm.org/D125782#inline-1293920
+
+In the comparison functions, pass references instead of pointers (when
+pointers cannot be null).
+
+//===----------------------------------------------------------------------===//
+// Use StringMap where possible.
+//===----------------------------------------------------------------------===//
+https://reviews.llvm.org/D125783#inline-1294211
+
+LLVM has a StringMap class that is advertised as more efficient than
+std::map<std::string, ValueType>. Mainly it does fewer allocations
+because the key is not a std::string.
+
+Replace the use of std::map<std::string, ValueType> with String Map.
+One specific case is the LVSymbolNames definitions.
+
+//===----------------------------------------------------------------------===//
+// Calculate unique offset for CodeView elements.
+//===----------------------------------------------------------------------===//
+In order to have the same logical functionality as the ELF Reader, such
+as:
+
+- find scopes contribution to debug info
+- sort by its physical location
+
+The logical elements must have an unique offset (similar like the DWARF
+DIE offset).
+
+//===----------------------------------------------------------------------===//
+// Move 'initializeFileAndStringTables' to the COFF Library.
+//===----------------------------------------------------------------------===//
+There is some code in the CodeView reader that was extracted/adapted
+from 'tools/llvm-readobj/COFFDumper.cpp' that can be moved to the COFF
+library.
+
+We had a similar case with code shared with llvm-pdbutil that was moved
+to the PDB library: https://reviews.llvm.org/D122226
+
+//===----------------------------------------------------------------------===//
+// Move 'getSymbolKindName'/'formatRegisterId' to the CodeView Library.
+//===----------------------------------------------------------------------===//
+There is some code in the CodeView reader that was extracted/adapted
+from 'lib/DebugInfo/CodeView/SymbolDumper.cpp' that can be used.
+
+//===----------------------------------------------------------------------===//
+// Use of std::unordered_set instead of std::set.
+//===----------------------------------------------------------------------===//
+https://reviews.llvm.org/D125784#inline-1221421
+
+Replace the std::set usage for DeducedScopes, UnresolvedScopes and
+IdentifiedNamespaces with std::unordered_set and get the benefit
+of the O(1) while inserting/searching, as the order is not important.
+
+//===----------------------------------------------------------------------===//
+// Optimize 'LVNamespaceDeduction::find' funtion.
+//===----------------------------------------------------------------------===//
+https://reviews.llvm.org/D125784#inline-1296195
+
+Optimize the 'find' method to use the proposed code:
+
+ LVStringRefs::iterator Iter = std::find_if(Components.begin(), Components.end(),
+ [](StringRef Name) {
+ return IdentifiedNamespaces.find(Name) == IdentifiedNamespaces.end();
+ });
+ LVStringRefs::size_type FirstNonNamespace = std::distance(Components.begin(), Iter);
+
+//===----------------------------------------------------------------------===//
+// Move all the printing support to a common module.
+//===----------------------------------------------------------------------===//
+Factor out printing functionality from the logical elements into a
+common module.
+
+//===----------------------------------------------------------------------===//
+// Refactor 'LVBinaryReader::processLines'.
+//===----------------------------------------------------------------------===//
+https://reviews.llvm.org/D125783#inline-1246155
+https://reviews.llvm.org/D137156
+
+During the traversal of the debug information sections, we created the
+logical lines representing the disassembled instructions from the text
+section and the logical lines representing the line records from the
+debug line section. Using the ranges associated with the logical scopes,
+we will allocate those logical lines to their logical scopes.
+
+Consider the case when any of those lines become orphans, causing
+incorrect scope parent for disassembly or line records.
+
+//===----------------------------------------------------------------------===//
+// Add support for '-ffunction-sections'.
+//===----------------------------------------------------------------------===//
+https://reviews.llvm.org/D125783#inline-1295012
+
+Only linked executables are handled. It does not support relocatable
+files compiled with -ffunction-sections.
+
+//===----------------------------------------------------------------------===//
+// Add support for DWARF v5 .debug_names section.
+// Add support for CodeView public symbols stream.
+//===----------------------------------------------------------------------===//
+https://reviews.llvm.org/D125783#inline-1294142
+
+The ELF and CodeView readers use the public names information to create
+the instructions (LVLineAssembler). Instead of relying on DWARF section
+names (.debug_pubnames, .debug_names) and CodeView public symbol stream
+(S_PUB32), the readers collects the needed information while processing
+the debug information.
+
+If the object file supports the above section names and stream, use them
+to create the public names.
+
+//===----------------------------------------------------------------------===//
+// Add support for some extra DWARF locations.
+//===----------------------------------------------------------------------===//
+The following DWARF debug location operands are not supported:
+
+- DW_OP_const_type
+- DW_OP_entry_value
+- DW_OP_implicit_value
+
+//===----------------------------------------------------------------------===//
+// Add support for additional binary formats.
+//===----------------------------------------------------------------------===//
+- WebAssembly (Wasm).
+ https://github.com/llvm/llvm-project/issues/57040#issuecomment-1211336680
+
+- Extended COFF (XCOFF)
+
+//===----------------------------------------------------------------------===//
+// Add support for JSON or YAML.
+//===----------------------------------------------------------------------===//
+The logical view uses its own and non-standard free form text when
+displaying information on logical elements.
+
+//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/contrib/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 27330a571bbe..156e10c84ddd 100644
--- a/contrib/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -11,9 +11,10 @@
//===----------------------------------------------------------------------===//
#include "llvm-dwarfdump.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
@@ -26,6 +27,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
@@ -34,6 +36,7 @@
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Triple.h"
#include <cstdlib>
using namespace llvm;
@@ -171,6 +174,10 @@ static list<std::string>
value_desc("name"), cat(DwarfDumpCategory));
static alias FindAlias("f", desc("Alias for --find."), aliasopt(Find),
cl::NotHidden);
+static opt<bool> FindAllApple(
+ "find-all-apple",
+ desc("Print every debug information entry in the accelerator tables."),
+ cat(DwarfDumpCategory));
static opt<bool> IgnoreCase("ignore-case",
desc("Ignore case distinctions when using --name."),
value_desc("i"), cat(DwarfDumpCategory));
@@ -453,6 +460,37 @@ static void filterByAccelName(
Die.dump(OS, 0, DumpOpts);
}
+/// Print all DIEs in apple accelerator tables
+static void findAllApple(
+ DWARFContext &DICtx, raw_ostream &OS,
+ std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
+ MapVector<StringRef, llvm::SmallSet<DWARFDie, 2>> NameToDies;
+
+ auto PushDIEs = [&](const AppleAcceleratorTable &Accel) {
+ for (const auto &Entry : Accel.entries()) {
+ if (std::optional<uint64_t> Off = Entry.BaseEntry.getDIESectionOffset()) {
+ std::optional<StringRef> MaybeName = Entry.readName();
+ DWARFDie Die = DICtx.getDIEForOffset(*Off);
+ if (Die && MaybeName)
+ NameToDies[*MaybeName].insert(Die);
+ }
+ }
+ };
+
+ PushDIEs(DICtx.getAppleNames());
+ PushDIEs(DICtx.getAppleNamespaces());
+ PushDIEs(DICtx.getAppleTypes());
+
+ DIDumpOptions DumpOpts = getDumpOpts(DICtx);
+ DumpOpts.GetNameForDWARFReg = GetNameForDWARFReg;
+ for (const auto &[Name, Dies] : NameToDies) {
+ OS << llvm::formatv("\nApple accelerator entries with name = \"{0}\":\n",
+ Name);
+ for (DWARFDie Die : Dies)
+ Die.dump(OS, 0, DumpOpts);
+ }
+}
+
/// Handle the --lookup option and dump the DIEs and line info for the given
/// address.
/// TODO: specified Address for --lookup option could relate for several
@@ -625,6 +663,12 @@ static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
return true;
}
+ // Handle the --find-all-apple option and lower it to --debug-info=<offset>.
+ if (FindAllApple) {
+ findAllApple(DICtx, OS, GetRegName);
+ return true;
+ }
+
// Dump the complete DWARF structure.
auto DumpOpts = getDumpOpts(DICtx);
DumpOpts.GetNameForDWARFReg = GetRegName;
@@ -782,7 +826,7 @@ int main(int argc, char **argv) {
// Unless dumping a specific DIE, default to --show-children.
if (!ShowChildren && !Verify && !OffsetRequested && Name.empty() &&
- Find.empty())
+ Find.empty() && !FindAllApple)
ShowChildren = true;
// Defaults to a.out if no filenames specified.
diff --git a/contrib/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/contrib/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
index ef222f8cc1a4..47a23e8448cc 100644
--- a/contrib/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
@@ -11,6 +11,7 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/DWARFLinker/DWARFLinker.h"
#include "llvm/DWARFLinker/DWARFStreamer.h"
+#include "llvm/DWARFLinkerParallel/DWARFLinker.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
#include "llvm/Object/ObjectFile.h"
@@ -37,11 +38,12 @@ namespace dwarfutil {
// exec: [LowPC, HighPC] is not inside address ranges of .text sections
//
// universal: maxpc and bfd
-class ObjFileAddressMap : public AddressesMap {
+template <typename AddressMapBase>
+class ObjFileAddressMap : public AddressMapBase {
public:
ObjFileAddressMap(DWARFContext &Context, const Options &Options,
object::ObjectFile &ObjFile)
- : Opts(Options), Context(Context) {
+ : Opts(Options) {
// Remember addresses of existing text sections.
for (const object::SectionRef &Sect : ObjFile.sections()) {
if (!Sect.isText())
@@ -57,21 +59,29 @@ public:
for (std::unique_ptr<DWARFUnit> &CU : Context.compile_units()) {
Expected<llvm::DWARFAddressRangesVector> ARanges =
CU->getUnitDIE().getAddressRanges();
- if (ARanges) {
- for (auto &Range : *ARanges) {
- if (!isDeadAddressRange(Range.LowPC, Range.HighPC, CU->getVersion(),
- Options.Tombstone, CU->getAddressByteSize()))
- DWARFAddressRanges.insert({Range.LowPC, Range.HighPC}, 0);
+ if (!ARanges) {
+ llvm::consumeError(ARanges.takeError());
+ continue;
+ }
+
+ for (auto &Range : *ARanges) {
+ if (!isDeadAddressRange(Range.LowPC, Range.HighPC, CU->getVersion(),
+ Options.Tombstone, CU->getAddressByteSize())) {
+ HasValidAddressRanges = true;
+ break;
}
}
+
+ if (HasValidAddressRanges)
+ break;
}
}
// should be renamed into has valid address ranges
- bool hasValidRelocs() override { return !DWARFAddressRanges.empty(); }
+ bool hasValidRelocs() override { return HasValidAddressRanges; }
- bool isLiveSubprogram(const DWARFDie &DIE,
- CompileUnit::DIEInfo &Info) override {
+ std::optional<int64_t>
+ getSubprogramRelocAdjustment(const DWARFDie &DIE) override {
assert((DIE.getTag() == dwarf::DW_TAG_subprogram ||
DIE.getTag() == dwarf::DW_TAG_label) &&
"Wrong type of input die");
@@ -80,53 +90,44 @@ public:
dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc))) {
if (!isDeadAddress(*LowPC, DIE.getDwarfUnit()->getVersion(),
Opts.Tombstone,
- DIE.getDwarfUnit()->getAddressByteSize())) {
- Info.AddrAdjust = 0;
- Info.InDebugMap = true;
- return true;
- }
+ DIE.getDwarfUnit()->getAddressByteSize()))
+ // Relocation value for the linked binary is 0.
+ return 0;
}
- return false;
+ return std::nullopt;
}
- bool isLiveVariable(const DWARFDie &DIE,
- CompileUnit::DIEInfo &Info) override {
- assert((DIE.getTag() == dwarf::DW_TAG_variable ||
- DIE.getTag() == dwarf::DW_TAG_constant) &&
- "Wrong type of input die");
-
- if (Expected<DWARFLocationExpressionsVector> Loc =
- DIE.getLocations(dwarf::DW_AT_location)) {
- DWARFUnit *U = DIE.getDwarfUnit();
- for (const auto &Entry : *Loc) {
- DataExtractor Data(toStringRef(Entry.Expr),
- U->getContext().isLittleEndian(), 0);
- DWARFExpression Expression(Data, U->getAddressByteSize(),
- U->getFormParams().Format);
- bool HasLiveAddresses =
- any_of(Expression, [&](const DWARFExpression::Operation &Op) {
- // TODO: add handling of dwarf::DW_OP_addrx
- return !Op.isError() &&
- (Op.getCode() == dwarf::DW_OP_addr &&
- !isDeadAddress(Op.getRawOperand(0), U->getVersion(),
- Opts.Tombstone,
- DIE.getDwarfUnit()->getAddressByteSize()));
- });
-
- if (HasLiveAddresses) {
- Info.AddrAdjust = 0;
- Info.InDebugMap = true;
- return true;
- }
+ std::optional<int64_t> getExprOpAddressRelocAdjustment(
+ DWARFUnit &U, const DWARFExpression::Operation &Op, uint64_t StartOffset,
+ uint64_t EndOffset) override {
+ switch (Op.getCode()) {
+ default: {
+ assert(false && "Specified operation does not have address operand");
+ } break;
+ case dwarf::DW_OP_const4u:
+ case dwarf::DW_OP_const8u:
+ case dwarf::DW_OP_const4s:
+ case dwarf::DW_OP_const8s:
+ case dwarf::DW_OP_addr: {
+ if (!isDeadAddress(Op.getRawOperand(0), U.getVersion(), Opts.Tombstone,
+ U.getAddressByteSize()))
+ // Relocation value for the linked binary is 0.
+ return 0;
+ } break;
+ case dwarf::DW_OP_constx:
+ case dwarf::DW_OP_addrx: {
+ if (std::optional<object::SectionedAddress> Address =
+ U.getAddrOffsetSectionItem(Op.getRawOperand(0))) {
+ if (!isDeadAddress(Address->Address, U.getVersion(), Opts.Tombstone,
+ U.getAddressByteSize()))
+ // Relocation value for the linked binary is 0.
+ return 0;
}
- } else {
- // FIXME: missing DW_AT_location is OK here, but other errors should be
- // reported to the user.
- consumeError(Loc.takeError());
+ } break;
}
- return false;
+ return std::nullopt;
}
bool applyValidRelocs(MutableArrayRef<char>, uint64_t, bool) override {
@@ -134,33 +135,7 @@ public:
return false;
}
- RangesTy &getValidAddressRanges() override { return DWARFAddressRanges; };
-
- void clear() override { DWARFAddressRanges.clear(); }
-
- llvm::Expected<uint64_t> relocateIndexedAddr(uint64_t StartOffset,
- uint64_t EndOffset) override {
- // No relocations in linked binary. Return just address value.
-
- const char *AddrPtr =
- Context.getDWARFObj().getAddrSection().Data.data() + StartOffset;
- support::endianness Endianess =
- Context.getDWARFObj().isLittleEndian() ? support::little : support::big;
-
- assert(EndOffset > StartOffset);
- switch (EndOffset - StartOffset) {
- case 1:
- return *AddrPtr;
- case 2:
- return support::endian::read16(AddrPtr, Endianess);
- case 4:
- return support::endian::read32(AddrPtr, Endianess);
- case 8:
- return support::endian::read64(AddrPtr, Endianess);
- }
-
- llvm_unreachable("relocateIndexedAddr unhandled case!");
- }
+ void clear() override {}
protected:
// returns true if specified address range is inside address ranges
@@ -228,10 +203,9 @@ protected:
}
private:
- RangesTy DWARFAddressRanges;
AddressRanges TextAddressRanges;
const Options &Opts;
- DWARFContext &Context;
+ bool HasValidAddressRanges = false;
};
static bool knownByDWARFUtil(StringRef SecName) {
@@ -258,12 +232,13 @@ static bool knownByDWARFUtil(StringRef SecName) {
.Default(false);
}
-static std::optional<DwarfLinkerAccelTableKind>
+template <typename AccelTableKind>
+static std::optional<AccelTableKind>
getAcceleratorTableKind(StringRef SecName) {
- return llvm::StringSwitch<std::optional<DwarfLinkerAccelTableKind>>(SecName)
- .Case(".debug_pubnames", DwarfLinkerAccelTableKind::Pub)
- .Case(".debug_pubtypes", DwarfLinkerAccelTableKind::Pub)
- .Case(".debug_names", DwarfLinkerAccelTableKind::DebugNames)
+ return llvm::StringSwitch<std::optional<AccelTableKind>>(SecName)
+ .Case(".debug_pubnames", AccelTableKind::Pub)
+ .Case(".debug_pubtypes", AccelTableKind::Pub)
+ .Case(".debug_names", AccelTableKind::DebugNames)
.Default(std::nullopt);
}
@@ -309,9 +284,9 @@ static std::string getMessageForDeletedAcceleratorTables(
return Message;
}
-Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
- raw_pwrite_stream &OutStream) {
-
+template <typename Linker, typename OutDwarfFile, typename AddressMapBase>
+Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options,
+ raw_pwrite_stream &OutStream) {
auto ReportWarn = [&](const Twine &Message, StringRef Context,
const DWARFDie *Die) {
warning(Message, Context);
@@ -331,39 +306,33 @@ Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
WithColor::error(errs(), Context) << Message << '\n';
};
- // Create output streamer.
- DwarfStreamer OutStreamer(OutputFileType::Object, OutStream, nullptr,
- ReportWarn, ReportWarn);
+ // Create DWARF linker.
+ std::unique_ptr<Linker> DebugInfoLinker =
+ Linker::createLinker(ReportErr, ReportWarn);
+
Triple TargetTriple = File.makeTriple();
- if (!OutStreamer.init(TargetTriple, formatv("cannot create a stream for {0}",
- TargetTriple.getTriple())
- .str()))
- return createStringError(std::errc::invalid_argument, "");
+ if (Error Err = DebugInfoLinker->createEmitter(
+ TargetTriple, Linker::OutputFileType::Object, OutStream))
+ return Err;
- std::unique_ptr<DWARFContext> Context = DWARFContext::create(File);
+ DebugInfoLinker->setEstimatedObjfilesAmount(1);
+ DebugInfoLinker->setNumThreads(Options.NumThreads);
+ DebugInfoLinker->setNoODR(!Options.DoODRDeduplication);
+ DebugInfoLinker->setVerbosity(Options.Verbose);
+ DebugInfoLinker->setUpdateIndexTablesOnly(!Options.DoGarbageCollection);
- // Create DWARF linker.
- DWARFLinker DebugInfoLinker(&OutStreamer, DwarfLinkerClient::LLD);
-
- DebugInfoLinker.setEstimatedObjfilesAmount(1);
- DebugInfoLinker.setErrorHandler(ReportErr);
- DebugInfoLinker.setWarningHandler(ReportWarn);
- DebugInfoLinker.setNumThreads(Options.NumThreads);
- DebugInfoLinker.setNoODR(!Options.DoODRDeduplication);
- DebugInfoLinker.setVerbosity(Options.Verbose);
- DebugInfoLinker.setUpdate(!Options.DoGarbageCollection);
-
- std::vector<std::unique_ptr<DWARFFile>> ObjectsForLinking(1);
- std::vector<std::unique_ptr<AddressesMap>> AddresssMapForLinking(1);
+ std::vector<std::unique_ptr<OutDwarfFile>> ObjectsForLinking(1);
std::vector<std::string> EmptyWarnings;
// Add object files to the DWARFLinker.
- AddresssMapForLinking[0] =
- std::make_unique<ObjFileAddressMap>(*Context, Options, File);
+ std::unique_ptr<DWARFContext> Context = DWARFContext::create(File);
+ std::unique_ptr<ObjFileAddressMap<AddressMapBase>> AddressesMap(
+ std::make_unique<ObjFileAddressMap<AddressMapBase>>(*Context, Options,
+ File));
- ObjectsForLinking[0] = std::make_unique<DWARFFile>(
- File.getFileName(), &*Context, AddresssMapForLinking[0].get(),
- EmptyWarnings);
+ ObjectsForLinking[0] =
+ std::make_unique<OutDwarfFile>(File.getFileName(), std::move(Context),
+ std::move(AddressesMap), EmptyWarnings);
uint16_t MaxDWARFVersion = 0;
std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded =
@@ -372,17 +341,17 @@ Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
};
for (size_t I = 0; I < ObjectsForLinking.size(); I++)
- DebugInfoLinker.addObjectFile(*ObjectsForLinking[I], nullptr,
- OnCUDieLoaded);
+ DebugInfoLinker->addObjectFile(*ObjectsForLinking[I], nullptr,
+ OnCUDieLoaded);
// If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway.
if (MaxDWARFVersion == 0)
MaxDWARFVersion = 3;
- if (Error Err = DebugInfoLinker.setTargetDWARFVersion(MaxDWARFVersion))
+ if (Error Err = DebugInfoLinker->setTargetDWARFVersion(MaxDWARFVersion))
return Err;
- SmallVector<DwarfLinkerAccelTableKind> AccelTables;
+ SmallVector<typename Linker::AccelTableKind> AccelTables;
switch (Options.AccelTableKind) {
case DwarfUtilAccelKind::None:
@@ -390,60 +359,74 @@ Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
break;
case DwarfUtilAccelKind::DWARF:
// use .debug_names for all DWARF versions.
- AccelTables.push_back(DwarfLinkerAccelTableKind::DebugNames);
+ AccelTables.push_back(Linker::AccelTableKind::DebugNames);
break;
}
// Add accelerator tables to DWARFLinker.
- for (DwarfLinkerAccelTableKind Table : AccelTables)
- DebugInfoLinker.addAccelTableKind(Table);
-
- SmallVector<StringRef> AccelTableNamesToReplace;
- SmallVector<StringRef> AccelTableNamesToDelete;
-
- // Unknown debug sections or non-requested accelerator sections would be
- // removed. Display warning for such sections.
- for (SectionName Sec : Context->getDWARFObj().getSectionNames()) {
- if (isDebugSection(Sec.Name)) {
- std::optional<DwarfLinkerAccelTableKind> SrcAccelTableKind =
- getAcceleratorTableKind(Sec.Name);
-
- if (SrcAccelTableKind) {
- assert(knownByDWARFUtil(Sec.Name));
-
- if (Options.AccelTableKind == DwarfUtilAccelKind::None)
- AccelTableNamesToDelete.push_back(Sec.Name);
- else if (std::find(AccelTables.begin(), AccelTables.end(),
- *SrcAccelTableKind) == AccelTables.end())
- AccelTableNamesToReplace.push_back(Sec.Name);
- } else if (!knownByDWARFUtil(Sec.Name)) {
- assert(!SrcAccelTableKind);
- warning(
- formatv("'{0}' is not currently supported: section will be skipped",
- Sec.Name),
- Options.InputFileName);
+ for (typename Linker::AccelTableKind Table : AccelTables)
+ DebugInfoLinker->addAccelTableKind(Table);
+
+ for (std::unique_ptr<OutDwarfFile> &CurFile : ObjectsForLinking) {
+ SmallVector<StringRef> AccelTableNamesToReplace;
+ SmallVector<StringRef> AccelTableNamesToDelete;
+
+ // Unknown debug sections or non-requested accelerator sections would be
+ // removed. Display warning for such sections.
+ for (SectionName Sec : CurFile->Dwarf->getDWARFObj().getSectionNames()) {
+ if (isDebugSection(Sec.Name)) {
+ std::optional<typename Linker::AccelTableKind> SrcAccelTableKind =
+ getAcceleratorTableKind<typename Linker::AccelTableKind>(Sec.Name);
+
+ if (SrcAccelTableKind) {
+ assert(knownByDWARFUtil(Sec.Name));
+
+ if (Options.AccelTableKind == DwarfUtilAccelKind::None)
+ AccelTableNamesToDelete.push_back(Sec.Name);
+ else if (!llvm::is_contained(AccelTables, *SrcAccelTableKind))
+ AccelTableNamesToReplace.push_back(Sec.Name);
+ } else if (!knownByDWARFUtil(Sec.Name)) {
+ assert(!SrcAccelTableKind);
+ warning(
+ formatv(
+ "'{0}' is not currently supported: section will be skipped",
+ Sec.Name),
+ Options.InputFileName);
+ }
}
}
- }
- // Display message for the replaced accelerator tables.
- if (!AccelTableNamesToReplace.empty())
- warning(getMessageForReplacedAcceleratorTables(AccelTableNamesToReplace,
- Options.AccelTableKind),
- Options.InputFileName);
+ // Display message for the replaced accelerator tables.
+ if (!AccelTableNamesToReplace.empty())
+ warning(getMessageForReplacedAcceleratorTables(AccelTableNamesToReplace,
+ Options.AccelTableKind),
+ Options.InputFileName);
- // Display message for the removed accelerator tables.
- if (!AccelTableNamesToDelete.empty())
- warning(getMessageForDeletedAcceleratorTables(AccelTableNamesToDelete),
- Options.InputFileName);
+ // Display message for the removed accelerator tables.
+ if (!AccelTableNamesToDelete.empty())
+ warning(getMessageForDeletedAcceleratorTables(AccelTableNamesToDelete),
+ Options.InputFileName);
+ }
// Link debug info.
- if (Error Err = DebugInfoLinker.link())
+ if (Error Err = DebugInfoLinker->link())
return Err;
- OutStreamer.finish();
+ DebugInfoLinker->getEmitter()->finish();
return Error::success();
}
+Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
+ raw_pwrite_stream &OutStream) {
+ if (Options.UseLLVMDWARFLinker)
+ return linkDebugInfoImpl<dwarflinker_parallel::DWARFLinker,
+ dwarflinker_parallel::DWARFFile,
+ dwarflinker_parallel::AddressesMap>(File, Options,
+ OutStream);
+ else
+ return linkDebugInfoImpl<DWARFLinker, DWARFFile, AddressesMap>(
+ File, Options, OutStream);
+}
+
} // end of namespace dwarfutil
} // end of namespace llvm
diff --git a/contrib/llvm-project/llvm/tools/llvm-dwarfutil/Error.h b/contrib/llvm-project/llvm/tools/llvm-dwarfutil/Error.h
index 9ef288d4f657..b92c50ca5a45 100644
--- a/contrib/llvm-project/llvm/tools/llvm-dwarfutil/Error.h
+++ b/contrib/llvm-project/llvm/tools/llvm-dwarfutil/Error.h
@@ -12,12 +12,12 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Triple.h"
namespace llvm {
namespace dwarfutil {
diff --git a/contrib/llvm-project/llvm/tools/llvm-dwarfutil/Options.h b/contrib/llvm-project/llvm/tools/llvm-dwarfutil/Options.h
index 38fa2b9eda63..e97833bdd79e 100644
--- a/contrib/llvm-project/llvm/tools/llvm-dwarfutil/Options.h
+++ b/contrib/llvm-project/llvm/tools/llvm-dwarfutil/Options.h
@@ -40,6 +40,7 @@ struct Options {
bool Verbose = false;
int NumThreads = 0;
bool Verify = false;
+ bool UseLLVMDWARFLinker = false;
DwarfUtilAccelKind AccelTableKind = DwarfUtilAccelKind::None;
std::string getSeparateDebugFileName() const {
diff --git a/contrib/llvm-project/llvm/tools/llvm-dwarfutil/Options.td b/contrib/llvm-project/llvm/tools/llvm-dwarfutil/Options.td
index d4541188c0c2..26b9ac678b6a 100644
--- a/contrib/llvm-project/llvm/tools/llvm-dwarfutil/Options.td
+++ b/contrib/llvm-project/llvm/tools/llvm-dwarfutil/Options.td
@@ -20,6 +20,11 @@ def h : Flag<["-"], "h">,
Alias<help>,
HelpText<"Alias for --help">;
+def linker: Separate<["--", "-"], "linker">,
+ MetaVarName<"<DWARF linker type>">,
+ HelpText<"Specify the desired type of DWARF linker. Defaults to 'apple'">;
+def: Joined<["--", "-"], "linker=">, Alias<linker>;
+
defm odr_deduplication : BB<"odr-deduplication",
"Do ODR deduplication for debug types(default)",
"Don`t do ODR deduplication for debug types">;
diff --git a/contrib/llvm-project/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp b/contrib/llvm-project/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
index 74b6104bc668..1c7627179795 100644
--- a/contrib/llvm-project/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
@@ -123,6 +123,18 @@ static Error validateAndSetOptions(opt::InputArgList &Args, Options &Options) {
formatv("unknown tombstone value: '{0}'", S).str().c_str());
}
+ if (opt::Arg *LinkerKind = Args.getLastArg(OPT_linker)) {
+ StringRef S = LinkerKind->getValue();
+ if (S == "apple")
+ Options.UseLLVMDWARFLinker = false;
+ else if (S == "llvm")
+ Options.UseLLVMDWARFLinker = true;
+ else
+ return createStringError(
+ std::errc::invalid_argument,
+ formatv("unknown linker kind value: '{0}'", S).str().c_str());
+ }
+
if (opt::Arg *BuildAccelerator = Args.getLastArg(OPT_build_accelerator)) {
StringRef S = BuildAccelerator->getValue();
diff --git a/contrib/llvm-project/llvm/tools/llvm-dwp/Opts.td b/contrib/llvm-project/llvm/tools/llvm-dwp/Opts.td
new file mode 100644
index 000000000000..c01fa4a12cba
--- /dev/null
+++ b/contrib/llvm-project/llvm/tools/llvm-dwp/Opts.td
@@ -0,0 +1,13 @@
+include "llvm/Option/OptParser.td"
+
+class F<string name, string help> : Flag<["-", "--"], name>, HelpText<help>;
+class S<string name, string help> : Separate<["-", "--"], name>, HelpText<help>;
+
+def help : F<"help", "Display this help">;
+def : F<"h", "Alias for --help">, Alias<help>;
+def version : F<"version", "Display the version of this program">;
+
+def execFileNames : S<"e", "Specify the executable/library files to get the list of *.dwo from.">, MetaVarName<"<filename>">;
+def outputFileName : S<"o", "Specify the output file.">, MetaVarName<"<filename>">;
+def continueOnCuIndexOverflow: F<"continue-on-cu-index-overflow", "This turns an error when offset for .debug_*.dwo sections "
+ "overfolws into a warning.">, MetaVarName<"<filename>">;
diff --git a/contrib/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp b/contrib/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp
index 0a2c1c1ccc02..350a37345e2c 100644
--- a/contrib/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp
@@ -23,6 +23,8 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/InitLLVM.h"
@@ -36,20 +38,46 @@ using namespace llvm::object;
static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;
-cl::OptionCategory DwpCategory("Specific Options");
-static cl::list<std::string>
- InputFiles(cl::Positional, cl::desc("<input files>"), cl::cat(DwpCategory));
+// Command-line option boilerplate.
+namespace {
+enum ID {
+ OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES) \
+ OPT_##ID,
+#include "Opts.inc"
+#undef OPTION
+};
-static cl::list<std::string> ExecFilenames(
- "e",
- cl::desc(
- "Specify the executable/library files to get the list of *.dwo from"),
- cl::value_desc("filename"), cl::cat(DwpCategory));
+#define PREFIX(NAME, VALUE) \
+ static constexpr StringLiteral NAME##_init[] = VALUE; \
+ static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \
+ std::size(NAME##_init) - 1);
+#include "Opts.inc"
+#undef PREFIX
-static cl::opt<std::string> OutputFilename(cl::Required, "o",
- cl::desc("Specify the output file."),
- cl::value_desc("filename"),
- cl::cat(DwpCategory));
+static constexpr opt::OptTable::Info InfoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES) \
+ { \
+ PREFIX, NAME, HELPTEXT, \
+ METAVAR, OPT_##ID, opt::Option::KIND##Class, \
+ PARAM, FLAGS, OPT_##GROUP, \
+ OPT_##ALIAS, ALIASARGS, VALUES},
+#include "Opts.inc"
+#undef OPTION
+};
+
+class DwpOptTable : public opt::GenericOptTable {
+public:
+ DwpOptTable() : GenericOptTable(InfoTable) {}
+};
+} // end anonymous namespace
+
+// Options
+static std::vector<std::string> ExecFilenames;
+static std::string OutputFilename;
+static bool ContinueOnCuIndexOverflow;
static Expected<SmallVector<std::string, 16>>
getDWOFilenames(StringRef ExecFilename) {
@@ -100,15 +128,41 @@ static Expected<Triple> readTargetTriple(StringRef FileName) {
int main(int argc, char **argv) {
InitLLVM X(argc, argv);
- cl::HideUnrelatedOptions({&DwpCategory, &getColorCategory()});
- cl::ParseCommandLineOptions(argc, argv, "merge split dwarf (.dwo) files\n");
+ DwpOptTable Tbl;
+ llvm::BumpPtrAllocator A;
+ llvm::StringSaver Saver{A};
+ opt::InputArgList Args =
+ Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
+ llvm::errs() << Msg << '\n';
+ std::exit(1);
+ });
+
+ if (Args.hasArg(OPT_help)) {
+ Tbl.printHelp(llvm::outs(), "llvm-dwp [options] <input files>",
+ "merge split dwarf (.dwo) files");
+ std::exit(0);
+ }
+
+ if (Args.hasArg(OPT_version)) {
+ llvm::cl::PrintVersionMessage();
+ std::exit(0);
+ }
+
+ OutputFilename = Args.getLastArgValue(OPT_outputFileName, "");
+ ContinueOnCuIndexOverflow = Args.hasArg(OPT_continueOnCuIndexOverflow);
+
+ for (const llvm::opt::Arg *A : Args.filtered(OPT_execFileNames))
+ ExecFilenames.emplace_back(A->getValue());
+
+ std::vector<std::string> DWOFilenames;
+ for (const llvm::opt::Arg *A : Args.filtered(OPT_INPUT))
+ DWOFilenames.emplace_back(A->getValue());
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllTargets();
llvm::InitializeAllAsmPrinters();
- std::vector<std::string> DWOFilenames = InputFiles;
for (const auto &ExecFilename : ExecFilenames) {
auto DWOs = getDWOFilenames(ExecFilename);
if (!DWOs) {
@@ -207,7 +261,7 @@ int main(int argc, char **argv) {
if (!MS)
return error("no object streamer for target " + TripleName, Context);
- if (auto Err = write(*MS, DWOFilenames)) {
+ if (auto Err = write(*MS, DWOFilenames, ContinueOnCuIndexOverflow)) {
logAllUnhandledErrors(std::move(Err), WithColor::error());
return 1;
}
diff --git a/contrib/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp b/contrib/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp
index 79e9d93061a2..51921d44d748 100644
--- a/contrib/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp
@@ -516,11 +516,10 @@ static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
/// Given the original \p Path to an output file, replace any path
/// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
/// resulting directory if it does not yet exist.
-static std::string getThinLTOOutputFile(const std::string &Path,
- const std::string &OldPrefix,
- const std::string &NewPrefix) {
+static std::string getThinLTOOutputFile(StringRef Path, StringRef OldPrefix,
+ StringRef NewPrefix) {
if (OldPrefix.empty() && NewPrefix.empty())
- return Path;
+ return std::string(Path);
SmallString<128> NewPath(Path);
llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
diff --git a/contrib/llvm-project/llvm/tools/llvm-lto2/llvm-lto2.cpp b/contrib/llvm-project/llvm/tools/llvm-lto2/llvm-lto2.cpp
index 09c74fc586f5..81c97a994038 100644
--- a/contrib/llvm-project/llvm/tools/llvm-lto2/llvm-lto2.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-lto2/llvm-lto2.cpp
@@ -167,10 +167,6 @@ static cl::opt<bool>
cl::desc("Run PGO context sensitive IR instrumentation"),
cl::Hidden);
-static cl::opt<bool> LtoOpaquePointers("lto-opaque-pointers",
- cl::desc("Enable opaque pointer types"),
- cl::init(true), cl::Hidden);
-
static cl::opt<bool>
DebugPassManager("debug-pass-manager", cl::Hidden,
cl::desc("Print pass management debugging information"));
@@ -182,6 +178,10 @@ static cl::list<std::string>
PassPlugins("load-pass-plugin",
cl::desc("Load passes from plugin library"));
+static cl::opt<std::string> UnifiedLTOMode("unified-lto", cl::Optional,
+ cl::desc("Set LTO mode"),
+ cl::value_desc("mode"));
+
static cl::opt<bool> EnableFreestanding(
"lto-freestanding",
cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"),
@@ -321,15 +321,15 @@ static int run(int argc, char **argv) {
Conf.StatsFile = StatsFile;
Conf.PTO.LoopVectorization = Conf.OptLevel > 1;
Conf.PTO.SLPVectorization = Conf.OptLevel > 1;
- Conf.OpaquePointers = LtoOpaquePointers;
ThinBackend Backend;
if (ThinLTODistributedIndexes)
- Backend =
- createWriteIndexesThinBackend(/* OldPrefix */ "",
- /* NewPrefix */ "", ThinLTOEmitImports,
- /* LinkedObjectsFile */ nullptr,
- /* OnWrite */ {});
+ Backend = createWriteIndexesThinBackend(/*OldPrefix=*/"",
+ /*NewPrefix=*/"",
+ /*NativeObjectPrefix=*/"",
+ ThinLTOEmitImports,
+ /*LinkedObjectsFile=*/nullptr,
+ /*OnWrite=*/{});
else
Backend = createInProcessThinBackend(
llvm::heavyweight_hardware_concurrency(Threads),
@@ -352,7 +352,20 @@ static int run(int argc, char **argv) {
HasErrors = true;
};
- LTO Lto(std::move(Conf), std::move(Backend));
+ LTO::LTOKind LTOMode = LTO::LTOK_Default;
+
+ if (UnifiedLTOMode == "full") {
+ LTOMode = LTO::LTOK_UnifiedRegular;
+ } else if (UnifiedLTOMode == "thin") {
+ LTOMode = LTO::LTOK_UnifiedThin;
+ } else if (UnifiedLTOMode == "default") {
+ LTOMode = LTO::LTOK_Default;
+ } else if (!UnifiedLTOMode.empty()) {
+ llvm::errs() << "invalid LTO mode\n";
+ return 1;
+ }
+
+ LTO Lto(std::move(Conf), std::move(Backend), 1, LTOMode);
for (std::string F : InputFilenames) {
std::unique_ptr<MemoryBuffer> MB = check(MemoryBuffer::getFile(F), F);
diff --git a/contrib/llvm-project/llvm/tools/llvm-mc/Disassembler.cpp b/contrib/llvm-project/llvm/tools/llvm-mc/Disassembler.cpp
index 2d1833429718..7456a2f2c915 100644
--- a/contrib/llvm-project/llvm/tools/llvm-mc/Disassembler.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-mc/Disassembler.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "Disassembler.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
@@ -25,6 +24,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Triple.h"
using namespace llvm;
diff --git a/contrib/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp b/contrib/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp
index dd5a66a6eb7d..572723afb79e 100644
--- a/contrib/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp
@@ -31,13 +31,13 @@
#include "llvm/Support/Compression.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/WithColor.h"
+#include "llvm/TargetParser/Host.h"
using namespace llvm;
diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp
index c91ed759ee77..ba5188076c2e 100644
--- a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp
@@ -115,7 +115,7 @@ void AnalysisRegions::endRegion(StringRef Description, SMLoc Loc) {
InstrumentRegions::InstrumentRegions(llvm::SourceMgr &S) : CodeRegions(S) {}
void InstrumentRegions::beginRegion(StringRef Description, SMLoc Loc,
- SharedInstrument I) {
+ UniqueInstrument I) {
if (Description.empty()) {
SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
"anonymous instrumentation regions are not permitted");
@@ -137,7 +137,8 @@ void InstrumentRegions::beginRegion(StringRef Description, SMLoc Loc,
}
ActiveRegions[Description] = Regions.size();
- Regions.emplace_back(std::make_unique<InstrumentRegion>(Description, Loc, I));
+ Regions.emplace_back(
+ std::make_unique<InstrumentRegion>(Description, Loc, std::move(I)));
}
void InstrumentRegions::endRegion(StringRef Description, SMLoc Loc) {
@@ -158,13 +159,13 @@ void InstrumentRegions::endRegion(StringRef Description, SMLoc Loc) {
}
}
-const SmallVector<SharedInstrument>
+const SmallVector<Instrument *>
InstrumentRegions::getActiveInstruments(SMLoc Loc) const {
- SmallVector<SharedInstrument> AI;
+ SmallVector<Instrument *> AI;
for (auto &R : Regions) {
if (R->isLocInRange(Loc)) {
InstrumentRegion *IR = static_cast<InstrumentRegion *>(R.get());
- AI.emplace_back(IR->getInstrument());
+ AI.push_back(IR->getInstrument());
}
}
return AI;
diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.h b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.h
index b5b2f3a0d118..ce107fd8f3b6 100644
--- a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.h
+++ b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.h
@@ -91,6 +91,8 @@ public:
CodeRegion(llvm::StringRef Desc, llvm::SMLoc Start)
: Description(Desc), RangeStart(Start) {}
+ virtual ~CodeRegion() = default;
+
void addInstruction(const llvm::MCInst &Instruction) {
Instructions.emplace_back(Instruction);
}
@@ -115,14 +117,14 @@ using AnalysisRegion = CodeRegion;
/// in analysis of the region.
class InstrumentRegion : public CodeRegion {
/// Instrument for this region.
- SharedInstrument Instrument;
+ UniqueInstrument I;
public:
- InstrumentRegion(llvm::StringRef Desc, llvm::SMLoc Start, SharedInstrument I)
- : CodeRegion(Desc, Start), Instrument(I) {}
+ InstrumentRegion(llvm::StringRef Desc, llvm::SMLoc Start, UniqueInstrument I)
+ : CodeRegion(Desc, Start), I(std::move(I)) {}
public:
- SharedInstrument getInstrument() const { return Instrument; }
+ Instrument *getInstrument() const { return I.get(); }
};
class CodeRegionParseError final : public Error {};
@@ -142,6 +144,7 @@ protected:
public:
CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {}
+ virtual ~CodeRegions() = default;
typedef std::vector<UniqueCodeRegion>::iterator iterator;
typedef std::vector<UniqueCodeRegion>::const_iterator const_iterator;
@@ -167,26 +170,34 @@ public:
bool isValid() const { return !FoundErrors; }
bool isRegionActive(llvm::StringRef Description) const {
- return ActiveRegions.find(Description) != ActiveRegions.end();
+ return ActiveRegions.contains(Description);
}
+
+ virtual void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) = 0;
+ virtual void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
+ UniqueInstrument Instrument) = 0;
+ virtual void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) = 0;
};
struct AnalysisRegions : public CodeRegions {
AnalysisRegions(llvm::SourceMgr &S);
- void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc);
- void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
+ void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) override;
+ void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
+ UniqueInstrument Instrument) override {}
+ void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) override;
};
struct InstrumentRegions : public CodeRegions {
+
InstrumentRegions(llvm::SourceMgr &S);
+ void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) override{};
void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
- SharedInstrument Instrument);
- void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
+ UniqueInstrument Instrument) override;
+ void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) override;
- const SmallVector<SharedInstrument>
- getActiveInstruments(llvm::SMLoc Loc) const;
+ const SmallVector<Instrument *> getActiveInstruments(llvm::SMLoc Loc) const;
};
} // namespace mca
diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
index b8e10fa69c2d..5241b584b746 100644
--- a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
@@ -17,7 +17,6 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
-#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/SMLoc.h"
@@ -29,46 +28,12 @@ namespace mca {
// This virtual dtor serves as the anchor for the CodeRegionGenerator class.
CodeRegionGenerator::~CodeRegionGenerator() {}
-// This class provides the callbacks that occur when parsing input assembly.
-class MCStreamerWrapper final : public MCStreamer {
- CodeRegions &Regions;
-
-public:
- MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)
- : MCStreamer(Context), Regions(R) {}
-
- // We only want to intercept the emission of new instructions.
- void emitInstruction(const MCInst &Inst,
- const MCSubtargetInfo & /* unused */) override {
- Regions.addInstruction(Inst);
- }
-
- bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
- return true;
- }
-
- void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
- Align ByteAlignment) override {}
- void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
- uint64_t Size = 0, Align ByteAlignment = Align(1),
- SMLoc Loc = SMLoc()) override {}
- void emitGPRel32Value(const MCExpr *Value) override {}
- void beginCOFFSymbolDef(const MCSymbol *Symbol) override {}
- void emitCOFFSymbolStorageClass(int StorageClass) override {}
- void emitCOFFSymbolType(int Type) override {}
- void endCOFFSymbolDef() override {}
-
- ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const {
- return Regions.getInstructionSequence(Index);
- }
-};
-
Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions(
const std::unique_ptr<MCInstPrinter> &IP) {
MCTargetOptions Opts;
Opts.PreserveAsmComments = false;
CodeRegions &Regions = getRegions();
- MCStreamerWrapper Str(Ctx, Regions);
+ MCStreamerWrapper *Str = getMCStreamer();
// Need to initialize an MCTargetStreamer otherwise
// certain asm directives will cause a segfault.
@@ -76,13 +41,13 @@ Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions(
// doesn't show up in the llvm-mca output.
raw_ostream &OSRef = nulls();
formatted_raw_ostream FOSRef(OSRef);
- TheTarget.createAsmTargetStreamer(Str, FOSRef, IP.get(),
+ TheTarget.createAsmTargetStreamer(*Str, FOSRef, IP.get(),
/*IsVerboseAsm=*/true);
// Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM
// comments.
std::unique_ptr<MCAsmParser> Parser(
- createMCAsmParser(Regions.getSourceMgr(), Ctx, Str, MAI));
+ createMCAsmParser(Regions.getSourceMgr(), Ctx, *Str, MAI));
MCAsmLexer &Lexer = Parser->getLexer();
MCACommentConsumer *CCP = getCommentConsumer();
Lexer.setCommentConsumer(CCP);
@@ -184,7 +149,7 @@ void InstrumentRegionCommentConsumer::HandleComment(SMLoc Loc,
return;
}
- SharedInstrument I = IM.createInstrument(InstrumentKind, Data);
+ UniqueInstrument I = IM.createInstrument(InstrumentKind, Data);
if (!I) {
if (Data.empty())
SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
@@ -202,7 +167,7 @@ void InstrumentRegionCommentConsumer::HandleComment(SMLoc Loc,
if (Regions.isRegionActive(InstrumentKind))
Regions.endRegion(InstrumentKind, Loc);
// Start new instrumentation region
- Regions.beginRegion(InstrumentKind, Loc, I);
+ Regions.beginRegion(InstrumentKind, Loc, std::move(I));
}
} // namespace mca
diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h
index 88621ed856c5..68da567f3e0f 100644
--- a/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h
+++ b/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h
@@ -20,6 +20,7 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/MCA/CustomBehaviour.h"
@@ -32,10 +33,10 @@ namespace mca {
class MCACommentConsumer : public AsmCommentConsumer {
protected:
- bool FoundError;
+ bool FoundError = false;
public:
- MCACommentConsumer() : FoundError(false) {}
+ MCACommentConsumer() = default;
bool hadErr() const { return FoundError; }
};
@@ -77,6 +78,67 @@ public:
/// region of type INSTRUMENATION_TYPE, then it will end the active
/// one and begin a new one using the new data.
void HandleComment(SMLoc Loc, StringRef CommentText) override;
+
+ InstrumentManager &getInstrumentManager() { return IM; }
+};
+
+// This class provides the callbacks that occur when parsing input assembly.
+class MCStreamerWrapper : public MCStreamer {
+protected:
+ CodeRegions &Regions;
+
+public:
+ MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)
+ : MCStreamer(Context), Regions(R) {}
+
+ // We only want to intercept the emission of new instructions.
+ void emitInstruction(const MCInst &Inst,
+ const MCSubtargetInfo & /* unused */) override {
+ Regions.addInstruction(Inst);
+ }
+
+ bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
+ return true;
+ }
+
+ void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ Align ByteAlignment) override {}
+ void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
+ uint64_t Size = 0, Align ByteAlignment = Align(1),
+ SMLoc Loc = SMLoc()) override {}
+ void emitGPRel32Value(const MCExpr *Value) override {}
+ void beginCOFFSymbolDef(const MCSymbol *Symbol) override {}
+ void emitCOFFSymbolStorageClass(int StorageClass) override {}
+ void emitCOFFSymbolType(int Type) override {}
+ void endCOFFSymbolDef() override {}
+
+ ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const {
+ return Regions.getInstructionSequence(Index);
+ }
+};
+
+class InstrumentMCStreamer : public MCStreamerWrapper {
+ InstrumentManager &IM;
+
+public:
+ InstrumentMCStreamer(MCContext &Context, mca::InstrumentRegions &R,
+ InstrumentManager &IM)
+ : MCStreamerWrapper(Context, R), IM(IM) {}
+
+ void emitInstruction(const MCInst &Inst,
+ const MCSubtargetInfo &MCSI) override {
+ MCStreamerWrapper::emitInstruction(Inst, MCSI);
+
+ // We know that Regions is an InstrumentRegions by the constructor.
+ for (UniqueInstrument &I : IM.createInstruments(Inst)) {
+ StringRef InstrumentKind = I.get()->getDesc();
+ // End InstrumentType region if one is open
+ if (Regions.isRegionActive(InstrumentKind))
+ Regions.endRegion(InstrumentKind, Inst.getLoc());
+ // Start new instrumentation region
+ Regions.beginRegion(InstrumentKind, Inst.getLoc(), std::move(I));
+ }
+ }
};
/// This abstract class is responsible for parsing the input given to
@@ -121,19 +183,22 @@ public:
/// generating a CodeRegions instance.
class AsmCodeRegionGenerator : public virtual CodeRegionGenerator {
const Target &TheTarget;
- MCContext &Ctx;
const MCAsmInfo &MAI;
const MCSubtargetInfo &STI;
const MCInstrInfo &MCII;
unsigned AssemblerDialect; // This is set during parsing.
+protected:
+ MCContext &Ctx;
+
public:
AsmCodeRegionGenerator(const Target &T, MCContext &C, const MCAsmInfo &A,
const MCSubtargetInfo &S, const MCInstrInfo &I)
- : TheTarget(T), Ctx(C), MAI(A), STI(S), MCII(I), AssemblerDialect(0) {}
+ : TheTarget(T), MAI(A), STI(S), MCII(I), AssemblerDialect(0), Ctx(C) {}
virtual MCACommentConsumer *getCommentConsumer() = 0;
virtual CodeRegions &getRegions() = 0;
+ virtual MCStreamerWrapper *getMCStreamer() = 0;
unsigned getAssemblerDialect() const { return AssemblerDialect; }
Expected<const CodeRegions &>
@@ -143,16 +208,18 @@ public:
class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator,
public AsmCodeRegionGenerator {
AnalysisRegionCommentConsumer CC;
+ MCStreamerWrapper Streamer;
public:
AsmAnalysisRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C,
const MCAsmInfo &A, const MCSubtargetInfo &S,
const MCInstrInfo &I)
: AnalysisRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
- CC(Regions) {}
+ CC(Regions), Streamer(Ctx, Regions) {}
MCACommentConsumer *getCommentConsumer() override { return &CC; };
CodeRegions &getRegions() override { return Regions; };
+ MCStreamerWrapper *getMCStreamer() override { return &Streamer; }
Expected<const AnalysisRegions &>
parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP) override {
@@ -172,6 +239,7 @@ public:
class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator,
public AsmCodeRegionGenerator {
InstrumentRegionCommentConsumer CC;
+ InstrumentMCStreamer Streamer;
public:
AsmInstrumentRegionGenerator(const Target &T, llvm::SourceMgr &SM,
@@ -179,10 +247,11 @@ public:
const MCSubtargetInfo &S, const MCInstrInfo &I,
InstrumentManager &IM)
: InstrumentRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
- CC(SM, Regions, IM) {}
+ CC(SM, Regions, IM), Streamer(Ctx, Regions, IM) {}
MCACommentConsumer *getCommentConsumer() override { return &CC; };
CodeRegions &getRegions() override { return Regions; };
+ MCStreamerWrapper *getMCStreamer() override { return &Streamer; }
Expected<const InstrumentRegions &>
parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP) override {
diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp b/contrib/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp
index dc0a07e75e48..b254ccd6670f 100644
--- a/contrib/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp
@@ -52,7 +52,7 @@ void PressureTracker::getResourceUsers(uint64_t ResourceMask,
const MCProcResourceDesc &PRDesc = *SM.getProcResource(ProcResID);
for (unsigned I = 0, E = PRDesc.NumUnits; I < E; ++I) {
const User U = getResourceUser(ProcResID, I);
- if (U.second && IPI.find(U.first) != IPI.end())
+ if (U.second && IPI.contains(U.first))
Users.emplace_back(U);
}
}
@@ -69,7 +69,7 @@ void PressureTracker::handleInstructionIssuedEvent(
for (const ResourceUse &Use : Event.UsedResources) {
const ResourceRef &RR = Use.first;
unsigned Index = ProcResID2ResourceUsersIndex[RR.first];
- Index += countTrailingZeros(RR.second);
+ Index += llvm::countr_zero(RR.second);
ResourceUsers[Index] = std::make_pair(IID, Use.second.getNumerator());
}
}
diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h b/contrib/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h
index cd5af0afcf5b..e709b25c3f76 100644
--- a/contrib/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h
+++ b/contrib/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h
@@ -146,19 +146,19 @@ public:
SmallVectorImpl<User> &Users) const;
unsigned getRegisterPressureCycles(unsigned IID) const {
- assert(IPI.find(IID) != IPI.end() && "Instruction is not tracked!");
+ assert(IPI.contains(IID) && "Instruction is not tracked!");
const InstructionPressureInfo &Info = IPI.find(IID)->second;
return Info.RegisterPressureCycles;
}
unsigned getMemoryPressureCycles(unsigned IID) const {
- assert(IPI.find(IID) != IPI.end() && "Instruction is not tracked!");
+ assert(IPI.contains(IID) && "Instruction is not tracked!");
const InstructionPressureInfo &Info = IPI.find(IID)->second;
return Info.MemoryPressureCycles;
}
unsigned getResourcePressureCycles(unsigned IID) const {
- assert(IPI.find(IID) != IPI.end() && "Instruction is not tracked!");
+ assert(IPI.contains(IID) && "Instruction is not tracked!");
const InstructionPressureInfo &Info = IPI.find(IID)->second;
return Info.ResourcePressureCycles;
}
diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp b/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp
index 257fdca8cb36..fea0c9b8455c 100644
--- a/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp
@@ -55,10 +55,7 @@ void InstructionInfoView::printView(raw_ostream &OS) const {
}
}
- int Index = 0;
- for (const auto &I : enumerate(zip(IIVD, Source))) {
- const InstructionInfoViewData &IIVDEntry = std::get<0>(I.value());
-
+ for (const auto &[Index, IIVDEntry, Inst] : enumerate(IIVD, Source)) {
TempStream << ' ' << IIVDEntry.NumMicroOpcodes << " ";
if (IIVDEntry.NumMicroOpcodes < 10)
TempStream << " ";
@@ -92,7 +89,7 @@ void InstructionInfoView::printView(raw_ostream &OS) const {
}
if (PrintEncodings) {
- StringRef Encoding(CE.getEncoding(I.index()));
+ StringRef Encoding(CE.getEncoding(Index));
unsigned EncodingSize = Encoding.size();
TempStream << " " << EncodingSize
<< (EncodingSize < 10 ? " " : " ");
@@ -104,9 +101,7 @@ void InstructionInfoView::printView(raw_ostream &OS) const {
FOS.flush();
}
- const MCInst &Inst = std::get<1>(I.value());
TempStream << printInstructionString(Inst) << '\n';
- ++Index;
}
TempStream.flush();
@@ -122,8 +117,13 @@ void InstructionInfoView::collectData(
InstructionInfoViewData &IIVDEntry = std::get<1>(I);
const MCInstrDesc &MCDesc = MCII.get(Inst.getOpcode());
- // Obtain the scheduling class information from the instruction.
- unsigned SchedClassID = MCDesc.getSchedClass();
+ // Obtain the scheduling class information from the instruction
+ // and instruments.
+ auto IVecIt = InstToInstruments.find(&Inst);
+ unsigned SchedClassID =
+ IVecIt == InstToInstruments.end()
+ ? MCDesc.getSchedClass()
+ : IM.getSchedClassID(MCII, Inst, IVecIt->second);
unsigned CPUID = SM.getProcessorID();
// Try to solve variant scheduling classes.
diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.h b/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.h
index bddd01a086b5..3befafda90a3 100644
--- a/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.h
+++ b/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.h
@@ -42,6 +42,7 @@
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MCA/CodeEmitter.h"
+#include "llvm/MCA/CustomBehaviour.h"
#include "llvm/Support/raw_ostream.h"
#define DEBUG_TYPE "llvm-mca"
@@ -57,6 +58,10 @@ class InstructionInfoView : public InstructionView {
bool PrintBarriers;
using UniqueInst = std::unique_ptr<Instruction>;
ArrayRef<UniqueInst> LoweredInsts;
+ const InstrumentManager &IM;
+ using InstToInstrumentsT =
+ DenseMap<const MCInst *, SmallVector<mca::Instrument *>>;
+ const InstToInstrumentsT &InstToInstruments;
struct InstructionInfoViewData {
unsigned NumMicroOpcodes = 0;
@@ -77,10 +82,12 @@ public:
bool ShouldPrintEncodings, llvm::ArrayRef<llvm::MCInst> S,
llvm::MCInstPrinter &IP,
ArrayRef<UniqueInst> LoweredInsts,
- bool ShouldPrintBarriers)
+ bool ShouldPrintBarriers, const InstrumentManager &IM,
+ const InstToInstrumentsT &InstToInstruments)
: InstructionView(ST, IP, S), MCII(II), CE(C),
PrintEncodings(ShouldPrintEncodings),
- PrintBarriers(ShouldPrintBarriers), LoweredInsts(LoweredInsts) {}
+ PrintBarriers(ShouldPrintBarriers), LoweredInsts(LoweredInsts), IM(IM),
+ InstToInstruments(InstToInstruments) {}
void printView(llvm::raw_ostream &OS) const override;
StringRef getNameAsString() const override { return "InstructionInfoView"; }
diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp b/contrib/llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp
index 77b3ba0b7c8d..0f059bcc0a06 100644
--- a/contrib/llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp
@@ -57,9 +57,9 @@ void ResourcePressureView::onEvent(const HWInstructionEvent &Event) {
for (const std::pair<ResourceRef, ResourceCycles> &Use :
IssueEvent.UsedResources) {
const ResourceRef &RR = Use.first;
- assert(Resource2VecIndex.find(RR.first) != Resource2VecIndex.end());
+ assert(Resource2VecIndex.contains(RR.first));
unsigned R2VIndex = Resource2VecIndex[RR.first];
- R2VIndex += countTrailingZeros(RR.second);
+ R2VIndex += llvm::countr_zero(RR.second);
ResourceUsage[R2VIndex + NumResourceUnits * SourceIdx] += Use.second;
ResourceUsage[R2VIndex + NumResourceUnits * Source.size()] += Use.second;
}
diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/Views/TimelineView.cpp b/contrib/llvm-project/llvm/tools/llvm-mca/Views/TimelineView.cpp
index 5c05edbdea68..2eca48aadfd7 100644
--- a/contrib/llvm-project/llvm/tools/llvm-mca/Views/TimelineView.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-mca/Views/TimelineView.cpp
@@ -315,6 +315,10 @@ json::Value TimelineView::toJSON() const {
json::Array TimelineInfo;
for (const TimelineViewEntry &TLE : Timeline) {
+ // Check if the timeline-max-cycles has been reached.
+ if (!TLE.CycleRetired && TLE.CycleExecuted)
+ break;
+
TimelineInfo.push_back(
json::Object({{"CycleDispatched", TLE.CycleDispatched},
{"CycleReady", TLE.CycleReady},
diff --git a/contrib/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp b/contrib/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp
index 33adf15fccaf..eb71cffba6dd 100644
--- a/contrib/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp
@@ -53,13 +53,13 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/WithColor.h"
+#include "llvm/TargetParser/Host.h"
using namespace llvm;
@@ -571,11 +571,14 @@ int main(int argc, char **argv) {
IPP->resetState();
+ DenseMap<const MCInst *, SmallVector<mca::Instrument *>>
+ InstToInstruments;
SmallVector<std::unique_ptr<mca::Instruction>> LoweredSequence;
for (const MCInst &MCI : Insts) {
SMLoc Loc = MCI.getLoc();
- const SmallVector<mca::SharedInstrument> Instruments =
+ const SmallVector<mca::Instrument *> Instruments =
InstrumentRegions.getActiveInstruments(Loc);
+ InstToInstruments.insert({&MCI, Instruments});
Expected<std::unique_ptr<mca::Instruction>> Inst =
IB.createInstruction(MCI, Instruments);
@@ -621,7 +624,7 @@ int main(int argc, char **argv) {
if (PrintInstructionInfoView) {
Printer.addView(std::make_unique<mca::InstructionInfoView>(
*STI, *MCII, CE, ShowEncoding, Insts, *IP, LoweredSequence,
- ShowBarriers));
+ ShowBarriers, *IM, InstToInstruments));
}
Printer.addView(
std::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts));
@@ -698,7 +701,7 @@ int main(int argc, char **argv) {
if (PrintInstructionInfoView)
Printer.addView(std::make_unique<mca::InstructionInfoView>(
*STI, *MCII, CE, ShowEncoding, Insts, *IP, LoweredSequence,
- ShowBarriers));
+ ShowBarriers, *IM, InstToInstruments));
// Fetch custom Views that are to be placed after the InstructionInfoView.
// Refer to the comment paired with the CB->getStartViews(*IP, Insts); line
diff --git a/contrib/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp b/contrib/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp
index 55319d0e4c72..1f6a5d1ab806 100644
--- a/contrib/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -16,7 +16,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/Demangle/Demangle.h"
@@ -40,14 +39,16 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LLVMDriver.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/Triple.h"
#include <vector>
using namespace llvm;
@@ -293,22 +294,6 @@ bool operator==(const NMSymbol &A, const NMSymbol &B) {
}
} // anonymous namespace
-static char isSymbolList64Bit(SymbolicFile &Obj) {
- if (auto *IRObj = dyn_cast<IRObjectFile>(&Obj))
- return Triple(IRObj->getTargetTriple()).isArch64Bit();
- if (isa<COFFObjectFile>(Obj) || isa<COFFImportFile>(Obj))
- return false;
- if (XCOFFObjectFile *XCOFFObj = dyn_cast<XCOFFObjectFile>(&Obj))
- return XCOFFObj->is64Bit();
- if (isa<WasmObjectFile>(Obj))
- return false;
- if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj))
- return Tapi->is64Bit();
- if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))
- return MachO->is64Bit();
- return cast<ELFObjectFileBase>(Obj).getBytesInAddress() == 8;
-}
-
static StringRef CurrentFilename;
static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I);
@@ -654,7 +639,7 @@ static void darwinPrintStab(MachOObjectFile *MachO, const NMSymbol &S) {
static std::optional<std::string> demangle(StringRef Name) {
std::string Demangled;
- if (nonMicrosoftDemangle(Name.str().c_str(), Demangled))
+ if (nonMicrosoftDemangle(Name, Demangled))
return Demangled;
return std::nullopt;
}
@@ -722,7 +707,7 @@ static void printSymbolList(SymbolicFile &Obj,
outs() << '\n' << CurrentFilename << ":\n";
} else if (OutputFormat == sysv) {
outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n";
- if (isSymbolList64Bit(Obj))
+ if (Obj.is64Bit())
outs() << "Name Value Class Type"
<< " Size Line Section\n";
else
@@ -732,7 +717,7 @@ static void printSymbolList(SymbolicFile &Obj,
}
const char *printBlanks, *printDashes, *printFormat;
- if (isSymbolList64Bit(Obj)) {
+ if (Obj.is64Bit()) {
printBlanks = " ";
printDashes = "----------------";
switch (AddressRadix) {
@@ -1044,7 +1029,15 @@ static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {
}
static char getSymbolNMTypeChar(TapiFile &Obj, basic_symbol_iterator I) {
- return 's';
+ auto Type = cantFail(Obj.getSymbolType(I->getRawDataRefImpl()));
+ switch (Type) {
+ case SymbolRef::ST_Data:
+ return 'd';
+ case SymbolRef::ST_Function:
+ return 't';
+ default:
+ return 's';
+ }
}
static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) {
@@ -1671,8 +1664,8 @@ static bool shouldDump(SymbolicFile &Obj) {
!isa<IRObjectFile>(Obj))
return true;
- return isSymbolList64Bit(Obj) ? BitMode != BitModeTy::Bit32
- : BitMode != BitModeTy::Bit64;
+ return Obj.is64Bit() ? BitMode != BitModeTy::Bit32
+ : BitMode != BitModeTy::Bit64;
}
static void getXCOFFExports(XCOFFObjectFile *XCOFFObj,
@@ -1961,26 +1954,39 @@ static bool checkMachOAndArchFlags(SymbolicFile *O, StringRef Filename) {
return true;
}
+static void printArchiveMap(iterator_range<Archive::symbol_iterator> &map,
+ StringRef Filename) {
+ for (auto I : map) {
+ Expected<Archive::Child> C = I.getMember();
+ if (!C) {
+ error(C.takeError(), Filename);
+ break;
+ }
+ Expected<StringRef> FileNameOrErr = C->getName();
+ if (!FileNameOrErr) {
+ error(FileNameOrErr.takeError(), Filename);
+ break;
+ }
+ StringRef SymName = I.getName();
+ outs() << SymName << " in " << FileNameOrErr.get() << "\n";
+ }
+
+ outs() << "\n";
+}
+
static void dumpArchiveMap(Archive *A, StringRef Filename) {
- Archive::symbol_iterator I = A->symbol_begin();
- Archive::symbol_iterator E = A->symbol_end();
- if (I != E) {
+ auto Map = A->symbols();
+ if (!Map.empty()) {
outs() << "Archive map\n";
- for (; I != E; ++I) {
- Expected<Archive::Child> C = I->getMember();
- if (!C) {
- error(C.takeError(), Filename);
- break;
- }
- Expected<StringRef> FileNameOrErr = C->getName();
- if (!FileNameOrErr) {
- error(FileNameOrErr.takeError(), Filename);
- break;
- }
- StringRef SymName = I->getName();
- outs() << SymName << " in " << FileNameOrErr.get() << "\n";
- }
- outs() << "\n";
+ printArchiveMap(Map, Filename);
+ }
+
+ auto ECMap = A->ec_symbols();
+ if (!ECMap) {
+ warn(ECMap.takeError(), Filename);
+ } else if (!ECMap->empty()) {
+ outs() << "Archive EC map\n";
+ printArchiveMap(*ECMap, Filename);
}
}
@@ -2261,11 +2267,7 @@ static std::vector<NMSymbol> dumpSymbolNamesFromFile(StringRef Filename) {
if (error(BufferOrErr.getError(), Filename))
return SymbolList;
- // Always enable opaque pointers, to handle archives with mixed typed and
- // opaque pointer bitcode files gracefully. As we're only reading symbols,
- // the used pointer types don't matter.
LLVMContext Context;
- Context.setOpaquePointers(true);
LLVMContext *ContextPtr = NoLLVMBitcode ? nullptr : &Context;
Expected<std::unique_ptr<Binary>> BinaryOrErr =
createBinary(BufferOrErr.get()->getMemBufferRef(), ContextPtr);
@@ -2302,7 +2304,7 @@ exportSymbolNamesFromFiles(const std::vector<std::string> &InputFilenames) {
printExportSymbolList(SymbolList);
}
-int llvm_nm_main(int argc, char **argv) {
+int llvm_nm_main(int argc, char **argv, const llvm::ToolContext &) {
InitLLVM X(argc, argv);
BumpPtrAllocator A;
StringSaver Saver(A);
diff --git a/contrib/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/contrib/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index 577b837320ae..265e4fc6073c 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -8,6 +8,7 @@
#include "ObjcopyOptions.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/BinaryFormat/COFF.h"
@@ -331,7 +332,11 @@ static const StringMap<MachineInfo> TargetMap{
// SPARC
{"elf32-sparc", {ELF::EM_SPARC, false, false}},
{"elf32-sparcel", {ELF::EM_SPARC, false, true}},
+ // Hexagon
{"elf32-hexagon", {ELF::EM_HEXAGON, false, true}},
+ // LoongArch
+ {"elf32-loongarch", {ELF::EM_LOONGARCH, false, true}},
+ {"elf64-loongarch", {ELF::EM_LOONGARCH, true, true}},
};
static Expected<TargetInfo>
diff --git a/contrib/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/contrib/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td
index 0fddd443a4cc..a7e4263271d3 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td
+++ b/contrib/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -27,7 +27,7 @@ def O : JoinedOrSeparate<["-"], "O">,
defm new_symbol_visibility : Eq<"new-symbol-visibility", "Visibility of "
"symbols generated for binary input or added"
" with --add-symbol unless otherwise"
- " specified. The default value is 'default'.">;
+ " specified. The default value is 'default'">;
def compress_debug_sections
: Joined<["--"], "compress-debug-sections=">,
@@ -37,7 +37,7 @@ def compress_debug_sections
def : Flag<["--"], "compress-debug-sections">, Alias<compress_debug_sections>,
AliasArgs<["zlib"]>;
def decompress_debug_sections : Flag<["--"], "decompress-debug-sections">,
- HelpText<"Decompress DWARF debug sections.">;
+ HelpText<"Decompress DWARF debug sections">;
defm split_dwo
: Eq<"split-dwo", "Equivalent to extract-dwo on the input file to "
"<dwo-file>, then strip-dwo on the input file">,
@@ -52,7 +52,7 @@ defm rename_section
"Renames a section from old to new, optionally with specified flags. "
"Flags supported for GNU compatibility: alloc, load, noload, "
"readonly, exclude, debug, code, data, rom, share, contents, merge, "
- "strings.">,
+ "strings">,
MetaVarName<"old=new[,flag1,...]">;
defm redefine_symbol
: Eq<"redefine-sym", "Change the name of a symbol old to new">,
@@ -64,7 +64,7 @@ defm redefine_symbols
"contains two symbols per line separated with whitespace and may "
"contain comments beginning with '#'. Leading and trailing "
"whitespace is stripped from each line. May be repeated to read "
- "symbols from many files.">,
+ "symbols from many files">,
MetaVarName<"filename">;
defm only_section : Eq<"only-section", "Remove all but <section>">,
@@ -74,18 +74,18 @@ def j : JoinedOrSeparate<["-"], "j">,
HelpText<"Alias for --only-section">;
defm add_section
: Eq<"add-section",
- "Make a section named <section> with the contents of <file>.">,
+ "Make a section named <section> with the contents of <file>">,
MetaVarName<"section=file">;
defm set_section_alignment
- : Eq<"set-section-alignment", "Set alignment for a given section.">,
+ : Eq<"set-section-alignment", "Set alignment for a given section">,
MetaVarName<"section=align">;
defm set_section_flags
: Eq<"set-section-flags",
"Set section flags for a given section. Flags supported for GNU "
"compatibility: alloc, load, noload, readonly, exclude, debug, code, "
- "data, rom, share, contents, merge, strings.">,
+ "data, rom, share, contents, merge, strings">,
MetaVarName<"section=flag1[,flag2,...]">;
defm set_section_type
@@ -136,7 +136,7 @@ defm localize_symbol : Eq<"localize-symbol", "Mark <symbol> as local">,
MetaVarName<"symbol">;
defm localize_symbols
: Eq<"localize-symbols",
- "Reads a list of symbols from <filename> and marks them local.">,
+ "Reads a list of symbols from <filename> and marks them local">,
MetaVarName<"filename">;
def L : JoinedOrSeparate<["-"], "L">,
@@ -148,13 +148,13 @@ defm globalize_symbol : Eq<"globalize-symbol", "Mark <symbol> as global">,
defm globalize_symbols
: Eq<"globalize-symbols",
- "Reads a list of symbols from <filename> and marks them global.">,
+ "Reads a list of symbols from <filename> and marks them global">,
MetaVarName<"filename">;
defm keep_global_symbol
: Eq<"keep-global-symbol",
"Convert all symbols except <symbol> to local. May be repeated to "
- "convert all except a set of symbols to local.">,
+ "convert all except a set of symbols to local">,
MetaVarName<"symbol">;
def G : JoinedOrSeparate<["-"], "G">,
Alias<keep_global_symbol>,
@@ -166,14 +166,14 @@ defm keep_global_symbols
"--keep-global-symbol=<symbol> is set for each one. <filename> "
"contains one symbol per line and may contain comments beginning with "
"'#'. Leading and trailing whitespace is stripped from each line. May "
- "be repeated to read symbols from many files.">,
+ "be repeated to read symbols from many files">,
MetaVarName<"filename">;
defm weaken_symbol : Eq<"weaken-symbol", "Mark <symbol> as weak">,
MetaVarName<"symbol">;
defm weaken_symbols
: Eq<"weaken-symbols",
- "Reads a list of symbols from <filename> and marks them weak.">,
+ "Reads a list of symbols from <filename> and marks them weak">,
MetaVarName<"filename">;
def W : JoinedOrSeparate<["-"], "W">,
@@ -184,7 +184,7 @@ def weaken : Flag<["--"], "weaken">,
defm strip_symbols
: Eq<"strip-symbols",
- "Reads a list of symbols from <filename> and removes them.">,
+ "Reads a list of symbols from <filename> and removes them">,
MetaVarName<"filename">;
defm keep_symbols
@@ -193,7 +193,7 @@ defm keep_symbols
"--keep-symbol=<symbol> is set for each one. <filename> "
"contains one symbol per line and may contain comments beginning with "
"'#'. Leading and trailing whitespace is stripped from each line. May "
- "be repeated to read symbols from many files.">,
+ "be repeated to read symbols from many files">,
MetaVarName<"filename">;
defm dump_section
@@ -209,11 +209,11 @@ defm prefix_alloc_sections
MetaVarName<"prefix">;
defm set_start : Eq<"set-start", "Set the start address to <addr>. Overrides "
- "any previous --change-start or --adjust-start values.">,
+ "any previous --change-start or --adjust-start values">,
MetaVarName<"addr">;
defm change_start : Eq<"change-start", "Add <incr> to the start address. Can be "
"specified multiple times, all values will be applied "
- "cumulatively.">,
+ "cumulatively">,
MetaVarName<"incr">;
def adjust_start : JoinedOrSeparate<["--"], "adjust-start">,
Alias<change_start>,
@@ -224,9 +224,9 @@ defm add_symbol
"global, local, weak, default, hidden, protected, file, section, object, "
"function, indirect-function. Accepted but ignored for "
"compatibility: debug, constructor, warning, indirect, synthetic, "
- "unique-object, before.">,
+ "unique-object, before">,
MetaVarName<"name=[section:]value[,flags]">;
defm update_section
- : Eq<"update-section", "Replace the contents of section <name> with contents from a file <file>.">,
+ : Eq<"update-section", "Replace the contents of section <name> with contents from a file <file>">,
MetaVarName<"name=file">;
diff --git a/contrib/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/contrib/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
index a24cd889b83f..2afa97601f5c 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -42,8 +42,8 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LLVMDriver.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
@@ -51,6 +51,7 @@
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Host.h"
#include <algorithm>
#include <cassert>
#include <cstdlib>
@@ -223,7 +224,7 @@ static Error executeObjcopy(ConfigManager &ConfigMgr) {
return Error::success();
}
-int llvm_objcopy_main(int argc, char **argv) {
+int llvm_objcopy_main(int argc, char **argv, const llvm::ToolContext &) {
InitLLVM X(argc, argv);
ToolName = argv[0];
diff --git a/contrib/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp b/contrib/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp
index 3bc7d3ce33b0..e1b38471c77f 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp
@@ -37,13 +37,15 @@ template <typename T> struct EnumEntry {
StringRef Name;
};
-class COFFDumper {
+class COFFDumper : public Dumper {
public:
- explicit COFFDumper(const llvm::object::COFFObjectFile &Obj) : Obj(Obj) {
+ explicit COFFDumper(const llvm::object::COFFObjectFile &O)
+ : Dumper(O), Obj(O) {
Is64 = !Obj.getPE32Header();
}
template <class PEHeader> void printPEHeader(const PEHeader &Hdr) const;
+ void printPrivateHeaders(bool MachOOnlyFirst) override;
private:
template <typename T> FormattedNumber formatAddr(T V) const {
@@ -59,6 +61,11 @@ private:
};
} // namespace
+std::unique_ptr<Dumper>
+objdump::createCOFFDumper(const object::COFFObjectFile &Obj) {
+ return std::make_unique<COFFDumper>(Obj);
+}
+
constexpr EnumEntry<uint16_t> PEHeaderMagic[] = {
{uint16_t(COFF::PE32Header::PE32), "PE32"},
{uint16_t(COFF::PE32Header::PE32_PLUS), "PE32+"},
@@ -545,12 +552,18 @@ static void printExportTable(const COFFObjectFile *Obj) {
outs() << " Ordinal base: " << OrdinalBase << "\n";
outs() << " Ordinal RVA Name\n";
for (; I != E; I = ++I) {
- uint32_t Ordinal;
- if (I->getOrdinal(Ordinal))
- return;
uint32_t RVA;
if (I->getExportRVA(RVA))
return;
+ StringRef Name;
+ if (I->getSymbolName(Name))
+ continue;
+ if (!RVA && Name.empty())
+ continue;
+
+ uint32_t Ordinal;
+ if (I->getOrdinal(Ordinal))
+ return;
bool IsForwarder;
if (I->isForwarder(IsForwarder))
return;
@@ -559,14 +572,11 @@ static void printExportTable(const COFFObjectFile *Obj) {
// Export table entries can be used to re-export symbols that
// this COFF file is imported from some DLLs. This is rare.
// In most cases IsForwarder is false.
- outs() << format(" % 4d ", Ordinal);
+ outs() << format(" %5d ", Ordinal);
} else {
- outs() << format(" % 4d %# 8x", Ordinal, RVA);
+ outs() << format(" %5d %# 8x", Ordinal, RVA);
}
- StringRef Name;
- if (I->getSymbolName(Name))
- continue;
if (!Name.empty())
outs() << " " << Name;
if (IsForwarder) {
@@ -761,7 +771,7 @@ void objdump::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
}
}
-void objdump::printCOFFFileHeader(const COFFObjectFile &Obj) {
+void COFFDumper::printPrivateHeaders(bool MachOOnlyFirst) {
COFFDumper CD(Obj);
const uint16_t Cha = Obj.getCharacteristics();
outs() << "Characteristics 0x" << Twine::utohexstr(Cha) << '\n';
@@ -849,8 +859,7 @@ void objdump::printCOFFSymbolTable(const COFFObjectFile &coff) {
<< Name;
if (Demangle && Name.startswith("?")) {
int Status = -1;
- char *DemangledSymbol =
- microsoftDemangle(Name.data(), nullptr, nullptr, nullptr, &Status);
+ char *DemangledSymbol = microsoftDemangle(Name, nullptr, &Status);
if (Status == 0 && DemangledSymbol) {
outs() << " (" << StringRef(DemangledSymbol) << ")";
diff --git a/contrib/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp b/contrib/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp
index b98b45e3015a..5b08a4b12858 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp
@@ -24,6 +24,39 @@ using namespace llvm;
using namespace llvm::object;
using namespace llvm::objdump;
+namespace {
+template <typename ELFT> class ELFDumper : public Dumper {
+public:
+ ELFDumper(const ELFObjectFile<ELFT> &O) : Dumper(O), Obj(O) {}
+ void printPrivateHeaders(bool MachOOnlyFirst) override;
+ void printDynamicRelocations() override;
+
+private:
+ const ELFObjectFile<ELFT> &Obj;
+
+ const ELFFile<ELFT> &getELFFile() const { return Obj.getELFFile(); }
+ void printDynamicSection();
+ void printProgramHeaders();
+ void printSymbolVersion();
+};
+} // namespace
+
+template <class ELFT>
+static std::unique_ptr<Dumper> createDumper(const ELFObjectFile<ELFT> &Obj) {
+ return std::make_unique<ELFDumper<ELFT>>(Obj);
+}
+
+std::unique_ptr<Dumper>
+objdump::createELFDumper(const object::ELFObjectFileBase &Obj) {
+ if (const auto *O = dyn_cast<ELF32LEObjectFile>(&Obj))
+ return createDumper(*O);
+ if (const auto *O = dyn_cast<ELF32BEObjectFile>(&Obj))
+ return createDumper(*O);
+ if (const auto *O = dyn_cast<ELF64LEObjectFile>(&Obj))
+ return createDumper(*O);
+ return createDumper(cast<ELF64BEObjectFile>(Obj));
+}
+
template <class ELFT>
static Expected<StringRef> getDynamicStrTab(const ELFFile<ELFT> &Elf) {
auto DynamicEntriesOrError = Elf.dynamicEntries();
@@ -108,10 +141,7 @@ static Error getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
Expected<StringRef> SymName = SI->getName();
if (!SymName)
return SymName.takeError();
- if (Demangle)
- Fmt << demangle(std::string(*SymName));
- else
- Fmt << *SymName;
+ Fmt << (Demangle ? demangle(*SymName) : *SymName);
}
} else {
Fmt << "*ABS*";
@@ -169,11 +199,11 @@ uint64_t objdump::getELFSectionLMA(const object::ELFSectionRef &Sec) {
return getSectionLMA(ELFObj->getELFFile(), Sec);
}
-template <class ELFT>
-static void printDynamicSection(const ELFFile<ELFT> &Elf, StringRef Filename) {
+template <class ELFT> void ELFDumper<ELFT>::printDynamicSection() {
+ const ELFFile<ELFT> &Elf = getELFFile();
auto DynamicEntriesOrErr = Elf.dynamicEntries();
if (!DynamicEntriesOrErr) {
- reportWarning(toString(DynamicEntriesOrErr.takeError()), Filename);
+ reportWarning(toString(DynamicEntriesOrErr.takeError()), Obj.getFileName());
return;
}
ArrayRef<typename ELFT::Dyn> DynamicEntries = *DynamicEntriesOrErr;
@@ -203,21 +233,20 @@ static void printDynamicSection(const ELFFile<ELFT> &Elf, StringRef Filename) {
outs() << (Data + Dyn.d_un.d_val) << "\n";
continue;
}
- reportWarning(toString(StrTabOrErr.takeError()), Filename);
+ reportWarning(toString(StrTabOrErr.takeError()), Obj.getFileName());
consumeError(StrTabOrErr.takeError());
}
outs() << format(Fmt, (uint64_t)Dyn.d_un.d_val);
}
}
-template <class ELFT>
-static void printProgramHeaders(const ELFFile<ELFT> &Obj, StringRef FileName) {
+template <class ELFT> void ELFDumper<ELFT>::printProgramHeaders() {
outs() << "\nProgram Header:\n";
- auto ProgramHeaderOrError = Obj.program_headers();
+ auto ProgramHeaderOrError = getELFFile().program_headers();
if (!ProgramHeaderOrError) {
reportWarning("unable to read program headers: " +
toString(ProgramHeaderOrError.takeError()),
- FileName);
+ Obj.getFileName());
return;
}
@@ -274,8 +303,7 @@ static void printProgramHeaders(const ELFFile<ELFT> &Obj, StringRef FileName) {
outs() << "off " << format(Fmt, (uint64_t)Phdr.p_offset) << "vaddr "
<< format(Fmt, (uint64_t)Phdr.p_vaddr) << "paddr "
<< format(Fmt, (uint64_t)Phdr.p_paddr)
- << format("align 2**%u\n",
- countTrailingZeros<uint64_t>(Phdr.p_align))
+ << format("align 2**%u\n", llvm::countr_zero<uint64_t>(Phdr.p_align))
<< " filesz " << format(Fmt, (uint64_t)Phdr.p_filesz)
<< "memsz " << format(Fmt, (uint64_t)Phdr.p_memsz) << "flags "
<< ((Phdr.p_flags & ELF::PF_R) ? "r" : "-")
@@ -284,6 +312,39 @@ static void printProgramHeaders(const ELFFile<ELFT> &Obj, StringRef FileName) {
}
}
+template <typename ELFT> void ELFDumper<ELFT>::printDynamicRelocations() {
+ if (!any_of(Obj.sections(), [](const ELFSectionRef Sec) {
+ return Sec.getType() == ELF::SHT_DYNAMIC;
+ })) {
+ reportError(Obj.getFileName(), "not a dynamic object");
+ return;
+ }
+
+ std::vector<SectionRef> DynRelSec =
+ cast<ObjectFile>(Obj).dynamic_relocation_sections();
+ if (DynRelSec.empty())
+ return;
+
+ outs() << "\nDYNAMIC RELOCATION RECORDS\n";
+ const uint32_t OffsetPadding = (Obj.getBytesInAddress() > 4 ? 16 : 8);
+ const uint32_t TypePadding = 24;
+ outs() << left_justify("OFFSET", OffsetPadding) << ' '
+ << left_justify("TYPE", TypePadding) << " VALUE\n";
+
+ StringRef Fmt = Obj.getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
+ for (const SectionRef &Section : DynRelSec)
+ for (const RelocationRef &Reloc : Section.relocations()) {
+ uint64_t Address = Reloc.getOffset();
+ SmallString<32> RelocName;
+ SmallString<32> ValueStr;
+ Reloc.getTypeName(RelocName);
+ if (Error E = getELFRelocationValueString(&Obj, Reloc, ValueStr))
+ reportError(std::move(E), Obj.getFileName());
+ outs() << format(Fmt.data(), Address) << ' '
+ << left_justify(RelocName, TypePadding) << ' ' << ValueStr << '\n';
+ }
+}
+
template <class ELFT>
static void printSymbolVersionDependency(StringRef FileName,
const ELFFile<ELFT> &Obj,
@@ -342,9 +403,9 @@ static void printSymbolVersionDefinition(const typename ELFT::Shdr &Shdr,
}
}
-template <class ELFT>
-static void printSymbolVersionInfo(const ELFFile<ELFT> &Elf,
- StringRef FileName) {
+template <class ELFT> void ELFDumper<ELFT>::printSymbolVersion() {
+ const ELFFile<ELFT> &Elf = getELFFile();
+ StringRef FileName = Obj.getFileName();
ArrayRef<typename ELFT::Shdr> Sections =
unwrapOrError(Elf.sections(), FileName);
for (const typename ELFT::Shdr &Shdr : Sections) {
@@ -365,35 +426,8 @@ static void printSymbolVersionInfo(const ELFFile<ELFT> &Elf,
}
}
-void objdump::printELFFileHeader(const object::ObjectFile *Obj) {
- if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
- printProgramHeaders(ELFObj->getELFFile(), Obj->getFileName());
- else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
- printProgramHeaders(ELFObj->getELFFile(), Obj->getFileName());
- else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
- printProgramHeaders(ELFObj->getELFFile(), Obj->getFileName());
- else if (const auto *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
- printProgramHeaders(ELFObj->getELFFile(), Obj->getFileName());
-}
-
-void objdump::printELFDynamicSection(const object::ObjectFile *Obj) {
- if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
- printDynamicSection(ELFObj->getELFFile(), Obj->getFileName());
- else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
- printDynamicSection(ELFObj->getELFFile(), Obj->getFileName());
- else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
- printDynamicSection(ELFObj->getELFFile(), Obj->getFileName());
- else if (const auto *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
- printDynamicSection(ELFObj->getELFFile(), Obj->getFileName());
-}
-
-void objdump::printELFSymbolVersionInfo(const object::ObjectFile *Obj) {
- if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
- printSymbolVersionInfo(ELFObj->getELFFile(), Obj->getFileName());
- else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
- printSymbolVersionInfo(ELFObj->getELFFile(), Obj->getFileName());
- else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
- printSymbolVersionInfo(ELFObj->getELFFile(), Obj->getFileName());
- else if (const auto *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
- printSymbolVersionInfo(ELFObj->getELFFile(), Obj->getFileName());
+template <class ELFT> void ELFDumper<ELFT>::printPrivateHeaders(bool) {
+ printProgramHeaders();
+ printDynamicSection();
+ printSymbolVersion();
}
diff --git a/contrib/llvm-project/llvm/tools/llvm-objdump/ELFDump.h b/contrib/llvm-project/llvm/tools/llvm-objdump/ELFDump.h
index 9b6b1f341cf3..205c3d256e2b 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objdump/ELFDump.h
+++ b/contrib/llvm-project/llvm/tools/llvm-objdump/ELFDump.h
@@ -30,8 +30,6 @@ Error getELFRelocationValueString(const object::ELFObjectFileBase *Obj,
uint64_t getELFSectionLMA(const object::ELFSectionRef &Sec);
void printELFFileHeader(const object::ObjectFile *O);
-void printELFDynamicSection(const object::ObjectFile *Obj);
-void printELFSymbolVersionInfo(const object::ObjectFile *Obj);
} // namespace objdump
} // namespace llvm
diff --git a/contrib/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp b/contrib/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp
index fadc8367a8c1..11fb1cb41a9f 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp
@@ -17,7 +17,6 @@
#include "llvm-c/Disassembler.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/Config/config.h"
#include "llvm/DebugInfo/DIContext.h"
@@ -49,6 +48,7 @@
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <cstring>
#include <system_error>
@@ -191,8 +191,21 @@ struct SymbolSorter {
return AAddr < BAddr;
}
};
+
+class MachODumper : public Dumper {
+ const object::MachOObjectFile &Obj;
+
+public:
+ MachODumper(const object::MachOObjectFile &O) : Dumper(O), Obj(O) {}
+ void printPrivateHeaders(bool OnlyFirst) override;
+};
} // namespace
+std::unique_ptr<Dumper>
+objdump::createMachODumper(const object::MachOObjectFile &Obj) {
+ return std::make_unique<MachODumper>(Obj);
+}
+
// Types for the storted data in code table that is built before disassembly
// and the predicate function to sort them.
typedef std::pair<uint64_t, DiceRef> DiceTableEntry;
@@ -2142,6 +2155,8 @@ static void printObjcMetaData(MachOObjectFile *O, bool verbose);
static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
StringRef ArchiveMemberName = StringRef(),
StringRef ArchitectureName = StringRef()) {
+ std::unique_ptr<Dumper> D = createMachODumper(*MachOOF);
+
// If we are doing some processing here on the Mach-O file print the header
// info. And don't print it otherwise like in the case of printing the
// UniversalHeaders or ArchiveHeaders.
@@ -2227,7 +2242,7 @@ static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
if (DylibId)
PrintDylibs(MachOOF, true);
if (SymbolTable)
- printSymbolTable(*MachOOF, ArchiveName, ArchitectureName);
+ D->printSymbolTable(ArchiveName, ArchitectureName);
if (UnwindInfo)
printMachOUnwindInfo(MachOOF);
if (PrivateHeaders) {
@@ -7280,9 +7295,7 @@ static const char *SymbolizerSymbolLookUp(void *DisInfo,
} else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
if (info->demangled_name != nullptr)
free(info->demangled_name);
- int status;
- info->demangled_name =
- itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status);
+ info->demangled_name = itaniumDemangle(SymbolName + 1);
if (info->demangled_name != nullptr) {
*ReferenceName = info->demangled_name;
*ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
@@ -7380,9 +7393,7 @@ static const char *SymbolizerSymbolLookUp(void *DisInfo,
} else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
if (info->demangled_name != nullptr)
free(info->demangled_name);
- int status;
- info->demangled_name =
- itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status);
+ info->demangled_name = itaniumDemangle(SymbolName + 1);
if (info->demangled_name != nullptr) {
*ReferenceName = info->demangled_name;
*ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
@@ -10362,6 +10373,8 @@ static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld,
outs() << " cmd LC_DYLD_EXPORTS_TRIE\n";
else if (ld.cmd == MachO::LC_DYLD_CHAINED_FIXUPS)
outs() << " cmd LC_DYLD_CHAINED_FIXUPS\n";
+ else if (ld.cmd == MachO::LC_ATOM_INFO)
+ outs() << " cmd LC_ATOM_INFO\n";
else
outs() << " cmd " << ld.cmd << " (?)\n";
outs() << " cmdsize " << ld.cmdsize;
@@ -10507,7 +10520,8 @@ static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS ||
Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT ||
Command.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE ||
- Command.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS) {
+ Command.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS ||
+ Command.C.cmd == MachO::LC_ATOM_INFO) {
MachO::linkedit_data_command Ld =
Obj->getLinkeditDataLoadCommand(Command);
PrintLinkEditDataCommand(Ld, Buf.size());
@@ -10540,6 +10554,12 @@ void objdump::printMachOFileHeader(const object::ObjectFile *Obj) {
PrintMachHeader(file, Verbose);
}
+void MachODumper::printPrivateHeaders(bool OnlyFirst) {
+ printMachOFileHeader(&Obj);
+ if (!OnlyFirst)
+ printMachOLoadCommands(&Obj);
+}
+
void objdump::printMachOLoadCommands(const object::ObjectFile *Obj) {
const MachOObjectFile *file = cast<const MachOObjectFile>(Obj);
uint32_t filetype = 0;
diff --git a/contrib/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td b/contrib/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td
index c6627c75157b..e3e74762420d 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td
+++ b/contrib/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td
@@ -65,7 +65,11 @@ def : Flag<["-"], "D">, Alias<disassemble_all>,
def symbol_description : Flag<["--"], "symbol-description">,
HelpText<"Add symbol description for disassembly. This "
- "option is for XCOFF files only.">;
+ "option is for XCOFF files only">;
+
+def traceback_table : Flag<["--"], "traceback-table">,
+ HelpText<"Decode traceback table in disassembly. Implies --disassemble. "
+ "This option is for XCOFF files only">;
def disassemble_symbols_EQ : Joined<["--"], "disassemble-symbols=">,
HelpText<"List of symbols to disassemble. "
diff --git a/contrib/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp b/contrib/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp
index 6736cbc9ad5f..b2fe56cf2e1c 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp
@@ -26,10 +26,6 @@
namespace llvm {
namespace objdump {
-unsigned getInstStartColumn(const MCSubtargetInfo &STI) {
- return !ShowRawInsn ? 16 : STI.getTargetTriple().isX86() ? 40 : 24;
-}
-
bool LiveVariable::liveAtAddress(object::SectionedAddress Addr) {
if (LocExpr.Range == std::nullopt)
return false;
@@ -452,6 +448,34 @@ void SourcePrinter::printLines(formatted_raw_ostream &OS,
}
}
+// Get the source line text for LineInfo:
+// - use LineInfo::LineSource if available;
+// - use LineCache if LineInfo::Source otherwise.
+StringRef SourcePrinter::getLine(const DILineInfo &LineInfo,
+ StringRef ObjectFilename) {
+ if (LineInfo.LineSource)
+ return LineInfo.LineSource.value();
+
+ if (SourceCache.find(LineInfo.FileName) == SourceCache.end())
+ if (!cacheSource(LineInfo))
+ return {};
+
+ auto LineBuffer = LineCache.find(LineInfo.FileName);
+ if (LineBuffer == LineCache.end())
+ return {};
+
+ if (LineInfo.Line > LineBuffer->second.size()) {
+ reportWarning(
+ formatv("debug info line number {0} exceeds the number of lines in {1}",
+ LineInfo.Line, LineInfo.FileName),
+ ObjectFilename);
+ return {};
+ }
+
+ // Vector begins at 0, line numbers are non-zero
+ return LineBuffer->second[LineInfo.Line - 1];
+}
+
void SourcePrinter::printSources(formatted_raw_ostream &OS,
const DILineInfo &LineInfo,
StringRef ObjectFilename, StringRef Delimiter,
@@ -461,21 +485,9 @@ void SourcePrinter::printSources(formatted_raw_ostream &OS,
OldLineInfo.FileName == LineInfo.FileName))
return;
- if (SourceCache.find(LineInfo.FileName) == SourceCache.end())
- if (!cacheSource(LineInfo))
- return;
- auto LineBuffer = LineCache.find(LineInfo.FileName);
- if (LineBuffer != LineCache.end()) {
- if (LineInfo.Line > LineBuffer->second.size()) {
- reportWarning(
- formatv(
- "debug info line number {0} exceeds the number of lines in {1}",
- LineInfo.Line, LineInfo.FileName),
- ObjectFilename);
- return;
- }
- // Vector begins at 0, line numbers are non-zero
- OS << Delimiter << LineBuffer->second[LineInfo.Line - 1];
+ StringRef Line = getLine(LineInfo, ObjectFilename);
+ if (!Line.empty()) {
+ OS << Delimiter << Line;
LVP.printBetweenInsts(OS, true);
}
}
diff --git a/contrib/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.h b/contrib/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.h
index 6209bb0e43e4..fc67fc650744 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.h
+++ b/contrib/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.h
@@ -151,6 +151,10 @@ private:
StringRef ObjectFilename, StringRef Delimiter,
LiveVariablePrinter &LVP);
+ // Returns line source code corresponding to `LineInfo`.
+ // Returns empty string if source code cannot be found.
+ StringRef getLine(const DILineInfo &LineInfo, StringRef ObjectFilename);
+
public:
SourcePrinter() = default;
SourcePrinter(const object::ObjectFile *Obj, StringRef DefaultArch);
diff --git a/contrib/llvm-project/llvm/tools/llvm-objdump/WasmDump.cpp b/contrib/llvm-project/llvm/tools/llvm-objdump/WasmDump.cpp
index df0a08e5b1dd..a1d767d81003 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objdump/WasmDump.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-objdump/WasmDump.cpp
@@ -19,12 +19,25 @@
using namespace llvm;
using namespace llvm::object;
-void objdump::printWasmFileHeader(const object::ObjectFile *Obj) {
- const auto *File = cast<const WasmObjectFile>(Obj);
+namespace {
+class WasmDumper : public objdump::Dumper {
+ const WasmObjectFile &Obj;
+public:
+ WasmDumper(const WasmObjectFile &O) : Dumper(O), Obj(O) {}
+ void printPrivateHeaders(bool MachOOnlyFirst) override;
+};
+} // namespace
+
+std::unique_ptr<objdump::Dumper>
+objdump::createWasmDumper(const object::WasmObjectFile &Obj) {
+ return std::make_unique<WasmDumper>(Obj);
+}
+
+void WasmDumper::printPrivateHeaders(bool) {
outs() << "Program Header:\n";
outs() << "Version: 0x";
- outs().write_hex(File->getHeader().Version);
+ outs().write_hex(Obj.getHeader().Version);
outs() << "\n";
}
diff --git a/contrib/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp b/contrib/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp
index 7171e2eb6eb3..87b1679a7969 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp
@@ -14,10 +14,34 @@
#include "XCOFFDump.h"
#include "llvm-objdump.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Demangle/Demangle.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/FormattedStream.h"
+#include <algorithm>
using namespace llvm;
using namespace llvm::object;
+using namespace llvm::XCOFF;
+using namespace llvm::support;
+
+namespace {
+class XCOFFDumper : public objdump::Dumper {
+public:
+ XCOFFDumper(const object::XCOFFObjectFile &O) : Dumper(O) {}
+ void printPrivateHeaders(bool MachOOnlyFirst) override;
+};
+} // namespace
+
+std::unique_ptr<objdump::Dumper>
+objdump::createXCOFFDumper(const object::XCOFFObjectFile &Obj) {
+ return std::make_unique<XCOFFDumper>(Obj);
+}
+
+void XCOFFDumper::printPrivateHeaders(bool) {}
Error objdump::getXCOFFRelocationValueString(const XCOFFObjectFile &Obj,
const RelocationRef &Rel,
@@ -32,10 +56,8 @@ Error objdump::getXCOFFRelocationValueString(const XCOFFObjectFile &Obj,
if (!SymNameOrErr)
return SymNameOrErr.takeError();
- std::string SymName = (*SymNameOrErr).str();
- if (Demangle)
- SymName = demangle(SymName);
-
+ std::string SymName =
+ Demangle ? demangle(*SymNameOrErr) : SymNameOrErr->str();
if (SymbolDescription)
SymName = getXCOFFSymbolDescription(createSymbolInfo(Obj, *SymI), SymName);
@@ -109,3 +131,299 @@ std::string objdump::getXCOFFSymbolDescription(const SymbolInfoTy &SymbolInfo,
return Result;
}
+
+#define PRINTBOOL(Prefix, Obj, Field) \
+ OS << Prefix << " " << ((Obj.Field()) ? "+" : "-") << #Field
+
+#define PRINTGET(Prefix, Obj, Field) \
+ OS << Prefix << " " << #Field << " = " \
+ << static_cast<unsigned>(Obj.get##Field())
+
+#define PRINTOPTIONAL(Field) \
+ if (TbTable.get##Field()) { \
+ OS << '\n'; \
+ printRawData(Bytes.slice(Index, 4), Address + Index, OS, STI); \
+ Index += 4; \
+ OS << "\t# " << #Field << " = " << *TbTable.get##Field(); \
+ }
+
+void objdump::dumpTracebackTable(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ formatted_raw_ostream &OS, uint64_t End,
+ const MCSubtargetInfo &STI,
+ const XCOFFObjectFile *Obj) {
+ uint64_t Index = 0;
+ unsigned TabStop = getInstStartColumn(STI) - 1;
+ // Print traceback table boundary.
+ printRawData(Bytes.slice(Index, 4), Address, OS, STI);
+ OS << "\t# Traceback table start\n";
+ Index += 4;
+
+ uint64_t Size = End - Address;
+ bool Is64Bit = Obj->is64Bit();
+
+ // XCOFFTracebackTable::create modifies the size parameter, so ensure Size
+ // isn't changed.
+ uint64_t SizeCopy = End - Address;
+ Expected<XCOFFTracebackTable> TTOrErr =
+ XCOFFTracebackTable::create(Bytes.data() + Index, SizeCopy, Is64Bit);
+
+ if (!TTOrErr) {
+ std::string WarningMsgStr;
+ raw_string_ostream WarningStream(WarningMsgStr);
+ WarningStream << "failure parsing traceback table with address: 0x"
+ << utohexstr(Address) + "\n>>> "
+ << toString(TTOrErr.takeError())
+ << "\n>>> Raw traceback table data is:\n";
+
+ uint64_t LastNonZero = Index;
+ for (uint64_t I = Index; I < Size; I += 4)
+ if (support::endian::read32be(Bytes.slice(I, 4).data()) != 0)
+ LastNonZero = I + 4 > Size ? Size : I + 4;
+
+ if (Size - LastNonZero <= 4)
+ LastNonZero = Size;
+
+ formatted_raw_ostream FOS(WarningStream);
+ while (Index < LastNonZero) {
+ printRawData(Bytes.slice(Index, 4), Address + Index, FOS, STI);
+ Index += 4;
+ WarningStream << '\n';
+ }
+
+ // Print all remaining zeroes as ...
+ if (Size - LastNonZero >= 8)
+ WarningStream << "\t\t...\n";
+
+ reportWarning(WarningMsgStr, Obj->getFileName());
+ return;
+ }
+
+ auto PrintBytes = [&](uint64_t N) {
+ printRawData(Bytes.slice(Index, N), Address + Index, OS, STI);
+ Index += N;
+ };
+
+ XCOFFTracebackTable TbTable = *TTOrErr;
+ // Print the first of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ OS << format("\t# Version = %i", TbTable.getVersion()) << '\n';
+
+ // Print the second of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ TracebackTable::LanguageID LangId =
+ static_cast<TracebackTable::LanguageID>(TbTable.getLanguageID());
+ OS << "\t# Language = " << getNameForTracebackTableLanguageId(LangId) << '\n';
+
+ auto Split = [&]() {
+ OS << '\n';
+ OS.indent(TabStop);
+ };
+
+ // Print the third of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ PRINTBOOL("\t#", TbTable, isGlobalLinkage);
+ PRINTBOOL(",", TbTable, isOutOfLineEpilogOrPrologue);
+ Split();
+ PRINTBOOL("\t ", TbTable, hasTraceBackTableOffset);
+ PRINTBOOL(",", TbTable, isInternalProcedure);
+ Split();
+ PRINTBOOL("\t ", TbTable, hasControlledStorage);
+ PRINTBOOL(",", TbTable, isTOCless);
+ Split();
+ PRINTBOOL("\t ", TbTable, isFloatingPointPresent);
+ Split();
+ PRINTBOOL("\t ", TbTable, isFloatingPointOperationLogOrAbortEnabled);
+ OS << '\n';
+
+ // Print the 4th of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ PRINTBOOL("\t#", TbTable, isInterruptHandler);
+ PRINTBOOL(",", TbTable, isFuncNamePresent);
+ PRINTBOOL(",", TbTable, isAllocaUsed);
+ Split();
+ PRINTGET("\t ", TbTable, OnConditionDirective);
+ PRINTBOOL(",", TbTable, isCRSaved);
+ PRINTBOOL(",", TbTable, isLRSaved);
+ OS << '\n';
+
+ // Print the 5th of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ PRINTBOOL("\t#", TbTable, isBackChainStored);
+ PRINTBOOL(",", TbTable, isFixup);
+ PRINTGET(",", TbTable, NumOfFPRsSaved);
+ OS << '\n';
+
+ // Print the 6th of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ PRINTBOOL("\t#", TbTable, hasExtensionTable);
+ PRINTBOOL(",", TbTable, hasVectorInfo);
+ PRINTGET(",", TbTable, NumOfGPRsSaved);
+ OS << '\n';
+
+ // Print the 7th of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ PRINTGET("\t#", TbTable, NumberOfFixedParms);
+ OS << '\n';
+
+ // Print the 8th of the 8 bytes of mandatory fields.
+ PrintBytes(1);
+ PRINTGET("\t#", TbTable, NumberOfFPParms);
+ PRINTBOOL(",", TbTable, hasParmsOnStack);
+
+ PRINTOPTIONAL(ParmsType);
+ PRINTOPTIONAL(TraceBackTableOffset);
+ PRINTOPTIONAL(HandlerMask);
+ PRINTOPTIONAL(NumOfCtlAnchors);
+
+ if (TbTable.getControlledStorageInfoDisp()) {
+ SmallVector<uint32_t, 8> Disp = *TbTable.getControlledStorageInfoDisp();
+ for (unsigned I = 0; I < Disp.size(); ++I) {
+ OS << '\n';
+ PrintBytes(4);
+ OS << "\t" << (I ? " " : "#") << " ControlledStorageInfoDisp[" << I
+ << "] = " << Disp[I];
+ }
+ }
+
+ // If there is a name, print the function name and function name length.
+ if (TbTable.isFuncNamePresent()) {
+ uint16_t FunctionNameLen = TbTable.getFunctionName()->size();
+ if (FunctionNameLen == 0) {
+ OS << '\n';
+ reportWarning(
+ "the length of the function name must be greater than zero if the "
+ "isFuncNamePresent bit is set in the traceback table",
+ Obj->getFileName());
+ return;
+ }
+
+ OS << '\n';
+ PrintBytes(2);
+ OS << "\t# FunctionNameLen = " << FunctionNameLen;
+
+ uint16_t RemainingBytes = FunctionNameLen;
+ bool HasPrinted = false;
+ while (RemainingBytes > 0) {
+ OS << '\n';
+ uint16_t PrintLen = RemainingBytes >= 4 ? 4 : RemainingBytes;
+ printRawData(Bytes.slice(Index, PrintLen), Address + Index, OS, STI);
+ Index += PrintLen;
+ RemainingBytes -= PrintLen;
+
+ if (!HasPrinted) {
+ OS << "\t# FunctionName = " << *TbTable.getFunctionName();
+ HasPrinted = true;
+ }
+ }
+ }
+
+ if (TbTable.isAllocaUsed()) {
+ OS << '\n';
+ PrintBytes(1);
+ OS << format("\t# AllocaRegister = %u", *TbTable.getAllocaRegister());
+ }
+
+ if (TbTable.getVectorExt()) {
+ OS << '\n';
+ TBVectorExt VecExt = *TbTable.getVectorExt();
+ // Print first byte of VectorExt.
+ PrintBytes(1);
+ PRINTGET("\t#", VecExt, NumberOfVRSaved);
+ PRINTBOOL(",", VecExt, isVRSavedOnStack);
+ PRINTBOOL(",", VecExt, hasVarArgs);
+ OS << '\n';
+
+ // Print the second byte of VectorExt.
+ PrintBytes(1);
+ PRINTGET("\t#", VecExt, NumberOfVectorParms);
+ PRINTBOOL(",", VecExt, hasVMXInstruction);
+ OS << '\n';
+
+ PrintBytes(4);
+ OS << "\t# VectorParmsInfoString = " << VecExt.getVectorParmsInfo();
+
+ // There are two bytes of padding after vector info.
+ OS << '\n';
+ PrintBytes(2);
+ OS << "\t# Padding";
+ }
+
+ if (TbTable.getExtensionTable()) {
+ OS << '\n';
+ PrintBytes(1);
+ ExtendedTBTableFlag Flag =
+ static_cast<ExtendedTBTableFlag>(*TbTable.getExtensionTable());
+ OS << "\t# ExtensionTable = " << getExtendedTBTableFlagString(Flag);
+ }
+
+ if (TbTable.getEhInfoDisp()) {
+ // There are 4 bytes alignment before eh info displacement.
+ if (Index % 4) {
+ OS << '\n';
+ PrintBytes(4 - Index % 4);
+ OS << "\t# Alignment padding for eh info displacement";
+ }
+ OS << '\n';
+ // The size of the displacement (address) is 4 bytes in 32-bit object files,
+ // and 8 bytes in 64-bit object files.
+ PrintBytes(4);
+ OS << "\t# EH info displacement";
+ if (Is64Bit) {
+ OS << '\n';
+ PrintBytes(4);
+ }
+ }
+
+ OS << '\n';
+ if (End == Address + Index)
+ return;
+
+ Size = End - Address;
+
+ const char *LineSuffix = "\t# Padding\n";
+ auto IsWordZero = [&](uint64_t WordPos) {
+ if (WordPos >= Size)
+ return false;
+ uint64_t LineLength = std::min(4 - WordPos % 4, Size - WordPos);
+ return std::all_of(Bytes.begin() + WordPos,
+ Bytes.begin() + WordPos + LineLength,
+ [](uint8_t Byte) { return Byte == 0; });
+ };
+
+ bool AreWordsZero[] = {IsWordZero(Index), IsWordZero(alignTo(Index, 4) + 4),
+ IsWordZero(alignTo(Index, 4) + 8)};
+ bool ShouldPrintLine = true;
+ while (true) {
+ // Determine the length of the line (4, except for the first line, which
+ // will be just enough to align to the word boundary, and the last line,
+ // which will be the remainder of the data).
+ uint64_t LineLength = std::min(4 - Index % 4, Size - Index);
+ if (ShouldPrintLine) {
+ // Print the line.
+ printRawData(Bytes.slice(Index, LineLength), Address + Index, OS, STI);
+ OS << LineSuffix;
+ LineSuffix = "\n";
+ }
+
+ Index += LineLength;
+ if (Index == Size)
+ return;
+
+ // For 3 or more consecutive lines of zeros, skip all but the first one, and
+ // replace them with "...".
+ if (AreWordsZero[0] && AreWordsZero[1] && AreWordsZero[2]) {
+ if (ShouldPrintLine)
+ OS << std::string(8, ' ') << "...\n";
+ ShouldPrintLine = false;
+ } else if (!AreWordsZero[1]) {
+ // We have reached the end of a skipped block of zeros.
+ ShouldPrintLine = true;
+ }
+ AreWordsZero[0] = AreWordsZero[1];
+ AreWordsZero[1] = AreWordsZero[2];
+ AreWordsZero[2] = IsWordZero(Index + 8);
+ }
+}
+#undef PRINTBOOL
+#undef PRINTGET
+#undef PRINTOPTIONAL
diff --git a/contrib/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.h b/contrib/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.h
index 35d1c0f1ebbe..cf5b19f910ea 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.h
+++ b/contrib/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.h
@@ -13,6 +13,8 @@
namespace llvm {
+class formatted_raw_ostream;
+class MCSubtargetInfo;
struct SymbolInfoTy;
namespace objdump {
@@ -32,6 +34,11 @@ std::string getXCOFFSymbolDescription(const SymbolInfoTy &SymbolInfo,
Error getXCOFFRelocationValueString(const object::XCOFFObjectFile &Obj,
const object::RelocationRef &RelRef,
llvm::SmallVectorImpl<char> &Result);
+
+void dumpTracebackTable(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ formatted_raw_ostream &OS, uint64_t End,
+ const MCSubtargetInfo &STI,
+ const object::XCOFFObjectFile *Obj);
} // namespace objdump
} // namespace llvm
#endif
diff --git a/contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp b/contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 9979a26cf115..bd45ed199767 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -30,7 +30,6 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
@@ -49,7 +48,6 @@
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/Archive.h"
@@ -74,7 +72,6 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/GraphWriter.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
@@ -82,6 +79,8 @@
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <cctype>
#include <cstring>
@@ -196,6 +195,7 @@ bool objdump::Demangle;
bool objdump::Disassemble;
bool objdump::DisassembleAll;
bool objdump::SymbolDescription;
+bool objdump::TracebackTable;
static std::vector<std::string> DisassembleSymbols;
static bool DisassembleZeroes;
static std::vector<std::string> DisassemblerOptions;
@@ -247,6 +247,31 @@ static StringRef ToolName;
std::unique_ptr<BuildIDFetcher> BIDFetcher;
ExitOnError ExitOnErr;
+void Dumper::reportUniqueWarning(Error Err) {
+ reportUniqueWarning(toString(std::move(Err)));
+}
+
+void Dumper::reportUniqueWarning(const Twine &Msg) {
+ if (Warnings.insert(StringRef(Msg.str())).second)
+ reportWarning(Msg, O.getFileName());
+}
+
+static Expected<std::unique_ptr<Dumper>> createDumper(const ObjectFile &Obj) {
+ if (const auto *O = dyn_cast<COFFObjectFile>(&Obj))
+ return createCOFFDumper(*O);
+ if (const auto *O = dyn_cast<ELFObjectFileBase>(&Obj))
+ return createELFDumper(*O);
+ if (const auto *O = dyn_cast<MachOObjectFile>(&Obj))
+ return createMachODumper(*O);
+ if (const auto *O = dyn_cast<WasmObjectFile>(&Obj))
+ return createWasmDumper(*O);
+ if (const auto *O = dyn_cast<XCOFFObjectFile>(&Obj))
+ return createXCOFFDumper(*O);
+
+ return createStringError(errc::invalid_argument,
+ "unsupported object file format");
+}
+
namespace {
struct FilterResult {
// True if the section should not be skipped.
@@ -442,14 +467,36 @@ static bool getHidden(RelocationRef RelRef) {
return false;
}
-namespace {
-
/// Get the column at which we want to start printing the instruction
/// disassembly, taking into account anything which appears to the left of it.
-unsigned getInstStartColumn(const MCSubtargetInfo &STI) {
+unsigned objdump::getInstStartColumn(const MCSubtargetInfo &STI) {
return !ShowRawInsn ? 16 : STI.getTargetTriple().isX86() ? 40 : 24;
}
+static void AlignToInstStartColumn(size_t Start, const MCSubtargetInfo &STI,
+ raw_ostream &OS) {
+ // The output of printInst starts with a tab. Print some spaces so that
+ // the tab has 1 column and advances to the target tab stop.
+ unsigned TabStop = getInstStartColumn(STI);
+ unsigned Column = OS.tell() - Start;
+ OS.indent(Column < TabStop - 1 ? TabStop - 1 - Column : 7 - Column % 8);
+}
+
+void objdump::printRawData(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ formatted_raw_ostream &OS,
+ MCSubtargetInfo const &STI) {
+ size_t Start = OS.tell();
+ if (LeadingAddr)
+ OS << format("%8" PRIx64 ":", Address);
+ if (ShowRawInsn) {
+ OS << ' ';
+ dumpBytes(Bytes, OS);
+ }
+ AlignToInstStartColumn(Start, STI, OS);
+}
+
+namespace {
+
static bool isAArch64Elf(const ObjectFile &Obj) {
const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj);
return Elf && Elf->getEMachine() == ELF::EM_AARCH64;
@@ -489,15 +536,6 @@ static void printRelocation(formatted_raw_ostream &OS, StringRef FileName,
OS << Name << "\t" << Val;
}
-static void AlignToInstStartColumn(size_t Start, const MCSubtargetInfo &STI,
- raw_ostream &OS) {
- // The output of printInst starts with a tab. Print some spaces so that
- // the tab has 1 column and advances to the target tab stop.
- unsigned TabStop = getInstStartColumn(STI);
- unsigned Column = OS.tell() - Start;
- OS.indent(Column < TabStop - 1 ? TabStop - 1 - Column : 7 - Column % 8);
-}
-
class PrettyPrinter {
public:
virtual ~PrettyPrinter() = default;
@@ -511,15 +549,7 @@ public:
SP->printSourceLine(OS, Address, ObjectFilename, LVP);
LVP.printBetweenInsts(OS, false);
- size_t Start = OS.tell();
- if (LeadingAddr)
- OS << format("%8" PRIx64 ":", Address.Address);
- if (ShowRawInsn) {
- OS << ' ';
- dumpBytes(Bytes, OS);
- }
-
- AlignToInstStartColumn(Start, STI, OS);
+ printRawData(Bytes, Address.Address, OS, STI);
if (MI) {
// See MCInstPrinter::printInst. On targets where a PC relative immediate
@@ -806,7 +836,7 @@ PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {
return AArch64PrettyPrinterInst;
}
}
-}
+} // namespace
static uint8_t getElfSymbolType(const ObjectFile &Obj, const SymbolRef &Sym) {
assert(Obj.isELF());
@@ -914,38 +944,35 @@ addMissingWasmCodeSymbols(const WasmObjectFile &Obj,
static void addPltEntries(const ObjectFile &Obj,
std::map<SectionRef, SectionSymbolsTy> &AllSymbols,
StringSaver &Saver) {
- std::optional<SectionRef> Plt;
- for (const SectionRef &Section : Obj.sections()) {
+ auto *ElfObj = dyn_cast<ELFObjectFileBase>(&Obj);
+ if (!ElfObj)
+ return;
+ DenseMap<StringRef, SectionRef> Sections;
+ for (SectionRef Section : Obj.sections()) {
Expected<StringRef> SecNameOrErr = Section.getName();
if (!SecNameOrErr) {
consumeError(SecNameOrErr.takeError());
continue;
}
- if (*SecNameOrErr == ".plt")
- Plt = Section;
- }
- if (!Plt)
- return;
- if (auto *ElfObj = dyn_cast<ELFObjectFileBase>(&Obj)) {
- for (auto PltEntry : ElfObj->getPltAddresses()) {
- if (PltEntry.first) {
- SymbolRef Symbol(*PltEntry.first, ElfObj);
- uint8_t SymbolType = getElfSymbolType(Obj, Symbol);
- if (Expected<StringRef> NameOrErr = Symbol.getName()) {
- if (!NameOrErr->empty())
- AllSymbols[*Plt].emplace_back(
- PltEntry.second, Saver.save((*NameOrErr + "@plt").str()),
- SymbolType);
- continue;
- } else {
- // The warning has been reported in disassembleObject().
- consumeError(NameOrErr.takeError());
- }
+ Sections[*SecNameOrErr] = Section;
+ }
+ for (auto Plt : ElfObj->getPltEntries()) {
+ if (Plt.Symbol) {
+ SymbolRef Symbol(*Plt.Symbol, ElfObj);
+ uint8_t SymbolType = getElfSymbolType(Obj, Symbol);
+ if (Expected<StringRef> NameOrErr = Symbol.getName()) {
+ if (!NameOrErr->empty())
+ AllSymbols[Sections[Plt.Section]].emplace_back(
+ Plt.Address, Saver.save((*NameOrErr + "@plt").str()), SymbolType);
+ continue;
+ } else {
+ // The warning has been reported in disassembleObject().
+ consumeError(NameOrErr.takeError());
}
- reportWarning("PLT entry at 0x" + Twine::utohexstr(PltEntry.second) +
- " references an invalid symbol",
- Obj.getFileName());
}
+ reportWarning("PLT entry at 0x" + Twine::utohexstr(Plt.Address) +
+ " references an invalid symbol",
+ Obj.getFileName());
}
}
@@ -1090,7 +1117,7 @@ SymbolInfoTy objdump::createSymbolInfo(const ObjectFile &Obj,
const uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName);
const StringRef Name = unwrapOrError(Symbol.getName(), FileName);
- if (Obj.isXCOFF() && SymbolDescription) {
+ if (Obj.isXCOFF() && (SymbolDescription || TracebackTable)) {
const auto &XCOFFObj = cast<XCOFFObjectFile>(Obj);
DataRefImpl SymbolDRI = Symbol.getRawDataRefImpl();
@@ -1111,7 +1138,7 @@ SymbolInfoTy objdump::createSymbolInfo(const ObjectFile &Obj,
static SymbolInfoTy createDummySymbolInfo(const ObjectFile &Obj,
const uint64_t Addr, StringRef &Name,
uint8_t Type) {
- if (Obj.isXCOFF() && SymbolDescription)
+ if (Obj.isXCOFF() && (SymbolDescription || TracebackTable))
return SymbolInfoTy(Addr, Name, std::nullopt, std::nullopt, false);
else
return SymbolInfoTy(Addr, Name, Type);
@@ -1129,11 +1156,11 @@ collectBBAddrMapLabels(const std::unordered_map<uint64_t, BBAddrMap> &AddrToBBAd
auto Iter = AddrToBBAddrMap.find(StartAddress);
if (Iter == AddrToBBAddrMap.end())
return;
- for (unsigned I = 0, Size = Iter->second.BBEntries.size(); I < Size; ++I) {
- uint64_t BBAddress = Iter->second.BBEntries[I].Offset + Iter->second.Addr;
+ for (const BBAddrMap::BBEntry &BBEntry : Iter->second.BBEntries) {
+ uint64_t BBAddress = BBEntry.Offset + Iter->second.Addr;
if (BBAddress >= EndAddress)
continue;
- Labels[BBAddress].push_back(("BB" + Twine(I)).str());
+ Labels[BBAddress].push_back(("BB" + Twine(BBEntry.ID)).str());
}
}
@@ -1285,10 +1312,10 @@ static void createFakeELFSections(ObjectFile &Obj) {
// Build ID. Returns std::nullopt if nothing was found.
static std::optional<OwningBinary<Binary>>
fetchBinaryByBuildID(const ObjectFile &Obj) {
- std::optional<object::BuildIDRef> BuildID = getBuildID(&Obj);
- if (!BuildID)
+ object::BuildIDRef BuildID = getBuildID(&Obj);
+ if (BuildID.empty())
return std::nullopt;
- std::optional<std::string> Path = BIDFetcher->fetch(*BuildID);
+ std::optional<std::string> Path = BIDFetcher->fetch(BuildID);
if (!Path)
return std::nullopt;
Expected<OwningBinary<Binary>> DebugBinary = createBinary(*Path);
@@ -1439,8 +1466,10 @@ static void disassembleObject(const Target *TheTarget, ObjectFile &Obj,
AddrToBBAddrMap.clear();
if (const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj)) {
auto BBAddrMapsOrErr = Elf->readBBAddrMap(SectionIndex);
- if (!BBAddrMapsOrErr)
+ if (!BBAddrMapsOrErr) {
reportWarning(toString(BBAddrMapsOrErr.takeError()), Obj.getFileName());
+ return;
+ }
for (auto &FunctionBBAddrMap : *BBAddrMapsOrErr)
AddrToBBAddrMap.emplace(FunctionBBAddrMap.Addr,
std::move(FunctionBBAddrMap));
@@ -1546,7 +1575,7 @@ static void disassembleObject(const Target *TheTarget, ObjectFile &Obj,
if (Demangle) {
// Fetch the demangled names and store them locally.
for (const SymbolInfoTy &Symbol : SymbolsHere)
- DemangledSymNamesHere.push_back(demangle(Symbol.Name.str()));
+ DemangledSymNamesHere.push_back(demangle(Symbol.Name));
// Now we've finished modifying that vector, it's safe to make
// a vector of StringRefs pointing into it.
SymNamesHere.insert(SymNamesHere.begin(), DemangledSymNamesHere.begin(),
@@ -1714,8 +1743,9 @@ static void disassembleObject(const Target *TheTarget, ObjectFile &Obj,
// distance to the next symbol, and sometimes it will be just a
// prologue and we should start disassembling instructions from where
// it left off.
- outs() << "// Error in decoding " << SymNamesHere[SHI]
- << " : Decoding failed region as bytes.\n";
+ outs() << Ctx.getAsmInfo()->getCommentString()
+ << " error in decoding " << SymNamesHere[SHI]
+ << " : decoding failed region as bytes.\n";
for (uint64_t I = 0; I < Size; ++I) {
outs() << "\t.byte\t " << format_hex(Bytes[I], 1, /*Upper=*/true)
<< "\n";
@@ -1736,6 +1766,11 @@ static void disassembleObject(const Target *TheTarget, ObjectFile &Obj,
}
bool DumpARMELFData = false;
+ bool DumpTracebackTableForXCOFFFunction =
+ Obj.isXCOFF() && Section.isText() && TracebackTable &&
+ Symbols[SI - 1].XCOFFSymInfo.StorageMappingClass &&
+ (*Symbols[SI - 1].XCOFFSymInfo.StorageMappingClass == XCOFF::XMC_PR);
+
formatted_raw_ostream FOS(outs());
std::unordered_map<uint64_t, std::string> AllLabels;
@@ -1788,6 +1823,16 @@ static void disassembleObject(const Target *TheTarget, ObjectFile &Obj,
}
}
+ if (DumpTracebackTableForXCOFFFunction &&
+ doesXCOFFTracebackTableBegin(Bytes.slice(Index, 4))) {
+ dumpTracebackTable(Bytes.slice(Index),
+ SectionAddr + Index + VMAAdjustment, FOS,
+ SectionAddr + End + VMAAdjustment, *STI,
+ cast<XCOFFObjectFile>(&Obj));
+ Index = End;
+ continue;
+ }
+
// Print local label if there's any.
auto Iter1 = BBAddrMapLabels.find(SectionAddr + Index);
if (Iter1 != BBAddrMapLabels.end()) {
@@ -1907,9 +1952,8 @@ static void disassembleObject(const Target *TheTarget, ObjectFile &Obj,
if (TargetSym != nullptr) {
uint64_t TargetAddress = TargetSym->Addr;
uint64_t Disp = Target - TargetAddress;
- std::string TargetName = TargetSym->Name.str();
- if (Demangle)
- TargetName = demangle(TargetName);
+ std::string TargetName = Demangle ? demangle(TargetSym->Name)
+ : TargetSym->Name.str();
*TargetOS << " <";
if (!Disp) {
@@ -2149,23 +2193,22 @@ static void disassembleObject(ObjectFile *Obj, bool InlineRelocs) {
SecondarySTI.get(), PIP, SP, InlineRelocs);
}
-void objdump::printRelocations(const ObjectFile *Obj) {
- StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 :
- "%08" PRIx64;
+void Dumper::printRelocations() {
+ StringRef Fmt = O.getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
// Build a mapping from relocation target to a vector of relocation
// sections. Usually, there is an only one relocation section for
// each relocated section.
MapVector<SectionRef, std::vector<SectionRef>> SecToRelSec;
uint64_t Ndx;
- for (const SectionRef &Section : ToolSectionFilter(*Obj, &Ndx)) {
- if (Obj->isELF() && (ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC))
+ for (const SectionRef &Section : ToolSectionFilter(O, &Ndx)) {
+ if (O.isELF() && (ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC))
continue;
if (Section.relocation_begin() == Section.relocation_end())
continue;
Expected<section_iterator> SecOrErr = Section.getRelocatedSection();
if (!SecOrErr)
- reportError(Obj->getFileName(),
+ reportError(O.getFileName(),
"section (" + Twine(Ndx) +
"): unable to get a relocation target: " +
toString(SecOrErr.takeError()));
@@ -2173,9 +2216,9 @@ void objdump::printRelocations(const ObjectFile *Obj) {
}
for (std::pair<SectionRef, std::vector<SectionRef>> &P : SecToRelSec) {
- StringRef SecName = unwrapOrError(P.first.getName(), Obj->getFileName());
+ StringRef SecName = unwrapOrError(P.first.getName(), O.getFileName());
outs() << "\nRELOCATION RECORDS FOR [" << SecName << "]:\n";
- uint32_t OffsetPadding = (Obj->getBytesInAddress() > 4 ? 16 : 8);
+ uint32_t OffsetPadding = (O.getBytesInAddress() > 4 ? 16 : 8);
uint32_t TypePadding = 24;
outs() << left_justify("OFFSET", OffsetPadding) << " "
<< left_justify("TYPE", TypePadding) << " "
@@ -2190,7 +2233,7 @@ void objdump::printRelocations(const ObjectFile *Obj) {
continue;
Reloc.getTypeName(RelocName);
if (Error E = getRelocationValueString(Reloc, ValueStr))
- reportError(std::move(E), Obj->getFileName());
+ reportUniqueWarning(std::move(E));
outs() << format(Fmt.data(), Address) << " "
<< left_justify(RelocName, TypePadding) << " " << ValueStr
@@ -2200,43 +2243,6 @@ void objdump::printRelocations(const ObjectFile *Obj) {
}
}
-void objdump::printDynamicRelocations(const ObjectFile *Obj) {
- // For the moment, this option is for ELF only
- if (!Obj->isELF())
- return;
-
- const auto *Elf = dyn_cast<ELFObjectFileBase>(Obj);
- if (!Elf || !any_of(Elf->sections(), [](const ELFSectionRef Sec) {
- return Sec.getType() == ELF::SHT_DYNAMIC;
- })) {
- reportError(Obj->getFileName(), "not a dynamic object");
- return;
- }
-
- std::vector<SectionRef> DynRelSec = Obj->dynamic_relocation_sections();
- if (DynRelSec.empty())
- return;
-
- outs() << "\nDYNAMIC RELOCATION RECORDS\n";
- const uint32_t OffsetPadding = (Obj->getBytesInAddress() > 4 ? 16 : 8);
- const uint32_t TypePadding = 24;
- outs() << left_justify("OFFSET", OffsetPadding) << ' '
- << left_justify("TYPE", TypePadding) << " VALUE\n";
-
- StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
- for (const SectionRef &Section : DynRelSec)
- for (const RelocationRef &Reloc : Section.relocations()) {
- uint64_t Address = Reloc.getOffset();
- SmallString<32> RelocName;
- SmallString<32> ValueStr;
- Reloc.getTypeName(RelocName);
- if (Error E = getRelocationValueString(Reloc, ValueStr))
- reportError(std::move(E), Obj->getFileName());
- outs() << format(Fmt.data(), Address) << ' '
- << left_justify(RelocName, TypePadding) << ' ' << ValueStr << '\n';
- }
-}
-
// Returns true if we need to show LMA column when dumping section headers. We
// show it only when the platform is ELF and either we have at least one section
// whose VMA and LMA are different and/or when --show-lma flag is used.
@@ -2355,8 +2361,8 @@ void objdump::printSectionContents(const ObjectFile *Obj) {
}
}
-void objdump::printSymbolTable(const ObjectFile &O, StringRef ArchiveName,
- StringRef ArchitectureName, bool DumpDynamic) {
+void Dumper::printSymbolTable(StringRef ArchiveName, StringRef ArchitectureName,
+ bool DumpDynamic) {
if (O.isCOFF() && !DumpDynamic) {
outs() << "\nSYMBOL TABLE:\n";
printCOFFSymbolTable(cast<const COFFObjectFile>(O));
@@ -2368,8 +2374,7 @@ void objdump::printSymbolTable(const ObjectFile &O, StringRef ArchiveName,
if (!DumpDynamic) {
outs() << "\nSYMBOL TABLE:\n";
for (auto I = O.symbol_begin(); I != O.symbol_end(); ++I)
- printSymbol(O, *I, {}, FileName, ArchiveName, ArchitectureName,
- DumpDynamic);
+ printSymbol(*I, {}, FileName, ArchiveName, ArchitectureName, DumpDynamic);
return;
}
@@ -2391,17 +2396,21 @@ void objdump::printSymbolTable(const ObjectFile &O, StringRef ArchiveName,
(void)!SymbolVersionsOrErr;
}
for (auto &Sym : Symbols)
- printSymbol(O, Sym, *SymbolVersionsOrErr, FileName, ArchiveName,
+ printSymbol(Sym, *SymbolVersionsOrErr, FileName, ArchiveName,
ArchitectureName, DumpDynamic);
}
-void objdump::printSymbol(const ObjectFile &O, const SymbolRef &Symbol,
- ArrayRef<VersionEntry> SymbolVersions,
- StringRef FileName, StringRef ArchiveName,
- StringRef ArchitectureName, bool DumpDynamic) {
+void Dumper::printSymbol(const SymbolRef &Symbol,
+ ArrayRef<VersionEntry> SymbolVersions,
+ StringRef FileName, StringRef ArchiveName,
+ StringRef ArchitectureName, bool DumpDynamic) {
const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(&O);
- uint64_t Address = unwrapOrError(Symbol.getAddress(), FileName, ArchiveName,
- ArchitectureName);
+ Expected<uint64_t> AddrOrErr = Symbol.getAddress();
+ if (!AddrOrErr) {
+ reportUniqueWarning(AddrOrErr.takeError());
+ return;
+ }
+ uint64_t Address = *AddrOrErr;
if ((Address < StartAddress) || (Address > StopAddress))
return;
SymbolRef::Type Type =
@@ -2509,10 +2518,8 @@ void objdump::printSymbol(const ObjectFile &O, const SymbolRef &Symbol,
if (NameOrErr) {
outs() << " (csect:";
- std::string SymName(NameOrErr.get());
-
- if (Demangle)
- SymName = demangle(SymName);
+ std::string SymName =
+ Demangle ? demangle(*NameOrErr) : NameOrErr->str();
if (SymbolDescription)
SymName = getXCOFFSymbolDescription(createSymbolInfo(O, *SymRef),
@@ -2566,10 +2573,7 @@ void objdump::printSymbol(const ObjectFile &O, const SymbolRef &Symbol,
outs() << " .hidden";
}
- std::string SymName(Name);
- if (Demangle)
- SymName = demangle(SymName);
-
+ std::string SymName = Demangle ? demangle(Name) : Name.str();
if (O.isXCOFF() && SymbolDescription)
SymName = getXCOFFSymbolDescription(createSymbolInfo(O, Symbol), SymName);
@@ -2672,24 +2676,8 @@ static void printFaultMaps(const ObjectFile *Obj) {
outs() << FMP;
}
-static void printPrivateFileHeaders(const ObjectFile *O, bool OnlyFirst) {
- if (O->isELF()) {
- printELFFileHeader(O);
- printELFDynamicSection(O);
- printELFSymbolVersionInfo(O);
- return;
- }
- if (O->isCOFF())
- return printCOFFFileHeader(cast<object::COFFObjectFile>(*O));
- if (O->isWasm())
- return printWasmFileHeader(O);
- if (O->isMachO()) {
- printMachOFileHeader(O);
- if (!OnlyFirst)
- printMachOLoadCommands(O);
- return;
- }
- reportError(O->getFileName(), "Invalid/Unsupported object file format");
+void Dumper::printPrivateHeaders(bool) {
+ reportError(O.getFileName(), "Invalid/Unsupported object file format");
}
static void printFileHeaders(const ObjectFile *O) {
@@ -2792,6 +2780,14 @@ static void checkForInvalidStartStopAddress(ObjectFile *Obj,
static void dumpObject(ObjectFile *O, const Archive *A = nullptr,
const Archive::Child *C = nullptr) {
+ Expected<std::unique_ptr<Dumper>> DumperOrErr = createDumper(*O);
+ if (!DumperOrErr) {
+ reportError(DumperOrErr.takeError(), O->getFileName(),
+ A ? A->getFileName() : "");
+ return;
+ }
+ Dumper &D = **DumperOrErr;
+
// Avoid other output when using a raw option.
if (!RawClangAST) {
outs() << '\n';
@@ -2805,6 +2801,9 @@ static void dumpObject(ObjectFile *O, const Archive *A = nullptr,
if (HasStartAddressFlag || HasStopAddressFlag)
checkForInvalidStartStopAddress(O, StartAddress, StopAddress);
+ // TODO: Change print* free functions to Dumper member functions to utilitize
+ // stateful functions like reportUniqueWarning.
+
// Note: the order here matches GNU objdump for compatability.
StringRef ArchiveName = A ? A->getFileName() : "";
if (ArchiveHeaders && !MachOOpt && C)
@@ -2812,14 +2811,14 @@ static void dumpObject(ObjectFile *O, const Archive *A = nullptr,
if (FileHeaders)
printFileHeaders(O);
if (PrivateHeaders || FirstPrivateHeader)
- printPrivateFileHeaders(O, FirstPrivateHeader);
+ D.printPrivateHeaders(FirstPrivateHeader);
if (SectionHeaders)
printSectionHeaders(*O);
if (SymbolTable)
- printSymbolTable(*O, ArchiveName);
+ D.printSymbolTable(ArchiveName);
if (DynamicSymbolTable)
- printSymbolTable(*O, ArchiveName, /*ArchitectureName=*/"",
- /*DumpDynamic=*/true);
+ D.printSymbolTable(ArchiveName, /*ArchitectureName=*/"",
+ /*DumpDynamic=*/true);
if (DwarfDumpType != DIDT_Null) {
std::unique_ptr<DIContext> DICtx = DWARFContext::create(*O);
// Dump the complete DWARF structure.
@@ -2828,9 +2827,9 @@ static void dumpObject(ObjectFile *O, const Archive *A = nullptr,
DICtx->dump(outs(), DumpOpts);
}
if (Relocations && !Disassemble)
- printRelocations(O);
+ D.printRelocations();
if (DynamicRelocations)
- printDynamicRelocations(O);
+ D.printDynamicRelocations();
if (SectionContents)
printSectionContents(O);
if (Disassemble)
@@ -2941,13 +2940,11 @@ static void parseIntArg(const llvm::opt::InputArgList &InputArgs, int ID,
static object::BuildID parseBuildIDArg(const opt::Arg *A) {
StringRef V(A->getValue());
- std::string Bytes;
- if (!tryGetFromHex(V, Bytes))
+ object::BuildID BID = parseBuildID(V);
+ if (BID.empty())
reportCmdLineError(A->getSpelling() + ": expected a build ID, but got '" +
V + "'");
- ArrayRef<uint8_t> BuildID(reinterpret_cast<const uint8_t *>(Bytes.data()),
- Bytes.size());
- return object::BuildID(BuildID.begin(), BuildID.end());
+ return BID;
}
void objdump::invalidArgValue(const opt::Arg *A) {
@@ -3027,6 +3024,7 @@ static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
Disassemble = InputArgs.hasArg(OBJDUMP_disassemble);
DisassembleAll = InputArgs.hasArg(OBJDUMP_disassemble_all);
SymbolDescription = InputArgs.hasArg(OBJDUMP_symbol_description);
+ TracebackTable = InputArgs.hasArg(OBJDUMP_traceback_table);
DisassembleSymbols =
commaSeparatedValues(InputArgs, OBJDUMP_disassemble_symbols_EQ);
DisassembleZeroes = InputArgs.hasArg(OBJDUMP_disassemble_zeroes);
@@ -3227,7 +3225,7 @@ int main(int argc, char **argv) {
ArchiveHeaders = FileHeaders = PrivateHeaders = Relocations =
SectionHeaders = SymbolTable = true;
- if (DisassembleAll || PrintSource || PrintLines ||
+ if (DisassembleAll || PrintSource || PrintLines || TracebackTable ||
!DisassembleSymbols.empty())
Disassemble = true;
diff --git a/contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h b/contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h
index efb445195259..b3136f0374d2 100644
--- a/contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/contrib/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -12,9 +12,13 @@
#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
+#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Object/Archive.h"
+#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/FormattedStream.h"
+#include <memory>
namespace llvm {
class StringRef;
@@ -27,6 +31,12 @@ class Arg;
namespace object {
class RelocationRef;
struct VersionEntry;
+
+class COFFObjectFile;
+class ELFObjectFileBase;
+class MachOObjectFile;
+class WasmObjectFile;
+class XCOFFObjectFile;
} // namespace object
namespace objdump {
@@ -55,64 +65,41 @@ extern bool SectionHeaders;
extern bool SectionContents;
extern bool ShowRawInsn;
extern bool SymbolDescription;
+extern bool TracebackTable;
extern bool SymbolTable;
extern std::string TripleName;
extern bool UnwindInfo;
extern StringSet<> FoundSectionSet;
-typedef std::function<bool(llvm::object::SectionRef const &)> FilterPredicate;
+class Dumper {
+ const object::ObjectFile &O;
+ StringSet<> Warnings;
-/// A filtered iterator for SectionRefs that skips sections based on some given
-/// predicate.
-class SectionFilterIterator {
public:
- SectionFilterIterator(FilterPredicate P,
- llvm::object::section_iterator const &I,
- llvm::object::section_iterator const &E)
- : Predicate(std::move(P)), Iterator(I), End(E) {
- ScanPredicate();
- }
- const llvm::object::SectionRef &operator*() const { return *Iterator; }
- SectionFilterIterator &operator++() {
- ++Iterator;
- ScanPredicate();
- return *this;
- }
- bool operator!=(SectionFilterIterator const &Other) const {
- return Iterator != Other.Iterator;
- }
-
-private:
- void ScanPredicate() {
- while (Iterator != End && !Predicate(*Iterator)) {
- ++Iterator;
- }
- }
- FilterPredicate Predicate;
- llvm::object::section_iterator Iterator;
- llvm::object::section_iterator End;
+ Dumper(const object::ObjectFile &O) : O(O) {}
+ virtual ~Dumper() {}
+
+ void reportUniqueWarning(Error Err);
+ void reportUniqueWarning(const Twine &Msg);
+
+ virtual void printPrivateHeaders(bool MachOOnlyFirst);
+ virtual void printDynamicRelocations() {}
+ void printSymbolTable(StringRef ArchiveName,
+ StringRef ArchitectureName = StringRef(),
+ bool DumpDynamic = false);
+ void printSymbol(const object::SymbolRef &Symbol,
+ ArrayRef<object::VersionEntry> SymbolVersions,
+ StringRef FileName, StringRef ArchiveName,
+ StringRef ArchitectureName, bool DumpDynamic);
+ void printRelocations();
};
-/// Creates an iterator range of SectionFilterIterators for a given Object and
-/// predicate.
-class SectionFilter {
-public:
- SectionFilter(FilterPredicate P, llvm::object::ObjectFile const &O)
- : Predicate(std::move(P)), Object(O) {}
- SectionFilterIterator begin() {
- return SectionFilterIterator(Predicate, Object.section_begin(),
- Object.section_end());
- }
- SectionFilterIterator end() {
- return SectionFilterIterator(Predicate, Object.section_end(),
- Object.section_end());
- }
-
-private:
- FilterPredicate Predicate;
- llvm::object::ObjectFile const &Object;
-};
+std::unique_ptr<Dumper> createCOFFDumper(const object::COFFObjectFile &Obj);
+std::unique_ptr<Dumper> createELFDumper(const object::ELFObjectFileBase &Obj);
+std::unique_ptr<Dumper> createMachODumper(const object::MachOObjectFile &Obj);
+std::unique_ptr<Dumper> createWasmDumper(const object::WasmObjectFile &Obj);
+std::unique_ptr<Dumper> createXCOFFDumper(const object::XCOFFObjectFile &Obj);
// Various helper functions.
@@ -122,21 +109,12 @@ private:
/// Idx is an optional output parameter that keeps track of which section index
/// this is. This may be different than the actual section number, as some
/// sections may be filtered (e.g. symbol tables).
-SectionFilter ToolSectionFilter(llvm::object::ObjectFile const &O,
- uint64_t *Idx = nullptr);
+object::SectionFilter ToolSectionFilter(const llvm::object::ObjectFile &O,
+ uint64_t *Idx = nullptr);
bool isRelocAddressLess(object::RelocationRef A, object::RelocationRef B);
-void printRelocations(const object::ObjectFile *O);
-void printDynamicRelocations(const object::ObjectFile *O);
void printSectionHeaders(object::ObjectFile &O);
void printSectionContents(const object::ObjectFile *O);
-void printSymbolTable(const object::ObjectFile &O, StringRef ArchiveName,
- StringRef ArchitectureName = StringRef(),
- bool DumpDynamic = false);
-void printSymbol(const object::ObjectFile &O, const object::SymbolRef &Symbol,
- ArrayRef<object::VersionEntry> SymbolVersions,
- StringRef FileName, StringRef ArchiveName,
- StringRef ArchitectureName, bool DumpDynamic);
[[noreturn]] void reportError(StringRef File, const Twine &Message);
[[noreturn]] void reportError(Error E, StringRef FileName,
StringRef ArchiveName = "",
@@ -156,6 +134,10 @@ std::string getFileNameForError(const object::Archive::Child &C,
unsigned Index);
SymbolInfoTy createSymbolInfo(const object::ObjectFile &Obj,
const object::SymbolRef &Symbol);
+unsigned getInstStartColumn(const MCSubtargetInfo &STI);
+void printRawData(llvm::ArrayRef<uint8_t> Bytes, uint64_t Address,
+ llvm::formatted_raw_ostream &OS,
+ llvm::MCSubtargetInfo const &STI);
} // namespace objdump
} // end namespace llvm
diff --git a/contrib/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/contrib/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
index 4b604206fc98..447a9cb6b359 100644
--- a/contrib/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
@@ -15,6 +15,7 @@
#include "llvm-pdbutil.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
diff --git a/contrib/llvm-project/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp b/contrib/llvm-project/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
index 8e17284871a9..96c3d49072b6 100644
--- a/contrib/llvm-project/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
@@ -8,6 +8,7 @@
#include "MinimalSymbolDumper.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/Formatters.h"
@@ -210,6 +211,8 @@ static std::string formatSourceLanguage(SourceLanguage Lang) {
RETURN_CASE(SourceLanguage, D, "d");
RETURN_CASE(SourceLanguage, Swift, "swift");
RETURN_CASE(SourceLanguage, Rust, "rust");
+ RETURN_CASE(SourceLanguage, ObjC, "objc");
+ RETURN_CASE(SourceLanguage, ObjCpp, "objc++");
}
return formatUnknownEnum(Lang);
}
diff --git a/contrib/llvm-project/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp b/contrib/llvm-project/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
index be7e487673fb..aaa430a9572e 100644
--- a/contrib/llvm-project/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
@@ -11,6 +11,7 @@
#include "TypeReferenceTracker.h"
#include "llvm-pdbutil.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
diff --git a/contrib/llvm-project/llvm/tools/llvm-pdbutil/PrettyCompilandDumper.cpp b/contrib/llvm-project/llvm/tools/llvm-pdbutil/PrettyCompilandDumper.cpp
index 591bd4f93702..b347cfdfc392 100644
--- a/contrib/llvm-project/llvm/tools/llvm-pdbutil/PrettyCompilandDumper.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-pdbutil/PrettyCompilandDumper.cpp
@@ -11,6 +11,7 @@
#include "PrettyFunctionDumper.h"
#include "llvm-pdbutil.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
diff --git a/contrib/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp b/contrib/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp
index c8e5e6d1ad68..da10ddcc58c6 100644
--- a/contrib/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -23,6 +23,7 @@
#include "llvm/ProfileData/RawMemProfReader.h"
#include "llvm/ProfileData/SampleProfReader.h"
#include "llvm/ProfileData/SampleProfWriter.h"
+#include "llvm/Support/BalancedPartitioning.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Discriminator.h"
#include "llvm/Support/Errc.h"
@@ -30,11 +31,13 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LLVMDriver.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/Threading.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -51,7 +54,7 @@ const std::string DuplicateNameStr = "----";
enum ProfileFormat {
PF_None = 0,
PF_Text,
- PF_Compact_Binary,
+ PF_Compact_Binary, // Deprecated
PF_Ext_Binary,
PF_GCC,
PF_Binary
@@ -214,9 +217,10 @@ struct WriterContext {
SmallSet<instrprof_error, 4> &WriterErrorCodes;
WriterContext(bool IsSparse, std::mutex &ErrLock,
- SmallSet<instrprof_error, 4> &WriterErrorCodes)
- : Writer(IsSparse), ErrLock(ErrLock), WriterErrorCodes(WriterErrorCodes) {
- }
+ SmallSet<instrprof_error, 4> &WriterErrorCodes,
+ uint64_t ReservoirSize = 0, uint64_t MaxTraceLength = 0)
+ : Writer(IsSparse, ReservoirSize, MaxTraceLength), ErrLock(ErrLock),
+ WriterErrorCodes(WriterErrorCodes) {}
};
/// Computer the overlap b/w profile BaseFilename and TestFileName,
@@ -226,12 +230,14 @@ static void overlapInput(const std::string &BaseFilename,
OverlapStats &Overlap,
const OverlapFuncFilters &FuncFilter,
raw_fd_ostream &OS, bool IsCS) {
- auto ReaderOrErr = InstrProfReader::create(TestFilename);
+ auto FS = vfs::getRealFileSystem();
+ auto ReaderOrErr = InstrProfReader::create(TestFilename, *FS);
if (Error E = ReaderOrErr.takeError()) {
// Skip the empty profiles by returning sliently.
- instrprof_error IPE = InstrProfError::take(std::move(E));
- if (IPE != instrprof_error::empty_raw_profile)
- WC->Errors.emplace_back(make_error<InstrProfError>(IPE), TestFilename);
+ auto [ErrorCode, Msg] = InstrProfError::take(std::move(E));
+ if (ErrorCode != instrprof_error::empty_raw_profile)
+ WC->Errors.emplace_back(make_error<InstrProfError>(ErrorCode, Msg),
+ TestFilename);
return;
}
@@ -276,8 +282,9 @@ static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
}
auto MemProfError = [&](Error E) {
- instrprof_error IPE = InstrProfError::take(std::move(E));
- WC->Errors.emplace_back(make_error<InstrProfError>(IPE), Filename);
+ auto [ErrorCode, Msg] = InstrProfError::take(std::move(E));
+ WC->Errors.emplace_back(make_error<InstrProfError>(ErrorCode, Msg),
+ Filename);
};
// Add the frame mappings into the writer context.
@@ -298,12 +305,14 @@ static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
return;
}
- auto ReaderOrErr = InstrProfReader::create(Input.Filename, Correlator);
+ auto FS = vfs::getRealFileSystem();
+ auto ReaderOrErr = InstrProfReader::create(Input.Filename, *FS, Correlator);
if (Error E = ReaderOrErr.takeError()) {
- // Skip the empty profiles by returning sliently.
- instrprof_error IPE = InstrProfError::take(std::move(E));
- if (IPE != instrprof_error::empty_raw_profile)
- WC->Errors.emplace_back(make_error<InstrProfError>(IPE), Filename);
+ // Skip the empty profiles by returning silently.
+ auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
+ if (ErrCode != instrprof_error::empty_raw_profile)
+ WC->Errors.emplace_back(make_error<InstrProfError>(ErrCode, Msg),
+ Filename);
return;
}
@@ -330,14 +339,20 @@ static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
}
Reported = true;
// Only show hint the first time an error occurs.
- instrprof_error IPE = InstrProfError::take(std::move(E));
+ auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
std::unique_lock<std::mutex> ErrGuard{WC->ErrLock};
- bool firstTime = WC->WriterErrorCodes.insert(IPE).second;
- handleMergeWriterError(make_error<InstrProfError>(IPE), Input.Filename,
- FuncName, firstTime);
+ bool firstTime = WC->WriterErrorCodes.insert(ErrCode).second;
+ handleMergeWriterError(make_error<InstrProfError>(ErrCode, Msg),
+ Input.Filename, FuncName, firstTime);
});
}
+ if (Reader->hasTemporalProfile()) {
+ auto &Traces = Reader->getTemporalProfTraces(Input.Weight);
+ if (!Traces.empty())
+ WC->Writer.addTemporalProfileTraces(
+ Traces, Reader->getTemporalProfTraceStreamSize());
+ }
if (Reader->hasError()) {
if (Error E = Reader->getError())
WC->Errors.emplace_back(std::move(E), Filename);
@@ -359,11 +374,11 @@ static void mergeWriterContexts(WriterContext *Dst, WriterContext *Src) {
exitWithError(std::move(E));
Dst->Writer.mergeRecordsFromWriter(std::move(Src->Writer), [&](Error E) {
- instrprof_error IPE = InstrProfError::take(std::move(E));
+ auto [ErrorCode, Msg] = InstrProfError::take(std::move(E));
std::unique_lock<std::mutex> ErrGuard{Dst->ErrLock};
- bool firstTime = Dst->WriterErrorCodes.insert(IPE).second;
+ bool firstTime = Dst->WriterErrorCodes.insert(ErrorCode).second;
if (firstTime)
- warn(toString(make_error<InstrProfError>(IPE)));
+ warn(toString(make_error<InstrProfError>(ErrorCode, Msg)));
});
}
@@ -388,15 +403,17 @@ static void writeInstrProfile(StringRef OutputFilename,
}
}
-static void mergeInstrProfile(const WeightedFileVector &Inputs,
- StringRef DebugInfoFilename,
- SymbolRemapper *Remapper,
- StringRef OutputFilename,
- ProfileFormat OutputFormat, bool OutputSparse,
- unsigned NumThreads, FailureMode FailMode,
- const StringRef ProfiledBinary) {
- if (OutputFormat != PF_Binary && OutputFormat != PF_Compact_Binary &&
- OutputFormat != PF_Ext_Binary && OutputFormat != PF_Text)
+static void
+mergeInstrProfile(const WeightedFileVector &Inputs, StringRef DebugInfoFilename,
+ SymbolRemapper *Remapper, StringRef OutputFilename,
+ ProfileFormat OutputFormat, uint64_t TraceReservoirSize,
+ uint64_t MaxTraceLength, bool OutputSparse,
+ unsigned NumThreads, FailureMode FailMode,
+ const StringRef ProfiledBinary) {
+ if (OutputFormat == PF_Compact_Binary)
+ exitWithError("Compact Binary is deprecated");
+ if (OutputFormat != PF_Binary && OutputFormat != PF_Ext_Binary &&
+ OutputFormat != PF_Text)
exitWithError("unknown format is specified");
std::unique_ptr<InstrProfCorrelator> Correlator;
@@ -420,7 +437,8 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
SmallVector<std::unique_ptr<WriterContext>, 4> Contexts;
for (unsigned I = 0; I < NumThreads; ++I)
Contexts.emplace_back(std::make_unique<WriterContext>(
- OutputSparse, ErrorLock, WriterErrorCodes));
+ OutputSparse, ErrorLock, WriterErrorCodes, TraceReservoirSize,
+ MaxTraceLength));
if (NumThreads == 1) {
for (const auto &Input : Inputs)
@@ -631,7 +649,7 @@ adjustInstrProfile(std::unique_ptr<WriterContext> &WC,
}
}
- if (StaticFuncMap.find(NewName) == StaticFuncMap.end()) {
+ if (!StaticFuncMap.contains(NewName)) {
StaticFuncMap[NewName] = Name;
} else {
StaticFuncMap[NewName] = DuplicateNameStr;
@@ -838,8 +856,9 @@ static void supplementInstrProfile(
// Read sample profile.
LLVMContext Context;
+ auto FS = vfs::getRealFileSystem();
auto ReaderOrErr = sampleprof::SampleProfileReader::create(
- SampleFilename.str(), Context, FSDiscriminatorPassOption);
+ SampleFilename.str(), Context, *FS, FSDiscriminatorPassOption);
if (std::error_code EC = ReaderOrErr.getError())
exitWithErrorCode(EC, SampleFilename);
auto Reader = std::move(ReaderOrErr.get());
@@ -896,7 +915,7 @@ remapSamples(const sampleprof::FunctionSamples &Samples,
static sampleprof::SampleProfileFormat FormatMap[] = {
sampleprof::SPF_None,
sampleprof::SPF_Text,
- sampleprof::SPF_Compact_Binary,
+ sampleprof::SPF_None,
sampleprof::SPF_Ext_Binary,
sampleprof::SPF_GCC,
sampleprof::SPF_Binary};
@@ -963,10 +982,11 @@ static void
mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper,
StringRef OutputFilename, ProfileFormat OutputFormat,
StringRef ProfileSymbolListFile, bool CompressAllSections,
- bool UseMD5, bool GenPartialProfile, bool GenCSNestedProfile,
+ bool UseMD5, bool GenPartialProfile,
+ SampleProfileLayout ProfileLayout,
bool SampleMergeColdContext, bool SampleTrimColdContext,
bool SampleColdContextFrameDepth, FailureMode FailMode,
- bool DropProfileSymbolList) {
+ bool DropProfileSymbolList, size_t OutputSizeLimit) {
using namespace sampleprof;
SampleProfileMap ProfileMap;
SmallVector<std::unique_ptr<sampleprof::SampleProfileReader>, 5> Readers;
@@ -975,7 +995,8 @@ mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper,
std::optional<bool> ProfileIsProbeBased;
std::optional<bool> ProfileIsCS;
for (const auto &Input : Inputs) {
- auto ReaderOrErr = SampleProfileReader::create(Input.Filename, Context,
+ auto FS = vfs::getRealFileSystem();
+ auto ReaderOrErr = SampleProfileReader::create(Input.Filename, Context, *FS,
FSDiscriminatorPassOption);
if (std::error_code EC = ReaderOrErr.getError()) {
warnOrExitGivenError(FailMode, EC, Input.Filename);
@@ -1042,9 +1063,12 @@ mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper,
SampleMergeColdContext, SampleColdContextFrameDepth, false);
}
- if (ProfileIsCS && GenCSNestedProfile) {
- CSProfileConverter CSConverter(ProfileMap);
- CSConverter.convertProfiles();
+ if (ProfileLayout == llvm::sampleprof::SPL_Flat) {
+ ProfileConverter::flattenProfile(ProfileMap, FunctionSamples::ProfileIsCS);
+ ProfileIsCS = FunctionSamples::ProfileIsCS = false;
+ } else if (ProfileIsCS && ProfileLayout == llvm::sampleprof::SPL_Nest) {
+ ProfileConverter CSConverter(ProfileMap);
+ CSConverter.convertCSProfiles();
ProfileIsCS = FunctionSamples::ProfileIsCS = false;
}
@@ -1059,7 +1083,10 @@ mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper,
auto Buffer = getInputFileBuf(ProfileSymbolListFile);
handleExtBinaryWriter(*Writer, OutputFormat, Buffer.get(), WriterList,
CompressAllSections, UseMD5, GenPartialProfile);
- if (std::error_code EC = Writer->write(ProfileMap))
+
+ // If OutputSizeLimit is 0 (default), it is the same as write().
+ if (std::error_code EC =
+ Writer->writeWithSizeLimit(ProfileMap, OutputSizeLimit))
exitWithErrorCode(std::move(EC));
}
@@ -1156,12 +1183,11 @@ static int merge_main(int argc, const char *argv[]) {
cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
clEnumVal(sample, "Sample profile")));
cl::opt<ProfileFormat> OutputFormat(
- cl::desc("Format of output profile"), cl::init(PF_Binary),
+ cl::desc("Format of output profile"), cl::init(PF_Ext_Binary),
cl::values(
- clEnumValN(PF_Binary, "binary", "Binary encoding (default)"),
- clEnumValN(PF_Compact_Binary, "compbinary",
- "Compact binary encoding"),
- clEnumValN(PF_Ext_Binary, "extbinary", "Extensible binary encoding"),
+ clEnumValN(PF_Binary, "binary", "Binary encoding"),
+ clEnumValN(PF_Ext_Binary, "extbinary", "Extensible binary encoding "
+ "(default)"),
clEnumValN(PF_Text, "text", "Text encoding"),
clEnumValN(PF_GCC, "gcc",
"GCC encoding (only meaningful for -sample)")));
@@ -1202,6 +1228,11 @@ static int merge_main(int argc, const char *argv[]) {
"sample-frame-depth-for-cold-context", cl::init(1),
cl::desc("Keep the last K frames while merging cold profile. 1 means the "
"context-less base profile"));
+ cl::opt<size_t> OutputSizeLimit(
+ "output-size-limit", cl::init(0), cl::Hidden,
+ cl::desc("Trim cold functions until profile size is below specified "
+ "limit in bytes. This uses a heursitic and functions may be "
+ "excessively trimmed"));
cl::opt<bool> GenPartialProfile(
"gen-partial-profile", cl::init(false), cl::Hidden,
cl::desc("Generate a partial profile (only meaningful for -extbinary)"));
@@ -1227,9 +1258,15 @@ static int merge_main(int argc, const char *argv[]) {
"instr-prof-cold-threshold", cl::init(0), cl::Hidden,
cl::desc("User specified cold threshold for instr profile which will "
"override the cold threshold got from profile summary. "));
- cl::opt<bool> GenCSNestedProfile(
- "gen-cs-nested-profile", cl::Hidden, cl::init(false),
- cl::desc("Generate nested function profiles for CSSPGO"));
+ cl::opt<SampleProfileLayout> ProfileLayout(
+ "convert-sample-profile-layout",
+ cl::desc("Convert the generated profile to a profile with a new layout"),
+ cl::init(SPL_None),
+ cl::values(
+ clEnumValN(SPL_Nest, "nest",
+ "Nested profile, the input should be CS flat profile"),
+ clEnumValN(SPL_Flat, "flat",
+ "Profile with nested inlinee flatten out")));
cl::opt<std::string> DebugInfoFilename(
"debug-info", cl::init(""),
cl::desc("Use the provided debug info to correlate the raw profile."));
@@ -1240,6 +1277,17 @@ static int merge_main(int argc, const char *argv[]) {
"drop-profile-symbol-list", cl::init(false), cl::Hidden,
cl::desc("Drop the profile symbol list when merging AutoFDO profiles "
"(only meaningful for -sample)"));
+ // WARNING: This reservoir size value is propagated to any input indexed
+ // profiles for simplicity. Changing this value between invocations could
+ // result in sample bias.
+ cl::opt<uint64_t> TemporalProfTraceReservoirSize(
+ "temporal-profile-trace-reservoir-size", cl::init(100),
+ cl::desc("The maximum number of stored temporal profile traces (default: "
+ "100)"));
+ cl::opt<uint64_t> TemporalProfMaxTraceLength(
+ "temporal-profile-max-trace-length", cl::init(10000),
+ cl::desc("The maximum length of a single temporal profile trace "
+ "(default: 10000)"));
cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
@@ -1281,14 +1329,17 @@ static int merge_main(int argc, const char *argv[]) {
if (ProfileKind == instr)
mergeInstrProfile(WeightedInputs, DebugInfoFilename, Remapper.get(),
- OutputFilename, OutputFormat, OutputSparse, NumThreads,
+ OutputFilename, OutputFormat,
+ TemporalProfTraceReservoirSize,
+ TemporalProfMaxTraceLength, OutputSparse, NumThreads,
FailureMode, ProfiledBinary);
else
- mergeSampleProfile(
- WeightedInputs, Remapper.get(), OutputFilename, OutputFormat,
- ProfileSymbolListFile, CompressAllSections, UseMD5, GenPartialProfile,
- GenCSNestedProfile, SampleMergeColdContext, SampleTrimColdContext,
- SampleColdContextFrameDepth, FailureMode, DropProfileSymbolList);
+ mergeSampleProfile(WeightedInputs, Remapper.get(), OutputFilename,
+ OutputFormat, ProfileSymbolListFile, CompressAllSections,
+ UseMD5, GenPartialProfile, ProfileLayout,
+ SampleMergeColdContext, SampleTrimColdContext,
+ SampleColdContextFrameDepth, FailureMode,
+ DropProfileSymbolList, OutputSizeLimit);
return 0;
}
@@ -2189,12 +2240,13 @@ std::error_code SampleOverlapAggregator::loadProfiles() {
using namespace sampleprof;
LLVMContext Context;
- auto BaseReaderOrErr = SampleProfileReader::create(BaseFilename, Context,
+ auto FS = vfs::getRealFileSystem();
+ auto BaseReaderOrErr = SampleProfileReader::create(BaseFilename, Context, *FS,
FSDiscriminatorPassOption);
if (std::error_code EC = BaseReaderOrErr.getError())
exitWithErrorCode(EC, BaseFilename);
- auto TestReaderOrErr = SampleProfileReader::create(TestFilename, Context,
+ auto TestReaderOrErr = SampleProfileReader::create(TestFilename, Context, *FS,
FSDiscriminatorPassOption);
if (std::error_code EC = TestReaderOrErr.getError())
exitWithErrorCode(EC, TestFilename);
@@ -2358,21 +2410,20 @@ static void showValueSitesStats(raw_fd_ostream &OS, uint32_t VK,
}
}
-static int showInstrProfile(const std::string &Filename, bool ShowCounts,
- uint32_t TopN, bool ShowIndirectCallTargets,
- bool ShowMemOPSizes, bool ShowDetailedSummary,
- std::vector<uint32_t> DetailedSummaryCutoffs,
- bool ShowAllFunctions, bool ShowCS,
- uint64_t ValueCutoff, bool OnlyListBelow,
- const std::string &ShowFunction, bool TextFormat,
- bool ShowBinaryIds, bool ShowCovered,
- bool ShowProfileVersion, ShowFormat SFormat,
- raw_fd_ostream &OS) {
+static int showInstrProfile(
+ const std::string &Filename, bool ShowCounts, uint32_t TopN,
+ bool ShowIndirectCallTargets, bool ShowMemOPSizes, bool ShowDetailedSummary,
+ std::vector<uint32_t> DetailedSummaryCutoffs, bool ShowAllFunctions,
+ bool ShowCS, uint64_t ValueCutoff, bool OnlyListBelow,
+ const std::string &ShowFunction, bool TextFormat, bool ShowBinaryIds,
+ bool ShowCovered, bool ShowProfileVersion, bool ShowTemporalProfTraces,
+ ShowFormat SFormat, raw_fd_ostream &OS) {
if (SFormat == ShowFormat::Json)
exitWithError("JSON output is not supported for instr profiles");
if (SFormat == ShowFormat::Yaml)
exitWithError("YAML output is not supported for instr profiles");
- auto ReaderOrErr = InstrProfReader::create(Filename);
+ auto FS = vfs::getRealFileSystem();
+ auto ReaderOrErr = InstrProfReader::create(Filename, *FS);
std::vector<uint32_t> Cutoffs = std::move(DetailedSummaryCutoffs);
if (ShowDetailedSummary && Cutoffs.empty()) {
Cutoffs = ProfileSummaryBuilder::DefaultCutoffs;
@@ -2583,6 +2634,19 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts,
if (ShowProfileVersion)
OS << "Profile version: " << Reader->getVersion() << "\n";
+
+ if (ShowTemporalProfTraces) {
+ auto &Traces = Reader->getTemporalProfTraces();
+ OS << "Temporal Profile Traces (samples=" << Traces.size()
+ << " seen=" << Reader->getTemporalProfTraceStreamSize() << "):\n";
+ for (unsigned i = 0; i < Traces.size(); i++) {
+ OS << " Temporal Profile Trace " << i << " (weight=" << Traces[i].Weight
+ << " count=" << Traces[i].FunctionNameRefs.size() << "):\n";
+ for (auto &NameRef : Traces[i].FunctionNameRefs)
+ OS << " " << Reader->getSymtab().getFuncName(NameRef) << "\n";
+ }
+ }
+
return 0;
}
@@ -2742,8 +2806,9 @@ static int showSampleProfile(const std::string &Filename, bool ShowCounts,
exitWithError("YAML output is not supported for sample profiles");
using namespace sampleprof;
LLVMContext Context;
- auto ReaderOrErr =
- SampleProfileReader::create(Filename, Context, FSDiscriminatorPassOption);
+ auto FS = vfs::getRealFileSystem();
+ auto ReaderOrErr = SampleProfileReader::create(Filename, Context, *FS,
+ FSDiscriminatorPassOption);
if (std::error_code EC = ReaderOrErr.getError())
exitWithErrorCode(EC, Filename);
@@ -2917,6 +2982,9 @@ static int show_main(int argc, const char *argv[]) {
"extbinary format"));
cl::opt<bool> ShowBinaryIds("binary-ids", cl::init(false),
cl::desc("Show binary ids in the profile. "));
+ cl::opt<bool> ShowTemporalProfTraces(
+ "temporal-profile-traces",
+ cl::desc("Show temporal profile traces in the profile."));
cl::opt<std::string> DebugInfoFilename(
"debug-info", cl::init(""),
cl::desc("Read and extract profile metadata from debug info and show "
@@ -2961,8 +3029,8 @@ static int show_main(int argc, const char *argv[]) {
Filename, ShowCounts, TopNFunctions, ShowIndirectCallTargets,
ShowMemOPSizes, ShowDetailedSummary, DetailedSummaryCutoffs,
ShowAllFunctions, ShowCS, ValueCutoff, OnlyListBelow, ShowFunction,
- TextFormat, ShowBinaryIds, ShowCovered, ShowProfileVersion, SFormat,
- OS);
+ TextFormat, ShowBinaryIds, ShowCovered, ShowProfileVersion,
+ ShowTemporalProfTraces, SFormat, OS);
if (ProfileKind == sample)
return showSampleProfile(Filename, ShowCounts, TopNFunctions,
ShowAllFunctions, ShowDetailedSummary,
@@ -2971,20 +3039,73 @@ static int show_main(int argc, const char *argv[]) {
return showMemProfProfile(Filename, ProfiledBinary, SFormat, OS);
}
-int llvm_profdata_main(int argc, char **argvNonConst) {
+static int order_main(int argc, const char *argv[]) {
+ cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"));
+ cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
+ cl::init("-"), cl::desc("Output file"));
+ cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
+ cl::aliasopt(OutputFilename));
+ cl::ParseCommandLineOptions(argc, argv, "LLVM profile data order\n");
+
+ std::error_code EC;
+ raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF);
+ if (EC)
+ exitWithErrorCode(EC, OutputFilename);
+ auto FS = vfs::getRealFileSystem();
+ auto ReaderOrErr = InstrProfReader::create(Filename, *FS);
+ if (Error E = ReaderOrErr.takeError())
+ exitWithError(std::move(E), Filename);
+
+ auto Reader = std::move(ReaderOrErr.get());
+ for (auto &I : *Reader) {
+ // Read all entries
+ (void)I;
+ }
+ auto &Traces = Reader->getTemporalProfTraces();
+ auto Nodes = TemporalProfTraceTy::createBPFunctionNodes(Traces);
+ BalancedPartitioningConfig Config;
+ BalancedPartitioning BP(Config);
+ BP.run(Nodes);
+
+ WithColor::note() << "# Ordered " << Nodes.size() << " functions\n";
+ for (auto &N : Nodes) {
+ auto FuncName = Reader->getSymtab().getFuncName(N.Id);
+ if (FuncName.contains(':')) {
+ // GlobalValue::getGlobalIdentifier() prefixes the filename if the symbol
+ // is local. This logic will break if there is a colon in the filename,
+ // but we cannot use rsplit() because ObjC symbols can have colons.
+ auto [Filename, ParsedFuncName] = FuncName.split(':');
+ // Emit a comment describing where this symbol came from
+ OS << "# " << Filename << "\n";
+ FuncName = ParsedFuncName;
+ }
+ OS << FuncName << "\n";
+ }
+ return 0;
+}
+
+typedef int (*llvm_profdata_subcommand)(int, const char *[]);
+
+static std::tuple<StringRef, llvm_profdata_subcommand>
+ llvm_profdata_subcommands[] = {
+ {"merge", merge_main},
+ {"show", show_main},
+ {"order", order_main},
+ {"overlap", overlap_main},
+};
+
+int llvm_profdata_main(int argc, char **argvNonConst,
+ const llvm::ToolContext &) {
const char **argv = const_cast<const char **>(argvNonConst);
InitLLVM X(argc, argv);
StringRef ProgName(sys::path::filename(argv[0]));
if (argc > 1) {
- int (*func)(int, const char *[]) = nullptr;
- if (strcmp(argv[1], "merge") == 0)
- func = merge_main;
- else if (strcmp(argv[1], "show") == 0)
- func = show_main;
- else if (strcmp(argv[1], "overlap") == 0)
- func = overlap_main;
+ llvm_profdata_subcommand func = nullptr;
+ for (auto [subcmd_name, subcmd_action] : llvm_profdata_subcommands)
+ if (subcmd_name == argv[1])
+ func = subcmd_action;
if (func) {
std::string Invocation(ProgName.str() + " " + argv[1]);
@@ -2999,7 +3120,17 @@ int llvm_profdata_main(int argc, char **argvNonConst) {
<< "USAGE: " << ProgName << " <command> [args...]\n"
<< "USAGE: " << ProgName << " <command> -help\n\n"
<< "See each individual command --help for more details.\n"
- << "Available commands: merge, show, overlap\n";
+ << "Available commands: "
+ << join(map_range(llvm_profdata_subcommands,
+ [](auto const &KV) { return std::get<0>(KV); }),
+ ", ")
+ << "\n";
+ return 0;
+ }
+
+ if (strcmp(argv[1], "--version") == 0) {
+ outs() << ProgName << '\n';
+ cl::PrintVersionMessage();
return 0;
}
}
@@ -3009,6 +3140,10 @@ int llvm_profdata_main(int argc, char **argvNonConst) {
else
errs() << ProgName << ": Unknown command!\n";
- errs() << "USAGE: " << ProgName << " <merge|show|overlap> [args...]\n";
+ errs() << "USAGE: " << ProgName << " <"
+ << join(map_range(llvm_profdata_subcommands,
+ [](auto const &KV) { return std::get<0>(KV); }),
+ "|")
+ << "> [args...]\n";
return 1;
}
diff --git a/contrib/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp b/contrib/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp
index 5279e5853cc5..0a5073d2d23f 100644
--- a/contrib/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -344,6 +344,7 @@ const EnumEntry<COFF::MachineTypes> ImageFileMachineType[] = {
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM ),
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64 ),
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64EC ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64X ),
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMNT ),
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_EBC ),
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_I386 ),
@@ -544,9 +545,10 @@ const EnumEntry<COFF::DebugType> ImageDebugType[] = {
static const EnumEntry<COFF::WeakExternalCharacteristics>
WeakExternalCharacteristics[] = {
- { "NoLibrary", COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY },
- { "Library" , COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY },
- { "Alias" , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS }
+ { "NoLibrary" , COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY },
+ { "Library" , COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY },
+ { "Alias" , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS },
+ { "AntiDependency" , COFF::IMAGE_WEAK_EXTERN_ANTI_DEPENDENCY },
};
const EnumEntry<uint32_t> SubSectionTypes[] = {
@@ -840,6 +842,93 @@ void COFFDumper::printCOFFLoadConfig() {
else
printCOFFLoadConfig(Obj->getLoadConfig32(), Tables);
+ if (auto CHPE = Obj->getCHPEMetadata()) {
+ ListScope LS(W, "CHPEMetadata");
+ W.printHex("Version", CHPE->Version);
+
+ if (CHPE->CodeMapCount) {
+ ListScope CMLS(W, "CodeMap");
+
+ uintptr_t CodeMapInt;
+ if (Error E = Obj->getRvaPtr(CHPE->CodeMap, CodeMapInt))
+ reportError(std::move(E), Obj->getFileName());
+ auto CodeMap = reinterpret_cast<const chpe_range_entry *>(CodeMapInt);
+ for (uint32_t i = 0; i < CHPE->CodeMapCount; i++) {
+ uint32_t Start = CodeMap[i].StartOffset & ~3;
+ W.startLine() << W.hex(Start) << " - "
+ << W.hex(Start + CodeMap[i].Length) << " ";
+ switch (CodeMap[i].StartOffset & 3) {
+ case CHPE_RANGE_ARM64:
+ W.getOStream() << "ARM64\n";
+ break;
+ case CHPE_RANGE_ARM64EC:
+ W.getOStream() << "ARM64EC\n";
+ break;
+ case CHPE_RANGE_AMD64:
+ W.getOStream() << "X64\n";
+ break;
+ default:
+ W.getOStream() << W.hex(CodeMap[i].StartOffset & 3) << "\n";
+ break;
+ }
+ }
+ } else {
+ W.printNumber("CodeMap", CHPE->CodeMap);
+ }
+
+ if (CHPE->CodeRangesToEntryPointsCount) {
+ ListScope CRLS(W, "CodeRangesToEntryPoints");
+
+ uintptr_t CodeRangesInt;
+ if (Error E =
+ Obj->getRvaPtr(CHPE->CodeRangesToEntryPoints, CodeRangesInt))
+ reportError(std::move(E), Obj->getFileName());
+ auto CodeRanges =
+ reinterpret_cast<const chpe_code_range_entry *>(CodeRangesInt);
+ for (uint32_t i = 0; i < CHPE->CodeRangesToEntryPointsCount; i++) {
+ W.startLine() << W.hex(CodeRanges[i].StartRva) << " - "
+ << W.hex(CodeRanges[i].EndRva) << " -> "
+ << W.hex(CodeRanges[i].EntryPoint) << "\n";
+ }
+ } else {
+ W.printNumber("CodeRangesToEntryPoints", CHPE->CodeRangesToEntryPoints);
+ }
+
+ if (CHPE->RedirectionMetadataCount) {
+ ListScope RMLS(W, "RedirectionMetadata");
+
+ uintptr_t RedirMetadataInt;
+ if (Error E = Obj->getRvaPtr(CHPE->RedirectionMetadata, RedirMetadataInt))
+ reportError(std::move(E), Obj->getFileName());
+ auto RedirMetadata =
+ reinterpret_cast<const chpe_redirection_entry *>(RedirMetadataInt);
+ for (uint32_t i = 0; i < CHPE->RedirectionMetadataCount; i++) {
+ W.startLine() << W.hex(RedirMetadata[i].Source) << " -> "
+ << W.hex(RedirMetadata[i].Destination) << "\n";
+ }
+ } else {
+ W.printNumber("RedirectionMetadata", CHPE->RedirectionMetadata);
+ }
+
+ W.printHex("__os_arm64x_dispatch_call_no_redirect",
+ CHPE->__os_arm64x_dispatch_call_no_redirect);
+ W.printHex("__os_arm64x_dispatch_ret", CHPE->__os_arm64x_dispatch_ret);
+ W.printHex("__os_arm64x_dispatch_call", CHPE->__os_arm64x_dispatch_call);
+ W.printHex("__os_arm64x_dispatch_icall", CHPE->__os_arm64x_dispatch_icall);
+ W.printHex("__os_arm64x_dispatch_icall_cfg",
+ CHPE->__os_arm64x_dispatch_icall_cfg);
+ W.printHex("AlternateEntryPoint", CHPE->AlternateEntryPoint);
+ W.printHex("AuxiliaryIAT", CHPE->AuxiliaryIAT);
+ W.printHex("GetX64InformationFunctionPointer",
+ CHPE->GetX64InformationFunctionPointer);
+ W.printHex("SetX64InformationFunctionPointer",
+ CHPE->SetX64InformationFunctionPointer);
+ W.printHex("ExtraRFETable", CHPE->ExtraRFETable);
+ W.printHex("ExtraRFETableSize", CHPE->ExtraRFETableSize);
+ W.printHex("__os_arm64x_dispatch_fptr", CHPE->__os_arm64x_dispatch_fptr);
+ W.printHex("AuxiliaryIATCopy", CHPE->AuxiliaryIATCopy);
+ }
+
if (Tables.SEHTableVA) {
ListScope LS(W, "SEHTable");
printRVATable(Tables.SEHTableVA, Tables.SEHTableCount, 4);
@@ -919,7 +1008,7 @@ void COFFDumper::printCOFFLoadConfig(const T *Conf, LoadConfigTables &Tables) {
W.printHex("SecurityCookie", Conf->SecurityCookie);
// Print the safe SEH table if present.
- if (Conf->Size < offsetof(coff_load_configuration32, GuardCFCheckFunction))
+ if (Conf->Size < offsetof(T, GuardCFCheckFunction))
return;
W.printHex("SEHandlerTable", Conf->SEHandlerTable);
W.printNumber("SEHandlerCount", Conf->SEHandlerCount);
@@ -1670,6 +1759,7 @@ void COFFDumper::printUnwindInfo() {
}
case COFF::IMAGE_FILE_MACHINE_ARM64:
case COFF::IMAGE_FILE_MACHINE_ARM64EC:
+ case COFF::IMAGE_FILE_MACHINE_ARM64X:
case COFF::IMAGE_FILE_MACHINE_ARMNT: {
ARM::WinEH::Decoder Decoder(W, Obj->getMachine() !=
COFF::IMAGE_FILE_MACHINE_ARMNT);
diff --git a/contrib/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp b/contrib/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp
index 45fff0cc4a76..aa924823e554 100644
--- a/contrib/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -220,6 +220,15 @@ public:
void printVersionInfo() override;
void printArchSpecificInfo() override;
void printStackMap() const override;
+ void printMemtag() override;
+ ArrayRef<uint8_t> getMemtagGlobalsSectionContents(uint64_t ExpectedAddr);
+
+ // Hash histogram shows statistics of how efficient the hash was for the
+ // dynamic symbol table. The table shows the number of hash buckets for
+ // different lengths of chains as an absolute number and percentage of the
+ // total buckets, and the cumulative coverage of symbols for each set of
+ // buckets.
+ void printHashHistograms() override;
const object::ELFObjectFile<ELFT> &getElfObject() const { return ObjF; };
@@ -234,6 +243,9 @@ public:
return 4;
}
+ std::vector<EnumEntry<unsigned>>
+ getOtherFlagsFromSymbol(const Elf_Ehdr &Header, const Elf_Sym &Symbol) const;
+
Elf_Dyn_Range dynamic_table() const {
// A valid .dynamic section contains an array of entries terminated
// with a DT_NULL entry. However, sometimes the section content may
@@ -296,6 +308,17 @@ protected:
virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0;
virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0;
+ virtual void printMemtag(
+ const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
+ const ArrayRef<uint8_t> AndroidNoteDesc,
+ const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) = 0;
+
+ virtual void printHashHistogram(const Elf_Hash &HashTable) const;
+ virtual void printGnuHashHistogram(const Elf_GnuHash &GnuHashTable) const;
+ virtual void printHashHistogramStats(size_t NBucket, size_t MaxChain,
+ size_t TotalSyms, ArrayRef<size_t> Count,
+ bool IsGnu) const = 0;
+
Expected<ArrayRef<Elf_Versym>>
getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab,
StringRef *StrTab, const Elf_Shdr **SymTabSec) const;
@@ -323,12 +346,6 @@ protected:
void printRelocatableStackSizes(std::function<void()> PrintHeader);
void printNonRelocatableStackSizes(std::function<void()> PrintHeader);
- /// Retrieves sections with corresponding relocation sections based on
- /// IsMatch.
- void getSectionAndRelocations(
- std::function<bool(const Elf_Shdr &)> IsMatch,
- llvm::MapVector<const Elf_Shdr *, const Elf_Shdr *> &SecToRelocMap);
-
const object::ELFObjectFile<ELFT> &ObjF;
const ELFFile<ELFT> &Obj;
StringRef FileName;
@@ -570,17 +587,21 @@ public:
void printVersionSymbolSection(const Elf_Shdr *Sec) override;
void printVersionDefinitionSection(const Elf_Shdr *Sec) override;
void printVersionDependencySection(const Elf_Shdr *Sec) override;
- void printHashHistograms() override;
void printCGProfile() override;
void printBBAddrMaps() override;
void printAddrsig() override;
void printNotes() override;
void printELFLinkerOptions() override;
void printStackSizes() override;
+ void printMemtag(
+ const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
+ const ArrayRef<uint8_t> AndroidNoteDesc,
+ const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) override;
+ void printHashHistogramStats(size_t NBucket, size_t MaxChain,
+ size_t TotalSyms, ArrayRef<size_t> Count,
+ bool IsGnu) const override;
private:
- void printHashHistogram(const Elf_Hash &HashTable);
- void printGnuHashHistogram(const Elf_GnuHash &GnuHashTable);
void printHashTableSymbols(const Elf_Hash &HashTable);
void printGnuHashTableSymbols(const Elf_GnuHash &GnuHashTable);
@@ -674,21 +695,27 @@ public:
void printVersionSymbolSection(const Elf_Shdr *Sec) override;
void printVersionDefinitionSection(const Elf_Shdr *Sec) override;
void printVersionDependencySection(const Elf_Shdr *Sec) override;
- void printHashHistograms() override;
void printCGProfile() override;
void printBBAddrMaps() override;
void printAddrsig() override;
void printNotes() override;
void printELFLinkerOptions() override;
void printStackSizes() override;
+ void printMemtag(
+ const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
+ const ArrayRef<uint8_t> AndroidNoteDesc,
+ const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) override;
+ void printSymbolSection(const Elf_Sym &Symbol, unsigned SymIndex,
+ DataRegion<Elf_Word> ShndxTable) const;
+ void printHashHistogramStats(size_t NBucket, size_t MaxChain,
+ size_t TotalSyms, ArrayRef<size_t> Count,
+ bool IsGnu) const override;
private:
void printRelrReloc(const Elf_Relr &R) override;
void printRelRelaReloc(const Relocation<ELFT> &R,
const RelSymbol<ELFT> &RelSym) override;
- void printSymbolSection(const Elf_Sym &Symbol, unsigned SymIndex,
- DataRegion<Elf_Word> ShndxTable) const;
void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
DataRegion<Elf_Word> ShndxTable,
std::optional<StringRef> StrTable, bool IsDynamic,
@@ -701,8 +728,22 @@ private:
void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
void printMipsABIFlags() override;
+ virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const;
protected:
+ virtual std::string getGroupSectionHeaderName() const;
+ void printSymbolOtherField(const Elf_Sym &Symbol) const;
+ virtual void printExpandedRelRelaReloc(const Relocation<ELFT> &R,
+ StringRef SymbolName,
+ StringRef RelocName);
+ virtual void printDefaultRelRelaReloc(const Relocation<ELFT> &R,
+ StringRef SymbolName,
+ StringRef RelocName);
+ virtual void printRelocationSectionInfo(const Elf_Shdr &Sec, StringRef Name,
+ const unsigned SecNdx);
+ virtual void printSectionGroupMembers(StringRef Name, uint64_t Idx) const;
+ virtual void printEmptyGroupMessage() const;
+
ScopedPrinter &W;
};
@@ -715,9 +756,23 @@ public:
JSONELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer)
: LLVMELFDumper<ELFT>(ObjF, Writer) {}
+ std::string getGroupSectionHeaderName() const override;
+
void printFileSummary(StringRef FileStr, ObjectFile &Obj,
ArrayRef<std::string> InputFilenames,
const Archive *A) override;
+ virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const override;
+
+ void printDefaultRelRelaReloc(const Relocation<ELFT> &R,
+ StringRef SymbolName,
+ StringRef RelocName) override;
+
+ void printRelocationSectionInfo(const Elf_Shdr &Sec, StringRef Name,
+ const unsigned SecNdx) override;
+
+ void printSectionGroupMembers(StringRef Name, uint64_t Idx) const override;
+
+ void printEmptyGroupMessage() const override;
private:
std::unique_ptr<DictScope> FileScope;
@@ -853,7 +908,7 @@ ELFDumper<ELFT>::getShndxTable(const Elf_Shdr *Symtab) const {
}
static std::string maybeDemangle(StringRef Name) {
- return opts::Demangle ? demangle(std::string(Name)) : Name.str();
+ return opts::Demangle ? demangle(Name) : Name.str();
}
template <typename ELFT>
@@ -1533,6 +1588,8 @@ const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion3[] = {
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90A),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90C),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX940),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX941),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX942),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1010),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1011),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1012),
@@ -1548,6 +1605,8 @@ const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion3[] = {
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1101),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1102),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1103),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1150),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1151),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_V3),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_SRAMECC_V3)
};
@@ -1593,6 +1652,8 @@ const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion4[] = {
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90A),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90C),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX940),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX941),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX942),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1010),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1011),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1012),
@@ -1608,6 +1669,8 @@ const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion4[] = {
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1101),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1102),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1103),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1150),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1151),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_ANY_V4),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_OFF_V4),
LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_ON_V4),
@@ -2251,7 +2314,29 @@ std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type,
case DT_AARCH64_BTI_PLT:
case DT_AARCH64_PAC_PLT:
case DT_AARCH64_VARIANT_PCS:
+ case DT_AARCH64_MEMTAG_GLOBALSSZ:
return std::to_string(Value);
+ case DT_AARCH64_MEMTAG_MODE:
+ switch (Value) {
+ case 0:
+ return "Synchronous (0)";
+ case 1:
+ return "Asynchronous (1)";
+ default:
+ return (Twine("Unknown (") + Twine(Value) + ")").str();
+ }
+ case DT_AARCH64_MEMTAG_HEAP:
+ case DT_AARCH64_MEMTAG_STACK:
+ switch (Value) {
+ case 0:
+ return "Disabled (0)";
+ case 1:
+ return "Enabled (1)";
+ default:
+ return (Twine("Unknown (") + Twine(Value) + ")").str();
+ }
+ case DT_AARCH64_MEMTAG_GLOBALS:
+ return (Twine("0x") + utohexstr(Value, /*LowerCase=*/true)).str();
default:
break;
}
@@ -2624,6 +2709,116 @@ void ELFDumper<ELFT>::printGnuHashTable() {
W.printHexList("Values", *Chains);
}
+template <typename ELFT> void ELFDumper<ELFT>::printHashHistograms() {
+ // Print histogram for the .hash section.
+ if (this->HashTable) {
+ if (Error E = checkHashTable<ELFT>(*this, this->HashTable))
+ this->reportUniqueWarning(std::move(E));
+ else
+ printHashHistogram(*this->HashTable);
+ }
+
+ // Print histogram for the .gnu.hash section.
+ if (this->GnuHashTable) {
+ if (Error E = checkGNUHashTable<ELFT>(this->Obj, this->GnuHashTable))
+ this->reportUniqueWarning(std::move(E));
+ else
+ printGnuHashHistogram(*this->GnuHashTable);
+ }
+}
+
+template <typename ELFT>
+void ELFDumper<ELFT>::printHashHistogram(const Elf_Hash &HashTable) const {
+ size_t NBucket = HashTable.nbucket;
+ size_t NChain = HashTable.nchain;
+ ArrayRef<Elf_Word> Buckets = HashTable.buckets();
+ ArrayRef<Elf_Word> Chains = HashTable.chains();
+ size_t TotalSyms = 0;
+ // If hash table is correct, we have at least chains with 0 length.
+ size_t MaxChain = 1;
+
+ if (NChain == 0 || NBucket == 0)
+ return;
+
+ std::vector<size_t> ChainLen(NBucket, 0);
+ // Go over all buckets and and note chain lengths of each bucket (total
+ // unique chain lengths).
+ for (size_t B = 0; B < NBucket; ++B) {
+ BitVector Visited(NChain);
+ for (size_t C = Buckets[B]; C < NChain; C = Chains[C]) {
+ if (C == ELF::STN_UNDEF)
+ break;
+ if (Visited[C]) {
+ this->reportUniqueWarning(
+ ".hash section is invalid: bucket " + Twine(C) +
+ ": a cycle was detected in the linked chain");
+ break;
+ }
+ Visited[C] = true;
+ if (MaxChain <= ++ChainLen[B])
+ ++MaxChain;
+ }
+ TotalSyms += ChainLen[B];
+ }
+
+ if (!TotalSyms)
+ return;
+
+ std::vector<size_t> Count(MaxChain, 0);
+ // Count how long is the chain for each bucket.
+ for (size_t B = 0; B < NBucket; B++)
+ ++Count[ChainLen[B]];
+ // Print Number of buckets with each chain lengths and their cumulative
+ // coverage of the symbols.
+ printHashHistogramStats(NBucket, MaxChain, TotalSyms, Count, /*IsGnu=*/false);
+}
+
+template <class ELFT>
+void ELFDumper<ELFT>::printGnuHashHistogram(
+ const Elf_GnuHash &GnuHashTable) const {
+ Expected<ArrayRef<Elf_Word>> ChainsOrErr =
+ getGnuHashTableChains<ELFT>(this->DynSymRegion, &GnuHashTable);
+ if (!ChainsOrErr) {
+ this->reportUniqueWarning("unable to print the GNU hash table histogram: " +
+ toString(ChainsOrErr.takeError()));
+ return;
+ }
+
+ ArrayRef<Elf_Word> Chains = *ChainsOrErr;
+ size_t Symndx = GnuHashTable.symndx;
+ size_t TotalSyms = 0;
+ size_t MaxChain = 1;
+
+ size_t NBucket = GnuHashTable.nbuckets;
+ if (Chains.empty() || NBucket == 0)
+ return;
+
+ ArrayRef<Elf_Word> Buckets = GnuHashTable.buckets();
+ std::vector<size_t> ChainLen(NBucket, 0);
+ for (size_t B = 0; B < NBucket; ++B) {
+ if (!Buckets[B])
+ continue;
+ size_t Len = 1;
+ for (size_t C = Buckets[B] - Symndx;
+ C < Chains.size() && (Chains[C] & 1) == 0; ++C)
+ if (MaxChain < ++Len)
+ ++MaxChain;
+ ChainLen[B] = Len;
+ TotalSyms += Len;
+ }
+ ++MaxChain;
+
+ if (!TotalSyms)
+ return;
+
+ std::vector<size_t> Count(MaxChain, 0);
+ for (size_t B = 0; B < NBucket; ++B)
+ ++Count[ChainLen[B]];
+ // Print Number of buckets with each chain lengths and their cumulative
+ // coverage of the symbols.
+ printHashHistogramStats(NBucket, MaxChain, TotalSyms, Count, /*IsGnu=*/true);
+}
+
template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {
StringRef SOName = "<Not found>";
if (SONameOffset)
@@ -3243,6 +3438,35 @@ void ELFDumper<ELFT>::printReloc(const Relocation<ELFT> &R, unsigned RelIndex,
printRelRelaReloc(R, *Target);
}
+template <class ELFT>
+std::vector<EnumEntry<unsigned>>
+ELFDumper<ELFT>::getOtherFlagsFromSymbol(const Elf_Ehdr &Header,
+ const Elf_Sym &Symbol) const {
+ std::vector<EnumEntry<unsigned>> SymOtherFlags(std::begin(ElfSymOtherFlags),
+ std::end(ElfSymOtherFlags));
+ if (Header.e_machine == EM_MIPS) {
+ // Someone in their infinite wisdom decided to make STO_MIPS_MIPS16
+ // flag overlap with other ST_MIPS_xxx flags. So consider both
+ // cases separately.
+ if ((Symbol.st_other & STO_MIPS_MIPS16) == STO_MIPS_MIPS16)
+ SymOtherFlags.insert(SymOtherFlags.end(),
+ std::begin(ElfMips16SymOtherFlags),
+ std::end(ElfMips16SymOtherFlags));
+ else
+ SymOtherFlags.insert(SymOtherFlags.end(),
+ std::begin(ElfMipsSymOtherFlags),
+ std::end(ElfMipsSymOtherFlags));
+ } else if (Header.e_machine == EM_AARCH64) {
+ SymOtherFlags.insert(SymOtherFlags.end(),
+ std::begin(ElfAArch64SymOtherFlags),
+ std::end(ElfAArch64SymOtherFlags));
+ } else if (Header.e_machine == EM_RISCV) {
+ SymOtherFlags.insert(SymOtherFlags.end(), std::begin(ElfRISCVSymOtherFlags),
+ std::end(ElfRISCVSymOtherFlags));
+ }
+ return SymOtherFlags;
+}
+
static inline void printFields(formatted_raw_ostream &OS, StringRef Str1,
StringRef Str2) {
OS.PadToColumn(2u);
@@ -3537,15 +3761,18 @@ void GNUELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R,
if (RelSym.Sym)
Fields[3].Str =
to_string(format_hex_no_prefix(RelSym.Sym->getValue(), Width));
+ if (RelSym.Sym && RelSym.Name.empty())
+ Fields[4].Str = "<null>";
+ else
+ Fields[4].Str = std::string(RelSym.Name);
- Fields[4].Str = std::string(RelSym.Name);
for (const Field &F : Fields)
printField(F);
std::string Addend;
if (std::optional<int64_t> A = R.Addend) {
int64_t RelAddend = *A;
- if (!RelSym.Name.empty()) {
+ if (!Fields[4].Str.empty()) {
if (RelAddend < 0) {
Addend = " - ";
RelAddend = std::abs(RelAddend);
@@ -4744,108 +4971,16 @@ void GNUELFDumper<ELFT>::printVersionDependencySection(const Elf_Shdr *Sec) {
}
template <class ELFT>
-void GNUELFDumper<ELFT>::printHashHistogram(const Elf_Hash &HashTable) {
- size_t NBucket = HashTable.nbucket;
- size_t NChain = HashTable.nchain;
- ArrayRef<Elf_Word> Buckets = HashTable.buckets();
- ArrayRef<Elf_Word> Chains = HashTable.chains();
- size_t TotalSyms = 0;
- // If hash table is correct, we have at least chains with 0 length
- size_t MaxChain = 1;
- size_t CumulativeNonZero = 0;
-
- if (NChain == 0 || NBucket == 0)
- return;
-
- std::vector<size_t> ChainLen(NBucket, 0);
- // Go over all buckets and and note chain lengths of each bucket (total
- // unique chain lengths).
- for (size_t B = 0; B < NBucket; B++) {
- BitVector Visited(NChain);
- for (size_t C = Buckets[B]; C < NChain; C = Chains[C]) {
- if (C == ELF::STN_UNDEF)
- break;
- if (Visited[C]) {
- this->reportUniqueWarning(".hash section is invalid: bucket " +
- Twine(C) +
- ": a cycle was detected in the linked chain");
- break;
- }
- Visited[C] = true;
- if (MaxChain <= ++ChainLen[B])
- MaxChain++;
- }
- TotalSyms += ChainLen[B];
- }
-
- if (!TotalSyms)
- return;
-
- std::vector<size_t> Count(MaxChain, 0);
- // Count how long is the chain for each bucket
- for (size_t B = 0; B < NBucket; B++)
- ++Count[ChainLen[B]];
- // Print Number of buckets with each chain lengths and their cumulative
- // coverage of the symbols
- OS << "Histogram for bucket list length (total of " << NBucket
- << " buckets)\n"
- << " Length Number % of total Coverage\n";
- for (size_t I = 0; I < MaxChain; I++) {
- CumulativeNonZero += Count[I] * I;
- OS << format("%7lu %-10lu (%5.1f%%) %5.1f%%\n", I, Count[I],
- (Count[I] * 100.0) / NBucket,
- (CumulativeNonZero * 100.0) / TotalSyms);
- }
-}
-
-template <class ELFT>
-void GNUELFDumper<ELFT>::printGnuHashHistogram(
- const Elf_GnuHash &GnuHashTable) {
- Expected<ArrayRef<Elf_Word>> ChainsOrErr =
- getGnuHashTableChains<ELFT>(this->DynSymRegion, &GnuHashTable);
- if (!ChainsOrErr) {
- this->reportUniqueWarning("unable to print the GNU hash table histogram: " +
- toString(ChainsOrErr.takeError()));
- return;
- }
-
- ArrayRef<Elf_Word> Chains = *ChainsOrErr;
- size_t Symndx = GnuHashTable.symndx;
- size_t TotalSyms = 0;
- size_t MaxChain = 1;
+void GNUELFDumper<ELFT>::printHashHistogramStats(size_t NBucket,
+ size_t MaxChain,
+ size_t TotalSyms,
+ ArrayRef<size_t> Count,
+ bool IsGnu) const {
size_t CumulativeNonZero = 0;
-
- size_t NBucket = GnuHashTable.nbuckets;
- if (Chains.empty() || NBucket == 0)
- return;
-
- ArrayRef<Elf_Word> Buckets = GnuHashTable.buckets();
- std::vector<size_t> ChainLen(NBucket, 0);
- for (size_t B = 0; B < NBucket; B++) {
- if (!Buckets[B])
- continue;
- size_t Len = 1;
- for (size_t C = Buckets[B] - Symndx;
- C < Chains.size() && (Chains[C] & 1) == 0; C++)
- if (MaxChain < ++Len)
- MaxChain++;
- ChainLen[B] = Len;
- TotalSyms += Len;
- }
- MaxChain++;
-
- if (!TotalSyms)
- return;
-
- std::vector<size_t> Count(MaxChain, 0);
- for (size_t B = 0; B < NBucket; B++)
- ++Count[ChainLen[B]];
- // Print Number of buckets with each chain lengths and their cumulative
- // coverage of the symbols
- OS << "Histogram for `.gnu.hash' bucket list length (total of " << NBucket
- << " buckets)\n"
+ OS << "Histogram for" << (IsGnu ? " `.gnu.hash'" : "")
+ << " bucket list length (total of " << NBucket << " buckets)\n"
<< " Length Number % of total Coverage\n";
- for (size_t I = 0; I < MaxChain; I++) {
+ for (size_t I = 0; I < MaxChain; ++I) {
CumulativeNonZero += Count[I] * I;
OS << format("%7lu %-10lu (%5.1f%%) %5.1f%%\n", I, Count[I],
(Count[I] * 100.0) / NBucket,
@@ -4853,28 +4988,6 @@ void GNUELFDumper<ELFT>::printGnuHashHistogram(
}
}
-// Hash histogram shows statistics of how efficient the hash was for the
-// dynamic symbol table. The table shows the number of hash buckets for
-// different lengths of chains as an absolute number and percentage of the total
-// buckets, and the cumulative coverage of symbols for each set of buckets.
-template <class ELFT> void GNUELFDumper<ELFT>::printHashHistograms() {
- // Print histogram for the .hash section.
- if (this->HashTable) {
- if (Error E = checkHashTable<ELFT>(*this, this->HashTable))
- this->reportUniqueWarning(std::move(E));
- else
- printHashHistogram(*this->HashTable);
- }
-
- // Print histogram for the .gnu.hash section.
- if (this->GnuHashTable) {
- if (Error E = checkGNUHashTable<ELFT>(this->Obj, this->GnuHashTable))
- this->reportUniqueWarning(std::move(E));
- else
- printGnuHashHistogram(*this->GnuHashTable);
- }
-}
-
template <class ELFT> void GNUELFDumper<ELFT>::printCGProfile() {
OS << "GNUStyle::printCGProfile not implemented\n";
}
@@ -5194,10 +5307,36 @@ static bool printAndroidNote(raw_ostream &OS, uint32_t NoteType,
return false;
for (const auto &KV : Props)
OS << " " << KV.first << ": " << KV.second << '\n';
- OS << '\n';
return true;
}
+template <class ELFT>
+void GNUELFDumper<ELFT>::printMemtag(
+ const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
+ const ArrayRef<uint8_t> AndroidNoteDesc,
+ const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) {
+ OS << "Memtag Dynamic Entries:\n";
+ if (DynamicEntries.empty())
+ OS << " < none found >\n";
+ for (const auto &DynamicEntryKV : DynamicEntries)
+ OS << " " << DynamicEntryKV.first << ": " << DynamicEntryKV.second
+ << "\n";
+
+ if (!AndroidNoteDesc.empty()) {
+ OS << "Memtag Android Note:\n";
+ printAndroidNote(OS, ELF::NT_ANDROID_TYPE_MEMTAG, AndroidNoteDesc);
+ }
+
+ if (Descriptors.empty())
+ return;
+
+ OS << "Memtag Global Descriptors:\n";
+ for (const auto &[Addr, BytesToTag] : Descriptors) {
+ OS << " 0x" << utohexstr(Addr, /*LowerCase=*/true) << ": 0x"
+ << utohexstr(BytesToTag, /*LowerCase=*/true) << "\n";
+ }
+}
+
template <typename ELFT>
static bool printLLVMOMPOFFLOADNote(raw_ostream &OS, uint32_t NoteType,
ArrayRef<uint8_t> Desc) {
@@ -5386,10 +5525,16 @@ static AMDGPUNote getAMDGPUNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {
if (!MsgPackDoc.readFromBlob(MsgPackString, /*Multi=*/false))
return {"", ""};
- AMDGPU::HSAMD::V3::MetadataVerifier Verifier(true);
std::string MetadataString;
- if (!Verifier.verify(MsgPackDoc.getRoot()))
- MetadataString = "Invalid AMDGPU Metadata\n";
+
+ // FIXME: Metadata Verifier only works with AMDHSA.
+ // This is an ugly workaround to avoid the verifier for other MD
+ // formats (e.g. amdpal)
+ if (MsgPackString.find("amdhsa.") != StringRef::npos) {
+ AMDGPU::HSAMD::V3::MetadataVerifier Verifier(true);
+ if (!Verifier.verify(MsgPackDoc.getRoot()))
+ MetadataString = "Invalid AMDGPU Metadata\n";
+ }
raw_string_ostream StrOS(MetadataString);
if (MsgPackDoc.getRoot().isScalar()) {
@@ -5623,6 +5768,12 @@ const NoteType CoreNoteTypes[] = {
"NT_ARM_HW_BREAK (AArch hardware breakpoint registers)"},
{ELF::NT_ARM_HW_WATCH,
"NT_ARM_HW_WATCH (AArch hardware watchpoint registers)"},
+ {ELF::NT_ARM_SVE, "NT_ARM_SVE (AArch64 SVE registers)"},
+ {ELF::NT_ARM_PAC_MASK,
+ "NT_ARM_PAC_MASK (AArch64 Pointer Authentication code masks)"},
+ {ELF::NT_ARM_SSVE, "NT_ARM_SSVE (AArch64 Streaming SVE registers)"},
+ {ELF::NT_ARM_ZA, "NT_ARM_ZA (AArch64 SME ZA registers)"},
+ {ELF::NT_ARM_ZT, "NT_ARM_ZT (AArch64 SME ZT registers)"},
{ELF::NT_FILE, "NT_FILE (mapped files)"},
{ELF::NT_PRXFPREG, "NT_PRXFPREG (user_xfpregs structure)"},
@@ -5681,10 +5832,10 @@ StringRef getNoteTypeName(const typename ELFT::Note &Note, unsigned ELFType) {
}
template <class ELFT>
-static void printNotesHelper(
+static void processNotesHelper(
const ELFDumper<ELFT> &Dumper,
llvm::function_ref<void(std::optional<StringRef>, typename ELFT::Off,
- typename ELFT::Addr)>
+ typename ELFT::Addr, size_t)>
StartNotesFn,
llvm::function_ref<Error(const typename ELFT::Note &, bool)> ProcessNoteFn,
llvm::function_ref<void()> FinishNotesFn) {
@@ -5697,7 +5848,7 @@ static void printNotesHelper(
if (S.sh_type != SHT_NOTE)
continue;
StartNotesFn(expectedToStdOptional(Obj.getSectionName(S)), S.sh_offset,
- S.sh_size);
+ S.sh_size, S.sh_addralign);
Error Err = Error::success();
size_t I = 0;
for (const typename ELFT::Note Note : Obj.notes(S, Err)) {
@@ -5728,7 +5879,7 @@ static void printNotesHelper(
const typename ELFT::Phdr &P = (*PhdrsOrErr)[I];
if (P.p_type != PT_NOTE)
continue;
- StartNotesFn(/*SecName=*/std::nullopt, P.p_offset, P.p_filesz);
+ StartNotesFn(/*SecName=*/std::nullopt, P.p_offset, P.p_filesz, P.p_align);
Error Err = Error::success();
size_t Index = 0;
for (const typename ELFT::Note Note : Obj.notes(P, Err)) {
@@ -5748,10 +5899,12 @@ static void printNotesHelper(
}
template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
+ size_t Align = 0;
bool IsFirstHeader = true;
auto PrintHeader = [&](std::optional<StringRef> SecName,
const typename ELFT::Off Offset,
- const typename ELFT::Addr Size) {
+ const typename ELFT::Addr Size, size_t Al) {
+ Align = std::max<size_t>(Al, 4);
// Print a newline between notes sections to match GNU readelf.
if (!IsFirstHeader) {
OS << '\n';
@@ -5772,7 +5925,7 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error {
StringRef Name = Note.getName();
- ArrayRef<uint8_t> Descriptor = Note.getDesc();
+ ArrayRef<uint8_t> Descriptor = Note.getDesc(Align);
Elf_Word Type = Note.getType();
// Print the note owner/type.
@@ -5837,7 +5990,132 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
return Error::success();
};
- printNotesHelper(*this, PrintHeader, ProcessNote, []() {});
+ processNotesHelper(*this, /*StartNotesFn=*/PrintHeader,
+ /*ProcessNoteFn=*/ProcessNote, /*FinishNotesFn=*/[]() {});
+}
+
+template <class ELFT>
+ArrayRef<uint8_t>
+ELFDumper<ELFT>::getMemtagGlobalsSectionContents(uint64_t ExpectedAddr) {
+ for (const typename ELFT::Shdr &Sec : cantFail(Obj.sections())) {
+ if (Sec.sh_type != SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC)
+ continue;
+ if (Sec.sh_addr != ExpectedAddr) {
+ reportUniqueWarning(
+ "SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section was unexpectedly at 0x" +
+ Twine::utohexstr(Sec.sh_addr) +
+ ", when DT_AARCH64_MEMTAG_GLOBALS says it should be at 0x" +
+ Twine::utohexstr(ExpectedAddr));
+ return ArrayRef<uint8_t>();
+ }
+ Expected<ArrayRef<uint8_t>> Contents = Obj.getSectionContents(Sec);
+ if (auto E = Contents.takeError()) {
+ reportUniqueWarning(
+ "couldn't get SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section contents: " +
+ toString(std::move(E)));
+ return ArrayRef<uint8_t>();
+ }
+ return Contents.get();
+ }
+ return ArrayRef<uint8_t>();
+}
+
+// Reserve the lower three bits of the first byte of the step distance when
+// encoding the memtag descriptors. Found to be the best overall size tradeoff
+// when compiling Android T with full MTE globals enabled.
+constexpr uint64_t MemtagStepVarintReservedBits = 3;
+constexpr uint64_t MemtagGranuleSize = 16;
+
+template <typename ELFT> void ELFDumper<ELFT>::printMemtag() {
+ if (Obj.getHeader().e_machine != EM_AARCH64) return;
+ std::vector<std::pair<std::string, std::string>> DynamicEntries;
+ uint64_t MemtagGlobalsSz = 0;
+ uint64_t MemtagGlobals = 0;
+ for (const typename ELFT::Dyn &Entry : dynamic_table()) {
+ uintX_t Tag = Entry.getTag();
+ switch (Tag) {
+ case DT_AARCH64_MEMTAG_GLOBALSSZ:
+ MemtagGlobalsSz = Entry.getVal();
+ DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag),
+ getDynamicEntry(Tag, Entry.getVal()));
+ break;
+ case DT_AARCH64_MEMTAG_GLOBALS:
+ MemtagGlobals = Entry.getVal();
+ DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag),
+ getDynamicEntry(Tag, Entry.getVal()));
+ break;
+ case DT_AARCH64_MEMTAG_MODE:
+ case DT_AARCH64_MEMTAG_HEAP:
+ case DT_AARCH64_MEMTAG_STACK:
+ DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag),
+ getDynamicEntry(Tag, Entry.getVal()));
+ break;
+ }
+ }
+
+ ArrayRef<uint8_t> AndroidNoteDesc;
+ auto FindAndroidNote = [&](const Elf_Note &Note, bool IsCore) -> Error {
+ if (Note.getName() == "Android" &&
+ Note.getType() == ELF::NT_ANDROID_TYPE_MEMTAG)
+ AndroidNoteDesc = Note.getDesc(4);
+ return Error::success();
+ };
+
+ processNotesHelper(
+ *this,
+ /*StartNotesFn=*/
+ [](std::optional<StringRef>, const typename ELFT::Off,
+ const typename ELFT::Addr, size_t) {},
+ /*ProcessNoteFn=*/FindAndroidNote, /*FinishNotesFn=*/[]() {});
+
+ ArrayRef<uint8_t> Contents = getMemtagGlobalsSectionContents(MemtagGlobals);
+ if (Contents.size() != MemtagGlobalsSz) {
+ reportUniqueWarning(
+ "mismatch between DT_AARCH64_MEMTAG_GLOBALSSZ (0x" +
+ Twine::utohexstr(MemtagGlobalsSz) +
+ ") and SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section size (0x" +
+ Twine::utohexstr(Contents.size()) + ")");
+ Contents = ArrayRef<uint8_t>();
+ }
+
+ std::vector<std::pair<uint64_t, uint64_t>> GlobalDescriptors;
+ uint64_t Address = 0;
+ // See the AArch64 MemtagABI document for a description of encoding scheme:
+ // https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#83encoding-of-sht_aarch64_memtag_globals_dynamic
+ for (size_t I = 0; I < Contents.size();) {
+ const char *Error = nullptr;
+ unsigned DecodedBytes = 0;
+ uint64_t Value = decodeULEB128(Contents.data() + I, &DecodedBytes,
+ Contents.end(), &Error);
+ I += DecodedBytes;
+ if (Error) {
+ reportUniqueWarning(
+ "error decoding distance uleb, " + Twine(DecodedBytes) +
+ " byte(s) into SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC: " + Twine(Error));
+ GlobalDescriptors.clear();
+ break;
+ }
+ uint64_t Distance = Value >> MemtagStepVarintReservedBits;
+ uint64_t GranulesToTag = Value & ((1 << MemtagStepVarintReservedBits) - 1);
+ if (GranulesToTag == 0) {
+ GranulesToTag = decodeULEB128(Contents.data() + I, &DecodedBytes,
+ Contents.end(), &Error) +
+ 1;
+ I += DecodedBytes;
+ if (Error) {
+ reportUniqueWarning(
+ "error decoding size-only uleb, " + Twine(DecodedBytes) +
+ " byte(s) into SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC: " + Twine(Error));
+ GlobalDescriptors.clear();
+ break;
+ }
+ }
+ Address += Distance * MemtagGranuleSize;
+ GlobalDescriptors.emplace_back(Address, GranulesToTag * MemtagGranuleSize);
+ Address += GranulesToTag * MemtagGranuleSize;
+ }
+
+ printMemtag(DynamicEntries, AndroidNoteDesc, GlobalDescriptors);
}
template <class ELFT> void GNUELFDumper<ELFT>::printELFLinkerOptions() {
@@ -6197,37 +6475,10 @@ void ELFDumper<ELFT>::printNonRelocatableStackSizes(
}
template <class ELFT>
-void ELFDumper<ELFT>::getSectionAndRelocations(
- std::function<bool(const Elf_Shdr &)> IsMatch,
- llvm::MapVector<const Elf_Shdr *, const Elf_Shdr *> &SecToRelocMap) {
- for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {
- if (IsMatch(Sec))
- if (SecToRelocMap.insert(std::make_pair(&Sec, (const Elf_Shdr *)nullptr))
- .second)
- continue;
-
- if (Sec.sh_type != ELF::SHT_RELA && Sec.sh_type != ELF::SHT_REL)
- continue;
-
- Expected<const Elf_Shdr *> RelSecOrErr = Obj.getSection(Sec.sh_info);
- if (!RelSecOrErr) {
- reportUniqueWarning(describe(Sec) +
- ": failed to get a relocated section: " +
- toString(RelSecOrErr.takeError()));
- continue;
- }
- const Elf_Shdr *ContentsSec = *RelSecOrErr;
- if (IsMatch(*ContentsSec))
- SecToRelocMap[ContentsSec] = &Sec;
- }
-}
-
-template <class ELFT>
void ELFDumper<ELFT>::printRelocatableStackSizes(
std::function<void()> PrintHeader) {
// Build a map between stack size sections and their corresponding relocation
// sections.
- llvm::MapVector<const Elf_Shdr *, const Elf_Shdr *> StackSizeRelocMap;
auto IsMatch = [&](const Elf_Shdr &Sec) -> bool {
StringRef SectionName;
if (Expected<StringRef> NameOrErr = Obj.getSectionName(Sec))
@@ -6237,9 +6488,16 @@ void ELFDumper<ELFT>::printRelocatableStackSizes(
return SectionName == ".stack_sizes";
};
- getSectionAndRelocations(IsMatch, StackSizeRelocMap);
- for (const auto &StackSizeMapEntry : StackSizeRelocMap) {
+ Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>>
+ StackSizeRelocMapOrErr = Obj.getSectionAndRelocations(IsMatch);
+ if (!StackSizeRelocMapOrErr) {
+ reportUniqueWarning("unable to get stack size map section(s): " +
+ toString(StackSizeRelocMapOrErr.takeError()));
+ return;
+ }
+
+ for (const auto &StackSizeMapEntry : *StackSizeRelocMapOrErr) {
PrintHeader();
const Elf_Shdr *StackSizesELFSec = StackSizeMapEntry.first;
const Elf_Shdr *RelocSec = StackSizeMapEntry.second;
@@ -6607,9 +6865,9 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printGroupSections() {
W.printNumber("Link", G.Link);
W.printNumber("Info", G.Info);
W.printHex("Type", getGroupType(G.Type), G.Type);
- W.startLine() << "Signature: " << G.Signature << "\n";
+ W.printString("Signature", G.Signature);
- ListScope L(W, "Section(s) in group");
+ ListScope L(W, getGroupSectionHeaderName());
for (const GroupMember &GM : G.Members) {
const GroupSection *MainGroup = Map[GM.Index];
if (MainGroup != &G)
@@ -6619,12 +6877,23 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printGroupSections() {
Twine(MainGroup->Index) +
", was also found in the group section with index " +
Twine(G.Index));
- W.startLine() << GM.Name << " (" << GM.Index << ")\n";
+ printSectionGroupMembers(GM.Name, GM.Index);
}
}
if (V.empty())
- W.startLine() << "There are no group sections in the file.\n";
+ printEmptyGroupMessage();
+}
+
+template <class ELFT>
+std::string LLVMELFDumper<ELFT>::getGroupSectionHeaderName() const {
+ return "Section(s) in group";
+}
+
+template <class ELFT>
+void LLVMELFDumper<ELFT>::printSectionGroupMembers(StringRef Name,
+ uint64_t Idx) const {
+ W.startLine() << Name << " (" << Idx << ")\n";
}
template <class ELFT> void LLVMELFDumper<ELFT>::printRelocations() {
@@ -6636,11 +6905,7 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printRelocations() {
StringRef Name = this->getPrintableSectionName(Sec);
unsigned SecNdx = &Sec - &cantFail(this->Obj.sections()).front();
- W.startLine() << "Section (" << SecNdx << ") " << Name << " {\n";
- W.indent();
- this->printRelocationsHelper(Sec);
- W.unindent();
- W.startLine() << "}\n";
+ printRelocationSectionInfo(Sec, Name, SecNdx);
}
}
@@ -6650,26 +6915,54 @@ void LLVMELFDumper<ELFT>::printRelrReloc(const Elf_Relr &R) {
}
template <class ELFT>
+void LLVMELFDumper<ELFT>::printExpandedRelRelaReloc(const Relocation<ELFT> &R,
+ StringRef SymbolName,
+ StringRef RelocName) {
+ DictScope Group(W, "Relocation");
+ W.printHex("Offset", R.Offset);
+ W.printNumber("Type", RelocName, R.Type);
+ W.printNumber("Symbol", !SymbolName.empty() ? SymbolName : "-", R.Symbol);
+ if (R.Addend)
+ W.printHex("Addend", (uintX_t)*R.Addend);
+}
+
+template <class ELFT>
+void LLVMELFDumper<ELFT>::printDefaultRelRelaReloc(const Relocation<ELFT> &R,
+ StringRef SymbolName,
+ StringRef RelocName) {
+ raw_ostream &OS = W.startLine();
+ OS << W.hex(R.Offset) << " " << RelocName << " "
+ << (!SymbolName.empty() ? SymbolName : "-");
+ if (R.Addend)
+ OS << " " << W.hex((uintX_t)*R.Addend);
+ OS << "\n";
+}
+
+template <class ELFT>
+void LLVMELFDumper<ELFT>::printRelocationSectionInfo(const Elf_Shdr &Sec,
+ StringRef Name,
+ const unsigned SecNdx) {
+ DictScope D(W, (Twine("Section (") + Twine(SecNdx) + ") " + Name).str());
+ this->printRelocationsHelper(Sec);
+}
+
+template <class ELFT> void LLVMELFDumper<ELFT>::printEmptyGroupMessage() const {
+ W.startLine() << "There are no group sections in the file.\n";
+}
+
+template <class ELFT>
void LLVMELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R,
const RelSymbol<ELFT> &RelSym) {
StringRef SymbolName = RelSym.Name;
+ if (RelSym.Sym && RelSym.Name.empty())
+ SymbolName = "<null>";
SmallString<32> RelocName;
this->Obj.getRelocationTypeName(R.Type, RelocName);
if (opts::ExpandRelocs) {
- DictScope Group(W, "Relocation");
- W.printHex("Offset", R.Offset);
- W.printNumber("Type", RelocName, R.Type);
- W.printNumber("Symbol", !SymbolName.empty() ? SymbolName : "-", R.Symbol);
- if (R.Addend)
- W.printHex("Addend", (uintX_t)*R.Addend);
+ printExpandedRelRelaReloc(R, SymbolName, RelocName);
} else {
- raw_ostream &OS = W.startLine();
- OS << W.hex(R.Offset) << " " << RelocName << " "
- << (!SymbolName.empty() ? SymbolName : "-");
- if (R.Addend)
- OS << " " << W.hex((uintX_t)*R.Addend);
- OS << "\n";
+ printDefaultRelRelaReloc(R, SymbolName, RelocName);
}
}
@@ -6785,6 +7078,22 @@ void LLVMELFDumper<ELFT>::printSymbolSection(
}
template <class ELFT>
+void LLVMELFDumper<ELFT>::printSymbolOtherField(const Elf_Sym &Symbol) const {
+ std::vector<EnumEntry<unsigned>> SymOtherFlags =
+ this->getOtherFlagsFromSymbol(this->Obj.getHeader(), Symbol);
+ W.printFlags("Other", Symbol.st_other, ArrayRef(SymOtherFlags), 0x3u);
+}
+
+template <class ELFT>
+void LLVMELFDumper<ELFT>::printZeroSymbolOtherField(
+ const Elf_Sym &Symbol) const {
+ assert(Symbol.st_other == 0 && "non-zero Other Field");
+ // Usually st_other flag is zero. Do not pollute the output
+ // by flags enumeration in that case.
+ W.printNumber("Other", 0);
+}
+
+template <class ELFT>
void LLVMELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
DataRegion<Elf_Word> ShndxTable,
std::optional<StringRef> StrTable,
@@ -6805,35 +7114,9 @@ void LLVMELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
else
W.printEnum("Type", SymbolType, ArrayRef(ElfSymbolTypes));
if (Symbol.st_other == 0)
- // Usually st_other flag is zero. Do not pollute the output
- // by flags enumeration in that case.
- W.printNumber("Other", 0);
- else {
- std::vector<EnumEntry<unsigned>> SymOtherFlags(std::begin(ElfSymOtherFlags),
- std::end(ElfSymOtherFlags));
- if (this->Obj.getHeader().e_machine == EM_MIPS) {
- // Someones in their infinite wisdom decided to make STO_MIPS_MIPS16
- // flag overlapped with other ST_MIPS_xxx flags. So consider both
- // cases separately.
- if ((Symbol.st_other & STO_MIPS_MIPS16) == STO_MIPS_MIPS16)
- SymOtherFlags.insert(SymOtherFlags.end(),
- std::begin(ElfMips16SymOtherFlags),
- std::end(ElfMips16SymOtherFlags));
- else
- SymOtherFlags.insert(SymOtherFlags.end(),
- std::begin(ElfMipsSymOtherFlags),
- std::end(ElfMipsSymOtherFlags));
- } else if (this->Obj.getHeader().e_machine == EM_AARCH64) {
- SymOtherFlags.insert(SymOtherFlags.end(),
- std::begin(ElfAArch64SymOtherFlags),
- std::end(ElfAArch64SymOtherFlags));
- } else if (this->Obj.getHeader().e_machine == EM_RISCV) {
- SymOtherFlags.insert(SymOtherFlags.end(),
- std::begin(ElfRISCVSymOtherFlags),
- std::end(ElfRISCVSymOtherFlags));
- }
- W.printFlags("Other", Symbol.st_other, ArrayRef(SymOtherFlags), 0x3u);
- }
+ printZeroSymbolOtherField(Symbol);
+ else
+ printSymbolOtherField(Symbol);
printSymbolSection(Symbol, SymIndex, ShndxTable);
}
@@ -7009,8 +7292,27 @@ void LLVMELFDumper<ELFT>::printVersionDependencySection(const Elf_Shdr *Sec) {
}
}
-template <class ELFT> void LLVMELFDumper<ELFT>::printHashHistograms() {
- W.startLine() << "Hash Histogram not implemented!\n";
+template <class ELFT>
+void LLVMELFDumper<ELFT>::printHashHistogramStats(size_t NBucket,
+ size_t MaxChain,
+ size_t TotalSyms,
+ ArrayRef<size_t> Count,
+ bool IsGnu) const {
+ StringRef HistName = IsGnu ? "GnuHashHistogram" : "HashHistogram";
+ StringRef BucketName = IsGnu ? "Bucket" : "Chain";
+ StringRef ListName = IsGnu ? "Buckets" : "Chains";
+ DictScope Outer(W, HistName);
+ W.printNumber("TotalBuckets", NBucket);
+ ListScope Buckets(W, ListName);
+ size_t CumulativeNonZero = 0;
+ for (size_t I = 0; I < MaxChain; ++I) {
+ CumulativeNonZero += Count[I] * I;
+ DictScope Bucket(W, BucketName);
+ W.printNumber("Length", I);
+ W.printNumber("Count", Count[I]);
+ W.printNumber("Percentage", (float)(Count[I] * 100.0) / NBucket);
+ W.printNumber("Coverage", (float)(CumulativeNonZero * 100.0) / TotalSyms);
+ }
}
// Returns true if rel/rela section exists, and populates SymbolIndices.
@@ -7063,14 +7365,19 @@ static bool getSymbolIndices(const typename ELFT::Shdr *CGRelSection,
}
template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() {
- llvm::MapVector<const Elf_Shdr *, const Elf_Shdr *> SecToRelocMap;
-
auto IsMatch = [](const Elf_Shdr &Sec) -> bool {
return Sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE;
};
- this->getSectionAndRelocations(IsMatch, SecToRelocMap);
- for (const auto &CGMapEntry : SecToRelocMap) {
+ Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr =
+ this->Obj.getSectionAndRelocations(IsMatch);
+ if (!SecToRelocMapOrErr) {
+ this->reportUniqueWarning("unable to get CG Profile section(s): " +
+ toString(SecToRelocMapOrErr.takeError()));
+ return;
+ }
+
+ for (const auto &CGMapEntry : *SecToRelocMapOrErr) {
const Elf_Shdr *CGSection = CGMapEntry.first;
const Elf_Shdr *CGRelSection = CGMapEntry.second;
@@ -7109,21 +7416,35 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() {
template <class ELFT> void LLVMELFDumper<ELFT>::printBBAddrMaps() {
bool IsRelocatable = this->Obj.getHeader().e_type == ELF::ET_REL;
- for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {
- if (Sec.sh_type != SHT_LLVM_BB_ADDR_MAP &&
- Sec.sh_type != SHT_LLVM_BB_ADDR_MAP_V0) {
- continue;
- }
+ using Elf_Shdr = typename ELFT::Shdr;
+ auto IsMatch = [](const Elf_Shdr &Sec) -> bool {
+ return Sec.sh_type == ELF::SHT_LLVM_BB_ADDR_MAP ||
+ Sec.sh_type == ELF::SHT_LLVM_BB_ADDR_MAP_V0;
+ };
+ Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecRelocMapOrErr =
+ this->Obj.getSectionAndRelocations(IsMatch);
+ if (!SecRelocMapOrErr) {
+ this->reportUniqueWarning(
+ "failed to get SHT_LLVM_BB_ADDR_MAP section(s): " +
+ toString(SecRelocMapOrErr.takeError()));
+ return;
+ }
+ for (auto const &[Sec, RelocSec] : *SecRelocMapOrErr) {
std::optional<const Elf_Shdr *> FunctionSec;
if (IsRelocatable)
FunctionSec =
- unwrapOrError(this->FileName, this->Obj.getSection(Sec.sh_link));
+ unwrapOrError(this->FileName, this->Obj.getSection(Sec->sh_link));
ListScope L(W, "BBAddrMap");
+ if (IsRelocatable && !RelocSec) {
+ this->reportUniqueWarning("unable to get relocation section for " +
+ this->describe(*Sec));
+ continue;
+ }
Expected<std::vector<BBAddrMap>> BBAddrMapOrErr =
- this->Obj.decodeBBAddrMap(Sec);
+ this->Obj.decodeBBAddrMap(*Sec, RelocSec);
if (!BBAddrMapOrErr) {
- this->reportUniqueWarning("unable to dump " + this->describe(Sec) + ": " +
- toString(BBAddrMapOrErr.takeError()));
+ this->reportUniqueWarning("unable to dump " + this->describe(*Sec) +
+ ": " + toString(BBAddrMapOrErr.takeError()));
continue;
}
for (const BBAddrMap &AM : *BBAddrMapOrErr) {
@@ -7135,7 +7456,7 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printBBAddrMaps() {
if (FuncSymIndex.empty())
this->reportUniqueWarning(
"could not identify function symbol for address (0x" +
- Twine::utohexstr(AM.Addr) + ") in " + this->describe(Sec));
+ Twine::utohexstr(AM.Addr) + ") in " + this->describe(*Sec));
else
FuncName = this->getStaticSymbolName(FuncSymIndex.front());
W.printString("Name", FuncName);
@@ -7146,10 +7467,11 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printBBAddrMaps() {
W.printNumber("ID", BBE.ID);
W.printHex("Offset", BBE.Offset);
W.printHex("Size", BBE.Size);
- W.printBoolean("HasReturn", BBE.HasReturn);
- W.printBoolean("HasTailCall", BBE.HasTailCall);
- W.printBoolean("IsEHPad", BBE.IsEHPad);
- W.printBoolean("CanFallThrough", BBE.CanFallThrough);
+ W.printBoolean("HasReturn", BBE.hasReturn());
+ W.printBoolean("HasTailCall", BBE.hasTailCall());
+ W.printBoolean("IsEHPad", BBE.isEHPad());
+ W.printBoolean("CanFallThrough", BBE.canFallThrough());
+ W.printBoolean("HasIndirectBranch", BBE.MD.HasIndirectBranch);
}
}
}
@@ -7216,6 +7538,35 @@ static bool printAndroidNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
return true;
}
+template <class ELFT>
+void LLVMELFDumper<ELFT>::printMemtag(
+ const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
+ const ArrayRef<uint8_t> AndroidNoteDesc,
+ const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) {
+ {
+ ListScope L(W, "Memtag Dynamic Entries:");
+ if (DynamicEntries.empty())
+ W.printString("< none found >");
+ for (const auto &DynamicEntryKV : DynamicEntries)
+ W.printString(DynamicEntryKV.first, DynamicEntryKV.second);
+ }
+
+ if (!AndroidNoteDesc.empty()) {
+ ListScope L(W, "Memtag Android Note:");
+ printAndroidNoteLLVMStyle(ELF::NT_ANDROID_TYPE_MEMTAG, AndroidNoteDesc, W);
+ }
+
+ if (Descriptors.empty())
+ return;
+
+ {
+ ListScope L(W, "Memtag Global Descriptors:");
+ for (const auto &[Addr, BytesToTag] : Descriptors) {
+ W.printHex("0x" + utohexstr(Addr), BytesToTag);
+ }
+ }
+}
+
template <typename ELFT>
static bool printLLVMOMPOFFLOADNoteLLVMStyle(uint32_t NoteType,
ArrayRef<uint8_t> Desc,
@@ -7251,9 +7602,11 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
ListScope L(W, "Notes");
std::unique_ptr<DictScope> NoteScope;
+ size_t Align = 0;
auto StartNotes = [&](std::optional<StringRef> SecName,
const typename ELFT::Off Offset,
- const typename ELFT::Addr Size) {
+ const typename ELFT::Addr Size, size_t Al) {
+ Align = std::max<size_t>(Al, 4);
NoteScope = std::make_unique<DictScope>(W, "NoteSection");
W.printString("Name", SecName ? *SecName : "<?>");
W.printHex("Offset", Offset);
@@ -7265,7 +7618,7 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error {
DictScope D2(W, "Note");
StringRef Name = Note.getName();
- ArrayRef<uint8_t> Descriptor = Note.getDesc();
+ ArrayRef<uint8_t> Descriptor = Note.getDesc(Align);
Elf_Word Type = Note.getType();
// Print the note owner/type.
@@ -7328,7 +7681,8 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
return Error::success();
};
- printNotesHelper(*this, StartNotes, ProcessNote, EndNotes);
+ processNotesHelper(*this, /*StartNotesFn=*/StartNotes,
+ /*ProcessNoteFn=*/ProcessNote, /*FinishNotesFn=*/EndNotes);
}
template <class ELFT> void LLVMELFDumper<ELFT>::printELFLinkerOptions() {
@@ -7554,3 +7908,45 @@ void JSONELFDumper<ELFT>::printFileSummary(StringRef FileStr, ObjectFile &Obj,
std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress())));
this->printLoadName();
}
+
+template <class ELFT>
+void JSONELFDumper<ELFT>::printZeroSymbolOtherField(
+ const Elf_Sym &Symbol) const {
+ // We want the JSON format to be uniform, since it is machine readable, so
+ // always print the `Other` field the same way.
+ this->printSymbolOtherField(Symbol);
+}
+
+template <class ELFT>
+void JSONELFDumper<ELFT>::printDefaultRelRelaReloc(const Relocation<ELFT> &R,
+ StringRef SymbolName,
+ StringRef RelocName) {
+ this->printExpandedRelRelaReloc(R, SymbolName, RelocName);
+}
+
+template <class ELFT>
+void JSONELFDumper<ELFT>::printRelocationSectionInfo(const Elf_Shdr &Sec,
+ StringRef Name,
+ const unsigned SecNdx) {
+ DictScope Group(this->W);
+ this->W.printNumber("SectionIndex", SecNdx);
+ ListScope D(this->W, "Relocs");
+ this->printRelocationsHelper(Sec);
+}
+
+template <class ELFT>
+std::string JSONELFDumper<ELFT>::getGroupSectionHeaderName() const {
+ return "GroupSections";
+}
+
+template <class ELFT>
+void JSONELFDumper<ELFT>::printSectionGroupMembers(StringRef Name,
+ uint64_t Idx) const {
+ DictScope Grp(this->W);
+ this->W.printString("Name", Name);
+ this->W.printNumber("Index", Idx);
+}
+
+template <class ELFT> void JSONELFDumper<ELFT>::printEmptyGroupMessage() const {
+ // JSON output does not need to print anything for empty groups
+}
diff --git a/contrib/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h b/contrib/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h
index 258d87240984..921792f886d0 100644
--- a/contrib/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/contrib/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h
@@ -136,6 +136,7 @@ public:
virtual void printStackSizes() {}
virtual void printSectionDetails() {}
virtual void printArchSpecificInfo() {}
+ virtual void printMemtag() {}
// Only implemented for PE/COFF.
virtual void printCOFFImports() { }
diff --git a/contrib/llvm-project/llvm/tools/llvm-readobj/Opts.td b/contrib/llvm-project/llvm/tools/llvm-readobj/Opts.td
index 4f7b12f95a60..fec0adb5e6a6 100644
--- a/contrib/llvm-project/llvm/tools/llvm-readobj/Opts.td
+++ b/contrib/llvm-project/llvm/tools/llvm-readobj/Opts.td
@@ -55,6 +55,7 @@ def section_groups : FF<"section-groups", "Display section groups">, Group<grp_e
def gnu_hash_table : FF<"gnu-hash-table", "Display the GNU hash table for dynamic symbols">, Group<grp_elf>;
def hash_symbols : FF<"hash-symbols", "Display the dynamic symbols derived from the hash section">, Group<grp_elf>;
def hash_table : FF<"hash-table", "Display .hash section">, Group<grp_elf>;
+def memtag : FF<"memtag", "Display memory tagging metadata (modes, Android notes, global descriptors)">, Group<grp_elf>;
def needed_libs : FF<"needed-libs", "Display the needed libraries">, Group<grp_elf>;
def notes : FF<"notes", "Display notes">, Group<grp_elf>;
def program_headers : FF<"program-headers", "Display program headers">, Group<grp_elf>;
diff --git a/contrib/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/contrib/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp
index 56f672b3c5aa..74ebcc4ec7d8 100644
--- a/contrib/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp
@@ -98,10 +98,11 @@ void XCOFFDumper::printFileHeaders() {
// tests will let us know.
time_t TimeDate = TimeStamp;
- char FormattedTime[21] = {};
- size_t BytesWritten =
- strftime(FormattedTime, 21, "%Y-%m-%dT%H:%M:%SZ", gmtime(&TimeDate));
- if (BytesWritten)
+ char FormattedTime[80] = {};
+
+ size_t BytesFormatted =
+ strftime(FormattedTime, sizeof(FormattedTime), "%F %T", gmtime(&TimeDate));
+ if (BytesFormatted)
W.printHex("TimeStamp", FormattedTime, TimeStamp);
else
W.printHex("Timestamp", TimeStamp);
@@ -709,7 +710,7 @@ static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {
const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = {
#define ECase(X) \
{ #X, XCOFF::X }
- ECase(TB_C), ECase(TB_CPLUSPLUS)
+ ECase(TB_C), ECase(TB_Fortran), ECase(TB_CPLUSPLUS)
#undef ECase
};
diff --git a/contrib/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp b/contrib/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp
index a11de35fcd76..d72eec04d06a 100644
--- a/contrib/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -43,6 +43,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LLVMDriver.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/WithColor.h"
@@ -135,6 +136,7 @@ static bool GnuHashTable;
static bool HashSymbols;
static bool HashTable;
static bool HashHistogram;
+static bool Memtag;
static bool NeededLibraries;
static bool Notes;
static bool ProgramHeaders;
@@ -265,6 +267,7 @@ static void parseOptions(const opt::InputArgList &Args) {
opts::HashSymbols = Args.hasArg(OPT_hash_symbols);
opts::HashTable = Args.hasArg(OPT_hash_table);
opts::HashHistogram = Args.hasArg(OPT_histogram);
+ opts::Memtag = Args.hasArg(OPT_memtag);
opts::NeededLibraries = Args.hasArg(OPT_needed_libs);
opts::Notes = Args.hasArg(OPT_notes);
opts::PrettyPrint = Args.hasArg(OPT_pretty_print);
@@ -472,6 +475,8 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
Dumper->printAddrsig();
if (opts::Notes)
Dumper->printNotes();
+ if (opts::Memtag)
+ Dumper->printMemtag();
}
if (Obj.isCOFF()) {
if (opts::COFFImports)
@@ -632,7 +637,7 @@ std::unique_ptr<ScopedPrinter> createWriter() {
return std::make_unique<ScopedPrinter>(fouts());
}
-int llvm_readobj_main(int argc, char **argv) {
+int llvm_readobj_main(int argc, char **argv, const llvm::ToolContext &) {
InitLLVM X(argc, argv);
BumpPtrAllocator A;
StringSaver Saver(A);
@@ -683,6 +688,7 @@ int llvm_readobj_main(int argc, char **argv) {
opts::Addrsig = true;
opts::PrintStackSizes = true;
}
+ opts::Memtag = true;
}
if (opts::Headers) {
diff --git a/contrib/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtil.cpp b/contrib/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtil.cpp
index 0412eae954ac..14af5d2842cf 100644
--- a/contrib/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtil.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtil.cpp
@@ -38,6 +38,10 @@ static cl::SubCommand
static cl::SubCommand InstructionCount(
"instruction-count",
"Function instruction count information (requires asm-printer remarks)");
+static cl::SubCommand
+ AnnotationCount("annotation-count",
+ "Collect count information from annotation remarks (uses "
+ "AnnotationRemarksPass)");
} // namespace subopts
// Keep input + output help + names consistent across the various modes via a
@@ -49,6 +53,23 @@ static cl::SubCommand InstructionCount(
static cl::opt<std::string> OutputFileName( \
"o", cl::init("-"), cl::cat(RemarkUtilCategory), cl::desc("Output"), \
cl::value_desc("filename"), cl::sub(SUBOPT));
+
+// Keep Input format and names consistent accross the modes via a macro.
+#define INPUT_FORMAT_COMMAND_LINE_OPTIONS(SUBOPT) \
+ static cl::opt<Format> InputFormat( \
+ "parser", cl::desc("Input remark format to parse"), \
+ cl::values(clEnumValN(Format::YAML, "yaml", "YAML"), \
+ clEnumValN(Format::Bitstream, "bitstream", "Bitstream")), \
+ cl::sub(SUBOPT));
+
+#define DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(SUBOPT) \
+ static cl::opt<bool> UseDebugLoc( \
+ "use-debug-loc", \
+ cl::desc( \
+ "Add debug loc information when generating tables for " \
+ "functions. The loc is represented as (path:line number:column " \
+ "number)"), \
+ cl::init(false), cl::sub(SUBOPT));
namespace yaml2bitstream {
/// Remark format to parse.
static constexpr Format InputFormat = Format::YAML;
@@ -66,14 +87,20 @@ INPUT_OUTPUT_COMMAND_LINE_OPTIONS(subopts::Bitstream2YAML)
} // namespace bitstream2yaml
namespace instructioncount {
-static cl::opt<Format> InputFormat(
- "parser", cl::desc("Input remark format to parse"),
- cl::values(clEnumValN(Format::YAML, "yaml", "YAML"),
- clEnumValN(Format::Bitstream, "bitstream", "Bitstream")),
- cl::sub(subopts::InstructionCount));
+INPUT_FORMAT_COMMAND_LINE_OPTIONS(subopts::InstructionCount)
INPUT_OUTPUT_COMMAND_LINE_OPTIONS(subopts::InstructionCount)
+DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(subopts::InstructionCount)
} // namespace instructioncount
+namespace annotationcount {
+INPUT_FORMAT_COMMAND_LINE_OPTIONS(subopts::AnnotationCount)
+static cl::opt<std::string> AnnotationTypeToCollect(
+ "annotation-type", cl::desc("annotation-type remark to collect count for"),
+ cl::sub(subopts::AnnotationCount));
+INPUT_OUTPUT_COMMAND_LINE_OPTIONS(subopts::AnnotationCount)
+DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(subopts::AnnotationCount)
+} // namespace annotationcount
+
/// \returns A MemoryBuffer for the input file on success, and an Error
/// otherwise.
static Expected<std::unique_ptr<MemoryBuffer>>
@@ -115,6 +142,10 @@ getOutputFileForRemarks(StringRef OutputFileName, Format OutputFormat) {
: sys::fs::OF_None);
}
+static bool shouldSkipRemark(bool UseDebugLoc, Remark &Remark) {
+ return UseDebugLoc && !Remark.Loc.has_value();
+}
+
namespace yaml2bitstream {
/// Parses all remarks in the input YAML file.
/// \p [out] ParsedRemarks - Filled with remarks parsed from the input file.
@@ -229,6 +260,8 @@ static Error tryInstructionCount() {
if (!MaybeParser)
return MaybeParser.takeError();
// Emit CSV header.
+ if (UseDebugLoc)
+ OF->os() << "Source,";
OF->os() << "Function,InstructionCount\n";
// Parse all remarks. Whenever we see an instruction count remark, output
// the file name and the number of instructions.
@@ -238,11 +271,19 @@ static Error tryInstructionCount() {
auto &Remark = **MaybeRemark;
if (Remark.RemarkName != "InstructionCount")
continue;
+ if (shouldSkipRemark(UseDebugLoc, Remark))
+ continue;
auto *InstrCountArg = find_if(Remark.Args, [](const Argument &Arg) {
return Arg.Key == "NumInstructions";
});
assert(InstrCountArg != Remark.Args.end() &&
"Expected instruction count remarks to have a NumInstructions key?");
+ if (UseDebugLoc) {
+ std::string Loc = Remark.Loc->SourceFilePath.str() + ":" +
+ std::to_string(Remark.Loc->SourceLine) + +":" +
+ std::to_string(Remark.Loc->SourceColumn);
+ OF->os() << Loc << ",";
+ }
OF->os() << Remark.FunctionName << "," << InstrCountArg->Val << "\n";
}
auto E = MaybeRemark.takeError();
@@ -254,6 +295,61 @@ static Error tryInstructionCount() {
}
} // namespace instructioncount
+namespace annotationcount {
+static Error tryAnnotationCount() {
+ // Create the output buffer.
+ auto MaybeOF = getOutputFileWithFlags(OutputFileName,
+ /*Flags = */ sys::fs::OF_TextWithCRLF);
+ if (!MaybeOF)
+ return MaybeOF.takeError();
+ auto OF = std::move(*MaybeOF);
+ // Create a parser for the user-specified input format.
+ auto MaybeBuf = getInputMemoryBuffer(InputFileName);
+ if (!MaybeBuf)
+ return MaybeBuf.takeError();
+ auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());
+ if (!MaybeParser)
+ return MaybeParser.takeError();
+ // Emit CSV header.
+ if (UseDebugLoc)
+ OF->os() << "Source,";
+ OF->os() << "Function,Count\n";
+ // Parse all remarks. When we see the specified remark collect the count
+ // information.
+ auto &Parser = **MaybeParser;
+ auto MaybeRemark = Parser.next();
+ for (; MaybeRemark; MaybeRemark = Parser.next()) {
+ auto &Remark = **MaybeRemark;
+ if (Remark.RemarkName != "AnnotationSummary")
+ continue;
+ if (shouldSkipRemark(UseDebugLoc, Remark))
+ continue;
+ auto *RemarkNameArg = find_if(Remark.Args, [](const Argument &Arg) {
+ return Arg.Key == "type" && Arg.Val == AnnotationTypeToCollect;
+ });
+ if (RemarkNameArg == Remark.Args.end())
+ continue;
+ auto *CountArg = find_if(
+ Remark.Args, [](const Argument &Arg) { return Arg.Key == "count"; });
+ assert(CountArg != Remark.Args.end() &&
+ "Expected annotation-type remark to have a count key?");
+ if (UseDebugLoc) {
+ std::string Loc = Remark.Loc->SourceFilePath.str() + ":" +
+ std::to_string(Remark.Loc->SourceLine) + +":" +
+ std::to_string(Remark.Loc->SourceColumn);
+ OF->os() << Loc << ",";
+ }
+ OF->os() << Remark.FunctionName << "," << CountArg->Val << "\n";
+ }
+ auto E = MaybeRemark.takeError();
+ if (!E.isA<EndOfFileError>())
+ return E;
+ consumeError(std::move(E));
+ OF->keep();
+ return Error::success();
+}
+
+} // namespace annotationcount
/// Handle user-specified suboptions (e.g. yaml2bitstream, bitstream2yaml).
/// \returns An Error if the specified suboption fails or if no suboption was
/// specified. Otherwise, Error::success().
@@ -264,6 +360,9 @@ static Error handleSuboptions() {
return yaml2bitstream::tryYAML2Bitstream();
if (subopts::InstructionCount)
return instructioncount::tryInstructionCount();
+ if (subopts::AnnotationCount)
+ return annotationcount::tryAnnotationCount();
+
return make_error<StringError>(
"Please specify a subcommand. (See -help for options)",
inconvertibleErrorCode());
diff --git a/contrib/llvm-project/llvm/tools/llvm-size/llvm-size.cpp b/contrib/llvm-project/llvm/tools/llvm-size/llvm-size.cpp
index 32dbf3d489c0..048a98b9af7d 100644
--- a/contrib/llvm-project/llvm/tools/llvm-size/llvm-size.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-size/llvm-size.cpp
@@ -26,6 +26,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LLVMDriver.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
@@ -869,7 +870,7 @@ static void printBerkeleyTotals() {
<< "(TOTALS)\n";
}
-int llvm_size_main(int argc, char **argv) {
+int llvm_size_main(int argc, char **argv, const llvm::ToolContext &) {
InitLLVM X(argc, argv);
BumpPtrAllocator A;
StringSaver Saver(A);
diff --git a/contrib/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp b/contrib/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp
index 639506c7d488..d1cf1607b94b 100644
--- a/contrib/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp
@@ -222,7 +222,7 @@ protected:
} else if (Tp->isFloatingPointTy()) {
if (getRandom() & 1)
return ConstantFP::getAllOnesValue(Tp);
- return ConstantFP::getNullValue(Tp);
+ return ConstantFP::getZero(Tp);
}
return UndefValue::get(Tp);
}
@@ -244,7 +244,7 @@ protected:
} else if (Tp->isFloatingPointTy()) {
if (getRandom() & 1)
return ConstantFP::getAllOnesValue(Tp);
- return ConstantFP::getNullValue(Tp);
+ return ConstantFP::getZero(Tp);
} else if (auto *VTp = dyn_cast<FixedVectorType>(Tp)) {
std::vector<Constant*> TempValues;
TempValues.reserve(VTp->getNumElements());
@@ -341,9 +341,7 @@ struct LoadModifier: public Modifier {
void Act() override {
// Try to use predefined pointers. If non-exist, use undef pointer value;
Value *Ptr = getRandomPointerValue();
- Type *Ty = Ptr->getType()->isOpaquePointerTy()
- ? pickType()
- : Ptr->getType()->getNonOpaquePointerElementType();
+ Type *Ty = pickType();
Value *V = new LoadInst(Ty, Ptr, "L", BB->getTerminator());
PT->push_back(V);
}
@@ -356,9 +354,7 @@ struct StoreModifier: public Modifier {
void Act() override {
// Try to use predefined pointers. If non-exist, use undef pointer value;
Value *Ptr = getRandomPointerValue();
- Type *ValTy = Ptr->getType()->isOpaquePointerTy()
- ? pickType()
- : Ptr->getType()->getNonOpaquePointerElementType();
+ Type *ValTy = pickType();
// Do not store vectors of i1s because they are unsupported
// by the codegen.
@@ -442,7 +438,7 @@ struct ConstModifier: public Modifier {
APFloat RandomFloat(Ty->getFltSemantics(), RandomInt);
if (getRandom() & 1)
- return PT->push_back(ConstantFP::getNullValue(Ty));
+ return PT->push_back(ConstantFP::getZero(Ty));
return PT->push_back(ConstantFP::get(Ty->getContext(), RandomFloat));
}
diff --git a/contrib/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp b/contrib/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp
index f6d08a1988b7..d9bc34ee621a 100644
--- a/contrib/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Opts.inc"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Object/Binary.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
@@ -62,6 +63,7 @@ class StringsOptTable : public opt::GenericOptTable {
public:
StringsOptTable() : GenericOptTable(InfoTable) {
setGroupedShortOptions(true);
+ setDashDashParsing(true);
}
};
} // namespace
diff --git a/contrib/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/contrib/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
index ed24e8550291..3e342a4db9ce 100644
--- a/contrib/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -36,6 +36,7 @@
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstdio>
@@ -83,6 +84,16 @@ public:
};
} // namespace
+static std::string ToolName;
+
+static void printError(const ErrorInfoBase &EI, StringRef Path) {
+ WithColor::error(errs(), ToolName);
+ if (!EI.isA<FileError>())
+ errs() << "'" << Path << "': ";
+ EI.log(errs());
+ errs() << '\n';
+}
+
template <typename T>
static void print(const Request &Request, Expected<T> &ResOrErr,
DIPrinter &Printer) {
@@ -96,8 +107,7 @@ static void print(const Request &Request, Expected<T> &ResOrErr,
bool PrintEmpty = true;
handleAllErrors(std::move(ResOrErr.takeError()),
[&](const ErrorInfoBase &EI) {
- PrintEmpty = Printer.printError(
- Request, EI, "LLVMSymbolizer: error reading file: ");
+ PrintEmpty = Printer.printError(Request, EI);
});
if (PrintEmpty)
@@ -125,15 +135,6 @@ static void enableDebuginfod(LLVMSymbolizer &Symbolizer,
HTTPClient::initialize();
}
-static object::BuildID parseBuildID(StringRef Str) {
- std::string Bytes;
- if (!tryGetFromHex(Str, Bytes))
- return {};
- ArrayRef<uint8_t> BuildID(reinterpret_cast<const uint8_t *>(Bytes.data()),
- Bytes.size());
- return object::BuildID(BuildID.begin(), BuildID.end());
-}
-
static bool parseCommand(StringRef BinaryName, bool IsAddr2Line,
StringRef InputString, Command &Cmd,
std::string &ModuleName, object::BuildID &BuildID,
@@ -218,17 +219,18 @@ void executeCommand(StringRef ModuleName, const T &ModuleSpec, Command Cmd,
uint64_t AdjustedOffset = Offset - AdjustVMA;
object::SectionedAddress Address = {AdjustedOffset,
object::SectionedAddress::UndefSection};
+ Request SymRequest = {ModuleName, Offset};
if (Cmd == Command::Data) {
Expected<DIGlobal> ResOrErr = Symbolizer.symbolizeData(ModuleSpec, Address);
- print({ModuleName, Offset}, ResOrErr, Printer);
+ print(SymRequest, ResOrErr, Printer);
} else if (Cmd == Command::Frame) {
Expected<std::vector<DILocal>> ResOrErr =
Symbolizer.symbolizeFrame(ModuleSpec, Address);
- print({ModuleName, Offset}, ResOrErr, Printer);
+ print(SymRequest, ResOrErr, Printer);
} else if (ShouldInline) {
Expected<DIInliningInfo> ResOrErr =
Symbolizer.symbolizeInlinedCode(ModuleSpec, Address);
- print({ModuleName, Offset}, ResOrErr, Printer);
+ print(SymRequest, ResOrErr, Printer);
} else if (Style == OutputStyle::GNU) {
// With PrintFunctions == FunctionNameKind::LinkageName (default)
// and UseSymbolTable == true (also default), Symbolizer.symbolizeCode()
@@ -243,11 +245,11 @@ void executeCommand(StringRef ModuleName, const T &ModuleSpec, Command Cmd,
? Expected<DILineInfo>(ResOrErr.takeError())
: ((ResOrErr->getNumberOfFrames() == 0) ? DILineInfo()
: ResOrErr->getFrame(0));
- print({ModuleName, Offset}, Res0OrErr, Printer);
+ print(SymRequest, Res0OrErr, Printer);
} else {
Expected<DILineInfo> ResOrErr =
Symbolizer.symbolizeCode(ModuleSpec, Address);
- print({ModuleName, Offset}, ResOrErr, Printer);
+ print(SymRequest, ResOrErr, Printer);
}
Symbolizer.pruneCache();
}
@@ -386,7 +388,8 @@ int main(int argc, char **argv) {
InitLLVM X(argc, argv);
sys::InitializeCOMRAII COM(sys::COMThreadingMode::MultiThreaded);
- bool IsAddr2Line = sys::path::stem(argv[0]).contains("addr2line");
+ ToolName = argv[0];
+ bool IsAddr2Line = sys::path::stem(ToolName).contains("addr2line");
BumpPtrAllocator A;
StringSaver Saver(A);
SymbolizerOptTable Tbl;
@@ -469,11 +472,25 @@ int main(int argc, char **argv) {
std::unique_ptr<DIPrinter> Printer;
if (Style == OutputStyle::GNU)
- Printer = std::make_unique<GNUPrinter>(outs(), errs(), Config);
+ Printer = std::make_unique<GNUPrinter>(outs(), printError, Config);
else if (Style == OutputStyle::JSON)
Printer = std::make_unique<JSONPrinter>(outs(), Config);
else
- Printer = std::make_unique<LLVMPrinter>(outs(), errs(), Config);
+ Printer = std::make_unique<LLVMPrinter>(outs(), printError, Config);
+
+ // When an input file is specified, exit immediately if the file cannot be
+ // read. If getOrCreateModuleInfo succeeds, symbolizeInput will reuse the
+ // cached file handle.
+ if (auto *Arg = Args.getLastArg(OPT_obj_EQ); Arg) {
+ auto Status = Symbolizer.getOrCreateModuleInfo(Arg->getValue());
+ if (!Status) {
+ Request SymRequest = {Arg->getValue(), 0};
+ handleAllErrors(Status.takeError(), [&](const ErrorInfoBase &EI) {
+ Printer->printError(SymRequest, EI);
+ });
+ return EXIT_FAILURE;
+ }
+ }
std::vector<std::string> InputAddresses = Args.getAllArgValues(OPT_INPUT);
if (InputAddresses.empty()) {
diff --git a/contrib/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp b/contrib/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp
index 9ebaadbeec26..3e07bb94f4df 100644
--- a/contrib/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp
@@ -11,11 +11,13 @@
//
//===----------------------------------------------------------------------===/
#include "DiffEngine.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TextAPI/InterfaceFile.h"
#include "llvm/TextAPI/Symbol.h"
#include "llvm/TextAPI/Target.h"
+#include <iterator>
using namespace llvm;
using namespace MachO;
@@ -74,43 +76,49 @@ StringLiteral SymScalar::getSymbolNamePrefix(MachO::SymbolKind Kind) {
llvm_unreachable("Unknown llvm::MachO::SymbolKind enum");
}
-std::string SymScalar::stringifySymbolFlag(MachO::SymbolFlags Flag) {
- switch (Flag) {
- case MachO::SymbolFlags::None:
- return "";
- case MachO::SymbolFlags::ThreadLocalValue:
- return "Thread-Local";
- case MachO::SymbolFlags::WeakDefined:
- return "Weak-Defined";
- case MachO::SymbolFlags::WeakReferenced:
- return "Weak-Referenced";
- case MachO::SymbolFlags::Undefined:
- return "Undefined";
- case MachO::SymbolFlags::Rexported:
- return "Reexported";
- }
- llvm_unreachable("Unknown llvm::MachO::SymbolFlags enum");
+std::string SymScalar::getFlagString(const MachO::Symbol *Sym) {
+ if (Sym->getFlags() == SymbolFlags::None)
+ return {};
+ SmallString<64> Flags(" - ");
+ if (Sym->isThreadLocalValue())
+ Flags.append("Thread-Local ");
+ if (Sym->isWeakDefined())
+ Flags.append("Weak-Defined ");
+ if (Sym->isWeakReferenced())
+ Flags.append("Weak-Referenced ");
+ if (Sym->isUndefined())
+ Flags.append("Undefined ");
+ if (Sym->isReexported())
+ Flags.append("Reexported ");
+ if (Sym->isData())
+ Flags.append("Data ");
+ if (Sym->isText())
+ Flags.append("Text ");
+
+ return std::string(Flags);
}
void SymScalar::print(raw_ostream &OS, std::string Indent, MachO::Target Targ) {
if (Val->getKind() == MachO::SymbolKind::ObjectiveCClass) {
if (Targ.Arch == MachO::AK_i386 && Targ.Platform == MachO::PLATFORM_MACOS) {
OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ")
- << ObjC1ClassNamePrefix << Val->getName()
- << getFlagString(Val->getFlags()) << "\n";
+ << ObjC1ClassNamePrefix << Val->getName() << getFlagString(Val)
+ << "\n";
return;
}
OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ")
- << ObjC2ClassNamePrefix << Val->getName()
- << getFlagString(Val->getFlags()) << "\n";
+ << ObjC2ClassNamePrefix << Val->getName() << getFlagString(Val) << "\n";
}
OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ")
<< getSymbolNamePrefix(Val->getKind()) << Val->getName()
- << getFlagString(Val->getFlags()) << "\n";
+ << getFlagString(Val) << "\n";
}
bool checkSymbolEquality(llvm::MachO::InterfaceFile::const_symbol_range LHS,
llvm::MachO::InterfaceFile::const_symbol_range RHS) {
+ if (std::distance(LHS.begin(), LHS.end()) !=
+ std::distance(RHS.begin(), RHS.end()))
+ return false;
return std::equal(LHS.begin(), LHS.end(), RHS.begin(),
[&](auto LHS, auto RHS) { return *LHS == *RHS; });
}
@@ -204,9 +212,6 @@ std::vector<DiffOutput> getSingleIF(InterfaceFile *Interface,
diffAttribute("Swift ABI Version", Output,
DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>(
Order, Interface->getSwiftABIVersion()));
- diffAttribute("InstallAPI", Output,
- DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
- Order, Interface->isInstallAPI()));
diffAttribute("Two Level Namespace", Output,
DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
Order, Interface->isTwoLevelNamespace()));
@@ -341,11 +346,6 @@ DiffEngine::findDifferences(const InterfaceFile *IFLHS,
DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>(
rhs, IFRHS->getSwiftABIVersion()),
"Swift ABI Version"));
- if (IFLHS->isInstallAPI() != IFRHS->isInstallAPI())
- Output.push_back(recordDifferences(
- DiffScalarVal<bool, AD_Diff_Scalar_Bool>(lhs, IFLHS->isInstallAPI()),
- DiffScalarVal<bool, AD_Diff_Scalar_Bool>(rhs, IFRHS->isInstallAPI()),
- "InstallAPI"));
if (IFLHS->isTwoLevelNamespace() != IFRHS->isTwoLevelNamespace())
Output.push_back(recordDifferences(DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
diff --git a/contrib/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h b/contrib/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h
index e4864054fa11..27b72573d011 100644
--- a/contrib/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h
+++ b/contrib/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h
@@ -83,11 +83,7 @@ public:
SymScalar(InterfaceInputOrder Order, const MachO::Symbol *Sym)
: Order(Order), Val(Sym){};
- std::string getFlagString(MachO::SymbolFlags Flags) {
- return Flags != MachO::SymbolFlags::None
- ? " - " + stringifySymbolFlag(Flags)
- : stringifySymbolFlag(Flags);
- }
+ std::string getFlagString(const MachO::Symbol *Sym);
void print(raw_ostream &OS, std::string Indent, MachO::Target Targ);
@@ -99,7 +95,6 @@ private:
InterfaceInputOrder Order;
const MachO::Symbol *Val;
StringLiteral getSymbolNamePrefix(MachO::SymbolKind Kind);
- std::string stringifySymbolFlag(MachO::SymbolFlags Flag);
};
class DiffStrVec : public AttributeDiff {
diff --git a/contrib/llvm-project/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp b/contrib/llvm-project/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
index 179c42b60605..9cc18f80910d 100644
--- a/contrib/llvm-project/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
@@ -8,7 +8,6 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Demangle/Demangle.h"
@@ -20,6 +19,7 @@
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/WithColor.h"
+#include "llvm/TargetParser/Triple.h"
using namespace llvm;
using namespace llvm::object;
@@ -107,7 +107,7 @@ static std::string getPrintableName(StringRef Name) {
std::string OutputName = "'";
OutputName += Name;
OutputName += "'";
- std::string DemangledName(demangle(Name.str()));
+ std::string DemangledName(demangle(Name));
if (Name != DemangledName) {
OutputName += " aka ";
OutputName += DemangledName;
diff --git a/contrib/llvm-project/llvm/tools/llvm-xray/xray-account.cpp b/contrib/llvm-project/llvm/tools/llvm-xray/xray-account.cpp
index a9d91297b4e1..24a3552cfb91 100644
--- a/contrib/llvm-project/llvm/tools/llvm-xray/xray-account.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-xray/xray-account.cpp
@@ -80,7 +80,7 @@ static cl::opt<SortField> AccountSortOutput(
"sort", cl::desc("sort output by this field"), cl::value_desc("field"),
cl::sub(Account), cl::init(SortField::FUNCID),
cl::values(clEnumValN(SortField::FUNCID, "funcid", "function id"),
- clEnumValN(SortField::COUNT, "count", "funciton call counts"),
+ clEnumValN(SortField::COUNT, "count", "function call counts"),
clEnumValN(SortField::MIN, "min", "minimum function durations"),
clEnumValN(SortField::MED, "med", "median function durations"),
clEnumValN(SortField::PCT90, "90p", "90th percentile durations"),
diff --git a/contrib/llvm-project/llvm/tools/llvm-xray/xray-graph.cpp b/contrib/llvm-project/llvm/tools/llvm-xray/xray-graph.cpp
index b8328052f473..de67993d7590 100644
--- a/contrib/llvm-project/llvm/tools/llvm-xray/xray-graph.cpp
+++ b/contrib/llvm-project/llvm/tools/llvm-xray/xray-graph.cpp
@@ -200,7 +200,7 @@ static std::string escapeString(StringRef Label) {
// example caused by tail call elimination and if the option is enabled then
// then tries to recover from this.
//
-// This funciton will also error if the records are out of order, as the trace
+// This function will also error if the records are out of order, as the trace
// is expected to be sorted.
//
// The graph generated has an immaginary root for functions called by no-one at
diff --git a/contrib/llvm-project/llvm/tools/opt/AnalysisWrappers.cpp b/contrib/llvm-project/llvm/tools/opt/AnalysisWrappers.cpp
deleted file mode 100644
index 2ae1da84a9a0..000000000000
--- a/contrib/llvm-project/llvm/tools/opt/AnalysisWrappers.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//===- AnalysisWrappers.cpp - Wrappers around non-pass analyses -----------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines pass wrappers around LLVM analyses that don't make sense to
-// be passes. It provides a nice standard pass interface to these classes so
-// that they can be printed out by analyze.
-//
-// These classes are separated out of analyze.cpp so that it is more clear which
-// code is the integral part of the analyze tool, and which part of the code is
-// just making it so more passes are available.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Analysis/CallGraph.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-namespace {
- /// ExternalFunctionsPassedConstants - This pass prints out call sites to
- /// external functions that are called with constant arguments. This can be
- /// useful when looking for standard library functions we should constant fold
- /// or handle in alias analyses.
- struct ExternalFunctionsPassedConstants : public ModulePass {
- static char ID; // Pass ID, replacement for typeid
- ExternalFunctionsPassedConstants() : ModulePass(ID) {}
- bool runOnModule(Module &M) override {
- for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
- if (!I->isDeclaration()) continue;
-
- bool PrintedFn = false;
- for (User *U : I->users()) {
- Instruction *UI = dyn_cast<Instruction>(U);
- if (!UI) continue;
-
- CallBase *CB = dyn_cast<CallBase>(UI);
- if (!CB)
- continue;
-
- for (auto AI = CB->arg_begin(), E = CB->arg_end(); AI != E; ++AI) {
- if (!isa<Constant>(*AI)) continue;
-
- if (!PrintedFn) {
- errs() << "Function '" << I->getName() << "':\n";
- PrintedFn = true;
- }
- errs() << *UI;
- break;
- }
- }
- }
-
- return false;
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesAll();
- }
- };
-}
-
-char ExternalFunctionsPassedConstants::ID = 0;
-static RegisterPass<ExternalFunctionsPassedConstants>
- P1("print-externalfnconstants",
- "Print external fn callsites passed constants");
diff --git a/contrib/llvm-project/llvm/tools/opt/BreakpointPrinter.cpp b/contrib/llvm-project/llvm/tools/opt/BreakpointPrinter.cpp
deleted file mode 100644
index a57a8c43c264..000000000000
--- a/contrib/llvm-project/llvm/tools/opt/BreakpointPrinter.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//===- BreakpointPrinter.cpp - Breakpoint location printer ----------------===//
-//
-// 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
-/// Breakpoint location printer.
-///
-//===----------------------------------------------------------------------===//
-#include "BreakpointPrinter.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/IR/DebugInfo.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-namespace {
-
-struct BreakpointPrinter : public ModulePass {
- raw_ostream &Out;
- static char ID;
-
- BreakpointPrinter(raw_ostream &out) : ModulePass(ID), Out(out) {}
-
- void getContextName(const DIScope *Context, std::string &N) {
- if (auto *NS = dyn_cast<DINamespace>(Context)) {
- if (!NS->getName().empty()) {
- getContextName(NS->getScope(), N);
- N = N + NS->getName().str() + "::";
- }
- } else if (auto *TY = dyn_cast<DIType>(Context)) {
- if (!TY->getName().empty()) {
- getContextName(TY->getScope(), N);
- N = N + TY->getName().str() + "::";
- }
- }
- }
-
- bool runOnModule(Module &M) override {
- StringSet<> Processed;
- if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.sp"))
- for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
- std::string Name;
- auto *SP = cast_or_null<DISubprogram>(NMD->getOperand(i));
- if (!SP)
- continue;
- getContextName(SP->getScope(), Name);
- Name = Name + SP->getName().str();
- if (!Name.empty() && Processed.insert(Name).second) {
- Out << Name << "\n";
- }
- }
- return false;
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesAll();
- }
-};
-
-char BreakpointPrinter::ID = 0;
-}
-
-ModulePass *llvm::createBreakpointPrinter(raw_ostream &out) {
- return new BreakpointPrinter(out);
-}
diff --git a/contrib/llvm-project/llvm/tools/opt/BreakpointPrinter.h b/contrib/llvm-project/llvm/tools/opt/BreakpointPrinter.h
deleted file mode 100644
index 2877555f852c..000000000000
--- a/contrib/llvm-project/llvm/tools/opt/BreakpointPrinter.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//===- BreakpointPrinter.h - Breakpoint location printer ------------------===//
-//
-// 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
-/// Breakpoint location printer.
-///
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_TOOLS_OPT_BREAKPOINTPRINTER_H
-#define LLVM_TOOLS_OPT_BREAKPOINTPRINTER_H
-
-namespace llvm {
-
-class ModulePass;
-class raw_ostream;
-
-ModulePass *createBreakpointPrinter(raw_ostream &out);
-}
-
-#endif // LLVM_TOOLS_OPT_BREAKPOINTPRINTER_H
diff --git a/contrib/llvm-project/llvm/tools/opt/NewPMDriver.cpp b/contrib/llvm-project/llvm/tools/opt/NewPMDriver.cpp
index a8db0c62898e..6ae3f87099af 100644
--- a/contrib/llvm-project/llvm/tools/opt/NewPMDriver.cpp
+++ b/contrib/llvm-project/llvm/tools/opt/NewPMDriver.cpp
@@ -31,6 +31,7 @@
#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
@@ -175,6 +176,9 @@ static cl::opt<PGOKind>
"Use sampled profile to guide PGO.")));
static cl::opt<std::string> ProfileFile("profile-file",
cl::desc("Path to the profile."), cl::Hidden);
+static cl::opt<std::string>
+ MemoryProfileFile("memory-profile-file",
+ cl::desc("Path to the memory profile."), cl::Hidden);
static cl::opt<CSPGOKind> CSPGOKindFlag(
"cspgo-kind", cl::init(NoCSPGO), cl::Hidden,
@@ -320,35 +324,38 @@ static void registerEPCallbacks(PassBuilder &PB) {
llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
#include "llvm/Support/Extension.def"
-bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
- TargetLibraryInfoImpl *TLII, ToolOutputFile *Out,
- ToolOutputFile *ThinLTOLinkOut,
- ToolOutputFile *OptRemarkFile,
- StringRef PassPipeline,
- ArrayRef<PassPlugin> PassPlugins,
- OutputKind OK, VerifierKind VK,
- bool ShouldPreserveAssemblyUseListOrder,
- bool ShouldPreserveBitcodeUseListOrder,
- bool EmitSummaryIndex, bool EmitModuleHash,
- bool EnableDebugify, bool VerifyDIPreserve) {
+bool llvm::runPassPipeline(
+ StringRef Arg0, Module &M, TargetMachine *TM, TargetLibraryInfoImpl *TLII,
+ ToolOutputFile *Out, ToolOutputFile *ThinLTOLinkOut,
+ ToolOutputFile *OptRemarkFile, StringRef PassPipeline,
+ ArrayRef<PassPlugin> PassPlugins, OutputKind OK, VerifierKind VK,
+ bool ShouldPreserveAssemblyUseListOrder,
+ bool ShouldPreserveBitcodeUseListOrder, bool EmitSummaryIndex,
+ bool EmitModuleHash, bool EnableDebugify, bool VerifyDIPreserve,
+ bool UnifiedLTO) {
bool VerifyEachPass = VK == VK_VerifyEachPass;
+ auto FS = vfs::getRealFileSystem();
std::optional<PGOOptions> P;
switch (PGOKindFlag) {
case InstrGen:
- P = PGOOptions(ProfileFile, "", "", PGOOptions::IRInstr);
+ P = PGOOptions(ProfileFile, "", "", MemoryProfileFile, FS,
+ PGOOptions::IRInstr);
break;
case InstrUse:
- P = PGOOptions(ProfileFile, "", ProfileRemappingFile, PGOOptions::IRUse);
+ P = PGOOptions(ProfileFile, "", ProfileRemappingFile, MemoryProfileFile, FS,
+ PGOOptions::IRUse);
break;
case SampleUse:
- P = PGOOptions(ProfileFile, "", ProfileRemappingFile,
+ P = PGOOptions(ProfileFile, "", ProfileRemappingFile, MemoryProfileFile, FS,
PGOOptions::SampleUse);
break;
case NoPGO:
- if (DebugInfoForProfiling || PseudoProbeForProfiling)
- P = PGOOptions("", "", "", PGOOptions::NoAction, PGOOptions::NoCSAction,
- DebugInfoForProfiling, PseudoProbeForProfiling);
+ if (DebugInfoForProfiling || PseudoProbeForProfiling ||
+ !MemoryProfileFile.empty())
+ P = PGOOptions("", "", "", MemoryProfileFile, FS, PGOOptions::NoAction,
+ PGOOptions::NoCSAction, DebugInfoForProfiling,
+ PseudoProbeForProfiling);
else
P = std::nullopt;
}
@@ -368,7 +375,8 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
P->CSProfileGenFile = CSProfileGenFile;
} else
P = PGOOptions("", CSProfileGenFile, ProfileRemappingFile,
- PGOOptions::NoAction, PGOOptions::CSIRInstr);
+ /*MemoryProfile=*/"", FS, PGOOptions::NoAction,
+ PGOOptions::CSIRInstr);
} else /* CSPGOKindFlag == CSInstrUse */ {
if (!P) {
errs() << "CSInstrUse needs to be together with InstrUse";
@@ -391,20 +399,20 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
PrintPassOpts.SkipAnalyses = DebugPM == DebugLogging::Quiet;
StandardInstrumentations SI(M.getContext(), DebugPM != DebugLogging::None,
VerifyEachPass, PrintPassOpts);
- SI.registerCallbacks(PIC, &FAM);
+ SI.registerCallbacks(PIC, &MAM);
DebugifyEachInstrumentation Debugify;
DebugifyStatsMap DIStatsMap;
DebugInfoPerPass DebugInfoBeforePass;
if (DebugifyEach) {
Debugify.setDIStatsMap(DIStatsMap);
Debugify.setDebugifyMode(DebugifyMode::SyntheticDebugInfo);
- Debugify.registerCallbacks(PIC);
+ Debugify.registerCallbacks(PIC, MAM);
} else if (VerifyEachDebugInfoPreserve) {
Debugify.setDebugInfoBeforePass(DebugInfoBeforePass);
Debugify.setDebugifyMode(DebugifyMode::OriginalDebugInfo);
Debugify.setOrigDIVerifyBugsReportFilePath(
VerifyDIPreserveExport);
- Debugify.registerCallbacks(PIC);
+ Debugify.registerCallbacks(PIC, MAM);
}
PipelineTuningOptions PTO;
@@ -412,6 +420,7 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
// to false above so we shouldn't necessarily need to check whether or not the
// option has been enabled.
PTO.LoopUnrolling = !DisableLoopUnrolling;
+ PTO.UnifiedLTO = UnifiedLTO;
PassBuilder PB(TM, PTO, P, &PIC);
registerEPCallbacks(PB);
diff --git a/contrib/llvm-project/llvm/tools/opt/NewPMDriver.h b/contrib/llvm-project/llvm/tools/opt/NewPMDriver.h
index a3cdd158d40f..3230c27c2d7a 100644
--- a/contrib/llvm-project/llvm/tools/opt/NewPMDriver.h
+++ b/contrib/llvm-project/llvm/tools/opt/NewPMDriver.h
@@ -67,13 +67,13 @@ void printPasses(raw_ostream &OS);
bool runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
TargetLibraryInfoImpl *TLII, ToolOutputFile *Out,
ToolOutputFile *ThinLinkOut, ToolOutputFile *OptRemarkFile,
- StringRef PassPipeline,
- ArrayRef<PassPlugin> PassPlugins, opt_tool::OutputKind OK,
- opt_tool::VerifierKind VK,
+ StringRef PassPipeline, ArrayRef<PassPlugin> PassPlugins,
+ opt_tool::OutputKind OK, opt_tool::VerifierKind VK,
bool ShouldPreserveAssemblyUseListOrder,
bool ShouldPreserveBitcodeUseListOrder,
bool EmitSummaryIndex, bool EmitModuleHash,
- bool EnableDebugify, bool VerifyDIPreserve);
+ bool EnableDebugify, bool VerifyDIPreserve,
+ bool UnifiedLTO = false);
} // namespace llvm
#endif
diff --git a/contrib/llvm-project/llvm/tools/opt/opt.cpp b/contrib/llvm-project/llvm/tools/opt/opt.cpp
index 40632b43e73b..9c20e7784223 100644
--- a/contrib/llvm-project/llvm/tools/opt/opt.cpp
+++ b/contrib/llvm-project/llvm/tools/opt/opt.cpp
@@ -11,9 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "BreakpointPrinter.h"
#include "NewPMDriver.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/LoopPass.h"
@@ -37,13 +35,11 @@
#include "llvm/InitializePasses.h"
#include "llvm/LinkAllIR.h"
#include "llvm/LinkAllPasses.h"
-#include "llvm/MC/SubtargetFeature.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Remarks/HotnessThresholdParser.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/SourceMgr.h"
@@ -52,6 +48,9 @@
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/SubtargetFeature.h"
+#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/IPO/WholeProgramDevirt.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Debugify.h"
@@ -68,12 +67,12 @@ static codegen::RegisterCodeGenFlags CFG;
static cl::list<const PassInfo *, bool, PassNameParser> PassList(cl::desc(
"Optimizations available (use '-passes=' for the new pass manager)"));
-static cl::opt<bool> EnableNewPassManager(
- "enable-new-pm",
- cl::desc("Enable the new pass manager, translating "
- "'opt -foo' to 'opt -passes=foo'. This is strictly for the new PM "
- "migration, use '-passes=' when possible."),
- cl::init(true));
+static cl::opt<bool> EnableLegacyPassManager(
+ "bugpoint-enable-legacy-pm",
+ cl::desc(
+ "Enable the legacy pass manager. This is strictly for bugpoint "
+ "due to it not working with the new PM, please do not use otherwise."),
+ cl::init(false));
// This flag specifies a textual description of the optimization pass pipeline
// to run over the module. This flag switches opt to use the new pass manager
@@ -117,6 +116,12 @@ static cl::opt<bool>
SplitLTOUnit("thinlto-split-lto-unit",
cl::desc("Enable splitting of a ThinLTO LTOUnit"));
+static cl::opt<bool>
+ UnifiedLTO("unified-lto",
+ cl::desc("Use unified LTO piplines. Ignored unless -thinlto-bc "
+ "is also specified."),
+ cl::Hidden, cl::init(false));
+
static cl::opt<std::string> ThinLinkBitcodeFile(
"thin-link-bitcode-file", cl::value_desc("filename"),
cl::desc(
@@ -203,10 +208,6 @@ static cl::opt<bool> VerifyDebugInfoPreserve(
cl::desc("Start the pipeline with collecting and end it with checking of "
"debug info preservation."));
-static cl::opt<bool>
-PrintBreakpoints("print-breakpoints-for-testing",
- cl::desc("Print select breakpoints location for testing"));
-
static cl::opt<std::string> ClDataLayout("data-layout",
cl::desc("data layout string to use"),
cl::value_desc("layout-string"),
@@ -279,15 +280,6 @@ static cl::list<std::string>
PassPlugins("load-pass-plugin",
cl::desc("Load passes from plugin library"));
-static inline void addPass(legacy::PassManagerBase &PM, Pass *P) {
- // Add the pass to the pass manager...
- PM.add(P);
-
- // If we are verifying all of the intermediate steps, add the verifier...
- if (VerifyEach)
- PM.add(createVerifierPass());
-}
-
//===----------------------------------------------------------------------===//
// CodeGen-related helper functions.
//
@@ -368,7 +360,6 @@ static bool shouldPinPassToLegacyPM(StringRef Pass) {
"verify-safepoint-ir",
"atomic-expand",
"expandvp",
- "hardware-loops",
"mve-tail-predication",
"interleaved-access",
"global-merge",
@@ -393,7 +384,8 @@ static bool shouldPinPassToLegacyPM(StringRef Pass) {
"expand-large-div-rem",
"structurizecfg",
"fix-irreducible",
- "expand-large-fp-convert"
+ "expand-large-fp-convert",
+ "callbrprepare",
};
for (const auto &P : PassNamePrefix)
if (Pass.startswith(P))
@@ -445,9 +437,9 @@ int main(int argc, char **argv) {
initializeExpandMemCmpPassPass(Registry);
initializeScalarizeMaskedMemIntrinLegacyPassPass(Registry);
initializeSelectOptimizePass(Registry);
+ initializeCallBrPreparePass(Registry);
initializeCodeGenPreparePass(Registry);
initializeAtomicExpandPass(Registry);
- initializeRewriteSymbolsLegacyPassPass(Registry);
initializeWinEHPreparePass(Registry);
initializeDwarfEHPrepareLegacyPassPass(Registry);
initializeSafeStackLegacyPassPass(Registry);
@@ -462,7 +454,6 @@ int main(int argc, char **argv) {
initializeExpandVectorPredicationPass(Registry);
initializeWasmEHPreparePass(Registry);
initializeWriteBitcodePassPass(Registry);
- initializeHardwareLoopsPass(Registry);
initializeReplaceWithVeclibLegacyPass(Registry);
initializeJMCInstrumenterPass(Registry);
@@ -485,11 +476,8 @@ int main(int argc, char **argv) {
LLVMContext Context;
- // If `-passes=` is specified, use NPM.
- // If `-enable-new-pm` is specified and there are no codegen passes, use NPM.
- // e.g. `-enable-new-pm -sroa` will use NPM.
- // but `-enable-new-pm -codegenprepare` will still revert to legacy PM.
- const bool UseNPM = (EnableNewPassManager && !shouldForceLegacyPM()) ||
+ // TODO: remove shouldForceLegacyPM().
+ const bool UseNPM = (!EnableLegacyPassManager && !shouldForceLegacyPM()) ||
PassPipeline.getNumOccurrences() > 0;
if (UseNPM && !PassList.empty()) {
@@ -647,8 +635,11 @@ int main(int argc, char **argv) {
if (CheckBitcodeOutputToConsole(Out->os()))
NoOutput = true;
- if (OutputThinLTOBC)
+ if (OutputThinLTOBC) {
M->addModuleFlag(Module::Error, "EnableSplitLTOUnit", SplitLTOUnit);
+ if (UnifiedLTO)
+ M->addModuleFlag(Module::Error, "UnifiedLTO", 1);
+ }
// Add an appropriate TargetLibraryInfo pass for the module's triple.
TargetLibraryInfoImpl TLII(ModuleTriple);
@@ -671,9 +662,8 @@ int main(int argc, char **argv) {
if (UseNPM) {
if (legacy::debugPassSpecified()) {
- errs()
- << "-debug-pass does not work with the new PM, either use "
- "-debug-pass-manager, or use the legacy PM (-enable-new-pm=0)\n";
+ errs() << "-debug-pass does not work with the new PM, either use "
+ "-debug-pass-manager, or use the legacy PM\n";
return 1;
}
auto NumOLevel = OptLevelO0 + OptLevelO1 + OptLevelO2 + OptLevelO3 +
@@ -721,7 +711,7 @@ int main(int argc, char **argv) {
PluginList, OK, VK, PreserveAssemblyUseListOrder,
PreserveBitcodeUseListOrder, EmitSummaryIndex,
EmitModuleHash, EnableDebugify,
- VerifyDebugInfoPreserve)
+ VerifyDebugInfoPreserve, UnifiedLTO)
? 0
: 1;
}
@@ -781,26 +771,6 @@ int main(int argc, char **argv) {
}
}
- std::unique_ptr<legacy::FunctionPassManager> FPasses;
-
- if (PrintBreakpoints) {
- // Default to standard output.
- if (!Out) {
- if (OutputFilename.empty())
- OutputFilename = "-";
-
- std::error_code EC;
- Out = std::make_unique<ToolOutputFile>(OutputFilename, EC,
- sys::fs::OF_None);
- if (EC) {
- errs() << EC.message() << '\n';
- return 1;
- }
- }
- Passes.add(createBreakpointPrinter(Out->os()));
- NoOutput = true;
- }
-
if (TM) {
// FIXME: We should dyn_cast this when supported.
auto &LTM = static_cast<LLVMTargetMachine &>(*TM);
@@ -811,21 +781,18 @@ int main(int argc, char **argv) {
// Create a new optimization pass for each one specified on the command line
for (unsigned i = 0; i < PassList.size(); ++i) {
const PassInfo *PassInf = PassList[i];
- Pass *P = nullptr;
- if (PassInf->getNormalCtor())
- P = PassInf->getNormalCtor()();
- else
+ if (PassInf->getNormalCtor()) {
+ Pass *P = PassInf->getNormalCtor()();
+ if (P) {
+ // Add the pass to the pass manager.
+ Passes.add(P);
+ // If we are verifying all of the intermediate steps, add the verifier.
+ if (VerifyEach)
+ Passes.add(createVerifierPass());
+ }
+ } else
errs() << argv[0] << ": cannot create pass: "
<< PassInf->getPassName() << "\n";
- if (P)
- addPass(Passes, P);
- }
-
- if (FPasses) {
- FPasses->doInitialization();
- for (Function &F : *M)
- FPasses->run(F);
- FPasses->doFinalization();
}
// Check that the module is well formed on completion of optimization
@@ -912,7 +879,7 @@ int main(int argc, char **argv) {
exportDebugifyStats(DebugifyExport, Passes.getDebugifyStatsMap());
// Declare success.
- if (!NoOutput || PrintBreakpoints)
+ if (!NoOutput)
Out->keep();
if (RemarksFile)