Skip to content

Commit ff3f918

Browse files
committed
Read bytecodes from Lean in Rust
1 parent 1dbc6e5 commit ff3f918

File tree

6 files changed

+224
-21
lines changed

6 files changed

+224
-21
lines changed

Ix/Aiur2/Bytecode.lean

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,42 @@ namespace Aiur
22

33
abbrev G := Fin 0xFFFFFFFF00000001
44

5+
namespace Bytecode
6+
7+
abbrev FunIdx := Nat
8+
abbrev ValIdx := Nat
9+
abbrev SelIdx := Nat
10+
11+
inductive Op
12+
| const : G → Op
13+
| add : ValIdx → ValIdx → Op
14+
| sub : ValIdx → ValIdx → Op
15+
| mul : ValIdx → ValIdx → Op
16+
| call : FunIdx → Array ValIdx → Op
17+
| store : Array ValIdx → Op
18+
| load : (width : Nat) → ValIdx → Op
19+
20+
mutual
21+
inductive Ctrl where
22+
| match : ValIdx → Array (G × Block) → Option Block → Ctrl
23+
| return : SelIdx → Array ValIdx → Ctrl
24+
25+
structure Block where
26+
ops : Array Op
27+
ctrl : Ctrl
28+
minSelIncluded: SelIdx
29+
maxSelExcluded: SelIdx
30+
end
31+
32+
structure Function where
33+
inputSize : Nat
34+
outputSize : Nat
35+
body : Block
36+
37+
structure Toplevel where
38+
functions : Array Function
39+
memoryWidths : Array Nat
40+
41+
end Bytecode
42+
543
end Aiur

src/aiur2/bytecode.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,29 @@ use p3_goldilocks::Goldilocks as G;
66
use rustc_hash::FxBuildHasher;
77

88
pub struct Toplevel {
9-
pub(super) functions: Vec<Function>,
10-
pub(super) memory_widths: Vec<usize>,
9+
pub(crate) functions: Vec<Function>,
10+
pub(crate) memory_widths: Vec<usize>,
1111
}
1212

1313
pub struct Function {
14-
input_size: usize,
15-
output_size: usize,
16-
pub(super) body: Block,
14+
pub(crate) input_size: usize,
15+
pub(crate) output_size: usize,
16+
pub(crate) body: Block,
1717
}
1818

1919
pub type FxIndexMap<K, V> = IndexMap<K, V, FxBuildHasher>;
2020

2121
pub struct Block {
22-
pub(super) ops: Vec<Op>,
23-
pub(super) ctrl: Ctrl,
24-
sel_range: SelRange,
22+
pub(crate) ops: Vec<Op>,
23+
pub(crate) ctrl: Ctrl,
24+
pub(crate) min_sel_included: SelIdx,
25+
pub(crate) max_sel_excluded: SelIdx,
2526
}
2627

