Cranelift: add a vreg limit check to correctly return an error on too-large inputs. (#4882)
Previously, Cranelift panicked (via a a panic in regalloc2) when the virtual-register limit of 2M (2^21) was reached. This resulted in a perplexing and unhelpful failure when the user provided a too-large input (such as the Wasm module in #4865). This PR adds an explicit check when allocating vregs that fails with a "code too large" error when the limit is hit, producing output such as (on the minimized testcase from #4865): ``` Error: failed to compile wasm function 3785 at offset 0xa3f3 Caused by: Compilation error: Code for function is too large ``` Fixes #4865.
This commit is contained in:
@@ -19,7 +19,7 @@ use crate::machinst::{
|
|||||||
LoweredBlock, MachLabel, Reg, SigSet, VCode, VCodeBuilder, VCodeConstant, VCodeConstantData,
|
LoweredBlock, MachLabel, Reg, SigSet, VCode, VCodeBuilder, VCodeConstant, VCodeConstantData,
|
||||||
VCodeConstants, VCodeInst, ValueRegs, Writable,
|
VCodeConstants, VCodeInst, ValueRegs, Writable,
|
||||||
};
|
};
|
||||||
use crate::{trace, CodegenResult};
|
use crate::{trace, CodegenError, CodegenResult};
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use regalloc2::VReg;
|
use regalloc2::VReg;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
@@ -323,6 +323,10 @@ fn alloc_vregs<I: VCodeInst>(
|
|||||||
let v = *next_vreg;
|
let v = *next_vreg;
|
||||||
let (regclasses, tys) = I::rc_for_type(ty)?;
|
let (regclasses, tys) = I::rc_for_type(ty)?;
|
||||||
*next_vreg += regclasses.len();
|
*next_vreg += regclasses.len();
|
||||||
|
if *next_vreg >= VReg::MAX {
|
||||||
|
return Err(CodegenError::CodeTooLarge);
|
||||||
|
}
|
||||||
|
|
||||||
let regs: ValueRegs<Reg> = match regclasses {
|
let regs: ValueRegs<Reg> = match regclasses {
|
||||||
&[rc0] => ValueRegs::one(VReg::new(v, rc0).into()),
|
&[rc0] => ValueRegs::one(VReg::new(v, rc0).into()),
|
||||||
&[rc0, rc1] => ValueRegs::two(VReg::new(v, rc0).into(), VReg::new(v + 1, rc1).into()),
|
&[rc0, rc1] => ValueRegs::two(VReg::new(v, rc0).into(), VReg::new(v + 1, rc1).into()),
|
||||||
|
|||||||
Reference in New Issue
Block a user