EXPERIMENTAL intrinsics.valgrind_client_request

This commit is contained in:
gingerBill
2022-08-17 13:52:13 +01:00
parent 82765ca96e
commit 82e840a0ca
6 changed files with 97 additions and 0 deletions

View File

@@ -295,6 +295,9 @@ objc_register_selector :: proc($name: string) -> objc_SEL ---
objc_find_class :: proc($name: string) -> objc_Class ---
objc_register_class :: proc($name: string) -> objc_Class ---
valgrind_client_request :: proc(default: uintptr, request: uintptr, a0, a1, a2, a3, a4: uintptr) -> uintptr ---
// Internal compiler use only
__entry_point :: proc() ---

View File

@@ -228,6 +228,7 @@ struct BuildContext {
bool ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not
bool ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing)
bool ODIN_FOREIGN_ERROR_PROCEDURES;
bool ODIN_VALGRIND_SUPPORT;
ErrorPosStyle ODIN_ERROR_POS_STYLE;
@@ -1190,6 +1191,8 @@ void init_build_context(TargetMetrics *cross_target) {
bc->optimization_level = gb_clamp(bc->optimization_level, 0, 3);
bc->ODIN_VALGRIND_SUPPORT = is_arch_x86() && build_context.metrics.os != TargetOs_windows;
#undef LINK_FLAG_X64
#undef LINK_FLAG_386
}

View File

@@ -5388,6 +5388,41 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
}
break;
case BuiltinProc_valgrind_client_request:
{
if (!is_arch_x86()) {
error(call, "'%.*s' is only allowed on x86 targets (i386, amd64)", LIT(builtin_name));
return false;
}
enum {ARG_COUNT = 7};
GB_ASSERT(builtin_procs[BuiltinProc_valgrind_client_request].arg_count == ARG_COUNT);
Operand operands[ARG_COUNT] = {};
for (isize i = 0; i < ARG_COUNT; i++) {
Operand *op = &operands[i];
check_expr_with_type_hint(c, op, ce->args[i], t_uintptr);
if (op->mode == Addressing_Invalid) {
return false;
}
convert_to_typed(c, op, t_uintptr);
if (op->mode == Addressing_Invalid) {
return false;
}
if (!are_types_identical(op->type, t_uintptr)) {
gbString str = type_to_string(op->type);
error(op->expr, "'%.*s' expected a uintptr, got %s", LIT(builtin_name), str);
gb_string_free(str);
return false;
}
}
operand->type = t_uintptr;
operand->mode = Addressing_Value;
operand->value = {};
return true;
}
}
return true;

View File

@@ -1037,6 +1037,9 @@ void init_universal(void) {
add_global_bool_constant("ODIN_FOREIGN_ERROR_PROCEDURES", bc->ODIN_FOREIGN_ERROR_PROCEDURES);
add_global_bool_constant("ODIN_DISALLOW_RTTI", bc->disallow_rtti);
add_global_bool_constant("ODIN_VALGRIND_SUPPORT", bc->ODIN_VALGRIND_SUPPORT);
// Builtin Procedures
for (isize i = 0; i < gb_count_of(builtin_procs); i++) {

View File

@@ -291,6 +291,8 @@ BuiltinProc__type_end,
BuiltinProc_wasm_memory_atomic_wait32,
BuiltinProc_wasm_memory_atomic_notify32,
BuiltinProc_valgrind_client_request,
BuiltinProc_COUNT,
};
gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
@@ -582,4 +584,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("wasm_memory_size"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("wasm_memory_atomic_wait32"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("wasm_memory_atomic_notify32"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("valgrind_client_request"), 7, false, Expr_Expr, BuiltinProcPkg_intrinsics},
};

View File

@@ -2745,6 +2745,55 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
res.value = LLVMBuildCall2(p->builder, func_type, the_asm, args, gb_count_of(args), "");
return res;
}
case BuiltinProc_valgrind_client_request:
{
lbValue args[7] = {};
for (isize i = 0; i < 7; i++) {
args[i] = lb_emit_conv(p, lb_build_expr(p, ce->args[i]), t_uintptr);
}
if (!build_context.ODIN_VALGRIND_SUPPORT) {
return args[0];
}
lbValue array = lb_generate_local_array(p, t_uintptr, 6, false);
for (isize i = 0; i < 6; i++) {
lbValue gep = lb_emit_array_epi(p, array, i);
lb_emit_store(p, gep, args[i+1]);
}
switch (build_context.metrics.arch) {
case TargetArch_amd64:
{
Type *param_types[2] = {};
param_types[0] = t_uintptr;
param_types[1] = array.type;
Type *type = alloc_type_proc_from_types(param_types, gb_count_of(param_types), t_uintptr, false, ProcCC_None);
LLVMTypeRef func_type = lb_get_procedure_raw_type(p->module, type);
LLVMValueRef the_asm = llvm_get_inline_asm(
func_type,
str_lit("rolq $3, %rdi; rolq $13, %rdi\n rolq $61, %rdi; rolq $51, %rdi\n xchgq %rbx, %rbx"),
str_lit("={rdx},{rdx},{rax},cc,memory"),
true
);
LLVMValueRef asm_args[2] = {};
asm_args[0] = args[0].value;
asm_args[1] = array.value;
lbValue res = {};
res.type = t_uintptr;
res.value = LLVMBuildCall2(p->builder, func_type, the_asm, asm_args, gb_count_of(asm_args), "");
return res;
}
break;
default:
GB_PANIC("Unsupported architecture: %.*s", LIT(target_arch_names[build_context.metrics.arch]));
break;
}
}
}
GB_PANIC("Unhandled built-in procedure %.*s", LIT(builtin_procs[id].name));