--- /dev/null
+
+-- | 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 SPARC.Instr
+import SPARC.Ppr ()
+import Instruction
+
+import Cmm
+
+import Outputable
+
+
+-- | Enforce intra-block invariants.
+--
+checkBlock
+ :: CmmBasicBlock -> 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
+
+