Fix exact value bug when updating expressions

This commit is contained in:
Ginger Bill
2016-10-16 00:26:53 +01:00
parent 79af939522
commit b9719df0ad
8 changed files with 86 additions and 52 deletions
+7
View File
@@ -1,6 +1,13 @@
#import "fmt.odin" #import "fmt.odin"
main :: proc() { main :: proc() {
Thing :: struct {
f: f32
a: any
}
t := Thing{1, "Hello"}
fmt.printf("Here % %\n", 123, 2.0)
} }
+7 -8
View File
@@ -74,11 +74,12 @@ type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
if info == nil { if info == nil {
return nil return nil
} }
match type i : info { base := info
match type i : base {
case Type_Info.Named: case Type_Info.Named:
info = i.base base = i.base
} }
return info return base
} }
@@ -259,10 +260,10 @@ __string_eq :: proc(a, b: string) -> bool {
if a.count != b.count { if a.count != b.count {
return false return false
} }
if ^a[0] == ^b[0] { if a.data == b.data {
return true return true
} }
return mem.compare(^a[0], ^b[0], a.count) == 0 return mem.compare(a.data, b.data, a.count) == 0
} }
__string_cmp :: proc(a, b : string) -> int { __string_cmp :: proc(a, b : string) -> int {
@@ -312,9 +313,7 @@ __substring_expr_error :: proc(file: string, line, column: int,
} }
__enum_to_string :: proc(info: ^Type_Info, value: i64) -> string { __enum_to_string :: proc(info: ^Type_Info, value: i64) -> string {
info = type_info_base(info) match type ti : type_info_base(info) {
match type ti : info {
case Type_Info.Enum: case Type_Info.Enum:
// TODO(bill): Search faster than linearly // TODO(bill): Search faster than linearly
for i := 0; i < ti.values.count; i++ { for i := 0; i < ti.values.count; i++ {
+7 -5
View File
@@ -90,7 +90,8 @@ print_pointer_to_buffer :: proc(buffer: ^[]byte, p: rawptr) #inline {
print_f32_to_buffer :: proc(buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 7) } print_f32_to_buffer :: proc(buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 7) }
print_f64_to_buffer :: proc(buffer: ^[]byte, f: f64) #inline { print__f64(buffer, f, 10) } print_f64_to_buffer :: proc(buffer: ^[]byte, f: f64) #inline { print__f64(buffer, f, 10) }
print_u64_to_buffer :: proc(buffer: ^[]byte, i: u64) { print_u64_to_buffer :: proc(buffer: ^[]byte, value: u64) {
i := value
buf: [22]byte buf: [22]byte
len := 0 len := 0
if i == 0 { if i == 0 {
@@ -105,7 +106,8 @@ print_u64_to_buffer :: proc(buffer: ^[]byte, i: u64) {
byte_reverse(buf[:len]) byte_reverse(buf[:len])
print_string_to_buffer(buffer, buf[:len] as string) print_string_to_buffer(buffer, buf[:len] as string)
} }
print_i64_to_buffer :: proc(buffer: ^[]byte, i: i64) { print_i64_to_buffer :: proc(buffer: ^[]byte, value: i64) {
i := value
neg := i < 0 neg := i < 0
if neg { if neg {
i = -i i = -i
@@ -114,7 +116,8 @@ print_i64_to_buffer :: proc(buffer: ^[]byte, i: i64) {
print_u64_to_buffer(buffer, i as u64) print_u64_to_buffer(buffer, i as u64)
} }
print__f64 :: proc(buffer: ^[]byte, f: f64, decimal_places: int) { print__f64 :: proc(buffer: ^[]byte, value: f64, decimal_places: int) {
f := value
if f == 0 { if f == 0 {
print_rune_to_buffer(buffer, #rune "0") print_rune_to_buffer(buffer, #rune "0")
return return
@@ -555,12 +558,11 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) {
bprint :: proc(buf: ^[]byte, args: ..any) { bprint :: proc(buf: ^[]byte, args: ..any) {
is_type_string :: proc(info: ^Type_Info) -> bool { is_type_string :: proc(info: ^Type_Info) -> bool {
using Type_Info using Type_Info
info = type_info_base(info)
if info == nil { if info == nil {
return false return false
} }
match type i : info { match type i : type_info_base(info) {
case String: case String:
return true return true
} }
+2 -1
View File
@@ -39,7 +39,8 @@ accept_sizes := [256]byte{
0x34, 0x04, 0x04, 0x04, 0x44, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xf0-0xff 0x34, 0x04, 0x04, 0x04, 0x44, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xf0-0xff
} }
encode_rune :: proc(r: rune) -> ([4]byte, int) { encode_rune :: proc(r_: rune) -> ([4]byte, int) {
r := r_
buf: [4]byte buf: [4]byte
i := r as u32 i := r as u32
mask: byte : 0x3f mask: byte : 0x3f
+1 -2
View File
@@ -645,7 +645,6 @@ void add_untyped(CheckerInfo *i, AstNode *expression, b32 lhs, AddressingMode mo
map_set(&i->untyped, hash_pointer(expression), make_expression_info(lhs, mode, basic_type, value)); map_set(&i->untyped, hash_pointer(expression), make_expression_info(lhs, mode, basic_type, value));
} }
void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode, Type *type, ExactValue value) { void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode, Type *type, ExactValue value) {
GB_ASSERT(expression != NULL); GB_ASSERT(expression != NULL);
if (mode == Addressing_Invalid) if (mode == Addressing_Invalid)
@@ -1306,7 +1305,7 @@ void check_parsed_files(Checker *c) {
ExpressionInfo *info = &entry->value; ExpressionInfo *info = &entry->value;
if (info != NULL && expr != NULL) { if (info != NULL && expr != NULL) {
if (is_type_typed(info->type)) { if (is_type_typed(info->type)) {
compiler_error("%s (type %s) is typed!", expr_to_string(expr), info->type); compiler_error("%s (type %s) is typed!", expr_to_string(expr), type_to_string(info->type));
} }
add_type_and_value(&c->info, expr, info->mode, info->type, info->value); add_type_and_value(&c->info, expr, info->mode, info->type, info->value);
} }
+36 -18
View File
@@ -933,7 +933,11 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
o->type = t_invalid; o->type = t_invalid;
return; return;
} }
o->mode = Addressing_Variable; // if (e->Variable.param) {
// o->mode = Addressing_Value;
// } else {
o->mode = Addressing_Variable;
// }
break; break;
case Entity_TypeName: { case Entity_TypeName: {
@@ -2239,7 +2243,6 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
operand->type = target_type; operand->type = target_type;
update_expr_type(c, operand->expr, target_type, true);
} }
b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *value) { b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *value) {
@@ -3265,7 +3268,6 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
defer (gb_temp_arena_memory_end(tmp)); defer (gb_temp_arena_memory_end(tmp));
isize operand_count = 0;
Array<Operand> operands; Array<Operand> operands;
array_init(&operands, c->tmp_allocator, 2*param_count); array_init(&operands, c->tmp_allocator, 2*param_count);
@@ -3289,11 +3291,10 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
} }
} }
operand_count = operands.count;
i32 error_code = 0; i32 error_code = 0;
if (operand_count < param_count) { if (operands.count < param_count) {
error_code = -1; error_code = -1;
} else if (!variadic && operand_count > param_count) { } else if (!variadic && operands.count > param_count) {
error_code = +1; error_code = +1;
} }
if (error_code != 0) { if (error_code != 0) {
@@ -3303,16 +3304,22 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
} }
gbString proc_str = expr_to_string(ce->proc); gbString proc_str = expr_to_string(ce->proc);
defer (gb_string_free(proc_str));
error(ast_node_token(call), err_fmt, proc_str, param_count); error(ast_node_token(call), err_fmt, proc_str, param_count);
gb_string_free(proc_str);
operand->mode = Addressing_Invalid; operand->mode = Addressing_Invalid;
} }
GB_ASSERT(proc_type->Proc.params != NULL); GB_ASSERT(proc_type->Proc.params != NULL);
Entity **sig_params = proc_type->Proc.params->Tuple.variables; Entity **sig_params = proc_type->Proc.params->Tuple.variables;
for (isize i = 0; i < param_count; i++) { isize operand_index = 0;
Type *arg_type = sig_params[i]->type; for (; operand_index < param_count; operand_index++) {
check_assignment(c, &operands[i], arg_type, make_string("argument"), true); Type *arg_type = sig_params[operand_index]->type;
Operand o = operands[operand_index];
if (variadic) {
o = operands[operand_index];
}
check_assignment(c, &o, arg_type, make_string("argument"), true);
} }
if (variadic) { if (variadic) {
@@ -3320,18 +3327,18 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
Type *slice = sig_params[param_count]->type; Type *slice = sig_params[param_count]->type;
Type *elem = base_type(slice)->Slice.elem; Type *elem = base_type(slice)->Slice.elem;
Type *t = elem; Type *t = elem;
for (isize i = param_count; i < operand_count; i++) { for (; operand_index < operands.count; operand_index++) {
Operand *o = &operands[i]; Operand o = operands[operand_index];
if (vari_expand) { if (vari_expand) {
variadic_expand = true; variadic_expand = true;
t = slice; t = slice;
if (i != param_count) { if (operand_index != param_count) {
error(ast_node_token(o->expr), error(ast_node_token(o.expr),
"`..` in a variadic procedure can only have one variadic argument at the end"); "`..` in a variadic procedure can only have one variadic argument at the end");
break; break;
} }
} }
check_assignment(c, o, t, make_string("argument"), true); check_assignment(c, &o, t, make_string("argument"), true);
} }
} }
} }
@@ -3574,10 +3581,14 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
fields_visited[sel.index[0]] = true; fields_visited[sel.index[0]] = true;
check_expr(c, o, fv->value); check_expr(c, o, fv->value);
if (base_type(field->type) == t_any) {
is_constant = false;
}
if (is_constant) { if (is_constant) {
is_constant = o->mode == Addressing_Constant; is_constant = o->mode == Addressing_Constant;
} }
check_assignment(c, o, field->type, make_string("structure literal")); check_assignment(c, o, field->type, make_string("structure literal"));
} }
} else { } else {
@@ -3596,6 +3607,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
break; break;
} }
if (base_type(field->type) == t_any) {
is_constant = false;
}
if (is_constant) { if (is_constant) {
is_constant = o->mode == Addressing_Constant; is_constant = o->mode == Addressing_Constant;
} }
@@ -3632,15 +3646,18 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
isize index = 0; isize index = 0;
isize elem_count = cl->elems.count; isize elem_count = cl->elems.count;
if (base_type(elem_type) == t_any) {
is_constant = false;
}
for (; index < elem_count; index++) { for (; index < elem_count; index++) {
AstNode *e = cl->elems[index]; AstNode *e = cl->elems[index];
if (e->kind == AstNode_FieldValue) { if (e->kind == AstNode_FieldValue) {
error(ast_node_token(e), error(ast_node_token(e),
"`field = value` is only allowed in structure literals"); "`field = value` is only allowed in struct literals");
continue; continue;
} }
if (t->kind == Type_Array && if (t->kind == Type_Array &&
t->Array.count >= 0 && t->Array.count >= 0 &&
index >= t->Array.count) { index >= t->Array.count) {
@@ -3660,8 +3677,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
is_constant = operand.mode == Addressing_Constant; is_constant = operand.mode == Addressing_Constant;
} }
} }
if (max < index) if (max < index) {
max = index; max = index;
}
if (t->kind == Type_Vector) { if (t->kind == Type_Vector) {
if (t->Vector.count > 1 && gb_is_between(index, 2, t->Vector.count-1)) { if (t->Vector.count > 1 && gb_is_between(index, 2, t->Vector.count-1)) {
+3 -6
View File
@@ -145,12 +145,10 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
case Basic_i16: ssa_fprintf(f, "i16"); break; case Basic_i16: ssa_fprintf(f, "i16"); break;
case Basic_i32: ssa_fprintf(f, "i32"); break; case Basic_i32: ssa_fprintf(f, "i32"); break;
case Basic_i64: ssa_fprintf(f, "i64"); break; case Basic_i64: ssa_fprintf(f, "i64"); break;
// case Basic_i128: ssa_fprintf(f, "i128"); break;
case Basic_u8: ssa_fprintf(f, "i8"); break; case Basic_u8: ssa_fprintf(f, "i8"); break;
case Basic_u16: ssa_fprintf(f, "i16"); break; case Basic_u16: ssa_fprintf(f, "i16"); break;
case Basic_u32: ssa_fprintf(f, "i32"); break; case Basic_u32: ssa_fprintf(f, "i32"); break;
case Basic_u64: ssa_fprintf(f, "i64"); break; case Basic_u64: ssa_fprintf(f, "i64"); break;
// case Basic_u128: ssa_fprintf(f, "i128"); break;
case Basic_f32: ssa_fprintf(f, "float"); break; case Basic_f32: ssa_fprintf(f, "float"); break;
case Basic_f64: ssa_fprintf(f, "double"); break; case Basic_f64: ssa_fprintf(f, "double"); break;
case Basic_rawptr: ssa_fprintf(f, "%%..rawptr"); break; case Basic_rawptr: ssa_fprintf(f, "%%..rawptr"); break;
@@ -176,12 +174,11 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
ssa_print_type(f, m, t->Array.elem); ssa_print_type(f, m, t->Array.elem);
ssa_fprintf(f, "]"); ssa_fprintf(f, "]");
break; break;
case Type_Vector: { case Type_Vector:
// TODO(bill): actually do correctly
ssa_fprintf(f, "<%lld x ", t->Vector.count); ssa_fprintf(f, "<%lld x ", t->Vector.count);
ssa_print_type(f, m, t->Vector.elem); ssa_print_type(f, m, t->Vector.elem);
ssa_fprintf(f, ">"); ssa_fprintf(f, ">");
} break; break;
case Type_Slice: case Type_Slice:
ssa_fprintf(f, "{"); ssa_fprintf(f, "{");
ssa_print_type(f, m, t->Slice.elem); ssa_print_type(f, m, t->Slice.elem);
@@ -278,7 +275,7 @@ void ssa_print_compound_element(ssaFileBuffer *f, ssaModule *m, ExactValue v, Ty
ssa_fprintf(f, " "); ssa_fprintf(f, " ");
} }
if (v.kind == ExactValue_Invalid) { if (v.kind == ExactValue_Invalid || base_type(elem_type) == t_any) {
ssa_fprintf(f, "zeroinitializer"); ssa_fprintf(f, "zeroinitializer");
} else if (v.kind == ExactValue_String) { } else if (v.kind == ExactValue_String) {
// HACK NOTE(bill): This is a hack but it works because strings are created at the very end // HACK NOTE(bill): This is a hack but it works because strings are created at the very end
+23 -12
View File
@@ -1418,6 +1418,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
proc->curr_block = proc->decl_block; proc->curr_block = proc->decl_block;
ssa_emit_jump(proc, proc->entry_block); ssa_emit_jump(proc, proc->entry_block);
#if 0
ssa_optimize_blocks(proc); ssa_optimize_blocks(proc);
ssa_build_referrers(proc); ssa_build_referrers(proc);
ssa_build_dom_tree(proc); ssa_build_dom_tree(proc);
@@ -1428,7 +1429,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
// [ ] Local stored once? Replace loads with dominating store // [ ] Local stored once? Replace loads with dominating store
// [ ] Convert to phi nodes // [ ] Convert to phi nodes
ssa_opt_mem2reg(proc); ssa_opt_mem2reg(proc);
#endif
// Number registers // Number registers
i32 reg_index = 0; i32 reg_index = 0;
@@ -1923,6 +1924,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
ev = exact_value_to_float(ev); ev = exact_value_to_float(ev);
} else if (is_type_string(dst)) { } else if (is_type_string(dst)) {
// Handled elsewhere // Handled elsewhere
GB_ASSERT(ev.kind == ExactValue_String);
} else if (is_type_integer(dst)) { } else if (is_type_integer(dst)) {
ev = exact_value_to_integer(ev); ev = exact_value_to_integer(ev);
} else if (is_type_pointer(dst)) { } else if (is_type_pointer(dst)) {
@@ -2479,7 +2481,10 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
case Type_Slice: et = bt->Slice.elem; break; case Type_Slice: et = bt->Slice.elem; break;
} }
auto is_elem_const = [](ssaModule *m, AstNode *elem) -> b32 { auto is_elem_const = [](ssaModule *m, AstNode *elem, Type *elem_type) -> b32 {
if (base_type(elem_type) == t_any) {
return false;
}
if (elem->kind == AstNode_FieldValue) { if (elem->kind == AstNode_FieldValue) {
elem = elem->FieldValue.value; elem = elem->FieldValue.value;
} }
@@ -2495,7 +2500,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssaValue *result = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)); ssaValue *result = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr));
for_array(index, cl->elems) { for_array(index, cl->elems) {
AstNode *elem = cl->elems[index]; AstNode *elem = cl->elems[index];
if (is_elem_const(proc->module, elem)) { if (is_elem_const(proc->module, elem, et)) {
continue; continue;
} }
ssaValue *field_elem = ssa_build_expr(proc, elem); ssaValue *field_elem = ssa_build_expr(proc, elem);
@@ -2526,9 +2531,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr))); ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
for_array(field_index, cl->elems) { for_array(field_index, cl->elems) {
AstNode *elem = cl->elems[field_index]; AstNode *elem = cl->elems[field_index];
if (is_elem_const(proc->module, elem)) {
continue;
}
ssaValue *field_expr = NULL; ssaValue *field_expr = NULL;
Entity *field = NULL; Entity *field = NULL;
@@ -2538,17 +2540,23 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ast_node(fv, FieldValue, elem); ast_node(fv, FieldValue, elem);
Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false); Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false);
index = sel.index[0]; index = sel.index[0];
field_expr = ssa_build_expr(proc, fv->value); elem = fv->value;
} else { } else {
TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem); TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem);
Selection sel = lookup_field(proc->module->allocator, bt, st->fields_in_src_order[field_index]->token.string, false); Selection sel = lookup_field(proc->module->allocator, bt, st->fields_in_src_order[field_index]->token.string, false);
index = sel.index[0]; index = sel.index[0];
field_expr = ssa_build_expr(proc, elem);
} }
field = st->fields[index];
if (is_elem_const(proc->module, elem, field->type)) {
continue;
}
field_expr = ssa_build_expr(proc, elem);
GB_ASSERT(ssa_type(field_expr)->kind != Type_Tuple); GB_ASSERT(ssa_type(field_expr)->kind != Type_Tuple);
field = st->fields[index];
Type *ft = field->type; Type *ft = field->type;
ssaValue *fv = ssa_emit_conv(proc, field_expr, ft); ssaValue *fv = ssa_emit_conv(proc, field_expr, ft);
@@ -2562,7 +2570,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr))); ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
for_array(i, cl->elems) { for_array(i, cl->elems) {
AstNode *elem = cl->elems[i]; AstNode *elem = cl->elems[i];
if (is_elem_const(proc->module, elem)) { if (is_elem_const(proc->module, elem, et)) {
continue; continue;
} }
ssaValue *field_expr = ssa_build_expr(proc, elem); ssaValue *field_expr = ssa_build_expr(proc, elem);
@@ -2587,7 +2595,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
for_array(i, cl->elems) { for_array(i, cl->elems) {
AstNode *elem = cl->elems[i]; AstNode *elem = cl->elems[i];
if (is_elem_const(proc->module,elem)) { if (is_elem_const(proc->module, elem, et)) {
continue; continue;
} }
@@ -3034,12 +3042,15 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_two32, t_int), len); ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_two32, t_int), len);
} }
if (args[0]->kind == ssaValue_Constant) {
auto *c = &args[0]->Constant;
gb_printf_err("%s %d\n", type_to_string(c->type), c->value.kind);
}
arg_count = type->param_count; arg_count = type->param_count;
args[arg_count-1] = ssa_emit_load(proc, slice); args[arg_count-1] = ssa_emit_load(proc, slice);
} }
return ssa_emit_call(proc, value, args, arg_count); return ssa_emit_call(proc, value, args, arg_count);
case_end; case_end;