aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend_opt.cpp
diff options
context:
space:
mode:
authorFourteenBrush <naessensarthur2@protonmail.com>2024-01-25 10:15:25 +0100
committerFourteenBrush <naessensarthur2@protonmail.com>2024-01-25 10:15:25 +0100
commit967ccfc7ccc0f76c653ff4bb625bac60e89a7904 (patch)
treef989a0f99337c7a0c93ee84249d73ec0c33e306d /src/llvm_backend_opt.cpp
parent712ae1c5ac73493498aa8e5076d91a6558337117 (diff)
parent9cfd4a953e2a7d19237891993b643b2d1477f8b3 (diff)
Merge branch 'master' of https://github.com/FourteenBrush/Odin
Diffstat (limited to 'src/llvm_backend_opt.cpp')
-rw-r--r--src/llvm_backend_opt.cpp83
1 files changed, 83 insertions, 0 deletions
diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp
index 2e03b7974..b57e74799 100644
--- a/src/llvm_backend_opt.cpp
+++ b/src/llvm_backend_opt.cpp
@@ -380,6 +380,86 @@ gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) {
}
}
+gb_internal LLVMValueRef lb_run_instrumentation_pass_insert_call(lbProcedure *p, Entity *entity, LLVMBuilderRef dummy_builder) {
+ lbModule *m = p->module;
+
+ lbValue cc = lb_find_procedure_value_from_entity(m, entity);
+
+ LLVMValueRef args[3] = {};
+ args[0] = p->value;
+
+ LLVMValueRef returnaddress_args[1] = {};
+
+ returnaddress_args[0] = LLVMConstInt(LLVMInt32TypeInContext(m->ctx), 0, false);
+
+ char const *instrinsic_name = "llvm.returnaddress";
+ unsigned id = LLVMLookupIntrinsicID(instrinsic_name, gb_strlen(instrinsic_name));
+ GB_ASSERT_MSG(id != 0, "Unable to find %s", instrinsic_name);
+ LLVMValueRef ip = LLVMGetIntrinsicDeclaration(m->mod, id, nullptr, 0);
+ LLVMTypeRef call_type = LLVMIntrinsicGetType(m->ctx, id, nullptr, 0);
+ args[1] = LLVMBuildCall2(dummy_builder, call_type, ip, returnaddress_args, gb_count_of(returnaddress_args), "");
+
+ Token name = {};
+ if (p->entity) {
+ name = p->entity->token;
+ }
+ args[2] = lb_emit_source_code_location_as_global_ptr(p, name.string, name.pos).value;
+
+ LLVMTypeRef fnp = lb_type_internal_for_procedures_raw(p->module, entity->type);
+ return LLVMBuildCall2(dummy_builder, fnp, cc.value, args, gb_count_of(args), "");
+}
+
+
+gb_internal void lb_run_instrumentation_pass(lbProcedure *p) {
+ lbModule *m = p->module;
+ Entity *enter = m->info->instrumentation_enter_entity;
+ Entity *exit = m->info->instrumentation_exit_entity;
+ if (enter == nullptr || exit == nullptr) {
+ return;
+ }
+ if (!(p->entity &&
+ p->entity->kind == Entity_Procedure &&
+ p->entity->Procedure.has_instrumentation)) {
+ return;
+ }
+
+#define LLVM_V_NAME(x) x, cast(unsigned)(gb_count_of(x)-1)
+
+ LLVMBuilderRef dummy_builder = LLVMCreateBuilderInContext(m->ctx);
+ defer (LLVMDisposeBuilder(dummy_builder));
+
+ LLVMBasicBlockRef entry_bb = p->entry_block->block;
+ LLVMPositionBuilder(dummy_builder, entry_bb, LLVMGetFirstInstruction(entry_bb));
+ lb_run_instrumentation_pass_insert_call(p, enter, dummy_builder);
+ LLVMRemoveStringAttributeAtIndex(p->value, LLVMAttributeIndex_FunctionIndex, LLVM_V_NAME("instrument-function-entry"));
+
+ unsigned bb_count = LLVMCountBasicBlocks(p->value);
+ LLVMBasicBlockRef *bbs = gb_alloc_array(temporary_allocator(), LLVMBasicBlockRef, bb_count);
+ LLVMGetBasicBlocks(p->value, bbs);
+ for (unsigned i = 0; i < bb_count; i++) {
+ LLVMBasicBlockRef bb = bbs[i];
+ LLVMValueRef terminator = LLVMGetBasicBlockTerminator(bb);
+ if (terminator == nullptr ||
+ !LLVMIsAReturnInst(terminator)) {
+ continue;
+ }
+
+ // TODO(bill): getTerminatingMustTailCall()
+ // If T is preceded by a musttail call, that's the real terminator.
+ // if (CallInst *CI = BB.getTerminatingMustTailCall())
+ // T = CI;
+
+
+ LLVMPositionBuilderBefore(dummy_builder, terminator);
+ lb_run_instrumentation_pass_insert_call(p, exit, dummy_builder);
+ }
+
+ LLVMRemoveStringAttributeAtIndex(p->value, LLVMAttributeIndex_FunctionIndex, LLVM_V_NAME("instrument-function-exit"));
+
+#undef LLVM_V_NAME
+}
+
+
gb_internal void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedure *p, lbFunctionPassManagerKind pass_manager_kind) {
if (p == nullptr) {
@@ -401,6 +481,7 @@ gb_internal void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedur
}
break;
}
+ lb_run_instrumentation_pass(p);
LLVMRunFunctionPassManager(fpm, p->value);
}
@@ -552,3 +633,5 @@ gb_internal void lb_run_remove_unused_globals_pass(lbModule *m) {
}
}
}
+
+