summaryrefslogtreecommitdiff
path: root/compiler/nativeGen/Reg.hs
blob: 1a341bbddabc8b321fba90bcf09cb6e9dd7c1459 (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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

-- | An architecture independent description of a register.
--	This needs to stay architecture independent because it is used
--	by NCGMonad and the register allocators, which are shared
--	by all architectures.
--
module Reg (
	RegNo,
	Reg(..),
	isRealReg,
	unRealReg,
	isVirtualReg,
	renameVirtualReg,
	getHiVRegFromLo
)

where

import Outputable
import Unique
import Panic

-- | An identifier for a real machine register.
type RegNo 
	= Int

-- RealRegs are machine regs which are available for allocation, in
-- 	the usual way.  We know what class they are, because that's part of
-- 	the processor's architecture.

-- VirtualRegs are virtual registers.  The register allocator will
-- 	eventually have to map them into RealRegs, or into spill slots.
--
-- 	VirtualRegs are allocated on the fly, usually to represent a single
-- 	value in the abstract assembly code (i.e. dynamic registers are
-- 	usually single assignment).  
--
--	With the new register allocator, the
-- 	single assignment restriction isn't necessary to get correct code,
-- 	although a better register allocation will result if single
-- 	assignment is used -- because the allocator maps a VirtualReg into
-- 	a single RealReg, even if the VirtualReg has multiple live ranges.

-- 	Virtual regs can be of either class, so that info is attached.
data Reg
	= RealReg      {-# UNPACK #-} !RegNo
	| VirtualRegI  {-# UNPACK #-} !Unique
	| VirtualRegHi {-# UNPACK #-} !Unique  -- High part of 2-word register
	| VirtualRegF  {-# UNPACK #-} !Unique
	| VirtualRegD  {-# UNPACK #-} !Unique
	deriving (Eq, Ord)


-- We like to have Uniques for Reg so that we can make UniqFM and UniqSets 
-- in the register allocator.
instance Uniquable Reg where
	getUnique (RealReg i)      = mkUnique 'C' i
	getUnique (VirtualRegI u)  = u
	getUnique (VirtualRegHi u) = u
	getUnique (VirtualRegF u)  = u
	getUnique (VirtualRegD u)  = u


-- | Print a reg in a generic manner
--	If you want the architecture specific names, then use the pprReg 
--	function from the appropriate Ppr module.
instance Outputable Reg where
	ppr reg
	 = case reg of
		RealReg i       -> text "%r" 	<> int i
		VirtualRegI  u  -> text "%vI_" 	<> pprUnique u
		VirtualRegHi u  -> text "%vHi_" <> pprUnique u
		VirtualRegF  u  -> text "%vF_" 	<> pprUnique u
		VirtualRegD  u  -> text "%vD_" 	<> pprUnique u



isRealReg :: Reg -> Bool
isRealReg = not . isVirtualReg

-- | Take the RegNo from a real reg
unRealReg :: Reg -> RegNo
unRealReg (RealReg i)	= i
unRealReg _		= panic "unRealReg on VirtualReg"

isVirtualReg :: Reg -> Bool
isVirtualReg (RealReg _)      = False
isVirtualReg (VirtualRegI _)  = True
isVirtualReg (VirtualRegHi _) = True
isVirtualReg (VirtualRegF _)  = True
isVirtualReg (VirtualRegD _)  = True


renameVirtualReg :: Unique -> Reg -> Reg
renameVirtualReg u r
 = case r of
 	RealReg _	-> error "renameVirtualReg: can't change unique on a real reg"
	VirtualRegI _	-> VirtualRegI  u
	VirtualRegHi _	-> VirtualRegHi u
	VirtualRegF _	-> VirtualRegF  u
	VirtualRegD _	-> VirtualRegD  u

-- Determine the upper-half vreg for a 64-bit quantity on a 32-bit platform
-- when supplied with the vreg for the lower-half of the quantity.
-- (NB. Not reversible).
getHiVRegFromLo :: Reg -> Reg
getHiVRegFromLo (VirtualRegI u) 
   = VirtualRegHi (newTagUnique u 'H') -- makes a pseudo-unique with tag 'H'

getHiVRegFromLo _ 
   = panic "RegsBase.getHiVRegFromLo"