|
@@ -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);
|
|
|
}
|
|
|
|