2121#include " llvm/ADT/Twine.h"
2222#include " llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
2323#include " llvm/MC/TargetRegistry.h"
24+ #include " llvm/Support/CommandLine.h"
2425#include " llvm/Support/CrashRecoveryContext.h"
2526#include " llvm/Support/Debug.h"
2627#include " llvm/Support/Error.h"
5960namespace llvm {
6061namespace exegesis {
6162
63+ static cl::opt<int > PrintGenAssembly (
64+ " print-gen-assembly" , cl::Optional, cl::init(0 ),
65+ cl::desc(" Print generated assembly snippets. -1 prints all lines, "
66+ " positive N prints first N lines with truncated middle part" ),
67+ cl::cat(BenchmarkOptions));
68+
6269BenchmarkRunner::BenchmarkRunner (const LLVMState &State, Benchmark::ModeE Mode,
6370 BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
6471 ExecutionModeE ExecutionMode,
@@ -595,35 +602,36 @@ class SubProcessFunctionExecutorImpl
595602};
596603#endif // __linux__
597604
605+ // Structure to hold instruction information for assembly printing
606+ struct InstructionInfo {
607+ std::string Text;
608+ uint64_t Address;
609+ std::string HexBytes;
610+ };
611+
598612// Helper function to print generated assembly snippets
599- void printGeneratedAssembly (
600- const std::vector<std::pair<std::string, std::pair<uint64_t , std::string>>>
601- &Instructions,
602- bool Preview, size_t PreviewFirst = 10 , size_t PreviewLast = 3 ) {
603- dbgs () << " ```\n " ;
604- size_t N = Instructions.size ();
605- // Print first "PreviewFirst" lines or all if less
606- for (size_t i = 0 ; i < std::min (size_t (PreviewFirst), N); ++i)
607- dbgs () << format_hex_no_prefix (Instructions[i].second .first , 0 ) << " :\t "
608- << Instructions[i].second .second << Instructions[i].first << ' \n ' ;
609-
610- if (N > (PreviewFirst + PreviewLast)) {
611- if (Preview)
612- dbgs () << " ...\t (" << (N - PreviewFirst - PreviewLast)
613- << " more instructions)\n " ;
614- else {
615- // Print all middle lines
616- for (size_t i = PreviewFirst; i < N - PreviewLast; ++i)
617- dbgs () << format_hex_no_prefix (Instructions[i].second .first , 0 ) << " :\t "
618- << Instructions[i].second .second << Instructions[i].first
619- << ' \n ' ;
620- }
621- // Print last "PreviewLast" lines
622- for (size_t i = N - PreviewLast; i < N; ++i)
623- dbgs () << format_hex_no_prefix (Instructions[i].second .first , 0 ) << " :\t "
624- << Instructions[i].second .second << Instructions[i].first << ' \n ' ;
625- }
626- dbgs () << " ```\n " ;
613+ void printInstructions (const std::vector<InstructionInfo> &Instructions,
614+ int InitialLinesCount, int LastLinesCount) {
615+ int N = Instructions.size ();
616+ outs () << " Generated assembly snippet:\n ```\n " ;
617+
618+ // Print initial lines
619+ for (int i = 0 ; i < InitialLinesCount; ++i)
620+ outs () << format_hex_no_prefix (Instructions[i].Address , 0 ) << " :\t "
621+ << Instructions[i].HexBytes << Instructions[i].Text << ' \n ' ;
622+
623+ // Show truncation message if needed
624+ int SkippedInstructions = N - InitialLinesCount - LastLinesCount;
625+ if (SkippedInstructions > 0 )
626+ outs () << " ...\t (" << SkippedInstructions << " more instructions)\n " ;
627+
628+ // Print last min(PreviewLast, N - PreviewFirst) lines
629+ int LastLinesToPrint = std::min (
630+ LastLinesCount, N > InitialLinesCount ? N - InitialLinesCount : 0 );
631+ for (int i = N - LastLinesToPrint; i < N; ++i)
632+ outs () << format_hex_no_prefix (Instructions[i].Address , 0 ) << " :\t "
633+ << Instructions[i].HexBytes << Instructions[i].Text << ' \n ' ;
634+ outs () << " ```\n " ;
627635}
628636
629637// Function to extract and print assembly from snippet
@@ -635,23 +643,20 @@ Error printAssembledSnippet(const LLVMState &State,
635643 return make_error<Failure>(" Failed to extract function bytes: " +
636644 toString (std::move (Err)));
637645
638- DisassemblerHelper DisHelper (State);
639- size_t Offset = 0 ;
640- const size_t FunctionBytesSize = FunctionBytes.size ();
641-
642646 // Decode all instructions first
643- std::vector<std::pair<std::string, std::pair<uint64_t , std::string>>>
644- Instructions;
647+ DisassemblerHelper DisHelper (State);
645648 uint64_t Address = 0 ;
649+ std::vector<InstructionInfo> Instructions;
650+ const size_t FunctionBytesSize = FunctionBytes.size ();
646651
647- while (Offset < FunctionBytesSize) {
652+ while (Address < FunctionBytesSize) {
648653 MCInst Inst;
649654 uint64_t Size;
650- ArrayRef<uint8_t > Bytes (FunctionBytes.data () + Offset ,
651- FunctionBytesSize - Offset );
655+ ArrayRef<uint8_t > Bytes (FunctionBytes.data () + Address ,
656+ FunctionBytesSize - Address );
652657
653658 if (!DisHelper.decodeInst (Inst, Size, Bytes)) {
654- Instructions.push_back ({" <decode error>" , { Address, " " } });
659+ Instructions.push_back ({" <decode error>" , Address, " " });
655660 break ;
656661 }
657662
@@ -666,26 +671,19 @@ Error printAssembledSnippet(const LLVMState &State,
666671 for (int i = Size - 1 ; i >= 0 ; --i)
667672 HexOS << format_hex_no_prefix (Bytes[i], 2 );
668673
669- Instructions.push_back ({OS.str (), {Address, HexOS.str ()}});
670- Offset += Size;
674+ Instructions.push_back ({OS.str (), Address, HexOS.str ()});
671675 Address += Size;
672676 }
673677
674- // Preview generated assembly snippet
675- {
676- #undef DEBUG_TYPE
677- #define DEBUG_TYPE " preview-gen-assembly"
678- LLVM_DEBUG (dbgs () << " Generated assembly snippet:\n " );
679- LLVM_DEBUG (printGeneratedAssembly (Instructions, true ));
680- #undef DEBUG_TYPE
681- #define DEBUG_TYPE " print-gen-assembly"
682- }
683- // Print generated assembly snippet
684- {
685- LLVM_DEBUG (dbgs () << " Generated assembly snippet:\n " );
686- LLVM_DEBUG (printGeneratedAssembly (Instructions, false ));
687- }
678+ if (PrintGenAssembly == 0 || PrintGenAssembly < -1 )
679+ return Error::success ();
688680
681+ int InitialLinesCount = PrintGenAssembly;
682+ int LastLinesCount = 3 ;
683+ if (PrintGenAssembly == -1 ||
684+ PrintGenAssembly > static_cast <int >(Instructions.size ()))
685+ InitialLinesCount = Instructions.size () - LastLinesCount;
686+ printInstructions (Instructions, InitialLinesCount, LastLinesCount);
689687 return Error::success ();
690688}
691689} // namespace
0 commit comments