diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-06-13 21:00:42 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-06-13 21:00:42 +0100 |
| commit | c3b510c2d9adf1a9281285fc711a28187288af75 (patch) | |
| tree | 10c63d92cb2e014135f42bf9066907653ab395b3 /src/ir.cpp | |
| parent | e7fc24e48c39f1aa9f886d13608ad8e22f167027 (diff) | |
C-style `c_vararg`s (Not heavily tested)
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 2fafd7a8c..8fb3be9a7 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1477,7 +1477,11 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, irValue **args, isize arg_ Type *results = pt->Proc.results; isize param_count = pt->Proc.param_count; - GB_ASSERT(param_count == arg_count); + if (pt->Proc.c_vararg) { + GB_ASSERT(param_count-1 <= arg_count); + } else { + GB_ASSERT(param_count == arg_count); + } for (isize i = 0; i < param_count; i++) { Type *original_type = pt->Proc.params->Tuple.variables[i]->type; Type *new_type = pt->Proc.abi_compat_params[i]; @@ -4649,6 +4653,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { irValue **args = gb_alloc_array(proc->module->allocator, irValue *, gb_max(type->param_count, arg_count)); bool variadic = type->variadic; bool vari_expand = ce->ellipsis.pos.line != 0; + bool is_c_vararg = type->c_vararg; for_array(i, ce->args) { irValue *a = ir_build_expr(proc, ce->args[i]); @@ -4683,7 +4688,26 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { } - if (variadic) { + if (is_c_vararg) { + GB_ASSERT(variadic); + GB_ASSERT(!vari_expand); + isize i = 0; + for (; i < type->param_count-1; i++) { + args[i] = ir_emit_conv(proc, args[i], pt->variables[i]->type); + } + Type *variadic_type = pt->variables[i]->type; + GB_ASSERT(is_type_slice(variadic_type)); + variadic_type = base_type(variadic_type)->Slice.elem; + if (!is_type_any(variadic_type)) { + for (; i < arg_count; i++) { + args[i] = ir_emit_conv(proc, args[i], variadic_type); + } + } else { + for (; i < arg_count; i++) { + args[i] = ir_emit_conv(proc, args[i], default_type(ir_type(args[i]))); + } + } + } else if (variadic) { isize i = 0; for (; i < type->param_count-1; i++) { args[i] = ir_emit_conv(proc, args[i], pt->variables[i]->type); @@ -4702,7 +4726,12 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { } } - if (variadic && !vari_expand) { + i64 final_count = type->param_count; + if (is_c_vararg) { + final_count = arg_count; + } + + if (variadic && !vari_expand && !is_c_vararg) { ir_emit_comment(proc, str_lit("variadic call argument generation")); gbAllocator allocator = proc->module->allocator; Type *slice_type = pt->variables[type->param_count-1]->type; @@ -4727,7 +4756,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { args[arg_count-1] = ir_emit_load(proc, slice); } - return ir_emit_call(proc, value, args, type->param_count); + return ir_emit_call(proc, value, args, final_count); case_end; case_ast_node(se, SliceExpr, expr); |