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