diff options
| author | gingerBill <bill@gingerbill.org> | 2023-06-21 14:01:46 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2023-06-21 14:01:46 +0100 |
| commit | 180003035659d56a898ddf7de59e8630493c2147 (patch) | |
| tree | 7f73054011d6d6fbf618eebf9862191e9ecf734a /src/llvm_backend_proc.cpp | |
| parent | 43ba2c6226dc71754c7aa74ed8ecb150231a9624 (diff) | |
Correct deferred procedures
Diffstat (limited to 'src/llvm_backend_proc.cpp')
| -rw-r--r-- | src/llvm_backend_proc.cpp | 196 |
1 files changed, 109 insertions, 87 deletions
diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 0beaf376b..48b4b9330 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1160,7 +1160,13 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> c } - Entity **found = map_get(&p->module->procedure_values, value.value); + LLVMValueRef the_proc_value = value.value; + + if (LLVMIsAConstantExpr(the_proc_value)) { + // NOTE(bill): it's a bit cast + the_proc_value = LLVMGetOperand(the_proc_value, 0); + } + Entity **found = map_get(&p->module->procedure_values, the_proc_value); if (found != nullptr) { Entity *e = *found; if (e != nullptr && entity_has_deferred_procedure(e)) { @@ -3156,14 +3162,89 @@ gb_internal void lb_add_values_to_array(lbProcedure *p, Array<lbValue> *args, lb array_add(args, value); } } -gb_internal lbValue lb_build_call_expr_internal_with_arg_split_args(lbProcedure *p, lbValue value, TypeProc *pt, Ast *call, AstSplitArgs *split_args) { - ast_node(ce, CallExpr, call); + +gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) { + lbModule *m = p->module; + + TypeAndValue tv = type_and_value_of_expr(expr); + + ast_node(ce, CallExpr, expr); + + TypeAndValue proc_tv = type_and_value_of_expr(ce->proc); + AddressingMode proc_mode = proc_tv.mode; + if (proc_mode == Addressing_Type) { + GB_ASSERT(ce->args.count == 1); + lbValue x = lb_build_expr(p, ce->args[0]); + lbValue y = lb_emit_conv(p, x, tv.type); + return y; + } + + Ast *proc_expr = unparen_expr(ce->proc); + if (proc_mode == Addressing_Builtin) { + Entity *e = entity_of_node(proc_expr); + BuiltinProcId id = BuiltinProc_Invalid; + if (e != nullptr) { + id = cast(BuiltinProcId)e->Builtin.id; + } else { + id = BuiltinProc_DIRECTIVE; + } + return lb_build_builtin_proc(p, expr, tv, id); + } + + // NOTE(bill): Regular call + lbValue value = {}; + + Entity *proc_entity = entity_of_node(proc_expr); + if (proc_entity != nullptr) { + if (proc_entity->flags & EntityFlag_Disabled) { + GB_ASSERT(tv.type == nullptr); + return {}; + } + } + + if (proc_expr->tav.mode == Addressing_Constant) { + ExactValue v = proc_expr->tav.value; + switch (v.kind) { + case ExactValue_Integer: + { + u64 u = big_int_to_u64(&v.value_integer); + lbValue x = {}; + x.value = LLVMConstInt(lb_type(m, t_uintptr), u, false); + x.type = t_uintptr; + x = lb_emit_conv(p, x, t_rawptr); + value = lb_emit_conv(p, x, proc_expr->tav.type); + break; + } + case ExactValue_Pointer: + { + u64 u = cast(u64)v.value_pointer; + lbValue x = {}; + x.value = LLVMConstInt(lb_type(m, t_uintptr), u, false); + x.type = t_uintptr; + x = lb_emit_conv(p, x, t_rawptr); + value = lb_emit_conv(p, x, proc_expr->tav.type); + break; + } + } + } + + if (value.value == nullptr) { + value = lb_build_expr(p, proc_expr); + } + + GB_ASSERT(value.value != nullptr); + Type *proc_type_ = base_type(value.type); + GB_ASSERT(proc_type_->kind == Type_Proc); + TypeProc *pt = &proc_type_->Proc; + + GB_ASSERT(ce->split_args != nullptr); auto args = array_make<lbValue>(permanent_allocator(), 0, pt->param_count); bool vari_expand = (ce->ellipsis.pos.line != 0); + bool is_c_vararg = pt->c_vararg; - for_array(i, split_args->positional) { + for_array(i, ce->split_args->positional) { Entity *e = pt->params->Tuple.variables[i]; if (e->kind == Entity_TypeName) { array_add(&args, lb_const_nil(p->module, e->type)); @@ -3177,12 +3258,28 @@ gb_internal lbValue lb_build_call_expr_internal_with_arg_split_args(lbProcedure if (pt->variadic && pt->variadic_index == i) { lbValue variadic_args = lb_const_nil(p->module, e->type); - auto variadic = slice(split_args->positional, pt->variadic_index, split_args->positional.count); + auto variadic = slice(ce->split_args->positional, pt->variadic_index, ce->split_args->positional.count); if (variadic.count != 0) { // variadic call argument generation Type *slice_type = e->type; GB_ASSERT(slice_type->kind == Type_Slice); - if (vari_expand) { + + if (is_c_vararg) { + GB_PANIC("TODO #c_vararg"); + GB_ASSERT(!vari_expand); + + Type *elem_type = slice_type->Slice.elem; + + for (Ast *var_arg : variadic) { + lbValue arg = lb_build_expr(p, var_arg); + if (!is_type_any(elem_type)) { + array_add(&args, lb_emit_conv(p, arg, elem_type)); + } else { + array_add(&args, lb_emit_conv(p, arg, default_type(arg.type))); + } + } + break; + } else if (vari_expand) { GB_ASSERT(variadic.count == 1); variadic_args = lb_build_expr(p, variadic[0]); variadic_args = lb_emit_conv(p, variadic_args, slice_type); @@ -3219,14 +3316,14 @@ gb_internal lbValue lb_build_call_expr_internal_with_arg_split_args(lbProcedure break; } else { - lbValue value = lb_build_expr(p, split_args->positional[i]); + lbValue value = lb_build_expr(p, ce->split_args->positional[i]); lb_add_values_to_array(p, &args, value); } } array_resize(&args, pt->param_count); - for (Ast *arg : split_args->named) { + for (Ast *arg : ce->split_args->named) { ast_node(fv, FieldValue, arg); GB_ASSERT(fv->field->kind == Ast_Ident); String name = fv->field->Ident.token.string; @@ -3243,6 +3340,7 @@ gb_internal lbValue lb_build_call_expr_internal_with_arg_split_args(lbProcedure if (pt->params != nullptr) { + GB_ASSERT(args.count >= pt->params->Tuple.variables.count); for_array(arg_index, pt->params->Tuple.variables) { Entity *e = pt->params->Tuple.variables[arg_index]; @@ -3269,84 +3367,8 @@ gb_internal lbValue lb_build_call_expr_internal_with_arg_split_args(lbProcedure } - return lb_emit_call(p, value, args, ce->inlining); -} - -gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) { - lbModule *m = p->module; - - TypeAndValue tv = type_and_value_of_expr(expr); - - ast_node(ce, CallExpr, expr); - - TypeAndValue proc_tv = type_and_value_of_expr(ce->proc); - AddressingMode proc_mode = proc_tv.mode; - if (proc_mode == Addressing_Type) { - GB_ASSERT(ce->args.count == 1); - lbValue x = lb_build_expr(p, ce->args[0]); - lbValue y = lb_emit_conv(p, x, tv.type); - return y; - } - - Ast *proc_expr = unparen_expr(ce->proc); - if (proc_mode == Addressing_Builtin) { - Entity *e = entity_of_node(proc_expr); - BuiltinProcId id = BuiltinProc_Invalid; - if (e != nullptr) { - id = cast(BuiltinProcId)e->Builtin.id; - } else { - id = BuiltinProc_DIRECTIVE; - } - return lb_build_builtin_proc(p, expr, tv, id); - } - - // NOTE(bill): Regular call - lbValue value = {}; - - Entity *proc_entity = entity_of_node(proc_expr); - if (proc_entity != nullptr) { - if (proc_entity->flags & EntityFlag_Disabled) { - GB_ASSERT(tv.type == nullptr); - return {}; - } - } - - if (proc_expr->tav.mode == Addressing_Constant) { - ExactValue v = proc_expr->tav.value; - switch (v.kind) { - case ExactValue_Integer: - { - u64 u = big_int_to_u64(&v.value_integer); - lbValue x = {}; - x.value = LLVMConstInt(lb_type(m, t_uintptr), u, false); - x.type = t_uintptr; - x = lb_emit_conv(p, x, t_rawptr); - value = lb_emit_conv(p, x, proc_expr->tav.type); - break; - } - case ExactValue_Pointer: - { - u64 u = cast(u64)v.value_pointer; - lbValue x = {}; - x.value = LLVMConstInt(lb_type(m, t_uintptr), u, false); - x.type = t_uintptr; - x = lb_emit_conv(p, x, t_rawptr); - value = lb_emit_conv(p, x, proc_expr->tav.type); - break; - } - } - } - - if (value.value == nullptr) { - value = lb_build_expr(p, proc_expr); - } - - GB_ASSERT(value.value != nullptr); - Type *proc_type_ = base_type(value.type); - GB_ASSERT(proc_type_->kind == Type_Proc); - TypeProc *pt = &proc_type_->Proc; - - GB_ASSERT(ce->split_args != nullptr); - return lb_build_call_expr_internal_with_arg_split_args(p, value, pt, expr, ce->split_args); + isize final_count = is_c_vararg ? args.count : pt->param_count; + auto call_args = array_slice(args, 0, final_count); + return lb_emit_call(p, value, call_args, ce->inlining); } |