From 45dbe8d354a776dfc526f5a31b9f49158640e45b Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Sat, 27 May 2017 11:47:21 +0100 Subject: [PATCH] `default:` to `case:`; `no_alias` to `#no_alias` --- code/demo.odin | 2 +- core/fmt.odin | 32 +- core/os.odin | 10 + core/os_windows.odin | 4 +- core/strconv.odin | 8 +- core/utf16.odin | 2 +- src/check_decl.c | 65 --- src/check_expr.c | 23 +- src/check_stmt.c | 17 +- src/checker.c | 53 +- src/entity.c | 25 +- src/ir.c | 109 ++-- src/ir_print.c | 30 +- src/old_vm.c | 1305 ------------------------------------------ src/parser.c | 106 ++-- src/ssa.c | 54 +- src/tokenizer.c | 3 - src/types.c | 4 +- 18 files changed, 240 insertions(+), 1612 deletions(-) delete mode 100644 src/old_vm.c diff --git a/code/demo.odin b/code/demo.odin index 323754a23..c67cee184 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -10,7 +10,7 @@ main :: proc() { case '-': accumulator -= 1; case '*': accumulator *= 2; case '/': accumulator /= 2; - default: // Ignore everything else + case: // Ignore everything else } } diff --git a/core/fmt.odin b/core/fmt.odin index 086716496..b2242d087 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -189,7 +189,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) { match { case ti == type_info(int): write_string(buf, "int"); case ti == type_info(uint): write_string(buf, "uint"); - default: + case: write_string(buf, info.signed ? "i" : "u"); fi := Fmt_Info{buf = buf}; fmt_int(&fi, u64(8*info.size), false, 64, 'd'); @@ -440,7 +440,7 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) { case u16: num = int(i); case u32: num = int(i); case u64: num = int(i); - default: + case: ok = false; } } @@ -468,7 +468,7 @@ fmt_bool :: proc(using fi: ^Fmt_Info, b: bool, verb: rune) { match verb { case 't', 'v': write_string(buf, b ? "true" : "false"); - default: + case: fmt_bad_verb(fi, verb); } } @@ -515,7 +515,7 @@ is_integer_negative :: proc(u: u64, is_signed: bool, bit_size: int) -> (unsigned neg = i < 0; if neg { i = -i; } u = u64(i); - default: + case: panic("is_integer_negative: Unknown integer size"); } } @@ -555,7 +555,7 @@ _write_int :: proc(fi: ^Fmt_Info, u: u64, base: int, is_signed: bool, bit_size: match base { case 2, 8, 10, 12, 16: break; - default: + case: panic("_write_int: unknown base, whoops"); } @@ -598,7 +598,7 @@ fmt_int :: proc(fi: ^Fmt_Info, u: u64, is_signed: bool, bit_size: int, verb: run _write_int(fi, u, 16, false, bit_size, __DIGITS_UPPER); } - default: + case: fmt_bad_verb(fi, verb); } } @@ -659,7 +659,7 @@ fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) { _pad(fi, str[1..]); } - default: + case: fmt_bad_verb(fi, verb); return; } @@ -681,7 +681,7 @@ fmt_string :: proc(fi: ^Fmt_Info, s: string, verb: rune) { _write_int(fi, u64(s[i]), 16, false, 8, verb == 'x' ? __DIGITS_LOWER : __DIGITS_UPPER); } - default: + case: fmt_bad_verb(fi, verb); } } @@ -690,7 +690,7 @@ fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) { match verb { case 'p', 'v': // Okay - default: + case: fmt_bad_verb(fi, verb); return; } @@ -709,7 +709,7 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) { using Type_Info; match e in v.type_info { - default: + case: fmt_bad_verb(fi, verb); return; case Enum: @@ -760,7 +760,7 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) { if !ok { write_string(fi.buf, "!%(BAD ENUM VALUE)"); } - default: + case: fmt_bad_verb(fi, verb); return; } @@ -796,7 +796,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { } write_byte(fi.buf, '}'); - default: + case: fmt_value(fi, any{v.data, info.base}, verb); } @@ -956,7 +956,7 @@ fmt_complex :: proc(fi: ^Fmt_Info, c: complex128, bits: int, verb: rune) { fmt_float(fi, i, bits/2, verb); write_rune(fi.buf, 'i'); - default: + case: fmt_bad_verb(fi, verb); return; } @@ -983,7 +983,7 @@ fmt_quaternion :: proc(fi: ^Fmt_Info, c: quaternion256, bits: int, verb: rune) { fmt_float(fi, k, bits/4, verb); write_rune(fi.buf, 'k'); - default: + case: fmt_bad_verb(fi, verb); return; } @@ -1029,7 +1029,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) { case u32: fmt_int(fi, u64(a), false, 32, verb); case u64: fmt_int(fi, u64(a), false, 64, verb); case string: fmt_string(fi, a, verb); - default: fmt_value(fi, arg, verb); + case: fmt_value(fi, arg, verb); } } @@ -1102,7 +1102,7 @@ sbprintf :: proc(b: ^String_Buffer, fmt: string, args: ..any) -> string { fi.hash = true; case '0': fi.zero = !fi.minus; - default: + case: break prefix_loop; } } diff --git a/core/os.odin b/core/os.odin index d3f6b79c6..e83efc3c8 100644 --- a/core/os.odin +++ b/core/os.odin @@ -35,3 +35,13 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) { return data[0.. bool { + fd, err := open(name, O_WRONLY, 0); + if err != 0 { + return false; + } + defer close(fd); + + bytes_written, write_err := write(fd, data); + return write_err != 0; +} diff --git a/core/os_windows.odin b/core/os_windows.odin index cd8b17f6a..7de7807b6 100644 --- a/core/os_windows.odin +++ b/core/os_windows.odin @@ -89,7 +89,7 @@ open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) { create_mode = win32.OPEN_ALWAYS; case mode&O_TRUNC == O_TRUNC: create_mode = win32.TRUNCATE_EXISTING; - default: + case: create_mode = win32.OPEN_EXISTING; } @@ -314,7 +314,7 @@ _alloc_command_line_arguments :: proc() -> []string { j += 2; case 0xdc00 <= str[j] && str[j] < 0xe000: return ""; - default: + case: if i+3 > len { return ""; } diff --git a/core/strconv.odin b/core/strconv.odin index 9c51b0573..7232acf1b 100644 --- a/core/strconv.odin +++ b/core/strconv.odin @@ -108,7 +108,7 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [ case 64: bits = transmute(u64, val); flt = &f64_info; - default: + case: panic("strconv: invalid bit_size"); } @@ -132,7 +132,7 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [ case 0: // denormalized exp++; - default: + case: mant |= u64(1) << flt.mantbits; } @@ -312,7 +312,7 @@ is_integer_negative :: proc(u: u64, is_signed: bool, bit_size: int) -> (unsigned neg = i < 0; if neg { i = -i; } u = u64(i); - default: + case: panic("is_integer_negative: Unknown integer size"); } } @@ -356,7 +356,7 @@ append_bits :: proc(buf: []byte, u: u64, base: int, is_signed: bool, bit_size: i case 10: i--; a[i] = 'd'; case 12: i--; a[i] = 'z'; case 16: i--; a[i] = 'x'; - default: ok = false; + case: ok = false; } if ok { i--; diff --git a/core/utf16.odin b/core/utf16.odin index f90bbff28..086843a2b 100644 --- a/core/utf16.odin +++ b/core/utf16.odin @@ -50,7 +50,7 @@ encode :: proc(d: []u16, s: []rune) { d[n+1] = u16(r2); n += 2; - default: + case: d[n] = u16(REPLACEMENT_CHAR); n++; } diff --git a/src/check_decl.c b/src/check_decl.c index 3778197c6..725876665 100644 --- a/src/check_decl.c +++ b/src/check_decl.c @@ -417,68 +417,6 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count check_init_variables(c, entities, entity_count, inits, str_lit("variable declaration")); } - -void check_alias_decl(Checker *c, Entity *e, AstNode *expr, Type *named_type) { - GB_ASSERT(e->type == NULL); - GB_ASSERT(e->kind == Entity_Alias); - - if (e->flags & EntityFlag_Visited) { - e->type = t_invalid; - return; - } - e->flags |= EntityFlag_Visited; - e->type = t_invalid; - - expr = unparen_expr(expr); - - if (expr->kind == AstNode_Alias) { - error_node(expr, "#alias of an #alias is not allowed"); - return; - } - - Operand operand = {0}; - check_expr_or_type(c, &operand, expr); - if (operand.mode != Addressing_Type) { - error_node(expr, "#alias declarations only allow types"); - return; - } - e->kind = Entity_TypeName; - e->TypeName.is_type_alias = true; - e->type = NULL; - - DeclInfo *d = c->context.decl; - d->type_expr = expr; - check_type_decl(c, e, d->type_expr, named_type); - - - // Operand o = {0}; - // Entity *f = NULL; - // if (expr->kind == AstNode_Ident) { - // f = check_ident(c, &o, expr, NULL, NULL, true); - // } else if (expr->kind == AstNode_SelectorExpr) { - // f = check_selector(c, &o, expr, NULL); - // } else { - // check_expr_or_type(c, &o, expr); - // } - // if (o.mode == Addressing_Invalid) { - // return; - // } - // switch (o.mode) { - // case Addressing_Type: - // e->type = o.type; - // // e->kind = Entity_TypeName; - // // e->TypeName.is_type_alias = true; - // e->Alias.kind = EntityAlias_Type; - // e->Alias.original = f; - // break; - // default: - // error_node(expr, "#alias declarations only allow types"); - // e->kind = Entity_Invalid; - // e->type = t_invalid; - // break; - // } -} - void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) { if (e->type != NULL) { return; @@ -513,9 +451,6 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) { case Entity_TypeName: check_type_decl(c, e, d->type_expr, named_type); break; - case Entity_Alias: - check_alias_decl(c, e, d->init_expr, named_type); - break; case Entity_Procedure: check_proc_lit(c, e, d); break; diff --git a/src/check_expr.c b/src/check_expr.c index dc98b1bc7..27659c800 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -1313,8 +1313,8 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type * } break; + case Entity_TypeAlias: case Entity_TypeName: - // NOTE(bill): Cyclical dependency checking is handled in the "type system" not here o->mode = Addressing_Type; break; @@ -1344,17 +1344,6 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type * o->mode = Addressing_Value; break; - case Entity_Alias: { - // error_node(n, "#alias entities are not yet supported"); - // TODO(bill): Fix Entity_Alias rules - if (e->Alias.kind == EntityAlias_Type) { - o->mode = Addressing_Type; - } else { - o->mode = Addressing_Invalid; - return e; - } - } break; - default: compiler_error("Unknown EntityKind"); break; @@ -3070,10 +3059,6 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h expr_entity = e; Entity *original_e = e; - while (e != NULL && e->kind == Entity_Alias && e->Alias.original != NULL) { - e = e->Alias.original; - } - if (e != NULL && e->kind == Entity_ImportName && selector->kind == AstNode_Ident) { // IMPORTANT NOTE(bill): This is very sloppy code but it's also very fragile // It pretty much needs to be in this order and this way @@ -3295,6 +3280,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h operand->mode = Addressing_Value; } break; + case Entity_TypeAlias: case Entity_TypeName: operand->mode = Addressing_Type; break; @@ -3306,11 +3292,6 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h operand->builtin_id = entity->Builtin.id; break; - case Entity_Alias: { - error_node(selector, "#alias entities are not yet supported"); - return NULL; - } break; - // NOTE(bill): These cases should never be hit but are here for sanity reasons case Entity_Nil: operand->mode = Addressing_Value; diff --git a/src/check_stmt.c b/src/check_stmt.c index 619431907..e00ba4bc1 100644 --- a/src/check_stmt.c +++ b/src/check_stmt.c @@ -262,10 +262,10 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) { AstNode *ln = unparen_expr(lhs_node); if (ln->kind == AstNode_IndexExpr) { AstNode *x = ln->IndexExpr.expr; - TypeAndValue *tav = type_and_value_of_expression(&c->info, x); - GB_ASSERT(tav != NULL); - if (tav->mode != Addressing_Variable) { - if (!is_type_pointer(tav->type)) { + TypeAndValue tav = type_and_value_of_expr(&c->info, x); + GB_ASSERT(tav.mode != Addressing_Invalid); + if (tav.mode != Addressing_Variable) { + if (!is_type_pointer(tav.type)) { gbString str = expr_to_string(lhs.expr); error_node(lhs.expr, "Cannot assign to the value of a map `%s`", str); gb_string_free(str); @@ -443,15 +443,6 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo add_entity_use(c, expr, e); switch (e->kind) { - case Entity_Alias: { - if (e->Alias.original != NULL) { - check_using_stmt_entity(c, us, expr, is_selector, e->Alias.original); - } else { - error(us->token, "`using` cannot be applied to the alias `%.*s`", LIT(e->token.string)); - return false; - } - } break; - case Entity_TypeName: { Type *t = base_type(e->type); if (is_type_union(t)) { diff --git a/src/checker.c b/src/checker.c index 72ebaf096..9ca8dc371 100644 --- a/src/checker.c +++ b/src/checker.c @@ -28,8 +28,8 @@ typedef enum BuiltinProcId { BuiltinProc_cap, BuiltinProc_new, - BuiltinProc_free, BuiltinProc_make, + BuiltinProc_free, BuiltinProc_reserve, BuiltinProc_clear, @@ -82,8 +82,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = { {STR_LIT("cap"), 1, false, Expr_Expr}, {STR_LIT("new"), 1, false, Expr_Expr}, - {STR_LIT("free"), 1, false, Expr_Stmt}, {STR_LIT("make"), 1, true, Expr_Expr}, + {STR_LIT("free"), 1, false, Expr_Stmt}, {STR_LIT("reserve"), 2, false, Expr_Stmt}, {STR_LIT("clear"), 1, false, Expr_Stmt}, @@ -624,14 +624,15 @@ void add_declaration_dependency(Checker *c, Entity *e) { } -void add_global_entity(Entity *entity) { +Entity *add_global_entity(Entity *entity) { String name = entity->token.string; if (gb_memchr(name.text, ' ', name.len)) { - return; // NOTE(bill): `untyped thing` + return entity; // NOTE(bill): `untyped thing` } if (scope_insert_entity(universal_scope, entity)) { compiler_error("double declaration"); } + return entity; } void add_global_constant(gbAllocator a, String name, Type *type, ExactValue value) { @@ -646,6 +647,11 @@ void add_global_string_constant(gbAllocator a, String name, String value) { } +Type *add_global_type_alias(gbAllocator a, String name, Type *t) { + Entity *e = add_global_entity(make_entity_type_alias(a, NULL, make_token_ident(name), t)); + return e->type; +} + void init_universal_scope(void) { BuildContext *bc = &build_context; @@ -657,9 +663,16 @@ void init_universal_scope(void) { for (isize i = 0; i < gb_count_of(basic_types); i++) { add_global_entity(make_entity_type_name(a, NULL, make_token_ident(basic_types[i].Basic.name), &basic_types[i])); } +#if 1 for (isize i = 0; i < gb_count_of(basic_type_aliases); i++) { add_global_entity(make_entity_type_name(a, NULL, make_token_ident(basic_type_aliases[i].Basic.name), &basic_type_aliases[i])); } +#else + { + t_byte = add_global_type_alias(a, str_lit("byte"), &basic_types[Basic_u8]); + t_rune = add_global_type_alias(a, str_lit("rune"), &basic_types[Basic_i32]); + } +#endif // Constants add_global_constant(a, str_lit("true"), t_untyped_bool, exact_value_bool(true)); @@ -786,11 +799,6 @@ void destroy_checker(Checker *c) { } -TypeAndValue *type_and_value_of_expression(CheckerInfo *i, AstNode *expression) { - TypeAndValue *found = map_tav_get(&i->types, hash_pointer(expression)); - return found; -} - Entity *entity_of_ident(CheckerInfo *i, AstNode *identifier) { if (identifier->kind == AstNode_Ident) { @@ -806,13 +814,22 @@ Entity *entity_of_ident(CheckerInfo *i, AstNode *identifier) { return NULL; } -Type *type_of_expr(CheckerInfo *i, AstNode *expression) { - TypeAndValue *found = type_and_value_of_expression(i, expression); - if (found) { - return found->type; + +TypeAndValue type_and_value_of_expr(CheckerInfo *i, AstNode *expression) { + TypeAndValue result = {0}; + TypeAndValue *found = map_tav_get(&i->types, hash_pointer(expression)); + if (found) result = *found; + return result; +} + + +Type *type_of_expr(CheckerInfo *i, AstNode *expr) { + TypeAndValue tav = type_and_value_of_expr(i, expr); + if (tav.mode != Addressing_Invalid) { + return tav.type; } - if (expression->kind == AstNode_Ident) { - Entity *entity = entity_of_ident(i, expression); + if (expr->kind == AstNode_Ident) { + Entity *entity = entity_of_ident(i, expr); if (entity) { return entity->type; } @@ -2102,6 +2119,7 @@ void check_parsed_files(Checker *c) { // TODO(bill): Any other checks? +#if 1 // Add "Basic" type information for (isize i = 0; i < gb_count_of(basic_types)-1; i++) { Type *t = &basic_types[i]; @@ -2116,14 +2134,13 @@ void check_parsed_files(Checker *c) { add_type_info_type(c, t); } } - +#endif // NOTE(bill): Check for illegal cyclic type declarations for_array(i, c->info.definitions.entries) { Entity *e = c->info.definitions.entries.e[i].value; - if (e->kind == Entity_TypeName || - (e->kind == Entity_Alias && e->Alias.kind == EntityAlias_Type)) { + if (e->kind == Entity_TypeName) { if (e->type != NULL) { // i64 size = type_size_of(c->sizes, c->allocator, e->type); i64 align = type_align_of(c->allocator, e->type); diff --git a/src/entity.c b/src/entity.c index 465d75640..60d3d4cd8 100644 --- a/src/entity.c +++ b/src/entity.c @@ -14,7 +14,8 @@ typedef struct DeclInfo DeclInfo; ENTITY_KIND(Builtin) \ ENTITY_KIND(ImportName) \ ENTITY_KIND(LibraryName) \ - ENTITY_KIND(Alias) \ + ENTITY_KIND(TypeAlias) \ + ENTITY_KIND(ProcedureAlias) \ ENTITY_KIND(Nil) \ ENTITY_KIND(Label) @@ -109,10 +110,10 @@ struct Entity { String name; bool used; } LibraryName; + i32 TypeAlias; struct { - EntityAliasKind kind; - Entity * original; - } Alias; + Entity *original; + } ProcedureAlias; i32 Nil; struct { String name; @@ -243,13 +244,19 @@ Entity *make_entity_library_name(gbAllocator a, Scope *scope, Token token, Type return entity; } -Entity *make_entity_alias(gbAllocator a, Scope *scope, Token token, Type *type, - EntityAliasKind kind, Entity *original) { - Entity *entity = alloc_entity(a, Entity_Alias, scope, token, type); - entity->Alias.kind = kind; - entity->Alias.original = original; +Entity *make_entity_type_alias(gbAllocator a, Scope *scope, Token token, Type *type) { + Entity *entity = alloc_entity(a, Entity_TypeAlias, scope, token, type); return entity; } +Entity *make_entity_procedure_alias(gbAllocator a, Scope *scope, Token token, Entity *original) { + GB_ASSERT(original != NULL); + Entity *entity = alloc_entity(a, Entity_ProcedureAlias, scope, token, original->type); + entity->ProcedureAlias.original = original; + return entity; +} + + + Entity *make_entity_nil(gbAllocator a, String name, Type *type) { Token token = make_token_ident(name); diff --git a/src/ir.c b/src/ir.c index ab1321bb4..1ef13f8b5 100644 --- a/src/ir.c +++ b/src/ir.c @@ -3570,23 +3570,23 @@ bool is_double_pointer(Type *t) { irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { expr = unparen_expr(expr); - TypeAndValue *tv = map_tav_get(&proc->module->info->types, hash_pointer(expr)); - GB_ASSERT_NOT_NULL(tv); + TypeAndValue tv = type_and_value_of_expr(proc->module->info, expr); + GB_ASSERT(tv.mode != Addressing_Invalid); - if (tv->value.kind != ExactValue_Invalid) { + if (tv.value.kind != ExactValue_Invalid) { // NOTE(bill): Edge case - if (tv->value.kind != ExactValue_Compound && - is_type_vector(tv->type)) { - Type *elem = base_vector_type(tv->type); - ExactValue value = convert_exact_value_for_type(tv->value, elem); + if (tv.value.kind != ExactValue_Compound && + is_type_vector(tv.type)) { + Type *elem = base_vector_type(tv.type); + ExactValue value = convert_exact_value_for_type(tv.value, elem); irValue *x = ir_add_module_constant(proc->module, elem, value); - return ir_emit_conv(proc, x, tv->type); + return ir_emit_conv(proc, x, tv.type); } - return ir_add_module_constant(proc->module, tv->type, tv->value); + return ir_add_module_constant(proc->module, tv.type, tv.value); } - if (tv->mode == Addressing_Variable) { + if (tv.mode == Addressing_Variable) { return ir_addr_load(proc, ir_build_addr(proc, expr)); } @@ -3614,7 +3614,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { LIT(token.pos.file), token.pos.line, token.pos.column); return NULL; } else if (e->kind == Entity_Nil) { - return ir_value_nil(proc->module->allocator, tv->type); + return ir_value_nil(proc->module->allocator, tv.type); } irValue **found = map_ir_value_get(&proc->module->values, hash_pointer(e)); @@ -3644,8 +3644,8 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { case_end; case_ast_node(se, SelectorExpr, expr); - TypeAndValue *tav = map_tav_get(&proc->module->info->types, hash_pointer(expr)); - GB_ASSERT(tav != NULL); + TypeAndValue tav = type_and_value_of_expr(proc->module->info, expr); + GB_ASSERT(tav.mode != Addressing_Invalid); return ir_addr_load(proc, ir_build_addr(proc, expr)); case_end; @@ -3725,7 +3725,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { case_ast_node(ta, TypeAssertion, expr); TokenPos pos = ast_node_token(expr).pos; - Type *type = tv->type; + Type *type = tv.type; irValue *e = ir_build_expr(proc, ta->expr); Type *t = type_deref(ir_type(e)); if (is_type_union(t)) { @@ -3744,13 +3744,13 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { case Token_And: return ir_emit_ptr_offset(proc, ir_build_addr(proc, ue->expr).addr, v_zero); // Make a copy of the pointer default: - return ir_emit_unary_arith(proc, ue->op.kind, ir_build_expr(proc, ue->expr), tv->type); + return ir_emit_unary_arith(proc, ue->op.kind, ir_build_expr(proc, ue->expr), tv.type); } case_end; case_ast_node(be, BinaryExpr, expr); irValue *left = ir_build_expr(proc, be->left); - Type *type = default_type(tv->type); + Type *type = default_type(tv.type); switch (be->op.kind) { case Token_Add: @@ -3822,7 +3822,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { if (map_tav_get(&proc->module->info->types, hash_pointer(ce->proc))->mode == Addressing_Type) { GB_ASSERT(ce->args.count == 1); irValue *x = ir_build_expr(proc, ce->args.e[0]); - irValue *y = ir_emit_conv(proc, x, tv->type); + irValue *y = ir_emit_conv(proc, x, tv.type); return y; } @@ -3843,7 +3843,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { case BuiltinProc_transmute: { irValue *x = ir_build_expr(proc, ce->args.e[1]); - return ir_emit_transmute(proc, x, tv->type); + return ir_emit_transmute(proc, x, tv.type); } case BuiltinProc_len: { @@ -4042,7 +4042,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { gbAllocator a = proc->module->allocator; AstNode *node = ce->args.e[0]; - TypeAndValue tav = *type_and_value_of_expression(proc->module->info, node); + TypeAndValue tav = type_and_value_of_expr(proc->module->info, node); Type *type = base_type(tav.type); if (is_type_dynamic_array(type)) { @@ -4394,14 +4394,14 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { return ir_addr_load(proc, vector_addr); } irValue *src = vector_addr.addr; - irValue *dst = ir_add_local_generated(proc, tv->type); + irValue *dst = ir_add_local_generated(proc, tv.type); for (i32 i = 1; i < ce->args.count; i++) { - TypeAndValue *tv = type_and_value_of_expression(proc->module->info, ce->args.e[i]); - GB_ASSERT(is_type_integer(tv->type)); - GB_ASSERT(tv->value.kind == ExactValue_Integer); + TypeAndValue tv = type_and_value_of_expr(proc->module->info, ce->args.e[i]); + GB_ASSERT(is_type_integer(tv.type)); + GB_ASSERT(tv.value.kind == ExactValue_Integer); - i32 src_index = cast(i32)tv->value.value_integer; + i32 src_index = cast(i32)tv.value.value_integer; i32 dst_index = i-1; irValue *src_elem = ir_emit_array_epi(proc, src, src_index); @@ -4418,9 +4418,9 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { ir_emit_comment(proc, str_lit("complex")); irValue *real = ir_build_expr(proc, ce->args.e[0]); irValue *imag = ir_build_expr(proc, ce->args.e[1]); - irValue *dst = ir_add_local_generated(proc, tv->type); + irValue *dst = ir_add_local_generated(proc, tv.type); - Type *ft = base_complex_elem_type(tv->type); + Type *ft = base_complex_elem_type(tv.type); real = ir_emit_conv(proc, real, ft); imag = ir_emit_conv(proc, imag, ft); ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 0), real); @@ -4435,9 +4435,9 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { irValue *imag = ir_build_expr(proc, ce->args.e[1]); irValue *jmag = ir_build_expr(proc, ce->args.e[2]); irValue *kmag = ir_build_expr(proc, ce->args.e[3]); - irValue *dst = ir_add_local_generated(proc, tv->type); + irValue *dst = ir_add_local_generated(proc, tv.type); - Type *ft = base_quaternion_elem_type(tv->type); + Type *ft = base_quaternion_elem_type(tv.type); real = ir_emit_conv(proc, real, ft); imag = ir_emit_conv(proc, imag, ft); jmag = ir_emit_conv(proc, jmag, ft); @@ -4454,25 +4454,25 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { ir_emit_comment(proc, str_lit("real")); irValue *val = ir_build_expr(proc, ce->args.e[0]); irValue *real = ir_emit_struct_ev(proc, val, 0); - return ir_emit_conv(proc, real, tv->type); + return ir_emit_conv(proc, real, tv.type); } break; case BuiltinProc_imag: { ir_emit_comment(proc, str_lit("imag")); irValue *val = ir_build_expr(proc, ce->args.e[0]); irValue *imag = ir_emit_struct_ev(proc, val, 1); - return ir_emit_conv(proc, imag, tv->type); + return ir_emit_conv(proc, imag, tv.type); } break; case BuiltinProc_jmag: { ir_emit_comment(proc, str_lit("jmag")); irValue *val = ir_build_expr(proc, ce->args.e[0]); irValue *jmag = ir_emit_struct_ev(proc, val, 2); - return ir_emit_conv(proc, jmag, tv->type); + return ir_emit_conv(proc, jmag, tv.type); } break; case BuiltinProc_kmag: { ir_emit_comment(proc, str_lit("kmag")); irValue *val = ir_build_expr(proc, ce->args.e[0]); irValue *kmag = ir_emit_struct_ev(proc, val, 3); - return ir_emit_conv(proc, kmag, tv->type); + return ir_emit_conv(proc, kmag, tv.type); } break; case BuiltinProc_conj: { @@ -4481,14 +4481,14 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { irValue *res = NULL; Type *t = ir_type(val); if (is_type_complex(t)) { - res = ir_add_local_generated(proc, tv->type); + res = ir_add_local_generated(proc, tv.type); irValue *real = ir_emit_struct_ev(proc, val, 0); irValue *imag = ir_emit_struct_ev(proc, val, 1); imag = ir_emit_unary_arith(proc, Token_Sub, imag, ir_type(imag)); ir_emit_store(proc, ir_emit_struct_ep(proc, res, 0), real); ir_emit_store(proc, ir_emit_struct_ep(proc, res, 1), imag); } else if (is_type_quaternion(t)) { - res = ir_add_local_generated(proc, tv->type); + res = ir_add_local_generated(proc, tv.type); irValue *real = ir_emit_struct_ev(proc, val, 0); irValue *imag = ir_emit_struct_ev(proc, val, 1); irValue *jmag = ir_emit_struct_ev(proc, val, 2); @@ -4526,9 +4526,9 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { irValue *s = ir_build_expr(proc, ce->args.e[0]); Type *t = base_type(ir_type(s)); if (is_type_u8_slice(t)) { - return ir_emit_conv(proc, s, tv->type); + return ir_emit_conv(proc, s, tv.type); } - irValue *slice = ir_add_local_generated(proc, tv->type); + irValue *slice = ir_add_local_generated(proc, tv.type); i64 elem_size = type_size_of(proc->module->allocator, t->Slice.elem); irValue *ptr = ir_emit_conv(proc, ir_slice_elem(proc, s), t_u8_ptr); @@ -4733,9 +4733,9 @@ bool ir_is_elem_const(irModule *m, AstNode *elem, Type *elem_type) { if (elem->kind == AstNode_FieldValue) { elem = elem->FieldValue.value; } - TypeAndValue *tav = type_and_value_of_expression(m->info, elem); - GB_ASSERT(tav != NULL); - return tav->value.kind != ExactValue_Invalid; + TypeAndValue tav = type_and_value_of_expr(m->info, elem); + GB_ASSERT(tav.mode != Addressing_Invalid); + return tav.value.kind != ExactValue_Invalid; } irAddr ir_build_addr_from_entity(irProcedure *proc, Entity *e, AstNode *expr) { @@ -4790,9 +4790,9 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { AstNode *sel = unparen_expr(se->selector); if (sel->kind == AstNode_Ident) { String selector = sel->Ident.string; - TypeAndValue *tav = type_and_value_of_expression(proc->module->info, se->expr); + TypeAndValue tav = type_and_value_of_expr(proc->module->info, se->expr); - if (tav == NULL) { + if (tav.mode == Addressing_Invalid) { // NOTE(bill): Imports Entity *imp = entity_of_ident(proc->module->info, se->expr); if (imp != NULL) { @@ -4802,8 +4802,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { } - Type *type = base_type(tav->type); - if (tav->mode == Addressing_Type) { // Addressing_Type + Type *type = base_type(tav.type); + if (tav.mode == Addressing_Type) { // Addressing_Type Selection sel = lookup_field(proc->module->allocator, type, selector, true); Entity *e = sel.entity; GB_ASSERT(e->kind == Entity_Variable); @@ -4838,7 +4838,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { Type *type = type_deref(type_of_expr(proc->module->info, se->expr)); Type *selector_type = base_type(type_of_expr(proc->module->info, se->selector)); GB_ASSERT_MSG(is_type_integer(selector_type), "%s", type_to_string(selector_type)); - ExactValue val = type_and_value_of_expression(proc->module->info, sel)->value; + ExactValue val = type_and_value_of_expr(proc->module->info, sel).value; i64 index = val.value_integer; Selection sel = lookup_field_from_index(proc->module->allocator, type, index); @@ -5009,7 +5009,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { case Type_Basic: { // Basic_string - TypeAndValue *tv = map_tav_get(&proc->module->info->types, hash_pointer(ie->expr)); irValue *str; irValue *elem; irValue *len; @@ -5214,7 +5213,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { index = sel.index.e[0]; elem = fv->value; } else { - TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem); + TypeAndValue tav = type_and_value_of_expr(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.e[0]; } @@ -5370,7 +5369,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { index = sel.index.e[0]; elem = fv->value; } else { - TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem); + TypeAndValue tav = type_and_value_of_expr(proc->module->info, elem); Selection sel = lookup_field(proc->module->allocator, bt, field_names[field_index], false); index = sel.index.e[0]; } @@ -6177,14 +6176,14 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { irBlock *done = NULL; AstNode *expr = unparen_expr(rs->expr); - TypeAndValue *tav = type_and_value_of_expression(proc->module->info, expr); + TypeAndValue tav = type_and_value_of_expr(proc->module->info, expr); if (is_ast_node_a_range(expr)) { ir_build_range_interval(proc, &expr->BinaryExpr, val_type, &val, &index, &loop, &done); - } else if (tav->mode == Addressing_Type) { + } else if (tav.mode == Addressing_Type) { TokenPos pos = ast_node_token(expr).pos; gbAllocator a = proc->module->allocator; - Type *t = tav->type; + Type *t = tav.type; GB_ASSERT(is_type_enum(t)); Type *enum_ptr = make_type_pointer(a, t); t = base_type(t); @@ -7158,12 +7157,12 @@ void ir_gen_tree(irGen *s) { if (is_type_any(e->type)) { } else { - TypeAndValue *tav = map_tav_get(&info->types, hash_pointer(decl->init_expr)); - if (tav != NULL) { - if (tav->value.kind != ExactValue_Invalid) { - ExactValue v = tav->value; + TypeAndValue tav = type_and_value_of_expr(info, decl->init_expr); + if (tav.mode != Addressing_Invalid) { + if (tav.value.kind != ExactValue_Invalid) { + ExactValue v = tav.value; // if (v.kind != ExactValue_String) { - g->Global.value = ir_add_module_constant(m, tav->type, v); + g->Global.value = ir_add_module_constant(m, tav.type, v); // } } } diff --git a/src/ir_print.c b/src/ir_print.c index 3d7b2e9d6..145cb55a0 100644 --- a/src/ir_print.c +++ b/src/ir_print.c @@ -490,9 +490,9 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type * if (i > 0) { ir_fprintf(f, ", "); } - TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems.e[i]); - GB_ASSERT(tav != NULL); - ir_print_compound_element(f, m, tav->value, elem_type); + TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[i]); + GB_ASSERT(tav.mode != Addressing_Invalid); + ir_print_compound_element(f, m, tav.value, elem_type); } for (isize i = elem_count; i < type->Array.count; i++) { if (i >= elem_count) { @@ -520,23 +520,23 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type * ir_fprintf(f, "]["); if (elem_count == 1 && type->Vector.count > 1) { - TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems.e[0]); - GB_ASSERT(tav != NULL); + TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[0]); + GB_ASSERT(tav.mode != Addressing_Invalid); for (isize i = 0; i < type->Vector.count; i++) { if (i > 0) { ir_fprintf(f, ", "); } - ir_print_compound_element(f, m, tav->value, elem_type); + ir_print_compound_element(f, m, tav.value, elem_type); } } else { for (isize i = 0; i < elem_count; i++) { if (i > 0) { ir_fprintf(f, ", "); } - TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems.e[i]); - GB_ASSERT(tav != NULL); - ir_print_compound_element(f, m, tav->value, elem_type); + TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[i]); + GB_ASSERT(tav.mode != Addressing_Invalid); + ir_print_compound_element(f, m, tav.value, elem_type); } } @@ -562,21 +562,21 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type * ast_node(fv, FieldValue, cl->elems.e[i]); String name = fv->field->Ident.string; - TypeAndValue *tav = type_and_value_of_expression(m->info, fv->value); - GB_ASSERT(tav != NULL); + TypeAndValue tav = type_and_value_of_expr(m->info, fv->value); + GB_ASSERT(tav.mode != Addressing_Invalid); Selection sel = lookup_field(m->allocator, type, name, false); Entity *f = type->Record.fields[sel.index.e[0]]; - values[f->Variable.field_index] = tav->value; + values[f->Variable.field_index] = tav.value; } } else { for (isize i = 0; i < value_count; i++) { Entity *f = type->Record.fields_in_src_order[i]; - TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems.e[i]); + TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[i]); ExactValue val = {0}; - if (tav != NULL) { - val = tav->value; + if (tav.mode != Addressing_Invalid) { + val = tav.value; } values[f->Variable.field_index] = val; } diff --git a/src/old_vm.c b/src/old_vm.c deleted file mode 100644 index 071af7ae3..000000000 --- a/src/old_vm.c +++ /dev/null @@ -1,1305 +0,0 @@ -// TODO(bill): COMPLETELY REWORK THIS ENTIRE INTERPRETER -#include "dyncall/include/dyncall.h" - -struct VirtualMachine; - -struct vmValueProc { - ssaProcedure *proc; // If `NULL`, use `ptr` instead and call external procedure - void * ptr; -}; - - -struct vmValue { - // NOTE(bill): Shouldn't need to store type here as the type checking - // has already been handled in the SSA - union { - f32 val_f32; - f64 val_f64; - void * val_ptr; - i64 val_int; - vmValueProc val_proc; - }; - Array val_comp; // NOTE(bill): Will be freed through "stack" - Type *type; -}; - -vmValue vm_make_value_ptr(Type *type, void *ptr) { - GB_ASSERT(is_type_pointer(type)); - vmValue v = {0}; - v.type = default_type(type); - v.val_ptr = ptr; - return v; -} -vmValue vm_make_value_int(Type *type, i64 i) { - GB_ASSERT(is_type_integer(type) || - is_type_boolean(type) || - is_type_enum(type)); - vmValue v = {0}; - v.type = default_type(type); - v.val_int = i; - return v; -} -vmValue vm_make_value_f32(Type *type, f32 f) { - GB_ASSERT(is_type_f32(type)); - vmValue v = {0}; - v.type = default_type(type); - v.val_f32 = f; - return v; -} -vmValue vm_make_value_f64(Type *type, f64 f) { - GB_ASSERT(is_type_f64(type)); - vmValue v = {0}; - v.type = default_type(type); - v.val_f64 = f; - return v; -} -vmValue vm_make_value_comp(Type *type, gbAllocator allocator, isize count) { - GB_ASSERT(is_type_string(type) || - is_type_any (type) || - is_type_array (type) || - is_type_vector(type) || - is_type_slice (type) || - is_type_maybe (type) || - is_type_struct(type) || - is_type_union(type) || - is_type_raw_union(type) || - is_type_tuple (type) || - is_type_proc (type)); - vmValue v = {0}; - v.type = default_type(type); - array_init_count(&v.val_comp, allocator, count); - return v; -} - - - - - - -struct vmFrame { - VirtualMachine * vm; - vmFrame * caller; - ssaProcedure * curr_proc; - ssaBlock * prev_block; - ssaBlock * curr_block; - i32 instr_index; // For the current block - - Map values; // Key: ssaValue * - gbTempArenaMemory temp_arena_memory; - gbAllocator stack_allocator; - Array locals; // Memory to locals - vmValue result; -}; - -struct VirtualMachine { - ssaModule * module; - gbArena stack_arena; - gbAllocator stack_allocator; - gbAllocator heap_allocator; - Array frame_stack; - Map globals; // Key: ssaValue * - Map const_compound_lits; // Key: ssaValue * - vmValue exit_value; -}; - -void vm_exec_instr (VirtualMachine *vm, ssaValue *value); -vmValue vm_operand_value(VirtualMachine *vm, ssaValue *value); -void vm_store (VirtualMachine *vm, void *dst, vmValue val, Type *type); -vmValue vm_load (VirtualMachine *vm, void *ptr, Type *type); -void vm_print_value (vmValue value, Type *type); - -void vm_jump_block(vmFrame *f, ssaBlock *target) { - f->prev_block = f->curr_block; - f->curr_block = target; - f->instr_index = 0; -} - - -vmFrame *vm_back_frame(VirtualMachine *vm) { - if (vm->frame_stack.count > 0) { - return &vm->frame_stack[vm->frame_stack.count-1]; - } - return NULL; -} - -i64 vm_type_size_of(VirtualMachine *vm, Type *type) { - return type_size_of(vm->module->sizes, vm->heap_allocator, type); -} -i64 vm_type_align_of(VirtualMachine *vm, Type *type) { - return type_align_of(vm->module->sizes, vm->heap_allocator, type); -} -i64 vm_type_offset_of(VirtualMachine *vm, Type *type, i64 index) { - return type_offset_of(vm->module->sizes, vm->heap_allocator, type, index); -} - - -void vm_init(VirtualMachine *vm, ssaModule *module) { - gb_arena_init_from_allocator(&vm->stack_arena, heap_allocator(), gb_megabytes(64)); - - vm->module = module; - vm->stack_allocator = gb_arena_allocator(&vm->stack_arena); - vm->heap_allocator = heap_allocator(); - array_init(&vm->frame_stack, vm->heap_allocator); - map_init(&vm->globals, vm->heap_allocator); - map_init(&vm->const_compound_lits, vm->heap_allocator); - - for_array(i, vm->module->values.entries) { - ssaValue *v = vm->module->values.entries[i].value; - switch (v->kind) { - case ssaValue_Global: { - Type *t = ssa_type(v); - GB_ASSERT(is_type_pointer(t)); - i64 size = vm_type_size_of(vm, t); - i64 align = vm_type_align_of(vm, t); - void *mem = gb_alloc_align(vm->heap_allocator, size, align); - if (v->Global.value != NULL && v->Global.value->kind == ssaValue_Constant) { - vm_store(vm, mem, vm_operand_value(vm, v->Global.value), type_deref(t)); - } - map_set(&vm->globals, hash_pointer(v), vm_make_value_ptr(t, mem)); - } break; - } - } - -} -void vm_destroy(VirtualMachine *vm) { - array_free(&vm->frame_stack); - map_destroy(&vm->globals); - map_destroy(&vm->const_compound_lits); - gb_arena_free(&vm->stack_arena); -} - - - - - - -void vm_set_value(vmFrame *f, ssaValue *v, vmValue val) { - if (v != NULL) { - GB_ASSERT(ssa_type(v) != NULL); - map_set(&f->values, hash_pointer(v), val); - } -} - - - -vmFrame *vm_push_frame(VirtualMachine *vm, ssaProcedure *proc) { - vmFrame frame = {0}; - - frame.vm = vm; - frame.curr_proc = proc; - frame.prev_block = proc->blocks[0]; - frame.curr_block = proc->blocks[0]; - frame.instr_index = 0; - frame.caller = vm_back_frame(vm); - frame.stack_allocator = vm->stack_allocator; - frame.temp_arena_memory = gb_temp_arena_memory_begin(&vm->stack_arena); - - map_init(&frame.values, vm->heap_allocator); - array_init(&frame.locals, vm->heap_allocator, proc->local_count); - array_add(&vm->frame_stack, frame); - return vm_back_frame(vm); -} - -void vm_pop_frame(VirtualMachine *vm) { - vmFrame *f = vm_back_frame(vm); - - gb_temp_arena_memory_end(f->temp_arena_memory); - array_free(&f->locals); - map_destroy(&f->values); - - array_pop(&vm->frame_stack); -} - - -vmValue vm_call_proc(VirtualMachine *vm, ssaProcedure *proc, Array values) { - Type *type = base_type(proc->type); - GB_ASSERT_MSG(type->Proc.param_count == values.count, - "Incorrect number of arguments passed into procedure call!\n" - "%.*s -> %td vs %td", - LIT(proc->name), - type->Proc.param_count, values.count); - Type *result_type = type->Proc.results; - if (result_type != NULL && - result_type->Tuple.variable_count == 1) { - result_type = result_type->Tuple.variables[0]->type; - } - - if (proc->body == NULL) { - // GB_PANIC("TODO(bill): external procedure"); - gb_printf_err("TODO(bill): external procedure: %.*s\n", LIT(proc->name)); - vmValue result = {0}; - result.type = result_type; - return result; - } - - void *result_mem = NULL; - if (result_type != NULL) { - result_mem = gb_alloc_align(vm->stack_allocator, - vm_type_size_of(vm, result_type), - vm_type_align_of(vm, result_type)); - } - - gb_printf("call: %.*s\n", LIT(proc->name)); - - vmFrame *f = vm_push_frame(vm, proc); - for_array(i, proc->params) { - vm_set_value(f, proc->params[i], values[i]); - } - - while (f->curr_block != NULL) { - ssaValue *curr_instr = f->curr_block->instrs[f->instr_index++]; - vm_exec_instr(vm, curr_instr); - } - - - - - if (type->Proc.result_count > 0) { - vmValue r = f->result; - - gb_printf("%.*s -> ", LIT(proc->name)); - vm_print_value(r, result_type); - gb_printf("\n"); - - vm_store(vm, result_mem, r, result_type); - } - - vm_pop_frame(vm); - if (result_mem != NULL) { - return vm_load(vm, result_mem, result_type); - } - - vmValue void_result = {0}; - return void_result; -} - - -ssaProcedure *vm_lookup_procedure(VirtualMachine *vm, String name) { - ssaValue *v = ssa_lookup_member(vm->module, name); - GB_ASSERT(v->kind == ssaValue_Proc); - return &v->Proc; -} - -vmValue vm_call_proc_by_name(VirtualMachine *vm, String name, Array args) { - return vm_call_proc(vm, vm_lookup_procedure(vm, name), args); -} - -vmValue vm_exact_value(VirtualMachine *vm, ssaValue *ptr, ExactValue value, Type *t) { - Type *original_type = t; - t = base_type(get_enum_base_type(t)); - // i64 size = vm_type_size_of(vm, t); - if (is_type_boolean(t)) { - return vm_make_value_int(original_type, value.value_bool); - } else if (is_type_integer(t)) { - return vm_make_value_int(original_type, value.value_integer); - } else if (is_type_float(t)) { - if (t->Basic.kind == Basic_f32) { - return vm_make_value_f32(original_type, cast(f32)value.value_float); - } else if (t->Basic.kind == Basic_f64) { - return vm_make_value_f64(original_type, cast(f64)value.value_float); - } - } else if (is_type_pointer(t)) { - return vm_make_value_ptr(original_type, cast(void *)cast(intptr)value.value_pointer); - } else if (is_type_string(t)) { - vmValue result = vm_make_value_comp(original_type, vm->stack_allocator, 2); - - String str = value.value_string; - i64 len = str.len; - u8 *text = gb_alloc_array(vm->heap_allocator, u8, len); - gb_memcopy(text, str.text, len); - - result.val_comp[0] = vm_make_value_ptr(t_u8_ptr, text); - result.val_comp[1] = vm_make_value_int(t_int, len); - - return result; - } else if (value.kind == ExactValue_Compound) { - if (ptr != NULL) { - vmValue *found = map_get(&vm->const_compound_lits, hash_pointer(ptr)); - if (found != NULL) { - return *found; - } - } - - ast_node(cl, CompoundLit, value.value_compound); - - if (is_type_array(t)) { - vmValue result = {0}; - - isize elem_count = cl->elems.count; - if (elem_count == 0) { - if (ptr != NULL) { - map_set(&vm->const_compound_lits, hash_pointer(ptr), result); - } - return result; - } - - Type *type = base_type(t); - result = vm_make_value_comp(t, vm->heap_allocator, type->Array.count); - for (isize i = 0; i < elem_count; i++) { - TypeAndValue *tav = type_and_value_of_expression(vm->module->info, cl->elems[i]); - vmValue elem = vm_exact_value(vm, NULL, tav->value, tav->type); - result.val_comp[i] = elem; - } - - if (ptr != NULL) { - map_set(&vm->const_compound_lits, hash_pointer(ptr), result); - } - - return result; - } else if (is_type_vector(t)) { - vmValue result = {0}; - - isize elem_count = cl->elems.count; - if (elem_count == 0) { - if (ptr != NULL) { - map_set(&vm->const_compound_lits, hash_pointer(ptr), result); - } - return result; - } - - Type *type = base_type(t); - result = vm_make_value_comp(t, vm->heap_allocator, type->Array.count); - for (isize i = 0; i < elem_count; i++) { - TypeAndValue *tav = type_and_value_of_expression(vm->module->info, cl->elems[i]); - vmValue elem = vm_exact_value(vm, NULL, tav->value, tav->type); - result.val_comp[i] = elem; - } - - if (ptr != NULL) { - map_set(&vm->const_compound_lits, hash_pointer(ptr), result); - } - - return result; - } else if (is_type_struct(t)) { - ast_node(cl, CompoundLit, value.value_compound); - - isize value_count = t->Record.field_count; - vmValue result = vm_make_value_comp(t, vm->heap_allocator, value_count); - - if (cl->elems.count == 0) { - return result; - } - - if (cl->elems[0]->kind == AstNode_FieldValue) { - isize elem_count = cl->elems.count; - for (isize i = 0; i < elem_count; i++) { - ast_node(fv, FieldValue, cl->elems[i]); - String name = fv->field->Ident.string; - - TypeAndValue *tav = type_and_value_of_expression(vm->module->info, fv->value); - GB_ASSERT(tav != NULL); - - Selection sel = lookup_field(vm->heap_allocator, t, name, false); - Entity *f = t->Record.fields[sel.index[0]]; - - result.val_comp[f->Variable.field_index] = vm_exact_value(vm, NULL, tav->value, f->type); - } - } else { - for (isize i = 0; i < value_count; i++) { - TypeAndValue *tav = type_and_value_of_expression(vm->module->info, cl->elems[i]); - GB_ASSERT(tav != NULL); - Entity *f = t->Record.fields_in_src_order[i]; - result.val_comp[f->Variable.field_index] = vm_exact_value(vm, NULL, tav->value, f->type); - } - } - - return result; - } else { - GB_PANIC("TODO(bill): Other compound types\n"); - } - - } else if (value.kind == ExactValue_Invalid) { - vmValue zero_result = {0}; - zero_result.type = t; - return zero_result; - } else { - gb_printf_err("TODO(bill): Other constant types: %s\n", type_to_string(original_type)); - } - - GB_ASSERT_MSG(t == NULL, "%s - %d", type_to_string(t), value.kind); - vmValue void_result = {0}; - return void_result; -} - - -vmValue vm_operand_value(VirtualMachine *vm, ssaValue *value) { - vmFrame *f = vm_back_frame(vm); - vmValue v = {0}; - switch (value->kind) { - case ssaValue_Constant: { - v = vm_exact_value(vm, value, value->Constant.value, value->Constant.type); - } break; - case ssaValue_ConstantSlice: { - ssaValueConstant *cs = &value->ConstantSlice; - v = vm_make_value_comp(ssa_type(value), vm->stack_allocator, 3); - v.val_comp[0] = vm_operand_value(vm, cs->backing_array); - v.val_comp[1] = vm_make_value_int(t_int, cs->count); - v.val_comp[2] = vm_make_value_int(t_int, cs->count); - } break; - case ssaValue_Nil: - GB_PANIC("TODO(bill): ssaValue_Nil"); - break; - case ssaValue_TypeName: - GB_PANIC("ssaValue_TypeName has no operand value"); - break; - case ssaValue_Global: - v = *map_get(&vm->globals, hash_pointer(value)); - break; - case ssaValue_Param: - v = *map_get(&f->values, hash_pointer(value)); - break; - case ssaValue_Proc: { - v.type = ssa_type(value); - v.val_proc.proc = &value->Proc; - // GB_PANIC("TODO(bill): ssaValue_Proc"); - } break; - case ssaValue_Block: - GB_PANIC("ssaValue_Block has no operand value"); - break; - case ssaValue_Instr: { - vmValue *found = map_get(&f->values, hash_pointer(value)); - if (found) { - v = *found; - } else { - GB_PANIC("Invalid instruction"); - } - } break; - } - - return v; -} - -void vm_store_integer(VirtualMachine *vm, void *dst, vmValue val) { - // TODO(bill): I assume little endian here - GB_ASSERT(dst != NULL); - Type *type = val.type; - GB_ASSERT_MSG(is_type_integer(type) || is_type_boolean(type), - "\nExpected integer/boolean, got %s (%s)", - type_to_string(type), - type_to_string(base_type(type))); - i64 size = vm_type_size_of(vm, type); - gb_memcopy(dst, &val.val_int, size); -} - -void vm_store_pointer(VirtualMachine *vm, void *dst, vmValue val) { - // TODO(bill): I assume little endian here - GB_ASSERT(dst != NULL); - GB_ASSERT(is_type_pointer(val.type)); - gb_memcopy(dst, &val.val_ptr, vm_type_size_of(vm, t_rawptr)); -} - - -void vm_store(VirtualMachine *vm, void *dst, vmValue val, Type *type) { - i64 size = vm_type_size_of(vm, type); - Type *original_type = type; - // NOTE(bill): enums are pretty much integers - type = base_type(get_enum_base_type(type)); - - switch (type->kind) { - case Type_Basic: - switch (type->Basic.kind) { - case Basic_bool: - case Basic_i8: - case Basic_u8: - case Basic_i16: - case Basic_u16: - case Basic_i32: - case Basic_u32: - case Basic_i64: - case Basic_u64: - case Basic_int: - case Basic_uint: - vm_store_integer(vm, dst, val); - break; - case Basic_f32: - *cast(f32 *)dst = val.val_f32; - break; - case Basic_f64: - *cast(f64 *)dst = val.val_f64; - break; - case Basic_rawptr: - vm_store_pointer(vm, dst, val); // NOTE(bill): A pointer can be treated as an integer - break; - case Basic_string: { - i64 word_size = vm_type_size_of(vm, t_int); - - u8 *mem = cast(u8 *)dst; - vm_store_pointer(vm, mem+0*word_size, val.val_comp[0]); - vm_store_integer(vm, mem+1*word_size, val.val_comp[1]); - } break; - case Basic_any: { - i64 word_size = vm_type_size_of(vm, t_int); - - u8 *mem = cast(u8 *)dst; - vm_store_pointer(vm, mem+0*word_size, val.val_comp[0]); - vm_store_pointer(vm, mem+1*word_size, val.val_comp[1]); - } break; - default: - gb_printf_err("TODO(bill): other basic types for `vm_store` %s\n", type_to_string(type)); - break; - } - break; - - case Type_Pointer: - vm_store_pointer(vm, dst, val); - break; - - case Type_Record: { - u8 *mem = cast(u8 *)dst; - gb_zero_size(mem, size); - - if (is_type_struct(type)) { - GB_ASSERT_MSG(type->Record.field_count >= val.val_comp.count, - "%td vs %td", - type->Record.field_count, val.val_comp.count); - - isize field_count = gb_min(val.val_comp.count, type->Record.field_count); - - for (isize i = 0; i < field_count; i++) { - Entity *f = type->Record.fields[i]; - i64 offset = vm_type_offset_of(vm, type, i); - vm_store(vm, mem+offset, val.val_comp[i], f->type); - } - } else if (is_type_union(type)) { - GB_ASSERT(val.val_comp.count == 2); - i64 word_size = vm_type_size_of(vm, t_int); - i64 size_of_union = vm_type_size_of(vm, type) - word_size; - for (isize i = 0; i < size_of_union; i++) { - mem[i] = cast(u8)val.val_comp[0].val_comp[i].val_int; - } - vm_store_integer(vm, mem + size_of_union, val.val_comp[1]); - - } else if (is_type_raw_union(type)) { - GB_ASSERT(val.val_comp.count == 1); - i64 word_size = vm_type_size_of(vm, t_int); - i64 size_of_union = vm_type_size_of(vm, type) - word_size; - for (isize i = 0; i < size_of_union; i++) { - mem[i] = cast(u8)val.val_comp[0].val_comp[i].val_int; - } - } else { - GB_PANIC("Unknown record type: %s", type_to_string(type)); - } - } break; - - case Type_Tuple: { - u8 *mem = cast(u8 *)dst; - - GB_ASSERT_MSG(type->Tuple.variable_count >= val.val_comp.count, - "%td vs %td", - type->Tuple.variable_count, val.val_comp.count); - - isize variable_count = gb_min(val.val_comp.count, type->Tuple.variable_count); - - for (isize i = 0; i < variable_count; i++) { - Entity *f = type->Tuple.variables[i]; - void *ptr = mem + vm_type_offset_of(vm, type, i); - vm_store(vm, ptr, val.val_comp[i], f->type); - } - } break; - - case Type_Array: { - Type *elem_type = type->Array.elem; - u8 *mem = cast(u8 *)dst; - i64 elem_size = vm_type_size_of(vm, elem_type); - i64 elem_count = gb_min(val.val_comp.count, type->Array.count); - - for (i64 i = 0; i < elem_count; i++) { - vm_store(vm, mem + i*elem_size, val.val_comp[i], elem_type); - } - } break; - - case Type_Vector: { - Type *elem_type = type->Array.elem; - GB_ASSERT_MSG(!is_type_boolean(elem_type), "TODO(bill): Booleans of vectors"); - u8 *mem = cast(u8 *)dst; - i64 elem_size = vm_type_size_of(vm, elem_type); - i64 elem_count = gb_min(val.val_comp.count, type->Array.count); - - for (i64 i = 0; i < elem_count; i++) { - vm_store(vm, mem + i*elem_size, val.val_comp[i], elem_type); - } - } break; - - case Type_Slice: { - i64 word_size = vm_type_size_of(vm, t_int); - - u8 *mem = cast(u8 *)dst; - vm_store_pointer(vm, mem+0*word_size, val.val_comp[0]); - vm_store_integer(vm, mem+1*word_size, val.val_comp[1]); - vm_store_integer(vm, mem+2*word_size, val.val_comp[2]); - } break; - - default: - gb_printf_err("TODO(bill): other types for `vm_store` %s\n", type_to_string(type)); - break; - } -} - -vmValue vm_load_integer(VirtualMachine *vm, void *ptr, Type *type) { - // TODO(bill): I assume little endian here - vmValue v = {0}; - v.type = type; - GB_ASSERT(is_type_integer(type) || is_type_boolean(type)); - // NOTE(bill): Only load the needed amount - gb_memcopy(&v.val_int, ptr, vm_type_size_of(vm, type)); - return v; -} - -vmValue vm_load_pointer(VirtualMachine *vm, void *ptr, Type *type) { - // TODO(bill): I assume little endian here - vmValue v = {0}; - v.type = type; - GB_ASSERT(is_type_pointer(type)); - // NOTE(bill): Only load the needed amount - gb_memcopy(&v.val_int, ptr, vm_type_size_of(vm, type)); - return v; -} - - -vmValue vm_load(VirtualMachine *vm, void *ptr, Type *type) { - i64 size = vm_type_size_of(vm, type); - Type *original_type = type; - type = base_type(get_enum_base_type(type)); - - switch (type->kind) { - case Type_Basic: - switch (type->Basic.kind) { - case Basic_bool: - case Basic_i8: - case Basic_u8: - case Basic_i16: - case Basic_u16: - case Basic_i32: - case Basic_u32: - case Basic_i64: - case Basic_u64: - case Basic_int: - case Basic_uint: - return vm_load_integer(vm, ptr, original_type); - case Basic_f32: - return vm_make_value_f32(original_type, *cast(f32 *)ptr); - case Basic_f64: - return vm_make_value_f64(original_type, *cast(f64 *)ptr); - case Basic_rawptr: - return vm_load_pointer(vm, ptr, original_type); - - - case Basic_string: { - u8 *mem = cast(u8 *)ptr; - i64 word_size = vm_type_size_of(vm, t_int); - vmValue result = vm_make_value_comp(type, vm->stack_allocator, 2); - result.val_comp[0] = vm_load_pointer(vm, mem+0*word_size, t_u8_ptr); - result.val_comp[1] = vm_load_integer(vm, mem+1*word_size, t_int); - return result; - } break; - - default: - GB_PANIC("TODO(bill): other basic types for `vm_load` %s", type_to_string(type)); - break; - } - break; - - case Type_Pointer: - return vm_load_pointer(vm, ptr, original_type); - - case Type_Array: { - i64 count = type->Array.count; - Type *elem_type = type->Array.elem; - i64 elem_size = vm_type_size_of(vm, elem_type); - - vmValue result = vm_make_value_comp(type, vm->stack_allocator, count); - - u8 *mem = cast(u8 *)ptr; - for (isize i = 0; i < count; i++) { - i64 offset = elem_size*i; - vmValue val = vm_load(vm, mem+offset, elem_type); - result.val_comp[i] = val; - } - - return result; - } break; - - case Type_Slice: { - Type *elem_type = type->Slice.elem; - i64 elem_size = vm_type_size_of(vm, elem_type); - i64 word_size = vm_type_size_of(vm, t_int); - - vmValue result = vm_make_value_comp(type, vm->stack_allocator, 3); - - u8 *mem = cast(u8 *)ptr; - result.val_comp[0] = vm_load(vm, mem+0*word_size, t_rawptr); // data - result.val_comp[1] = vm_load(vm, mem+1*word_size, t_int); // count - result.val_comp[2] = vm_load(vm, mem+2*word_size, t_int); // capacity - return result; - } break; - - case Type_Record: { - if (is_type_struct(type)) { - isize field_count = type->Record.field_count; - - vmValue result = vm_make_value_comp(type, vm->stack_allocator, field_count); - - u8 *mem = cast(u8 *)ptr; - for (isize i = 0; i < field_count; i++) { - Entity *f = type->Record.fields[i]; - i64 offset = vm_type_offset_of(vm, type, i); - result.val_comp[i] = vm_load(vm, mem+offset, f->type); - } - - return result; - } else if (is_type_union(type)) { - i64 word_size = vm_type_size_of(vm, t_int); - i64 size_of_union = vm_type_size_of(vm, type) - word_size; - u8 *mem = cast(u8 *)ptr; - - vmValue result = vm_make_value_comp(type, vm->stack_allocator, 2); - result.val_comp[0] = vm_load(vm, mem, make_type_array(vm->stack_allocator, t_u8, size_of_union)); - result.val_comp[1] = vm_load(vm, mem+size_of_union, t_int); - return result; - } else if (is_type_raw_union(type)) { - gb_printf_err("TODO(bill): load raw_union\n"); - } else { - gb_printf_err("TODO(bill): load other records\n"); - } - } break; - - case Type_Tuple: { - isize count = type->Tuple.variable_count; - - vmValue result = vm_make_value_comp(type, vm->stack_allocator, count); - - u8 *mem = cast(u8 *)ptr; - for (isize i = 0; i < count; i++) { - Entity *f = type->Tuple.variables[i]; - i64 offset = vm_type_offset_of(vm, type, i); - result.val_comp[i] = vm_load(vm, mem+offset, f->type); - } - return result; - } break; - - default: - GB_PANIC("TODO(bill): other types for `vm_load` %s", type_to_string(type)); - break; - } - - GB_ASSERT(type == NULL); - vmValue void_result = {0}; - return void_result; -} - -vmValue vm_exec_binary_op(VirtualMachine *vm, Type *type, vmValue lhs, vmValue rhs, TokenKind op) { - vmValue result = {0}; - - type = base_type(type); - if (is_type_vector(type)) { - Type *elem = type->Vector.elem; - i64 count = type->Vector.count; - - result = vm_make_value_comp(type, vm->stack_allocator, count); - - for (i64 i = 0; i < count; i++) { - result.val_comp[i] = vm_exec_binary_op(vm, elem, lhs.val_comp[i], rhs.val_comp[i], op); - } - - return result; - } - - if (gb_is_between(op, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) { - if (is_type_integer(type) || is_type_boolean(type)) { - // TODO(bill): Do I need to take into account the size of the integer? - switch (op) { - case Token_CmpEq: result.val_int = lhs.val_int == rhs.val_int; break; - case Token_NotEq: result.val_int = lhs.val_int != rhs.val_int; break; - case Token_Lt: result.val_int = lhs.val_int < rhs.val_int; break; - case Token_Gt: result.val_int = lhs.val_int > rhs.val_int; break; - case Token_LtEq: result.val_int = lhs.val_int <= rhs.val_int; break; - case Token_GtEq: result.val_int = lhs.val_int >= rhs.val_int; break; - } - } else if (type == t_f32) { - switch (op) { - case Token_CmpEq: result.val_f32 = lhs.val_f32 == rhs.val_f32; break; - case Token_NotEq: result.val_f32 = lhs.val_f32 != rhs.val_f32; break; - case Token_Lt: result.val_f32 = lhs.val_f32 < rhs.val_f32; break; - case Token_Gt: result.val_f32 = lhs.val_f32 > rhs.val_f32; break; - case Token_LtEq: result.val_f32 = lhs.val_f32 <= rhs.val_f32; break; - case Token_GtEq: result.val_f32 = lhs.val_f32 >= rhs.val_f32; break; - } - } else if (type == t_f64) { - switch (op) { - case Token_CmpEq: result.val_f64 = lhs.val_f64 == rhs.val_f64; break; - case Token_NotEq: result.val_f64 = lhs.val_f64 != rhs.val_f64; break; - case Token_Lt: result.val_f64 = lhs.val_f64 < rhs.val_f64; break; - case Token_Gt: result.val_f64 = lhs.val_f64 > rhs.val_f64; break; - case Token_LtEq: result.val_f64 = lhs.val_f64 <= rhs.val_f64; break; - case Token_GtEq: result.val_f64 = lhs.val_f64 >= rhs.val_f64; break; - } - } else if (is_type_string(type)) { - Array args = {0}; - array_init_count(&args, vm->stack_allocator, 2); - args[0] = lhs; - args[1] = rhs; - switch (op) { - case Token_CmpEq: result = vm_call_proc_by_name(vm, make_string("__string_eq"), args); break; - case Token_NotEq: result = vm_call_proc_by_name(vm, make_string("__string_ne"), args); break; - case Token_Lt: result = vm_call_proc_by_name(vm, make_string("__string_lt"), args); break; - case Token_Gt: result = vm_call_proc_by_name(vm, make_string("__string_gt"), args); break; - case Token_LtEq: result = vm_call_proc_by_name(vm, make_string("__string_le"), args); break; - case Token_GtEq: result = vm_call_proc_by_name(vm, make_string("__string_ge"), args); break; - } - } else { - GB_PANIC("TODO(bill): Vector BinaryOp"); - } - } else { - if (is_type_integer(type) || is_type_boolean(type)) { - switch (op) { - case Token_Add: result.val_int = lhs.val_int + rhs.val_int; break; - case Token_Sub: result.val_int = lhs.val_int - rhs.val_int; break; - case Token_And: result.val_int = lhs.val_int & rhs.val_int; break; - case Token_Or: result.val_int = lhs.val_int | rhs.val_int; break; - case Token_Xor: result.val_int = lhs.val_int ^ rhs.val_int; break; - case Token_Shl: result.val_int = lhs.val_int << rhs.val_int; break; - case Token_Shr: result.val_int = lhs.val_int >> rhs.val_int; break; - case Token_Mul: result.val_int = lhs.val_int * rhs.val_int; break; - case Token_Not: result.val_int = lhs.val_int ^ rhs.val_int; break; - - case Token_AndNot: result.val_int = lhs.val_int & (~rhs.val_int); break; - - // TODO(bill): Take into account size of integer and signedness - case Token_Quo: GB_PANIC("TODO(bill): BinaryOp Integer Token_Quo"); break; - case Token_Mod: GB_PANIC("TODO(bill): BinaryOp Integer Token_Mod"); break; - - } - } else if (is_type_float(type)) { - if (type == t_f32) { - switch (op) { - case Token_Add: result.val_f32 = lhs.val_f32 + rhs.val_f32; break; - case Token_Sub: result.val_f32 = lhs.val_f32 - rhs.val_f32; break; - case Token_Mul: result.val_f32 = lhs.val_f32 * rhs.val_f32; break; - case Token_Quo: result.val_f32 = lhs.val_f32 / rhs.val_f32; break; - - case Token_Mod: GB_PANIC("TODO(bill): BinaryOp f32 Token_Mod"); break; - } - } else if (type == t_f64) { - switch (op) { - case Token_Add: result.val_f64 = lhs.val_f64 + rhs.val_f64; break; - case Token_Sub: result.val_f64 = lhs.val_f64 - rhs.val_f64; break; - case Token_Mul: result.val_f64 = lhs.val_f64 * rhs.val_f64; break; - case Token_Quo: result.val_f64 = lhs.val_f64 / rhs.val_f64; break; - - case Token_Mod: GB_PANIC("TODO(bill): BinaryOp f64 Token_Mod"); break; - } - } - } else { - GB_PANIC("Invalid binary op type"); - } - } - - return result; -} - -void vm_exec_instr(VirtualMachine *vm, ssaValue *value) { - GB_ASSERT(value != NULL); - GB_ASSERT(value->kind == ssaValue_Instr); - ssaInstr *instr = &value->Instr; - vmFrame *f = vm_back_frame(vm); - -#if 0 - if (instr->kind != ssaInstr_Comment) { - gb_printf("exec_instr: %.*s\n", LIT(ssa_instr_strings[instr->kind])); - } -#endif - - switch (instr->kind) { - case ssaInstr_StartupRuntime: { -#if 1 - Array args = {0}; // Empty - vm_call_proc_by_name(vm, make_string(SSA_STARTUP_RUNTIME_PROC_NAME), args); // NOTE(bill): No return value -#endif - } break; - - case ssaInstr_Comment: - break; - - case ssaInstr_Local: { - Type *type = ssa_type(value); - GB_ASSERT(is_type_pointer(type)); - isize size = gb_max(1, vm_type_size_of(vm, type)); - isize align = gb_max(1, vm_type_align_of(vm, type)); - void *memory = gb_alloc_align(vm->stack_allocator, size, align); - GB_ASSERT(memory != NULL); - vm_set_value(f, value, vm_make_value_ptr(type, memory)); - array_add(&f->locals, memory); - } break; - - case ssaInstr_ZeroInit: { - Type *t = type_deref(ssa_type(instr->ZeroInit.address)); - vmValue addr = vm_operand_value(vm, instr->ZeroInit.address); - void *data = addr.val_ptr; - i64 size = vm_type_size_of(vm, t); - gb_zero_size(data, size); - } break; - - case ssaInstr_Store: { - vmValue addr = vm_operand_value(vm, instr->Store.address); - vmValue val = vm_operand_value(vm, instr->Store.value); - GB_ASSERT(val.type != NULL); - Type *t = type_deref(ssa_type(instr->Store.address)); - vm_store(vm, addr.val_ptr, val, t); - } break; - - case ssaInstr_Load: { - vmValue addr = vm_operand_value(vm, instr->Load.address); - Type *t = ssa_type(value); - vmValue v = vm_load(vm, addr.val_ptr, t); - vm_set_value(f, value, v); - } break; - - case ssaInstr_ArrayElementPtr: { - vmValue address = vm_operand_value(vm, instr->ArrayElementPtr.address); - vmValue elem_index = vm_operand_value(vm, instr->ArrayElementPtr.elem_index); - - Type *t = ssa_type(instr->ArrayElementPtr.address); - GB_ASSERT(is_type_pointer(t)); - i64 elem_size = vm_type_size_of(vm, type_deref(t)); - void *ptr = cast(u8 *)address.val_ptr + elem_index.val_int*elem_size; - vm_set_value(f, value, vm_make_value_ptr(t, ptr)); - } break; - - case ssaInstr_StructElementPtr: { - vmValue address = vm_operand_value(vm, instr->StructElementPtr.address); - i32 elem_index = instr->StructElementPtr.elem_index; - - Type *t = ssa_type(instr->StructElementPtr.address); - GB_ASSERT(is_type_pointer(t)); - i64 offset = vm_type_offset_of(vm, type_deref(t), elem_index); - void *ptr = cast(u8 *)address.val_ptr + offset; - vm_set_value(f, value, vm_make_value_ptr(t, ptr)); - } break; - - case ssaInstr_PtrOffset: { - Type *t = ssa_type(instr->PtrOffset.address); - GB_ASSERT(is_type_pointer(t)); - i64 elem_size = vm_type_size_of(vm, type_deref(t)); - vmValue address = vm_operand_value(vm, instr->PtrOffset.address); - vmValue offset = vm_operand_value(vm, instr->PtrOffset.offset); - - void *ptr = cast(u8 *)address.val_ptr + offset.val_int*elem_size; - vm_set_value(f, value, vm_make_value_ptr(t, ptr)); - } break; - - case ssaInstr_Phi: { - for_array(i, f->curr_block->preds) { - ssaBlock *pred = f->curr_block->preds[i]; - if (f->prev_block == pred) { - vmValue edge = vm_operand_value(vm, instr->Phi.edges[i]); - vm_set_value(f, value, edge); - break; - } - } - } break; - - case ssaInstr_ArrayExtractValue: { - vmValue s = vm_operand_value(vm, instr->ArrayExtractValue.address); - vmValue v = s.val_comp[instr->ArrayExtractValue.index]; - vm_set_value(f, value, v); - } break; - - case ssaInstr_StructExtractValue: { - vmValue s = vm_operand_value(vm, instr->StructExtractValue.address); - vmValue v = s.val_comp[instr->StructExtractValue.index]; - vm_set_value(f, value, v); - } break; - - case ssaInstr_Jump: { - vm_jump_block(f, instr->Jump.block); - } break; - - case ssaInstr_If: { - vmValue cond = vm_operand_value(vm, instr->If.cond); - if (cond.val_int != 0) { - vm_jump_block(f, instr->If.true_block); - } else { - vm_jump_block(f, instr->If.false_block); - } - } break; - - case ssaInstr_Return: { - Type *return_type = NULL; - vmValue result = {0}; - - if (instr->Return.value != NULL) { - return_type = ssa_type(instr->Return.value); - result = vm_operand_value(vm, instr->Return.value); - } - - f->result = result; - f->curr_block = NULL; - f->instr_index = 0; - return; - } break; - - case ssaInstr_Conv: { - // TODO(bill): Assuming little endian - vmValue dst = {0}; - vmValue src = vm_operand_value(vm, instr->Conv.value); - i64 from_size = vm_type_size_of(vm, instr->Conv.from); - i64 to_size = vm_type_size_of(vm, instr->Conv.to); - switch (instr->Conv.kind) { - case ssaConv_trunc: - gb_memcopy(&dst, &src, to_size); - break; - case ssaConv_zext: - gb_memcopy(&dst, &src, from_size); - break; - case ssaConv_fptrunc: { - GB_ASSERT(from_size > to_size); - GB_ASSERT(base_type(instr->Conv.from) == t_f64); - GB_ASSERT(base_type(instr->Conv.to) == t_f32); - dst.val_f32 = cast(f32)src.val_f64; - } break; - case ssaConv_fpext: { - GB_ASSERT(from_size < to_size); - GB_ASSERT(base_type(instr->Conv.from) == t_f32); - GB_ASSERT(base_type(instr->Conv.to) == t_f64); - dst.val_f64 = cast(f64)src.val_f32; - } break; - case ssaConv_fptoui: { - Type *from = base_type(instr->Conv.from); - if (from == t_f64) { - u64 u = cast(u64)src.val_f64; - vm_store_integer(vm, &dst, vm_make_value_int(instr->Conv.to, u)); - } else { - u64 u = cast(u64)src.val_f32; - vm_store_integer(vm, &dst, vm_make_value_int(instr->Conv.to, u)); - } - } break; - case ssaConv_fptosi: { - Type *from = base_type(instr->Conv.from); - if (from == t_f64) { - i64 i = cast(i64)src.val_f64; - vm_store_integer(vm, &dst, vm_make_value_int(instr->Conv.to, i)); - } else { - i64 i = cast(i64)src.val_f32; - vm_store_integer(vm, &dst, vm_make_value_int(instr->Conv.to, i)); - } - } break; - case ssaConv_uitofp: { - Type *to = base_type(instr->Conv.to); - if (to == t_f64) { - dst = vm_make_value_f64(instr->Conv.to, cast(f64)cast(u64)src.val_int); - } else { - dst = vm_make_value_f32(instr->Conv.to, cast(f32)cast(u64)src.val_int); - } - } break; - case ssaConv_sitofp: { - Type *to = base_type(instr->Conv.to); - if (to == t_f64) { - dst = vm_make_value_f64(instr->Conv.to, cast(f64)cast(i64)src.val_int); - } else { - dst = vm_make_value_f32(instr->Conv.to, cast(f32)cast(i64)src.val_int); - } - } break; - - case ssaConv_ptrtoint: - dst = vm_make_value_int(instr->Conv.to, cast(i64)src.val_ptr); - break; - case ssaConv_inttoptr: - dst = vm_make_value_ptr(instr->Conv.to, cast(void *)src.val_int); - break; - case ssaConv_bitcast: - dst = src; - dst.type = instr->Conv.to; - break; - } - - vm_set_value(f, value, dst); - } break; - - case ssaInstr_Unreachable: { - GB_PANIC("Unreachable"); - } break; - - case ssaInstr_BinaryOp: { - ssaInstrBinaryOp *bo = &instr->BinaryOp; - Type *type = ssa_type(bo->left); - vmValue lhs = vm_operand_value(vm, bo->left); - vmValue rhs = vm_operand_value(vm, bo->right); - vmValue v = vm_exec_binary_op(vm, type, lhs, rhs, bo->op); - vm_set_value(f, value, v); - } break; - - case ssaInstr_Call: { - Array args = {0}; - array_init(&args, f->stack_allocator, instr->Call.arg_count); - for (isize i = 0; i < instr->Call.arg_count; i++) { - array_add(&args, vm_operand_value(vm, instr->Call.args[i])); - } - vmValue proc = vm_operand_value(vm, instr->Call.value); - if (proc.val_proc.proc != NULL) { - vmValue result = vm_call_proc(vm, proc.val_proc.proc, args); - vm_set_value(f, value, result); - } else { - GB_PANIC("TODO(bill): external procedure calls"); - } - - } break; - - case ssaInstr_Select: { - vmValue v = {0}; - vmValue cond = vm_operand_value(vm, instr->Select.cond); - if (cond.val_int != 0) { - v = vm_operand_value(vm, instr->Select.true_value); - } else { - v = vm_operand_value(vm, instr->Select.false_value); - } - - vm_set_value(f, value, v); - } break; - - case ssaInstr_VectorExtractElement: { - vmValue vector = vm_operand_value(vm, instr->VectorExtractElement.vector); - vmValue index = vm_operand_value(vm, instr->VectorExtractElement.index); - vmValue v = vector.val_comp[index.val_int]; - vm_set_value(f, value, v); - } break; - - case ssaInstr_VectorInsertElement: { - vmValue vector = vm_operand_value(vm, instr->VectorInsertElement.vector); - vmValue elem = vm_operand_value(vm, instr->VectorInsertElement.elem); - vmValue index = vm_operand_value(vm, instr->VectorInsertElement.index); - vector.val_comp[index.val_int] = elem; - } break; - - case ssaInstr_VectorShuffle: { - ssaValueVectorShuffle *vs = &instr->VectorShuffle; - vmValue old_vector = vm_operand_value(vm, instr->VectorShuffle.vector); - vmValue new_vector = vm_make_value_comp(ssa_type(value), vm->stack_allocator, vs->index_count); - - for (i32 i = 0; i < vs->index_count; i++) { - new_vector.val_comp[i] = old_vector.val_comp[vs->indices[i]]; - } - - vm_set_value(f, value, new_vector); - } break; - - case ssaInstr_BoundsCheck: { - ssaInstrBoundsCheck *bc = &instr->BoundsCheck; - Array args = {0}; - array_init(&args, vm->stack_allocator, 5); - array_add(&args, vm_exact_value(vm, NULL, make_exact_value_string(bc->pos.file), t_string)); - array_add(&args, vm_exact_value(vm, NULL, make_exact_value_integer(bc->pos.line), t_int)); - array_add(&args, vm_exact_value(vm, NULL, make_exact_value_integer(bc->pos.column), t_int)); - array_add(&args, vm_operand_value(vm, bc->index)); - array_add(&args, vm_operand_value(vm, bc->len)); - - vm_call_proc_by_name(vm, make_string("__bounds_check_error"), args); - } break; - - case ssaInstr_SliceBoundsCheck: { - ssaInstrSliceBoundsCheck *bc = &instr->SliceBoundsCheck; - Array args = {0}; - - array_init(&args, vm->stack_allocator, 7); - array_add(&args, vm_exact_value(vm, NULL, make_exact_value_string(bc->pos.file), t_string)); - array_add(&args, vm_exact_value(vm, NULL, make_exact_value_integer(bc->pos.line), t_int)); - array_add(&args, vm_exact_value(vm, NULL, make_exact_value_integer(bc->pos.column), t_int)); - array_add(&args, vm_operand_value(vm, bc->low)); - array_add(&args, vm_operand_value(vm, bc->high)); - if (!bc->is_substring) { - array_add(&args, vm_operand_value(vm, bc->max)); - vm_call_proc_by_name(vm, make_string("__slice_expr_error"), args); - } else { - vm_call_proc_by_name(vm, make_string("__substring_expr_error"), args); - } - } break; - - default: { - GB_PANIC(" %d\n", instr->kind); - } break; - } -} - - - -void vm_print_value(vmValue value, Type *type) { - type = base_type(type); - if (is_type_string(type)) { - vmValue data = value.val_comp[0]; - vmValue count = value.val_comp[1]; - gb_printf("`%.*s`", cast(int)count.val_int, cast(u8 *)data.val_ptr); - } else if (is_type_boolean(type)) { - if (value.val_int != 0) { - gb_printf("true"); - } else { - gb_printf("false"); - } - } else if (is_type_integer(type)) { - gb_printf("%lld", cast(i64)value.val_int); - } else if (type == t_f32) { - gb_printf("%f", value.val_f32); - } else if (type == t_f64) { - gb_printf("%f", value.val_f64); - } else if (is_type_pointer(type)) { - gb_printf("0x%08x", value.val_ptr); - } else if (is_type_array(type)) { - gb_printf("["); - for_array(i, value.val_comp) { - if (i > 0) { - gb_printf(", "); - } - vm_print_value(value.val_comp[i], type->Array.elem); - } - gb_printf("]"); - } else if (is_type_vector(type)) { - gb_printf("<"); - for_array(i, value.val_comp) { - if (i > 0) { - gb_printf(", "); - } - vm_print_value(value.val_comp[i], type->Vector.elem); - } - gb_printf(">"); - } else if (is_type_slice(type)) { - gb_printf("["); - for_array(i, value.val_comp) { - if (i > 0) { - gb_printf(", "); - } - vm_print_value(value.val_comp[i], type->Slice.elem); - } - gb_printf("]"); - } else if (is_type_maybe(type)) { - if (value.val_comp[1].val_int != 0) { - gb_printf("?"); - vm_print_value(value.val_comp[0], type->Maybe.elem); - } else { - gb_printf("nil"); - } - } else if (is_type_struct(type)) { - if (value.val_comp.count == 0) { - gb_printf("nil"); - } else { - gb_printf("{"); - for_array(i, value.val_comp) { - if (i > 0) { - gb_printf(", "); - } - vm_print_value(value.val_comp[i], type->Record.fields[i]->type); - } - gb_printf("}"); - } - } else if (is_type_tuple(type)) { - if (value.val_comp.count != 1) { - gb_printf("("); - } - for_array(i, value.val_comp) { - if (i > 0) { - gb_printf(", "); - } - vm_print_value(value.val_comp[i], type->Tuple.variables[i]->type); - } - if (value.val_comp.count != 1) { - gb_printf(")"); - } - } -} diff --git a/src/parser.c b/src/parser.c index 74800dd44..a13e1431b 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1547,9 +1547,9 @@ void fix_advance_to_next_stmt(AstFile *f) { case Token_defer: case Token_asm: case Token_using: + case Token_immutable: // case Token_thread_local: - case Token_no_alias: - // case Token_immutable: + // case Token_no_alias: case Token_break: case Token_continue: @@ -2703,14 +2703,38 @@ AstNode *parse_var_type(AstFile *f, bool allow_ellipsis) { return type; } -bool is_token_field_prefix(TokenKind kind) { - switch (kind) { + +typedef enum FieldPrefixKind { + FieldPrefix_Invalid, + + FieldPrefix_Using, + FieldPrefix_Immutable, + FieldPrefix_NoAlias, +} FieldPrefixKind; + +FieldPrefixKind is_token_field_prefix(AstFile *f) { + switch (f->curr_token.kind) { + case Token_EOF: + return FieldPrefix_Invalid; + case Token_using: - case Token_no_alias: + return FieldPrefix_Using; + case Token_immutable: - return true; + return FieldPrefix_Immutable; + + case Token_Hash: { + next_token(f); + switch (f->curr_token.kind) { + case Token_Ident: + if (str_eq(f->curr_token.string, str_lit("no_alias"))) { + return FieldPrefix_NoAlias; + } + break; + } + } break; } - return false; + return FieldPrefix_Invalid; } @@ -2719,16 +2743,20 @@ u32 parse_field_prefixes(AstFile *f) { i32 no_alias_count = 0; i32 immutable_count = 0; - while (is_token_field_prefix(f->curr_token.kind)) { - switch (f->curr_token.kind) { - case Token_using: using_count += 1; next_token(f); break; - case Token_no_alias: no_alias_count += 1; next_token(f); break; - case Token_immutable: immutable_count += 1; next_token(f); break; + for (;;) { + FieldPrefixKind kind = is_token_field_prefix(f); + if (kind == FieldPrefix_Invalid) { + break; + } + switch (kind) { + case FieldPrefix_Using: using_count += 1; next_token(f); break; + case FieldPrefix_Immutable: immutable_count += 1; next_token(f); break; + case FieldPrefix_NoAlias: no_alias_count += 1; next_token(f); break; } } if (using_count > 1) syntax_error(f->curr_token, "Multiple `using` in this field list"); - if (no_alias_count > 1) syntax_error(f->curr_token, "Multiple `no_alias` in this field list"); if (immutable_count > 1) syntax_error(f->curr_token, "Multiple `immutable` in this field list"); + if (no_alias_count > 1) syntax_error(f->curr_token, "Multiple `#no_alias` in this field list"); u32 field_flags = 0; @@ -3369,50 +3397,23 @@ AstNode *parse_for_stmt(AstFile *f) { } -AstNode *parse_case_clause(AstFile *f) { +AstNode *parse_case_clause(AstFile *f, bool is_type) { Token token = f->curr_token; AstNodeArray list = make_ast_node_array(f); - if (allow_token(f, Token_case)) { - bool prev_allow_range = f->allow_range; - f->allow_range = true; + expect_token(f, Token_case); + bool prev_allow_range = f->allow_range; + f->allow_range = !is_type; + if (f->curr_token.kind != Token_Colon) { list = parse_rhs_expr_list(f); - f->allow_range = prev_allow_range; - } else { - expect_token(f, Token_default); } + f->allow_range = prev_allow_range; expect_token(f, Token_Colon); // TODO(bill): Is this the best syntax? - // expect_token(f, Token_ArrowRight); // TODO(bill): Is this the best syntax? AstNodeArray stmts = parse_stmt_list(f); return ast_case_clause(f, token, list, stmts); } -AstNode *parse_type_case_clause(AstFile *f) { - Token token = f->curr_token; - AstNodeArray list = make_ast_node_array(f); - if (allow_token(f, Token_case)) { - for (;;) { - AstNode *t = parse_type(f); - array_add(&list, t); - if (f->curr_token.kind != Token_Comma || - f->curr_token.kind == Token_EOF) { - break; - } - next_token(f); - } - } else { - expect_token(f, Token_default); - } - expect_token(f, Token_Colon); // TODO(bill): Is this the best syntax? - // expect_token(f, Token_ArrowRight); // TODO(bill): Is this the best syntax? - AstNodeArray stmts = parse_stmt_list(f); - - return ast_case_clause(f, token, list, stmts); -} - - - AstNode *parse_match_stmt(AstFile *f) { if (f->curr_proc == NULL) { syntax_error(f->curr_token, "You cannot use a match statement in the file scope"); @@ -3425,6 +3426,7 @@ AstNode *parse_match_stmt(AstFile *f) { AstNode *body = NULL; Token open, close; bool is_type_match = false; + AstNodeArray list = make_ast_node_array(f); if (f->curr_token.kind != Token_OpenBrace) { isize prev_level = f->expr_level; @@ -3445,15 +3447,9 @@ AstNode *parse_match_stmt(AstFile *f) { f->expr_level = prev_level; } open = expect_token(f, Token_OpenBrace); - AstNodeArray list = make_ast_node_array(f); - while (f->curr_token.kind == Token_case || - f->curr_token.kind == Token_default) { - if (is_type_match) { - array_add(&list, parse_type_case_clause(f)); - } else { - array_add(&list, parse_case_clause(f)); - } + while (f->curr_token.kind == Token_case) { + array_add(&list, parse_case_clause(f, is_type_match)); } close = expect_token(f, Token_CloseBrace); @@ -3863,7 +3859,7 @@ AstNodeArray parse_stmt_list(AstFile *f) { AstNodeArray list = make_ast_node_array(f); while (f->curr_token.kind != Token_case && - f->curr_token.kind != Token_default && + // f->curr_token.kind != Token_default && f->curr_token.kind != Token_CloseBrace && f->curr_token.kind != Token_EOF) { AstNode *stmt = parse_stmt(f); diff --git a/src/ssa.c b/src/ssa.c index de4e4ad80..087eb2105 100644 --- a/src/ssa.c +++ b/src/ssa.c @@ -1051,9 +1051,9 @@ ssaAddr ssa_build_addr(ssaProc *p, AstNode *expr) { AstNode *sel = unparen_expr(se->selector); if (sel->kind == AstNode_Ident) { String selector = sel->Ident.string; - TypeAndValue *tav = type_and_value_of_expression(p->module->info, se->expr); + TypeAndValue tav = type_and_value_of_expr(p->module->info, se->expr); - if (tav == NULL) { + if (tav.mode == Addressing_Invalid) { // NOTE(bill): Imports Entity *imp = entity_of_ident(p->module->info, se->expr); if (imp != NULL) { @@ -1063,8 +1063,8 @@ ssaAddr ssa_build_addr(ssaProc *p, AstNode *expr) { } - Type *type = base_type(tav->type); - if (tav->mode == Addressing_Type) { // Addressing_Type + Type *type = base_type(tav.type); + if (tav.mode == Addressing_Type) { // Addressing_Type GB_PANIC("TODO: SelectorExpr Addressing_Type"); // Selection sel = lookup_field(p->allocator, type, selector, true); // Entity *e = sel.entity; @@ -1099,7 +1099,7 @@ ssaAddr ssa_build_addr(ssaProc *p, AstNode *expr) { } else { Type *type = base_type(type_of_expr(p->module->info, se->expr)); GB_ASSERT(is_type_integer(type)); - ExactValue val = type_and_value_of_expression(p->module->info, sel)->value; + ExactValue val = type_and_value_of_expr(p->module->info, sel).value; i64 index = val.value_integer; Selection sel = lookup_field_from_index(p->allocator, type, index); @@ -1635,43 +1635,43 @@ ssaValue *ssa_emit_logical_binary_expr(ssaProc *p, AstNode *expr) { ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) { expr = unparen_expr(expr); - TypeAndValue *tv = map_tav_get(&p->module->info->types, hash_pointer(expr)); - GB_ASSERT_NOT_NULL(tv); + TypeAndValue tv = type_and_value_of_expr(p->module->info, expr); + GB_ASSERT(tv.mode != Addressing_Invalid); - if (tv->value.kind != ExactValue_Invalid) { - Type *t = core_type(tv->type); + if (tv.value.kind != ExactValue_Invalid) { + Type *t = core_type(tv.type); if (is_type_boolean(t)) { - return ssa_const_bool(p, tv->type, tv->value.value_bool); + return ssa_const_bool(p, tv.type, tv.value.value_bool); } else if (is_type_string(t)) { - GB_ASSERT(tv->value.kind == ExactValue_String); - return ssa_const_string(p, tv->type, tv->value.value_string); + GB_ASSERT(tv.value.kind == ExactValue_String); + return ssa_const_string(p, tv.type, tv.value.value_string); } else if(is_type_slice(t)) { - return ssa_const_slice(p, tv->type, tv->value); + return ssa_const_slice(p, tv.type, tv.value); } else if (is_type_integer(t)) { - GB_ASSERT(tv->value.kind == ExactValue_Integer); + GB_ASSERT(tv.value.kind == ExactValue_Integer); i64 s = 8*type_size_of(p->allocator, t); switch (s) { - case 8: return ssa_const_i8 (p, tv->type, tv->value.value_integer); - case 16: return ssa_const_i16(p, tv->type, tv->value.value_integer); - case 32: return ssa_const_i32(p, tv->type, tv->value.value_integer); - case 64: return ssa_const_i64(p, tv->type, tv->value.value_integer); + case 8: return ssa_const_i8 (p, tv.type, tv.value.value_integer); + case 16: return ssa_const_i16(p, tv.type, tv.value.value_integer); + case 32: return ssa_const_i32(p, tv.type, tv.value.value_integer); + case 64: return ssa_const_i64(p, tv.type, tv.value.value_integer); default: GB_PANIC("Unknown integer size"); } } else if (is_type_float(t)) { - GB_ASSERT(tv->value.kind == ExactValue_Float); + GB_ASSERT(tv.value.kind == ExactValue_Float); i64 s = 8*type_size_of(p->allocator, t); switch (s) { - case 32: return ssa_const_f32(p, tv->type, tv->value.value_float); - case 64: return ssa_const_f64(p, tv->type, tv->value.value_float); + case 32: return ssa_const_f32(p, tv.type, tv.value.value_float); + case 64: return ssa_const_f64(p, tv.type, tv.value.value_float); default: GB_PANIC("Unknown float size"); } } // IMPORTANT TODO(bill): Do constant record/array literals correctly - return ssa_const_nil(p, tv->type); + return ssa_const_nil(p, tv.type); } - if (tv->mode == Addressing_Variable) { + if (tv.mode == Addressing_Variable) { return ssa_addr_load(p, ssa_build_addr(p, expr)); } @@ -1716,12 +1716,12 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) { return ssa_build_addr(p, ue->expr).addr; } ssaValue *x = ssa_build_expr(p, ue->expr); - return ssa_emit_unary_arith(p, ue->op.kind, x, tv->type); + return ssa_emit_unary_arith(p, ue->op.kind, x, tv.type); case_end; case_ast_node(be, BinaryExpr, expr); - Type *type = default_type(tv->type); + Type *type = default_type(tv.type); switch (be->op.kind) { case Token_Add: @@ -1803,7 +1803,7 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) { ssa_emit_jump(p, done); ssa_start_block(p, done); - return ssa_new_value2(p, ssaOp_Phi, tv->type, yes, no); + return ssa_new_value2(p, ssaOp_Phi, tv.type, yes, no); case_end; @@ -1840,7 +1840,7 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) { if (map_tav_get(&p->module->info->types, hash_pointer(ce->proc))->mode == Addressing_Type) { GB_ASSERT(ce->args.count == 1); ssaValue *x = ssa_build_expr(p, ce->args.e[0]); - return ssa_emit_conv(p, x, tv->type); + return ssa_emit_conv(p, x, tv.type); } AstNode *p = unparen_expr(ce->proc); diff --git a/src/tokenizer.c b/src/tokenizer.c index 08496a6d1..056a81f28 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -88,14 +88,12 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ TOKEN_KIND(Token_for, "for"), \ TOKEN_KIND(Token_in, "in"), \ TOKEN_KIND(Token_match, "match"), \ - TOKEN_KIND(Token_default, "default"), \ TOKEN_KIND(Token_case, "case"), \ TOKEN_KIND(Token_break, "break"), \ TOKEN_KIND(Token_continue, "continue"), \ TOKEN_KIND(Token_fallthrough, "fallthrough"), \ TOKEN_KIND(Token_defer, "defer"), \ TOKEN_KIND(Token_return, "return"), \ - TOKEN_KIND(Token_give, "give"), \ TOKEN_KIND(Token_proc, "proc"), \ TOKEN_KIND(Token_macro, "macro"), \ TOKEN_KIND(Token_struct, "struct"), \ @@ -107,7 +105,6 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ TOKEN_KIND(Token_dynamic, "dynamic"), \ TOKEN_KIND(Token_map, "map"), \ TOKEN_KIND(Token_using, "using"), \ - TOKEN_KIND(Token_no_alias, "no_alias"), \ TOKEN_KIND(Token_immutable, "immutable"), \ TOKEN_KIND(Token_context, "context"), \ TOKEN_KIND(Token_push_context, "push_context"), \ diff --git a/src/types.c b/src/types.c index c5a5e6d1d..b70e79fbf 100644 --- a/src/types.c +++ b/src/types.c @@ -36,7 +36,7 @@ typedef enum BasicKind { Basic_UntypedRune, Basic_UntypedNil, - Basic_Count, + Basic_COUNT, Basic_byte = Basic_u8, Basic_rune = Basic_i32, @@ -290,10 +290,10 @@ gb_global Type *t_untyped_quaternion = &basic_types[Basic_UntypedQuaternion]; gb_global Type *t_untyped_string = &basic_types[Basic_UntypedString]; gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune]; gb_global Type *t_untyped_nil = &basic_types[Basic_UntypedNil]; + gb_global Type *t_byte = &basic_type_aliases[0]; gb_global Type *t_rune = &basic_type_aliases[1]; - gb_global Type *t_u8_ptr = NULL; gb_global Type *t_int_ptr = NULL; gb_global Type *t_i64_ptr = NULL;