v / vlib / v2 / ssa / build_assert_from_flat_test.v
94 lines · 88 sloc · 2.88 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 s181: `build_assert_from_flat` (sixth per-kind port
7// inside the s175 seam) must emit the same SSA `.br` + assert_fail
8// (call exit(1) + .unreachable) shape as the legacy `build_assert`. The
9// flat path decodes only the assert condition (edge 0) — the AssertStmt
10// struct itself is never rehydrated, and the optional `extra` message
11// (edge 1) is ignored on both paths since the legacy build_assert only
12// reads stmt.expr.
13module ssa
14
15import v2.ast
16import v2.types
17
18// Fixture: a fn `do_assert` containing `assert true`. The condition is a
19// BasicLiteral so build_expr stays trivial. The shape of the emitted SSA
20// (br + assert_pass + assert_fail + call exit(1) + unreachable) is what we
21// pin — both paths must produce the same blocks/instrs/values counts.
22fn make_assert_fixture() []ast.File {
23 return [
24 ast.File{
25 name: 'main.v'
26 mod: 'main'
27 stmts: [
28 ast.Stmt(ast.ModuleStmt{
29 name: 'main'
30 }),
31 ast.Stmt(ast.FnDecl{
32 name: 'do_assert'
33 typ: ast.FnType{}
34 stmts: [
35 ast.Stmt(ast.AssertStmt{
36 expr: ast.Expr(ast.BasicLiteral{
37 kind: .key_true
38 value: 'true'
39 })
40 }),
41 ]
42 }),
43 ]
44 },
45 ]
46}
47
48fn build_via_legacy_assert(files []ast.File, env &types.Environment, name string) &Module {
49 mut mod := Module.new(name)
50 mut b := Builder.new_with_env(mod, env)
51 b.register_fn_signatures(files[0])
52 b.build_fn_bodies(files[0])
53 return mod
54}
55
56fn build_via_flat_assert(files []ast.File, env &types.Environment, name string) &Module {
57 flat := ast.flatten_files(files)
58 mut mod := Module.new(name)
59 mut b := Builder.new_with_env(mod, env)
60 b.register_fn_signatures_from_flat(flat.file_cursor(0))
61 stmts := flat.file_cursor(0).stmts()
62 for si in 0 .. stmts.len() {
63 c := stmts.at(si)
64 if c.kind() != .stmt_fn_decl {
65 continue
66 }
67 decl := c.fn_decl_signature()
68 fn_name := b.mangle_fn_name(decl)
69 func_idx := b.fn_index[fn_name] or { continue }
70 b.cur_func = func_idx
71 b.label_blocks = map[string]BlockID{}
72 entry := mod.add_block(func_idx, 'entry')
73 b.cur_block = entry
74 body := c.list_at(3)
75 b.build_stmts_from_flat(body)
76 if !b.block_has_terminator(b.cur_block) {
77 mod.add_instr(.ret, b.cur_block, 0, []ValueID{})
78 }
79 }
80 return mod
81}
82
83fn test_build_assert_from_flat_matches_legacy() {
84 files := make_assert_fixture()
85 env := types.Environment.new()
86 mod_legacy := build_via_legacy_assert(files, env, 'assert_legacy')
87 mod_flat := build_via_flat_assert(files, env, 'assert_flat')
88
89 assert mod_legacy.funcs.len == mod_flat.funcs.len
90 assert mod_legacy.funcs.len == 1
91 assert mod_legacy.blocks.len == mod_flat.blocks.len
92 assert mod_legacy.instrs.len == mod_flat.instrs.len
93 assert mod_legacy.values.len == mod_flat.values.len
94}
95