mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 01:21:38 -07:00
Fix exact value bug when updating expressions
This commit is contained in:
@@ -1,6 +1,13 @@
|
||||
#import "fmt.odin"
|
||||
|
||||
main :: proc() {
|
||||
Thing :: struct {
|
||||
f: f32
|
||||
a: any
|
||||
}
|
||||
t := Thing{1, "Hello"}
|
||||
|
||||
|
||||
fmt.printf("Here % %\n", 123, 2.0)
|
||||
}
|
||||
|
||||
|
||||
+7
-8
@@ -74,11 +74,12 @@ type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||
if info == nil {
|
||||
return nil
|
||||
}
|
||||
match type i : info {
|
||||
base := info
|
||||
match type i : base {
|
||||
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 {
|
||||
return false
|
||||
}
|
||||
if ^a[0] == ^b[0] {
|
||||
if a.data == b.data {
|
||||
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 {
|
||||
@@ -312,9 +313,7 @@ __substring_expr_error :: proc(file: string, line, column: int,
|
||||
}
|
||||
|
||||
__enum_to_string :: proc(info: ^Type_Info, value: i64) -> string {
|
||||
info = type_info_base(info)
|
||||
|
||||
match type ti : info {
|
||||
match type ti : type_info_base(info) {
|
||||
case Type_Info.Enum:
|
||||
// TODO(bill): Search faster than linearly
|
||||
for i := 0; i < ti.values.count; i++ {
|
||||
|
||||
+7
-5
@@ -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_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
|
||||
len := 0
|
||||
if i == 0 {
|
||||
@@ -105,7 +106,8 @@ print_u64_to_buffer :: proc(buffer: ^[]byte, i: u64) {
|
||||
byte_reverse(buf[:len])
|
||||
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
|
||||
if neg {
|
||||
i = -i
|
||||
@@ -114,7 +116,8 @@ print_i64_to_buffer :: proc(buffer: ^[]byte, i: i64) {
|
||||
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 {
|
||||
print_rune_to_buffer(buffer, #rune "0")
|
||||
return
|
||||
@@ -555,12 +558,11 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) {
|
||||
bprint :: proc(buf: ^[]byte, args: ..any) {
|
||||
is_type_string :: proc(info: ^Type_Info) -> bool {
|
||||
using Type_Info
|
||||
info = type_info_base(info)
|
||||
if info == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
match type i : info {
|
||||
match type i : type_info_base(info) {
|
||||
case String:
|
||||
return true
|
||||
}
|
||||
|
||||
+2
-1
@@ -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
|
||||
}
|
||||
|
||||
encode_rune :: proc(r: rune) -> ([4]byte, int) {
|
||||
encode_rune :: proc(r_: rune) -> ([4]byte, int) {
|
||||
r := r_
|
||||
buf: [4]byte
|
||||
i := r as u32
|
||||
mask: byte : 0x3f
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode, Type *type, ExactValue value) {
|
||||
GB_ASSERT(expression != NULL);
|
||||
if (mode == Addressing_Invalid)
|
||||
@@ -1306,7 +1305,7 @@ void check_parsed_files(Checker *c) {
|
||||
ExpressionInfo *info = &entry->value;
|
||||
if (info != NULL && expr != NULL) {
|
||||
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);
|
||||
}
|
||||
|
||||
+36
-18
@@ -933,7 +933,11 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
|
||||
o->type = t_invalid;
|
||||
return;
|
||||
}
|
||||
o->mode = Addressing_Variable;
|
||||
// if (e->Variable.param) {
|
||||
// o->mode = Addressing_Value;
|
||||
// } else {
|
||||
o->mode = Addressing_Variable;
|
||||
// }
|
||||
break;
|
||||
|
||||
case Entity_TypeName: {
|
||||
@@ -2239,7 +2243,6 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
|
||||
|
||||
|
||||
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) {
|
||||
@@ -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);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
isize operand_count = 0;
|
||||
Array<Operand> operands;
|
||||
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;
|
||||
if (operand_count < param_count) {
|
||||
if (operands.count < param_count) {
|
||||
error_code = -1;
|
||||
} else if (!variadic && operand_count > param_count) {
|
||||
} else if (!variadic && operands.count > param_count) {
|
||||
error_code = +1;
|
||||
}
|
||||
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);
|
||||
defer (gb_string_free(proc_str));
|
||||
error(ast_node_token(call), err_fmt, proc_str, param_count);
|
||||
gb_string_free(proc_str);
|
||||
operand->mode = Addressing_Invalid;
|
||||
}
|
||||
|
||||
GB_ASSERT(proc_type->Proc.params != NULL);
|
||||
Entity **sig_params = proc_type->Proc.params->Tuple.variables;
|
||||
for (isize i = 0; i < param_count; i++) {
|
||||
Type *arg_type = sig_params[i]->type;
|
||||
check_assignment(c, &operands[i], arg_type, make_string("argument"), true);
|
||||
isize operand_index = 0;
|
||||
for (; operand_index < param_count; operand_index++) {
|
||||
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) {
|
||||
@@ -3320,18 +3327,18 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
|
||||
Type *slice = sig_params[param_count]->type;
|
||||
Type *elem = base_type(slice)->Slice.elem;
|
||||
Type *t = elem;
|
||||
for (isize i = param_count; i < operand_count; i++) {
|
||||
Operand *o = &operands[i];
|
||||
for (; operand_index < operands.count; operand_index++) {
|
||||
Operand o = operands[operand_index];
|
||||
if (vari_expand) {
|
||||
variadic_expand = true;
|
||||
t = slice;
|
||||
if (i != param_count) {
|
||||
error(ast_node_token(o->expr),
|
||||
if (operand_index != param_count) {
|
||||
error(ast_node_token(o.expr),
|
||||
"`..` in a variadic procedure can only have one variadic argument at the end");
|
||||
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;
|
||||
check_expr(c, o, fv->value);
|
||||
|
||||
if (base_type(field->type) == t_any) {
|
||||
is_constant = false;
|
||||
}
|
||||
if (is_constant) {
|
||||
is_constant = o->mode == Addressing_Constant;
|
||||
}
|
||||
|
||||
|
||||
check_assignment(c, o, field->type, make_string("structure literal"));
|
||||
}
|
||||
} else {
|
||||
@@ -3596,6 +3607,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
||||
break;
|
||||
}
|
||||
|
||||
if (base_type(field->type) == t_any) {
|
||||
is_constant = false;
|
||||
}
|
||||
if (is_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 elem_count = cl->elems.count;
|
||||
|
||||
if (base_type(elem_type) == t_any) {
|
||||
is_constant = false;
|
||||
}
|
||||
|
||||
for (; index < elem_count; index++) {
|
||||
AstNode *e = cl->elems[index];
|
||||
if (e->kind == AstNode_FieldValue) {
|
||||
error(ast_node_token(e),
|
||||
"`field = value` is only allowed in structure literals");
|
||||
"`field = value` is only allowed in struct literals");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (t->kind == Type_Array &&
|
||||
t->Array.count >= 0 &&
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (max < index)
|
||||
if (max < index) {
|
||||
max = index;
|
||||
}
|
||||
|
||||
if (t->kind == Type_Vector) {
|
||||
if (t->Vector.count > 1 && gb_is_between(index, 2, t->Vector.count-1)) {
|
||||
|
||||
@@ -145,12 +145,10 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
|
||||
case Basic_i16: ssa_fprintf(f, "i16"); break;
|
||||
case Basic_i32: ssa_fprintf(f, "i32"); 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_u16: ssa_fprintf(f, "i16"); break;
|
||||
case Basic_u32: ssa_fprintf(f, "i32"); 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_f64: ssa_fprintf(f, "double"); 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_fprintf(f, "]");
|
||||
break;
|
||||
case Type_Vector: {
|
||||
// TODO(bill): actually do correctly
|
||||
case Type_Vector:
|
||||
ssa_fprintf(f, "<%lld x ", t->Vector.count);
|
||||
ssa_print_type(f, m, t->Vector.elem);
|
||||
ssa_fprintf(f, ">");
|
||||
} break;
|
||||
break;
|
||||
case Type_Slice:
|
||||
ssa_fprintf(f, "{");
|
||||
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, " ");
|
||||
}
|
||||
|
||||
if (v.kind == ExactValue_Invalid) {
|
||||
if (v.kind == ExactValue_Invalid || base_type(elem_type) == t_any) {
|
||||
ssa_fprintf(f, "zeroinitializer");
|
||||
} else if (v.kind == ExactValue_String) {
|
||||
// HACK NOTE(bill): This is a hack but it works because strings are created at the very end
|
||||
|
||||
+23
-12
@@ -1418,6 +1418,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
|
||||
proc->curr_block = proc->decl_block;
|
||||
ssa_emit_jump(proc, proc->entry_block);
|
||||
|
||||
#if 0
|
||||
ssa_optimize_blocks(proc);
|
||||
ssa_build_referrers(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
|
||||
// [ ] Convert to phi nodes
|
||||
ssa_opt_mem2reg(proc);
|
||||
|
||||
#endif
|
||||
|
||||
// Number registers
|
||||
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);
|
||||
} else if (is_type_string(dst)) {
|
||||
// Handled elsewhere
|
||||
GB_ASSERT(ev.kind == ExactValue_String);
|
||||
} else if (is_type_integer(dst)) {
|
||||
ev = exact_value_to_integer(ev);
|
||||
} 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
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));
|
||||
for_array(index, cl->elems) {
|
||||
AstNode *elem = cl->elems[index];
|
||||
if (is_elem_const(proc->module, elem)) {
|
||||
if (is_elem_const(proc->module, elem, et)) {
|
||||
continue;
|
||||
}
|
||||
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)));
|
||||
for_array(field_index, cl->elems) {
|
||||
AstNode *elem = cl->elems[field_index];
|
||||
if (is_elem_const(proc->module, elem)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ssaValue *field_expr = NULL;
|
||||
Entity *field = NULL;
|
||||
@@ -2538,17 +2540,23 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
ast_node(fv, FieldValue, elem);
|
||||
Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false);
|
||||
index = sel.index[0];
|
||||
field_expr = ssa_build_expr(proc, fv->value);
|
||||
elem = fv->value;
|
||||
} else {
|
||||
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);
|
||||
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);
|
||||
|
||||
field = st->fields[index];
|
||||
|
||||
|
||||
Type *ft = field->type;
|
||||
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)));
|
||||
for_array(i, cl->elems) {
|
||||
AstNode *elem = cl->elems[i];
|
||||
if (is_elem_const(proc->module, elem)) {
|
||||
if (is_elem_const(proc->module, elem, et)) {
|
||||
continue;
|
||||
}
|
||||
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) {
|
||||
AstNode *elem = cl->elems[i];
|
||||
if (is_elem_const(proc->module,elem)) {
|
||||
if (is_elem_const(proc->module, elem, et)) {
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
args[arg_count-1] = ssa_emit_load(proc, slice);
|
||||
}
|
||||
|
||||
|
||||
return ssa_emit_call(proc, value, args, arg_count);
|
||||
case_end;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user