gollvm: add support for -fdebug-prefix-map= option
Implement support for -fdebug-prefix-map (previously this flag was
accepted but ignored).
Change-Id: I16d23e5432b1d4f7c81144b6795b7cf23d6a3134
Reviewed-on: https://go-review.googlesource.com/113722
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/bridge/go-llvm-dibuildhelper.cpp b/bridge/go-llvm-dibuildhelper.cpp
index 612f8fb..3f9853f 100644
--- a/bridge/go-llvm-dibuildhelper.cpp
+++ b/bridge/go-llvm-dibuildhelper.cpp
@@ -43,8 +43,8 @@
// Create compile unit
llvm::SmallString<256> currentDir;
llvm::sys::fs::current_path(currentDir);
- auto primaryFile =
- dibuilder_->createFile(linemap_->get_initial_file(), currentDir);
+ std::string filestr = applyDebugPrefix(linemap_->get_initial_file());
+ auto primaryFile = dibuilder_->createFile(filestr, currentDir);
bool isOptimized = true;
std::string compileFlags; // FIXME
unsigned runtimeVersion = 0; // not sure what would be for Go
@@ -284,9 +284,24 @@
}
}
+void DIBuildHelper::addDebugPrefix(std::pair<llvm::StringRef, llvm::StringRef> pref)
+{
+ std::string from(pref.first);
+ std::string to(pref.second);
+ debugPrefixMap_[from] = to;
+}
+
+std::string DIBuildHelper::applyDebugPrefix(llvm::StringRef path) {
+ for (const auto &remap : debugPrefixMap_)
+ if (path.startswith(remap.first))
+ return (llvm::Twine(remap.second) +
+ path.substr(remap.first.size())).str();
+ return path.str();
+}
+
llvm::DIFile *DIBuildHelper::diFileFromLocation(Location location)
{
- std::string locfile = linemap()->location_file(location);
+ std::string locfile = applyDebugPrefix(linemap()->location_file(location));
llvm::StringRef locdir = llvm::sys::path::parent_path(locfile);
llvm::StringRef locfilename = llvm::sys::path::filename(locfile);
if (linemap()->is_predeclared(location))
diff --git a/bridge/go-llvm-dibuildhelper.h b/bridge/go-llvm-dibuildhelper.h
index 53b708c..4d5df84 100644
--- a/bridge/go-llvm-dibuildhelper.h
+++ b/bridge/go-llvm-dibuildhelper.h
@@ -66,6 +66,9 @@
void processExprInst(Bexpression *expr, llvm::Instruction *inst);
+ // Support for -fdebug-prefix
+ void addDebugPrefix(std::pair<llvm::StringRef, llvm::StringRef>);
+
// Return module scope
llvm::DIScope *moduleScope() const { return moduleScope_; }
@@ -94,6 +97,7 @@
std::unique_ptr<llvm::DIBuilder> dibuilder_;
std::vector<llvm::DIScope*> diScopeStack_;
std::unordered_map<Btype *, llvm::DIType*> typeCache_;
+ std::unordered_map<std::string, std::string> debugPrefixMap_;
std::vector<std::pair<Bvariable *, bool> > globalsToProcess_;
// The following items are specific to the current function we're visiting.
@@ -110,6 +114,7 @@
void processVarsInBLock(const std::vector<Bvariable*> &vars,
llvm::DIScope *scope);
void markBlocks(Bnode *node);
+ std::string applyDebugPrefix(llvm::StringRef path);
};
#endif // !defined(GO_LLVM_DIBUILDHELPER_H)
diff --git a/bridge/go-llvm.cpp b/bridge/go-llvm.cpp
index 547990c..1e09d29 100644
--- a/bridge/go-llvm.cpp
+++ b/bridge/go-llvm.cpp
@@ -135,6 +135,11 @@
setTypeManagerTraceLevel(level);
}
+void Llvm_backend::addDebugPrefix(std::pair<llvm::StringRef, llvm::StringRef> prefix)
+{
+ dibuildhelper_->addDebugPrefix(prefix);
+}
+
void
Llvm_backend::verifyModule()
{
@@ -3494,7 +3499,7 @@
// Create and populate entry block
llvm::BasicBlock *entryBlock = genEntryBlock(function);
- // Avoid debug meta-generation if errors seen
+ // Avoid debug metadata generation if errors seen
DIBuildHelper *dibh = nullptr;
if (createDebugMetaData_ && errorCount_ == 0 && !go_be_saw_errors())
dibh = dibuildhelper();
diff --git a/bridge/go-llvm.h b/bridge/go-llvm.h
index 7b965d3..d3700b9 100644
--- a/bridge/go-llvm.h
+++ b/bridge/go-llvm.h
@@ -342,12 +342,12 @@
// DI build helper. Will be NULL if debug meta-data generation disabled.
DIBuildHelper *dibuildhelper() { return dibuildhelper_.get(); }
+ // Support for -fdebug-prefix=
+ void addDebugPrefix(std::pair<llvm::StringRef, llvm::StringRef> prefix);
+
// Bnode builder
BnodeBuilder &nodeBuilder() { return nbuilder_; }
- // Return top-level debug meta data object for module
- llvm::DICompileUnit *getDICompUnit();
-
// Finalize export data for the module. Exposed for unit testing.
void finalizeExportData();
diff --git a/driver/CompileGo.cpp b/driver/CompileGo.cpp
index 2c49b5a..4100966 100644
--- a/driver/CompileGo.cpp
+++ b/driver/CompileGo.cpp
@@ -427,6 +427,10 @@
bridge_->setTraceLevel(*tl);
bridge_->setNoInline(args_.hasArg(gollvm::options::OPT_fno_inline));
+ // Honor -fdebug-prefix=... option.
+ for (const auto &arg : driver_.args().getAllArgValues(gollvm::options::OPT_fdebug_prefix_map_EQ))
+ bridge_->addDebugPrefix(llvm::StringRef(arg).split('='));
+
// Support -fgo-dump-ast
if (args_.hasArg(gollvm::options::OPT_fgo_dump_ast))
go_enable_dump("ast");
diff --git a/unittests/BackendCore/BackendDebugEmit.cpp b/unittests/BackendCore/BackendDebugEmit.cpp
index d45c3e3..77179a9 100644
--- a/unittests/BackendCore/BackendDebugEmit.cpp
+++ b/unittests/BackendCore/BackendDebugEmit.cpp
@@ -36,7 +36,7 @@
%x = alloca i32
store i32 0, i32* %x
call void @llvm.dbg.declare(metadata i32* %x, metadata !3,
- metadata !DIExpression()), !dbg !11
+ metadata !DIExpression()), !dbg !10
ret void
}
)RAW_RESULT";
@@ -69,7 +69,7 @@
define void @foo(i8* nest %nest.0, { i64, i64, i64 }* byval %p0) #0 {
entry:
call void @llvm.dbg.declare(metadata { i64, i64, i64 }* %p0, metadata !3,
- metadata !DIExpression()), !dbg !15
+ metadata !DIExpression()), !dbg !16
ret void
}
)RAW_RESULT";
@@ -211,4 +211,31 @@
}
+TEST(BackendDebugEmit, TestDebugPrefixMap) {
+
+ FcnTestHarness h;
+ Llvm_backend *be = h.be();
+ Btype *bi64t = be->integer_type(false, 64);
+ BFunctionType *befty = mkFuncTyp(be, L_PARM, bi64t, L_RES, bi64t, L_END);
+
+ llvm::StringRef from2("/bar");
+ llvm::StringRef to2("/something");
+ be->addDebugPrefix(std::make_pair(from2, to2));
+
+ Location loc = h.newFileLineLoc("/bar/another/barcode.go", 11);
+ Bfunction *func = h.mkFunction("bar", befty);
+ Bvariable *p0 = func->getNthParamVar(0);
+ Bexpression *vec = be->var_expression(p0, loc);
+ h.mkReturn(std::vector<Bexpression*>{vec});
+
+ bool broken = h.finish(PreserveDebugInfo);
+ EXPECT_FALSE(broken && "Module failed to verify.");
+
+ be->dumpModule();
+
+ // Check for remapped source file.
+ bool ok = h.expectModuleDumpContains("!DIFile(filename: \"barcode.go\", directory: \"/something/another\")");
+ EXPECT_TRUE(ok);
+}
+
}
diff --git a/unittests/BackendCore/TestUtils.cpp b/unittests/BackendCore/TestUtils.cpp
index eaf1380..9334045 100644
--- a/unittests/BackendCore/TestUtils.cpp
+++ b/unittests/BackendCore/TestUtils.cpp
@@ -232,7 +232,8 @@
return func;
}
-Bfunction *mkFuncFromType(Backend *be, const char *fname, BFunctionType *befty)
+Bfunction *mkFuncFromType(Backend *be, const char *fname,
+ BFunctionType *befty, Location loc)
{
bool visible = true;
bool is_declaration = false;
@@ -240,7 +241,6 @@
bool split_stack = true;
bool unique_sec = false;
bool no_ret = false;
- Location loc;
Bfunction *func = be->function(befty, fname, fname, visible,
is_declaration, is_inl,
split_stack, no_ret, unique_sec, loc);
@@ -425,9 +425,17 @@
return loc_;
}
+Location FcnTestHarness::newFileLineLoc(const char *file, unsigned line)
+{
+ lineNum_ = line;
+ be_->linemap()->start_file(file, lineNum_);
+ loc_ = be_->linemap()->get_location(lineNum_);
+ return loc_;
+}
+
Bfunction *FcnTestHarness::mkFunction(const char *fcnName, BFunctionType *befty)
{
- func_ = mkFuncFromType(be(), fcnName, befty);
+ func_ = mkFuncFromType(be(), fcnName, befty, loc_);
entryBlock_ = be()->block(func_, nullptr, emptyVarList_, loc_, loc_);
curBlock_ = be()->block(func_, nullptr, emptyVarList_, loc_, loc_);
return func_;
diff --git a/unittests/BackendCore/TestUtils.h b/unittests/BackendCore/TestUtils.h
index 986975f..12f64e3 100644
--- a/unittests/BackendCore/TestUtils.h
+++ b/unittests/BackendCore/TestUtils.h
@@ -108,7 +108,8 @@
Bfunction *mkFunci32o64(Backend *be, const char *fname, bool mkParams = true);
// Returns function created from type
-Bfunction *mkFuncFromType(Backend *be, const char *fname, BFunctionType *befty);
+Bfunction *mkFuncFromType(Backend *be, const char *fname,
+ BFunctionType *befty, Location loc = Location());
// Manufacture an unsigned 64-bit integer constant
Bexpression *mkUint64Const(Backend *be, uint64_t val);
@@ -168,6 +169,9 @@
// Update the dummy location to something new, then return it.
Location newloc();
+ // New location with specified file and line.
+ Location newFileLineLoc(const char *file, unsigned line);
+
// Return current function
Bfunction *func() const { return func_; }