mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-02 23:04:23 +01:00
Merge 'Small VDBE insn tweaks' from Jussi Saurio
1. allow calling op_null with Insn::BeginSubrtn
- BeginSubrtn is identical to Null, but named differently so that
its use in context is clearer
2. Insn::Return: add possibility to fallthrough on non-integer values as
per sqlite spec
Closes #1588
This commit is contained in:
@@ -760,6 +760,7 @@ pub fn group_by_emit_row_phase<'a>(
|
||||
});
|
||||
program.emit_insn(Insn::Return {
|
||||
return_reg: registers.reg_subrtn_acc_output_return_offset,
|
||||
can_fallthrough: false,
|
||||
});
|
||||
|
||||
program.resolve_label(labels.label_subrtn_acc_output, program.offset());
|
||||
@@ -784,6 +785,7 @@ pub fn group_by_emit_row_phase<'a>(
|
||||
}
|
||||
program.emit_insn(Insn::Return {
|
||||
return_reg: registers.reg_subrtn_acc_output_return_offset,
|
||||
can_fallthrough: false,
|
||||
});
|
||||
|
||||
// Finalize aggregate values for output
|
||||
@@ -916,6 +918,7 @@ pub fn group_by_emit_row_phase<'a>(
|
||||
|
||||
program.emit_insn(Insn::Return {
|
||||
return_reg: registers.reg_subrtn_acc_output_return_offset,
|
||||
can_fallthrough: false,
|
||||
});
|
||||
|
||||
// Subroutine to clear accumulators for a new group
|
||||
@@ -955,6 +958,7 @@ pub fn group_by_emit_row_phase<'a>(
|
||||
});
|
||||
program.emit_insn(Insn::Return {
|
||||
return_reg: registers.reg_subrtn_acc_clear_return_offset,
|
||||
can_fallthrough: false,
|
||||
});
|
||||
program.preassign_label_to_next_insn(labels.label_group_by_end);
|
||||
Ok(())
|
||||
|
||||
@@ -322,15 +322,17 @@ pub fn op_null(
|
||||
pager: &Rc<Pager>,
|
||||
mv_store: Option<&Rc<MvStore>>,
|
||||
) -> Result<InsnFunctionStepResult> {
|
||||
let Insn::Null { dest, dest_end } = insn else {
|
||||
unreachable!("unexpected Insn {:?}", insn)
|
||||
};
|
||||
if let Some(dest_end) = dest_end {
|
||||
for i in *dest..=*dest_end {
|
||||
state.registers[i] = Register::Value(Value::Null);
|
||||
match insn {
|
||||
Insn::Null { dest, dest_end } | Insn::BeginSubrtn { dest, dest_end } => {
|
||||
if let Some(dest_end) = dest_end {
|
||||
for i in *dest..=*dest_end {
|
||||
state.registers[i] = Register::Value(Value::Null);
|
||||
}
|
||||
} else {
|
||||
state.registers[*dest] = Register::Value(Value::Null);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
state.registers[*dest] = Register::Value(Value::Null);
|
||||
_ => unreachable!("unexpected Insn {:?}", insn),
|
||||
}
|
||||
state.pc += 1;
|
||||
Ok(InsnFunctionStepResult::Step)
|
||||
@@ -1809,7 +1811,11 @@ pub fn op_return(
|
||||
pager: &Rc<Pager>,
|
||||
mv_store: Option<&Rc<MvStore>>,
|
||||
) -> Result<InsnFunctionStepResult> {
|
||||
let Insn::Return { return_reg } = insn else {
|
||||
let Insn::Return {
|
||||
return_reg,
|
||||
can_fallthrough,
|
||||
} = insn
|
||||
else {
|
||||
unreachable!("unexpected Insn {:?}", insn)
|
||||
};
|
||||
if let Value::Integer(pc) = state.registers[*return_reg].get_owned_value() {
|
||||
@@ -1818,9 +1824,12 @@ pub fn op_return(
|
||||
.unwrap_or_else(|_| panic!("Return register is negative: {}", pc));
|
||||
state.pc = pc;
|
||||
} else {
|
||||
return Err(LimboError::InternalError(
|
||||
"Return register is not an integer".to_string(),
|
||||
));
|
||||
if !*can_fallthrough {
|
||||
return Err(LimboError::InternalError(
|
||||
"Return register is not an integer".to_string(),
|
||||
));
|
||||
}
|
||||
state.pc += 1;
|
||||
}
|
||||
Ok(InsnFunctionStepResult::Step)
|
||||
}
|
||||
|
||||
@@ -625,11 +625,14 @@ pub fn insn_to_str(
|
||||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
Insn::Return { return_reg } => (
|
||||
Insn::Return {
|
||||
return_reg,
|
||||
can_fallthrough,
|
||||
} => (
|
||||
"Return",
|
||||
*return_reg as i32,
|
||||
0,
|
||||
0,
|
||||
*can_fallthrough as i32,
|
||||
Value::build_text(""),
|
||||
0,
|
||||
"".to_string(),
|
||||
|
||||
@@ -429,8 +429,11 @@ pub enum Insn {
|
||||
},
|
||||
|
||||
/// Returns to the program counter stored in register 'return_reg'.
|
||||
/// If can_fallthrough is true, fall through to the next instruction
|
||||
/// if return_reg does not contain an integer value. Otherwise raise an error.
|
||||
Return {
|
||||
return_reg: usize,
|
||||
can_fallthrough: bool,
|
||||
},
|
||||
|
||||
/// Write an integer value into a register.
|
||||
|
||||
Reference in New Issue
Block a user