[llvm] [llvm-exegesis] Debug generated disassembly (PR #142540)
Lakshay Kumar via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 3 01:58:59 PDT 2025
================
@@ -588,6 +594,99 @@ class SubProcessFunctionExecutorImpl
const std::optional<int> BenchmarkProcessCPU;
};
#endif // __linux__
+
+// Helper function to print generated assembly snippets
+void printGeneratedAssembly(
+ const std::vector<std::pair<std::string, std::pair<uint64_t, std::string>>>
+ &Instructions,
+ bool Preview, size_t PreviewFirst = 10, size_t PreviewLast = 3) {
+ dbgs() << "```\n";
+ size_t N = Instructions.size();
+ // Print first "PreviewFirst" lines or all if less
+ for (size_t i = 0; i < std::min(size_t(PreviewFirst), N); ++i) {
+ dbgs() << format_hex_no_prefix(Instructions[i].second.first, 0) << ":\t"
+ << Instructions[i].second.second << Instructions[i].first << '\n';
+ }
+ if (N > (PreviewFirst + PreviewLast)) {
+ if (Preview) {
+ dbgs() << "...\t(" << (N - PreviewFirst - PreviewLast)
+ << " more instructions)\n";
+ } else {
+ // Print all middle lines
+ for (size_t i = PreviewFirst; i < N - PreviewLast; ++i) {
+ dbgs() << format_hex_no_prefix(Instructions[i].second.first, 0) << ":\t"
+ << Instructions[i].second.second << Instructions[i].first
+ << '\n';
+ }
+ }
+ // Print last "PreviewLast" lines
+ for (size_t i = N - PreviewLast; i < N; ++i) {
+ dbgs() << format_hex_no_prefix(Instructions[i].second.first, 0) << ":\t"
+ << Instructions[i].second.second << Instructions[i].first << '\n';
+ }
+ }
+ dbgs() << "```\n";
+}
+
+// Function to extract and print assembly from snippet
+void printAssembledSnippet(const LLVMState &State,
+ const SmallString<0> &Snippet) {
+ // Extract the actual function bytes from the object file
+ std::vector<uint8_t> FunctionBytes;
+ if (auto Err = getBenchmarkFunctionBytes(Snippet, FunctionBytes)) {
+ dbgs() << "Failed to extract function bytes: " << toString(std::move(Err))
+ << "\n";
+ return;
+ }
+
+ DisassemblerHelper DisHelper(State);
+ ArrayRef<uint8_t> Bytes(FunctionBytes);
+
+ // Decode all instructions first
+ std::vector<std::pair<std::string, std::pair<uint64_t, std::string>>>
+ Instructions;
+ uint64_t Address = 0;
+
+ while (!Bytes.empty()) {
+ MCInst Inst;
+ uint64_t Size;
+ if (DisHelper.decodeInst(Inst, Size, Bytes)) {
+ // Format instruction text
+ std::string InstStr;
+ raw_string_ostream OS(InstStr);
+ DisHelper.printInst(&Inst, OS);
+
+ // Create hex string for this instruction (big-endian order)
+ std::string HexStr;
+ raw_string_ostream HexOS(HexStr);
+ for (int i = Size - 1; i >= 0; --i) {
+ HexOS << format_hex_no_prefix(Bytes[i], 2);
+ }
+
+ Instructions.push_back({OS.str(), {Address, HexOS.str()}});
+ Bytes = Bytes.slice(Size);
+ Address += Size;
+ } else {
+ Instructions.push_back({"<decode error>", {Address, ""}});
+ break;
+ }
+ }
+
+ // Preview generated assembly snippet
+ {
+#undef DEBUG_TYPE
+#define DEBUG_TYPE "preview-gen-assembly"
+ LLVM_DEBUG(dbgs() << "Generated assembly snippet:\n");
----------------
lakshayk-nv wrote:
Yes, You are correct about LLVM_DEBUG not executing in release mode.
I double checked, we can get output in stream when assertion are on for release mode i.e.
```
cmake -G Ninja -S ../llvm -B . -DLLVM_ENABLE_PROJECTS="clang" -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=ON
```
But, Not with assertion on.
Thus, we would potentially require to introduce a flag instead.
My idea is to have argument `--print-gen-assembly=<#>`
`#=-1` : prints all the line,
`#=10` : prints initial "10" lines, Resulting in truncated middle part with fixed arbitrary number of ending line like 3.
https://github.com/llvm/llvm-project/pull/142540
More information about the llvm-commits
mailing list