1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//! Phase 0b — `mem` family seam: `Op::LoadFieldAtAbsolute` lowering.
//!
//! `LoadFieldAtAbsolute { offset, ty }` is the dynamic-base sibling of
//! `LoadField`: it pops an i32 arena-relative address off the operand
//! stack and loads the field at `offset` of type `ty` from
//! `arena_base + addr + offset`. It is emitted by the IR lowering for
//! schema field access — both `self.field` inside a schema method body
//! and chained `obj.sub.leaf` paths in the entry body.
//!
//! ## Why there is no three-way (cranelift / tree-walker) differential
//! here
//!
//! The task brief called for a cranelift-gold-standard differential.
//! That is not achievable for this op:
//!
//! * **Cranelift** does NOT implement `LoadFieldAtAbsolute` either —
//! `relon-codegen-cranelift::codegen::op_visitor::visit_load_field_at_absolute`
//! returns `unsupported("LoadFieldAtAbsolute")`. So cranelift cannot
//! serve as an oracle; feeding it a fixture that uses the op errors
//! out before producing any result to compare against.
//!
//! * Every *source-level* path that emits `LoadFieldAtAbsolute` first
//! lifts the schema-typed receiver to an absolute address with
//! `Op::LoadSchemaPtr` (for an entry-body `o.inner.v`) or routes the
//! receiver through a method call (`m.method()`), which itself begins
//! with `LoadSchemaPtr`. `LoadSchemaPtr` lives in the LLVM backend's
//! `schema` family seam (`codegen/schema.rs::lower_schema_rest`) and
//! is still unimplemented. Phase 0b's hard constraint forbids this
//! lane from touching any family other than `mem`, so the schema
//! prerequisite cannot be supplied here.
//!
//! * The LLVM `codegen` module is private and there is no public
//! hand-built-buffer-protocol-IR constructor (`from_ir_direct`
//! rejects buffer-protocol IR; only `from_source` builds it, and that
//! goes through the frontend which inserts the `LoadSchemaPtr`
//! prerequisite). So the op cannot be exercised in isolation through
//! the public surface.
//!
//! What this test pins is the **full end-to-end path**: with the
//! `schema` family (`LoadSchemaPtr`) and the `mem` family
//! (`LoadFieldAtAbsolute`) both landed, *and* the Phase 0b host-side
//! Schema-typed `#main` arg marshaller wired into
//! `evaluator.rs::write_value_into_builder` (recursive `sub_record` /
//! `finish_sub_record`), the nested-field program both compiles and
//! runs. `#main(Outer o) -> Int : o.inner.v` with `o.inner.v == 42`
//! returns `Value::Int(42)`, matching the tree-walk gold standard.
use HashMap;
use LlvmAotEvaluator;
use ;
/// Source whose `#main` body reads a nested schema field
/// (`o.inner.v`). The IR lowering emits `LoadSchemaPtr { offset: 0 }`
/// (lift `o` to its absolute address) followed by
/// `LoadFieldAtAbsolute { offset: 0, ty: I64 }` (read `.v`).
const NESTED_FIELD_SRC: &str = "\
#schema Inner { Int v: * }
#schema Outer { Inner inner: * }
#main(Outer o) -> Int
o.inner.v";
/// End-to-end value assertion for the nested-schema-field path.
///
/// With `schema` (`LoadSchemaPtr`), `mem` (`LoadFieldAtAbsolute`), and
/// the Phase 0b host-side Schema-typed `#main` arg marshaller all wired,
/// `#main(Outer o) -> Int : o.inner.v` runs end to end. The host packs
/// the nested `Outer { inner: Inner { v: 42 } }` into the input buffer
/// (recursive `sub_record` / `finish_sub_record`), `LoadSchemaPtr` lifts
/// `o` to its absolute address, and `LoadFieldAtAbsolute` reads through
/// to `.inner.v`. The result must equal the tree-walk gold standard,
/// `Value::Int(42)`.