[pkg-d-commits] [ldc] 125/211: Implement -finstrument-functions.
Matthias Klumpp
mak at moszumanska.debian.org
Sun Apr 23 22:36:16 UTC 2017
This is an automated email from the git hooks/post-receive script.
mak pushed a commit to annotated tag v1.1.0
in repository ldc.
commit 596fc8225487f887989688472df132602fe6a57d
Author: LemonBoy <thatlemon at gmail.com>
Date: Thu Oct 20 00:35:14 2016 +0200
Implement -finstrument-functions.
Closes #1839.
---
driver/cl_options.cpp | 5 +++++
driver/cl_options.h | 1 +
gen/functions.cpp | 4 ++++
gen/runtime.cpp | 36 ++++++++++++++++++++++++++++++++++++
gen/runtime.h | 4 ++++
gen/statements.cpp | 2 ++
tests/codegen/instrumentation.d | 29 +++++++++++++++++++++++++++++
7 files changed, 81 insertions(+)
diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp
index d82aba9..b7be19b 100644
--- a/driver/cl_options.cpp
+++ b/driver/cl_options.cpp
@@ -455,6 +455,11 @@ cl::opt<std::string> usefileInstrProf(
cl::ValueRequired);
#endif
+cl::opt<bool>
+ instrumentFunctions("finstrument-functions",
+ cl::desc("Instrument function entry and exit with "
+ "GCC-compatible profiling calls"));
+
static cl::extrahelp footer(
"\n"
"-d-debug can also be specified without options, in which case it enables "
diff --git a/driver/cl_options.h b/driver/cl_options.h
index ef33884..a2b8b49 100644
--- a/driver/cl_options.h
+++ b/driver/cl_options.h
@@ -87,6 +87,7 @@ extern cl::opt<unsigned, true> nestedTemplateDepth;
extern cl::opt<std::string> genfileInstrProf;
extern cl::opt<std::string> usefileInstrProf;
#endif
+extern cl::opt<bool> instrumentFunctions;
// Arguments to -d-debug
extern std::vector<std::string> debugArgs;
diff --git a/gen/functions.cpp b/gen/functions.cpp
index 287eee7..840e8c3 100644
--- a/gen/functions.cpp
+++ b/gen/functions.cpp
@@ -962,6 +962,8 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
// debug info - after all allocas, but before any llvm.dbg.declare etc
gIR->DBuilder.EmitFuncStart(fd);
+ emitInstrumentationFnEnter(fd);
+
// this hack makes sure the frame pointer elimination optimization is
// disabled.
// this this eliminates a bunch of inline asm related issues.
@@ -1077,6 +1079,8 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
// llvm requires all basic blocks to end with a TerminatorInst but DMD does
// not put a return statement in automatically, so we do it here.
+ emitInstrumentationFnLeave(fd);
+
// pass the previous block into this block
gIR->DBuilder.EmitStopPoint(fd->endloc);
if (func->getReturnType() == LLType::getVoidTy(gIR->context())) {
diff --git a/gen/runtime.cpp b/gen/runtime.cpp
index d46fc0a..4fe29d2 100644
--- a/gen/runtime.cpp
+++ b/gen/runtime.cpp
@@ -21,6 +21,7 @@
#include "ir/irfunction.h"
#include "ir/irtype.h"
#include "ir/irtypefunction.h"
+#include "driver/cl_options.h"
#include "ldcbindings.h"
#include "mars.h"
#include "module.h"
@@ -329,6 +330,16 @@ static void buildRuntimeModule() {
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
+ // void __cyg_profile_func_enter(void *callee, void *caller)
+ // void __cyg_profile_func_exit(void *callee, void *caller)
+ createFwdDecl(LINKc, voidTy,
+ {"__cyg_profile_func_exit", "__cyg_profile_func_enter"},
+ {voidPtrTy, voidPtrTy}, {}, Attr_NoUnwind);
+
+ //////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////
+
// void _d_assert(string file, uint line)
// void _d_arraybounds(string file, uint line)
createFwdDecl(LINKc, Type::tvoid, {"_d_assert", "_d_arraybounds"},
@@ -739,3 +750,28 @@ static void buildRuntimeModule() {
}
}
}
+
+static void emitInstrumentationFn(const char *name) {
+ LLFunction *fn = getRuntimeFunction(Loc(), gIR->module, name);
+
+ // Grab the address of the calling function
+ auto *caller =
+ gIR->ir->CreateCall(GET_INTRINSIC_DECL(returnaddress), DtoConstInt(1));
+ auto callee = DtoBitCast(gIR->topfunc(), getVoidPtrType());
+
+#if LDC_LLVM_VER >= 307
+ gIR->ir->CreateCall(fn, {callee, caller});
+#else
+ gIR->ir->CreateCall2(fn, callee, caller);
+#endif
+}
+
+void emitInstrumentationFnEnter(FuncDeclaration *decl) {
+ if (opts::instrumentFunctions && decl->emitInstrumentation)
+ emitInstrumentationFn("__cyg_profile_func_enter");
+}
+
+void emitInstrumentationFnLeave(FuncDeclaration *decl) {
+ if (opts::instrumentFunctions && decl->emitInstrumentation)
+ emitInstrumentationFn("__cyg_profile_func_exit");
+}
diff --git a/gen/runtime.h b/gen/runtime.h
index 3c61183..10bd26d 100644
--- a/gen/runtime.h
+++ b/gen/runtime.h
@@ -21,6 +21,7 @@ class Module;
}
struct Loc;
+struct FuncDeclaration;
// D runtime support helpers
bool initRuntime();
@@ -32,4 +33,7 @@ llvm::Function *getRuntimeFunction(const Loc &loc, llvm::Module &target,
llvm::GlobalVariable *
getRuntimeGlobal(const Loc &loc, llvm::Module &target, const char *name);
+void emitInstrumentationFnEnter(FuncDeclaration *decl);
+void emitInstrumentationFnLeave(FuncDeclaration *decl);
+
#endif // LDC_GEN_RUNTIME_H
diff --git a/gen/statements.cpp b/gen/statements.cpp
index 4595f49..0e730ca 100644
--- a/gen/statements.cpp
+++ b/gen/statements.cpp
@@ -134,6 +134,8 @@ public:
FuncDeclaration *const fd = f->decl;
LLFunction *const llFunc = f->func;
+ emitInstrumentationFnLeave(fd);
+
// is there a return value expression?
if (stmt->exp || (!stmt->exp && (llFunc == irs->mainFunc))) {
// if the function's return type is void, it uses sret
diff --git a/tests/codegen/instrumentation.d b/tests/codegen/instrumentation.d
new file mode 100644
index 0000000..a5b85ca
--- /dev/null
+++ b/tests/codegen/instrumentation.d
@@ -0,0 +1,29 @@
+// RUN: %ldc -c -output-ll -finstrument-functions -of=%t.ll %s && FileCheck %s < %t.ll
+
+void fun0 () {
+ // CHECK-LABEL: define{{.*}} @{{.*}}4fun0FZv
+ // CHECK: call void @__cyg_profile_func_enter
+ // CHECK: call void @__cyg_profile_func_exit
+ // CHECK-NEXT: ret
+ return;
+}
+
+pragma(LDC_profile_instr, false)
+int fun1 (int x) {
+ // CHECK-LABEL: define{{.*}} @{{.*}}4fun1FiZi
+ // CHECK-NOT: call void @__cyg_profile_func_enter
+ // CHECK-NOT: call void @__cyg_profile_func_exit
+ return 42;
+}
+
+bool fun2 (int x) {
+ // CHECK-LABEL: define{{.*}} @{{.*}}4fun2FiZb
+ if (x < 10)
+ // CHECK: call void @__cyg_profile_func_exit
+ // CHECK-NEXT: ret
+ return true;
+
+ // CHECK: call void @__cyg_profile_func_exit
+ // CHECK-NEXT: ret
+ return false;
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-d/ldc.git
More information about the pkg-d-commits
mailing list