[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