diff --git a/code/demo.odin b/code/demo.odin index ec54c491c..3011b745a 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -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) } diff --git a/core/_preload.odin b/core/_preload.odin index 586604b22..5a62a16f1 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -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++ { diff --git a/core/fmt.odin b/core/fmt.odin index cb147228a..6e2f24d1a 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -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 } diff --git a/core/utf8.odin b/core/utf8.odin index f256794b9..e604e069b 100644 --- a/core/utf8.odin +++ b/core/utf8.odin @@ -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 diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index 18f5548a7..1cbaf99d4 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -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); } diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index d8e1ac908..e71266edf 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -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 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)) { diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp index 1c2e0929d..95fd4fe5b 100644 --- a/src/codegen/print_llvm.cpp +++ b/src/codegen/print_llvm.cpp @@ -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 diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index 20868d475..80f5b7e12 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -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;