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
25 , Area(..), AreaId(..), SubArea, SubAreaSet, AreaMap, isStackSlotOf
29 , pprMachOp, isCommutableMachOp, isAssociativeMachOp
30 , isComparisonMachOp, machOpResultType
31 , machOpArgReps, maybeInvertComparison
34 , mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
35 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
36 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
37 , mo_wordULe, mo_wordUGt, mo_wordULt
38 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
39 , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
40 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
41 , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32
45 #include "HsVersions.h"
59 -----------------------------------------------------------------------------
61 -- An expression. Expressions have no side effects.
62 -----------------------------------------------------------------------------
65 = CmmLit CmmLit -- Literal
66 | CmmLoad CmmExpr CmmType -- Read memory location
67 | CmmReg CmmReg -- Contents of register
68 | CmmMachOp MachOp [CmmExpr] -- Machine operation (+, -, *, etc.)
69 | CmmStackSlot Area Int -- addressing expression of a stack slot
70 | CmmRegOff CmmReg Int
72 -- ** is shorthand only, meaning **
73 -- CmmMachOp (MO_S_Add rep (CmmReg reg) (CmmLit (CmmInt i rep)))
74 -- where rep = cmmRegType reg
76 instance Eq CmmExpr where -- Equality ignores the types
77 CmmLit l1 == CmmLit l2 = l1==l2
78 CmmLoad e1 _ == CmmLoad e2 _ = e1==e2
79 CmmReg r1 == CmmReg r2 = r1==r2
80 CmmRegOff r1 i1 == CmmRegOff r2 i2 = r1==r2 && i1==i2
81 CmmMachOp op1 es1 == CmmMachOp op2 es2 = op1==op2 && es1==es2
82 CmmStackSlot a1 i1 == CmmStackSlot a2 i2 = a1==a2 && i1==i2
90 -- | A stack area is either the stack slot where a variable is spilled
91 -- or the stack space where function arguments and results are passed.
98 = Old -- See Note [Old Area]
104 There is a single call area 'Old', allocated at the extreme old
105 end of the stack frame (ie just younger than the return address)
107 * incoming (overflow) parameters,
108 * outgoing (overflow) parameter to tail calls,
109 * outgoing (overflow) result values
110 * the update frame (if any)
112 Its size is the max of all these requirements. On entry, the stack
113 pointer will point to the youngest incoming parameter, which is not
114 necessarily at the young end of the Old area.
118 type SubArea = (Area, Int, Int) -- area, offset, width
119 type SubAreaSet = FiniteMap Area [SubArea]
121 type AreaMap = FiniteMap Area Int
122 -- Byte offset of the oldest byte of the Area,
123 -- relative to the oldest byte of the Old Area
126 = CmmInt Integer Width
127 -- Interpretation: the 2's complement representation of the value
128 -- is truncated to the specified size. This is easier than trying
129 -- to keep the value within range, because we don't know whether
130 -- it will be used as a signed or unsigned value (the CmmType doesn't
131 -- distinguish between signed & unsigned).
132 | CmmFloat Rational Width
133 | CmmLabel CLabel -- Address of label
134 | CmmLabelOff CLabel Int -- Address of label + byte offset
136 -- Due to limitations in the C backend, the following
137 -- MUST ONLY be used inside the info table indicated by label2
138 -- (label2 must be the info label), and label1 must be an
139 -- SRT, a slow entrypoint or a large bitmap (see the Mangler)
140 -- Don't use it at all unless tablesNextToCode.
141 -- It is also used inside the NCG during when generating
142 -- position-independent code.
143 | CmmLabelDiffOff CLabel CLabel Int -- label1 - label2 + offset
144 | CmmBlock BlockId -- Code label
145 | CmmHighStackMark -- stands for the max stack space used during a procedure
148 cmmExprType :: CmmExpr -> CmmType
149 cmmExprType (CmmLit lit) = cmmLitType lit
150 cmmExprType (CmmLoad _ rep) = rep
151 cmmExprType (CmmReg reg) = cmmRegType reg
152 cmmExprType (CmmMachOp op args) = machOpResultType op (map cmmExprType args)
153 cmmExprType (CmmRegOff reg _) = cmmRegType reg
154 cmmExprType (CmmStackSlot _ _) = bWord -- an address
156 cmmLitType :: CmmLit -> CmmType
157 cmmLitType (CmmInt _ width) = cmmBits width
158 cmmLitType (CmmFloat _ width) = cmmFloat width
159 cmmLitType (CmmLabel lbl) = cmmLabelType lbl
160 cmmLitType (CmmLabelOff lbl _) = cmmLabelType lbl
161 cmmLitType (CmmLabelDiffOff {}) = bWord
162 cmmLitType (CmmBlock _) = bWord
163 cmmLitType (CmmHighStackMark) = bWord
165 cmmLabelType :: CLabel -> CmmType
166 cmmLabelType lbl | isGcPtrLabel lbl = gcWord
169 cmmExprWidth :: CmmExpr -> Width
170 cmmExprWidth e = typeWidth (cmmExprType e)
173 --- Negation for conditional branches
175 maybeInvertCmmExpr :: CmmExpr -> Maybe CmmExpr
176 maybeInvertCmmExpr (CmmMachOp op args) = do op' <- maybeInvertComparison op
177 return (CmmMachOp op' args)
178 maybeInvertCmmExpr _ = Nothing
180 -----------------------------------------------------------------------------
182 -----------------------------------------------------------------------------
185 = LocalReg !Unique CmmType
190 instance Eq LocalReg where
191 (LocalReg u1 _) == (LocalReg u2 _) = u1 == u2
193 instance Ord LocalReg where
194 compare (LocalReg u1 _) (LocalReg u2 _) = compare u1 u2
196 instance Uniquable LocalReg where
197 getUnique (LocalReg uniq _) = uniq
199 cmmRegType :: CmmReg -> CmmType
200 cmmRegType (CmmLocal reg) = localRegType reg
201 cmmRegType (CmmGlobal reg) = globalRegType reg
203 localRegType :: LocalReg -> CmmType
204 localRegType (LocalReg _ rep) = rep
206 -----------------------------------------------------------------------------
207 -- Register-use information for expressions and other types
208 -----------------------------------------------------------------------------
210 -- | Sets of local registers
211 type RegSet = UniqSet LocalReg
212 emptyRegSet :: RegSet
213 elemRegSet :: LocalReg -> RegSet -> Bool
214 extendRegSet :: RegSet -> LocalReg -> RegSet
215 deleteFromRegSet :: RegSet -> LocalReg -> RegSet
216 mkRegSet :: [LocalReg] -> RegSet
217 minusRegSet, plusRegSet, timesRegSet :: RegSet -> RegSet -> RegSet
219 emptyRegSet = emptyUniqSet
220 elemRegSet = elementOfUniqSet
221 extendRegSet = addOneToUniqSet
222 deleteFromRegSet = delOneFromUniqSet
224 minusRegSet = minusUniqSet
225 plusRegSet = unionUniqSets
226 timesRegSet = intersectUniqSets
228 class UserOfLocalRegs a where
229 foldRegsUsed :: (b -> LocalReg -> b) -> b -> a -> b
231 class DefinerOfLocalRegs a where
232 foldRegsDefd :: (b -> LocalReg -> b) -> b -> a -> b
234 filterRegsUsed :: UserOfLocalRegs e => (LocalReg -> Bool) -> e -> RegSet
236 foldRegsUsed (\regs r -> if p r then extendRegSet regs r else regs)
239 instance UserOfLocalRegs CmmReg where
240 foldRegsUsed f z (CmmLocal reg) = f z reg
241 foldRegsUsed _ z (CmmGlobal _) = z
243 instance DefinerOfLocalRegs CmmReg where
244 foldRegsDefd f z (CmmLocal reg) = f z reg
245 foldRegsDefd _ z (CmmGlobal _) = z
247 instance UserOfLocalRegs LocalReg where
248 foldRegsUsed f z r = f z r
250 instance DefinerOfLocalRegs LocalReg where
251 foldRegsDefd f z r = f z r
253 instance UserOfLocalRegs RegSet where
254 foldRegsUsed f = foldUniqSet (flip f)
256 instance UserOfLocalRegs CmmExpr where
257 foldRegsUsed f z e = expr z e
258 where expr z (CmmLit _) = z
259 expr z (CmmLoad addr _) = foldRegsUsed f z addr
260 expr z (CmmReg r) = foldRegsUsed f z r
261 expr z (CmmMachOp _ exprs) = foldRegsUsed f z exprs
262 expr z (CmmRegOff r _) = foldRegsUsed f z r
263 expr z (CmmStackSlot _ _) = z
265 instance UserOfLocalRegs a => UserOfLocalRegs [a] where
266 foldRegsUsed _ set [] = set
267 foldRegsUsed f set (x:xs) = foldRegsUsed f (foldRegsUsed f set x) xs
269 instance DefinerOfLocalRegs a => DefinerOfLocalRegs [a] where
270 foldRegsDefd _ set [] = set
271 foldRegsDefd f set (x:xs) = foldRegsDefd f (foldRegsDefd f set x) xs
273 instance DefinerOfLocalRegs a => DefinerOfLocalRegs (Maybe a) where
274 foldRegsDefd _ set Nothing = set
275 foldRegsDefd f set (Just x) = foldRegsDefd f set x
278 -----------------------------------------------------------------------------
280 -----------------------------------------------------------------------------
282 isStackSlotOf :: CmmExpr -> LocalReg -> Bool
283 isStackSlotOf (CmmStackSlot (RegSlot r) _) r' = r == r'
284 isStackSlotOf _ _ = False
286 -----------------------------------------------------------------------------
287 -- Stack slot use information for expressions and other types [_$_]
288 -----------------------------------------------------------------------------
290 -- Fold over the area, the offset into the area, and the width of the subarea.
291 class UserOfSlots a where
292 foldSlotsUsed :: (b -> SubArea -> b) -> b -> a -> b
294 class DefinerOfSlots a where
295 foldSlotsDefd :: (b -> SubArea -> b) -> b -> a -> b
297 instance UserOfSlots CmmExpr where
298 foldSlotsUsed f z e = expr z e
299 where expr z (CmmLit _) = z
300 expr z (CmmLoad (CmmStackSlot a i) ty) = f z (a, i, widthInBytes $ typeWidth ty)
301 expr z (CmmLoad addr _) = foldSlotsUsed f z addr
302 expr z (CmmReg _) = z
303 expr z (CmmMachOp _ exprs) = foldSlotsUsed f z exprs
304 expr z (CmmRegOff _ _) = z
305 expr z (CmmStackSlot _ _) = z
307 instance UserOfSlots a => UserOfSlots [a] where
308 foldSlotsUsed _ set [] = set
309 foldSlotsUsed f set (x:xs) = foldSlotsUsed f (foldSlotsUsed f set x) xs
312 -----------------------------------------------------------------------------
313 -- Global STG registers
314 -----------------------------------------------------------------------------
316 data VGcPtr = VGcPtr | VNonGcPtr deriving( Eq, Show )
319 -----------------------------------------------------------------------------
320 -- Global STG registers
321 -----------------------------------------------------------------------------
322 vgcFlag :: CmmType -> VGcPtr
323 vgcFlag ty | isGcPtrType ty = VGcPtr
324 | otherwise = VNonGcPtr
327 -- Argument and return registers
328 = VanillaReg -- pointers, unboxed ints and chars
329 {-# UNPACK #-} !Int -- its number
332 | FloatReg -- single-precision floating-point registers
333 {-# UNPACK #-} !Int -- its number
335 | DoubleReg -- double-precision floating-point registers
336 {-# UNPACK #-} !Int -- its number
338 | LongReg -- long int registers (64-bit, really)
339 {-# UNPACK #-} !Int -- its number
342 | Sp -- Stack ptr; points to last occupied stack location.
343 | SpLim -- Stack limit
344 | Hp -- Heap ptr; points to last occupied heap location.
345 | HpLim -- Heap limit register
346 | CurrentTSO -- pointer to current thread's TSO
347 | CurrentNursery -- pointer to allocation area
348 | HpAlloc -- allocation count for heap check failure
350 -- We keep the address of some commonly-called
351 -- functions in the register table, to keep code
353 | EagerBlackholeInfo -- stg_EAGER_BLACKHOLE_info
354 | GCEnter1 -- stg_gc_enter_1
355 | GCFun -- stg_gc_fun
357 -- Base offset for the register table, used for accessing registers
358 -- which do not have real registers assigned to them. This register
359 -- will only appear after we have expanded GlobalReg into memory accesses
360 -- (where necessary) in the native code generator.
363 -- Base Register for PIC (position-independent code) calculations
364 -- Only used inside the native code generator. It's exact meaning differs
365 -- from platform to platform (see module PositionIndependentCode).
370 instance Eq GlobalReg where
371 VanillaReg i _ == VanillaReg j _ = i==j -- Ignore type when seeking clashes
372 FloatReg i == FloatReg j = i==j
373 DoubleReg i == DoubleReg j = i==j
374 LongReg i == LongReg j = i==j
376 SpLim == SpLim = True
378 HpLim == HpLim = True
379 CurrentTSO == CurrentTSO = True
380 CurrentNursery == CurrentNursery = True
381 HpAlloc == HpAlloc = True
382 GCEnter1 == GCEnter1 = True
383 GCFun == GCFun = True
384 BaseReg == BaseReg = True
385 PicBaseReg == PicBaseReg = True
388 instance Ord GlobalReg where
389 compare (VanillaReg i _) (VanillaReg j _) = compare i j
390 -- Ignore type when seeking clashes
391 compare (FloatReg i) (FloatReg j) = compare i j
392 compare (DoubleReg i) (DoubleReg j) = compare i j
393 compare (LongReg i) (LongReg j) = compare i j
395 compare SpLim SpLim = EQ
397 compare HpLim HpLim = EQ
398 compare CurrentTSO CurrentTSO = EQ
399 compare CurrentNursery CurrentNursery = EQ
400 compare HpAlloc HpAlloc = EQ
401 compare EagerBlackholeInfo EagerBlackholeInfo = EQ
402 compare GCEnter1 GCEnter1 = EQ
403 compare GCFun GCFun = EQ
404 compare BaseReg BaseReg = EQ
405 compare PicBaseReg PicBaseReg = EQ
406 compare (VanillaReg _ _) _ = LT
407 compare _ (VanillaReg _ _) = GT
408 compare (FloatReg _) _ = LT
409 compare _ (FloatReg _) = GT
410 compare (DoubleReg _) _ = LT
411 compare _ (DoubleReg _) = GT
412 compare (LongReg _) _ = LT
413 compare _ (LongReg _) = GT
422 compare CurrentTSO _ = LT
423 compare _ CurrentTSO = GT
424 compare CurrentNursery _ = LT
425 compare _ CurrentNursery = GT
426 compare HpAlloc _ = LT
427 compare _ HpAlloc = GT
428 compare GCEnter1 _ = LT
429 compare _ GCEnter1 = GT
432 compare BaseReg _ = LT
433 compare _ BaseReg = GT
434 compare EagerBlackholeInfo _ = LT
435 compare _ EagerBlackholeInfo = GT
437 -- convenient aliases
438 spReg, hpReg, spLimReg, nodeReg :: CmmReg
441 spLimReg = CmmGlobal SpLim
442 nodeReg = CmmGlobal node
445 node = VanillaReg 1 VGcPtr
447 globalRegType :: GlobalReg -> CmmType
448 globalRegType (VanillaReg _ VGcPtr) = gcWord
449 globalRegType (VanillaReg _ VNonGcPtr) = bWord
450 globalRegType (FloatReg _) = cmmFloat W32
451 globalRegType (DoubleReg _) = cmmFloat W64
452 globalRegType (LongReg _) = cmmBits W64
453 globalRegType Hp = gcWord -- The initialiser for all
454 -- dynamically allocated closures
455 globalRegType _ = bWord
458 -----------------------------------------------------------------------------
460 -----------------------------------------------------------------------------
462 -- NOTE: CmmType is an abstract type, not exported from this
463 -- module so you can easily change its representation
465 -- However Width is exported in a concrete way,
466 -- and is used extensively in pattern-matching
468 data CmmType -- The important one!
469 = CmmType CmmCat Width
471 data CmmCat -- "Category" (not exported)
472 = GcPtrCat -- GC pointer
473 | BitsCat -- Non-pointer
476 -- See Note [Signed vs unsigned] at the end
478 instance Outputable CmmType where
479 ppr (CmmType cat wid) = ppr cat <> ppr (widthInBits wid)
481 instance Outputable CmmCat where
482 ppr FloatCat = ptext $ sLit("F")
483 ppr _ = ptext $ sLit("I")
485 -- ppr FloatCat = ptext $ sLit("float")
486 -- ppr BitsCat = ptext $ sLit("bits")
487 -- ppr GcPtrCat = ptext $ sLit("gcptr")
489 -- Why is CmmType stratified? For native code generation,
490 -- most of the time you just want to know what sort of register
491 -- to put the thing in, and for this you need to know how
492 -- many bits thing has and whether it goes in a floating-point
493 -- register. By contrast, the distinction between GcPtr and
494 -- GcNonPtr is of interest to only a few parts of the code generator.
496 -------- Equality on CmmType --------------
497 -- CmmType is *not* an instance of Eq; sometimes we care about the
498 -- Gc/NonGc distinction, and sometimes we don't
499 -- So we use an explicit function to force you to think about it
500 cmmEqType :: CmmType -> CmmType -> Bool -- Exact equality
501 cmmEqType (CmmType c1 w1) (CmmType c2 w2) = c1==c2 && w1==w2
503 cmmEqType_ignoring_ptrhood :: CmmType -> CmmType -> Bool
504 -- This equality is temporary; used in CmmLint
505 -- but the RTS files are not yet well-typed wrt pointers
506 cmmEqType_ignoring_ptrhood (CmmType c1 w1) (CmmType c2 w2)
507 = c1 `weak_eq` c2 && w1==w2
509 FloatCat `weak_eq` FloatCat = True
510 FloatCat `weak_eq` _other = False
511 _other `weak_eq` FloatCat = False
512 _word1 `weak_eq` _word2 = True -- Ignores GcPtr
514 --- Simple operations on CmmType -----
515 typeWidth :: CmmType -> Width
516 typeWidth (CmmType _ w) = w
518 cmmBits, cmmFloat :: Width -> CmmType
519 cmmBits = CmmType BitsCat
520 cmmFloat = CmmType FloatCat
522 -------- Common CmmTypes ------------
523 -- Floats and words of specific widths
524 b8, b16, b32, b64, f32, f64 :: CmmType
532 -- CmmTypes of native word widths
533 bWord, bHalfWord, gcWord :: CmmType
534 bWord = cmmBits wordWidth
535 bHalfWord = cmmBits halfWordWidth
536 gcWord = CmmType GcPtrCat wordWidth
538 cInt, cLong :: CmmType
539 cInt = cmmBits cIntWidth
540 cLong = cmmBits cLongWidth
543 ------------ Predicates ----------------
544 isFloatType, isGcPtrType :: CmmType -> Bool
545 isFloatType (CmmType FloatCat _) = True
546 isFloatType _other = False
548 isGcPtrType (CmmType GcPtrCat _) = True
549 isGcPtrType _other = False
551 isWord32, isWord64, isFloat32, isFloat64 :: CmmType -> Bool
552 -- isWord64 is true of 64-bit non-floats (both gc-ptrs and otherwise)
553 -- isFloat32 and 64 are obvious
555 isWord64 (CmmType BitsCat W64) = True
556 isWord64 (CmmType GcPtrCat W64) = True
557 isWord64 _other = False
559 isWord32 (CmmType BitsCat W32) = True
560 isWord32 (CmmType GcPtrCat W32) = True
561 isWord32 _other = False
563 isFloat32 (CmmType FloatCat W32) = True
564 isFloat32 _other = False
566 isFloat64 (CmmType FloatCat W64) = True
567 isFloat64 _other = False
569 -----------------------------------------------------------------------------
571 -----------------------------------------------------------------------------
573 data Width = W8 | W16 | W32 | W64
574 | W80 -- Extended double-precision float,
575 -- used in x86 native codegen only.
576 -- (we use Ord, so it'd better be in this order)
578 deriving (Eq, Ord, Show)
580 instance Outputable Width where
581 ppr rep = ptext (mrStr rep)
583 mrStr :: Width -> LitString
584 mrStr W8 = sLit("W8")
585 mrStr W16 = sLit("W16")
586 mrStr W32 = sLit("W32")
587 mrStr W64 = sLit("W64")
588 mrStr W128 = sLit("W128")
589 mrStr W80 = sLit("W80")
592 -------- Common Widths ------------
593 wordWidth, halfWordWidth :: Width
594 wordWidth | wORD_SIZE == 4 = W32
595 | wORD_SIZE == 8 = W64
596 | otherwise = panic "MachOp.wordRep: Unknown word size"
598 halfWordWidth | wORD_SIZE == 4 = W16
599 | wORD_SIZE == 8 = W32
600 | otherwise = panic "MachOp.halfWordRep: Unknown word size"
602 -- cIntRep is the Width for a C-language 'int'
603 cIntWidth, cLongWidth :: Width
606 #elif SIZEOF_INT == 8
612 #elif SIZEOF_LONG == 8
616 widthInBits :: Width -> Int
621 widthInBits W128 = 128
624 widthInBytes :: Width -> Int
629 widthInBytes W128 = 16
630 widthInBytes W80 = 10
632 widthFromBytes :: Int -> Width
633 widthFromBytes 1 = W8
634 widthFromBytes 2 = W16
635 widthFromBytes 4 = W32
636 widthFromBytes 8 = W64
637 widthFromBytes 16 = W128
638 widthFromBytes 10 = W80
639 widthFromBytes n = pprPanic "no width for given number of bytes" (ppr n)
641 -- log_2 of the width in bytes, useful for generating shifts.
642 widthInLog :: Width -> Int
648 widthInLog W80 = panic "widthInLog: F80"
650 -- widening / narrowing
652 narrowU :: Width -> Integer -> Integer
653 narrowU W8 x = fromIntegral (fromIntegral x :: Word8)
654 narrowU W16 x = fromIntegral (fromIntegral x :: Word16)
655 narrowU W32 x = fromIntegral (fromIntegral x :: Word32)
656 narrowU W64 x = fromIntegral (fromIntegral x :: Word64)
657 narrowU _ _ = panic "narrowTo"
659 narrowS :: Width -> Integer -> Integer
660 narrowS W8 x = fromIntegral (fromIntegral x :: Int8)
661 narrowS W16 x = fromIntegral (fromIntegral x :: Int16)
662 narrowS W32 x = fromIntegral (fromIntegral x :: Int32)
663 narrowS W64 x = fromIntegral (fromIntegral x :: Int64)
664 narrowS _ _ = panic "narrowTo"
666 -----------------------------------------------------------------------------
668 -----------------------------------------------------------------------------
671 Implementation notes:
673 It might suffice to keep just a width, without distinguishing between
674 floating and integer types. However, keeping the distinction will
675 help the native code generator to assign registers more easily.
680 Machine-level primops; ones which we can reasonably delegate to the
681 native code generators to handle. Basically contains C's primops
684 Nomenclature: all ops indicate width and signedness, where
685 appropriate. Widths: 8\/16\/32\/64 means the given size, obviously.
686 Nat means the operation works on STG word sized objects.
687 Signedness: S means signed, U means unsigned. For operations where
688 signedness is irrelevant or makes no difference (for example
689 integer add), the signedness component is omitted.
691 An exception: NatP is a ptr-typed native word. From the point of
692 view of the native code generators this distinction is irrelevant,
693 but the C code generator sometimes needs this info to emit the
698 -- Integer operations (insensitive to signed/unsigned)
703 | MO_Mul Width -- low word of multiply
705 -- Signed multiply/divide
706 | MO_S_MulMayOflo Width -- nonzero if signed multiply overflows
707 | MO_S_Quot Width -- signed / (same semantics as IntQuotOp)
708 | MO_S_Rem Width -- signed % (same semantics as IntRemOp)
709 | MO_S_Neg Width -- unary -
711 -- Unsigned multiply/divide
712 | MO_U_MulMayOflo Width -- nonzero if unsigned multiply overflows
713 | MO_U_Quot Width -- unsigned / (same semantics as WordQuotOp)
714 | MO_U_Rem Width -- unsigned % (same semantics as WordRemOp)
716 -- Signed comparisons
722 -- Unsigned comparisons
728 -- Floating point arithmetic
731 | MO_F_Neg Width -- unary -
735 -- Floating point comparison
743 -- Bitwise operations. Not all of these may be supported
744 -- at all sizes, and only integral Widths are valid.
750 | MO_U_Shr Width -- unsigned shift right
751 | MO_S_Shr Width -- signed shift right
753 -- Conversions. Some of these will be NOPs.
754 -- Floating-point conversions use the signed variant.
755 | MO_SF_Conv Width Width -- Signed int -> Float
756 | MO_FS_Conv Width Width -- Float -> Signed int
757 | MO_SS_Conv Width Width -- Signed int -> Signed int
758 | MO_UU_Conv Width Width -- unsigned int -> unsigned int
759 | MO_FF_Conv Width Width -- Float -> Float
762 pprMachOp :: MachOp -> SDoc
763 pprMachOp mo = text (show mo)
767 -- -----------------------------------------------------------------------------
768 -- Some common MachReps
770 -- A 'wordRep' is a machine word on the target architecture
771 -- Specifically, it is the size of an Int#, Word#, Addr#
772 -- and the unit of allocation on the stack and the heap
773 -- Any pointer is also guaranteed to be a wordRep.
775 mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
776 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
777 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
778 , mo_wordULe, mo_wordUGt, mo_wordULt
779 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
780 , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
781 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
782 , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32
785 mo_wordAdd = MO_Add wordWidth
786 mo_wordSub = MO_Sub wordWidth
787 mo_wordEq = MO_Eq wordWidth
788 mo_wordNe = MO_Ne wordWidth
789 mo_wordMul = MO_Mul wordWidth
790 mo_wordSQuot = MO_S_Quot wordWidth
791 mo_wordSRem = MO_S_Rem wordWidth
792 mo_wordSNeg = MO_S_Neg wordWidth
793 mo_wordUQuot = MO_U_Quot wordWidth
794 mo_wordURem = MO_U_Rem wordWidth
796 mo_wordSGe = MO_S_Ge wordWidth
797 mo_wordSLe = MO_S_Le wordWidth
798 mo_wordSGt = MO_S_Gt wordWidth
799 mo_wordSLt = MO_S_Lt wordWidth
801 mo_wordUGe = MO_U_Ge wordWidth
802 mo_wordULe = MO_U_Le wordWidth
803 mo_wordUGt = MO_U_Gt wordWidth
804 mo_wordULt = MO_U_Lt wordWidth
806 mo_wordAnd = MO_And wordWidth
807 mo_wordOr = MO_Or wordWidth
808 mo_wordXor = MO_Xor wordWidth
809 mo_wordNot = MO_Not wordWidth
810 mo_wordShl = MO_Shl wordWidth
811 mo_wordSShr = MO_S_Shr wordWidth
812 mo_wordUShr = MO_U_Shr wordWidth
814 mo_u_8To32 = MO_UU_Conv W8 W32
815 mo_s_8To32 = MO_SS_Conv W8 W32
816 mo_u_16To32 = MO_UU_Conv W16 W32
817 mo_s_16To32 = MO_SS_Conv W16 W32
819 mo_u_8ToWord = MO_UU_Conv W8 wordWidth
820 mo_s_8ToWord = MO_SS_Conv W8 wordWidth
821 mo_u_16ToWord = MO_UU_Conv W16 wordWidth
822 mo_s_16ToWord = MO_SS_Conv W16 wordWidth
823 mo_s_32ToWord = MO_SS_Conv W32 wordWidth
824 mo_u_32ToWord = MO_UU_Conv W32 wordWidth
826 mo_WordTo8 = MO_UU_Conv wordWidth W8
827 mo_WordTo16 = MO_UU_Conv wordWidth W16
828 mo_WordTo32 = MO_UU_Conv wordWidth W32
830 mo_32To8 = MO_UU_Conv W32 W8
831 mo_32To16 = MO_UU_Conv W32 W16
834 -- ----------------------------------------------------------------------------
835 -- isCommutableMachOp
838 Returns 'True' if the MachOp has commutable arguments. This is used
839 in the platform-independent Cmm optimisations.
841 If in doubt, return 'False'. This generates worse code on the
842 native routes, but is otherwise harmless.
844 isCommutableMachOp :: MachOp -> Bool
845 isCommutableMachOp mop =
851 MO_S_MulMayOflo _ -> True
852 MO_U_MulMayOflo _ -> True
858 -- ----------------------------------------------------------------------------
859 -- isAssociativeMachOp
862 Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
863 This is used in the platform-independent Cmm optimisations.
865 If in doubt, return 'False'. This generates worse code on the
866 native routes, but is otherwise harmless.
868 isAssociativeMachOp :: MachOp -> Bool
869 isAssociativeMachOp mop =
871 MO_Add {} -> True -- NB: does not include
872 MO_Mul {} -> True -- floatint point!
878 -- ----------------------------------------------------------------------------
879 -- isComparisonMachOp
882 Returns 'True' if the MachOp is a comparison.
884 If in doubt, return False. This generates worse code on the
885 native routes, but is otherwise harmless.
887 isComparisonMachOp :: MachOp -> Bool
888 isComparisonMachOp mop =
908 -- -----------------------------------------------------------------------------
909 -- Inverting conditions
911 -- Sometimes it's useful to be able to invert the sense of a
912 -- condition. Not all conditional tests are invertible: in
913 -- particular, floating point conditionals cannot be inverted, because
914 -- there exist floating-point values which return False for both senses
915 -- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).
917 maybeInvertComparison :: MachOp -> Maybe MachOp
918 maybeInvertComparison op
919 = case op of -- None of these Just cases include floating point
920 MO_Eq r -> Just (MO_Ne r)
921 MO_Ne r -> Just (MO_Eq r)
922 MO_U_Lt r -> Just (MO_U_Ge r)
923 MO_U_Gt r -> Just (MO_U_Le r)
924 MO_U_Le r -> Just (MO_U_Gt r)
925 MO_U_Ge r -> Just (MO_U_Lt r)
926 MO_S_Lt r -> Just (MO_S_Ge r)
927 MO_S_Gt r -> Just (MO_S_Le r)
928 MO_S_Le r -> Just (MO_S_Gt r)
929 MO_S_Ge r -> Just (MO_S_Lt r)
930 MO_F_Eq r -> Just (MO_F_Ne r)
931 MO_F_Ne r -> Just (MO_F_Eq r)
932 MO_F_Ge r -> Just (MO_F_Le r)
933 MO_F_Le r -> Just (MO_F_Ge r)
934 MO_F_Gt r -> Just (MO_F_Lt r)
935 MO_F_Lt r -> Just (MO_F_Gt r)
938 -- ----------------------------------------------------------------------------
942 Returns the MachRep of the result of a MachOp.
944 machOpResultType :: MachOp -> [CmmType] -> CmmType
945 machOpResultType mop tys =
947 MO_Add {} -> ty1 -- Preserve GC-ptr-hood
948 MO_Sub {} -> ty1 -- of first arg
949 MO_Mul r -> cmmBits r
950 MO_S_MulMayOflo r -> cmmBits r
951 MO_S_Quot r -> cmmBits r
952 MO_S_Rem r -> cmmBits r
953 MO_S_Neg r -> cmmBits r
954 MO_U_MulMayOflo r -> cmmBits r
955 MO_U_Quot r -> cmmBits r
956 MO_U_Rem r -> cmmBits r
958 MO_Eq {} -> comparisonResultRep
959 MO_Ne {} -> comparisonResultRep
960 MO_S_Ge {} -> comparisonResultRep
961 MO_S_Le {} -> comparisonResultRep
962 MO_S_Gt {} -> comparisonResultRep
963 MO_S_Lt {} -> comparisonResultRep
965 MO_U_Ge {} -> comparisonResultRep
966 MO_U_Le {} -> comparisonResultRep
967 MO_U_Gt {} -> comparisonResultRep
968 MO_U_Lt {} -> comparisonResultRep
970 MO_F_Add r -> cmmFloat r
971 MO_F_Sub r -> cmmFloat r
972 MO_F_Mul r -> cmmFloat r
973 MO_F_Quot r -> cmmFloat r
974 MO_F_Neg r -> cmmFloat r
975 MO_F_Eq {} -> comparisonResultRep
976 MO_F_Ne {} -> comparisonResultRep
977 MO_F_Ge {} -> comparisonResultRep
978 MO_F_Le {} -> comparisonResultRep
979 MO_F_Gt {} -> comparisonResultRep
980 MO_F_Lt {} -> comparisonResultRep
982 MO_And {} -> ty1 -- Used for pointer masking
985 MO_Not r -> cmmBits r
986 MO_Shl r -> cmmBits r
987 MO_U_Shr r -> cmmBits r
988 MO_S_Shr r -> cmmBits r
990 MO_SS_Conv _ to -> cmmBits to
991 MO_UU_Conv _ to -> cmmBits to
992 MO_FS_Conv _ to -> cmmBits to
993 MO_SF_Conv _ to -> cmmFloat to
994 MO_FF_Conv _ to -> cmmFloat to
998 comparisonResultRep :: CmmType
999 comparisonResultRep = bWord -- is it?
1002 -- -----------------------------------------------------------------------------
1005 -- | This function is used for debugging only: we can check whether an
1006 -- application of a MachOp is "type-correct" by checking that the MachReps of
1007 -- its arguments are the same as the MachOp expects. This is used when
1008 -- linting a CmmExpr.
1010 machOpArgReps :: MachOp -> [Width]
1018 MO_S_MulMayOflo r -> [r,r]
1019 MO_S_Quot r -> [r,r]
1022 MO_U_MulMayOflo r -> [r,r]
1023 MO_U_Quot r -> [r,r]
1039 MO_F_Quot r -> [r,r]
1052 MO_Shl r -> [r,wordWidth]
1053 MO_U_Shr r -> [r,wordWidth]
1054 MO_S_Shr r -> [r,wordWidth]
1056 MO_SS_Conv from _ -> [from]
1057 MO_UU_Conv from _ -> [from]
1058 MO_SF_Conv from _ -> [from]
1059 MO_FS_Conv from _ -> [from]
1060 MO_FF_Conv from _ -> [from]
1063 -------------------------------------------------------------------------
1064 {- Note [Signed vs unsigned]
1065 ~~~~~~~~~~~~~~~~~~~~~~~~~
1066 Should a CmmType include a signed vs. unsigned distinction?
1068 This is very much like a "hint" in C-- terminology: it isn't necessary
1069 in order to generate correct code, but it might be useful in that the
1070 compiler can generate better code if it has access to higher-level
1071 hints about data. This is important at call boundaries, because the
1072 definition of a function is not visible at all of its call sites, so
1073 the compiler cannot infer the hints.
1075 Here in Cmm, we're taking a slightly different approach. We include
1076 the int vs. float hint in the MachRep, because (a) the majority of
1077 platforms have a strong distinction between float and int registers,
1078 and (b) we don't want to do any heavyweight hint-inference in the
1079 native code backend in order to get good code. We're treating the
1080 hint more like a type: our Cmm is always completely consistent with
1081 respect to hints. All coercions between float and int are explicit.
1083 What about the signed vs. unsigned hint? This information might be
1084 useful if we want to keep sub-word-sized values in word-size
1085 registers, which we must do if we only have word-sized registers.
1087 On such a system, there are two straightforward conventions for
1088 representing sub-word-sized values:
1090 (a) Leave the upper bits undefined. Comparison operations must
1091 sign- or zero-extend both operands before comparing them,
1092 depending on whether the comparison is signed or unsigned.
1094 (b) Always keep the values sign- or zero-extended as appropriate.
1095 Arithmetic operations must narrow the result to the appropriate
1098 A clever compiler might not use either (a) or (b) exclusively, instead
1099 it would attempt to minimize the coercions by analysis: the same kind
1100 of analysis that propagates hints around. In Cmm we don't want to
1101 have to do this, so we plump for having richer types and keeping the
1102 type information consistent.
1104 If signed/unsigned hints are missing from MachRep, then the only
1105 choice we have is (a), because we don't know whether the result of an
1106 operation should be sign- or zero-extended.
1108 Many architectures have extending load operations, which work well
1109 with (b). To make use of them with (a), you need to know whether the
1110 value is going to be sign- or zero-extended by an enclosing comparison
1111 (for example), which involves knowing above the context. This is
1112 doable but more complex.
1114 Further complicating the issue is foreign calls: a foreign calling
1115 convention can specify that signed 8-bit quantities are passed as
1116 sign-extended 32 bit quantities, for example (this is the case on the
1117 PowerPC). So we *do* need sign information on foreign call arguments.
1119 Pros for adding signed vs. unsigned to MachRep:
1121 - It would let us use convention (b) above, and get easier
1122 code generation for extending loads.
1124 - Less information required on foreign calls.
1126 - MachOp type would be simpler
1132 - What is the MachRep for a VanillaReg? Currently it is
1133 always wordRep, but now we have to decide whether it is
1134 signed or unsigned. The same VanillaReg can thus have
1135 different MachReps in different parts of the program.
1137 - Extra coercions cluttering up expressions.
1139 Currently for GHC, the foreign call point is moot, because we do our
1140 own promotion of sub-word-sized values to word-sized values. The Int8
1141 type is represnted by an Int# which is kept sign-extended at all times
1142 (this is slightly naughty, because we're making assumptions about the
1143 C calling convention rather early on in the compiler). However, given
1144 this, the cons outweigh the pros.