v / vlib / v2 / ssa / build_cast_from_flat_test.v
120 lines · 114 sloc · 3.54 KB · d358576851079d4716834cc86627307d28acd1ae
Raw
1// Copyright (c) 2026 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4// vtest build: macos
5//
6// Bit-equality pin for s192: `build_cast_from_flat` is the eighth per-kind
7// arm inside `build_expr_from_flat`. CastExpr flat encoding (flat.v:1876)
8// is (.expr_cast, pos, -1, -1, 0, 0, [edge0=typ, edge1=expr]). Both edges
9// need full `decode_expr` rehydration: `ast_type_to_ssa` pattern-matches on
10// type expr kinds, and `build_addr`/`build_expr` on the value side require
11// fully-rehydrated `ast.Expr` sum-types.
12module ssa
13
14import v2.ast
15import v2.types
16
17// Fixture: `fn cast() i64 { return i64(42) }`. CastExpr with
18// typ=Ident('i64'), expr=BasicLiteral('42'). Exercises the common
19// numeric-widening path through `build_cast_value_to_type`.
20fn make_cast_fixture() []ast.File {
21 return [
22 ast.File{
23 name: 'main.v'
24 mod: 'main'
25 stmts: [
26 ast.Stmt(ast.ModuleStmt{
27 name: 'main'
28 }),
29 ast.Stmt(ast.FnDecl{
30 name: 'cast64'
31 typ: ast.FnType{
32 return_type: ast.Expr(ast.Ident{
33 name: 'i64'
34 })
35 }
36 stmts: [
37 ast.Stmt(ast.ReturnStmt{
38 exprs: [
39 ast.Expr(ast.CastExpr{
40 typ: ast.Expr(ast.Ident{
41 name: 'i64'
42 })
43 expr: ast.Expr(ast.BasicLiteral{
44 kind: .number
45 value: '42'
46 })
47 }),
48 ]
49 }),
50 ]
51 }),
52 ]
53 },
54 ]
55}
56
57fn build_via_legacy_cast(files []ast.File, env &types.Environment, name string) &Module {
58 mut mod := Module.new(name)
59 mut b := Builder.new_with_env(mod, env)
60 b.register_fn_signatures(files[0])
61 b.build_fn_bodies(files[0])
62 return mod
63}
64
65fn build_via_flat_cast(files []ast.File, env &types.Environment, name string) &Module {
66 flat := ast.flatten_files(files)
67 mut mod := Module.new(name)
68 mut b := Builder.new_with_env(mod, env)
69 b.register_fn_signatures_from_flat(flat.file_cursor(0))
70 stmts := flat.file_cursor(0).stmts()
71 for si in 0 .. stmts.len() {
72 c := stmts.at(si)
73 if c.kind() != .stmt_fn_decl {
74 continue
75 }
76 decl := c.fn_decl_signature()
77 fn_name := b.mangle_fn_name(decl)
78 func_idx := b.fn_index[fn_name] or { continue }
79 b.cur_func = func_idx
80 b.label_blocks = map[string]BlockID{}
81 b.vars = map[string]ValueID{}
82 entry := mod.add_block(func_idx, 'entry')
83 b.cur_block = entry
84 for param in decl.typ.params {
85 param_type := b.ast_type_to_ssa(param.typ)
86 param_val := mod.add_value_node(.argument, param_type, param.name, 0)
87 mod.func_add_param(func_idx, param_val)
88 alloca := mod.add_instr(.alloca, entry, mod.type_store.get_ptr(param_type), []ValueID{})
89 mod.add_instr(.store, entry, 0, [param_val, alloca])
90 b.vars[param.name] = alloca
91 }
92 body := c.list_at(3)
93 for bi in 0 .. body.len() {
94 stmt_c := body.at(bi)
95 if stmt_c.kind() == .stmt_return {
96 ret_expr_c := stmt_c.edge(0)
97 val := b.build_expr_from_flat(ret_expr_c)
98 mod.add_instr(.ret, b.cur_block, 0, [val])
99 } else {
100 b.build_stmt_from_flat(stmt_c)
101 }
102 }
103 if !b.block_has_terminator(b.cur_block) {
104 mod.add_instr(.ret, b.cur_block, 0, []ValueID{})
105 }
106 }
107 return mod
108}
109
110fn test_build_cast_from_flat_i64_matches_legacy() {
111 files := make_cast_fixture()
112 env := types.Environment.new()
113 mod_legacy := build_via_legacy_cast(files, env, 'cast_legacy')
114 mod_flat := build_via_flat_cast(files, env, 'cast_flat')
115
116 assert mod_legacy.funcs.len == mod_flat.funcs.len
117 assert mod_legacy.blocks.len == mod_flat.blocks.len
118 assert mod_legacy.instrs.len == mod_flat.instrs.len
119 assert mod_legacy.values.len == mod_flat.values.len
120}
121