2728
pub enum Op {
2829
Const(G),
2930
Add(ValIdx, ValIdx),
31+
Sub(ValIdx, ValIdx),
3032
Mul(ValIdx, ValIdx),
3133
Call(FunIdx, Vec<ValIdx>),
3234
Store(Vec<ValIdx>),
@@ -38,13 +40,8 @@ pub enum Ctrl {
3840
Return(SelIdx, Vec<ValIdx>),
3941
}
4042

41-
pub struct SelRange {
42-
min_included: SelIdx,
43-
max_excluded: SelIdx,
44-
}
45-
4643
#[derive(Clone, Copy)]
47-
pub struct SelIdx(usize);
44+
pub struct SelIdx(pub(crate) usize);
4845

4946
impl SelIdx {
5047
#[inline]
@@ -54,7 +51,7 @@ impl SelIdx {
5451
}
5552

5653
#[derive(Clone, Copy)]
57-
pub struct ValIdx(usize);
54+
pub struct ValIdx(pub(crate) usize);
5855

5956
impl ValIdx {
6057
#[inline]
@@ -64,7 +61,7 @@ impl ValIdx {
6461
}
6562

6663
#[derive(Clone, Copy)]
67-
pub struct FunIdx(usize);
64+
pub struct FunIdx(pub(crate) usize);
6865

6966
impl FunIdx {
7067
#[inline]

src/aiur2/execute.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::aiur2::bytecode::{Ctrl, FunIdx, Function, FxIndexMap, Op, Toplevel};
55

66
pub struct QueryResult {
77
output: Vec<G>,
8-
multiplicity: usize,
8+
multiplicity: G,
99
}
1010

1111
pub type QueryMap = FxIndexMap<Vec<G>, QueryResult>;
@@ -78,6 +78,11 @@ impl Function {
7878
let b = map[b.to_usize()];
7979
map.push(a + b);
8080
}
81+
ExecEntry::Op(Op::Sub(a, b)) => {
82+
let a = map[a.to_usize()];
83+
let b = map[b.to_usize()];
84+
map.push(a - b);
85+
}
8186
ExecEntry::Op(Op::Mul(a, b)) => {
8287
let a = map[a.to_usize()];
8388
let b = map[b.to_usize()];
@@ -88,7 +93,7 @@ impl Function {
8893
if let Some(result) =
8994
record.function_queries[callee_idx.to_usize()].get_mut(&args)
9095
{
91-
result.multiplicity += 1;
96+
result.multiplicity += G::ONE;
9297
map.extend(result.output.clone());
9398
} else {
9499
let saved_map = std::mem::replace(&mut map, args);
@@ -111,13 +116,13 @@ impl Function {
111116
.get_mut(&width)
112117
.expect("Invalid memory width");
113118
if let Some(result) = memory_queries.get_mut(&values) {
114-
result.multiplicity += 1;
119+
result.multiplicity += G::ONE;
115120
map.extend(&result.output);
116121
} else {
117122
let ptr = G::ZERO;
118123
let result = QueryResult {
119124
output: vec![ptr],
120-
multiplicity: 1,
125+
multiplicity: G::ONE,
121126
};
122127
memory_queries.insert(values, result);
123128
map.push(ptr);
@@ -134,7 +139,7 @@ impl Function {
134139
let (args, result) = memory_queries
135140
.get_index_mut(ptr_usize)
136141
.expect("Unbound pointer");
137-
result.multiplicity += 1;
142+
result.multiplicity += G::ONE;
138143
map.extend(args);
139144
}
140145
ExecEntry::Ctrl(Ctrl::Match(val_idx, cases, default)) => {

src/lean/ffi/aiur2/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod toplevel;

src/lean/ffi/aiur2/toplevel.rs

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
// TODO: remove
2+
#![allow(dead_code)]
3+
4+
use p3_field::integers::QuotientMap;
5+
use p3_goldilocks::Goldilocks as G;
6+
use std::ffi::c_void;
7+
8+
use crate::{
9+
aiur2::bytecode::{Block, Ctrl, FunIdx, Function, FxIndexMap, Op, SelIdx, Toplevel, ValIdx},
10+
lean::{
11+
array::LeanArrayObject,
12+
ctor::LeanCtorObject,
13+
ffi::{as_ref_unsafe, lean_is_scalar},
14+
},
15+
lean_unbox,
16+
};
17+
18+
fn lean_unbox_nat_as_usize(ptr: *const c_void) -> usize {
19+
assert!(lean_is_scalar(ptr));
20+
lean_unbox!(usize, ptr)
21+
}
22+
23+
fn lean_unbox_nat_as_g(ptr: *const c_void) -> G {
24+
assert!(lean_is_scalar(ptr));
25+
unsafe { G::from_canonical_unchecked(lean_unbox!(u64, ptr)) }
26+
}
27+
28+
fn lean_ptr_to_vec_val_idx(ptr: *const c_void) -> Vec<ValIdx> {
29+
let array: &LeanArrayObject = as_ref_unsafe(ptr.cast());
30+
array.to_vec(|ptr| ValIdx(lean_unbox_nat_as_usize(ptr)))
31+
}
32+
33+
fn lean_ptr_to_op(ptr: *const c_void) -> Op {
34+
let ctor: &LeanCtorObject = as_ref_unsafe(ptr.cast());
35+
match ctor.tag() {
36+
0 => {
37+
let [const_val_ptr] = ctor.objs();
38+
Op::Const(lean_unbox_nat_as_g(const_val_ptr))
39+
}
40+
1 => {
41+
let [a_ptr, b_ptr] = ctor.objs();
42+
Op::Add(
43+
ValIdx(lean_unbox_nat_as_usize(a_ptr)),
44+
ValIdx(lean_unbox_nat_as_usize(b_ptr)),
45+
)
46+
}
47+
2 => {
48+
let [a_ptr, b_ptr] = ctor.objs();
49+
Op::Sub(
50+
ValIdx(lean_unbox_nat_as_usize(a_ptr)),
51+
ValIdx(lean_unbox_nat_as_usize(b_ptr)),
52+
)
53+
}
54+
3 => {
55+
let [a_ptr, b_ptr] = ctor.objs();
56+
Op::Mul(
57+
ValIdx(lean_unbox_nat_as_usize(a_ptr)),
58+
ValIdx(lean_unbox_nat_as_usize(b_ptr)),
59+
)
60+
}
61+
4 => {
62+
let [fun_idx_ptr, val_idxs_ptr] = ctor.objs();
63+
let fun_idx = FunIdx(lean_unbox_nat_as_usize(fun_idx_ptr));
64+
let val_idxs = lean_ptr_to_vec_val_idx(val_idxs_ptr);
65+
Op::Call(fun_idx, val_idxs)
66+
}
67+
5 => {
68+
let [val_idxs_ptr] = ctor.objs();
69+
Op::Store(lean_ptr_to_vec_val_idx(val_idxs_ptr))
70+
}
71+
6 => {
72+
let [width_ptr, val_idx_ptr] = ctor.objs();
73+
Op::Load(
74+
lean_unbox_nat_as_usize(width_ptr),
75+
ValIdx(lean_unbox_nat_as_usize(val_idx_ptr)),
76+
)
77+
}
78+
_ => unreachable!(),
79+
}
80+
}
81+
82+
fn lean_ptr_to_g_block_pair(ptr: *const c_void) -> (G, Block) {
83+
let ctor: &LeanCtorObject = as_ref_unsafe(ptr.cast());
84+
let [g_ptr, block_ptr] = ctor.objs();
85+
let g = lean_unbox_nat_as_g(g_ptr);
86+
let block = lean_ctor_to_block(as_ref_unsafe(block_ptr.cast()));
87+
(g, block)
88+
}
89+
90+
fn lean_ctor_to_ctrl(ctor: &LeanCtorObject) -> Ctrl {
91+
match ctor.tag() {
92+
0 => {
93+
let [val_idx_ptr, cases_ptr, default_ptr] = ctor.objs();
94+
let val_idx = ValIdx(lean_unbox_nat_as_usize(val_idx_ptr));
95+
let cases_array: &LeanArrayObject = as_ref_unsafe(cases_ptr.cast());
96+
let vec_cases = cases_array.to_vec(lean_ptr_to_g_block_pair);
97+
let cases = FxIndexMap::from_iter(vec_cases);
98+
let default = if lean_is_scalar(default_ptr) {
99+
None
100+
} else {
101+
let default_ctor: &LeanCtorObject = as_ref_unsafe(default_ptr.cast());
102+
let [block_ptr] = default_ctor.objs();
103+
let block = lean_ctor_to_block(as_ref_unsafe(block_ptr.cast()));
104+
Some(Box::new(block))
105+
};
106+
Ctrl::Match(val_idx, cases, default)
107+
}
108+
1 => {
109+
let [sel_idx_ptr, val_idxs_ptr] = ctor.objs();
110+
let sel_idx = SelIdx(lean_unbox_nat_as_usize(sel_idx_ptr));
111+
let val_idxs = lean_ptr_to_vec_val_idx(val_idxs_ptr);
112+
Ctrl::Return(sel_idx, val_idxs)
113+
}
114+
_ => unreachable!(),
115+
}
116+
}
117+
118+
fn lean_ctor_to_block(ctor: &LeanCtorObject) -> Block {
119+
let [
120+
ops_ptr,
121+
ctrl_ptr,
122+
min_sel_included_ptr,
123+
max_sel_excluded_ptr,
124+
] = ctor.objs();
125+
let ops_array: &LeanArrayObject = as_ref_unsafe(ops_ptr.cast());
126+
let ops = ops_array.to_vec(lean_ptr_to_op);
127+
let ctrl = lean_ctor_to_ctrl(as_ref_unsafe(ctrl_ptr.cast()));
128+
let min_sel_included = SelIdx(lean_unbox_nat_as_usize(min_sel_included_ptr));
129+
let max_sel_excluded = SelIdx(lean_unbox_nat_as_usize(max_sel_excluded_ptr));
130+
Block {
131+
ops,
132+
ctrl,
133+
min_sel_included,
134+
max_sel_excluded,
135+
}
136+
}
137+
138+
fn lean_ptr_to_function(ptr: *const c_void) -> Function {
139+
let ctor: &LeanCtorObject = as_ref_unsafe(ptr.cast());
140+
let [input_size_ptr, output_size_ptr, body_ptr] = ctor.objs();
141+
let input_size = lean_unbox_nat_as_usize(input_size_ptr);
142+
let output_size = lean_unbox_nat_as_usize(output_size_ptr);
143+
let body = lean_ctor_to_block(as_ref_unsafe(body_ptr.cast()));
144+
Function {
145+
input_size,
146+
output_size,
147+
body,
148+
}
149+
}
150+
151+
fn lean_ctor_to_toplevel(ctor: &LeanCtorObject) -> Toplevel {
152+
let [functions_ptr, memory_widths_ptr] = ctor.objs();
153+
let functions_array: &LeanArrayObject = as_ref_unsafe(functions_ptr.cast());
154+
let functions = functions_array.to_vec(lean_ptr_to_function);
155+
let memory_widths_array: &LeanArrayObject = as_ref_unsafe(memory_widths_ptr.cast());
156+
let memory_widths = memory_widths_array.to_vec(lean_unbox_nat_as_usize);
157+
Toplevel {
158+
functions,
159+
memory_widths,
160+
}
161+
}

src/lean/ffi/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub mod aiur2;
12
pub mod archon;
23
pub mod binius;
34
pub mod byte_array;

0 commit comments

Comments
 (0)