10
10
11
11
#include < stdio.h>
12
12
13
+ #include < vector>
14
+
13
15
#include " rustllvm.h"
14
16
15
17
#include " llvm/Analysis/TargetLibraryInfo.h"
16
18
#include " llvm/Analysis/TargetTransformInfo.h"
17
19
#include " llvm/IR/AutoUpgrade.h"
20
+ #include " llvm/IR/AssemblyAnnotationWriter.h"
18
21
#include " llvm/Support/CBindingWrapping.h"
19
22
#include " llvm/Support/FileSystem.h"
20
23
#include " llvm/Support/Host.h"
@@ -503,8 +506,129 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
503
506
return LLVMRustResult::Success;
504
507
}
505
508
509
+
510
+ // Callback to demangle function name
511
+ // Parameters:
512
+ // * name to be demangled
513
+ // * name len
514
+ // * output buffer
515
+ // * output buffer len
516
+ // Returns len of demangled string, or 0 if demangle failed.
517
+ typedef size_t (*DemangleFn)(const char *, size_t , char *, size_t );
518
+
519
+
520
+ namespace {
521
+
522
+ class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter {
523
+ DemangleFn Demangle;
524
+ std::vector<char > Buf;
525
+
526
+ public:
527
+ RustAssemblyAnnotationWriter (DemangleFn Demangle) : Demangle(Demangle) {}
528
+
529
+ // Return empty string if demangle failed
530
+ // or if name does not need to be demangled
531
+ StringRef CallDemangle (StringRef name) {
532
+ if (!Demangle) {
533
+ return StringRef ();
534
+ }
535
+
536
+ if (Buf.size () < name.size () * 2 ) {
537
+ // Semangled name usually shorter than mangled,
538
+ // but allocate twice as much memory just in case
539
+ Buf.resize (name.size () * 2 );
540
+ }
541
+
542
+ auto R = Demangle (name.data (), name.size (), Buf.data (), Buf.size ());
543
+ if (!R) {
544
+ // Demangle failed.
545
+ return StringRef ();
546
+ }
547
+
548
+ auto Demangled = StringRef (Buf.data (), R);
549
+ if (Demangled == name) {
550
+ // Do not print anything if demangled name is equal to mangled.
551
+ return StringRef ();
552
+ }
553
+
554
+ return Demangled;
555
+ }
556
+
557
+ void emitFunctionAnnot (const Function *F,
558
+ formatted_raw_ostream &OS) override {
559
+ StringRef Demangled = CallDemangle (F->getName ());
560
+ if (Demangled.empty ()) {
561
+ return ;
562
+ }
563
+
564
+ OS << " ; " << Demangled << " \n " ;
565
+ }
566
+
567
+ void emitInstructionAnnot (const Instruction *I,
568
+ formatted_raw_ostream &OS) override {
569
+ const char *Name;
570
+ const Value *Value;
571
+ if (const CallInst *CI = dyn_cast<CallInst>(I)) {
572
+ Name = " call" ;
573
+ Value = CI->getCalledValue ();
574
+ } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
575
+ Name = " invoke" ;
576
+ Value = II->getCalledValue ();
577
+ } else {
578
+ // Could demangle more operations, e. g.
579
+ // `store %place, @function`.
580
+ return ;
581
+ }
582
+
583
+ if (!Value->hasName ()) {
584
+ return ;
585
+ }
586
+
587
+ StringRef Demangled = CallDemangle (Value->getName ());
588
+ if (Demangled.empty ()) {
589
+ return ;
590
+ }
591
+
592
+ OS << " ; " << Name << " " << Demangled << " \n " ;
593
+ }
594
+ };
595
+
596
+ class RustPrintModulePass : public ModulePass {
597
+ raw_ostream* OS;
598
+ DemangleFn Demangle;
599
+ public:
600
+ static char ID;
601
+ RustPrintModulePass () : ModulePass(ID), OS(nullptr ), Demangle(nullptr ) {}
602
+ RustPrintModulePass (raw_ostream &OS, DemangleFn Demangle)
603
+ : ModulePass(ID), OS(&OS), Demangle(Demangle) {}
604
+
605
+ bool runOnModule (Module &M) override {
606
+ RustAssemblyAnnotationWriter AW (Demangle);
607
+
608
+ M.print (*OS, &AW, false );
609
+
610
+ return false ;
611
+ }
612
+
613
+ void getAnalysisUsage (AnalysisUsage &AU) const override {
614
+ AU.setPreservesAll ();
615
+ }
616
+
617
+ static StringRef name () { return " RustPrintModulePass" ; }
618
+ };
619
+
620
+ } // namespace
621
+
622
+ namespace llvm {
623
+ void initializeRustPrintModulePassPass (PassRegistry&);
624
+ }
625
+
626
+ char RustPrintModulePass::ID = 0 ;
627
+ INITIALIZE_PASS (RustPrintModulePass, " print-rust-module" ,
628
+ " Print rust module to stderr" , false , false )
629
+
506
630
extern " C" void LLVMRustPrintModule (LLVMPassManagerRef PMR, LLVMModuleRef M,
507
- const char *Path) {
631
+ const char *Path, DemangleFn Demangle ) {
508
632
llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
509
633
std::string ErrorInfo;
510
634
@@ -515,7 +639,7 @@ extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
515
639
516
640
formatted_raw_ostream FOS (OS);
517
641
518
- PM->add (createPrintModulePass (FOS));
642
+ PM->add (new RustPrintModulePass (FOS, Demangle ));
519
643
520
644
PM->run (*unwrap (M));
521
645
}
0 commit comments