summaryrefslogtreecommitdiff
path: root/compiler/nativeGen/SPARC/CodeGen/Sanity.hs
blob: b60c958a73538a1ee474e0ee465d04160d8c10bd (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
-- | 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 GHC.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