Honour -dsuppress-uniques more thoroughly
[ghc.git] / compiler / cmm / CmmExpr.hs
1 {-# LANGUAGE BangPatterns #-}
2 {-# LANGUAGE CPP #-}
3 {-# LANGUAGE FlexibleContexts #-}
4 {-# LANGUAGE FlexibleInstances #-}
5 {-# LANGUAGE MultiParamTypeClasses #-}
6 {-# LANGUAGE UndecidableInstances #-}
7
8 module CmmExpr
9 ( CmmExpr(..), cmmExprType, cmmExprWidth, maybeInvertCmmExpr
10 , CmmReg(..), cmmRegType
11 , CmmLit(..), cmmLitType
12 , LocalReg(..), localRegType
13 , GlobalReg(..), isArgReg, globalRegType, spReg, hpReg, spLimReg, nodeReg, node, baseReg
14 , VGcPtr(..)
15
16 , DefinerOfRegs, UserOfRegs
17 , foldRegsDefd, foldRegsUsed
18 , foldLocalRegsDefd, foldLocalRegsUsed
19
20 , RegSet, LocalRegSet, GlobalRegSet
21 , emptyRegSet, elemRegSet, extendRegSet, deleteFromRegSet, mkRegSet
22 , plusRegSet, minusRegSet, timesRegSet, sizeRegSet, nullRegSet
23 , regSetToList
24
25 , Area(..)
26 , module CmmMachOp
27 , module CmmType
28 )
29 where
30
31 import BlockId
32 import CLabel
33 import CmmMachOp
34 import CmmType
35 import DynFlags
36 import Outputable (panic)
37 import Unique
38
39 import Data.Set (Set)
40 import Data.List
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 -- This is non-deterministic but we do not currently support deterministic
254 -- code-generation. See Note [Unique Determinism and code generation]
255 -- See Note [No Ord for Unique]
256 instance Ord LocalReg where
257 compare (LocalReg u1 _) (LocalReg u2 _) = nonDetCmpUnique u1 u2
258
259 instance Uniquable LocalReg where
260 getUnique (LocalReg uniq _) = uniq
261
262 cmmRegType :: DynFlags -> CmmReg -> CmmType
263 cmmRegType _ (CmmLocal reg) = localRegType reg
264 cmmRegType dflags (CmmGlobal reg) = globalRegType dflags reg
265
266 localRegType :: LocalReg -> CmmType
267 localRegType (LocalReg _ rep) = rep
268
269 -----------------------------------------------------------------------------
270 -- Register-use information for expressions and other types
271 -----------------------------------------------------------------------------
272
273 -- | Sets of registers
274
275 -- These are used for dataflow facts, and a common operation is taking
276 -- the union of two RegSets and then asking whether the union is the
277 -- same as one of the inputs. UniqSet isn't good here, because
278 -- sizeUniqSet is O(n) whereas Set.size is O(1), so we use ordinary
279 -- Sets.
280
281 type RegSet r = Set r
282 type LocalRegSet = RegSet LocalReg
283 type GlobalRegSet = RegSet GlobalReg
284
285 emptyRegSet :: RegSet r
286 nullRegSet :: RegSet r -> Bool
287 elemRegSet :: Ord r => r -> RegSet r -> Bool
288 extendRegSet :: Ord r => RegSet r -> r -> RegSet r
289 deleteFromRegSet :: Ord r => RegSet r -> r -> RegSet r
290 mkRegSet :: Ord r => [r] -> RegSet r
291 minusRegSet, plusRegSet, timesRegSet :: Ord r => RegSet r -> RegSet r -> RegSet r
292 sizeRegSet :: RegSet r -> Int
293 regSetToList :: RegSet r -> [r]
294
295 emptyRegSet = Set.empty
296 nullRegSet = Set.null
297 elemRegSet = Set.member
298 extendRegSet = flip Set.insert
299 deleteFromRegSet = flip Set.delete
300 mkRegSet = Set.fromList
301 minusRegSet = Set.difference
302 plusRegSet = Set.union
303 timesRegSet = Set.intersection
304 sizeRegSet = Set.size
305 regSetToList = Set.toList
306
307 class Ord r => UserOfRegs r a where
308 foldRegsUsed :: DynFlags -> (b -> r -> b) -> b -> a -> b
309
310 foldLocalRegsUsed :: UserOfRegs LocalReg a
311 => DynFlags -> (b -> LocalReg -> b) -> b -> a -> b
312 foldLocalRegsUsed = foldRegsUsed
313
314 class Ord r => DefinerOfRegs r a where
315 foldRegsDefd :: DynFlags -> (b -> r -> b) -> b -> a -> b
316
317 foldLocalRegsDefd :: DefinerOfRegs LocalReg a
318 => DynFlags -> (b -> LocalReg -> b) -> b -> a -> b
319 foldLocalRegsDefd = foldRegsDefd
320
321 instance UserOfRegs LocalReg CmmReg where
322 foldRegsUsed _ f z (CmmLocal reg) = f z reg
323 foldRegsUsed _ _ z (CmmGlobal _) = z
324
325 instance DefinerOfRegs LocalReg CmmReg where
326 foldRegsDefd _ f z (CmmLocal reg) = f z reg
327 foldRegsDefd _ _ z (CmmGlobal _) = z
328
329 instance UserOfRegs GlobalReg CmmReg where
330 foldRegsUsed _ _ z (CmmLocal _) = z
331 foldRegsUsed _ f z (CmmGlobal reg) = f z reg
332
333 instance DefinerOfRegs GlobalReg CmmReg where
334 foldRegsDefd _ _ z (CmmLocal _) = z
335 foldRegsDefd _ f z (CmmGlobal reg) = f z reg
336
337 instance Ord r => UserOfRegs r r where
338 foldRegsUsed _ f z r = f z r
339
340 instance Ord r => DefinerOfRegs r r where
341 foldRegsDefd _ f z r = f z r
342
343 instance (Ord r, UserOfRegs r CmmReg) => UserOfRegs r CmmExpr where
344 -- The (Ord r) in the context is necessary here
345 -- See Note [Recursive superclasses] in TcInstDcls
346 foldRegsUsed dflags f !z e = expr z e
347 where expr z (CmmLit _) = z
348 expr z (CmmLoad addr _) = foldRegsUsed dflags f z addr
349 expr z (CmmReg r) = foldRegsUsed dflags f z r
350 expr z (CmmMachOp _ exprs) = foldRegsUsed dflags f z exprs
351 expr z (CmmRegOff r _) = foldRegsUsed dflags f z r
352 expr z (CmmStackSlot _ _) = z
353
354 instance UserOfRegs r a => UserOfRegs r [a] where
355 foldRegsUsed dflags f set as = foldl' (foldRegsUsed dflags f) set as
356 {-# INLINABLE foldRegsUsed #-}
357
358 instance DefinerOfRegs r a => DefinerOfRegs r [a] where
359 foldRegsDefd dflags f set as = foldl' (foldRegsDefd dflags f) set as
360 {-# INLINABLE foldRegsDefd #-}
361
362 -----------------------------------------------------------------------------
363 -- Global STG registers
364 -----------------------------------------------------------------------------
365
366 data VGcPtr = VGcPtr | VNonGcPtr deriving( Eq, Show )
367
368 -----------------------------------------------------------------------------
369 -- Global STG registers
370 -----------------------------------------------------------------------------
371 {-
372 Note [Overlapping global registers]
373
374 The backend might not faithfully implement the abstraction of the STG
375 machine with independent registers for different values of type
376 GlobalReg. Specifically, certain pairs of registers (r1, r2) may
377 overlap in the sense that a store to r1 invalidates the value in r2,
378 and vice versa.
379
380 Currently this occurs only on the x86_64 architecture where FloatReg n
381 and DoubleReg n are assigned the same microarchitectural register, in
382 order to allow functions to receive more Float# or Double# arguments
383 in registers (as opposed to on the stack).
384
385 There are no specific rules about which registers might overlap with
386 which other registers, but presumably it's safe to assume that nothing
387 will overlap with special registers like Sp or BaseReg.
388
389 Use CmmUtils.regsOverlap to determine whether two GlobalRegs overlap
390 on a particular platform. The instance Eq GlobalReg is syntactic
391 equality of STG registers and does not take overlap into
392 account. However it is still used in UserOfRegs/DefinerOfRegs and
393 there are likely still bugs there, beware!
394 -}
395
396 data GlobalReg
397 -- Argument and return registers
398 = VanillaReg -- pointers, unboxed ints and chars
399 {-# UNPACK #-} !Int -- its number
400 VGcPtr
401
402 | FloatReg -- single-precision floating-point registers
403 {-# UNPACK #-} !Int -- its number
404
405 | DoubleReg -- double-precision floating-point registers
406 {-# UNPACK #-} !Int -- its number
407
408 | LongReg -- long int registers (64-bit, really)
409 {-# UNPACK #-} !Int -- its number
410
411 | XmmReg -- 128-bit SIMD vector register
412 {-# UNPACK #-} !Int -- its number
413
414 | YmmReg -- 256-bit SIMD vector register
415 {-# UNPACK #-} !Int -- its number
416
417 | ZmmReg -- 512-bit SIMD vector register
418 {-# UNPACK #-} !Int -- its number
419
420 -- STG registers
421 | Sp -- Stack ptr; points to last occupied stack location.
422 | SpLim -- Stack limit
423 | Hp -- Heap ptr; points to last occupied heap location.
424 | HpLim -- Heap limit register
425 | CCCS -- Current cost-centre stack
426 | CurrentTSO -- pointer to current thread's TSO
427 | CurrentNursery -- pointer to allocation area
428 | HpAlloc -- allocation count for heap check failure
429
430 -- We keep the address of some commonly-called
431 -- functions in the register table, to keep code
432 -- size down:
433 | EagerBlackholeInfo -- stg_EAGER_BLACKHOLE_info
434 | GCEnter1 -- stg_gc_enter_1
435 | GCFun -- stg_gc_fun
436
437 -- Base offset for the register table, used for accessing registers
438 -- which do not have real registers assigned to them. This register
439 -- will only appear after we have expanded GlobalReg into memory accesses
440 -- (where necessary) in the native code generator.
441 | BaseReg
442
443 -- The register used by the platform for the C stack pointer. This is
444 -- a break in the STG abstraction used exclusively to setup stack unwinding
445 -- information.
446 | MachSp
447
448 -- The is a dummy register used to indicate to the stack unwinder where
449 -- a routine would return to.
450 | UnwindReturnReg
451
452 -- Base Register for PIC (position-independent code) calculations
453 -- Only used inside the native code generator. It's exact meaning differs
454 -- from platform to platform (see module PositionIndependentCode).
455 | PicBaseReg
456
457 deriving( Show )
458
459 instance Eq GlobalReg where
460 VanillaReg i _ == VanillaReg j _ = i==j -- Ignore type when seeking clashes
461 FloatReg i == FloatReg j = i==j
462 DoubleReg i == DoubleReg j = i==j
463 LongReg i == LongReg j = i==j
464 XmmReg i == XmmReg j = i==j
465 YmmReg i == YmmReg j = i==j
466 ZmmReg i == ZmmReg j = i==j
467 Sp == Sp = True
468 SpLim == SpLim = True
469 Hp == Hp = True
470 HpLim == HpLim = True
471 CCCS == CCCS = True
472 CurrentTSO == CurrentTSO = True
473 CurrentNursery == CurrentNursery = True
474 HpAlloc == HpAlloc = True
475 EagerBlackholeInfo == EagerBlackholeInfo = True
476 GCEnter1 == GCEnter1 = True
477 GCFun == GCFun = True
478 BaseReg == BaseReg = True
479 MachSp == MachSp = True
480 UnwindReturnReg == UnwindReturnReg = True
481 PicBaseReg == PicBaseReg = True
482 _r1 == _r2 = False
483
484 instance Ord GlobalReg where
485 compare (VanillaReg i _) (VanillaReg j _) = compare i j
486 -- Ignore type when seeking clashes
487 compare (FloatReg i) (FloatReg j) = compare i j
488 compare (DoubleReg i) (DoubleReg j) = compare i j
489 compare (LongReg i) (LongReg j) = compare i j
490 compare (XmmReg i) (XmmReg j) = compare i j
491 compare (YmmReg i) (YmmReg j) = compare i j
492 compare (ZmmReg i) (ZmmReg j) = compare i j
493 compare Sp Sp = EQ
494 compare SpLim SpLim = EQ
495 compare Hp Hp = EQ
496 compare HpLim HpLim = EQ
497 compare CCCS CCCS = EQ
498 compare CurrentTSO CurrentTSO = EQ
499 compare CurrentNursery CurrentNursery = EQ
500 compare HpAlloc HpAlloc = EQ
501 compare EagerBlackholeInfo EagerBlackholeInfo = EQ
502 compare GCEnter1 GCEnter1 = EQ
503 compare GCFun GCFun = EQ
504 compare BaseReg BaseReg = EQ
505 compare MachSp MachSp = EQ
506 compare UnwindReturnReg UnwindReturnReg = EQ
507 compare PicBaseReg PicBaseReg = EQ
508 compare (VanillaReg _ _) _ = LT
509 compare _ (VanillaReg _ _) = GT
510 compare (FloatReg _) _ = LT
511 compare _ (FloatReg _) = GT
512 compare (DoubleReg _) _ = LT
513 compare _ (DoubleReg _) = GT
514 compare (LongReg _) _ = LT
515 compare _ (LongReg _) = GT
516 compare (XmmReg _) _ = LT
517 compare _ (XmmReg _) = GT
518 compare (YmmReg _) _ = LT
519 compare _ (YmmReg _) = GT
520 compare (ZmmReg _) _ = LT
521 compare _ (ZmmReg _) = GT
522 compare Sp _ = LT
523 compare _ Sp = GT
524 compare SpLim _ = LT
525 compare _ SpLim = GT
526 compare Hp _ = LT
527 compare _ Hp = GT
528 compare HpLim _ = LT
529 compare _ HpLim = GT
530 compare CCCS _ = LT
531 compare _ CCCS = GT
532 compare CurrentTSO _ = LT
533 compare _ CurrentTSO = GT
534 compare CurrentNursery _ = LT
535 compare _ CurrentNursery = GT
536 compare HpAlloc _ = LT
537 compare _ HpAlloc = GT
538 compare GCEnter1 _ = LT
539 compare _ GCEnter1 = GT
540 compare GCFun _ = LT
541 compare _ GCFun = GT
542 compare BaseReg _ = LT
543 compare _ BaseReg = GT
544 compare MachSp _ = LT
545 compare _ MachSp = GT
546 compare UnwindReturnReg _ = LT
547 compare _ UnwindReturnReg = GT
548 compare EagerBlackholeInfo _ = LT
549 compare _ EagerBlackholeInfo = GT
550
551 -- convenient aliases
552 baseReg, spReg, hpReg, spLimReg, nodeReg :: CmmReg
553 baseReg = CmmGlobal BaseReg
554 spReg = CmmGlobal Sp
555 hpReg = CmmGlobal Hp
556 spLimReg = CmmGlobal SpLim
557 nodeReg = CmmGlobal node
558
559 node :: GlobalReg
560 node = VanillaReg 1 VGcPtr
561
562 globalRegType :: DynFlags -> GlobalReg -> CmmType
563 globalRegType dflags (VanillaReg _ VGcPtr) = gcWord dflags
564 globalRegType dflags (VanillaReg _ VNonGcPtr) = bWord dflags
565 globalRegType _ (FloatReg _) = cmmFloat W32
566 globalRegType _ (DoubleReg _) = cmmFloat W64
567 globalRegType _ (LongReg _) = cmmBits W64
568 globalRegType _ (XmmReg _) = cmmVec 4 (cmmBits W32)
569 globalRegType _ (YmmReg _) = cmmVec 8 (cmmBits W32)
570 globalRegType _ (ZmmReg _) = cmmVec 16 (cmmBits W32)
571
572 globalRegType dflags Hp = gcWord dflags
573 -- The initialiser for all
574 -- dynamically allocated closures
575 globalRegType dflags _ = bWord dflags
576
577 isArgReg :: GlobalReg -> Bool
578 isArgReg (VanillaReg {}) = True
579 isArgReg (FloatReg {}) = True
580 isArgReg (DoubleReg {}) = True
581 isArgReg (LongReg {}) = True
582 isArgReg (XmmReg {}) = True
583 isArgReg (YmmReg {}) = True
584 isArgReg (ZmmReg {}) = True
585 isArgReg _ = False