From e697d2d02852ef41a5d37138f596fd21704cd54d Mon Sep 17 00:00:00 2001 From: Jose Mendoza <56417208+StunxFS@users.noreply.github.com> Date: Fri, 15 Dec 2023 16:40:23 +0000 Subject: [PATCH 1/7] first change --- lib/core/src/utils.ri | 17 +++++++++++++++-- rivetc/src/codegen/__init__.py | 14 +++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/lib/core/src/utils.ri b/lib/core/src/utils.ri index eec3ef0b2..e24fe876d 100644 --- a/lib/core/src/utils.ri +++ b/lib/core/src/utils.ri @@ -13,7 +13,7 @@ func enum_cast(ptr: rawptr, expected_id: uint) -> rawptr { if enum_info._id_ != expected_id { // TODO: replace indexes with names console_ewriteln( - "runtime error: enum cast: cannot cast ID({}) to ID({})", enum_info._id_, expected_id + "runtime error: cannot cast tagged enum ID({}) to type ID({})", enum_info._id_, expected_id ); bt_print(2); process_exit(1); @@ -21,11 +21,24 @@ func enum_cast(ptr: rawptr, expected_id: uint) -> rawptr { return enum_info.obj; } + + +func tagged_enum_cast(expected_id: uint, got_id: uint) { + if got_id != expected_id { + // TODO: replace indexes with names + console_ewriteln( + "runtime error: cannot cast tagged enum ID({}) to type ID({})", enum_info._id_, expected_id + ); + bt_print(2); + process_exit(1); + } +} + func trait_cast(got_obj: rawptr, got_id: uint, expected_id: uint) -> rawptr { if got_id != expected_id { // TODO: replace indexes with names console_ewriteln( - "runtime error: trait cast: cannot cast ID({}) to ID({})", got_id, expected_id + "runtime error: cannot cast trait ID({}) to type ID({})", got_id, expected_id ); bt_print(2); process_exit(1); diff --git a/rivetc/src/codegen/__init__.py b/rivetc/src/codegen/__init__.py index cca5a6f13..98eb25019 100644 --- a/rivetc/src/codegen/__init__.py +++ b/rivetc/src/codegen/__init__.py @@ -717,7 +717,7 @@ def gen_expr(self, expr, custom_tmp = None): elif isinstance(expr, ast.EnumLiteral): enum_sym = expr.typ.symbol() if expr.is_instance: - return self.boxed_enum_value(enum_sym, expr.value, None) + return self.tagged_enum_value(enum_sym, expr.value, None) return ir.IntLit( self.ir_type(enum_sym.info.underlying_typ), str(expr.variant_info.value) @@ -1053,7 +1053,7 @@ def gen_expr(self, expr, custom_tmp = None): self.cur_func.store( ir.Selector(f_typ, tmp, ir.Name(f.name)), value ) - return self.boxed_enum_variant_with_fields_value( + return self.tagged_enum_variant_with_fields_value( typ_sym, expr.left.value if isinstance(expr.left, ast.EnumLiteral) else expr.left.field_name, tmp, custom_tmp = custom_tmp @@ -1063,14 +1063,14 @@ def gen_expr(self, expr, custom_tmp = None): x = expr.args[0].expr else: x = None - return self.boxed_enum_value( + return self.tagged_enum_value( typ_sym, expr.left.value, x, custom_tmp = custom_tmp ) if len(expr.args) > 0: x = expr.args[0].expr else: x = None - return self.boxed_enum_value( + return self.tagged_enum_value( typ_sym, expr.left.field_name, x, custom_tmp = custom_tmp ) @@ -1463,7 +1463,7 @@ def gen_expr(self, expr, custom_tmp = None): expr.left_sym, sym.Type ) and expr.left_sym.kind == TypeKind.Enum: if expr.left_sym.info.is_tagged: - return self.boxed_enum_value( + return self.tagged_enum_value( expr.left_sym, expr.field_name, None, custom_tmp = custom_tmp ) @@ -2791,7 +2791,7 @@ def trait_value(self, value, value_typ, trait_typ): ) return tmp - def boxed_enum_value( + def tagged_enum_value( self, enum_sym, variant_name, value, custom_tmp = None ): if custom_tmp: @@ -2826,7 +2826,7 @@ def boxed_enum_value( self.cur_func.store(ir.Selector(uint_t, tmp, ir.Name("obj")), value) return tmp - def boxed_enum_variant_with_fields_value( + def tagged_enum_variant_with_fields_value( self, enum_sym, variant_name, value, custom_tmp = None ): if custom_tmp: From 4f6915575324065ce21b51abdf87e7b511743088 Mon Sep 17 00:00:00 2001 From: Jose Mendoza <56417208+StunxFS@users.noreply.github.com> Date: Fri, 15 Dec 2023 16:43:02 +0000 Subject: [PATCH 2/7] mvoe function to utils mod --- lib/core/src/utils.ri | 2 +- rivetc/src/codegen/__init__.py | 20 +------------------- rivetc/src/codegen/cg_utils.py | 20 +++++++++++++++++++- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/core/src/utils.ri b/lib/core/src/utils.ri index e24fe876d..197e44b12 100644 --- a/lib/core/src/utils.ri +++ b/lib/core/src/utils.ri @@ -27,7 +27,7 @@ func tagged_enum_cast(expected_id: uint, got_id: uint) { if got_id != expected_id { // TODO: replace indexes with names console_ewriteln( - "runtime error: cannot cast tagged enum ID({}) to type ID({})", enum_info._id_, expected_id + "runtime error: cannot cast tagged enum ID({}) to type ID({})", got_id, expected_id ); bt_print(2); process_exit(1); diff --git a/rivetc/src/codegen/__init__.py b/rivetc/src/codegen/__init__.py index 98eb25019..927e15714 100644 --- a/rivetc/src/codegen/__init__.py +++ b/rivetc/src/codegen/__init__.py @@ -686,7 +686,7 @@ def gen_expr(self, expr, custom_tmp = None): if expr.is_byte: return ir.IntLit( ir.UINT8_T, - str(utils.bytestr(self.decode_escape(expr.lit)).buf[0]) + str(utils.bytestr(cg_utils.decode_escape(expr.lit)).buf[0]) ) return ir.RuneLit(ir.RUNE_T, expr.lit) elif isinstance(expr, ast.IntegerLiteral): @@ -3208,21 +3208,3 @@ def sort_type_symbols(self, tss): if ts.mangled_name == node.name: types_sorted.append(ts) return types_sorted - - def decode_escape(self, ch): - if ch.startswith("\\"): - code = ch[1:] - code_b = utils.bytestr(code).buf[0] - if code in ("\\", "'", '"'): - return chr(code_b) - elif code in ("a", "b", "f"): - return chr(code_b - 90) - elif code == "n": - return "\n" - elif code == "r": - return "\r" - elif code == "t": - return "\t" - elif code == "v": - return "\v" - return ch diff --git a/rivetc/src/codegen/cg_utils.py b/rivetc/src/codegen/cg_utils.py index 4fca34dc4..d047b6df3 100644 --- a/rivetc/src/codegen/cg_utils.py +++ b/rivetc/src/codegen/cg_utils.py @@ -5,9 +5,27 @@ import os from ..sym import TypeKind -from .. import ast, sym, type +from .. import ast, sym, type, utils from ..token import OVERLOADABLE_OPERATORS_STR +def decode_escape(ch): + if ch.startswith("\\"): + code = ch[1:] + code_b = utils.bytestr(code).buf[0] + if code in ("\\", "'", '"'): + return chr(code_b) + elif code in ("a", "b", "f"): + return chr(code_b - 90) + elif code == "n": + return "\n" + elif code == "r": + return "\r" + elif code == "t": + return "\t" + elif code == "v": + return "\v" + return ch + def prefix_type(tt): prefix = "" if isinstance(tt, type.Ptr): From 54b4ba198b5886851a3e24b0b0d90127b5cb0732 Mon Sep 17 00:00:00 2001 From: Jose Mendoza <56417208+StunxFS@users.noreply.github.com> Date: Fri, 15 Dec 2023 16:57:27 +0000 Subject: [PATCH 3/7] support union generation --- rivetc/src/codegen/__init__.py | 12 ++++++++++-- rivetc/src/codegen/c.py | 22 ++++++++++++++++++---- rivetc/src/codegen/ir.py | 27 +++++++++++++++++++++++++-- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/rivetc/src/codegen/__init__.py b/rivetc/src/codegen/__init__.py index 927e15714..f4cf68dae 100644 --- a/rivetc/src/codegen/__init__.py +++ b/rivetc/src/codegen/__init__.py @@ -3024,12 +3024,20 @@ def gen_types(self): # TODO: in the self-hosted compiler calculate the enum value here # not in register nor resolver. if ts.info.is_tagged: + mangled_name = cg_utils.mangle_symbol(ts) + fields = [] + for v in ts.info.variants: + if v.has_typ: + typ_sym = v.typ.symbol() + fields.append(ir.Field(f"v{typ_sym.id}", self.ir_type(v.typ))) + union_name = mangled_name + "5Union" + self.out_rir.unions.append(ir.Union(union_name, fields)) self.out_rir.structs.append( ir.Struct( - False, cg_utils.mangle_symbol(ts), [ + False, mangled_name, [ ir.Field("_rc_", ir.UINT_T), ir.Field("_idx_", ir.UINT_T), - ir.Field("obj", ir.VOID_PTR_T) + ir.Field("obj", ir.Type(union_name)) ] ) ) diff --git a/rivetc/src/codegen/c.py b/rivetc/src/codegen/c.py index 3ff470536..fa0e1ea66 100644 --- a/rivetc/src/codegen/c.py +++ b/rivetc/src/codegen/c.py @@ -29,12 +29,15 @@ class CGen: def __init__(self, comp): self.comp = comp self.typedefs = utils.Builder() + self.unions = utils.Builder() self.structs = utils.Builder() self.protos = utils.Builder() self.globals = utils.Builder() self.out = utils.Builder() def gen(self, out_rir): + self.comp.vlog("cgen: generating unions...") + self.gen_unions(out_rir.unions) self.comp.vlog("cgen: generating structs...") self.gen_structs(out_rir.structs) self.comp.vlog("cgen: generating externs...") @@ -51,6 +54,7 @@ def gen(self, out_rir): if self.comp.prefs.build_mode != prefs.BuildMode.Release: out.write(c_headers.RIVET_BREAKPOINT) out.write(str(self.typedefs).strip() + "\n\n") + out.write(str(self.unions).strip() + "\n\n") out.write(str(self.structs).strip() + "\n\n") out.write(str(self.protos).strip() + "\n\n") out.write(str(self.globals).strip() + "\n\n") @@ -96,6 +100,19 @@ def write(self, txt): def writeln(self, txt = ""): self.out.writeln(txt) + def gen_unions(self, unions): + for u in unions: + self.typedefs.writeln(f"typedef union {u.name} {u.name};") + self.unions.writeln(f"union {u.name} {{") + for i, f in enumerate(u.fields): + f_name = c_escape(f.name) + self.unions.write(" ") + self.unions.write(self.gen_type(f.typ, f_name)) + if not isinstance(f.typ, (ir.Array, ir.Function)): + self.unions.write(f" {f_name}") + self.unions.writeln(";") + self.unions.writeln("};\n") + def gen_structs(self, structs): for s in structs: self.typedefs.writeln(f"typedef struct {s.name} {s.name};") @@ -107,10 +124,7 @@ def gen_structs(self, structs): self.structs.write(self.gen_type(f.typ, f_name)) if not isinstance(f.typ, (ir.Array, ir.Function)): self.structs.write(f" {f_name}") - if i < len(s.fields) - 1: - self.structs.writeln(";") - else: - self.structs.writeln(";") + self.structs.writeln(";") self.structs.writeln("};") self.structs.writeln() diff --git a/rivetc/src/codegen/ir.py b/rivetc/src/codegen/ir.py index f4d895271..1ddac0340 100644 --- a/rivetc/src/codegen/ir.py +++ b/rivetc/src/codegen/ir.py @@ -128,6 +128,7 @@ def __eq__(self, other): class RIRFile: def __init__(self, mod_name): self.mod_name = mod_name + self.unions = [] self.structs = [] self.externs = [] self.globals = [] @@ -146,6 +147,11 @@ def __repr__(self): "// and is subject to change without notice. Knock yourself out." ) sb.writeln() + for i, u in enumerate(self.unions): + sb.writeln(str(u)) + if i < len(self.unions) - 1: + sb.writeln() + sb.writeln() for i, s in enumerate(self.structs): sb.writeln(str(s)) if i < len(self.structs) - 1: @@ -189,6 +195,23 @@ def __str__(self): sb.write("}") return str(sb) +class Union: + def __init__(self, name, fields): + self.name = name + self.fields = fields + + def __str__(self): + sb = utils.Builder() + sb.writeln(f'union {self.name} {{') + for i, f in enumerate(self.fields): + sb.write(f' {f.name}: {f.typ}') + if i < len(self.fields) - 1: + sb.writeln(",") + else: + sb.writeln() + sb.write("}") + return str(sb) + class Struct: def __init__(self, is_opaque, name, fields): self.is_opaque = is_opaque @@ -198,9 +221,9 @@ def __init__(self, is_opaque, name, fields): def __str__(self): sb = utils.Builder() if self.is_opaque: - sb.write(f'type {self.name} opaque') + sb.write(f'struct {self.name} opaque') else: - sb.writeln(f'type {self.name} {{') + sb.writeln(f'struct {self.name} {{') for i, f in enumerate(self.fields): sb.write(f' {f.name}: {f.typ}') if i < len(self.fields) - 1: From 767fc11d9421b27021cab0bd2a7f8ff1aa7c766a Mon Sep 17 00:00:00 2001 From: Jose Mendoza <56417208+StunxFS@users.noreply.github.com> Date: Fri, 15 Dec 2023 17:27:26 +0000 Subject: [PATCH 4/7] changes --- rivetc/src/codegen/__init__.py | 85 ++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/rivetc/src/codegen/__init__.py b/rivetc/src/codegen/__init__.py index f4cf68dae..f651250a3 100644 --- a/rivetc/src/codegen/__init__.py +++ b/rivetc/src/codegen/__init__.py @@ -1877,17 +1877,25 @@ def gen_expr(self, expr, custom_tmp = None): var_t2 = var_t if isinstance( var_t, ir.Pointer ) or expr.var.is_mut else var_t.ptr() - val = ir.Inst( - ir.InstKind.Cast, [ - ir.Selector(ir.VOID_PTR_T, left, ir.Name("obj")), - var_t2 - ] - ) - if not ( - (isinstance(var_t2, ir.Pointer) and var_t2.is_managed) - or expr.var.is_mut - ): - val = ir.Inst(ir.InstKind.LoadPtr, [val], var_t2) + if left_sym.kind == TypeKind.Enum: + union_name = f"{cg_utils.mangle_symbol(left_sym)}5Union" + union_type = ir.Type(union_name) + obj_val = ir.Selector(union_type, left, ir.Name("obj")) + val = ir.Selector( + ir.Type(self.ir_type(expr.typ)), obj_val, ir.Name(f"v{expr.var.typ.symbol().id}") + ) + else: + val = ir.Inst( + ir.InstKind.Cast, [ + ir.Selector(ir.VOID_PTR_T, left, ir.Name("obj")), + var_t2 + ] + ) + if not ( + (isinstance(var_t2, ir.Pointer) and var_t2.is_managed) + or expr.var.is_mut + ): + val = ir.Inst(ir.InstKind.LoadPtr, [val], var_t2) unique_name = self.cur_func.unique_name(expr.var.name) expr.scope.update_ir_name(expr.var.name, unique_name) self.cur_func.inline_alloca(var_t, unique_name, val) @@ -2227,14 +2235,14 @@ def gen_expr(self, expr, custom_tmp = None): var_t = self.ir_type(b.var_typ) var_t2 = var_t.ptr( ) if not isinstance(var_t, ir.Pointer) else var_t - if expr.expr.typ.symbol().kind == TypeKind.Enum: - val = ir.Inst( - ir.InstKind.Cast, [ - ir.Selector( - ir.VOID_PTR_T, match_expr, - ir.Name("obj") - ), var_t2 - ] + e_expr_typ_sym = expr.expr.typ.symbol() + if e_expr_typ_sym.kind == TypeKind.Enum: + obj_f = ir.Selector( + e_expr_typ_sym.name + "5Union", match_expr, ir.Name("obj") + ) + val = ir.Selector( + self.ir_type(p.variant_info.typ), + obj_f, ir.Name(f"v{p.variant_info.typ.symbol().id}") ) else: val = ir.Inst( @@ -2245,13 +2253,13 @@ def gen_expr(self, expr, custom_tmp = None): ), var_t ] ) - if not ( - b.var_is_mut or ( - isinstance(var_t, ir.Pointer) - and var_t.is_managed - ) - ): - val = ir.Inst(ir.InstKind.LoadPtr, [val]) + if not ( + b.var_is_mut or ( + isinstance(var_t, ir.Pointer) + and var_t.is_managed + ) + ): + val = ir.Inst(ir.InstKind.LoadPtr, [val]) if b.var_is_mut and not isinstance( var_t, ir.Pointer ): @@ -2809,21 +2817,14 @@ def tagged_enum_value( if variant_info.has_typ and value and not isinstance( value, ast.EmptyExpr ): + variant_typ_sym = variant_info.typ.symbol() arg0 = self.gen_expr_with_cast(variant_info.typ, value) size, _ = self.comp.type_size(variant_info.typ) - if isinstance(arg0.typ, ir.Pointer): - value = arg0 - else: - value = ir.Inst( - ir.InstKind.Call, [ - ir.Name("_R4core7mem_dupF"), - ir.Inst(ir.InstKind.GetRef, [arg0]), - ir.IntLit(uint_t, str(size)) - ] - ) - else: - value = ir.NoneLit(ir.VOID_PTR_T) - self.cur_func.store(ir.Selector(uint_t, tmp, ir.Name("obj")), value) + obj_f = ir.Selector(ir.Type(f"{cg_utils.mangle_symbol(enum_sym)}5Union"), tmp, ir.Name("obj")) + self.cur_func.store( + ir.Selector(self.ir_type(variant_info.typ), obj_f, ir.Name(f"v{variant_typ_sym.id}")), + arg0 + ) return tmp def tagged_enum_variant_with_fields_value( @@ -2836,11 +2837,15 @@ def tagged_enum_variant_with_fields_value( cg_utils.mangle_symbol(enum_sym), enum_sym.id ) variant_info = enum_sym.info.get_variant(variant_name) + variant_typ_sym = variant_info.typ.symbol() self.cur_func.store( ir.Selector(ir.UINT_T, tmp, ir.Name("_idx_")), ir.IntLit(ir.UINT_T, variant_info.value) ) - self.cur_func.store(ir.Selector(ir.UINT_T, tmp, ir.Name("obj")), value) + obj_f = ir.Selector(ir.Type(f"{cg_utils.mangle_symbol(enum_sym)}5Union"), tmp, ir.Name("obj")) + self.cur_func.store( + ir.Selector(self.ir_type(variant_info.typ), obj_f, ir.Name(f"v{variant_typ_sym.id}")), value + ) return tmp def gen_return_trace_add(self, pos): From 888ffb3ae656632bd2f5f89e2c9a0ebb6acf2900 Mon Sep 17 00:00:00 2001 From: Jose Mendoza <56417208+StunxFS@users.noreply.github.com> Date: Fri, 15 Dec 2023 17:51:32 +0000 Subject: [PATCH 5/7] sort tagged enum variants --- rivetc/src/codegen/__init__.py | 26 ++++++++++----- rivetc/src/codegen/c.py | 59 +++++++++++++++------------------ rivetc/src/codegen/c_headers.py | 8 ++--- rivetc/src/codegen/ir.py | 14 +++----- 4 files changed, 52 insertions(+), 55 deletions(-) diff --git a/rivetc/src/codegen/__init__.py b/rivetc/src/codegen/__init__.py index f651250a3..0b5fd4c1e 100644 --- a/rivetc/src/codegen/__init__.py +++ b/rivetc/src/codegen/__init__.py @@ -321,7 +321,7 @@ def gen_decl(self, decl): name = f"_R{len(name)}{name}" if name not in self.generated_array_returns: arr_ret_struct = name - self.out_rir.structs.append( + self.out_rir.types.append( ir.Struct(False, name, [ir.Field("arr", ret_typ)]) ) self.generated_array_returns.append(name) @@ -2933,7 +2933,7 @@ def ir_type(self, typ, gen_self_arg = False): name = f"_R6Result{cg_utils.mangle_type(typ.typ)}" if name not in self.generated_opt_res_types: is_void = typ.typ in self.void_types - self.out_rir.structs.append( + self.out_rir.types.append( ir.Struct( False, name, [ ir.Field( @@ -2955,7 +2955,7 @@ def ir_type(self, typ, gen_self_arg = False): name = f"_R6Option{cg_utils.mangle_type(typ.typ)}" if name not in self.generated_opt_res_types: is_void = typ.typ in self.void_types - self.out_rir.structs.append( + self.out_rir.types.append( ir.Struct( False, name, [ ir.Field( @@ -3022,7 +3022,7 @@ def gen_types(self): fields = [] for i, f in enumerate(ts.info.types): fields.append(ir.Field(f"f{i}", self.ir_type(f))) - self.out_rir.structs.append( + self.out_rir.types.append( ir.Struct(False, cg_utils.mangle_symbol(ts), fields) ) elif ts.kind == TypeKind.Enum: @@ -3036,8 +3036,8 @@ def gen_types(self): typ_sym = v.typ.symbol() fields.append(ir.Field(f"v{typ_sym.id}", self.ir_type(v.typ))) union_name = mangled_name + "5Union" - self.out_rir.unions.append(ir.Union(union_name, fields)) - self.out_rir.structs.append( + self.out_rir.types.append(ir.Union(union_name, fields)) + self.out_rir.types.append( ir.Struct( False, mangled_name, [ ir.Field("_rc_", ir.UINT_T), @@ -3059,7 +3059,7 @@ def gen_types(self): if not isinstance(f_typ, ir.Pointer): f_typ = f_typ.ptr() fields.append(ir.Field(f.name, f_typ)) - self.out_rir.structs.append(ir.Struct(False, ts_name, fields)) + self.out_rir.types.append(ir.Struct(False, ts_name, fields)) # Virtual table vtbl_name = f"{ts_name}4Vtbl" static_vtbl_name = f"{ts_name}4VTBL" @@ -3098,7 +3098,7 @@ def gen_types(self): funcs.append(map) index_of_vtbl.append((its.qualname(), its.id, idx)) if len(funcs) > 0 and ts.info.has_objects: - self.out_rir.structs.append( + self.out_rir.types.append( ir.Struct(False, vtbl_name, fields) ) self.out_rir.decls.append( @@ -3139,7 +3139,7 @@ def gen_types(self): ] if ts.info.is_boxed else [] for f in ts.full_fields(): fields.append(ir.Field(f.name, self.ir_type(f.typ))) - self.out_rir.structs.append( + self.out_rir.types.append( ir.Struct( ts.info.is_opaque, cg_utils.mangle_symbol(ts), fields ) @@ -3182,6 +3182,14 @@ def sort_type_symbols(self, tss): ): continue field_deps.append(dep) + elif ts.kind == TypeKind.Enum and ts.info.is_tagged: + for variant in ts.info.variants: + if variant.has_typ: + variant_sym = variant.typ.symbol() + dep = cg_utils.mangle_symbol(variant_sym) + if dep not in typ_names or dep in field_deps: + continue + field_deps.append(dep) elif ts.kind == TypeKind.Trait: for base in ts.info.bases: dep = cg_utils.mangle_symbol(base) diff --git a/rivetc/src/codegen/c.py b/rivetc/src/codegen/c.py index fa0e1ea66..82ee87c3f 100644 --- a/rivetc/src/codegen/c.py +++ b/rivetc/src/codegen/c.py @@ -29,17 +29,14 @@ class CGen: def __init__(self, comp): self.comp = comp self.typedefs = utils.Builder() - self.unions = utils.Builder() - self.structs = utils.Builder() + self.types = utils.Builder() self.protos = utils.Builder() self.globals = utils.Builder() self.out = utils.Builder() def gen(self, out_rir): - self.comp.vlog("cgen: generating unions...") - self.gen_unions(out_rir.unions) - self.comp.vlog("cgen: generating structs...") - self.gen_structs(out_rir.structs) + self.comp.vlog("cgen: generating types...") + self.gen_types(out_rir.types) self.comp.vlog("cgen: generating externs...") self.gen_externs(out_rir.externs) self.comp.vlog("cgen: generating globals...") @@ -54,8 +51,7 @@ def gen(self, out_rir): if self.comp.prefs.build_mode != prefs.BuildMode.Release: out.write(c_headers.RIVET_BREAKPOINT) out.write(str(self.typedefs).strip() + "\n\n") - out.write(str(self.unions).strip() + "\n\n") - out.write(str(self.structs).strip() + "\n\n") + out.write(str(self.types).strip() + "\n\n") out.write(str(self.protos).strip() + "\n\n") out.write(str(self.globals).strip() + "\n\n") out.write(str(self.out).strip()) @@ -100,33 +96,32 @@ def write(self, txt): def writeln(self, txt = ""): self.out.writeln(txt) - def gen_unions(self, unions): - for u in unions: - self.typedefs.writeln(f"typedef union {u.name} {u.name};") - self.unions.writeln(f"union {u.name} {{") - for i, f in enumerate(u.fields): - f_name = c_escape(f.name) - self.unions.write(" ") - self.unions.write(self.gen_type(f.typ, f_name)) - if not isinstance(f.typ, (ir.Array, ir.Function)): - self.unions.write(f" {f_name}") - self.unions.writeln(";") - self.unions.writeln("};\n") - - def gen_structs(self, structs): - for s in structs: - self.typedefs.writeln(f"typedef struct {s.name} {s.name};") - if not s.is_opaque: - self.structs.writeln(f"struct {s.name} {{") + def gen_types(self, types): + for s in types: + if isinstance(s, ir.Struct): + self.typedefs.writeln(f"typedef struct {s.name} {s.name};") + if not s.is_opaque: + self.types.writeln(f"struct {s.name} {{") + for i, f in enumerate(s.fields): + f_name = c_escape(f.name) + self.types.write(" ") + self.types.write(self.gen_type(f.typ, f_name)) + if not isinstance(f.typ, (ir.Array, ir.Function)): + self.types.write(f" {f_name}") + self.types.writeln(";") + self.types.writeln("};") + self.types.writeln() + else: + self.typedefs.writeln(f"typedef union {s.name} {s.name};") + self.types.writeln(f"union {s.name} {{") for i, f in enumerate(s.fields): f_name = c_escape(f.name) - self.structs.write(" ") - self.structs.write(self.gen_type(f.typ, f_name)) + self.types.write(" ") + self.types.write(self.gen_type(f.typ, f_name)) if not isinstance(f.typ, (ir.Array, ir.Function)): - self.structs.write(f" {f_name}") - self.structs.writeln(";") - self.structs.writeln("};") - self.structs.writeln() + self.types.write(f" {f_name}") + self.types.writeln(";") + self.types.writeln("};\n") def gen_externs(self, externs): for extern_fn in externs: diff --git a/rivetc/src/codegen/c_headers.py b/rivetc/src/codegen/c_headers.py index 2ffb0ce4c..3806888aa 100644 --- a/rivetc/src/codegen/c_headers.py +++ b/rivetc/src/codegen/c_headers.py @@ -64,13 +64,13 @@ typedef uint64_t uint64; typedef ptrdiff_t ri_int; typedef size_t ri_uint; -typedef ri_int comptime_int; - -typedef uint8 bool; -typedef uint32 rune; typedef float float32; typedef double float64; + +typedef uint8 bool; +typedef uint32 rune; +typedef ri_int comptime_int; typedef float64 comptime_float; """ diff --git a/rivetc/src/codegen/ir.py b/rivetc/src/codegen/ir.py index 1ddac0340..584339539 100644 --- a/rivetc/src/codegen/ir.py +++ b/rivetc/src/codegen/ir.py @@ -128,8 +128,7 @@ def __eq__(self, other): class RIRFile: def __init__(self, mod_name): self.mod_name = mod_name - self.unions = [] - self.structs = [] + self.types = [] self.externs = [] self.globals = [] self.decls = [] @@ -147,14 +146,9 @@ def __repr__(self): "// and is subject to change without notice. Knock yourself out." ) sb.writeln() - for i, u in enumerate(self.unions): - sb.writeln(str(u)) - if i < len(self.unions) - 1: - sb.writeln() - sb.writeln() - for i, s in enumerate(self.structs): - sb.writeln(str(s)) - if i < len(self.structs) - 1: + for i, t in enumerate(self.types): + sb.writeln(str(t)) + if i < len(self.types) - 1: sb.writeln() sb.writeln() for i, e in enumerate(self.externs): From 42001876d0207b51cdd62c2cd791998143a5b0b3 Mon Sep 17 00:00:00 2001 From: Jose Mendoza <56417208+StunxFS@users.noreply.github.com> Date: Fri, 15 Dec 2023 18:42:39 +0000 Subject: [PATCH 6/7] final change --- lib/core/src/utils.ri | 23 +------ rivetc/src/codegen/__init__.py | 109 ++++++++++++++------------------- rivetc/src/codegen/c.py | 2 +- rivetc/src/codegen/ir.py | 4 +- 4 files changed, 49 insertions(+), 89 deletions(-) diff --git a/lib/core/src/utils.ri b/lib/core/src/utils.ri index 197e44b12..e811d6f3d 100644 --- a/lib/core/src/utils.ri +++ b/lib/core/src/utils.ri @@ -2,32 +2,11 @@ // Use of this source code is governed by an MIT license that can // be found in the LICENSE file. -struct EnumInfo { - _rc_: uint; - _id_: uint; - obj: rawptr; -} - -func enum_cast(ptr: rawptr, expected_id: uint) -> rawptr { - enum_info := unsafe { @as(&EnumInfo, ptr) }; - if enum_info._id_ != expected_id { - // TODO: replace indexes with names - console_ewriteln( - "runtime error: cannot cast tagged enum ID({}) to type ID({})", enum_info._id_, expected_id - ); - bt_print(2); - process_exit(1); - } - return enum_info.obj; -} - - - func tagged_enum_cast(expected_id: uint, got_id: uint) { if got_id != expected_id { // TODO: replace indexes with names console_ewriteln( - "runtime error: cannot cast tagged enum ID({}) to type ID({})", got_id, expected_id + "runtime error: cannot cast tagged enum ID({}) to variant ID({})", got_id, expected_id ); bt_print(2); process_exit(1); diff --git a/rivetc/src/codegen/__init__.py b/rivetc/src/codegen/__init__.py index 0b5fd4c1e..606c25887 100644 --- a/rivetc/src/codegen/__init__.py +++ b/rivetc/src/codegen/__init__.py @@ -165,7 +165,7 @@ def gen_source_files(self, source_files): argc, ir.Inst(ir.InstKind.Cast, [argv, ir.UINT8_T.ptr().ptr()]), - ir.Inst(ir.InstKind.GetRef, [testRunner]) + ir.Inst(ir.InstKind.GetPtr, [testRunner]) ] ) else: @@ -605,7 +605,7 @@ def gen_expr_with_cast(self, expected_typ_, expr, custom_tmp = None): elif nr_level < nr_level_expected: while nr_level < nr_level_expected: res_expr = ir.Inst( - ir.InstKind.GetRef, [res_expr], + ir.InstKind.GetPtr, [res_expr], res_expr.typ.ptr() ) nr_level += 1 @@ -623,7 +623,7 @@ def gen_expr_with_cast(self, expected_typ_, expr, custom_tmp = None): ) if isinstance(res_expr.typ, ir.Pointer) else 0 while nr_level < nr_level_expected: res_expr = ir.Inst( - ir.InstKind.GetRef, [res_expr], res_expr.typ.ptr() + ir.InstKind.GetPtr, [res_expr], res_expr.typ.ptr() ) nr_level += 1 @@ -640,25 +640,13 @@ def gen_expr_with_cast(self, expected_typ_, expr, custom_tmp = None): ): tmp = self.cur_func.local_name() tmp_t = expected_typ - load_ptr = False - if not ( - isinstance(expected_typ, ir.Pointer) and expected_typ.is_managed - ): - load_ptr = True - expected_typ = expected_typ.ptr(True) - value = ir.Inst( - ir.InstKind.Cast, [ - ir.Inst( - ir.InstKind.Call, [ - ir.Name("_R4core9enum_castF"), res_expr, - expr_sym.info.get_variant_by_type(expected_typ_ - ).value - ] - ), expected_typ - ] - ) - if load_ptr: - value = ir.Inst(ir.InstKind.LoadPtr, [value]) + variant_idx = expr_sym.info.get_variant_by_type(expected_typ_).value + self.cur_func.add_call("_R4core16tagged_enum_castF", [ + ir.Selector(ir.UINT_T, res_expr, ir.Name("_idx_")), + variant_idx + ]) + obj_f = ir.Selector(ir.Type(cg_utils.mangle_symbol(expr_sym)+"5Union"), res_expr, ir.Name("obj")) + value = ir.Selector(self.ir_type(expr.typ), obj_f, ir.Name(f"v{variant_idx}")) self.cur_func.inline_alloca(tmp_t, tmp, value) res_expr = ir.Ident(tmp_t, tmp) @@ -817,25 +805,13 @@ def gen_expr(self, expr, custom_tmp = None): elif typ_sym.kind == TypeKind.Enum and typ_sym.info.is_tagged: tmp = self.cur_func.local_name() tmp_t = ir_typ - load_ptr = False - if not ( - isinstance(ir_typ, ir.Pointer) and ir_typ.is_managed - ): - load_ptr = True - ir_typ = ir_typ.ptr(True) - value = ir.Inst( - ir.InstKind.Cast, [ - ir.Inst( - ir.InstKind.Call, [ - ir.Name("_R4core9enum_castF"), res, - typ_sym.info.get_variant_by_type(expr.typ - ).value - ] - ), ir_typ - ] - ) - if load_ptr: - value = ir.Inst(ir.InstKind.LoadPtr, [value]) + variant_idx = typ_sym.info.get_variant_by_type(expr.typ).value + self.cur_func.add_call("_R4core16tagged_enum_castF", [ + ir.Selector(ir.UINT_T, res, ir.Name("_idx_")), + variant_idx + ]) + obj_f = ir.Selector(ir.Type(cg_utils.mangle_symbol(typ_sym)+"5Union"), res, ir.Name("obj")) + value = ir.Selector(self.ir_type(expr.typ), obj_f, ir.Name(f"v{variant_idx}")) self.cur_func.inline_alloca(tmp_t, tmp, value) return ir.Ident(tmp_t, tmp) tmp = self.cur_func.local_name() @@ -964,10 +940,10 @@ def gen_expr(self, expr, custom_tmp = None): right_operand = right if not isinstance(expr_left_typ_ir, ir.Pointer): left_operand = ir.Inst( - ir.InstKind.GetRef, [left_operand] + ir.InstKind.GetPtr, [left_operand] ) right_operand = ir.Inst( - ir.InstKind.GetRef, [right_operand] + ir.InstKind.GetPtr, [right_operand] ) self.cur_func.store( left, @@ -1227,7 +1203,7 @@ def gen_expr(self, expr, custom_tmp = None): if sym_rec_is_ref and not isinstance( self_expr.typ, ir.Pointer ): - self_expr = ir.Inst(ir.InstKind.GetRef, [self_expr]) + self_expr = ir.Inst(ir.InstKind.GetPtr, [self_expr]) elif isinstance( receiver.typ, type.Ptr ) and not sym_rec_is_ref: @@ -1252,7 +1228,7 @@ def gen_expr(self, expr, custom_tmp = None): if left_sym.kind == TypeKind.DynArray and expr.sym.name == "push": if arg.typ.symbol().is_boxed(): arg_value = ir.Inst( - ir.InstKind.GetRef, [arg_value], + ir.InstKind.GetPtr, [arg_value], arg_value.typ.ptr() ) args.append(arg_value) @@ -1547,7 +1523,7 @@ def gen_expr(self, expr, custom_tmp = None): init_value = self.gen_expr_with_cast( expr.elem_type, expr.init_value ) - args.append(ir.Inst(ir.InstKind.GetRef, [init_value])) + args.append(ir.Inst(ir.InstKind.GetPtr, [init_value])) # element size args.append(ir.IntLit(ir.UINT_T, str(size))) # length @@ -1582,7 +1558,7 @@ def gen_expr(self, expr, custom_tmp = None): ir.IntLit( ir.UINT_T, str(expr.typ.symbol().info.size) ), - ir.Inst(ir.InstKind.GetRef, [init_value]) + ir.Inst(ir.InstKind.GetPtr, [init_value]) ] ) if custom_tmp: @@ -1733,7 +1709,7 @@ def gen_expr(self, expr, custom_tmp = None): ) and right.kind == ir.InstKind.LoadPtr: right = right.args[0] else: - right = ir.Inst(ir.InstKind.GetRef, [right]) + right = ir.Inst(ir.InstKind.GetPtr, [right]) self.cur_func.inline_alloca(self.ir_type(expr.typ), tmp, right) return ir.Ident(self.ir_type(expr.typ), tmp) @@ -1882,8 +1858,10 @@ def gen_expr(self, expr, custom_tmp = None): union_type = ir.Type(union_name) obj_val = ir.Selector(union_type, left, ir.Name("obj")) val = ir.Selector( - ir.Type(self.ir_type(expr.typ)), obj_val, ir.Name(f"v{expr.var.typ.symbol().id}") + ir.Type(self.ir_type(expr.typ)), obj_val, ir.Name(f"v{expr.right.variant_info.value}") ) + if expr.var.is_mut and isinstance(var_t2, ir.Pointer): + val = ir.Inst(ir.InstKind.GetPtr, [val], var_t2) else: val = ir.Inst( ir.InstKind.Cast, [ @@ -2059,9 +2037,9 @@ def gen_expr(self, expr, custom_tmp = None): cg_utils.mangle_symbol(typ_sym) + f"{len(op_method)}{op_method}M" ), left if sym_is_boxed else - ir.Inst(ir.InstKind.GetRef, [left]), + ir.Inst(ir.InstKind.GetPtr, [left]), right if sym_is_boxed else - ir.Inst(ir.InstKind.GetRef, [right]) + ir.Inst(ir.InstKind.GetPtr, [right]) ] ) ) @@ -2242,8 +2220,10 @@ def gen_expr(self, expr, custom_tmp = None): ) val = ir.Selector( self.ir_type(p.variant_info.typ), - obj_f, ir.Name(f"v{p.variant_info.typ.symbol().id}") + obj_f, ir.Name(f"v{p.variant_info.value}") ) + if b.var_is_mut and not isinstance(var_t, ir.Pointer): + val = ir.Inst(ir.InstKind.GetPtr, [val]) else: val = ir.Inst( ir.InstKind.Cast, [ @@ -2456,14 +2436,14 @@ def gen_left_assign(self, expr, right, assign_op): if left_sym.kind == TypeKind.DynArray and assign_op == Kind.Assign: rec = self.gen_expr_with_cast(expr.left_typ, expr.left) if not isinstance(left_ir_typ, ir.Pointer): - rec = ir.Inst(ir.InstKind.GetRef, [rec]) + rec = ir.Inst(ir.InstKind.GetPtr, [rec]) expr_right = self.gen_expr_with_cast(right.typ, right) val_sym = right.typ.symbol() self.cur_func.add_call( "_R4core8DynArray3setM", [ rec, self.gen_expr(expr.index), - ir.Inst(ir.InstKind.GetRef, [expr_right]) + ir.Inst(ir.InstKind.GetPtr, [expr_right]) ] ) self.inside_lhs_assign = old_inside_lhs_assign @@ -2761,12 +2741,12 @@ def trait_value(self, value, value_typ, trait_typ): value_f = ir.Selector(f_typ, value, ir.Name(f.name)) if not isinstance(f_typ, ir.Pointer): f_typ = f_typ.ptr(True) - value_f = ir.Inst(ir.InstKind.GetRef, [value_f], f_typ) + value_f = ir.Inst(ir.InstKind.GetPtr, [value_f], f_typ) self.cur_func.store( ir.Selector(f_typ, tmp, ir.Name(f.name)), value_f ) if not is_ptr: - value = ir.Inst(ir.InstKind.GetRef, [value]) + value = ir.Inst(ir.InstKind.GetPtr, [value]) value = value if is_ptr else ir.Inst( ir.InstKind.Call, [ ir.Name("_R4core7mem_dupF"), value, @@ -2817,12 +2797,11 @@ def tagged_enum_value( if variant_info.has_typ and value and not isinstance( value, ast.EmptyExpr ): - variant_typ_sym = variant_info.typ.symbol() arg0 = self.gen_expr_with_cast(variant_info.typ, value) size, _ = self.comp.type_size(variant_info.typ) obj_f = ir.Selector(ir.Type(f"{cg_utils.mangle_symbol(enum_sym)}5Union"), tmp, ir.Name("obj")) self.cur_func.store( - ir.Selector(self.ir_type(variant_info.typ), obj_f, ir.Name(f"v{variant_typ_sym.id}")), + ir.Selector(self.ir_type(variant_info.typ), obj_f, ir.Name(f"v{variant_info.value}")), arg0 ) return tmp @@ -2837,14 +2816,13 @@ def tagged_enum_variant_with_fields_value( cg_utils.mangle_symbol(enum_sym), enum_sym.id ) variant_info = enum_sym.info.get_variant(variant_name) - variant_typ_sym = variant_info.typ.symbol() self.cur_func.store( ir.Selector(ir.UINT_T, tmp, ir.Name("_idx_")), ir.IntLit(ir.UINT_T, variant_info.value) ) obj_f = ir.Selector(ir.Type(f"{cg_utils.mangle_symbol(enum_sym)}5Union"), tmp, ir.Name("obj")) self.cur_func.store( - ir.Selector(self.ir_type(variant_info.typ), obj_f, ir.Name(f"v{variant_typ_sym.id}")), value + ir.Selector(self.ir_type(variant_info.typ), obj_f, ir.Name(f"v{variant_info.value}")), value ) return tmp @@ -2867,7 +2845,7 @@ def gen_return_trace_add(self, pos): self.cur_func.add_call( "_R4core11ReturnTrace3addM", [ ir.Inst( - ir.InstKind.GetRef, [ + ir.InstKind.GetPtr, [ ir.Ident( ir.Type("_R4core11ReturnTrace"), "_R4core11returnTrace" @@ -2881,7 +2859,7 @@ def gen_return_trace_clear(self): self.cur_func.add_call( "_R4core11ReturnTrace5clearM", [ ir.Inst( - ir.InstKind.GetRef, [ + ir.InstKind.GetPtr, [ ir.Ident( ir.Type("_R4core11ReturnTrace"), "_R4core11returnTrace" @@ -3033,8 +3011,7 @@ def gen_types(self): fields = [] for v in ts.info.variants: if v.has_typ: - typ_sym = v.typ.symbol() - fields.append(ir.Field(f"v{typ_sym.id}", self.ir_type(v.typ))) + fields.append(ir.Field(f"v{v.value}", self.ir_type(v.typ))) union_name = mangled_name + "5Union" self.out_rir.types.append(ir.Union(union_name, fields)) self.out_rir.types.append( @@ -3186,6 +3163,10 @@ def sort_type_symbols(self, tss): for variant in ts.info.variants: if variant.has_typ: variant_sym = variant.typ.symbol() + if variant_sym.kind != TypeKind.Struct: + continue + if variant_sym.is_boxed() or isinstance(variant.typ, type.Option): + continue dep = cg_utils.mangle_symbol(variant_sym) if dep not in typ_names or dep in field_deps: continue diff --git a/rivetc/src/codegen/c.py b/rivetc/src/codegen/c.py index 82ee87c3f..e9aed42ba 100644 --- a/rivetc/src/codegen/c.py +++ b/rivetc/src/codegen/c.py @@ -288,7 +288,7 @@ def gen_inst(self, inst): self.write(" + ") self.gen_expr(inst.args[1]) self.write(")") - elif inst.kind == InstKind.GetRef: + elif inst.kind == InstKind.GetPtr: arg0 = inst.args[0] if isinstance(arg0, (ir.Ident, ir.Selector, ir.ArrayLit)): if isinstance(arg0, ir.ArrayLit): diff --git a/rivetc/src/codegen/ir.py b/rivetc/src/codegen/ir.py index 584339539..8ea5ce316 100644 --- a/rivetc/src/codegen/ir.py +++ b/rivetc/src/codegen/ir.py @@ -528,7 +528,7 @@ class InstKind(Enum): StorePtr = auto_enum() LoadPtr = auto_enum() GetElementPtr = auto_enum() - GetRef = auto_enum() + GetPtr = auto_enum() Cast = auto_enum() Cmp = auto_enum() @@ -570,7 +570,7 @@ def __repr__(self): elif self == InstKind.StorePtr: return "store_ptr" elif self == InstKind.LoadPtr: return "load_ptr" elif self == InstKind.GetElementPtr: return "get_element_ptr" - elif self == InstKind.GetRef: return "get_ref" + elif self == InstKind.GetPtr: return "get_ref" elif self == InstKind.Cast: return "cast" elif self == InstKind.Cmp: return "cmp" elif self == InstKind.DbgStmtLine: return "dbg_stmt_line" From ee70927c6274d7843e831b7d91809007febdd326 Mon Sep 17 00:00:00 2001 From: Jose Mendoza <56417208+StunxFS@users.noreply.github.com> Date: Fri, 15 Dec 2023 18:46:38 +0000 Subject: [PATCH 7/7] fix --- rivetc/src/codegen/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rivetc/src/codegen/__init__.py b/rivetc/src/codegen/__init__.py index 606c25887..f8c84c1cd 100644 --- a/rivetc/src/codegen/__init__.py +++ b/rivetc/src/codegen/__init__.py @@ -1860,7 +1860,7 @@ def gen_expr(self, expr, custom_tmp = None): val = ir.Selector( ir.Type(self.ir_type(expr.typ)), obj_val, ir.Name(f"v{expr.right.variant_info.value}") ) - if expr.var.is_mut and isinstance(var_t2, ir.Pointer): + if expr.var.is_mut and not isinstance(var_t2, ir.Pointer): val = ir.Inst(ir.InstKind.GetPtr, [val], var_t2) else: val = ir.Inst(