Be aware of overlapping global STG registers in CmmSink (#10521)
[ghc.git] / compiler / cmm / CmmExpr.hs
1 {-# LANGUAGE CPP #-}
2 {-# LANGUAGE FlexibleContexts #-}
3 {-# LANGUAGE FlexibleInstances #-}
4 {-# LANGUAGE MultiParamTypeClasses #-}
5 {-# LANGUAGE UndecidableInstances #-}
6
7 module CmmExpr
8 ( CmmExpr(..), cmmExprType, cmmExprWidth, maybeInvertCmmExpr
9 , CmmReg(..), cmmRegType
10 , CmmLit(..), cmmLitType
11 , LocalReg(..), localRegType
12 , GlobalReg(..), isArgReg, globalRegType, spReg, hpReg, spLimReg, nodeReg, node, baseReg
13 , VGcPtr(..), vgcFlag -- Temporary!
14
15 , DefinerOfRegs, UserOfRegs
16 , foldRegsDefd, foldRegsUsed, filterRegsUsed
17 , foldLocalRegsDefd, foldLocalRegsUsed
18
19 , RegSet, LocalRegSet, GlobalRegSet
20 , emptyRegSet, elemRegSet, extendRegSet, deleteFromRegSet, mkRegSet
21 , plusRegSet, minusRegSet, timesRegSet, sizeRegSet, nullRegSet
22 , regSetToList
23
24 , Area(..)
25 , module CmmMachOp
26 , module CmmType
27 )
28 where
29
30 #include "HsVersions.h"
31
32 import CmmType
33 import CmmMachOp
34 import BlockId
35 import CLabel
36 import DynFlags
37 import Unique
38 import Outputable (panic)
39
40 import Data.Set (Set)
41 import qualified Data.Set as Set
42
43 -----------------------------------------------------------------------------
44 -- CmmExpr
45 -- An expression. Expressions have no side effects.
46 -----------------------------------------------------------------------------
47
48 data CmmExpr
49 = CmmLit CmmLit -- Literal
50 | CmmLoad !CmmExpr !CmmType -- Read memory location
51 | CmmReg !CmmReg -- Contents of register
52 | CmmMachOp MachOp [CmmExpr] -- Machine operation (+, -, *, etc.)
53 | CmmStackSlot Area {-# UNPACK #-} !Int
54 -- addressing expression of a stack slot
55 -- See Note [CmmStackSlot aliasing]
56 | CmmRegOff !CmmReg Int
57 -- CmmRegOff reg i
58 -- ** is shorthand only, meaning **
59 -- CmmMachOp (MO_Add rep) [x, CmmLit (CmmInt (fromIntegral i) rep)]
60 -- where rep = typeWidth (cmmRegType reg)
61
62 instance Eq CmmExpr where -- Equality ignores the types
63 CmmLit l1 == CmmLit l2 = l1==l2
64 CmmLoad e1 _ == CmmLoad e2 _ = e1==e2
65 CmmReg r1 == CmmReg r2 = r1==r2
66 CmmRegOff r1 i1 == CmmRegOff r2 i2 = r1==r2 && i1==i2
67 CmmMachOp op1 es1 == CmmMachOp op2 es2 = op1==op2 && es1==es2
68 CmmStackSlot a1 i1 == CmmStackSlot a2 i2 = a1==a2 && i1==i2
69 _e1 == _e2 = False
70
71 data CmmReg
72 = CmmLocal {-# UNPACK #-} !LocalReg
73 | CmmGlobal GlobalReg
74 deriving( Eq, Ord )
75
76 -- | A stack area is either the stack slot where a variable is spilled
77 -- or the stack space where function arguments and results are passed.
78 data Area
79 = Old -- See Note [Old Area]
80 | Young {-# UNPACK #-} !BlockId -- Invariant: must be a continuation BlockId
81 -- See Note [Continuation BlockId] in CmmNode.
82 deriving (Eq, Ord)
83
84 {- Note [Old Area]
85 ~~~~~~~~~~~~~~~~~~
86 There is a single call area 'Old', allocated at the extreme old
87 end of the stack frame (ie just younger than the return address)
88 which holds:
89 * incoming (overflow) parameters,
90 * outgoing (overflow) parameter to tail calls,
91 * outgoing (overflow) result values
92 * the update frame (if any)
93
94 Its size is the max of all these requirements. On entry, the stack
95 pointer will point to the youngest incoming parameter, which is not
96 necessarily at the young end of the Old area.
97
98 End of note -}
99
100
101 {- Note [CmmStackSlot aliasing]
102 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
103 When do two CmmStackSlots alias?
104
105 - T[old+N] aliases with U[young(L)+M] for all T, U, L, N and M
106 - T[old+N] aliases with U[old+M] only if the areas actually overlap
107
108 Or more informally, different Areas may overlap with each other.
109
110 An alternative semantics, that we previously had, was that different
111 Areas do not overlap. The problem that lead to redefining the
112 semantics of stack areas is described below.
113
114 e.g. if we had
115
116 x = Sp[old + 8]
117 y = Sp[old + 16]
118
119 Sp[young(L) + 8] = L
120 Sp[young(L) + 16] = y
121 Sp[young(L) + 24] = x
122 call f() returns to L
123
124 if areas semantically do not overlap, then we might optimise this to
125
126 Sp[young(L) + 8] = L
127 Sp[young(L) + 16] = Sp[old + 8]
128 Sp[young(L) + 24] = Sp[old + 16]
129 call f() returns to L
130
131 and now young(L) cannot be allocated at the same place as old, and we
132 are doomed to use more stack.
133
134 - old+8 conflicts with young(L)+8
135 - old+16 conflicts with young(L)+16 and young(L)+8
136
137 so young(L)+8 == old+24 and we get
138
139 Sp[-8] = L
140 Sp[-16] = Sp[8]
141 Sp[-24] = Sp[0]
142 Sp -= 24
143 call f() returns to L
144
145 However, if areas are defined to be "possibly overlapping" in the
146 semantics, then we cannot commute any loads/stores of old with
147 young(L), and we will be able to re-use both old+8 and old+16 for
148 young(L).
149
150 x = Sp[8]
151 y = Sp[0]
152
153 Sp[8] = L
154 Sp[0] = y
155 Sp[-8] = x
156 Sp = Sp - 8
157 call f() returns to L
158
159 Now, the assignments of y go away,
160
161 x = Sp[8]
162 Sp[8] = L
163 Sp[-8] = x
164 Sp = Sp - 8
165 call f() returns to L
166 -}
167
168 data CmmLit
169 = CmmInt !Integer Width
170 -- Interpretation: the 2's complement representation of the value
171 -- is truncated to the specified size. This is easier than trying
172 -- to keep the value within range, because we don't know whether
173 -- it will be used as a signed or unsigned value (the CmmType doesn't
174 -- distinguish between signed & unsigned).
175 | CmmFloat Rational Width
176 | CmmVec [CmmLit] -- Vector literal
177 | CmmLabel CLabel -- Address of label
178 | CmmLabelOff CLabel Int -- Address of label + byte offset
179
180 -- Due to limitations in the C backend, the following
181 -- MUST ONLY be used inside the info table indicated by label2
182 -- (label2 must be the info label), and label1 must be an
183 -- SRT, a slow entrypoint or a large bitmap (see the Mangler)
184 -- Don't use it at all unless tablesNextToCode.
185 -- It is also used inside the NCG during when generating
186 -- position-independent code.
187 | CmmLabelDiffOff CLabel CLabel Int -- label1 - label2 + offset
188
189 | CmmBlock {-# UNPACK #-} !BlockId -- Code label
190 -- Invariant: must be a continuation BlockId
191 -- See Note [Continuation BlockId] in CmmNode.
192
193 | CmmHighStackMark -- A late-bound constant that stands for the max
194 -- #bytes of stack space used during a procedure.
195 -- During the stack-layout pass, CmmHighStackMark
196 -- is replaced by a CmmInt for the actual number
197 -- of bytes used
198 deriving Eq
199
200 cmmExprType :: DynFlags -> CmmExpr -> CmmType
201 cmmExprType dflags (CmmLit lit) = cmmLitType dflags lit
202 cmmExprType _ (CmmLoad _ rep) = rep
203 cmmExprType dflags (CmmReg reg) = cmmRegType dflags reg
204 cmmExprType dflags (CmmMachOp op args) = machOpResultType dflags op (map (cmmExprType dflags) args)
205 cmmExprType dflags (CmmRegOff reg _) = cmmRegType dflags reg
206 cmmExprType dflags (CmmStackSlot _ _) = bWord dflags -- an address
207 -- Careful though: what is stored at the stack slot may be bigger than
208 -- an address
209
210 cmmLitType :: DynFlags -> CmmLit -> CmmType
211 cmmLitType _ (CmmInt _ width) = cmmBits width
212 cmmLitType _ (CmmFloat _ width) = cmmFloat width
213 cmmLitType _ (CmmVec []) = panic "cmmLitType: CmmVec []"
214 cmmLitType cflags (CmmVec (l:ls)) = let ty = cmmLitType cflags l
215 in if all (`cmmEqType` ty) (map (cmmLitType cflags) ls)
216 then cmmVec (1+length ls) ty
217 else panic "cmmLitType: CmmVec"
218 cmmLitType dflags (CmmLabel lbl) = cmmLabelType dflags lbl
219 cmmLitType dflags (CmmLabelOff lbl _) = cmmLabelType dflags lbl
220 cmmLitType dflags (CmmLabelDiffOff {}) = bWord dflags
221 cmmLitType dflags (CmmBlock _) = bWord dflags
222 cmmLitType dflags (CmmHighStackMark) = bWord dflags
223
224 cmmLabelType :: DynFlags -> CLabel -> CmmType
225 cmmLabelType dflags lbl
226 | isGcPtrLabel lbl = gcWord dflags
227 | otherwise = bWord dflags
228
229 cmmExprWidth :: DynFlags -> CmmExpr -> Width
230 cmmExprWidth dflags e = typeWidth (cmmExprType dflags e)
231
232 --------
233 --- Negation for conditional branches
234
235 maybeInvertCmmExpr :: CmmExpr -> Maybe CmmExpr
236 maybeInvertCmmExpr (CmmMachOp op args) = do op' <- maybeInvertComparison op
237 return (CmmMachOp op' args)
238 maybeInvertCmmExpr _ = Nothing
239
240 -----------------------------------------------------------------------------
241 -- Local registers
242 -----------------------------------------------------------------------------
243
244 data LocalReg
245 = LocalReg {-# UNPACK #-} !Unique CmmType
246 -- ^ Parameters:
247 -- 1. Identifier
248 -- 2. Type
249
250 instance Eq LocalReg where
251 (LocalReg u1 _) == (LocalReg u2 _) = u1 == u2
252
253 instance Ord LocalReg where
254 compare (LocalReg u1 _) (LocalReg u2 _) = compare u1 u2
255
256 instance Uniquable LocalReg where
257 getUnique (LocalReg uniq _) = uniq
258
259 cmmRegType :: DynFlags -> CmmReg -> CmmType
260 cmmRegType _ (CmmLocal reg) = localRegType reg
261 cmmRegType dflags (CmmGlobal reg) = globalRegType dflags reg
262
263 localRegType :: LocalReg -> CmmType
264 localRegType (LocalReg _ rep) = rep
265
266 -----------------------------------------------------------------------------
267 -- Register-use information for expressions and other types
268 -----------------------------------------------------------------------------
269
270 -- | Sets of registers
271
272 -- These are used for dataflow facts, and a common operation is taking
273 -- the union of two RegSets and then asking whether the union is the
274 -- same as one of the inputs. UniqSet isn't good here, because
275 -- sizeUniqSet is O(n) whereas Set.size is O(1), so we use ordinary
276 -- Sets.
277
278 type RegSet r = Set r
279 type LocalRegSet = RegSet LocalReg
280 type GlobalRegSet = RegSet GlobalReg
281
282 emptyRegSet :: RegSet r
283 nullRegSet :: RegSet r -> Bool
284 elemRegSet :: Ord r => r -> RegSet r -> Bool
285 extendRegSet :: Ord r => RegSet r -> r -> RegSet r
286 deleteFromRegSet :: Ord r => RegSet r -> r -> RegSet r
287 mkRegSet :: Ord r => [r] -> RegSet r
288 minusRegSet, plusRegSet, timesRegSet :: Ord r => RegSet r -> RegSet r -> RegSet r
289 sizeRegSet :: RegSet r -> Int
290 regSetToList :: RegSet r -> [r]
291
292 emptyRegSet = Set.empty
293 nullRegSet = Set.null
294 elemRegSet = Set.member
295 extendRegSet = flip Set.insert
296 deleteFromRegSet = flip Set.delete
297 mkRegSet = Set.fromList
298 minusRegSet = Set.difference
299 plusRegSet = Set.union
300 timesRegSet = Set.intersection
301 sizeRegSet = Set.size
302 regSetToList = Set.toList
303
304 class Ord r => UserOfRegs r a where
305 foldRegsUsed :: DynFlags -> (b -> r -> b) -> b -> a -> b
306
307 foldLocalRegsUsed :: UserOfRegs LocalReg a
308 => DynFlags -> (b -> LocalReg -> b) -> b -> a -> b
309 foldLocalRegsUsed = foldRegsUsed
310
311 class Ord r => DefinerOfRegs r a where
312 foldRegsDefd :: DynFlags -> (b -> r -> b) -> b -> a -> b
313
314 foldLocalRegsDefd :: DefinerOfRegs LocalReg a
315 => DynFlags -> (b -> LocalReg -> b) -> b -> a -> b
316 foldLocalRegsDefd = foldRegsDefd
317
318 filterRegsUsed :: UserOfRegs r e => DynFlags -> (r -> Bool) -> e -> RegSet r
319 filterRegsUsed dflags p e =
320 foldRegsUsed dflags
321 (\regs r -> if p r then extendRegSet regs r else regs)
322 emptyRegSet e
323
324 instance UserOfRegs LocalReg CmmReg where
325 foldRegsUsed _ f z (CmmLocal reg) = f z reg
326 foldRegsUsed _ _ z (CmmGlobal _) = z
327
328 instance DefinerOfRegs LocalReg CmmReg where
329 foldRegsDefd _ f z (CmmLocal reg) = f z reg
330 foldRegsDefd _ _ z (CmmGlobal _) = z
331
332 instance UserOfRegs GlobalReg CmmReg where
333 foldRegsUsed _ _ z (CmmLocal _) = z
334 foldRegsUsed _ f z (CmmGlobal reg) = f z reg
335
336 instance DefinerOfRegs GlobalReg CmmReg where
337 foldRegsDefd _ _ z (CmmLocal _) = z
338 foldRegsDefd _ f z (CmmGlobal reg) = f z reg
339
340 instance Ord r => UserOfRegs r r where
341 foldRegsUsed _ f z r = f z r
342
343 instance Ord r => DefinerOfRegs r r where
344 foldRegsDefd _ f z r = f z r
345
346 instance Ord r => UserOfRegs r (RegSet r) where
347 foldRegsUsed _ f = Set.fold (flip f)
348
349 instance (Ord r, UserOfRegs r CmmReg) => UserOfRegs r CmmExpr where
350 -- The (Ord r) in the context is necessary here
351 -- See Note [Recursive superclasses] in TcInstDcls
352 foldRegsUsed dflags f z e = expr z e
353 where expr z (CmmLit _) = z
354 expr z (CmmLoad addr _) = foldRegsUsed dflags f z addr
355 expr z (CmmReg r) = foldRegsUsed dflags f z r
356 expr z (CmmMachOp _ exprs) = foldRegsUsed dflags f z exprs
357 expr z (CmmRegOff r _) = foldRegsUsed dflags f z r
358 expr z (CmmStackSlot _ _) = z
359
360 instance UserOfRegs r a => UserOfRegs r (Maybe a) where
361 foldRegsUsed dflags f z (Just x) = foldRegsUsed dflags f z x
362 foldRegsUsed _ _ z Nothing = z
363
364 instance UserOfRegs r a => UserOfRegs r [a] where
365 foldRegsUsed _ _ set [] = set
366 foldRegsUsed dflags f set (x:xs) = foldRegsUsed dflags f (foldRegsUsed dflags f set x) xs
367
368 instance DefinerOfRegs r a => DefinerOfRegs r [a] where
369 foldRegsDefd _ _ set [] = set
370 foldRegsDefd dflags f set (x:xs) = foldRegsDefd dflags f (foldRegsDefd dflags f set x) xs
371
372 instance DefinerOfRegs r a => DefinerOfRegs r (Maybe a) where
373 foldRegsDefd _ _ set Nothing = set
374 foldRegsDefd dflags f set (Just x) = foldRegsDefd dflags f set x
375
376 -----------------------------------------------------------------------------
377 -- Global STG registers
378 -----------------------------------------------------------------------------
379
380 data VGcPtr = VGcPtr | VNonGcPtr deriving( Eq, Show )
381 -- TEMPORARY!!!
382
383 -----------------------------------------------------------------------------
384 -- Global STG registers
385 -----------------------------------------------------------------------------
386 vgcFlag :: CmmType -> VGcPtr
387 vgcFlag ty | isGcPtrType ty = VGcPtr
388 | otherwise = VNonGcPtr
389
390 {-
391 Note [Overlapping global registers]
392
393 The backend might not faithfully implement the abstraction of the STG
394 machine with independent registers for different values of type
395 GlobalReg. Specifically, certain pairs of registers (r1, r2) may
396 overlap in the sense that a store to r1 invalidates the value in r2,
397 and vice versa.
398
399 Currently this occurs only on the x86_64 architecture where FloatReg n
400 and DoubleReg n are assigned the same microarchitectural register, in
401 order to allow functions to receive more Float# or Double# arguments
402 in registers (as opposed to on the stack).
403
404 There are no specific rules about which registers might overlap with
405 which other registers, but presumably it's safe to assume that nothing
406 will overlap with special registers like Sp or BaseReg.
407
408 Use CmmUtils.regsOverlap to determine whether two GlobalRegs overlap
409 on a particular platform. The instance Eq GlobalReg is syntactic
410 equality of STG registers and does not take overlap into
411 account. However it is still used in UserOfRegs/DefinerOfRegs and
412 there are likely still bugs there, beware!
413 -}
414
415 data GlobalReg
416 -- Argument and return registers
417 = VanillaReg -- pointers, unboxed ints and chars
418 {-# UNPACK #-} !Int -- its number
419 VGcPtr
420
421 | FloatReg -- single-precision floating-point registers
422 {-# UNPACK #-} !Int -- its number
423
424 | DoubleReg -- double-precision floating-point registers
425 {-# UNPACK #-} !Int -- its number
426
427 | LongReg -- long int registers (64-bit, really)
428 {-# UNPACK #-} !Int -- its number
429
430 | XmmReg -- 128-bit SIMD vector register
431 {-# UNPACK #-} !Int -- its number
432
433 | YmmReg -- 256-bit SIMD vector register
434 {-# UNPACK #-} !Int -- its number
435
436 | ZmmReg -- 512-bit SIMD vector register
437 {-# UNPACK #-} !Int -- its number
438
439 -- STG registers
440 | Sp -- Stack ptr; points to last occupied stack location.
441 | SpLim -- Stack limit
442 | Hp -- Heap ptr; points to last occupied heap location.
443 | HpLim -- Heap limit register
444 | CCCS -- Current cost-centre stack
445 | CurrentTSO -- pointer to current thread's TSO
446 | CurrentNursery -- pointer to allocation area
447 | HpAlloc -- allocation count for heap check failure
448
449 -- We keep the address of some commonly-called
450 -- functions in the register table, to keep code
451 -- size down:
452 | EagerBlackholeInfo -- stg_EAGER_BLACKHOLE_info
453 | GCEnter1 -- stg_gc_enter_1
454 | GCFun -- stg_gc_fun
455
456 -- Base offset for the register table, used for accessing registers
457 -- which do not have real registers assigned to them. This register
458 -- will only appear after we have expanded GlobalReg into memory accesses
459 -- (where necessary) in the native code generator.
460 | BaseReg
461
462 -- Base Register for PIC (position-independent code) calculations
463 -- Only used inside the native code generator. It's exact meaning differs
464 -- from platform to platform (see module PositionIndependentCode).
465 | PicBaseReg
466
467 deriving( Show )
468
469 instance Eq GlobalReg where
470 VanillaReg i _ == VanillaReg j _ = i==j -- Ignore type when seeking clashes
471 FloatReg i == FloatReg j = i==j
472 DoubleReg i == DoubleReg j = i==j
473 LongReg i == LongReg j = i==j
474 XmmReg i == XmmReg j = i==j
475 YmmReg i == YmmReg j = i==j
476 ZmmReg i == ZmmReg j = i==j
477 Sp == Sp = True
478 SpLim == SpLim = True
479 Hp == Hp = True
480 HpLim == HpLim = True
481 CCCS == CCCS = True
482 CurrentTSO == CurrentTSO = True
483 CurrentNursery == CurrentNursery = True
484 HpAlloc == HpAlloc = True
485 EagerBlackholeInfo == EagerBlackholeInfo = True
486 GCEnter1 == GCEnter1 = True
487 GCFun == GCFun = True
488 BaseReg == BaseReg = True
489 PicBaseReg == PicBaseReg = True
490 _r1 == _r2 = False
491
492 instance Ord GlobalReg where
493 compare (VanillaReg i _) (VanillaReg j _) = compare i j
494 -- Ignore type when seeking clashes
495 compare (FloatReg i) (FloatReg j) = compare i j
496 compare (DoubleReg i) (DoubleReg j) = compare i j
497 compare (LongReg i) (LongReg j) = compare i j
498 compare (XmmReg i) (XmmReg j) = compare i j
499 compare (YmmReg i) (YmmReg j) = compare i j
500 compare (ZmmReg i) (ZmmReg j) = compare i j
501 compare Sp Sp = EQ
502 compare SpLim SpLim = EQ
503 compare Hp Hp = EQ
504 compare HpLim HpLim = EQ
505 compare CCCS CCCS = EQ
506 compare CurrentTSO CurrentTSO = EQ
507 compare CurrentNursery CurrentNursery = EQ
508 compare HpAlloc HpAlloc = EQ
509 compare EagerBlackholeInfo EagerBlackholeInfo = EQ
510 compare GCEnter1 GCEnter1 = EQ
511 compare GCFun GCFun = EQ
512 compare BaseReg BaseReg = EQ
513 compare PicBaseReg PicBaseReg = EQ
514 compare (VanillaReg _ _) _ = LT
515 compare _ (VanillaReg _ _) = GT
516 compare (FloatReg _) _ = LT
517 compare _ (FloatReg _) = GT
518 compare (DoubleReg _) _ = LT
519 compare _ (DoubleReg _) = GT
520 compare (LongReg _) _ = LT
521 compare _ (LongReg _) = GT
522 compare (XmmReg _) _ = LT
523 compare _ (XmmReg _) = GT
524 compare (YmmReg _) _ = LT
525 compare _ (YmmReg _) = GT
526 compare (ZmmReg _) _ = LT
527 compare _ (ZmmReg _) = GT
528 compare Sp _ = LT
529 compare _ Sp = GT
530 compare SpLim _ = LT
531 compare _ SpLim = GT
532 compare Hp _ = LT
533 compare _ Hp = GT
534 compare HpLim _ = LT
535 compare _ HpLim = GT
536 compare CCCS _ = LT
537 compare _ CCCS = GT
538 compare CurrentTSO _ = LT
539 compare _ CurrentTSO = GT
540 compare CurrentNursery _ = LT
541 compare _ CurrentNursery = GT
542 compare HpAlloc _ = LT
543 compare _ HpAlloc = GT
544 compare GCEnter1 _ = LT
545 compare _ GCEnter1 = GT
546 compare GCFun _ = LT
547 compare _ GCFun = GT
548 compare BaseReg _ = LT
549 compare _ BaseReg = GT
550 compare EagerBlackholeInfo _ = LT
551 compare _ EagerBlackholeInfo = GT
552
553 -- convenient aliases
554 baseReg, spReg, hpReg, spLimReg, nodeReg :: CmmReg
555 baseReg = CmmGlobal BaseReg
556 spReg = CmmGlobal Sp
557 hpReg = CmmGlobal Hp
558 spLimReg = CmmGlobal SpLim
559 nodeReg = CmmGlobal node
560
561 node :: GlobalReg
562 node = VanillaReg 1 VGcPtr
563
564 globalRegType :: DynFlags -> GlobalReg -> CmmType
565 globalRegType dflags (VanillaReg _ VGcPtr) = gcWord dflags
566 globalRegType dflags (VanillaReg _ VNonGcPtr) = bWord dflags
567 globalRegType _ (FloatReg _) = cmmFloat W32
568 globalRegType _ (DoubleReg _) = cmmFloat W64
569 globalRegType _ (LongReg _) = cmmBits W64
570 globalRegType _ (XmmReg _) = cmmVec 4 (cmmBits W32)
571 globalRegType _ (YmmReg _) = cmmVec 8 (cmmBits W32)
572 globalRegType _ (ZmmReg _) = cmmVec 16 (cmmBits W32)
573
574 globalRegType dflags Hp = gcWord dflags
575 -- The initialiser for all
576 -- dynamically allocated closures
577 globalRegType dflags _ = bWord dflags
578
579 isArgReg :: GlobalReg -> Bool
580 isArgReg (VanillaReg {}) = True
581 isArgReg (FloatReg {}) = True
582 isArgReg (DoubleReg {}) = True
583 isArgReg (LongReg {}) = True
584 isArgReg (XmmReg {}) = True
585 isArgReg (YmmReg {}) = True
586 isArgReg (ZmmReg {}) = True
587 isArgReg _ = False