Initial version of debug info pass for RS.
This introduces a new LLVM pass into libbcc called
RSAddDebugInfoPass. Its purpose is to add debug information metadata
to LLVM constructs generated by the other parts of libbcc. The
generated code generally lacks sufficient debugging information as it
has not been processed by the clang-based front-end.
The initial version of RSAddDebugInfoPass provides the following:
1. It annotates the expanded function generated by RSExpandKernel pass
with debug information, stating the name of the function and
source file indicating that the function has been generated.
2. It annotates the instructions of the *.expand function with
filename/line indicating that the function code has been generated.
The source file of both the generated function definition and
the instructions that make up the function is mapped to the source
location of /opt/renderscriptdebugger/1/generated.rs:1. That might be
source-mapped by the debugger to an appropriate file in the SDK, the
contents of which clearly indicate that the user is dealing with
generated code (i.e. one without a "physical" source file).
Change-Id: I2e566160a448d7bfbb3f8d16680e09e43c845693
diff --git a/include/bcc/Compiler.h b/include/bcc/Compiler.h
index 8a30c38..a0925b8 100644
--- a/include/bcc/Compiler.h
+++ b/include/bcc/Compiler.h
@@ -82,6 +82,7 @@
bool addInternalizeSymbolsPass(Script &pScript, llvm::legacy::PassManager &pPM);
void addExpandKernelPass(llvm::legacy::PassManager &pPM);
+ void addDebugInfoPass(Script &pScript, llvm::legacy::PassManager &pPM);
void addGlobalInfoPass(Script &pScript, llvm::legacy::PassManager &pPM);
void addInvariantPass(llvm::legacy::PassManager &pPM);
void addInvokeHelperPass(llvm::legacy::PassManager &pPM);
diff --git a/include/bcc/Renderscript/RSTransforms.h b/include/bcc/Renderscript/RSTransforms.h
index 6dcfedd..3c81860 100644
--- a/include/bcc/Renderscript/RSTransforms.h
+++ b/include/bcc/Renderscript/RSTransforms.h
@@ -43,6 +43,8 @@
llvm::ModulePass * createRSX86_64CallConvPass();
+llvm::ModulePass * createRSAddDebugInfoPass();
+
} // end namespace bcc
#endif // BCC_RS_TRANSFORMS_H
diff --git a/include/bcc/Source.h b/include/bcc/Source.h
index 54263a2..e6bef2e 100644
--- a/include/bcc/Source.h
+++ b/include/bcc/Source.h
@@ -82,6 +82,10 @@
void addBuildChecksumMetadata(const char *) const;
+ // Get whether debugging has been enabled for this module by checking
+ // for presence of debug info in the module.
+ bool getDebugInfoEnabled() const;
+
~Source();
};
diff --git a/lib/Core/Compiler.cpp b/lib/Core/Compiler.cpp
index eea0750..35f19d7 100644
--- a/lib/Core/Compiler.cpp
+++ b/lib/Core/Compiler.cpp
@@ -159,6 +159,7 @@
// Add some initial custom passes.
addInvokeHelperPass(transformPasses);
addExpandKernelPass(transformPasses);
+ addDebugInfoPass(pScript, transformPasses);
addInvariantPass(transformPasses);
if (!addInternalizeSymbolsPass(pScript, transformPasses))
return kErrCustomPasses;
@@ -387,6 +388,11 @@
}
}
+void Compiler::addDebugInfoPass(Script &pScript, llvm::legacy::PassManager &pPM) {
+ if (pScript.getSource().getDebugInfoEnabled())
+ pPM.add(createRSAddDebugInfoPass());
+}
+
void Compiler::addExpandKernelPass(llvm::legacy::PassManager &pPM) {
// Expand ForEach and reduce on CPU path to reduce launch overhead.
bool pEnableStepOpt = true;
diff --git a/lib/Core/Source.cpp b/lib/Core/Source.cpp
index 94da98e..25b263f 100644
--- a/lib/Core/Source.cpp
+++ b/lib/Core/Source.cpp
@@ -181,4 +181,8 @@
node->addOperand(llvm::MDNode::get(context, val));
}
+bool Source::getDebugInfoEnabled() const {
+ return mModule->getNamedMetadata("llvm.dbg.cu") != nullptr;
+}
+
} // namespace bcc
diff --git a/lib/Renderscript/Android.mk b/lib/Renderscript/Android.mk
index 7744447..32e65b3 100644
--- a/lib/Renderscript/Android.mk
+++ b/lib/Renderscript/Android.mk
@@ -22,6 +22,7 @@
#=====================================================================
libbcc_renderscript_SRC_FILES := \
+ RSAddDebugInfoPass.cpp \
RSCompilerDriver.cpp \
RSEmbedInfo.cpp \
RSKernelExpand.cpp \
diff --git a/lib/Renderscript/RSAddDebugInfoPass.cpp b/lib/Renderscript/RSAddDebugInfoPass.cpp
new file mode 100644
index 0000000..03ad24a
--- /dev/null
+++ b/lib/Renderscript/RSAddDebugInfoPass.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Assert.h"
+#include "bcc/Renderscript/RSTransforms.h"
+
+#include <llvm/Pass.h>
+#include <llvm/IR/DataLayout.h>
+#include <llvm/IR/DIBuilder.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/InstIterator.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/MDBuilder.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+#include <llvm/Transforms/Utils/BasicBlockUtils.h>
+
+namespace {
+
+const char DEBUG_SOURCE_PATH[] = "/opt/renderscriptdebugger/1";
+const char DEBUG_GENERATED_FILE[] = "generated.rs";
+
+/*
+ * LLVM pass to attach debug information to the bits of code
+ * generated by the compiler.
+ */
+class RSAddDebugInfoPass : public llvm::ModulePass {
+
+public:
+ // Pass ID
+ static char ID;
+
+ RSAddDebugInfoPass() : ModulePass(ID) {
+ }
+
+ virtual bool runOnModule(llvm::Module &Module) {
+ // Set up the debug info builder.
+ llvm::DIBuilder DebugInfo(Module);
+ DebugInfo.createCompileUnit(llvm::dwarf::DW_LANG_C99,
+ DEBUG_GENERATED_FILE, DEBUG_SOURCE_PATH,
+ "RS", false, "", 0);
+
+ // Attach DI metadata to each generated function.
+ for (llvm::Function &Func : Module)
+ if (Func.getName().endswith(".expand"))
+ attachDebugInfo(DebugInfo, Func);
+
+ DebugInfo.finalize();
+
+ return true;
+ }
+
+private:
+
+ /// @brief Add debug information to a generated function.
+ ///
+ /// This function is used to attach source file and line information
+ /// to the generated function code.
+ void attachDebugInfo(llvm::DIBuilder &DebugInfo, llvm::Function &Func) {
+ llvm::DIFile *sourceFileName =
+ DebugInfo.createFile(DEBUG_GENERATED_FILE, DEBUG_SOURCE_PATH);
+
+ // Fabricated function type
+ llvm::MDTuple *nullMD = llvm::MDTuple::get(Func.getParent()->getContext(),
+ { DebugInfo.createUnspecifiedType("void") });
+
+ // Create function-level debug metadata.
+ llvm::DIScope *GeneratedScope = DebugInfo.createFunction(
+ sourceFileName, // scope
+ Func.getName(), Func.getName(),
+ sourceFileName, 1,
+ DebugInfo.createSubroutineType(sourceFileName, nullMD),
+ false, true, 1, 0, false, &Func
+ );
+
+ // Attach location inforamtion to each instruction in the function
+ for (llvm::inst_iterator Inst = llvm::inst_begin(Func),
+ InstEnd = llvm::inst_end(Func);
+ Inst != InstEnd;
+ ++Inst) {
+ Inst->setDebugLoc(llvm::DebugLoc::get(1, 1, GeneratedScope));
+ }
+ }
+
+}; // end class RSAddDebugInfoPass
+
+char RSAddDebugInfoPass::ID = 0;
+static llvm::RegisterPass<RSAddDebugInfoPass> X("addrsdi", "Add RS DebugInfo Pass");
+
+} // end anonymous namespace
+
+namespace bcc {
+
+llvm::ModulePass * createRSAddDebugInfoPass() {
+ return new RSAddDebugInfoPass();
+}
+
+} // end namespace bcc