Fix IR generation issue

This commit is contained in:
gingerBill
2017-11-05 19:37:46 +00:00
parent 66ee2cb6ed
commit 74341b9b74
+34 -26
View File
@@ -5031,6 +5031,8 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
return ir_emit_call(proc, value, args, param_count); return ir_emit_call(proc, value, args, param_count);
} }
isize arg_index = 0;
isize arg_count = 0; isize arg_count = 0;
for_array(i, ce->args) { for_array(i, ce->args) {
AstNode *a = ce->args[i]; AstNode *a = ce->args[i];
@@ -5042,8 +5044,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
} }
} }
Array<irValue *> args = {}; irValue **args = gb_alloc_array(proc->module->allocator, irValue *, gb_max(type->param_count, arg_count));
array_init(&args, proc->module->allocator, gb_max(type->param_count, arg_count));
bool variadic = type->variadic; bool variadic = type->variadic;
bool vari_expand = ce->ellipsis.pos.line != 0; bool vari_expand = ce->ellipsis.pos.line != 0;
bool is_c_vararg = type->c_vararg; bool is_c_vararg = type->c_vararg;
@@ -5052,7 +5053,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
AstNode *arg = ce->args[i]; AstNode *arg = ce->args[i];
TypeAndValue arg_tv = type_and_value_of_expr(proc->module->info, arg); TypeAndValue arg_tv = type_and_value_of_expr(proc->module->info, arg);
if (arg_tv.mode == Addressing_Type) { if (arg_tv.mode == Addressing_Type) {
array_add(&args, ir_value_nil(proc->module->allocator, arg_tv.type)); args[arg_index++] = ir_value_nil(proc->module->allocator, arg_tv.type);
} else { } else {
irValue *a = ir_build_expr(proc, arg); irValue *a = ir_build_expr(proc, arg);
Type *at = ir_type(a); Type *at = ir_type(a);
@@ -5060,46 +5061,51 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
for_array(i, at->Tuple.variables) { for_array(i, at->Tuple.variables) {
Entity *e = at->Tuple.variables[i]; Entity *e = at->Tuple.variables[i];
irValue *v = ir_emit_struct_ev(proc, a, cast(i32)i); irValue *v = ir_emit_struct_ev(proc, a, cast(i32)i);
array_add(&args, v); args[arg_index++] = v;
} }
} else { } else {
array_add(&args, a); args[arg_index++] = a;
} }
} }
} }
i64 param_count = type->param_count;
if (type->param_count > 0) {
GB_ASSERT_MSG(type->params != nullptr, "%s %td", expr_to_string(expr), type->param_count);
TypeTuple *pt = &type->params->Tuple; TypeTuple *pt = &type->params->Tuple;
param_count = type->param_count;
GB_ASSERT(param_count < 1000000);
if (arg_count < type->param_count) { if (arg_count < param_count) {
String procedure = {}; String procedure = {};
if (proc->entity != nullptr) { if (proc->entity != nullptr) {
procedure = proc->entity->token.string; procedure = proc->entity->token.string;
} }
TokenPos pos = ast_node_token(ce->proc).pos; TokenPos pos = ast_node_token(ce->proc).pos;
isize end = type->param_count; isize end = param_count;
if (variadic) { if (variadic) {
end--; end--;
} }
while (args.count < end) { while (arg_index < end) {
Entity *e = pt->variables[args.count]; Entity *e = pt->variables[arg_index];
GB_ASSERT(e->kind == Entity_Variable); GB_ASSERT(e->kind == Entity_Variable);
if (e->Variable.default_value.kind != ExactValue_Invalid) { if (e->Variable.default_value.kind != ExactValue_Invalid) {
array_add(&args, ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value)); args[arg_index++] = ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value);
} else if (e->Variable.default_is_location) { } else if (e->Variable.default_is_location) {
array_add(&args, ir_emit_source_code_location(proc, procedure, pos)); args[arg_index++] = ir_emit_source_code_location(proc, procedure, pos);
} else { } else {
array_add(&args, ir_value_nil(proc->module->allocator, e->type)); args[arg_index++] = ir_value_nil(proc->module->allocator, e->type);
} }
} }
} }
if (is_c_vararg) { if (is_c_vararg) {
GB_ASSERT(variadic); GB_ASSERT(variadic);
GB_ASSERT(!vari_expand); GB_ASSERT(!vari_expand);
isize i = 0; isize i = 0;
for (; i < type->param_count-1; i++) { for (; i < param_count-1; i++) {
Entity *e = pt->variables[i]; Entity *e = pt->variables[i];
if (e->kind == Entity_Variable) { if (e->kind == Entity_Variable) {
args[i] = ir_emit_conv(proc, args[i], e->type); args[i] = ir_emit_conv(proc, args[i], e->type);
@@ -5119,7 +5125,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
} }
} else if (variadic) { } else if (variadic) {
isize i = 0; isize i = 0;
for (; i < type->param_count-1; i++) { for (; i < param_count-1; i++) {
Entity *e = pt->variables[i]; Entity *e = pt->variables[i];
if (e->kind == Entity_Variable) { if (e->kind == Entity_Variable) {
args[i] = ir_emit_conv(proc, args[i], e->type); args[i] = ir_emit_conv(proc, args[i], e->type);
@@ -5134,31 +5140,27 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
} }
} }
} else { } else {
for (isize i = 0; i < type->param_count; i++) { for (i64 i = 0; i < param_count; i++) {
Entity *e = pt->variables[i]; Entity *e = pt->variables[i];
if (e->kind == Entity_Variable) { if (e->kind == Entity_Variable) {
GB_ASSERT(args[i] != nullptr);
args[i] = ir_emit_conv(proc, args[i], e->type); args[i] = ir_emit_conv(proc, args[i], e->type);
} }
} }
} }
i64 final_count = type->param_count;
if (is_c_vararg) {
final_count = arg_count;
}
if (variadic && !vari_expand && !is_c_vararg) { if (variadic && !vari_expand && !is_c_vararg) {
ir_emit_comment(proc, str_lit("variadic call argument generation")); ir_emit_comment(proc, str_lit("variadic call argument generation"));
gbAllocator allocator = proc->module->allocator; gbAllocator allocator = proc->module->allocator;
Type *slice_type = pt->variables[type->param_count-1]->type; Type *slice_type = pt->variables[param_count-1]->type;
Type *elem_type = base_type(slice_type)->Slice.elem; Type *elem_type = base_type(slice_type)->Slice.elem;
irValue *slice = ir_add_local_generated(proc, slice_type); irValue *slice = ir_add_local_generated(proc, slice_type);
isize slice_len = arg_count+1 - type->param_count; isize slice_len = arg_count+1 - param_count;
if (slice_len > 0) { if (slice_len > 0) {
irValue *base_array = ir_add_local_generated(proc, make_type_array(allocator, elem_type, slice_len)); irValue *base_array = ir_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++) { for (isize i = param_count-1, j = 0; i < arg_count; i++, j++) {
irValue *addr = ir_emit_array_epi(proc, base_array, cast(i32)j); irValue *addr = ir_emit_array_epi(proc, base_array, cast(i32)j);
ir_emit_store(proc, addr, args[i]); ir_emit_store(proc, addr, args[i]);
} }
@@ -5168,11 +5170,17 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
ir_fill_slice(proc, slice, base_elem, len, len); ir_fill_slice(proc, slice, base_elem, len, len);
} }
arg_count = type->param_count; arg_count = param_count;
args[arg_count-1] = ir_emit_load(proc, slice); args[arg_count-1] = ir_emit_load(proc, slice);
} }
}
return ir_emit_call(proc, value, args.data, final_count); i64 final_count = param_count;
if (is_c_vararg) {
final_count = arg_count;
}
return ir_emit_call(proc, value, args, final_count);
case_end; case_end;
case_ast_node(se, SliceExpr, expr); case_ast_node(se, SliceExpr, expr);