1
Fork 0

When writing LLVM IR output demangled fn name in comments

`--emit=llvm-ir` looks like this now:

```
; <alloc::vec::Vec<T> as core::ops::index::IndexMut<core::ops::range::RangeFull>>::index_mut
; Function Attrs: inlinehint uwtable
define internal { i8*, i64 } @"_ZN106_$LT$alloc..vec..Vec$LT$T$GT$$u20$as$u20$core..ops..index..IndexMut$LT$core..ops..range..RangeFull$GT$$GT$9index_mut17h7f7b576609f30262E"(%"alloc::vec::Vec<u8>"* dereferenceable(24)) unnamed_addr #0 {
start:
  ...
```

cc https://github.com/integer32llc/rust-playground/issues/15
This commit is contained in:
Stepan Koltsov 2017-06-29 17:52:43 +03:00
parent 37849a002e
commit b62bdaafe0
6 changed files with 173 additions and 5 deletions

View file

@ -10,11 +10,14 @@
#include <stdio.h>
#include <vector>
#include "rustllvm.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/AssemblyAnnotationWriter.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
@ -503,8 +506,129 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
return LLVMRustResult::Success;
}
// Callback to demangle function name
// Parameters:
// * name to be demangled
// * name len
// * output buffer
// * output buffer len
// Returns len of demangled string, or 0 if demangle failed.
typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t);
namespace {
class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter {
DemangleFn Demangle;
std::vector<char> Buf;
public:
RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {}
// Return empty string if demangle failed
// or if name does not need to be demangled
StringRef CallDemangle(StringRef name) {
if (!Demangle) {
return StringRef();
}
if (Buf.size() < name.size() * 2) {
// Semangled name usually shorter than mangled,
// but allocate twice as much memory just in case
Buf.resize(name.size() * 2);
}
auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size());
if (!R) {
// Demangle failed.
return StringRef();
}
auto Demangled = StringRef(Buf.data(), R);
if (Demangled == name) {
// Do not print anything if demangled name is equal to mangled.
return StringRef();
}
return Demangled;
}
void emitFunctionAnnot(const Function *F,
formatted_raw_ostream &OS) override {
StringRef Demangled = CallDemangle(F->getName());
if (Demangled.empty()) {
return;
}
OS << "; " << Demangled << "\n";
}
void emitInstructionAnnot(const Instruction *I,
formatted_raw_ostream &OS) override {
const char *Name;
const Value *Value;
if (const CallInst *CI = dyn_cast<CallInst>(I)) {
Name = "call";
Value = CI->getCalledValue();
} else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
Name = "invoke";
Value = II->getCalledValue();
} else {
// Could demangle more operations, e. g.
// `store %place, @function`.
return;
}
if (!Value->hasName()) {
return;
}
StringRef Demangled = CallDemangle(Value->getName());
if (Demangled.empty()) {
return;
}
OS << "; " << Name << " " << Demangled << "\n";
}
};
class RustPrintModulePass : public ModulePass {
raw_ostream* OS;
DemangleFn Demangle;
public:
static char ID;
RustPrintModulePass() : ModulePass(ID), OS(nullptr), Demangle(nullptr) {}
RustPrintModulePass(raw_ostream &OS, DemangleFn Demangle)
: ModulePass(ID), OS(&OS), Demangle(Demangle) {}
bool runOnModule(Module &M) override {
RustAssemblyAnnotationWriter AW(Demangle);
M.print(*OS, &AW, false);
return false;
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
static StringRef name() { return "RustPrintModulePass"; }
};
} // namespace
namespace llvm {
void initializeRustPrintModulePassPass(PassRegistry&);
}
char RustPrintModulePass::ID = 0;
INITIALIZE_PASS(RustPrintModulePass, "print-rust-module",
"Print rust module to stderr", false, false)
extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
const char *Path) {
const char *Path, DemangleFn Demangle) {
llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
std::string ErrorInfo;
@ -515,7 +639,7 @@ extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
formatted_raw_ostream FOS(OS);
PM->add(createPrintModulePass(FOS));
PM->add(new RustPrintModulePass(FOS, Demangle));
PM->run(*unwrap(M));
}