@@ -35,12 +35,15 @@ pub enum VerifierError {
3535 op : u32 ,
3636 found_vreg : Option < VirtReg > ,
3737 } ,
38- SpillToSpillCopy {
38+ IllegalSpillCopy {
3939 copy_idx : u32 ,
4040 } ,
4141 UndefCopySource {
4242 copy_idx : u32 ,
4343 } ,
44+ BadRematOperands {
45+ copy_idx : u32 ,
46+ } ,
4447 BadGhostCopyBlock {
4548 block : Block ,
4649 } ,
@@ -119,9 +122,13 @@ impl<M: MachineCore> fmt::Display for DisplayVerifierError<'_, M> {
119122 "expected {instr} use {op} to be of {expected_vreg}, found {found_vreg}"
120123 )
121124 }
122- VerifierError :: SpillToSpillCopy { copy_idx } => {
125+ VerifierError :: IllegalSpillCopy { copy_idx } => {
123126 let copy = & self . assignment . copies [ copy_idx as usize ] ;
124- write ! ( f, "copy before {} copies between spill slots" , copy. instr)
127+ write ! (
128+ f,
129+ "copy before {} copies from non-register into spill" ,
130+ copy. instr
131+ )
125132 }
126133 VerifierError :: UndefCopySource { copy_idx } => {
127134 let copy = & self . assignment . copies [ copy_idx as usize ] ;
@@ -133,6 +140,19 @@ impl<M: MachineCore> fmt::Display for DisplayVerifierError<'_, M> {
133140 copy. instr
134141 )
135142 }
143+ VerifierError :: BadRematOperands { copy_idx } => {
144+ let copy = & self . assignment . copies [ copy_idx as usize ] ;
145+ let remat_instr = match copy. copy . from {
146+ AssignmentCopySource :: Remat ( instr) => instr,
147+ _ => unreachable ! ( ) ,
148+ } ;
149+
150+ write ! (
151+ f,
152+ "instruction {} rematerialized before {} has unsupported operands" ,
153+ remat_instr, copy. instr
154+ )
155+ }
136156 VerifierError :: BadGhostCopyBlock { block } => {
137157 write ! ( f, "block '{block}' contained exit ghost copies despite not having a single successor" )
138158 }
@@ -246,17 +266,29 @@ fn verify_copy<M: MachineCore>(
246266 copy : & AssignmentCopy ,
247267 reg_state : & mut KnownRegState ,
248268) -> Result < ( ) , VerifierError > {
249- // TODO: Should remat into a stack slot should be disallowed?
250- if copy. from . is_spill ( ) && copy. to . is_spill ( ) {
251- return Err ( VerifierError :: SpillToSpillCopy { copy_idx } ) ;
269+ if !copy. from . is_reg ( ) && copy. to . is_spill ( ) {
270+ return Err ( VerifierError :: IllegalSpillCopy { copy_idx } ) ;
252271 }
253272
254273 let from_vreg = match copy. from {
255274 AssignmentCopySource :: Operand ( from) => * reg_state
256275 . get ( & from)
257276 . ok_or ( VerifierError :: UndefCopySource { copy_idx } ) ?,
258- // TODO: Validate instruction shape.
259- AssignmentCopySource :: Remat ( instr) => lir. instr_defs ( instr) [ 0 ] . reg ( ) ,
277+ AssignmentCopySource :: Remat ( instr) => {
278+ if !lir. instr_uses ( instr) . is_empty ( ) {
279+ return Err ( VerifierError :: BadRematOperands { copy_idx } ) ;
280+ }
281+
282+ let [ def] = lir. instr_defs ( instr) else {
283+ return Err ( VerifierError :: BadRematOperands { copy_idx } ) ;
284+ } ;
285+
286+ if def. constraint ( ) != DefOperandConstraint :: AnyReg {
287+ return Err ( VerifierError :: BadRematOperands { copy_idx } ) ;
288+ }
289+
290+ def. reg ( )
291+ }
260292 } ;
261293
262294 reg_state. insert ( copy. to , from_vreg) ;
0 commit comments