Implement instrumentation pass

This commit is contained in:
gingerBill
2024-01-07 21:34:44 +00:00
parent aff8f06e3c
commit f4782157d3
14 changed files with 143 additions and 21 deletions
+77
View File
@@ -380,6 +380,80 @@ 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[2] = {};
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), "");
LLVMTypeRef fnp = lb_type_internal_for_procedures_raw(p->module, entity->type);
return LLVMBuildCall2(dummy_builder, fnp, cc.value, args, 2, "");
}
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 +475,7 @@ gb_internal void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedur
}
break;
}
lb_run_instrumentation_pass(p);
LLVMRunFunctionPassManager(fpm, p->value);
}
@@ -552,3 +627,5 @@ gb_internal void lb_run_remove_unused_globals_pass(lbModule *m) {
}
}
}