mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-06 21:17:40 +00:00
EXPERIMENTAL intrinsics.valgrind_client_request
This commit is contained in:
@@ -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() ---
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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},
|
||||
};
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user