
{-# OPTIONS -fno-warn-tabs #-}
-- The above warning supression flag is a temporary kludge.
-- While working on this module you are encouraged to remove it and
-- detab the module (please do the detabbing in a separate patch). See
--     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSpaces
-- for details

-- | 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 OldCmm

import Outputable
import Platform


-- | Enforce intra-block invariants.
--
checkBlock :: Platform
           -> CmmBasicBlock
           -> NatBasicBlock Instr
           -> NatBasicBlock Instr

checkBlock platform cmm block@(BasicBlock _ instrs)
	| checkBlockInstrs instrs
	= block
	
	| otherwise
	= pprPanic 
		("SPARC.CodeGen: bad block\n")
		( vcat	[ text " -- cmm -----------------\n"
			, pprPlatform platform cmm
			, text " -- native code ---------\n"
			, pprPlatform platform 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


