Skip to content

Commit 9164518

Browse files
committed
Fix bytecode immediates
1 parent 31f8104 commit 9164518

2 files changed

Lines changed: 67 additions & 10 deletions

File tree

fidget-bytecode/src/lib.rs

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,14 @@ impl Bytecode {
170170
&self.data
171171
}
172172

173-
/// Maximum register index used by the tape
173+
/// Number of registers (0-indexed) used by the tape
174174
///
175175
/// This does not include the virtual register `0xFF` used for immediates
176176
pub fn reg_count(&self) -> u8 {
177177
self.reg_count
178178
}
179179

180-
/// Maximum memory slot used for `Load` / `Store` operations
180+
/// Number of memory slots (0-indexed) used for `Load` / `Store` operations
181181
pub fn mem_count(&self) -> u32 {
182182
self.mem_count
183183
}
@@ -197,14 +197,15 @@ impl Bytecode {
197197
let mut data = vec![u32::MAX, 0u32];
198198
let mut reg_count = 0u8;
199199
let mut mem_count = 0u32;
200+
let mem_offset = u32::try_from(N).unwrap();
200201
for op in t.iter_asm() {
201202
let mut word = [0xFF; 4];
202203
let mut imm = None;
203204
let mut store_reg = |i, r| {
204205
if r == u8::MAX {
205206
Err(ReservedRegister)
206207
} else {
207-
reg_count = reg_count.max(r); // update the max reg
208+
reg_count = reg_count.max(r + 1);
208209
word[i] = r;
209210
Ok(())
210211
}
@@ -217,15 +218,15 @@ impl Bytecode {
217218

218219
RegOp::Load(reg, slot) => {
219220
store_reg(1, reg)?;
220-
store_reg(2, u8::MAX)?;
221-
mem_count = mem_count.max(slot);
222-
imm = Some(slot);
221+
word[2] = u8::MAX;
222+
mem_count = mem_count.max(slot + 1 - mem_offset);
223+
imm = Some(slot - mem_offset);
223224
}
224225
RegOp::Store(reg, slot) => {
225-
store_reg(1, u8::MAX)?;
226226
store_reg(2, reg)?;
227-
mem_count = mem_count.max(slot);
228-
imm = Some(slot);
227+
word[1] = u8::MAX;
228+
mem_count = mem_count.max(slot + 1 - mem_offset);
229+
imm = Some(slot - mem_offset);
229230
}
230231

231232
RegOp::CopyImm(out, imm_f32) => {
@@ -361,6 +362,7 @@ mod test {
361362

362363
#[test]
363364
fn load_store() {
365+
// Build a bytecode tape with only 2 registers to test load and store
364366
let mut ctx = fidget_core::Context::new();
365367
let x = ctx.x();
366368
let y = ctx.y();
@@ -369,13 +371,65 @@ mod test {
369371
let out = ctx.max(xy, z).unwrap();
370372
let data = VmData::<2>::new(&ctx, &[out]).unwrap();
371373
let bc = Bytecode::new(&data).unwrap();
374+
assert_eq!(bc.reg_count(), 2);
375+
assert_eq!(bc.mem_count(), 1);
372376
let mut iter = bc.data.iter();
373377
let mut next = || *iter.next().unwrap();
374378
assert_eq!(next(), 0xFFFFFFFF); // start marker
375379
assert_eq!(next(), 0);
380+
381+
// Input(1, Z)
382+
assert_eq!(
383+
next().to_le_bytes(),
384+
[BytecodeOp::Input as u8, 1, 0xFF, 0xFF]
385+
);
386+
assert_eq!(next(), 2); // Z
387+
388+
// Copy from reg[1] -> mem[0]
389+
assert_eq!(
390+
next().to_le_bytes(),
391+
[BytecodeOp::Mem as u8, 0xFF, 1, 0xFF]
392+
);
393+
assert_eq!(next(), 0);
394+
395+
// Input(1, Y)
376396
assert_eq!(
377397
next().to_le_bytes(),
378-
[BytecodeOp::Copy as u8, 0, 0xFF, 0xFF]
398+
[BytecodeOp::Input as u8, 1, 0xFF, 0xFF]
399+
);
400+
assert_eq!(next(), 1); // Y
401+
402+
// Input(0, X)
403+
assert_eq!(
404+
next().to_le_bytes(),
405+
[BytecodeOp::Input as u8, 0, 0xFF, 0xFF]
379406
);
407+
assert_eq!(next(), 0); // X
408+
409+
// r1 = max(1, 0)
410+
assert_eq!(next().to_le_bytes(), [BytecodeOp::Max as u8, 1, 1, 0]);
411+
assert_eq!(next(), 0xFF000000);
412+
413+
// Copy from mem[0] -> reg[0]
414+
assert_eq!(
415+
next().to_le_bytes(),
416+
[BytecodeOp::Mem as u8, 0, 0xFF, 0xFF]
417+
);
418+
assert_eq!(next(), 0);
419+
420+
// r0 = max(0, 1)
421+
assert_eq!(next().to_le_bytes(), [BytecodeOp::Max as u8, 0, 0, 1]);
422+
assert_eq!(next(), 0xFF000000);
423+
424+
// output(0) = r0
425+
assert_eq!(
426+
next().to_le_bytes(),
427+
[BytecodeOp::Output as u8, 0, 0xFF, 0xFF]
428+
);
429+
assert_eq!(next(), 0);
430+
431+
assert_eq!(next(), 0xFFFFFFFF); // end marker
432+
assert_eq!(next(), 0xFFFFFFFF);
433+
assert!(iter.next().is_none());
380434
}
381435
}

fidget-core/src/compiler/op.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,9 @@ opcodes!(
275275
///
276276
/// We have a maximum of 256 registers, though some tapes (e.g. ones
277277
/// targeting physical hardware) may choose to use fewer.
278+
///
279+
/// Note that memory slots are not zero-indexed; they start at `N` (where
280+
/// `N` is the register count).
278281
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
279282
pub enum RegOp<u8> {
280283
// default variants

0 commit comments

Comments
 (0)