ghc-8.10.1: nativeGen/SPARC/CodeGen/Sanity.hs
-- | One ounce of sanity checking is worth 10000000000000000 ounces
-- of staring blindly at assembly code trying to find the problem..
module SPARC.CodeGen.Sanity (
checkBlock
)
where
import GhcPrelude
import SPARC.Instr
import SPARC.Ppr () -- For Outputable instances
import Instruction
import Cmm
import Outputable
-- | Enforce intra-block invariants.
--
checkBlock :: CmmBlock
-> NatBasicBlock Instr
-> NatBasicBlock Instr
checkBlock cmm block@(BasicBlock _ instrs)
| checkBlockInstrs instrs
= block
| otherwise
= pprPanic
("SPARC.CodeGen: bad block\n")
( vcat [ text " -- cmm -----------------\n"
, ppr cmm
, text " -- native code ---------\n"
, ppr block ])
checkBlockInstrs :: [Instr] -> Bool
checkBlockInstrs ii
-- An unconditional jumps end the block.
-- There must be an unconditional jump in the block, otherwise
-- the register liveness determinator will get the liveness
-- information wrong.
--
-- If the block ends with a cmm call that never returns
-- then there can be unreachable instructions after the jump,
-- but we don't mind here.
--
| instr : NOP : _ <- ii
, isUnconditionalJump instr
= True
-- All jumps must have a NOP in their branch delay slot.
-- The liveness determinator and register allocators aren't smart
-- enough to handle branch delay slots.
--
| instr : NOP : is <- ii
, isJumpishInstr instr
= checkBlockInstrs is
-- keep checking
| _:i2:is <- ii
= checkBlockInstrs (i2:is)
-- this block is no good
| otherwise
= False