4 , b8, b16, b32, b64, f32, f64, bWord, bHalfWord, gcWord
7 , typeWidth, cmmEqType, cmmEqType_ignoring_ptrhood
8 , isFloatType, isGcPtrType, isWord32, isWord64, isFloat64, isFloat32
11 , widthInBits, widthInBytes, widthInLog, widthFromBytes
12 , wordWidth, halfWordWidth, cIntWidth, cLongWidth
15 , CmmExpr(..), cmmExprType, cmmExprWidth, maybeInvertCmmExpr
16 , CmmReg(..), cmmRegType
17 , CmmLit(..), cmmLitType
18 , LocalReg(..), localRegType
19 , GlobalReg(..), globalRegType, spReg, hpReg, spLimReg, nodeReg, node
20 , VGcPtr(..), vgcFlag -- Temporary!
21 , DefinerOfLocalRegs, UserOfLocalRegs, foldRegsDefd, foldRegsUsed, filterRegsUsed
22 , DefinerOfSlots, UserOfSlots, foldSlotsDefd, foldSlotsUsed
23 , RegSet, emptyRegSet, elemRegSet, extendRegSet, deleteFromRegSet, mkRegSet
24 , plusRegSet, minusRegSet, timesRegSet
26 , Area(..), AreaId(..), SubArea, SubAreaSet, AreaMap, isStackSlotOf
30 , pprMachOp, isCommutableMachOp, isAssociativeMachOp
31 , isComparisonMachOp, machOpResultType
32 , machOpArgReps, maybeInvertComparison
35 , mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
36 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
37 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
38 , mo_wordULe, mo_wordUGt, mo_wordULt
39 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
40 , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
41 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
42 , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32
46 #include "HsVersions.h"
60 -----------------------------------------------------------------------------
62 -- An expression. Expressions have no side effects.
63 -----------------------------------------------------------------------------
66 = CmmLit CmmLit -- Literal
67 | CmmLoad CmmExpr CmmType -- Read memory location
68 | CmmReg CmmReg -- Contents of register
69 | CmmMachOp MachOp [CmmExpr] -- Machine operation (+, -, *, etc.)
70 | CmmStackSlot Area Int -- addressing expression of a stack slot
71 | CmmRegOff CmmReg Int
73 -- ** is shorthand only, meaning **
74 -- CmmMachOp (MO_S_Add rep (CmmReg reg) (CmmLit (CmmInt i rep)))
75 -- where rep = cmmRegType reg
77 instance Eq CmmExpr where -- Equality ignores the types
78 CmmLit l1 == CmmLit l2 = l1==l2
79 CmmLoad e1 _ == CmmLoad e2 _ = e1==e2
80 CmmReg r1 == CmmReg r2 = r1==r2
81 CmmRegOff r1 i1 == CmmRegOff r2 i2 = r1==r2 && i1==i2
82 CmmMachOp op1 es1 == CmmMachOp op2 es2 = op1==op2 && es1==es2
83 CmmStackSlot a1 i1 == CmmStackSlot a2 i2 = a1==a2 && i1==i2
91 -- | A stack area is either the stack slot where a variable is spilled
92 -- or the stack space where function arguments and results are passed.
99 = Old -- See Note [Old Area]
105 There is a single call area 'Old', allocated at the extreme old
106 end of the stack frame (ie just younger than the return address)
108 * incoming (overflow) parameters,
109 * outgoing (overflow) parameter to tail calls,
110 * outgoing (overflow) result values
111 * the update frame (if any)
113 Its size is the max of all these requirements. On entry, the stack
114 pointer will point to the youngest incoming parameter, which is not
115 necessarily at the young end of the Old area.
119 type SubArea = (Area, Int, Int) -- area, offset, width
120 type SubAreaSet = FiniteMap Area [SubArea]
122 type AreaMap = FiniteMap Area Int
123 -- Byte offset of the oldest byte of the Area,
124 -- relative to the oldest byte of the Old Area
127 = CmmInt Integer Width
128 -- Interpretation: the 2's complement representation of the value
129 -- is truncated to the specified size. This is easier than trying
130 -- to keep the value within range, because we don't know whether
131 -- it will be used as a signed or unsigned value (the CmmType doesn't
132 -- distinguish between signed & unsigned).
133 | CmmFloat Rational Width
134 | CmmLabel CLabel -- Address of label
135 | CmmLabelOff CLabel Int -- Address of label + byte offset
137 -- Due to limitations in the C backend, the following
138 -- MUST ONLY be used inside the info table indicated by label2
139 -- (label2 must be the info label), and label1 must be an
140 -- SRT, a slow entrypoint or a large bitmap (see the Mangler)
141 -- Don't use it at all unless tablesNextToCode.
142 -- It is also used inside the NCG during when generating
143 -- position-independent code.
144 | CmmLabelDiffOff CLabel CLabel Int -- label1 - label2 + offset
145 | CmmBlock BlockId -- Code label
146 | CmmHighStackMark -- stands for the max stack space used during a procedure
149 cmmExprType :: CmmExpr -> CmmType
150 cmmExprType (CmmLit lit) = cmmLitType lit
151 cmmExprType (CmmLoad _ rep) = rep
152 cmmExprType (CmmReg reg) = cmmRegType reg
153 cmmExprType (CmmMachOp op args) = machOpResultType op (map cmmExprType args)
154 cmmExprType (CmmRegOff reg _) = cmmRegType reg
155 cmmExprType (CmmStackSlot _ _) = bWord -- an address
157 cmmLitType :: CmmLit -> CmmType
158 cmmLitType (CmmInt _ width) = cmmBits width
159 cmmLitType (CmmFloat _ width) = cmmFloat width
160 cmmLitType (CmmLabel lbl) = cmmLabelType lbl
161 cmmLitType (CmmLabelOff lbl _) = cmmLabelType lbl
162 cmmLitType (CmmLabelDiffOff {}) = bWord
163 cmmLitType (CmmBlock _) = bWord
164 cmmLitType (CmmHighStackMark) = bWord
166 cmmLabelType :: CLabel -> CmmType
167 cmmLabelType lbl | isGcPtrLabel lbl = gcWord
170 cmmExprWidth :: CmmExpr -> Width
171 cmmExprWidth e = typeWidth (cmmExprType e)
174 --- Negation for conditional branches
176 maybeInvertCmmExpr :: CmmExpr -> Maybe CmmExpr
177 maybeInvertCmmExpr (CmmMachOp op args) = do op' <- maybeInvertComparison op
178 return (CmmMachOp op' args)
179 maybeInvertCmmExpr _ = Nothing
181 -----------------------------------------------------------------------------
183 -----------------------------------------------------------------------------
186 = LocalReg !Unique CmmType
191 instance Eq LocalReg where
192 (LocalReg u1 _) == (LocalReg u2 _) = u1 == u2
194 instance Ord LocalReg where
195 compare (LocalReg u1 _) (LocalReg u2 _) = compare u1 u2
197 instance Uniquable LocalReg where
198 getUnique (LocalReg uniq _) = uniq
200 cmmRegType :: CmmReg -> CmmType
201 cmmRegType (CmmLocal reg) = localRegType reg
202 cmmRegType (CmmGlobal reg) = globalRegType reg
204 localRegType :: LocalReg -> CmmType
205 localRegType (LocalReg _ rep) = rep
207 -----------------------------------------------------------------------------
208 -- Register-use information for expressions and other types
209 -----------------------------------------------------------------------------
211 -- | Sets of local registers
212 type RegSet = UniqSet LocalReg
213 emptyRegSet :: RegSet
214 elemRegSet :: LocalReg -> RegSet -> Bool
215 extendRegSet :: RegSet -> LocalReg -> RegSet
216 deleteFromRegSet :: RegSet -> LocalReg -> RegSet
217 mkRegSet :: [LocalReg] -> RegSet
218 minusRegSet, plusRegSet, timesRegSet :: RegSet -> RegSet -> RegSet
220 emptyRegSet = emptyUniqSet
221 elemRegSet = elementOfUniqSet
222 extendRegSet = addOneToUniqSet
223 deleteFromRegSet = delOneFromUniqSet
225 minusRegSet = minusUniqSet
226 plusRegSet = unionUniqSets
227 timesRegSet = intersectUniqSets
229 class UserOfLocalRegs a where
230 foldRegsUsed :: (b -> LocalReg -> b) -> b -> a -> b
232 class DefinerOfLocalRegs a where
233 foldRegsDefd :: (b -> LocalReg -> b) -> b -> a -> b
235 filterRegsUsed :: UserOfLocalRegs e => (LocalReg -> Bool) -> e -> RegSet
237 foldRegsUsed (\regs r -> if p r then extendRegSet regs r else regs)
240 instance UserOfLocalRegs CmmReg where
241 foldRegsUsed f z (CmmLocal reg) = f z reg
242 foldRegsUsed _ z (CmmGlobal _) = z
244 instance DefinerOfLocalRegs CmmReg where
245 foldRegsDefd f z (CmmLocal reg) = f z reg
246 foldRegsDefd _ z (CmmGlobal _) = z
248 instance UserOfLocalRegs LocalReg where
249 foldRegsUsed f z r = f z r
251 instance DefinerOfLocalRegs LocalReg where
252 foldRegsDefd f z r = f z r
254 instance UserOfLocalRegs RegSet where
255 foldRegsUsed f = foldUniqSet (flip f)
257 instance UserOfLocalRegs CmmExpr where
258 foldRegsUsed f z e = expr z e
259 where expr z (CmmLit _) = z
260 expr z (CmmLoad addr _) = foldRegsUsed f z addr
261 expr z (CmmReg r) = foldRegsUsed f z r
262 expr z (CmmMachOp _ exprs) = foldRegsUsed f z exprs
263 expr z (CmmRegOff r _) = foldRegsUsed f z r
264 expr z (CmmStackSlot _ _) = z
266 instance UserOfLocalRegs a => UserOfLocalRegs [a] where
267 foldRegsUsed _ set [] = set
268 foldRegsUsed f set (x:xs) = foldRegsUsed f (foldRegsUsed f set x) xs
270 instance DefinerOfLocalRegs a => DefinerOfLocalRegs [a] where
271 foldRegsDefd _ set [] = set
272 foldRegsDefd f set (x:xs) = foldRegsDefd f (foldRegsDefd f set x) xs
274 instance DefinerOfLocalRegs a => DefinerOfLocalRegs (Maybe a) where
275 foldRegsDefd _ set Nothing = set
276 foldRegsDefd f set (Just x) = foldRegsDefd f set x
278 -----------------------------------------------------------------------------
279 -- Another reg utility
281 regUsedIn :: CmmReg -> CmmExpr -> Bool
282 _ `regUsedIn` CmmLit _ = False
283 reg `regUsedIn` CmmLoad e _ = reg `regUsedIn` e
284 reg `regUsedIn` CmmReg reg' = reg == reg'
285 reg `regUsedIn` CmmRegOff reg' _ = reg == reg'
286 reg `regUsedIn` CmmMachOp _ es = any (reg `regUsedIn`) es
287 _ `regUsedIn` CmmStackSlot _ _ = False
289 -----------------------------------------------------------------------------
291 -----------------------------------------------------------------------------
293 isStackSlotOf :: CmmExpr -> LocalReg -> Bool
294 isStackSlotOf (CmmStackSlot (RegSlot r) _) r' = r == r'
295 isStackSlotOf _ _ = False
297 -----------------------------------------------------------------------------
298 -- Stack slot use information for expressions and other types [_$_]
299 -----------------------------------------------------------------------------
301 -- Fold over the area, the offset into the area, and the width of the subarea.
302 class UserOfSlots a where
303 foldSlotsUsed :: (b -> SubArea -> b) -> b -> a -> b
305 class DefinerOfSlots a where
306 foldSlotsDefd :: (b -> SubArea -> b) -> b -> a -> b
308 instance UserOfSlots CmmExpr where
309 foldSlotsUsed f z e = expr z e
310 where expr z (CmmLit _) = z
311 expr z (CmmLoad (CmmStackSlot a i) ty) = f z (a, i, widthInBytes $ typeWidth ty)
312 expr z (CmmLoad addr _) = foldSlotsUsed f z addr
313 expr z (CmmReg _) = z
314 expr z (CmmMachOp _ exprs) = foldSlotsUsed f z exprs
315 expr z (CmmRegOff _ _) = z
316 expr z (CmmStackSlot _ _) = z
318 instance UserOfSlots a => UserOfSlots [a] where
319 foldSlotsUsed _ set [] = set
320 foldSlotsUsed f set (x:xs) = foldSlotsUsed f (foldSlotsUsed f set x) xs
323 -----------------------------------------------------------------------------
324 -- Global STG registers
325 -----------------------------------------------------------------------------
327 data VGcPtr = VGcPtr | VNonGcPtr deriving( Eq, Show )
330 -----------------------------------------------------------------------------
331 -- Global STG registers
332 -----------------------------------------------------------------------------
333 vgcFlag :: CmmType -> VGcPtr
334 vgcFlag ty | isGcPtrType ty = VGcPtr
335 | otherwise = VNonGcPtr
338 -- Argument and return registers
339 = VanillaReg -- pointers, unboxed ints and chars
340 {-# UNPACK #-} !Int -- its number
343 | FloatReg -- single-precision floating-point registers
344 {-# UNPACK #-} !Int -- its number
346 | DoubleReg -- double-precision floating-point registers
347 {-# UNPACK #-} !Int -- its number
349 | LongReg -- long int registers (64-bit, really)
350 {-# UNPACK #-} !Int -- its number
353 | Sp -- Stack ptr; points to last occupied stack location.
354 | SpLim -- Stack limit
355 | Hp -- Heap ptr; points to last occupied heap location.
356 | HpLim -- Heap limit register
357 | CurrentTSO -- pointer to current thread's TSO
358 | CurrentNursery -- pointer to allocation area
359 | HpAlloc -- allocation count for heap check failure
361 -- We keep the address of some commonly-called
362 -- functions in the register table, to keep code
364 | EagerBlackholeInfo -- stg_EAGER_BLACKHOLE_info
365 | GCEnter1 -- stg_gc_enter_1
366 | GCFun -- stg_gc_fun
368 -- Base offset for the register table, used for accessing registers
369 -- which do not have real registers assigned to them. This register
370 -- will only appear after we have expanded GlobalReg into memory accesses
371 -- (where necessary) in the native code generator.
374 -- Base Register for PIC (position-independent code) calculations
375 -- Only used inside the native code generator. It's exact meaning differs
376 -- from platform to platform (see module PositionIndependentCode).
381 instance Eq GlobalReg where
382 VanillaReg i _ == VanillaReg j _ = i==j -- Ignore type when seeking clashes
383 FloatReg i == FloatReg j = i==j
384 DoubleReg i == DoubleReg j = i==j
385 LongReg i == LongReg j = i==j
387 SpLim == SpLim = True
389 HpLim == HpLim = True
390 CurrentTSO == CurrentTSO = True
391 CurrentNursery == CurrentNursery = True
392 HpAlloc == HpAlloc = True
393 GCEnter1 == GCEnter1 = True
394 GCFun == GCFun = True
395 BaseReg == BaseReg = True
396 PicBaseReg == PicBaseReg = True
399 instance Ord GlobalReg where
400 compare (VanillaReg i _) (VanillaReg j _) = compare i j
401 -- Ignore type when seeking clashes
402 compare (FloatReg i) (FloatReg j) = compare i j
403 compare (DoubleReg i) (DoubleReg j) = compare i j
404 compare (LongReg i) (LongReg j) = compare i j
406 compare SpLim SpLim = EQ
408 compare HpLim HpLim = EQ
409 compare CurrentTSO CurrentTSO = EQ
410 compare CurrentNursery CurrentNursery = EQ
411 compare HpAlloc HpAlloc = EQ
412 compare EagerBlackholeInfo EagerBlackholeInfo = EQ
413 compare GCEnter1 GCEnter1 = EQ
414 compare GCFun GCFun = EQ
415 compare BaseReg BaseReg = EQ
416 compare PicBaseReg PicBaseReg = EQ
417 compare (VanillaReg _ _) _ = LT
418 compare _ (VanillaReg _ _) = GT
419 compare (FloatReg _) _ = LT
420 compare _ (FloatReg _) = GT
421 compare (DoubleReg _) _ = LT
422 compare _ (DoubleReg _) = GT
423 compare (LongReg _) _ = LT
424 compare _ (LongReg _) = GT
433 compare CurrentTSO _ = LT
434 compare _ CurrentTSO = GT
435 compare CurrentNursery _ = LT
436 compare _ CurrentNursery = GT
437 compare HpAlloc _ = LT
438 compare _ HpAlloc = GT
439 compare GCEnter1 _ = LT
440 compare _ GCEnter1 = GT
443 compare BaseReg _ = LT
444 compare _ BaseReg = GT
445 compare EagerBlackholeInfo _ = LT
446 compare _ EagerBlackholeInfo = GT
448 -- convenient aliases
449 spReg, hpReg, spLimReg, nodeReg :: CmmReg
452 spLimReg = CmmGlobal SpLim
453 nodeReg = CmmGlobal node
456 node = VanillaReg 1 VGcPtr
458 globalRegType :: GlobalReg -> CmmType
459 globalRegType (VanillaReg _ VGcPtr) = gcWord
460 globalRegType (VanillaReg _ VNonGcPtr) = bWord
461 globalRegType (FloatReg _) = cmmFloat W32
462 globalRegType (DoubleReg _) = cmmFloat W64
463 globalRegType (LongReg _) = cmmBits W64
464 globalRegType Hp = gcWord -- The initialiser for all
465 -- dynamically allocated closures
466 globalRegType _ = bWord
469 -----------------------------------------------------------------------------
471 -----------------------------------------------------------------------------
473 -- NOTE: CmmType is an abstract type, not exported from this
474 -- module so you can easily change its representation
476 -- However Width is exported in a concrete way,
477 -- and is used extensively in pattern-matching
479 data CmmType -- The important one!
480 = CmmType CmmCat Width
482 data CmmCat -- "Category" (not exported)
483 = GcPtrCat -- GC pointer
484 | BitsCat -- Non-pointer
487 -- See Note [Signed vs unsigned] at the end
489 instance Outputable CmmType where
490 ppr (CmmType cat wid) = ppr cat <> ppr (widthInBits wid)
492 instance Outputable CmmCat where
493 ppr FloatCat = ptext $ sLit("F")
494 ppr _ = ptext $ sLit("I")
496 -- ppr FloatCat = ptext $ sLit("float")
497 -- ppr BitsCat = ptext $ sLit("bits")
498 -- ppr GcPtrCat = ptext $ sLit("gcptr")
500 -- Why is CmmType stratified? For native code generation,
501 -- most of the time you just want to know what sort of register
502 -- to put the thing in, and for this you need to know how
503 -- many bits thing has and whether it goes in a floating-point
504 -- register. By contrast, the distinction between GcPtr and
505 -- GcNonPtr is of interest to only a few parts of the code generator.
507 -------- Equality on CmmType --------------
508 -- CmmType is *not* an instance of Eq; sometimes we care about the
509 -- Gc/NonGc distinction, and sometimes we don't
510 -- So we use an explicit function to force you to think about it
511 cmmEqType :: CmmType -> CmmType -> Bool -- Exact equality
512 cmmEqType (CmmType c1 w1) (CmmType c2 w2) = c1==c2 && w1==w2
514 cmmEqType_ignoring_ptrhood :: CmmType -> CmmType -> Bool
515 -- This equality is temporary; used in CmmLint
516 -- but the RTS files are not yet well-typed wrt pointers
517 cmmEqType_ignoring_ptrhood (CmmType c1 w1) (CmmType c2 w2)
518 = c1 `weak_eq` c2 && w1==w2
520 FloatCat `weak_eq` FloatCat = True
521 FloatCat `weak_eq` _other = False
522 _other `weak_eq` FloatCat = False
523 _word1 `weak_eq` _word2 = True -- Ignores GcPtr
525 --- Simple operations on CmmType -----
526 typeWidth :: CmmType -> Width
527 typeWidth (CmmType _ w) = w
529 cmmBits, cmmFloat :: Width -> CmmType
530 cmmBits = CmmType BitsCat
531 cmmFloat = CmmType FloatCat
533 -------- Common CmmTypes ------------
534 -- Floats and words of specific widths
535 b8, b16, b32, b64, f32, f64 :: CmmType
543 -- CmmTypes of native word widths
544 bWord, bHalfWord, gcWord :: CmmType
545 bWord = cmmBits wordWidth
546 bHalfWord = cmmBits halfWordWidth
547 gcWord = CmmType GcPtrCat wordWidth
549 cInt, cLong :: CmmType
550 cInt = cmmBits cIntWidth
551 cLong = cmmBits cLongWidth
554 ------------ Predicates ----------------
555 isFloatType, isGcPtrType :: CmmType -> Bool
556 isFloatType (CmmType FloatCat _) = True
557 isFloatType _other = False
559 isGcPtrType (CmmType GcPtrCat _) = True
560 isGcPtrType _other = False
562 isWord32, isWord64, isFloat32, isFloat64 :: CmmType -> Bool
563 -- isWord64 is true of 64-bit non-floats (both gc-ptrs and otherwise)
564 -- isFloat32 and 64 are obvious
566 isWord64 (CmmType BitsCat W64) = True
567 isWord64 (CmmType GcPtrCat W64) = True
568 isWord64 _other = False
570 isWord32 (CmmType BitsCat W32) = True
571 isWord32 (CmmType GcPtrCat W32) = True
572 isWord32 _other = False
574 isFloat32 (CmmType FloatCat W32) = True
575 isFloat32 _other = False
577 isFloat64 (CmmType FloatCat W64) = True
578 isFloat64 _other = False
580 -----------------------------------------------------------------------------
582 -----------------------------------------------------------------------------
584 data Width = W8 | W16 | W32 | W64
585 | W80 -- Extended double-precision float,
586 -- used in x86 native codegen only.
587 -- (we use Ord, so it'd better be in this order)
589 deriving (Eq, Ord, Show)
591 instance Outputable Width where
592 ppr rep = ptext (mrStr rep)
594 mrStr :: Width -> LitString
595 mrStr W8 = sLit("W8")
596 mrStr W16 = sLit("W16")
597 mrStr W32 = sLit("W32")
598 mrStr W64 = sLit("W64")
599 mrStr W128 = sLit("W128")
600 mrStr W80 = sLit("W80")
603 -------- Common Widths ------------
604 wordWidth, halfWordWidth :: Width
605 wordWidth | wORD_SIZE == 4 = W32
606 | wORD_SIZE == 8 = W64
607 | otherwise = panic "MachOp.wordRep: Unknown word size"
609 halfWordWidth | wORD_SIZE == 4 = W16
610 | wORD_SIZE == 8 = W32
611 | otherwise = panic "MachOp.halfWordRep: Unknown word size"
613 -- cIntRep is the Width for a C-language 'int'
614 cIntWidth, cLongWidth :: Width
617 #elif SIZEOF_INT == 8
623 #elif SIZEOF_LONG == 8
627 widthInBits :: Width -> Int
632 widthInBits W128 = 128
635 widthInBytes :: Width -> Int
640 widthInBytes W128 = 16
641 widthInBytes W80 = 10
643 widthFromBytes :: Int -> Width
644 widthFromBytes 1 = W8
645 widthFromBytes 2 = W16
646 widthFromBytes 4 = W32
647 widthFromBytes 8 = W64
648 widthFromBytes 16 = W128
649 widthFromBytes 10 = W80
650 widthFromBytes n = pprPanic "no width for given number of bytes" (ppr n)
652 -- log_2 of the width in bytes, useful for generating shifts.
653 widthInLog :: Width -> Int
659 widthInLog W80 = panic "widthInLog: F80"
661 -- widening / narrowing
663 narrowU :: Width -> Integer -> Integer
664 narrowU W8 x = fromIntegral (fromIntegral x :: Word8)
665 narrowU W16 x = fromIntegral (fromIntegral x :: Word16)
666 narrowU W32 x = fromIntegral (fromIntegral x :: Word32)
667 narrowU W64 x = fromIntegral (fromIntegral x :: Word64)
668 narrowU _ _ = panic "narrowTo"
670 narrowS :: Width -> Integer -> Integer
671 narrowS W8 x = fromIntegral (fromIntegral x :: Int8)
672 narrowS W16 x = fromIntegral (fromIntegral x :: Int16)
673 narrowS W32 x = fromIntegral (fromIntegral x :: Int32)
674 narrowS W64 x = fromIntegral (fromIntegral x :: Int64)
675 narrowS _ _ = panic "narrowTo"
677 -----------------------------------------------------------------------------
679 -----------------------------------------------------------------------------
682 Implementation notes:
684 It might suffice to keep just a width, without distinguishing between
685 floating and integer types. However, keeping the distinction will
686 help the native code generator to assign registers more easily.
691 Machine-level primops; ones which we can reasonably delegate to the
692 native code generators to handle. Basically contains C's primops
695 Nomenclature: all ops indicate width and signedness, where
696 appropriate. Widths: 8\/16\/32\/64 means the given size, obviously.
697 Nat means the operation works on STG word sized objects.
698 Signedness: S means signed, U means unsigned. For operations where
699 signedness is irrelevant or makes no difference (for example
700 integer add), the signedness component is omitted.
702 An exception: NatP is a ptr-typed native word. From the point of
703 view of the native code generators this distinction is irrelevant,
704 but the C code generator sometimes needs this info to emit the
709 -- Integer operations (insensitive to signed/unsigned)
714 | MO_Mul Width -- low word of multiply
716 -- Signed multiply/divide
717 | MO_S_MulMayOflo Width -- nonzero if signed multiply overflows
718 | MO_S_Quot Width -- signed / (same semantics as IntQuotOp)
719 | MO_S_Rem Width -- signed % (same semantics as IntRemOp)
720 | MO_S_Neg Width -- unary -
722 -- Unsigned multiply/divide
723 | MO_U_MulMayOflo Width -- nonzero if unsigned multiply overflows
724 | MO_U_Quot Width -- unsigned / (same semantics as WordQuotOp)
725 | MO_U_Rem Width -- unsigned % (same semantics as WordRemOp)
727 -- Signed comparisons
733 -- Unsigned comparisons
739 -- Floating point arithmetic
742 | MO_F_Neg Width -- unary -
746 -- Floating point comparison
754 -- Bitwise operations. Not all of these may be supported
755 -- at all sizes, and only integral Widths are valid.
761 | MO_U_Shr Width -- unsigned shift right
762 | MO_S_Shr Width -- signed shift right
764 -- Conversions. Some of these will be NOPs.
765 -- Floating-point conversions use the signed variant.
766 | MO_SF_Conv Width Width -- Signed int -> Float
767 | MO_FS_Conv Width Width -- Float -> Signed int
768 | MO_SS_Conv Width Width -- Signed int -> Signed int
769 | MO_UU_Conv Width Width -- unsigned int -> unsigned int
770 | MO_FF_Conv Width Width -- Float -> Float
773 pprMachOp :: MachOp -> SDoc
774 pprMachOp mo = text (show mo)
778 -- -----------------------------------------------------------------------------
779 -- Some common MachReps
781 -- A 'wordRep' is a machine word on the target architecture
782 -- Specifically, it is the size of an Int#, Word#, Addr#
783 -- and the unit of allocation on the stack and the heap
784 -- Any pointer is also guaranteed to be a wordRep.
786 mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
787 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
788 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
789 , mo_wordULe, mo_wordUGt, mo_wordULt
790 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
791 , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
792 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
793 , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32
796 mo_wordAdd = MO_Add wordWidth
797 mo_wordSub = MO_Sub wordWidth
798 mo_wordEq = MO_Eq wordWidth
799 mo_wordNe = MO_Ne wordWidth
800 mo_wordMul = MO_Mul wordWidth
801 mo_wordSQuot = MO_S_Quot wordWidth
802 mo_wordSRem = MO_S_Rem wordWidth
803 mo_wordSNeg = MO_S_Neg wordWidth
804 mo_wordUQuot = MO_U_Quot wordWidth
805 mo_wordURem = MO_U_Rem wordWidth
807 mo_wordSGe = MO_S_Ge wordWidth
808 mo_wordSLe = MO_S_Le wordWidth
809 mo_wordSGt = MO_S_Gt wordWidth
810 mo_wordSLt = MO_S_Lt wordWidth
812 mo_wordUGe = MO_U_Ge wordWidth
813 mo_wordULe = MO_U_Le wordWidth
814 mo_wordUGt = MO_U_Gt wordWidth
815 mo_wordULt = MO_U_Lt wordWidth
817 mo_wordAnd = MO_And wordWidth
818 mo_wordOr = MO_Or wordWidth
819 mo_wordXor = MO_Xor wordWidth
820 mo_wordNot = MO_Not wordWidth
821 mo_wordShl = MO_Shl wordWidth
822 mo_wordSShr = MO_S_Shr wordWidth
823 mo_wordUShr = MO_U_Shr wordWidth
825 mo_u_8To32 = MO_UU_Conv W8 W32
826 mo_s_8To32 = MO_SS_Conv W8 W32
827 mo_u_16To32 = MO_UU_Conv W16 W32
828 mo_s_16To32 = MO_SS_Conv W16 W32
830 mo_u_8ToWord = MO_UU_Conv W8 wordWidth
831 mo_s_8ToWord = MO_SS_Conv W8 wordWidth
832 mo_u_16ToWord = MO_UU_Conv W16 wordWidth
833 mo_s_16ToWord = MO_SS_Conv W16 wordWidth
834 mo_s_32ToWord = MO_SS_Conv W32 wordWidth
835 mo_u_32ToWord = MO_UU_Conv W32 wordWidth
837 mo_WordTo8 = MO_UU_Conv wordWidth W8
838 mo_WordTo16 = MO_UU_Conv wordWidth W16
839 mo_WordTo32 = MO_UU_Conv wordWidth W32
841 mo_32To8 = MO_UU_Conv W32 W8
842 mo_32To16 = MO_UU_Conv W32 W16
845 -- ----------------------------------------------------------------------------
846 -- isCommutableMachOp
849 Returns 'True' if the MachOp has commutable arguments. This is used
850 in the platform-independent Cmm optimisations.
852 If in doubt, return 'False'. This generates worse code on the
853 native routes, but is otherwise harmless.
855 isCommutableMachOp :: MachOp -> Bool
856 isCommutableMachOp mop =
862 MO_S_MulMayOflo _ -> True
863 MO_U_MulMayOflo _ -> True
869 -- ----------------------------------------------------------------------------
870 -- isAssociativeMachOp
873 Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
874 This is used in the platform-independent Cmm optimisations.
876 If in doubt, return 'False'. This generates worse code on the
877 native routes, but is otherwise harmless.
879 isAssociativeMachOp :: MachOp -> Bool
880 isAssociativeMachOp mop =
882 MO_Add {} -> True -- NB: does not include
883 MO_Mul {} -> True -- floatint point!
889 -- ----------------------------------------------------------------------------
890 -- isComparisonMachOp
893 Returns 'True' if the MachOp is a comparison.
895 If in doubt, return False. This generates worse code on the
896 native routes, but is otherwise harmless.
898 isComparisonMachOp :: MachOp -> Bool
899 isComparisonMachOp mop =
919 -- -----------------------------------------------------------------------------
920 -- Inverting conditions
922 -- Sometimes it's useful to be able to invert the sense of a
923 -- condition. Not all conditional tests are invertible: in
924 -- particular, floating point conditionals cannot be inverted, because
925 -- there exist floating-point values which return False for both senses
926 -- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).
928 maybeInvertComparison :: MachOp -> Maybe MachOp
929 maybeInvertComparison op
930 = case op of -- None of these Just cases include floating point
931 MO_Eq r -> Just (MO_Ne r)
932 MO_Ne r -> Just (MO_Eq r)
933 MO_U_Lt r -> Just (MO_U_Ge r)
934 MO_U_Gt r -> Just (MO_U_Le r)
935 MO_U_Le r -> Just (MO_U_Gt r)
936 MO_U_Ge r -> Just (MO_U_Lt r)
937 MO_S_Lt r -> Just (MO_S_Ge r)
938 MO_S_Gt r -> Just (MO_S_Le r)
939 MO_S_Le r -> Just (MO_S_Gt r)
940 MO_S_Ge r -> Just (MO_S_Lt r)
941 MO_F_Eq r -> Just (MO_F_Ne r)
942 MO_F_Ne r -> Just (MO_F_Eq r)
943 MO_F_Ge r -> Just (MO_F_Le r)
944 MO_F_Le r -> Just (MO_F_Ge r)
945 MO_F_Gt r -> Just (MO_F_Lt r)
946 MO_F_Lt r -> Just (MO_F_Gt r)
949 -- ----------------------------------------------------------------------------
953 Returns the MachRep of the result of a MachOp.
955 machOpResultType :: MachOp -> [CmmType] -> CmmType
956 machOpResultType mop tys =
958 MO_Add {} -> ty1 -- Preserve GC-ptr-hood
959 MO_Sub {} -> ty1 -- of first arg
960 MO_Mul r -> cmmBits r
961 MO_S_MulMayOflo r -> cmmBits r
962 MO_S_Quot r -> cmmBits r
963 MO_S_Rem r -> cmmBits r
964 MO_S_Neg r -> cmmBits r
965 MO_U_MulMayOflo r -> cmmBits r
966 MO_U_Quot r -> cmmBits r
967 MO_U_Rem r -> cmmBits r
969 MO_Eq {} -> comparisonResultRep
970 MO_Ne {} -> comparisonResultRep
971 MO_S_Ge {} -> comparisonResultRep
972 MO_S_Le {} -> comparisonResultRep
973 MO_S_Gt {} -> comparisonResultRep
974 MO_S_Lt {} -> comparisonResultRep
976 MO_U_Ge {} -> comparisonResultRep
977 MO_U_Le {} -> comparisonResultRep
978 MO_U_Gt {} -> comparisonResultRep
979 MO_U_Lt {} -> comparisonResultRep
981 MO_F_Add r -> cmmFloat r
982 MO_F_Sub r -> cmmFloat r
983 MO_F_Mul r -> cmmFloat r
984 MO_F_Quot r -> cmmFloat r
985 MO_F_Neg r -> cmmFloat r
986 MO_F_Eq {} -> comparisonResultRep
987 MO_F_Ne {} -> comparisonResultRep
988 MO_F_Ge {} -> comparisonResultRep
989 MO_F_Le {} -> comparisonResultRep
990 MO_F_Gt {} -> comparisonResultRep
991 MO_F_Lt {} -> comparisonResultRep
993 MO_And {} -> ty1 -- Used for pointer masking
996 MO_Not r -> cmmBits r
997 MO_Shl r -> cmmBits r
998 MO_U_Shr r -> cmmBits r
999 MO_S_Shr r -> cmmBits r
1001 MO_SS_Conv _ to -> cmmBits to
1002 MO_UU_Conv _ to -> cmmBits to
1003 MO_FS_Conv _ to -> cmmBits to
1004 MO_SF_Conv _ to -> cmmFloat to
1005 MO_FF_Conv _ to -> cmmFloat to
1009 comparisonResultRep :: CmmType
1010 comparisonResultRep = bWord -- is it?
1013 -- -----------------------------------------------------------------------------
1016 -- | This function is used for debugging only: we can check whether an
1017 -- application of a MachOp is "type-correct" by checking that the MachReps of
1018 -- its arguments are the same as the MachOp expects. This is used when
1019 -- linting a CmmExpr.
1021 machOpArgReps :: MachOp -> [Width]
1029 MO_S_MulMayOflo r -> [r,r]
1030 MO_S_Quot r -> [r,r]
1033 MO_U_MulMayOflo r -> [r,r]
1034 MO_U_Quot r -> [r,r]
1050 MO_F_Quot r -> [r,r]
1063 MO_Shl r -> [r,wordWidth]
1064 MO_U_Shr r -> [r,wordWidth]
1065 MO_S_Shr r -> [r,wordWidth]
1067 MO_SS_Conv from _ -> [from]
1068 MO_UU_Conv from _ -> [from]
1069 MO_SF_Conv from _ -> [from]
1070 MO_FS_Conv from _ -> [from]
1071 MO_FF_Conv from _ -> [from]
1074 -------------------------------------------------------------------------
1075 {- Note [Signed vs unsigned]
1076 ~~~~~~~~~~~~~~~~~~~~~~~~~
1077 Should a CmmType include a signed vs. unsigned distinction?
1079 This is very much like a "hint" in C-- terminology: it isn't necessary
1080 in order to generate correct code, but it might be useful in that the
1081 compiler can generate better code if it has access to higher-level
1082 hints about data. This is important at call boundaries, because the
1083 definition of a function is not visible at all of its call sites, so
1084 the compiler cannot infer the hints.
1086 Here in Cmm, we're taking a slightly different approach. We include
1087 the int vs. float hint in the MachRep, because (a) the majority of
1088 platforms have a strong distinction between float and int registers,
1089 and (b) we don't want to do any heavyweight hint-inference in the
1090 native code backend in order to get good code. We're treating the
1091 hint more like a type: our Cmm is always completely consistent with
1092 respect to hints. All coercions between float and int are explicit.
1094 What about the signed vs. unsigned hint? This information might be
1095 useful if we want to keep sub-word-sized values in word-size
1096 registers, which we must do if we only have word-sized registers.
1098 On such a system, there are two straightforward conventions for
1099 representing sub-word-sized values:
1101 (a) Leave the upper bits undefined. Comparison operations must
1102 sign- or zero-extend both operands before comparing them,
1103 depending on whether the comparison is signed or unsigned.
1105 (b) Always keep the values sign- or zero-extended as appropriate.
1106 Arithmetic operations must narrow the result to the appropriate
1109 A clever compiler might not use either (a) or (b) exclusively, instead
1110 it would attempt to minimize the coercions by analysis: the same kind
1111 of analysis that propagates hints around. In Cmm we don't want to
1112 have to do this, so we plump for having richer types and keeping the
1113 type information consistent.
1115 If signed/unsigned hints are missing from MachRep, then the only
1116 choice we have is (a), because we don't know whether the result of an
1117 operation should be sign- or zero-extended.
1119 Many architectures have extending load operations, which work well
1120 with (b). To make use of them with (a), you need to know whether the
1121 value is going to be sign- or zero-extended by an enclosing comparison
1122 (for example), which involves knowing above the context. This is
1123 doable but more complex.
1125 Further complicating the issue is foreign calls: a foreign calling
1126 convention can specify that signed 8-bit quantities are passed as
1127 sign-extended 32 bit quantities, for example (this is the case on the
1128 PowerPC). So we *do* need sign information on foreign call arguments.
1130 Pros for adding signed vs. unsigned to MachRep:
1132 - It would let us use convention (b) above, and get easier
1133 code generation for extending loads.
1135 - Less information required on foreign calls.
1137 - MachOp type would be simpler
1143 - What is the MachRep for a VanillaReg? Currently it is
1144 always wordRep, but now we have to decide whether it is
1145 signed or unsigned. The same VanillaReg can thus have
1146 different MachReps in different parts of the program.
1148 - Extra coercions cluttering up expressions.
1150 Currently for GHC, the foreign call point is moot, because we do our
1151 own promotion of sub-word-sized values to word-sized values. The Int8
1152 type is represnted by an Int# which is kept sign-extended at all times
1153 (this is slightly naughty, because we're making assumptions about the
1154 C calling convention rather early on in the compiler). However, given
1155 this, the cons outweigh the pros.