Instr.hs 4.93 KB
Newer Older
1

2 3 4 5 6
module GHC.CmmToAsm.Instr
   ( Instruction(..)
   , RegUsage(..)
   , noUsage
   )
7 8
where

9
import GHC.Prelude
10

11
import GHC.Platform
Sylvain Henry's avatar
Sylvain Henry committed
12
import GHC.Platform.Reg
13
import GHC.Utils.Outputable (SDoc)
14

15
import GHC.Cmm.BlockId
16 17

import GHC.CmmToAsm.Config
18 19

-- | Holds a list of source and destination registers used by a
20
--      particular instruction.
21 22
--
--   Machine registers that are pre-allocated to stgRegs are filtered
23 24
--      out, because they are uninteresting from a register allocation
--      standpoint.  (We wouldn't want them to end up on the free list!)
25 26
--
--   As far as we are concerned, the fixed registers simply don't exist
27
--      (for allocation purposes, anyway).
28
--
29
data RegUsage
30 31 32 33
        = RU    {
                reads :: [Reg],
                writes :: [Reg]
                }
34 35 36 37 38 39

-- | No regs read or written to.
noUsage :: RegUsage
noUsage  = RU [] []

-- | Common things that we can do with instructions, on all architectures.
40 41
--      These are used by the shared parts of the native code generator,
--      specifically the register allocators.
42
--
43
class Instruction instr where
44 45 46 47 48 49 50 51

        -- | Get the registers that are being used by this instruction.
        --      regUsage doesn't need to do any trickery for jumps and such.
        --      Just state precisely the regs read and written by that insn.
        --      The consequences of control flow transfers, as far as register
        --      allocation goes, are taken care of by the register allocator.
        --
        regUsageOfInstr
52 53
                :: Platform
                -> instr
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 79 80 81 82 83 84 85 86 87 88
                -> RegUsage


        -- | Apply a given mapping to all the register references in this
        --      instruction.
        patchRegsOfInstr
                :: instr
                -> (Reg -> Reg)
                -> instr


        -- | Checks whether this instruction is a jump/branch instruction.
        --      One that can change the flow of control in a way that the
        --      register allocator needs to worry about.
        isJumpishInstr
                :: instr -> Bool


        -- | Give the possible destinations of this jump instruction.
        --      Must be defined for all jumpish instructions.
        jumpDestsOfInstr
                :: instr -> [BlockId]


        -- | Change the destination of this jump instruction.
        --      Used in the linear allocator when adding fixup blocks for join
        --      points.
        patchJumpInstr
                :: instr
                -> (BlockId -> BlockId)
                -> instr


        -- | An instruction to spill a register into a spill slot.
        mkSpillInstr
89
                :: NCGConfig
90
                -> Reg          -- ^ the reg to spill
91 92 93 94 95 96 97
                -> Int          -- ^ the current stack delta
                -> Int          -- ^ spill slot to use
                -> instr


        -- | An instruction to reload a register from a spill slot.
        mkLoadInstr
98
                :: NCGConfig
99
                -> Reg          -- ^ the reg to reload.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
                -> Int          -- ^ the current stack delta
                -> Int          -- ^ the spill slot to use
                -> instr

        -- | See if this instruction is telling us the current C stack delta
        takeDeltaInstr
                :: instr
                -> Maybe Int

        -- | Check whether this instruction is some meta thing inserted into
        --      the instruction stream for other purposes.
        --
        --      Not something that has to be treated as a real machine instruction
        --      and have its registers allocated.
        --
        --      eg, comments, delta, ldata, etc.
        isMetaInstr
                :: instr
                -> Bool



        -- | Copy the value in a register to another one.
        --      Must work for all register classes.
        mkRegRegMoveInstr
125 126
                :: Platform
                -> Reg          -- ^ source register
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
                -> Reg          -- ^ destination register
                -> instr

        -- | Take the source and destination from this reg -> reg move instruction
        --      or Nothing if it's not one
        takeRegRegMoveInstr
                :: instr
                -> Maybe (Reg, Reg)

        -- | Make an unconditional jump instruction.
        --      For architectures with branch delay slots, its ok to put
        --      a NOP after the jump. Don't fill the delay slot with an
        --      instruction that references regs or you'll confuse the
        --      linear allocator.
        mkJumpInstr
                :: BlockId
                -> [instr]


146 147
        -- Subtract an amount from the C stack pointer
        mkStackAllocInstr
148
                :: Platform
149
                -> Int
150
                -> [instr]
151 152 153

        -- Add an amount to the C stack pointer
        mkStackDeallocInstr
154
                :: Platform
155
                -> Int
156
                -> [instr]
157 158 159

        -- | Pretty-print an instruction
        pprInstr :: Platform -> instr -> SDoc