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:
Chris Fallin
2022-09-08 12:04:59 -05:00
committed by GitHub
parent ef5ad26ab2
commit 13c7846815

View File

@@ -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()),