aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/bugpoint/bugpoint.cpp3
-rw-r--r--llvm/tools/dsymutil/MachOUtils.cpp2
-rw-r--r--llvm/tools/llc/llc.cpp4
-rw-r--r--llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp6
-rw-r--r--llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp207
-rw-r--r--llvm/tools/llvm-objdump/ObjdumpOpts.td16
-rw-r--r--llvm/tools/llvm-objdump/SourcePrinter.cpp238
-rw-r--r--llvm/tools/llvm-objdump/SourcePrinter.h102
-rw-r--r--llvm/tools/llvm-objdump/llvm-objdump.cpp144
-rw-r--r--llvm/tools/llvm-objdump/llvm-objdump.h7
-rw-r--r--llvm/tools/llvm-rc/llvm-rc.cpp2
-rw-r--r--llvm/tools/llvm-readobj/COFFDumper.cpp11
-rw-r--r--llvm/tools/llvm-readobj/ELFDumper.cpp192
-rw-r--r--llvm/tools/llvm-readobj/ObjDumper.cpp6
-rw-r--r--llvm/tools/llvm-readobj/ObjDumper.h5
-rw-r--r--llvm/tools/llvm-readobj/Opts.td2
-rw-r--r--llvm/tools/llvm-readobj/llvm-readobj.cpp4
-rw-r--r--llvm/tools/opt/NewPMDriver.cpp8
-rw-r--r--llvm/tools/opt/NewPMDriver.h2
-rw-r--r--llvm/tools/opt/optdriver.cpp12
-rw-r--r--llvm/tools/spirv-tools/CMakeLists.txt4
21 files changed, 698 insertions, 279 deletions
diff --git a/llvm/tools/bugpoint/bugpoint.cpp b/llvm/tools/bugpoint/bugpoint.cpp
index e49efdf..87581e80a 100644
--- a/llvm/tools/bugpoint/bugpoint.cpp
+++ b/llvm/tools/bugpoint/bugpoint.cpp
@@ -22,6 +22,7 @@
#include "llvm/LinkAllIR.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/Passes/PassPlugin.h"
+#include "llvm/Support/AlwaysTrue.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/PluginLoader.h"
@@ -111,7 +112,7 @@ int main(int argc, char **argv) {
initializeInstCombine(Registry);
initializeTarget(Registry);
- if (std::getenv("bar") == (char*) -1) {
+ if (!llvm::getNonFoldableAlwaysTrue()) {
InitializeAllTargets();
InitializeAllTargetMCs();
InitializeAllAsmPrinters();
diff --git a/llvm/tools/dsymutil/MachOUtils.cpp b/llvm/tools/dsymutil/MachOUtils.cpp
index be1934f..362a999 100644
--- a/llvm/tools/dsymutil/MachOUtils.cpp
+++ b/llvm/tools/dsymutil/MachOUtils.cpp
@@ -331,7 +331,7 @@ static bool createDwarfSegment(const MCAssembler& Asm,uint64_t VMAddr, uint64_t
/* InitProt =*/3);
for (unsigned int i = 0, n = Writer.getSectionOrder().size(); i != n; ++i) {
- MCSection *Sec = Writer.getSectionOrder()[i];
+ auto *Sec = static_cast<MCSectionMachO *>(Writer.getSectionOrder()[i]);
if (!Asm.getSectionFileSize(*Sec))
continue;
diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp
index 93b4a50..b3d7185 100644
--- a/llvm/tools/llc/llc.cpp
+++ b/llvm/tools/llc/llc.cpp
@@ -733,8 +733,8 @@ static int compileModule(char **argv, LLVMContext &Context) {
reportError("target does not support generation of this file type");
}
- const_cast<TargetLoweringObjectFile *>(Target->getObjFileLowering())
- ->Initialize(MMIWP->getMMI().getContext(), *Target);
+ Target->getObjFileLowering()->Initialize(MMIWP->getMMI().getContext(),
+ *Target);
if (MIR) {
assert(MMIWP && "Forgot to create MMIWP?");
if (MIR->parseMachineFunctions(*M, MMIWP->getMMI()))
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index 676479b..ea830bd 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -651,8 +651,10 @@ static std::vector<MCInst> loadFP64RegBits32(const MCSubtargetInfo &STI,
}
std::vector<MCInst> Instrs = loadIntReg(STI, ScratchIntReg, Bits);
- Instrs.push_back(
- MCInstBuilder(RISCV::FCVT_D_W).addReg(Reg).addReg(ScratchIntReg));
+ Instrs.push_back(MCInstBuilder(RISCV::FCVT_D_W)
+ .addReg(Reg)
+ .addReg(ScratchIntReg)
+ .addImm(RISCVFPRndMode::RNE));
return Instrs;
}
diff --git a/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp b/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp
index e1e5fad..f6ed94b 100644
--- a/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp
+++ b/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp
@@ -9,13 +9,20 @@
/// \file
/// This file implements the IR2Vec embedding generation tool.
///
-/// This tool provides two main functionalities:
+/// This tool provides three main modes:
///
/// 1. Triplet Generation Mode (--mode=triplets):
-/// Generates triplets (opcode, type, operands) for vocabulary training.
-/// Usage: llvm-ir2vec --mode=triplets input.bc -o triplets.txt
+/// Generates numeric triplets (head, tail, relation) for vocabulary
+/// training. Output format: MAX_RELATION=N header followed by
+/// head\ttail\trelation lines. Relations: 0=Type, 1=Next, 2+=Arg0,Arg1,...
+/// Usage: llvm-ir2vec --mode=triplets input.bc -o train2id.txt
///
-/// 2. Embedding Generation Mode (--mode=embeddings):
+/// 2. Entities Generation Mode (--mode=entities):
+/// Generates entity mappings for vocabulary training.
+/// Output format: <total_entities> header followed by entity\tid lines.
+/// Usage: llvm-ir2vec --mode=entities input.bc -o entity2id.txt
+///
+/// 3. Embedding Generation Mode (--mode=embeddings):
/// Generates IR2Vec embeddings using a trained vocabulary.
/// Usage: llvm-ir2vec --mode=embeddings --ir2vec-vocab-path=vocab.json
/// --level=func input.bc -o embeddings.txt Levels: --level=inst
@@ -60,16 +67,19 @@ static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
enum ToolMode {
TripletMode, // Generate triplets for vocabulary training
+ EntityMode, // Generate entity mappings for vocabulary training
EmbeddingMode // Generate embeddings using trained vocabulary
};
-static cl::opt<ToolMode>
- Mode("mode", cl::desc("Tool operation mode:"),
- cl::values(clEnumValN(TripletMode, "triplets",
- "Generate triplets for vocabulary training"),
- clEnumValN(EmbeddingMode, "embeddings",
- "Generate embeddings using trained vocabulary")),
- cl::init(EmbeddingMode), cl::cat(IR2VecToolCategory));
+static cl::opt<ToolMode> Mode(
+ "mode", cl::desc("Tool operation mode:"),
+ cl::values(clEnumValN(TripletMode, "triplets",
+ "Generate triplets for vocabulary training"),
+ clEnumValN(EntityMode, "entities",
+ "Generate entity mappings for vocabulary training"),
+ clEnumValN(EmbeddingMode, "embeddings",
+ "Generate embeddings using trained vocabulary")),
+ cl::init(EmbeddingMode), cl::cat(IR2VecToolCategory));
static cl::opt<std::string>
FunctionName("function", cl::desc("Process specific function only"),
@@ -94,6 +104,13 @@ static cl::opt<EmbeddingLevel>
namespace {
+/// Relation types for triplet generation
+enum RelationType {
+ TypeRelation = 0, ///< Instruction to type relationship
+ NextRelation = 1, ///< Sequential instruction relationship
+ ArgRelation = 2 ///< Instruction to operand relationship (ArgRelation + N)
+};
+
/// Helper class for collecting IR triplets and generating embeddings
class IR2VecTool {
private:
@@ -111,29 +128,101 @@ public:
// option
MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
MAM.registerPass([&] { return IR2VecVocabAnalysis(); });
+ // This will throw an error if vocab is not found or invalid
Vocab = &MAM.getResult<IR2VecVocabAnalysis>(M);
return Vocab->isValid();
}
- /// Generate triplets for the entire module
+ /// Generate triplets for the module
+ /// Output format: MAX_RELATION=N header followed by relationships
void generateTriplets(raw_ostream &OS) const {
- for (const Function &F : M)
- generateTriplets(F, OS);
+ unsigned MaxRelation = NextRelation; // Track maximum relation ID
+ std::string Relationships;
+ raw_string_ostream RelOS(Relationships);
+
+ for (const Function &F : M) {
+ unsigned FuncMaxRelation = generateTriplets(F, RelOS);
+ MaxRelation = std::max(MaxRelation, FuncMaxRelation);
+ }
+
+ RelOS.flush();
+
+ // Write metadata header followed by relationships
+ OS << "MAX_RELATION=" << MaxRelation << '\n';
+ OS << Relationships;
}
/// Generate triplets for a single function
- void generateTriplets(const Function &F, raw_ostream &OS) const {
+ /// Returns the maximum relation ID used in this function
+ unsigned generateTriplets(const Function &F, raw_ostream &OS) const {
if (F.isDeclaration())
- return;
+ return 0;
+
+ unsigned MaxRelation = 1;
+ unsigned PrevOpcode = 0;
+ bool HasPrevOpcode = false;
+
+ for (const BasicBlock &BB : F) {
+ for (const auto &I : BB.instructionsWithoutDebug()) {
+ unsigned Opcode = Vocabulary::getNumericID(I.getOpcode());
+ unsigned TypeID = Vocabulary::getNumericID(I.getType()->getTypeID());
+
+ // Add "Next" relationship with previous instruction
+ if (HasPrevOpcode) {
+ OS << PrevOpcode << '\t' << Opcode << '\t' << NextRelation << '\n';
+ LLVM_DEBUG(dbgs()
+ << Vocabulary::getVocabKeyForOpcode(PrevOpcode + 1) << '\t'
+ << Vocabulary::getVocabKeyForOpcode(Opcode + 1) << '\t'
+ << "Next\n");
+ }
- std::string LocalOutput;
- raw_string_ostream LocalOS(LocalOutput);
+ // Add "Type" relationship
+ OS << Opcode << '\t' << TypeID << '\t' << TypeRelation << '\n';
+ LLVM_DEBUG(
+ dbgs() << Vocabulary::getVocabKeyForOpcode(Opcode + 1) << '\t'
+ << Vocabulary::getVocabKeyForTypeID(I.getType()->getTypeID())
+ << '\t' << "Type\n");
+
+ // Add "Arg" relationships
+ unsigned ArgIndex = 0;
+ for (const Use &U : I.operands()) {
+ unsigned OperandID = Vocabulary::getNumericID(U.get());
+ unsigned RelationID = ArgRelation + ArgIndex;
+ OS << Opcode << '\t' << OperandID << '\t' << RelationID << '\n';
+
+ LLVM_DEBUG({
+ StringRef OperandStr = Vocabulary::getVocabKeyForOperandKind(
+ Vocabulary::getOperandKind(U.get()));
+ dbgs() << Vocabulary::getVocabKeyForOpcode(Opcode + 1) << '\t'
+ << OperandStr << '\t' << "Arg" << ArgIndex << '\n';
+ });
+
+ ++ArgIndex;
+ }
+ // Only update MaxRelation if there were operands
+ if (ArgIndex > 0) {
+ MaxRelation = std::max(MaxRelation, ArgRelation + ArgIndex - 1);
+ }
+ PrevOpcode = Opcode;
+ HasPrevOpcode = true;
+ }
+ }
- for (const BasicBlock &BB : F)
- traverseBasicBlock(BB, LocalOS);
+ return MaxRelation;
+ }
- LocalOS.flush();
- OS << LocalOutput;
+ /// Dump entity ID to string mappings
+ static void generateEntityMappings(raw_ostream &OS) {
+ // FIXME: Currently, the generated entity mappings are not one-to-one;
+ // Multiple TypeIDs map to same string key (Like Half, BFloat, etc. map to
+ // FloatTy). This would hinder learning good seed embeddings.
+ // We should fix this in the future by ensuring unique string keys either by
+ // post-processing here without changing the mapping in ir2vec::Vocabulary,
+ // or by changing the Vocabulary generation logic to ensure unique keys.
+ auto EntityLen = Vocabulary::expectedSize();
+ OS << EntityLen << "\n";
+ for (unsigned EntityID = 0; EntityID < EntityLen; ++EntityID)
+ OS << Vocabulary::getStringKey(EntityID) << '\t' << EntityID << '\n';
}
/// Generate embeddings for the entire module
@@ -197,31 +286,6 @@ public:
}
}
}
-
-private:
- /// Process a single basic block for triplet generation
- void traverseBasicBlock(const BasicBlock &BB, raw_string_ostream &OS) const {
- // Consider only non-debug and non-pseudo instructions
- for (const auto &I : BB.instructionsWithoutDebug()) {
- StringRef OpcStr = Vocabulary::getVocabKeyForOpcode(I.getOpcode());
- StringRef TypeStr =
- Vocabulary::getVocabKeyForTypeID(I.getType()->getTypeID());
-
- OS << '\n' << OpcStr << ' ' << TypeStr << ' ';
-
- LLVM_DEBUG({
- I.print(dbgs());
- dbgs() << "\n";
- I.getType()->print(dbgs());
- dbgs() << " Type\n";
- });
-
- for (const Use &U : I.operands())
- OS << Vocabulary::getVocabKeyForOperandKind(
- Vocabulary::getOperandKind(U.get()))
- << ' ';
- }
- }
};
Error processModule(Module &M, raw_ostream &OS) {
@@ -230,11 +294,9 @@ Error processModule(Module &M, raw_ostream &OS) {
if (Mode == EmbeddingMode) {
// Initialize vocabulary for embedding generation
// Note: Requires --ir2vec-vocab-path option to be set
- if (!Tool.initializeVocabulary())
- return createStringError(
- errc::invalid_argument,
- "Failed to initialize IR2Vec vocabulary. "
- "Make sure to specify --ir2vec-vocab-path for embedding mode.");
+ auto VocabStatus = Tool.initializeVocabulary();
+ assert(VocabStatus && "Failed to initialize IR2Vec vocabulary");
+ (void)VocabStatus;
if (!FunctionName.empty()) {
// Process single function
@@ -249,18 +311,7 @@ Error processModule(Module &M, raw_ostream &OS) {
Tool.generateEmbeddings(OS);
}
} else {
- // Triplet generation mode - no vocabulary needed
- if (!FunctionName.empty())
- // Process single function
- if (const Function *F = M.getFunction(FunctionName))
- Tool.generateTriplets(*F, OS);
- else
- return createStringError(errc::invalid_argument,
- "Function '%s' not found",
- FunctionName.c_str());
- else
- // Process all functions
- Tool.generateTriplets(OS);
+ Tool.generateTriplets(OS);
}
return Error::success();
}
@@ -284,8 +335,25 @@ int main(int argc, char **argv) {
"information.\n");
// Validate command line options
- if (Mode == TripletMode && Level.getNumOccurrences() > 0)
- errs() << "Warning: --level option is ignored in triplet mode\n";
+ if (Mode != EmbeddingMode) {
+ if (Level.getNumOccurrences() > 0)
+ errs() << "Warning: --level option is ignored\n";
+ if (FunctionName.getNumOccurrences() > 0)
+ errs() << "Warning: --function option is ignored\n";
+ }
+
+ std::error_code EC;
+ raw_fd_ostream OS(OutputFilename, EC);
+ if (EC) {
+ errs() << "Error opening output file: " << EC.message() << "\n";
+ return 1;
+ }
+
+ if (Mode == EntityMode) {
+ // Just dump entity mappings without processing any IR
+ IR2VecTool::generateEntityMappings(OS);
+ return 0;
+ }
// Parse the input LLVM IR file or stdin
SMDiagnostic Err;
@@ -296,13 +364,6 @@ int main(int argc, char **argv) {
return 1;
}
- std::error_code EC;
- raw_fd_ostream OS(OutputFilename, EC);
- if (EC) {
- errs() << "Error opening output file: " << EC.message() << "\n";
- return 1;
- }
-
if (Error Err = processModule(*M, OS)) {
handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EIB) {
errs() << "Error: " << EIB.message() << "\n";
diff --git a/llvm/tools/llvm-objdump/ObjdumpOpts.td b/llvm/tools/llvm-objdump/ObjdumpOpts.td
index c3764c6..c97e06f 100644
--- a/llvm/tools/llvm-objdump/ObjdumpOpts.td
+++ b/llvm/tools/llvm-objdump/ObjdumpOpts.td
@@ -241,17 +241,23 @@ defm prefix_strip
"paths. No effect without --prefix">,
MetaVarName<"prefix">;
+def debug_indent_EQ : Joined<["--"], "debug-indent=">,
+ HelpText<"Distance to indent the source-level variable and inlined function display, "
+ "relative to the start of the disassembly">;
+
+def debug_inlined_funcs_EQ : Joined<["--"], "debug-inlined-funcs=">,
+ HelpText<"Print the locations of inlined functions alongside disassembly. "
+ "Supported formats: ascii, limits-only, and unicode (default)">,
+ Values<"ascii,limits-only,unicode">;
+def : Flag<["--"], "debug-inlined-funcs">, Alias<debug_inlined_funcs_EQ>, AliasArgs<["unicode"]>;
+
def debug_vars_EQ : Joined<["--"], "debug-vars=">,
HelpText<"Print the locations (in registers or memory) of "
"source-level variables alongside disassembly. "
"Supported formats: ascii, unicode (default)">,
- Values<"unicode,ascii">;
+ Values<"ascii,unicode">;
def : Flag<["--"], "debug-vars">, Alias<debug_vars_EQ>, AliasArgs<["unicode"]>;
-def debug_vars_indent_EQ : Joined<["--"], "debug-vars-indent=">,
- HelpText<"Distance to indent the source-level variable display, "
- "relative to the start of the disassembly">;
-
def x86_asm_syntax_att : Flag<["--"], "x86-asm-syntax=att">,
HelpText<"Emit AT&T-style disassembly">;
diff --git a/llvm/tools/llvm-objdump/SourcePrinter.cpp b/llvm/tools/llvm-objdump/SourcePrinter.cpp
index 3630502..b0ff89d 100644
--- a/llvm/tools/llvm-objdump/SourcePrinter.cpp
+++ b/llvm/tools/llvm-objdump/SourcePrinter.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the LiveVariablePrinter and SourcePrinter classes to
+// This file implements the LiveElementPrinter and SourcePrinter classes to
// keep track of DWARF info as the current address is updated, and print out the
-// source file line and variable liveness as needed.
+// source file line and variable or inlined function liveness as needed.
//
//===----------------------------------------------------------------------===//
@@ -17,6 +17,7 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/Demangle/Demangle.h"
#include "llvm/Support/FormatVariadic.h"
#define DEBUG_TYPE "objdump"
@@ -24,7 +25,70 @@
namespace llvm {
namespace objdump {
-bool LiveVariable::liveAtAddress(object::SectionedAddress Addr) {
+bool InlinedFunction::liveAtAddress(object::SectionedAddress Addr) const {
+ if (!Range.valid())
+ return false;
+
+ return Range.LowPC <= Addr.Address && Range.HighPC > Addr.Address;
+}
+
+void InlinedFunction::print(raw_ostream &OS, const MCRegisterInfo &MRI) const {
+ const char *MangledCallerName = FuncDie.getName(DINameKind::LinkageName);
+ if (!MangledCallerName)
+ return;
+
+ if (Demangle)
+ OS << "inlined into " << demangle(MangledCallerName);
+ else
+ OS << "inlined into " << MangledCallerName;
+}
+
+void InlinedFunction::dump(raw_ostream &OS) const {
+ OS << Name << " @ " << Range << ": ";
+}
+
+void InlinedFunction::printElementLine(raw_ostream &OS,
+ object::SectionedAddress Addr,
+ bool IsEnd) const {
+ bool LiveIn = !IsEnd && Range.LowPC == Addr.Address;
+ bool LiveOut = IsEnd && Range.HighPC == Addr.Address;
+ if (!(LiveIn || LiveOut))
+ return;
+
+ uint32_t CallFile, CallLine, CallColumn, CallDiscriminator;
+ InlinedFuncDie.getCallerFrame(CallFile, CallLine, CallColumn,
+ CallDiscriminator);
+ const DWARFDebugLine::LineTable *LineTable =
+ Unit->getContext().getLineTableForUnit(Unit);
+ std::string FileName;
+ if (!LineTable->hasFileAtIndex(CallFile))
+ return;
+ if (!LineTable->getFileNameByIndex(
+ CallFile, Unit->getCompilationDir(),
+ DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FileName))
+ return;
+
+ if (FileName.empty())
+ return;
+
+ const char *MangledCallerName = FuncDie.getName(DINameKind::LinkageName);
+ if (!MangledCallerName)
+ return;
+
+ std::string CallerName = MangledCallerName;
+ std::string CalleeName = Name;
+ if (Demangle) {
+ CallerName = demangle(MangledCallerName);
+ CalleeName = demangle(Name);
+ }
+
+ OS << "; " << FileName << ":" << CallLine << ":" << CallColumn << ": ";
+ if (IsEnd)
+ OS << "end of ";
+ OS << CalleeName << " inlined into " << CallerName << "\n";
+}
+
+bool LiveVariable::liveAtAddress(object::SectionedAddress Addr) const {
if (LocExpr.Range == std::nullopt)
return false;
return LocExpr.Range->SectionIndex == Addr.SectionIndex &&
@@ -49,7 +113,24 @@ void LiveVariable::print(raw_ostream &OS, const MCRegisterInfo &MRI) const {
printDwarfExpressionCompact(&Expression, OS, GetRegName);
}
-void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) {
+void LiveVariable::dump(raw_ostream &OS) const {
+ OS << Name << " @ " << LocExpr.Range << ": ";
+}
+
+void LiveElementPrinter::addInlinedFunction(DWARFDie FuncDie,
+ DWARFDie InlinedFuncDie) {
+ uint64_t FuncLowPC, FuncHighPC, SectionIndex;
+ if (!InlinedFuncDie.getLowAndHighPC(FuncLowPC, FuncHighPC, SectionIndex))
+ return;
+
+ DWARFUnit *U = InlinedFuncDie.getDwarfUnit();
+ const char *InlinedFuncName = InlinedFuncDie.getName(DINameKind::LinkageName);
+ DWARFAddressRange Range{FuncLowPC, FuncHighPC, SectionIndex};
+ LiveElements.emplace_back(std::make_unique<InlinedFunction>(
+ InlinedFuncName, U, FuncDie, InlinedFuncDie, Range));
+}
+
+void LiveElementPrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) {
uint64_t FuncLowPC, FuncHighPC, SectionIndex;
FuncDie.getLowAndHighPC(FuncLowPC, FuncHighPC, SectionIndex);
const char *VarName = VarDie.getName(DINameKind::ShortName);
@@ -67,7 +148,8 @@ void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) {
for (const DWARFLocationExpression &LocExpr : *Locs) {
if (LocExpr.Range) {
- LiveVariables.emplace_back(LocExpr, VarName, U, FuncDie);
+ LiveElements.emplace_back(
+ std::make_unique<LiveVariable>(LocExpr, VarName, U, FuncDie));
} else {
// If the LocExpr does not have an associated range, it is valid for
// the whole of the function.
@@ -75,24 +157,30 @@ void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) {
// LocExpr, does that happen in reality?
DWARFLocationExpression WholeFuncExpr{
DWARFAddressRange(FuncLowPC, FuncHighPC, SectionIndex), LocExpr.Expr};
- LiveVariables.emplace_back(WholeFuncExpr, VarName, U, FuncDie);
+ LiveElements.emplace_back(
+ std::make_unique<LiveVariable>(WholeFuncExpr, VarName, U, FuncDie));
}
}
}
-void LiveVariablePrinter::addFunction(DWARFDie D) {
+void LiveElementPrinter::addFunction(DWARFDie D) {
for (const DWARFDie &Child : D.children()) {
- if (Child.getTag() == dwarf::DW_TAG_variable ||
- Child.getTag() == dwarf::DW_TAG_formal_parameter)
+ if (DbgVariables != DFDisabled &&
+ (Child.getTag() == dwarf::DW_TAG_variable ||
+ Child.getTag() == dwarf::DW_TAG_formal_parameter)) {
addVariable(D, Child);
- else
+ } else if (DbgInlinedFunctions != DFDisabled &&
+ Child.getTag() == dwarf::DW_TAG_inlined_subroutine) {
+ addInlinedFunction(D, Child);
+ addFunction(Child);
+ } else
addFunction(Child);
}
}
-// Get the column number (in characters) at which the first live variable
+// Get the column number (in characters) at which the first live element
// line should be printed.
-unsigned LiveVariablePrinter::getIndentLevel() const {
+unsigned LiveElementPrinter::getIndentLevel() const {
return DbgIndent + getInstStartColumn(STI);
}
@@ -100,8 +188,8 @@ unsigned LiveVariablePrinter::getIndentLevel() const {
// printed line, and return the index of that column.
// TODO: formatted_raw_ostream uses "column" to mean a number of characters
// since the last \n, and we use it to mean the number of slots in which we
-// put live variable lines. Pick a less overloaded word.
-unsigned LiveVariablePrinter::moveToFirstVarColumn(formatted_raw_ostream &OS) {
+// put live element lines. Pick a less overloaded word.
+unsigned LiveElementPrinter::moveToFirstVarColumn(formatted_raw_ostream &OS) {
// Logical column number: column zero is the first column we print in, each
// logical column is 2 physical columns wide.
unsigned FirstUnprintedLogicalColumn =
@@ -117,7 +205,7 @@ unsigned LiveVariablePrinter::moveToFirstVarColumn(formatted_raw_ostream &OS) {
return FirstUnprintedLogicalColumn;
}
-unsigned LiveVariablePrinter::findFreeColumn() {
+unsigned LiveElementPrinter::findFreeColumn() {
for (unsigned ColIdx = 0; ColIdx < ActiveCols.size(); ++ColIdx)
if (!ActiveCols[ColIdx].isActive())
return ColIdx;
@@ -127,15 +215,15 @@ unsigned LiveVariablePrinter::findFreeColumn() {
return OldSize;
}
-void LiveVariablePrinter::dump() const {
- for (const LiveVariable &LV : LiveVariables) {
- dbgs() << LV.VarName << " @ " << LV.LocExpr.Range << ": ";
- LV.print(dbgs(), MRI);
+void LiveElementPrinter::dump() const {
+ for (const std::unique_ptr<LiveElement> &LE : LiveElements) {
+ LE->dump(dbgs());
+ LE->print(dbgs(), MRI);
dbgs() << "\n";
}
}
-void LiveVariablePrinter::addCompileUnit(DWARFDie D) {
+void LiveElementPrinter::addCompileUnit(DWARFDie D) {
if (D.getTag() == dwarf::DW_TAG_subprogram)
addFunction(D);
else
@@ -148,47 +236,57 @@ void LiveVariablePrinter::addCompileUnit(DWARFDie D) {
/// live-in to the instruction, and any live range active at NextAddr is
/// live-out of the instruction. If IncludeDefinedVars is false, then live
/// ranges starting at NextAddr will be ignored.
-void LiveVariablePrinter::update(object::SectionedAddress ThisAddr,
- object::SectionedAddress NextAddr,
- bool IncludeDefinedVars) {
+void LiveElementPrinter::update(object::SectionedAddress ThisAddr,
+ object::SectionedAddress NextAddr,
+ bool IncludeDefinedVars) {
+ // Do not create live ranges when debug-inlined-funcs option is provided with
+ // line format option.
+ if (DbgInlinedFunctions == DFLimitsOnly)
+ return;
+
// First, check variables which have already been assigned a column, so
// that we don't change their order.
- SmallSet<unsigned, 8> CheckedVarIdxs;
+ SmallSet<unsigned, 8> CheckedElementIdxs;
for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) {
if (!ActiveCols[ColIdx].isActive())
continue;
- CheckedVarIdxs.insert(ActiveCols[ColIdx].VarIdx);
- LiveVariable &LV = LiveVariables[ActiveCols[ColIdx].VarIdx];
- ActiveCols[ColIdx].LiveIn = LV.liveAtAddress(ThisAddr);
- ActiveCols[ColIdx].LiveOut = LV.liveAtAddress(NextAddr);
+
+ CheckedElementIdxs.insert(ActiveCols[ColIdx].ElementIdx);
+ const std::unique_ptr<LiveElement> &LE =
+ LiveElements[ActiveCols[ColIdx].ElementIdx];
+ ActiveCols[ColIdx].LiveIn = LE->liveAtAddress(ThisAddr);
+ ActiveCols[ColIdx].LiveOut = LE->liveAtAddress(NextAddr);
+ std::string Name = Demangle ? demangle(LE->getName()) : LE->getName();
LLVM_DEBUG(dbgs() << "pass 1, " << ThisAddr.Address << "-"
- << NextAddr.Address << ", " << LV.VarName << ", Col "
- << ColIdx << ": LiveIn=" << ActiveCols[ColIdx].LiveIn
+ << NextAddr.Address << ", " << Name << ", Col " << ColIdx
+ << ": LiveIn=" << ActiveCols[ColIdx].LiveIn
<< ", LiveOut=" << ActiveCols[ColIdx].LiveOut << "\n");
if (!ActiveCols[ColIdx].LiveIn && !ActiveCols[ColIdx].LiveOut)
- ActiveCols[ColIdx].VarIdx = Column::NullVarIdx;
+ ActiveCols[ColIdx].ElementIdx = Column::NullElementIdx;
}
// Next, look for variables which don't already have a column, but which
// are now live.
if (IncludeDefinedVars) {
- for (unsigned VarIdx = 0, End = LiveVariables.size(); VarIdx < End;
- ++VarIdx) {
- if (CheckedVarIdxs.count(VarIdx))
+ for (unsigned ElementIdx = 0, End = LiveElements.size(); ElementIdx < End;
+ ++ElementIdx) {
+ if (CheckedElementIdxs.count(ElementIdx))
continue;
- LiveVariable &LV = LiveVariables[VarIdx];
- bool LiveIn = LV.liveAtAddress(ThisAddr);
- bool LiveOut = LV.liveAtAddress(NextAddr);
+
+ const std::unique_ptr<LiveElement> &LE = LiveElements[ElementIdx];
+ bool LiveIn = LE->liveAtAddress(ThisAddr);
+ bool LiveOut = LE->liveAtAddress(NextAddr);
if (!LiveIn && !LiveOut)
continue;
unsigned ColIdx = findFreeColumn();
+ std::string Name = Demangle ? demangle(LE->getName()) : LE->getName();
LLVM_DEBUG(dbgs() << "pass 2, " << ThisAddr.Address << "-"
- << NextAddr.Address << ", " << LV.VarName << ", Col "
+ << NextAddr.Address << ", " << Name << ", Col "
<< ColIdx << ": LiveIn=" << LiveIn
<< ", LiveOut=" << LiveOut << "\n");
- ActiveCols[ColIdx].VarIdx = VarIdx;
+ ActiveCols[ColIdx].ElementIdx = ElementIdx;
ActiveCols[ColIdx].LiveIn = LiveIn;
ActiveCols[ColIdx].LiveOut = LiveOut;
ActiveCols[ColIdx].MustDrawLabel = true;
@@ -205,8 +303,8 @@ enum class LineChar {
LabelCornerActive,
LabelHoriz,
};
-const char *LiveVariablePrinter::getLineChar(LineChar C) const {
- bool IsASCII = DbgVariables == DVASCII;
+const char *LiveElementPrinter::getLineChar(LineChar C) const {
+ bool IsASCII = DbgVariables == DFASCII || DbgInlinedFunctions == DFASCII;
switch (C) {
case LineChar::RangeStart:
return IsASCII ? "^" : (const char *)u8"\u2548";
@@ -231,8 +329,8 @@ const char *LiveVariablePrinter::getLineChar(LineChar C) const {
/// we only need to print active ranges or empty columns. If AfterInst is
/// true, this is being printed after the last instruction fed to update(),
/// otherwise this is being printed before it.
-void LiveVariablePrinter::printAfterOtherLine(formatted_raw_ostream &OS,
- bool AfterInst) {
+void LiveElementPrinter::printAfterOtherLine(formatted_raw_ostream &OS,
+ bool AfterInst) {
if (ActiveCols.size()) {
unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS);
for (size_t ColIdx = FirstUnprintedColumn, End = ActiveCols.size();
@@ -252,15 +350,15 @@ void LiveVariablePrinter::printAfterOtherLine(formatted_raw_ostream &OS,
OS << "\n";
}
-/// Print any live variable range info needed to the right of a
-/// non-instruction line of disassembly. This is where we print the variable
+/// Print any live element range info needed to the right of a
+/// non-instruction line of disassembly. This is where we print the element
/// names and expressions, with thin line-drawing characters connecting them
/// to the live range which starts at the next instruction. If MustPrint is
/// true, we have to print at least one line (with the continuation of any
/// already-active live ranges) because something has already been printed
/// earlier on this line.
-void LiveVariablePrinter::printBetweenInsts(formatted_raw_ostream &OS,
- bool MustPrint) {
+void LiveElementPrinter::printBetweenInsts(formatted_raw_ostream &OS,
+ bool MustPrint) {
bool PrintedSomething = false;
for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) {
if (ActiveCols[ColIdx].isActive() && ActiveCols[ColIdx].MustDrawLabel) {
@@ -277,17 +375,20 @@ void LiveVariablePrinter::printBetweenInsts(formatted_raw_ostream &OS,
OS << " ";
}
+ const std::unique_ptr<LiveElement> &LE =
+ LiveElements[ActiveCols[ColIdx].ElementIdx];
// Then print the variable name and location of the new live range,
// with box drawing characters joining it to the live range line.
OS << getLineChar(ActiveCols[ColIdx].LiveIn ? LineChar::LabelCornerActive
: LineChar::LabelCornerNew)
<< getLineChar(LineChar::LabelHoriz) << " ";
- WithColor(OS, raw_ostream::GREEN)
- << LiveVariables[ActiveCols[ColIdx].VarIdx].VarName;
+
+ std::string Name = Demangle ? demangle(LE->getName()) : LE->getName();
+ WithColor(OS, raw_ostream::GREEN) << Name;
OS << " = ";
{
WithColor ExprColor(OS, raw_ostream::CYAN);
- LiveVariables[ActiveCols[ColIdx].VarIdx].print(OS, MRI);
+ LE->print(OS, MRI);
}
// If there are any columns to the right of the expression we just
@@ -317,8 +418,8 @@ void LiveVariablePrinter::printBetweenInsts(formatted_raw_ostream &OS,
printAfterOtherLine(OS, false);
}
-/// Print the live variable ranges to the right of a disassembled instruction.
-void LiveVariablePrinter::printAfterInst(formatted_raw_ostream &OS) {
+/// Print the live element ranges to the right of a disassembled instruction.
+void LiveElementPrinter::printAfterInst(formatted_raw_ostream &OS) {
if (!ActiveCols.size())
return;
unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS);
@@ -337,6 +438,24 @@ void LiveVariablePrinter::printAfterInst(formatted_raw_ostream &OS) {
}
}
+void LiveElementPrinter::printStartLine(formatted_raw_ostream &OS,
+ object::SectionedAddress Addr) {
+ // Print a line to idenfity the start of an inlined function if line format
+ // is specified.
+ if (DbgInlinedFunctions == DFLimitsOnly)
+ for (const std::unique_ptr<LiveElement> &LE : LiveElements)
+ LE->printElementLine(OS, Addr, false);
+}
+
+void LiveElementPrinter::printEndLine(formatted_raw_ostream &OS,
+ object::SectionedAddress Addr) {
+ // Print a line to idenfity the end of an inlined function if line format is
+ // specified.
+ if (DbgInlinedFunctions == DFLimitsOnly)
+ for (const std::unique_ptr<LiveElement> &LE : LiveElements)
+ LE->printElementLine(OS, Addr, true);
+}
+
bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) {
std::unique_ptr<MemoryBuffer> Buffer;
if (LineInfo.Source) {
@@ -371,7 +490,7 @@ bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) {
void SourcePrinter::printSourceLine(formatted_raw_ostream &OS,
object::SectionedAddress Address,
StringRef ObjectFilename,
- LiveVariablePrinter &LVP,
+ LiveElementPrinter &LEP,
StringRef Delimiter) {
if (!Symbolizer)
return;
@@ -419,15 +538,16 @@ void SourcePrinter::printSourceLine(formatted_raw_ostream &OS,
}
if (PrintLines)
- printLines(OS, LineInfo, Delimiter, LVP);
+ printLines(OS, Address, LineInfo, Delimiter, LEP);
if (PrintSource)
- printSources(OS, LineInfo, ObjectFilename, Delimiter, LVP);
+ printSources(OS, LineInfo, ObjectFilename, Delimiter, LEP);
OldLineInfo = LineInfo;
}
void SourcePrinter::printLines(formatted_raw_ostream &OS,
+ object::SectionedAddress Address,
const DILineInfo &LineInfo, StringRef Delimiter,
- LiveVariablePrinter &LVP) {
+ LiveElementPrinter &LEP) {
bool PrintFunctionName = LineInfo.FunctionName != DILineInfo::BadString &&
LineInfo.FunctionName != OldLineInfo.FunctionName;
if (PrintFunctionName) {
@@ -442,7 +562,7 @@ void SourcePrinter::printLines(formatted_raw_ostream &OS,
(OldLineInfo.Line != LineInfo.Line ||
OldLineInfo.FileName != LineInfo.FileName || PrintFunctionName)) {
OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line;
- LVP.printBetweenInsts(OS, true);
+ LEP.printBetweenInsts(OS, true);
}
}
@@ -477,7 +597,7 @@ StringRef SourcePrinter::getLine(const DILineInfo &LineInfo,
void SourcePrinter::printSources(formatted_raw_ostream &OS,
const DILineInfo &LineInfo,
StringRef ObjectFilename, StringRef Delimiter,
- LiveVariablePrinter &LVP) {
+ LiveElementPrinter &LEP) {
if (LineInfo.FileName == DILineInfo::BadString || LineInfo.Line == 0 ||
(OldLineInfo.Line == LineInfo.Line &&
OldLineInfo.FileName == LineInfo.FileName))
@@ -486,7 +606,7 @@ void SourcePrinter::printSources(formatted_raw_ostream &OS,
StringRef Line = getLine(LineInfo, ObjectFilename);
if (!Line.empty()) {
OS << Delimiter << Line;
- LVP.printBetweenInsts(OS, true);
+ LEP.printBetweenInsts(OS, true);
}
}
diff --git a/llvm/tools/llvm-objdump/SourcePrinter.h b/llvm/tools/llvm-objdump/SourcePrinter.h
index fc67fc6..5c131a0 100644
--- a/llvm/tools/llvm-objdump/SourcePrinter.h
+++ b/llvm/tools/llvm-objdump/SourcePrinter.h
@@ -22,40 +22,83 @@
namespace llvm {
namespace objdump {
+/// Base class for representing the location of a source-level variable or
+/// an inlined function.
+class LiveElement {
+protected:
+ const char *Name;
+ DWARFUnit *Unit;
+ const DWARFDie FuncDie;
+
+public:
+ LiveElement(const char *Name, DWARFUnit *Unit, const DWARFDie FuncDie)
+ : Name(Name), Unit(Unit), FuncDie(FuncDie) {}
+
+ virtual ~LiveElement() {};
+ const char *getName() const { return Name; }
+
+ virtual bool liveAtAddress(object::SectionedAddress Addr) const = 0;
+ virtual void print(raw_ostream &OS, const MCRegisterInfo &MRI) const = 0;
+ virtual void dump(raw_ostream &OS) const = 0;
+ virtual void printElementLine(raw_ostream &OS,
+ object::SectionedAddress Address,
+ bool IsEnd) const {}
+};
+
+class InlinedFunction : public LiveElement {
+private:
+ DWARFDie InlinedFuncDie;
+ DWARFAddressRange Range;
+
+public:
+ InlinedFunction(const char *FunctionName, DWARFUnit *Unit,
+ const DWARFDie FuncDie, const DWARFDie InlinedFuncDie,
+ DWARFAddressRange &Range)
+ : LiveElement(FunctionName, Unit, FuncDie),
+ InlinedFuncDie(InlinedFuncDie), Range(Range) {}
+
+ bool liveAtAddress(object::SectionedAddress Addr) const override;
+ void print(raw_ostream &OS, const MCRegisterInfo &MRI) const override;
+ void dump(raw_ostream &OS) const override;
+ void printElementLine(raw_ostream &OS, object::SectionedAddress Address,
+ bool IsEnd) const override;
+};
+
/// Stores a single expression representing the location of a source-level
/// variable, along with the PC range for which that expression is valid.
-struct LiveVariable {
+class LiveVariable : public LiveElement {
+private:
DWARFLocationExpression LocExpr;
- const char *VarName;
- DWARFUnit *Unit;
- const DWARFDie FuncDie;
+public:
LiveVariable(const DWARFLocationExpression &LocExpr, const char *VarName,
DWARFUnit *Unit, const DWARFDie FuncDie)
- : LocExpr(LocExpr), VarName(VarName), Unit(Unit), FuncDie(FuncDie) {}
+ : LiveElement(VarName, Unit, FuncDie), LocExpr(LocExpr) {}
- bool liveAtAddress(object::SectionedAddress Addr);
-
- void print(raw_ostream &OS, const MCRegisterInfo &MRI) const;
+ bool liveAtAddress(object::SectionedAddress Addr) const override;
+ void print(raw_ostream &OS, const MCRegisterInfo &MRI) const override;
+ void dump(raw_ostream &OS) const override;
};
-/// Helper class for printing source variable locations alongside disassembly.
-class LiveVariablePrinter {
- // Information we want to track about one column in which we are printing a
- // variable live range.
+/// Helper class for printing source locations for variables and inlined
+/// subroutines alongside disassembly.
+class LiveElementPrinter {
+ // Information we want to track about one column in which we are printing an
+ // element live range.
struct Column {
- unsigned VarIdx = NullVarIdx;
+ unsigned ElementIdx = NullElementIdx;
bool LiveIn = false;
bool LiveOut = false;
bool MustDrawLabel = false;
- bool isActive() const { return VarIdx != NullVarIdx; }
+ bool isActive() const { return ElementIdx != NullElementIdx; }
- static constexpr unsigned NullVarIdx = std::numeric_limits<unsigned>::max();
+ static constexpr unsigned NullElementIdx =
+ std::numeric_limits<unsigned>::max();
};
- // All live variables we know about in the object/image file.
- std::vector<LiveVariable> LiveVariables;
+ // All live elements we know about in the object/image file.
+ std::vector<std::unique_ptr<LiveElement>> LiveElements;
// The columns we are currently drawing.
IndexedMap<Column> ActiveCols;
@@ -63,11 +106,12 @@ class LiveVariablePrinter {
const MCRegisterInfo &MRI;
const MCSubtargetInfo &STI;
+ void addInlinedFunction(DWARFDie FuncDie, DWARFDie InlinedFuncDie);
void addVariable(DWARFDie FuncDie, DWARFDie VarDie);
void addFunction(DWARFDie D);
- // Get the column number (in characters) at which the first live variable
+ // Get the column number (in characters) at which the first live element
// line should be printed.
unsigned getIndentLevel() const;
@@ -75,13 +119,13 @@ class LiveVariablePrinter {
// printed line, and return the index of that column.
// TODO: formatted_raw_ostream uses "column" to mean a number of characters
// since the last \n, and we use it to mean the number of slots in which we
- // put live variable lines. Pick a less overloaded word.
+ // put live element lines. Pick a less overloaded word.
unsigned moveToFirstVarColumn(formatted_raw_ostream &OS);
unsigned findFreeColumn();
public:
- LiveVariablePrinter(const MCRegisterInfo &MRI, const MCSubtargetInfo &STI)
+ LiveElementPrinter(const MCRegisterInfo &MRI, const MCSubtargetInfo &STI)
: ActiveCols(Column()), MRI(MRI), STI(STI) {}
void dump() const;
@@ -114,7 +158,7 @@ public:
/// otherwise this is being printed before it.
void printAfterOtherLine(formatted_raw_ostream &OS, bool AfterInst);
- /// Print any live variable range info needed to the right of a
+ /// Print any live element range info needed to the right of a
/// non-instruction line of disassembly. This is where we print the variable
/// names and expressions, with thin line-drawing characters connecting them
/// to the live range which starts at the next instruction. If MustPrint is
@@ -123,8 +167,13 @@ public:
/// earlier on this line.
void printBetweenInsts(formatted_raw_ostream &OS, bool MustPrint);
- /// Print the live variable ranges to the right of a disassembled instruction.
+ /// Print the live element ranges to the right of a disassembled instruction.
void printAfterInst(formatted_raw_ostream &OS);
+
+ /// Print a line to idenfity the start of a live element.
+ void printStartLine(formatted_raw_ostream &OS, object::SectionedAddress Addr);
+ /// Print a line to idenfity the end of a live element.
+ void printEndLine(formatted_raw_ostream &OS, object::SectionedAddress Addr);
};
class SourcePrinter {
@@ -144,12 +193,13 @@ protected:
private:
bool cacheSource(const DILineInfo &LineInfoFile);
- void printLines(formatted_raw_ostream &OS, const DILineInfo &LineInfo,
- StringRef Delimiter, LiveVariablePrinter &LVP);
+ void printLines(formatted_raw_ostream &OS, object::SectionedAddress Address,
+ const DILineInfo &LineInfo, StringRef Delimiter,
+ LiveElementPrinter &LEP);
void printSources(formatted_raw_ostream &OS, const DILineInfo &LineInfo,
StringRef ObjectFilename, StringRef Delimiter,
- LiveVariablePrinter &LVP);
+ LiveElementPrinter &LEP);
// Returns line source code corresponding to `LineInfo`.
// Returns empty string if source code cannot be found.
@@ -162,7 +212,7 @@ public:
virtual void printSourceLine(formatted_raw_ostream &OS,
object::SectionedAddress Address,
StringRef ObjectFilename,
- LiveVariablePrinter &LVP,
+ LiveElementPrinter &LEP,
StringRef Delimiter = "; ");
};
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 74eb903..0316c4b 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -348,7 +348,8 @@ static bool Wide;
std::string objdump::Prefix;
uint32_t objdump::PrefixStrip;
-DebugVarsFormat objdump::DbgVariables = DVDisabled;
+DebugFormat objdump::DbgVariables = DFDisabled;
+DebugFormat objdump::DbgInlinedFunctions = DFDisabled;
int objdump::DbgIndent = 52;
@@ -523,8 +524,8 @@ static const Target *getTarget(const ObjectFile *Obj) {
// Get the target specific parser.
std::string Error;
- const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple,
- Error);
+ const Target *TheTarget =
+ TargetRegistry::lookupTarget(ArchName, TheTriple, Error);
if (!TheTarget)
reportError(Obj->getFileName(), "can't find target: " + Error);
@@ -633,7 +634,7 @@ static bool isCSKYElf(const ObjectFile &Obj) {
}
static bool hasMappingSymbols(const ObjectFile &Obj) {
- return isArmElf(Obj) || isAArch64Elf(Obj) || isCSKYElf(Obj) ;
+ return isArmElf(Obj) || isAArch64Elf(Obj) || isCSKYElf(Obj);
}
static void printRelocation(formatted_raw_ostream &OS, StringRef FileName,
@@ -653,7 +654,7 @@ static void printRelocation(formatted_raw_ostream &OS, StringRef FileName,
static void printBTFRelocation(formatted_raw_ostream &FOS, llvm::BTFParser &BTF,
object::SectionedAddress Address,
- LiveVariablePrinter &LVP) {
+ LiveElementPrinter &LEP) {
const llvm::BTF::BPFFieldReloc *Reloc = BTF.findFieldReloc(Address);
if (!Reloc)
return;
@@ -664,7 +665,7 @@ static void printBTFRelocation(formatted_raw_ostream &FOS, llvm::BTFParser &BTF,
if (LeadingAddr)
FOS << format("%016" PRIx64 ": ", Address.Address + AdjustVMA);
FOS << "CO-RE " << Val;
- LVP.printAfterOtherLine(FOS, true);
+ LEP.printAfterOtherLine(FOS, true);
}
class PrettyPrinter {
@@ -675,10 +676,11 @@ public:
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
- LiveVariablePrinter &LVP) {
+ LiveElementPrinter &LEP) {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP);
- LVP.printBetweenInsts(OS, false);
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP);
+ LEP.printStartLine(OS, Address);
+ LEP.printBetweenInsts(OS, false);
printRawData(Bytes, Address.Address, OS, STI);
@@ -698,7 +700,7 @@ public:
const MCAsmInfo &MAI,
const MCSubtargetInfo &STI,
StringRef Comments,
- LiveVariablePrinter &LVP) {
+ LiveElementPrinter &LEP) {
do {
if (!Comments.empty()) {
// Emit a line of comments.
@@ -712,7 +714,7 @@ public:
FOS.PadToColumn(CommentColumn);
FOS << MAI.getCommentString() << ' ' << Comment;
}
- LVP.printAfterInst(FOS);
+ LEP.printAfterInst(FOS);
FOS << "\n";
} while (!Comments.empty());
FOS.flush();
@@ -757,10 +759,10 @@ public:
void emitPostInstructionInfo(formatted_raw_ostream &FOS, const MCAsmInfo &MAI,
const MCSubtargetInfo &STI, StringRef Comments,
- LiveVariablePrinter &LVP) override {
+ LiveElementPrinter &LEP) override {
// Hexagon does not write anything to the comment stream, so we can just
// print the separator.
- LVP.printAfterInst(FOS);
+ LEP.printAfterInst(FOS);
FOS << getInstructionSeparator();
FOS.flush();
if (ShouldClosePacket)
@@ -771,9 +773,9 @@ public:
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
- LiveVariablePrinter &LVP) override {
+ LiveElementPrinter &LEP) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP, "");
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP, "");
if (!MI) {
printLead(Bytes, Address.Address, OS);
OS << " <unknown>";
@@ -784,7 +786,7 @@ public:
StringRef Preamble = IsStartOfBundle ? " { " : " ";
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP, "");
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP, "");
printLead(Bytes, Address.Address, OS);
OS << Preamble;
std::string Buf;
@@ -845,9 +847,9 @@ public:
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
- LiveVariablePrinter &LVP) override {
+ LiveElementPrinter &LEP) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP);
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP);
if (MI) {
SmallString<40> InstStr;
@@ -866,10 +868,10 @@ public:
support::endian::read32<llvm::endianness::little>(Bytes.data()));
OS.indent(42);
} else {
- OS << format("\t.byte 0x%02" PRIx8, Bytes[0]);
- for (unsigned int i = 1; i < Bytes.size(); i++)
- OS << format(", 0x%02" PRIx8, Bytes[i]);
- OS.indent(55 - (6 * Bytes.size()));
+ OS << format("\t.byte 0x%02" PRIx8, Bytes[0]);
+ for (unsigned int i = 1; i < Bytes.size(); i++)
+ OS << format(", 0x%02" PRIx8, Bytes[i]);
+ OS.indent(55 - (6 * Bytes.size()));
}
}
@@ -880,7 +882,7 @@ public:
for (uint32_t D :
ArrayRef(reinterpret_cast<const support::little32_t *>(Bytes.data()),
Bytes.size() / 4))
- OS << format(" %08" PRIX32, D);
+ OS << format(" %08" PRIX32, D);
} else {
for (unsigned char B : Bytes)
OS << format(" %02" PRIX8, B);
@@ -898,9 +900,9 @@ public:
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
- LiveVariablePrinter &LVP) override {
+ LiveElementPrinter &LEP) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP);
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP);
if (LeadingAddr)
OS << format("%8" PRId64 ":", Address.Address / 8);
if (ShowRawInsn) {
@@ -921,10 +923,11 @@ public:
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
- LiveVariablePrinter &LVP) override {
+ LiveElementPrinter &LEP) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP);
- LVP.printBetweenInsts(OS, false);
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP);
+ LEP.printStartLine(OS, Address);
+ LEP.printBetweenInsts(OS, false);
size_t Start = OS.tell();
if (LeadingAddr)
@@ -975,10 +978,11 @@ public:
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
- LiveVariablePrinter &LVP) override {
+ LiveElementPrinter &LEP) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP);
- LVP.printBetweenInsts(OS, false);
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP);
+ LEP.printStartLine(OS, Address);
+ LEP.printBetweenInsts(OS, false);
size_t Start = OS.tell();
if (LeadingAddr)
@@ -1013,10 +1017,11 @@ public:
object::SectionedAddress Address, formatted_raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
StringRef ObjectFilename, std::vector<RelocationRef> *Rels,
- LiveVariablePrinter &LVP) override {
+ LiveElementPrinter &LEP) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, ObjectFilename, LVP);
- LVP.printBetweenInsts(OS, false);
+ SP->printSourceLine(OS, Address, ObjectFilename, LEP);
+ LEP.printStartLine(OS, Address);
+ LEP.printBetweenInsts(OS, false);
size_t Start = OS.tell();
if (LeadingAddr)
@@ -1057,7 +1062,7 @@ public:
RISCVPrettyPrinter RISCVPrettyPrinterInst;
PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {
- switch(Triple.getArch()) {
+ switch (Triple.getArch()) {
default:
return PrettyPrinterInst;
case Triple::hexagon:
@@ -1108,8 +1113,7 @@ private:
DisassemblerTarget::DisassemblerTarget(const Target *TheTarget, ObjectFile &Obj,
StringRef TripleName, StringRef MCPU,
SubtargetFeatures &Features)
- : TheTarget(TheTarget),
- Printer(&selectPrettyPrinter(Triple(TripleName))),
+ : TheTarget(TheTarget), Printer(&selectPrettyPrinter(Triple(TripleName))),
RegisterInfo(TheTarget->createMCRegInfo(TripleName)) {
if (!RegisterInfo)
reportError(Obj.getFileName(), "no register info for target " + TripleName);
@@ -1388,7 +1392,6 @@ static bool shouldAdjustVA(const SectionRef &Section) {
return false;
}
-
typedef std::pair<uint64_t, char> MappingSymbolPair;
static char getMappingSymbolKind(ArrayRef<MappingSymbolPair> MappingSymbols,
uint64_t Address) {
@@ -1416,8 +1419,7 @@ static uint64_t dumpARMELFData(uint64_t SectionAddr, uint64_t Index,
dumpBytes(Bytes.slice(Index, 4), OS);
AlignToInstStartColumn(Start, STI, OS);
OS << "\t.word\t"
- << format_hex(support::endian::read32(Bytes.data() + Index, Endian),
- 10);
+ << format_hex(support::endian::read32(Bytes.data() + Index, Endian), 10);
return 4;
}
if (Index + 2 <= End) {
@@ -1791,9 +1793,9 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
// STAB symbol's section field refers to a valid section index. Otherwise
// the symbol may error trying to load a section that does not exist.
DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
- uint8_t NType = (MachO->is64Bit() ?
- MachO->getSymbol64TableEntry(SymDRI).n_type:
- MachO->getSymbolTableEntry(SymDRI).n_type);
+ uint8_t NType =
+ (MachO->is64Bit() ? MachO->getSymbol64TableEntry(SymDRI).n_type
+ : MachO->getSymbolTableEntry(SymDRI).n_type);
if (NType & MachO::N_STAB)
continue;
}
@@ -1892,15 +1894,15 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
llvm::stable_sort(AbsoluteSymbols);
std::unique_ptr<DWARFContext> DICtx;
- LiveVariablePrinter LVP(*DT->Context->getRegisterInfo(), *DT->SubtargetInfo);
+ LiveElementPrinter LEP(*DT->Context->getRegisterInfo(), *DT->SubtargetInfo);
- if (DbgVariables != DVDisabled) {
+ if (DbgVariables != DFDisabled || DbgInlinedFunctions != DFDisabled) {
DICtx = DWARFContext::create(DbgObj);
for (const std::unique_ptr<DWARFUnit> &CU : DICtx->compile_units())
- LVP.addCompileUnit(CU->getUnitDIE(false));
+ LEP.addCompileUnit(CU->getUnitDIE(false));
}
- LLVM_DEBUG(LVP.dump());
+ LLVM_DEBUG(LEP.dump());
BBAddrMapInfo FullAddrMap;
auto ReadBBAddrMap = [&](std::optional<unsigned> SectionIndex =
@@ -2368,8 +2370,9 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
ThisBytes.size(),
DT->DisAsm->suggestBytesToSkip(ThisBytes, ThisAddr));
- LVP.update({Index, Section.getIndex()},
- {Index + Size, Section.getIndex()}, Index + Size != End);
+ LEP.update({ThisAddr, Section.getIndex()},
+ {ThisAddr + Size, Section.getIndex()},
+ Index + Size != End);
DT->InstPrinter->setCommentStream(CommentStream);
@@ -2377,7 +2380,7 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
*DT->InstPrinter, Disassembled ? &Inst : nullptr,
Bytes.slice(Index, Size),
{SectionAddr + Index + VMAAdjustment, Section.getIndex()}, FOS,
- "", *DT->SubtargetInfo, &SP, Obj.getFileName(), &Rels, LVP);
+ "", *DT->SubtargetInfo, &SP, Obj.getFileName(), &Rels, LEP);
DT->InstPrinter->setCommentStream(llvm::nulls());
@@ -2562,22 +2565,26 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
assert(DT->Context->getAsmInfo());
DT->Printer->emitPostInstructionInfo(FOS, *DT->Context->getAsmInfo(),
*DT->SubtargetInfo,
- CommentStream.str(), LVP);
+ CommentStream.str(), LEP);
Comments.clear();
if (BTF)
- printBTFRelocation(FOS, *BTF, {Index, Section.getIndex()}, LVP);
+ printBTFRelocation(FOS, *BTF, {Index, Section.getIndex()}, LEP);
if (InlineRelocs) {
while (findRel()) {
// When --adjust-vma is used, update the address printed.
printRelocation(FOS, Obj.getFileName(), *RelCur,
SectionAddr + RelOffset + VMAAdjustment, Is64Bits);
- LVP.printAfterOtherLine(FOS, true);
+ LEP.printAfterOtherLine(FOS, true);
++RelCur;
}
}
+ object::SectionedAddress NextAddr = {
+ SectionAddr + Index + VMAAdjustment + Size, Section.getIndex()};
+ LEP.printEndLine(FOS, NextAddr);
+
Index += Size;
}
}
@@ -2869,7 +2876,8 @@ void objdump::printSectionContents(const ObjectFile *Obj) {
continue;
}
- StringRef Contents = unwrapOrError(Section.getContents(), Obj->getFileName());
+ StringRef Contents =
+ unwrapOrError(Section.getContents(), Obj->getFileName());
// Dump out the content as hex and printable ascii characters.
for (std::size_t Addr = 0, End = Contents.size(); Addr < End; Addr += 16) {
@@ -3293,8 +3301,8 @@ static bool shouldWarnForInvalidStartStopAddress(ObjectFile *Obj) {
return false;
}
-static void checkForInvalidStartStopAddress(ObjectFile *Obj,
- uint64_t Start, uint64_t Stop) {
+static void checkForInvalidStartStopAddress(ObjectFile *Obj, uint64_t Start,
+ uint64_t Stop) {
if (!shouldWarnForInvalidStartStopAddress(Obj))
return;
@@ -3617,13 +3625,25 @@ static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
Prefix = InputArgs.getLastArgValue(OBJDUMP_prefix).str();
parseIntArg(InputArgs, OBJDUMP_prefix_strip, PrefixStrip);
if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_debug_vars_EQ)) {
- DbgVariables = StringSwitch<DebugVarsFormat>(A->getValue())
- .Case("ascii", DVASCII)
- .Case("unicode", DVUnicode)
- .Default(DVInvalid);
- if (DbgVariables == DVInvalid)
+ DbgVariables = StringSwitch<DebugFormat>(A->getValue())
+ .Case("ascii", DFASCII)
+ .Case("unicode", DFUnicode)
+ .Default(DFInvalid);
+ if (DbgVariables == DFInvalid)
+ invalidArgValue(A);
+ }
+
+ if (const opt::Arg *A =
+ InputArgs.getLastArg(OBJDUMP_debug_inlined_funcs_EQ)) {
+ DbgInlinedFunctions = StringSwitch<DebugFormat>(A->getValue())
+ .Case("ascii", DFASCII)
+ .Case("limits-only", DFLimitsOnly)
+ .Case("unicode", DFUnicode)
+ .Default(DFInvalid);
+ if (DbgInlinedFunctions == DFInvalid)
invalidArgValue(A);
}
+
if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_disassembler_color_EQ)) {
DisassemblyColor = StringSwitch<ColorOutput>(A->getValue())
.Case("on", ColorOutput::Enable)
@@ -3634,7 +3654,7 @@ static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
invalidArgValue(A);
}
- parseIntArg(InputArgs, OBJDUMP_debug_vars_indent_EQ, DbgIndent);
+ parseIntArg(InputArgs, OBJDUMP_debug_indent_EQ, DbgIndent);
parseMachOOptions(InputArgs);
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h
index 25d9c1e..ce06429 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -40,11 +40,12 @@ class XCOFFObjectFile;
namespace objdump {
-enum DebugVarsFormat { DVDisabled, DVUnicode, DVASCII, DVInvalid };
+enum DebugFormat { DFASCII, DFDisabled, DFInvalid, DFLimitsOnly, DFUnicode };
extern bool ArchiveHeaders;
extern int DbgIndent;
-extern DebugVarsFormat DbgVariables;
+extern DebugFormat DbgVariables;
+extern DebugFormat DbgInlinedFunctions;
extern bool Demangle;
extern bool Disassemble;
extern bool DisassembleAll;
@@ -126,7 +127,7 @@ void printSectionContents(const object::ObjectFile *O);
void reportWarning(const Twine &Message, StringRef File);
template <typename T, typename... Ts>
-T unwrapOrError(Expected<T> EO, Ts &&... Args) {
+T unwrapOrError(Expected<T> EO, Ts &&...Args) {
if (EO)
return std::move(*EO);
reportError(EO.takeError(), std::forward<Ts>(Args)...);
diff --git a/llvm/tools/llvm-rc/llvm-rc.cpp b/llvm/tools/llvm-rc/llvm-rc.cpp
index 7362154..f623342 100644
--- a/llvm/tools/llvm-rc/llvm-rc.cpp
+++ b/llvm/tools/llvm-rc/llvm-rc.cpp
@@ -201,7 +201,7 @@ std::string getMingwTriple() {
Triple T(sys::getDefaultTargetTriple());
if (!isUsableArch(T.getArch()))
T.setArch(getDefaultFallbackArch());
- if (T.isWindowsGNUEnvironment())
+ if (T.isOSCygMing())
return T.str();
// Write out the literal form of the vendor/env here, instead of
// constructing them with enum values (which end up with them in
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index dce8e60..96e0a634 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -412,10 +412,19 @@ const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = {
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE),
};
+// clang-format off
static const EnumEntry<COFF::ExtendedDLLCharacteristics>
PEExtendedDLLCharacteristics[] = {
- LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_1 ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_2 ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_FORWARD_CFI_COMPAT ),
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE ),
};
+// clang-format on
static const EnumEntry<COFF::SectionCharacteristics>
ImageSectionCharacteristics[] = {
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index ccc64fe..94ce386 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -30,6 +30,7 @@
#include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/BinaryFormat/MsgPackDocument.h"
+#include "llvm/BinaryFormat/SFrame.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ELF.h"
@@ -38,6 +39,7 @@
#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/RelocationResolver.h"
+#include "llvm/Object/SFrameParser.h"
#include "llvm/Object/StackMapParser.h"
#include "llvm/Support/AArch64AttributeParser.h"
#include "llvm/Support/AMDGPUMetadata.h"
@@ -225,6 +227,8 @@ public:
void printArchSpecificInfo() override;
void printStackMap() const override;
void printMemtag() override;
+ void printSectionsAsSFrame(ArrayRef<std::string> Sections) override;
+
ArrayRef<uint8_t> getMemtagGlobalsSectionContents(uint64_t ExpectedAddr);
// Hash histogram shows statistics of how efficient the hash was for the
@@ -420,6 +424,9 @@ protected:
ArrayRef<Elf_Word> getShndxTable(const Elf_Shdr *Symtab) const;
+ void printSFrameHeader(const SFrameParser<ELFT::Endianness> &Parser);
+ void printSFrameFDEs(const SFrameParser<ELFT::Endianness> &Parser);
+
private:
mutable SmallVector<std::optional<VersionEntry>, 0> VersionMap;
};
@@ -1083,26 +1090,25 @@ const EnumEntry<unsigned> ElfObjectFileType[] = {
};
const EnumEntry<unsigned> ElfOSABI[] = {
- {"SystemV", "UNIX - System V", ELF::ELFOSABI_NONE},
- {"HPUX", "UNIX - HP-UX", ELF::ELFOSABI_HPUX},
- {"NetBSD", "UNIX - NetBSD", ELF::ELFOSABI_NETBSD},
- {"GNU/Linux", "UNIX - GNU", ELF::ELFOSABI_LINUX},
- {"GNU/Hurd", "GNU/Hurd", ELF::ELFOSABI_HURD},
- {"Solaris", "UNIX - Solaris", ELF::ELFOSABI_SOLARIS},
- {"AIX", "UNIX - AIX", ELF::ELFOSABI_AIX},
- {"IRIX", "UNIX - IRIX", ELF::ELFOSABI_IRIX},
- {"FreeBSD", "UNIX - FreeBSD", ELF::ELFOSABI_FREEBSD},
- {"TRU64", "UNIX - TRU64", ELF::ELFOSABI_TRU64},
- {"Modesto", "Novell - Modesto", ELF::ELFOSABI_MODESTO},
- {"OpenBSD", "UNIX - OpenBSD", ELF::ELFOSABI_OPENBSD},
- {"OpenVMS", "VMS - OpenVMS", ELF::ELFOSABI_OPENVMS},
- {"NSK", "HP - Non-Stop Kernel", ELF::ELFOSABI_NSK},
- {"AROS", "AROS", ELF::ELFOSABI_AROS},
- {"FenixOS", "FenixOS", ELF::ELFOSABI_FENIXOS},
- {"CloudABI", "CloudABI", ELF::ELFOSABI_CLOUDABI},
- {"CUDA", "NVIDIA - CUDA", ELF::ELFOSABI_CUDA},
- {"Standalone", "Standalone App", ELF::ELFOSABI_STANDALONE}
-};
+ {"SystemV", "UNIX - System V", ELF::ELFOSABI_NONE},
+ {"HPUX", "UNIX - HP-UX", ELF::ELFOSABI_HPUX},
+ {"NetBSD", "UNIX - NetBSD", ELF::ELFOSABI_NETBSD},
+ {"GNU/Linux", "UNIX - GNU", ELF::ELFOSABI_LINUX},
+ {"GNU/Hurd", "GNU/Hurd", ELF::ELFOSABI_HURD},
+ {"Solaris", "UNIX - Solaris", ELF::ELFOSABI_SOLARIS},
+ {"AIX", "UNIX - AIX", ELF::ELFOSABI_AIX},
+ {"IRIX", "UNIX - IRIX", ELF::ELFOSABI_IRIX},
+ {"FreeBSD", "UNIX - FreeBSD", ELF::ELFOSABI_FREEBSD},
+ {"TRU64", "UNIX - TRU64", ELF::ELFOSABI_TRU64},
+ {"Modesto", "Novell - Modesto", ELF::ELFOSABI_MODESTO},
+ {"OpenBSD", "UNIX - OpenBSD", ELF::ELFOSABI_OPENBSD},
+ {"OpenVMS", "VMS - OpenVMS", ELF::ELFOSABI_OPENVMS},
+ {"NSK", "HP - Non-Stop Kernel", ELF::ELFOSABI_NSK},
+ {"AROS", "AROS", ELF::ELFOSABI_AROS},
+ {"FenixOS", "FenixOS", ELF::ELFOSABI_FENIXOS},
+ {"CloudABI", "CloudABI", ELF::ELFOSABI_CLOUDABI},
+ {"CUDA", "NVIDIA - CUDA", ELF::ELFOSABI_CUDA},
+ {"Standalone", "Standalone App", ELF::ELFOSABI_STANDALONE}};
const EnumEntry<unsigned> AMDGPUElfOSABI[] = {
{"AMDGPU_HSA", "AMDGPU - HSA", ELF::ELFOSABI_AMDGPU_HSA},
@@ -1667,16 +1673,17 @@ const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion4[] = {
};
const EnumEntry<unsigned> ElfHeaderNVPTXFlags[] = {
- ENUM_ENT(EF_CUDA_SM20, "sm_20"), ENUM_ENT(EF_CUDA_SM21, "sm_21"),
- ENUM_ENT(EF_CUDA_SM30, "sm_30"), ENUM_ENT(EF_CUDA_SM32, "sm_32"),
- ENUM_ENT(EF_CUDA_SM35, "sm_35"), ENUM_ENT(EF_CUDA_SM37, "sm_37"),
- ENUM_ENT(EF_CUDA_SM50, "sm_50"), ENUM_ENT(EF_CUDA_SM52, "sm_52"),
- ENUM_ENT(EF_CUDA_SM53, "sm_53"), ENUM_ENT(EF_CUDA_SM60, "sm_60"),
- ENUM_ENT(EF_CUDA_SM61, "sm_61"), ENUM_ENT(EF_CUDA_SM62, "sm_62"),
- ENUM_ENT(EF_CUDA_SM70, "sm_70"), ENUM_ENT(EF_CUDA_SM72, "sm_72"),
- ENUM_ENT(EF_CUDA_SM75, "sm_75"), ENUM_ENT(EF_CUDA_SM80, "sm_80"),
- ENUM_ENT(EF_CUDA_SM86, "sm_86"), ENUM_ENT(EF_CUDA_SM87, "sm_87"),
- ENUM_ENT(EF_CUDA_SM89, "sm_89"), ENUM_ENT(EF_CUDA_SM90, "sm_90"),
+ ENUM_ENT(EF_CUDA_SM20, "sm_20"), ENUM_ENT(EF_CUDA_SM21, "sm_21"),
+ ENUM_ENT(EF_CUDA_SM30, "sm_30"), ENUM_ENT(EF_CUDA_SM32, "sm_32"),
+ ENUM_ENT(EF_CUDA_SM35, "sm_35"), ENUM_ENT(EF_CUDA_SM37, "sm_37"),
+ ENUM_ENT(EF_CUDA_SM50, "sm_50"), ENUM_ENT(EF_CUDA_SM52, "sm_52"),
+ ENUM_ENT(EF_CUDA_SM53, "sm_53"), ENUM_ENT(EF_CUDA_SM60, "sm_60"),
+ ENUM_ENT(EF_CUDA_SM61, "sm_61"), ENUM_ENT(EF_CUDA_SM62, "sm_62"),
+ ENUM_ENT(EF_CUDA_SM70, "sm_70"), ENUM_ENT(EF_CUDA_SM72, "sm_72"),
+ ENUM_ENT(EF_CUDA_SM75, "sm_75"), ENUM_ENT(EF_CUDA_SM80, "sm_80"),
+ ENUM_ENT(EF_CUDA_SM86, "sm_86"), ENUM_ENT(EF_CUDA_SM87, "sm_87"),
+ ENUM_ENT(EF_CUDA_SM89, "sm_89"), ENUM_ENT(EF_CUDA_SM90, "sm_90"),
+ ENUM_ENT(EF_CUDA_SM100, "sm_100"), ENUM_ENT(EF_CUDA_SM120, "sm_120"),
};
const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = {
@@ -3651,10 +3658,16 @@ template <class ELFT> void GNUELFDumper<ELFT>::printFileHeaders() {
else if (e.e_machine == EM_XTENSA)
ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderXtensaFlags),
unsigned(ELF::EF_XTENSA_MACH));
- else if (e.e_machine == EM_CUDA)
+ else if (e.e_machine == EM_CUDA) {
ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderNVPTXFlags),
unsigned(ELF::EF_CUDA_SM));
- else if (e.e_machine == EM_AMDGPU) {
+ if (e.e_ident[ELF::EI_ABIVERSION] == ELF::ELFABIVERSION_CUDA_V1 &&
+ (e.e_flags & ELF::EF_CUDA_ACCELERATORS_V1))
+ ElfFlags += "a";
+ else if (e.e_ident[ELF::EI_ABIVERSION] == ELF::ELFABIVERSION_CUDA_V2 &&
+ (e.e_flags & ELF::EF_CUDA_ACCELERATORS))
+ ElfFlags += "a";
+ } else if (e.e_machine == EM_AMDGPU) {
switch (e.e_ident[ELF::EI_ABIVERSION]) {
default:
break;
@@ -6429,6 +6442,121 @@ template <typename ELFT> void ELFDumper<ELFT>::printMemtag() {
printMemtag(DynamicEntries, AndroidNoteDesc, GlobalDescriptors);
}
+template <typename ELFT>
+void ELFDumper<ELFT>::printSFrameHeader(
+ const SFrameParser<ELFT::Endianness> &Parser) {
+ DictScope HeaderScope(W, "Header");
+
+ const sframe::Preamble<ELFT::Endianness> &Preamble = Parser.getPreamble();
+ W.printHex("Magic", Preamble.Magic.value());
+ W.printEnum("Version", Preamble.Version.value(), sframe::getVersions());
+ W.printFlags("Flags", Preamble.Flags.value(), sframe::getFlags());
+
+ const sframe::Header<ELFT::Endianness> &Header = Parser.getHeader();
+ W.printEnum("ABI", Header.ABIArch.value(), sframe::getABIs());
+
+ W.printNumber(("CFA fixed FP offset" +
+ Twine(Parser.usesFixedFPOffset() ? "" : " (unused)"))
+ .str(),
+ Header.CFAFixedFPOffset.value());
+
+ W.printNumber(("CFA fixed RA offset" +
+ Twine(Parser.usesFixedRAOffset() ? "" : " (unused)"))
+ .str(),
+ Header.CFAFixedRAOffset.value());
+
+ W.printNumber("Auxiliary header length", Header.AuxHdrLen.value());
+ W.printNumber("Num FDEs", Header.NumFDEs.value());
+ W.printNumber("Num FREs", Header.NumFREs.value());
+ W.printNumber("FRE subsection length", Header.FRELen.value());
+ W.printNumber("FDE subsection offset", Header.FDEOff.value());
+ W.printNumber("FRE subsection offset", Header.FREOff.value());
+
+ if (Expected<ArrayRef<uint8_t>> Aux = Parser.getAuxHeader())
+ W.printHexList("Auxiliary header", *Aux);
+ else
+ reportWarning(Aux.takeError(), FileName);
+}
+
+template <typename ELFT>
+void ELFDumper<ELFT>::printSFrameFDEs(
+ const SFrameParser<ELFT::Endianness> &Parser) {
+ typename SFrameParser<ELFT::Endianness>::FDERange FDEs;
+ if (Error Err = Parser.fdes().moveInto(FDEs)) {
+ reportWarning(std::move(Err), FileName);
+ return;
+ }
+
+ ListScope IndexScope(W, "Function Index");
+ for (auto It = FDEs.begin(); It != FDEs.end(); ++It) {
+ DictScope FDEScope(
+ W,
+ formatv("FuncDescEntry [{0}]", std::distance(FDEs.begin(), It)).str());
+
+ W.printHex("PC", Parser.getAbsoluteStartAddress(It));
+ W.printHex("Size", It->Size);
+ W.printHex("Start FRE Offset", It->StartFREOff);
+ W.printNumber("Num FREs", It->NumFREs);
+
+ {
+ DictScope InfoScope(W, "Info");
+ W.printEnum("FRE Type", It->getFREType(), sframe::getFRETypes());
+ W.printEnum("FDE Type", It->getFDEType(), sframe::getFDETypes());
+ switch (Parser.getHeader().ABIArch) {
+ case sframe::ABI::AArch64EndianBig:
+ case sframe::ABI::AArch64EndianLittle:
+ W.printEnum("PAuth Key", sframe::AArch64PAuthKey(It->getPAuthKey()),
+ sframe::getAArch64PAuthKeys());
+ break;
+ case sframe::ABI::AMD64EndianLittle:
+ // unused
+ break;
+ }
+
+ W.printHex("Raw", It->Info);
+ }
+
+ W.printHex(
+ ("Repetitive block size" +
+ Twine(It->getFDEType() == sframe::FDEType::PCMask ? "" : " (unused)"))
+ .str(),
+ It->RepSize);
+
+ W.printHex("Padding2", It->Padding2);
+ }
+}
+
+template <typename ELFT>
+void ELFDumper<ELFT>::printSectionsAsSFrame(ArrayRef<std::string> Sections) {
+ constexpr endianness E = ELFT::Endianness;
+ for (object::SectionRef Section :
+ getSectionRefsByNameOrIndex(ObjF, Sections)) {
+ // Validity of sections names checked in getSectionRefsByNameOrIndex.
+ StringRef SectionName = cantFail(Section.getName());
+
+ DictScope SectionScope(W,
+ formatv("SFrame section '{0}'", SectionName).str());
+
+ StringRef SectionContent;
+ if (Error Err = Section.getContents().moveInto(SectionContent)) {
+ reportWarning(std::move(Err), FileName);
+ continue;
+ }
+
+ Expected<object::SFrameParser<E>> Parser = object::SFrameParser<E>::create(
+ arrayRefFromStringRef(SectionContent), Section.getAddress());
+ if (!Parser) {
+ reportWarning(createError("invalid sframe section: " +
+ toString(Parser.takeError())),
+ FileName);
+ continue;
+ }
+
+ printSFrameHeader(*Parser);
+ printSFrameFDEs(*Parser);
+ }
+}
+
template <class ELFT> void GNUELFDumper<ELFT>::printELFLinkerOptions() {
OS << "printELFLinkerOptions not implemented!\n";
}
diff --git a/llvm/tools/llvm-readobj/ObjDumper.cpp b/llvm/tools/llvm-readobj/ObjDumper.cpp
index 1a535ed..bd670ae 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.cpp
+++ b/llvm/tools/llvm-readobj/ObjDumper.cpp
@@ -102,9 +102,9 @@ void ObjDumper::printFileSummary(StringRef FileStr, object::ObjectFile &Obj,
this->printLoadName();
}
-static std::vector<object::SectionRef>
-getSectionRefsByNameOrIndex(const object::ObjectFile &Obj,
- ArrayRef<std::string> Sections) {
+std::vector<object::SectionRef>
+ObjDumper::getSectionRefsByNameOrIndex(const object::ObjectFile &Obj,
+ ArrayRef<std::string> Sections) {
std::vector<object::SectionRef> Ret;
std::map<std::string, bool, std::less<>> SecNames;
std::map<unsigned, bool> SecIndices;
diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index a76afbe..1dc2966 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -139,6 +139,7 @@ public:
virtual void printSectionDetails() {}
virtual void printArchSpecificInfo() {}
virtual void printMemtag() {}
+ virtual void printSectionsAsSFrame(ArrayRef<std::string> Sections) {}
// Only implemented for PE/COFF.
virtual void printCOFFImports() { }
@@ -190,6 +191,10 @@ public:
protected:
ScopedPrinter &W;
+ static std::vector<object::SectionRef>
+ getSectionRefsByNameOrIndex(const object::ObjectFile &Obj,
+ ArrayRef<std::string> Sections);
+
private:
virtual void printSymbols(bool ExtraSymInfo) {}
virtual void printSymbols(std::optional<SymbolComparator> Comp) {}
diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td
index f95461a..48d43cc 100644
--- a/llvm/tools/llvm-readobj/Opts.td
+++ b/llvm/tools/llvm-readobj/Opts.td
@@ -62,6 +62,8 @@ def memtag : FF<"memtag", "Display memory tagging metadata (modes, Android notes
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>;
+def sframe_EQ : Joined<["--"], "sframe=">, HelpText<"Display SFrame section <name>">, MetaVarName<"<name>">, Group<grp_elf>;
+def sframe: FF<"sframe", "Alias for --sframe=.sframe">, Alias<sframe_EQ>, AliasArgs<[".sframe"]>, Group<grp_elf>;
def version_info : FF<"version-info", "Display version sections">, Group<grp_elf>;
// Mach-O specific options.
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index 1231c02..4c84ed7 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -137,6 +137,7 @@ static bool NeededLibraries;
static bool Notes;
static bool ProgramHeaders;
static bool SectionGroups;
+static std::vector<std::string> SFrame;
static bool VersionInfo;
// Mach-O specific options.
@@ -275,6 +276,7 @@ static void parseOptions(const opt::InputArgList &Args) {
opts::PrettyPrint = Args.hasArg(OPT_pretty_print);
opts::ProgramHeaders = Args.hasArg(OPT_program_headers);
opts::SectionGroups = Args.hasArg(OPT_section_groups);
+ opts::SFrame = Args.getAllArgValues(OPT_sframe_EQ);
if (Arg *A = Args.getLastArg(OPT_sort_symbols_EQ)) {
for (StringRef KeyStr : llvm::split(A->getValue(), ",")) {
SortSymbolKeyTy KeyType = StringSwitch<SortSymbolKeyTy>(KeyStr)
@@ -478,6 +480,8 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
Dumper->printNotes();
if (opts::Memtag)
Dumper->printMemtag();
+ if (!opts::SFrame.empty())
+ Dumper->printSectionsAsSFrame(opts::SFrame);
}
if (Obj.isCOFF()) {
if (opts::COFFImports)
diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp
index 7d168a6..b9b8929 100644
--- a/llvm/tools/opt/NewPMDriver.cpp
+++ b/llvm/tools/opt/NewPMDriver.cpp
@@ -40,6 +40,7 @@
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
#include "llvm/Transforms/Scalar/LoopPassManager.h"
#include "llvm/Transforms/Utils/Debugify.h"
+#include "llvm/Transforms/Utils/ProfileVerify.h"
using namespace llvm;
using namespace opt_tool;
@@ -356,7 +357,7 @@ bool llvm::runPassPipeline(
OutputKind OK, VerifierKind VK, bool ShouldPreserveAssemblyUseListOrder,
bool ShouldPreserveBitcodeUseListOrder, bool EmitSummaryIndex,
bool EmitModuleHash, bool EnableDebugify, bool VerifyDIPreserve,
- bool UnifiedLTO) {
+ bool EnableProfcheck, bool UnifiedLTO) {
auto FS = vfs::getRealFileSystem();
std::optional<PGOOptions> P;
switch (PGOKindFlag) {
@@ -487,7 +488,8 @@ bool llvm::runPassPipeline(
if (VerifyDIPreserve)
MPM.addPass(NewPMDebugifyPass(DebugifyMode::OriginalDebugInfo, "",
&DebugInfoBeforePass));
-
+ if (EnableProfcheck)
+ MPM.addPass(createModuleToFunctionPassAdaptor(ProfileInjectorPass()));
// Add passes according to the -passes options.
if (!PassPipeline.empty()) {
if (auto Err = PB.parsePassPipeline(MPM, PassPipeline)) {
@@ -504,6 +506,8 @@ bool llvm::runPassPipeline(
MPM.addPass(NewPMCheckDebugifyPass(
false, "", nullptr, DebugifyMode::OriginalDebugInfo,
&DebugInfoBeforePass, VerifyDIPreserveExport));
+ if (EnableProfcheck)
+ MPM.addPass(createModuleToFunctionPassAdaptor(ProfileVerifierPass()));
// Add any relevant output pass at the end of the pipeline.
switch (OK) {
diff --git a/llvm/tools/opt/NewPMDriver.h b/llvm/tools/opt/NewPMDriver.h
index 2daae57..6c21d6c 100644
--- a/llvm/tools/opt/NewPMDriver.h
+++ b/llvm/tools/opt/NewPMDriver.h
@@ -75,7 +75,7 @@ bool runPassPipeline(
bool ShouldPreserveAssemblyUseListOrder,
bool ShouldPreserveBitcodeUseListOrder, bool EmitSummaryIndex,
bool EmitModuleHash, bool EnableDebugify, bool VerifyDIPreserve,
- bool UnifiedLTO = false);
+ bool EnableProfcheck, bool UnifiedLTO = false);
} // namespace llvm
#endif
diff --git a/llvm/tools/opt/optdriver.cpp b/llvm/tools/opt/optdriver.cpp
index 892b63b..4a3b058 100644
--- a/llvm/tools/opt/optdriver.cpp
+++ b/llvm/tools/opt/optdriver.cpp
@@ -217,6 +217,15 @@ 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> EnableProfileVerification(
+ "enable-profcheck",
+#if defined(LLVM_ENABLE_PROFCHECK)
+ cl::init(true),
+#else
+ cl::init(false),
+#endif
+ cl::desc("Start the pipeline with prof-inject and end it with prof-check"));
+
static cl::opt<std::string> ClDataLayout("data-layout",
cl::desc("data layout string to use"),
cl::value_desc("layout-string"),
@@ -746,7 +755,8 @@ extern "C" int optMain(
RemarksFile.get(), Pipeline, PluginList, PassBuilderCallbacks,
OK, VK, PreserveAssemblyUseListOrder,
PreserveBitcodeUseListOrder, EmitSummaryIndex, EmitModuleHash,
- EnableDebugify, VerifyDebugInfoPreserve, UnifiedLTO)
+ EnableDebugify, VerifyDebugInfoPreserve,
+ EnableProfileVerification, UnifiedLTO)
? 0
: 1;
}
diff --git a/llvm/tools/spirv-tools/CMakeLists.txt b/llvm/tools/spirv-tools/CMakeLists.txt
index c2c0f3e..5db7aec 100644
--- a/llvm/tools/spirv-tools/CMakeLists.txt
+++ b/llvm/tools/spirv-tools/CMakeLists.txt
@@ -5,10 +5,6 @@ if (NOT LLVM_INCLUDE_SPIRV_TOOLS_TESTS)
return()
endif ()
-if (NOT "SPIRV" IN_LIST LLVM_TARGETS_TO_BUILD)
- message(FATAL_ERROR "Building SPIRV-Tools tests is unsupported without the SPIR-V target")
-endif ()
-
# SPIRV_DIS, SPIRV_VAL, SPIRV_AS and SPIRV_LINK variables can be used to provide paths to existing
# spirv-dis, spirv-val, spirv-as, and spirv-link binaries, respectively. Otherwise, build them from
# SPIRV-Tools source.