blob: d4cdaf2b16728419f14372ff1a7c4d9b1c4fe1c3 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
{-# 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://ghc.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 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
|