aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/codegen.cpp2
-rw-r--r--src/codegen/ssa.cpp66
2 files changed, 62 insertions, 6 deletions
diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp
index 8235fb615..735dfd580 100644
--- a/src/codegen/codegen.cpp
+++ b/src/codegen/codegen.cpp
@@ -131,7 +131,7 @@ void ssa_gen_code(ssaGen *s) {
String name = make_string(SSA_STARTUP_RUNTIME_PROC_NAME);
Type *proc_type = make_type_proc(a, gb_alloc_item(a, Scope),
NULL, 0,
- NULL, 0);
+ NULL, 0, false);
AstNode *body = gb_alloc_item(a, AstNode);
ssaValue *p = ssa_make_value_procedure(a, m, proc_type, NULL, body, name);
Token token = {};
diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp
index 0616a9302..24a350034 100644
--- a/src/codegen/ssa.cpp
+++ b/src/codegen/ssa.cpp
@@ -2159,10 +2159,23 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
auto *type = &proc_type_->Proc;
isize arg_index = 0;
- isize arg_count = type->param_count;
+
+ isize arg_count = 0;
+ for (AstNode *a = ce->arg_list; a != NULL; a = a->next) {
+ Type *at = get_base_type(type_of_expr(proc->module->info, a));
+ if (at->kind == Type_Tuple) {
+ arg_count += at->Tuple.variable_count;
+ } else {
+ arg_count++;
+ }
+ }
ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, arg_count);
+ b32 variadic = proc_type_->Proc.variadic;
- for (AstNode *arg = ce->arg_list; arg != NULL; arg = arg->next) {
+ AstNode *arg = ce->arg_list;
+ for (;
+ arg != NULL;
+ arg = arg->next) {
ssaValue *a = ssa_build_expr(proc, arg);
Type *at = ssa_type(a);
if (at->kind == Type_Tuple) {
@@ -2176,11 +2189,54 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
}
}
- auto *pt = &proc_type_->Proc.params->Tuple;
- for (isize i = 0; i < arg_count; i++) {
- args[i] = ssa_emit_conv(proc, args[i], pt->variables[i]->type, true);
+ auto *pt = &type->params->Tuple;
+
+ if (variadic) {
+ isize i = 0;
+ for (; i < type->param_count-1; i++) {
+ args[i] = ssa_emit_conv(proc, args[i], pt->variables[i]->type, true);
+ }
+ Type *variadic_type = pt->variables[i]->type;
+ GB_ASSERT(is_type_slice(variadic_type));
+ variadic_type = get_base_type(variadic_type)->Slice.elem;
+ for (; i < arg_count; i++) {
+ args[i] = ssa_emit_conv(proc, args[i], variadic_type, true);
+ }
+ } else {
+ for (isize i = 0; i < arg_count; i++) {
+ args[i] = ssa_emit_conv(proc, args[i], pt->variables[i]->type, true);
+ }
}
+ if (variadic) {
+ gbAllocator allocator = proc->module->allocator;
+ Type *slice_type = pt->variables[type->param_count-1]->type;
+ Type *elem_type = get_base_type(slice_type)->Slice.elem;
+ Type *elem_ptr_type = make_type_pointer(allocator, elem_type);
+ ssaValue *slice = ssa_add_local_generated(proc, slice_type);
+ isize slice_len = arg_count+1 - type->param_count;
+
+ if (slice_len > 0) {
+ ssaValue *base_array = ssa_add_local_generated(proc, make_type_array(allocator, elem_type, slice_len));
+
+ for (isize i = type->param_count-1, j = 0; i < arg_count; i++, j++) {
+ ssaValue *addr = ssa_emit_struct_gep(proc, base_array, j, elem_type);
+ ssa_emit_store(proc, addr, args[i]);
+ }
+
+ ssaValue *base_elem = ssa_emit_struct_gep(proc, base_array, v_zero32, elem_type);
+ ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_zero32, elem_ptr_type), base_elem);
+ ssaValue *len = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(slice_len));
+ ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_one32, t_int), len);
+ ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_two32, t_int), len);
+ }
+
+
+ arg_count = type->param_count;
+ args[arg_count-1] = ssa_emit_load(proc, slice);
+ }
+
+
return ssa_emit_call(proc, value, args, arg_count);
case_end;