Skip to content

Commit 925912c

Browse files
committed
jit: preserve return types for recursive calls
Assisted-by: Codex:5.6-sol
1 parent 81df1ff commit 925912c

3 files changed

Lines changed: 44 additions & 2 deletions

File tree

crates/jit/src/instructions.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -548,8 +548,22 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
548548
match self.stack.pop().ok_or(JitCompileError::BadBytecode)? {
549549
JitValue::FuncRef(reference) => {
550550
let call = self.builder.ins().call(reference, &args);
551-
let returns = self.builder.inst_results(call);
552-
self.stack.push(JitValue::Int(returns[0]));
551+
// The only callable reachable here is this function itself,
552+
// so the result carries the declared return type - it is not
553+
// always an Int. A function whose return type is still
554+
// unknown has no return slot in the signature it was
555+
// declared with, and there is nothing to type the result as.
556+
let ret = match *self.builder.inst_results(call) {
557+
[] => None,
558+
[val] => Some(val),
559+
_ => return Err(JitCompileError::NotSupported),
560+
};
561+
let val = match (self.sig.ret.clone(), ret) {
562+
(Some(JitType::None), None) => JitValue::None,
563+
(Some(ty), Some(val)) => JitValue::from_type_and_value(ty, val),
564+
_ => return Err(JitCompileError::NotSupported),
565+
};
566+
self.stack.push(val);
553567

554568
Ok(())
555569
}

crates/jit/tests/bool_tests.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,4 +202,18 @@ mod tests {
202202
assert_eq!(lte(false, 1), Ok(1));
203203
assert_eq!(lte(true, 0), Ok(0));
204204
}
205+
206+
#[test]
207+
fn recursive_bool() {
208+
let recursive_bool = jit_function! { recursive_bool(n: i64) -> bool => r##"
209+
def recursive_bool(n: int) -> bool:
210+
if n == 0:
211+
return True
212+
return not recursive_bool(n - 1)
213+
"## };
214+
215+
assert_eq!(recursive_bool(0), Ok(true));
216+
assert_eq!(recursive_bool(1), Ok(false));
217+
assert_eq!(recursive_bool(4), Ok(true));
218+
}
205219
}

crates/jit/tests/float_tests.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,4 +379,18 @@ mod tests {
379379
assert_eq!(float_lte(f64::NAN, f64::NAN), Ok(false));
380380
assert_eq!(float_lte(f64::INFINITY, f64::NEG_INFINITY), Ok(false));
381381
}
382+
383+
#[test]
384+
fn recursive_float() {
385+
let recursive_float = jit_function! { recursive_float(n: i64) -> f64 => r##"
386+
def recursive_float(n: int) -> float:
387+
if n == 0:
388+
return 1.0
389+
return recursive_float(n - 1) / 2.0
390+
"## };
391+
392+
assert_eq!(recursive_float(0), Ok(1.0));
393+
assert_eq!(recursive_float(1), Ok(0.5));
394+
assert_eq!(recursive_float(4), Ok(0.0625));
395+
}
382396
}

0 commit comments

Comments
 (0)