diff --git a/vlib/v/gen/native/amd64.v b/vlib/v/gen/native/amd64.v index 5fa4ec95ae..45cacb35ba 100644 --- a/vlib/v/gen/native/amd64.v +++ b/vlib/v/gen/native/amd64.v @@ -112,11 +112,6 @@ fn (mut c Amd64) dec(reg Amd64Register) { c.g.println('dec ${reg}') } -[inline] -fn byt(n int, s int) u8 { - return u8((n >> (s * 8)) & 0xff) -} - fn (mut c Amd64) inc(reg Amd64Register) { c.g.write8(0x48) c.g.write8(0xff) @@ -1009,6 +1004,7 @@ fn (mut c Amd64) push(reg Amd64Register) { } c.is_16bit_aligned = !c.is_16bit_aligned c.g.println('push ${reg}') + c.g.stack_depth++ } pub fn (mut c Amd64) pop(reg Amd64Register) { @@ -1018,6 +1014,7 @@ pub fn (mut c Amd64) pop(reg Amd64Register) { c.g.write8(0x58 + int(reg) % 8) c.is_16bit_aligned = !c.is_16bit_aligned c.g.println('pop ${reg}') + c.g.stack_depth-- } pub fn (mut c Amd64) sub8(reg Amd64Register, val int) { @@ -2102,8 +2099,14 @@ fn (mut c Amd64) assign_right_expr(node ast.AssignStmt, i int, right ast.Expr, n ast.StructInit { match node.op { .decl_assign { - c.g.allocate_by_type(name, right.typ) - c.init_struct(ident, right) + dest := c.g.allocate_by_type(name, right.typ) + if right.typ.is_any_kind_of_pointer() + || c.g.unwrap(right.typ).is_any_kind_of_pointer() { + c.g.expr(right) + c.mov_reg_to_var(LocalVar{dest, ast.u64_type_idx, name}, Amd64Register.rax) + } else { + c.init_struct(ident, right) + } } else { c.g.n_error('Unexpected operator `${node.op}`') @@ -2773,6 +2776,9 @@ fn (mut c Amd64) gen_left_value(node ast.Expr) { c.add(.rax, offset) } } + ast.StructInit, ast.ArrayInit { + c.g.expr(node) + } ast.IndexExpr {} // TODO ast.PrefixExpr { if node.op != .mul { @@ -2825,6 +2831,58 @@ fn (mut c Amd64) prefix_expr(node ast.PrefixExpr) { } } +fn (mut c Amd64) fp_infix_expr(node ast.InfixExpr, left_type ast.Type) { + // optimize for ast.Ident + match node.left { + ast.Ident { + c.mov_ssereg(.xmm1, .xmm0) + c.mov_var_to_ssereg(.xmm0, node.left as ast.Ident) + } + else { + c.push_sse(.xmm0) + c.g.expr(node.left) + c.pop_sse(.xmm1) + } + } + match node.op { + .eq, .ne { + c.g.write32(0xc1c20ff3) + c.g.write8(if node.op == .eq { 0x00 } else { 0x04 }) + inst := if node.op == .eq { 'cmpeqss' } else { 'cmpneqss' } + c.g.println('${inst} xmm0, xmm1') + c.mov_ssereg_to_reg(.rax, .xmm0, ast.f32_type_idx) + c.g.write([u8(0x83), 0xe0, 0x01]) + c.g.println('and eax, 0x1') + } + .gt, .lt, .ge, .le { + c.cmp_sse(.xmm0, .xmm1, left_type) + // TODO mov_extend_reg + c.mov64(Amd64Register.rax, 0) + c.cset(match node.op { + .gt { .a } + .lt { .b } + .ge { .ae } + else { .be } + }) + } + .plus { + c.add_sse(.xmm0, .xmm1, left_type) + } + .minus { + c.sub_sse(.xmm0, .xmm1, left_type) + } + .mul { + c.mul_sse(.xmm0, .xmm1, left_type) + } + .div { + c.div_sse(.xmm0, .xmm1, left_type) + } + else { + c.g.n_error('`${node.op}` expression is not supported right now') + } + } +} + fn (mut c Amd64) infix_expr(node ast.InfixExpr) { if node.op in [.logical_or, .and] { c.g.expr(node.left) @@ -2838,163 +2896,115 @@ fn (mut c Amd64) infix_expr(node ast.InfixExpr) { c.g.expr(node.right) c.g.labels.addrs[label] = c.g.pos() return - } else { - c.g.expr(node.right) - if node.left_type.is_pure_float() { - typ := node.left_type - // optimize for ast.Ident - match node.left { - ast.Ident { - c.mov_ssereg(.xmm1, .xmm0) - c.mov_var_to_ssereg(.xmm0, node.left as ast.Ident) - } - else { - c.push_sse(.xmm0) - c.g.expr(node.left) - c.pop_sse(.xmm1) - } - } - match node.op { - .eq, .ne { - c.g.write32(0xc1c20ff3) - c.g.write8(if node.op == .eq { 0x00 } else { 0x04 }) - inst := if node.op == .eq { 'cmpeqss' } else { 'cmpneqss' } - c.g.println('${inst} xmm0, xmm1') - c.mov_ssereg_to_reg(.rax, .xmm0, ast.f32_type_idx) - c.g.write([u8(0x83), 0xe0, 0x01]) - c.g.println('and eax, 0x1') - } - .gt, .lt, .ge, .le { - c.cmp_sse(.xmm0, .xmm1, typ) - // TODO mov_extend_reg - c.mov64(Amd64Register.rax, 0) - c.cset(match node.op { - .gt { .a } - .lt { .b } - .ge { .ae } - else { .be } - }) - } - .plus { - c.add_sse(.xmm0, .xmm1, typ) - } - .minus { - c.sub_sse(.xmm0, .xmm1, typ) - } - .mul { - c.mul_sse(.xmm0, .xmm1, typ) - } - .div { - c.div_sse(.xmm0, .xmm1, typ) - } - else { - c.g.n_error('`${node.op}` expression is not supported right now') - } - } - return + } + + c.g.expr(node.right) + + left_type := c.g.unwrap(node.left_type) + + if left_type.is_pure_float() { + c.fp_infix_expr(node, left_type) + return + } + + // optimize for ast.Ident + match node.left { + ast.Ident { + c.mov_reg(match node.op { + .left_shift, .right_shift, .unsigned_right_shift, .div, .mod { Amd64Register.rcx } + else { Amd64Register.rdx } + }, Amd64Register.rax) + c.mov_var_to_reg(Amd64Register.rax, node.left as ast.Ident) } - // optimize for ast.Ident - match node.left { - ast.Ident { - c.mov_reg(match node.op { - .left_shift, .right_shift, .unsigned_right_shift, .div, .mod { Amd64Register.rcx } - else { Amd64Register.rdx } - }, Amd64Register.rax) - c.mov_var_to_reg(Amd64Register.rax, node.left as ast.Ident) - } - else { - c.push(Amd64Register.rax) - c.g.expr(node.left) - c.pop(match node.op { - .left_shift, .right_shift, .unsigned_right_shift, .div, .mod { .rcx } - else { .rdx } - }) + else { + c.push(Amd64Register.rax) + c.g.expr(node.left) + c.pop(match node.op { + .left_shift, .right_shift, .unsigned_right_shift, .div, .mod { .rcx } + else { .rdx } + }) + } + } + + if left_type !in ast.integer_type_idxs && left_type != ast.bool_type_idx + && c.g.table.sym(left_type).info !is ast.Enum && !left_type.is_any_kind_of_pointer() + && node.left_type.is_any_kind_of_pointer() { + c.g.n_error('unsupported type for `${node.op}`: ${left_type}') + } + + // left: rax, right: rdx + match node.op { + .eq, .ne, .gt, .lt, .ge, .le { + c.cmp_reg(.rax, .rdx) + // TODO mov_extend_reg + c.mov64(Amd64Register.rax, 0) + c.cset_op(node.op) + } + .plus { + c.add_reg(.rax, .rdx) + } + .minus { + c.sub_reg(.rax, .rdx) + } + .mul { + c.g.write32(0xc2af0f48) + c.g.println('imul rax, rdx') + } + .div { + if left_type in ast.unsigned_integer_type_idxs { + c.g.write8(0xba) + c.g.write32(0) + c.g.println('mov edx, 0') + c.g.write([u8(0x48), 0xf7, 0xf1]) + c.g.println('div rcx') + } else { + c.g.write16(0x9948) + c.g.println('cqo') + c.g.write([u8(0x48), 0xf7, 0xf9]) + c.g.println('idiv rcx') } } - if node.left_type !in ast.integer_type_idxs && node.left_type != ast.bool_type_idx - && c.g.table.sym(node.left_type).info !is ast.Enum && !node.left_type.is_ptr() - && !node.left_type.is_voidptr() { - c.g.n_error('unsupported type for `${node.op}`: ${node.left_type}') + .mod { + if left_type in ast.unsigned_integer_type_idxs { + c.g.write8(0xba) + c.g.write32(0) + c.g.println('mov edx, 0') + c.g.write([u8(0x48), 0xf7, 0xf1]) + c.g.println('div rcx') + } else { + c.g.write16(0x9948) + c.g.println('cqo') + c.g.write([u8(0x48), 0xf7, 0xf9]) + c.g.println('idiv rcx') + } + c.mov_reg(Amd64Register.rax, Amd64Register.rdx) } - // left: rax, right: rdx - match node.op { - .eq, .ne, .gt, .lt, .ge, .le { - c.cmp_reg(.rax, .rdx) - // TODO mov_extend_reg - c.mov64(Amd64Register.rax, 0) - c.cset_op(node.op) - } - .plus { - c.add_reg(.rax, .rdx) - } - .minus { - c.sub_reg(.rax, .rdx) - } - .mul { - c.g.write32(0xc2af0f48) - c.g.println('imul rax, rdx') - } - .div { - if node.left_type in ast.unsigned_integer_type_idxs { - c.g.write8(0xba) - c.g.write32(0) - c.g.println('mov edx, 0') - c.g.write([u8(0x48), 0xf7, 0xf1]) - c.g.println('div rcx') - } else { - c.g.write16(0x9948) - c.g.println('cqo') - c.g.write([u8(0x48), 0xf7, 0xf9]) - c.g.println('idiv rcx') - } - } - .mod { - if node.left_type in ast.unsigned_integer_type_idxs { - c.g.write8(0xba) - c.g.write32(0) - c.g.println('mov edx, 0') - c.g.write([u8(0x48), 0xf7, 0xf1]) - c.g.println('div rcx') - } else { - c.g.write16(0x9948) - c.g.println('cqo') - c.g.write([u8(0x48), 0xf7, 0xf9]) - c.g.println('idiv rcx') - } - c.mov_reg(Amd64Register.rax, Amd64Register.rdx) - } - .amp { - c.bitand_reg(.rax, .rdx) - } - .pipe { - c.bitor_reg(.rax, .rdx) - } - .xor { - c.bitxor_reg(.rax, .rdx) - } - .left_shift { - c.shl_reg(.rax, .rcx) - } - .right_shift { - c.sar_reg(.rax, .rcx) - } - .unsigned_right_shift { - c.shr_reg(.rax, .rcx) - } - else { - c.g.n_error('`${node.op}` expression is not supported right now') - } + .amp { + c.bitand_reg(.rax, .rdx) + } + .pipe { + c.bitor_reg(.rax, .rdx) + } + .xor { + c.bitxor_reg(.rax, .rdx) + } + .left_shift { + c.shl_reg(.rax, .rcx) + } + .right_shift { + c.sar_reg(.rax, .rcx) + } + .unsigned_right_shift { + c.shr_reg(.rax, .rcx) + } + else { + c.g.n_error('`${node.op}` expression is not supported right now') } } } fn (mut c Amd64) trap() { - // funnily works on x86 and arm64 - if c.g.pref.arch == .arm64 { - c.g.write32(0xcccccccc) - } else { - c.g.write8(0xcc) - } + c.g.write8(0xcc) c.g.println('trap') } @@ -3993,6 +4003,7 @@ fn (mut c Amd64) push_sse(reg Amd64SSERegister) { c.g.println('movsd [rsp], ${reg}') c.is_16bit_aligned = !c.is_16bit_aligned c.g.println('; push ${reg}') + c.g.stack_depth++ } fn (mut c Amd64) pop_sse(reg Amd64SSERegister) { @@ -4008,6 +4019,7 @@ fn (mut c Amd64) pop_sse(reg Amd64SSERegister) { c.g.println('add rsp, 0x8') c.is_16bit_aligned = !c.is_16bit_aligned c.g.println('; pop ${reg}') + c.g.stack_depth-- } fn (mut c Amd64) gen_cast_expr(expr ast.CastExpr) { diff --git a/vlib/v/gen/native/arm64.v b/vlib/v/gen/native/arm64.v index c0043ca738..a761dfe883 100644 --- a/vlib/v/gen/native/arm64.v +++ b/vlib/v/gen/native/arm64.v @@ -385,7 +385,8 @@ fn (mut c Arm64) apicall(call ApiCall) { } fn (mut c Arm64) trap() { - panic('Arm64.trap() not implemented') + c.g.write32(0xcccccccc) + c.g.println('trap') } fn (mut c Arm64) leave() { diff --git a/vlib/v/gen/native/expr.v b/vlib/v/gen/native/expr.v index 1d38021170..f9b4dc5ca2 100644 --- a/vlib/v/gen/native/expr.v +++ b/vlib/v/gen/native/expr.v @@ -4,6 +4,7 @@ module native import v.ast +import v.util fn (mut g Gen) expr(node ast.Expr) { match node { @@ -16,23 +17,24 @@ fn (mut g Gen) expr(node ast.Expr) { g.code_gen.lea_var_to_reg(g.code_gen.main_reg(), pos) } ast.BoolLiteral { - g.code_gen.mov64(g.code_gen.main_reg(), if node.val { - 1 - } else { - 0 - }) + g.code_gen.mov64(g.code_gen.main_reg(), int(node.val)) } ast.CallExpr { - if node.name == 'C.syscall' { - g.code_gen.gen_syscall(node) - } else if node.name == 'exit' { - g.code_gen.gen_exit(node.args[0].expr) - } else if node.name in ['println', 'print', 'eprintln', 'eprint'] { - expr := node.args[0].expr - typ := node.args[0].typ - g.gen_print_from_expr(expr, typ, node.name) - } else { - g.code_gen.call_fn(node) + match node.name { + 'C.syscall' { + g.code_gen.gen_syscall(node) + } + 'exit' { + g.code_gen.gen_exit(node.args[0].expr) + } + 'println', 'print', 'eprintln', 'eprint' { + expr := node.args[0].expr + typ := node.args[0].typ + g.gen_print_from_expr(expr, typ, node.name) + } + else { + g.code_gen.call_fn(node) + } } } ast.FloatLiteral { @@ -41,29 +43,9 @@ fn (mut g Gen) expr(node ast.Expr) { } ast.Ident { var := g.get_var_from_ident(node) - // XXX this is intel specific match var { LocalVar { - if g.is_register_type(var.typ) { - g.code_gen.mov_var_to_reg(g.code_gen.main_reg(), node as ast.Ident) - } else if var.typ.is_pure_float() { - g.code_gen.load_fp_var(node as ast.Ident) - } else { - ts := g.table.sym(g.unwrap(var.typ)) - match ts.info { - ast.Struct { - g.code_gen.lea_var_to_reg(g.code_gen.main_reg(), g.get_var_offset(node.name)) - } - ast.Enum { - g.code_gen.mov_var_to_reg(g.code_gen.main_reg(), node as ast.Ident, - typ: ast.int_type_idx - ) - } - else { - g.n_error('Unsupported variable type') - } - } - } + g.local_var_ident(node, var) } else { g.n_error('Unsupported variable kind') @@ -131,12 +113,38 @@ fn (mut g Gen) expr(node ast.Expr) { ast.ConcatExpr { g.code_gen.gen_concat_expr(node) } + ast.TypeOf { + g.gen_typeof_expr(node, false) + } else { g.n_error('expr: unhandled node type: ${node.type_name()}') } } } +fn (mut g Gen) local_var_ident(ident ast.Ident, var LocalVar) { + if g.is_register_type(var.typ) { + g.code_gen.mov_var_to_reg(g.code_gen.main_reg(), ident) + } else if g.is_fp_type(var.typ) { + g.code_gen.load_fp_var(ident) + } else { + ts := g.table.sym(g.unwrap(var.typ)) + match ts.info { + ast.Struct { + g.code_gen.lea_var_to_reg(g.code_gen.main_reg(), g.get_var_offset(ident.name)) + } + ast.Enum { + g.code_gen.mov_var_to_reg(g.code_gen.main_reg(), ident, + typ: ast.int_type_idx + ) + } + else { + g.n_error('Unsupported variable type') + } + } + } +} + fn (mut g Gen) condition(expr ast.Expr, neg bool) int { g.expr(expr) g.code_gen.cmp_zero(g.code_gen.main_reg()) @@ -213,10 +221,66 @@ fn (mut g Gen) postfix_expr(node ast.PostfixExpr) { } } -fn (mut g Gen) gen_typeof_expr(it ast.TypeOf, newline bool) { +fn (mut g Gen) fn_decl_str(info ast.FnType) string { + mut fn_str := 'fn (' + for i, arg in info.func.params { + if arg.is_mut { + fn_str += 'mut ' + } + if i > 0 { + fn_str += ', ' + } + fn_str += util.strip_main_name(g.table.get_type_name(arg.typ)) + } + fn_str += ')' + if info.func.return_type == ast.ovoid_type { + fn_str += ' ?' + } else if info.func.return_type == ast.rvoid_type { + fn_str += ' !' + } else if info.func.return_type != ast.void_type { + x := util.strip_main_name(g.table.get_type_name(info.func.return_type)) + if info.func.return_type.has_flag(.option) { + fn_str += ' ?${x}' + } else if info.func.return_type.has_flag(.result) { + fn_str += ' !${x}' + } else { + fn_str += ' ${x}' + } + } + return fn_str +} + +fn (mut g Gen) gen_typeof_expr(node ast.TypeOf, newline bool) { nl := if newline { '\n' } else { '' } - r := g.typ(it.typ).name - g.code_gen.learel(g.code_gen.main_reg(), g.allocate_string('${r}${nl}', 3, .rel32)) + ts := g.table.sym(node.typ) + mut str := '' + + match ts.kind { + .sum_type { + g.n_error('`typeof()` is not implemented for sum types yet') + } + .array_fixed { + fixed_info := ts.info as ast.ArrayFixed + typ_name := g.table.get_type_name(fixed_info.elem_type) + str = '[${fixed_info.size}]${util.strip_main_name(typ_name)}' + } + .function { + func_info := ts.info as ast.FnType + if node.typ.is_ptr() { + str = '&' + } + str += g.fn_decl_str(func_info) + } + else { + str = util.strip_main_name(if node.typ.has_flag(.variadic) { + g.table.sym(g.table.value_type(node.typ)).name + } else { + g.table.type_to_str(node.typ) + }) + } + } + + g.code_gen.learel(g.code_gen.main_reg(), g.allocate_string('${str}${nl}', 3, .rel32)) } fn (mut g Gen) gen_print_from_expr(expr ast.Expr, typ ast.Type, name string) { diff --git a/vlib/v/gen/native/gen.v b/vlib/v/gen/native/gen.v index 998d750cf5..9877786a63 100644 --- a/vlib/v/gen/native/gen.v +++ b/vlib/v/gen/native/gen.v @@ -41,6 +41,7 @@ mut: var_offset map[string]int // local var stack offset var_alloc_size map[string]int // local var allocation size stack_var_pos int + stack_depth int debug_pos int errors []errors.Error warnings []errors.Warning @@ -230,6 +231,11 @@ union F64I64 { i i64 } +[inline] +fn byt(n int, s int) u8 { + return u8((n >> (s * 8)) & 0xff) +} + fn (mut g Gen) get_var_from_ident(ident ast.Ident) IdentVar { mut obj := ident.obj if obj !in [ast.Var, ast.ConstField, ast.GlobalField, ast.AsmRegister] { @@ -735,9 +741,15 @@ fn (mut g Gen) get_multi_return(types []ast.Type) MultiReturn { return ret } -fn (g Gen) is_register_type(typ ast.Type) bool { - return typ.is_pure_int() || typ == ast.char_type_idx || typ.is_any_kind_of_pointer() - || typ.is_bool() +fn (mut g Gen) is_register_type(typ ast.Type) bool { + return typ.is_pure_int() || typ == ast.char_type_idx + || typ.is_any_kind_of_pointer() || typ.is_bool() + || (g.table.sym(typ).info is ast.Alias && g.is_register_type(g.unwrap(typ))) +} + +fn (mut g Gen) is_fp_type(typ ast.Type) bool { + return typ.is_pure_float() + || (g.table.sym(typ).info is ast.Alias && g.is_fp_type(g.unwrap(typ))) } fn (mut g Gen) get_sizeof_ident(ident ast.Ident) int { @@ -981,12 +993,17 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) { } g.stack_var_pos = 0 + g.stack_depth = 0 g.register_function_address(name) g.labels = &LabelTable{} g.defer_stmts.clear() g.return_type = node.return_type g.code_gen.fn_decl(node) g.patch_labels() + + if g.stack_depth != 0 { + g.println('^^^ stack_depth != 0 (${g.stack_depth}) !!!') + } } pub fn (mut g Gen) register_function_address(name string) { diff --git a/vlib/v/gen/native/tests/assign.vv b/vlib/v/gen/native/tests/assign.vv index 1946070ad2..2fe65b057f 100644 --- a/vlib/v/gen/native/tests/assign.vv +++ b/vlib/v/gen/native/tests/assign.vv @@ -1,6 +1,8 @@ fn main() { test_int() test_fp() + test_unsafe() + test_alias(100, 9) } fn test_int() { @@ -25,4 +27,21 @@ fn test_fp() { b /= 2 println(int(b)) +} + +fn test_unsafe() { + a := 10 + + unsafe { + b := 4 + println(a + b) + } +} + +type Integer = int + +fn test_alias(a Integer, b Integer) { + e := a + b + assert e == a + b + println(e) } \ No newline at end of file diff --git a/vlib/v/gen/native/tests/assign.vv.out b/vlib/v/gen/native/tests/assign.vv.out index 79756e9f13..20e53381b5 100644 --- a/vlib/v/gen/native/tests/assign.vv.out +++ b/vlib/v/gen/native/tests/assign.vv.out @@ -1,2 +1,4 @@ 246 -3 \ No newline at end of file +3 +14 +109 diff --git a/vlib/v/gen/native/tests/struct.vv b/vlib/v/gen/native/tests/struct.vv index 4df4b74f33..839dea5f95 100644 --- a/vlib/v/gen/native/tests/struct.vv +++ b/vlib/v/gen/native/tests/struct.vv @@ -56,6 +56,9 @@ fn struct_test() { mut f := &e f.a = 3 assert e.a == 3 + + g := &Mutable{2} + assert g.a == 2 } type AliasedStruct = Mutable diff --git a/vlib/v/gen/native/tests/typeof.vv b/vlib/v/gen/native/tests/typeof.vv index 5d99730e46..075abe8d0a 100644 --- a/vlib/v/gen/native/tests/typeof.vv +++ b/vlib/v/gen/native/tests/typeof.vv @@ -1,16 +1,86 @@ +type IntegerAlias = int +struct Test { + a int = 0 + b voidptr = voidptr(0) + c &Test = unsafe { 0 } + d map[int][3]string = {} +} fn main() { + // strings a := 'string' t := typeof(a) println(t) t2 := typeof('another string') println(t2) + + // integers n := 123 t3 := typeof(n) println(t3) t4 := typeof(123) println(t4) -// id := 'hello world' -// println(id) + test_alias(0) + + // pointers + t5 := typeof(voidptr(0)) + println(t5) + t6 := typeof(charptr(0)) + println(t6) + t7 := typeof(&u8(3)) + println(t7) + + // functions + t8 := typeof(main) + println(t8) + t9 := typeof(test_alias) + println(t9) + t10 := typeof(return_func) + println(t10) + + // arrays + t11 := typeof([]int{}) + println(t11) + t12 := typeof([16]int{}) + println(t12) + + // maps + t13 := typeof(map[int]string) + println(t13) + t14 := typeof(map[int][2]int) + println(t14) + + // options, results + t15 := typeof(result_func) + println(t15) + t16 := typeof(result_func()) + println(t16) + t17 := typeof(opt_func) + println(t17) + t18 := typeof(opt_func()) + println(t18) + + // structs + t19 := typeof(Test{}) + println(t19) + t20 := typeof(Test{}.d) + println(t20) } + +fn test_alias(t IntegerAlias) { + t1 := typeof(t) + println(t1) +} + +fn return_func(foo int, bar []int, baz voidptr) string { + return '' +} + +fn result_func() !int { + return 0 +} + +fn opt_func() ?int { + return 0 +} \ No newline at end of file diff --git a/vlib/v/gen/native/tests/typeof.vv.out b/vlib/v/gen/native/tests/typeof.vv.out index 0fc858b170..4283c30d09 100644 --- a/vlib/v/gen/native/tests/typeof.vv.out +++ b/vlib/v/gen/native/tests/typeof.vv.out @@ -2,3 +2,20 @@ string string int int literal +IntegerAlias +voidptr +charptr +&u8 +fn () +fn (IntegerAlias) +fn (int, []int, voidptr) string +[]int +[16]int +map[int]string +map[int][2]int +fn () !int +!int +fn () ?int +?int +Test +map[int][3]string