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 -- entry parameters, jumps, and returns share one call area at old end of stack
102 type SubArea = (Area, Int, Int) -- area, offset, width
103 type SubAreaSet = FiniteMap Area [SubArea]
104 type AreaMap = FiniteMap Area Int
107 = CmmInt Integer Width
108 -- Interpretation: the 2's complement representation of the value
109 -- is truncated to the specified size. This is easier than trying
110 -- to keep the value within range, because we don't know whether
111 -- it will be used as a signed or unsigned value (the CmmType doesn't
112 -- distinguish between signed & unsigned).
113 | CmmFloat Rational Width
114 | CmmLabel CLabel -- Address of label
115 | CmmLabelOff CLabel Int -- Address of label + byte offset
117 -- Due to limitations in the C backend, the following
118 -- MUST ONLY be used inside the info table indicated by label2
119 -- (label2 must be the info label), and label1 must be an
120 -- SRT, a slow entrypoint or a large bitmap (see the Mangler)
121 -- Don't use it at all unless tablesNextToCode.
122 -- It is also used inside the NCG during when generating
123 -- position-independent code.
124 | CmmLabelDiffOff CLabel CLabel Int -- label1 - label2 + offset
125 | CmmBlock BlockId -- Code label
126 | CmmHighStackMark -- stands for the max stack space used during a procedure
129 cmmExprType :: CmmExpr -> CmmType
130 cmmExprType (CmmLit lit) = cmmLitType lit
131 cmmExprType (CmmLoad _ rep) = rep
132 cmmExprType (CmmReg reg) = cmmRegType reg
133 cmmExprType (CmmMachOp op args) = machOpResultType op (map cmmExprType args)
134 cmmExprType (CmmRegOff reg _) = cmmRegType reg
135 cmmExprType (CmmStackSlot _ _) = bWord -- an address
137 cmmLitType :: CmmLit -> CmmType
138 cmmLitType (CmmInt _ width) = cmmBits width
139 cmmLitType (CmmFloat _ width) = cmmFloat width
140 cmmLitType (CmmLabel lbl) = cmmLabelType lbl
141 cmmLitType (CmmLabelOff lbl _) = cmmLabelType lbl
142 cmmLitType (CmmLabelDiffOff {}) = bWord
143 cmmLitType (CmmBlock _) = bWord
144 cmmLitType (CmmHighStackMark) = bWord
146 cmmLabelType :: CLabel -> CmmType
147 cmmLabelType lbl | isGcPtrLabel lbl = gcWord
150 cmmExprWidth :: CmmExpr -> Width
151 cmmExprWidth e = typeWidth (cmmExprType e)
154 --- Negation for conditional branches
156 maybeInvertCmmExpr :: CmmExpr -> Maybe CmmExpr
157 maybeInvertCmmExpr (CmmMachOp op args) = do op' <- maybeInvertComparison op
158 return (CmmMachOp op' args)
159 maybeInvertCmmExpr _ = Nothing
161 -----------------------------------------------------------------------------
163 -----------------------------------------------------------------------------
166 = LocalReg !Unique CmmType
171 instance Eq LocalReg where
172 (LocalReg u1 _) == (LocalReg u2 _) = u1 == u2
174 instance Ord LocalReg where
175 compare (LocalReg u1 _) (LocalReg u2 _) = compare u1 u2
177 instance Uniquable LocalReg where
178 getUnique (LocalReg uniq _) = uniq
180 cmmRegType :: CmmReg -> CmmType
181 cmmRegType (CmmLocal reg) = localRegType reg
182 cmmRegType (CmmGlobal reg) = globalRegType reg
184 localRegType :: LocalReg -> CmmType
185 localRegType (LocalReg _ rep) = rep
187 -----------------------------------------------------------------------------
188 -- Register-use information for expressions and other types
189 -----------------------------------------------------------------------------
191 -- | Sets of local registers
192 type RegSet = UniqSet LocalReg
193 emptyRegSet :: RegSet
194 elemRegSet :: LocalReg -> RegSet -> Bool
195 extendRegSet :: RegSet -> LocalReg -> RegSet
196 deleteFromRegSet :: RegSet -> LocalReg -> RegSet
197 mkRegSet :: [LocalReg] -> RegSet
198 minusRegSet, plusRegSet, timesRegSet :: RegSet -> RegSet -> RegSet
200 emptyRegSet = emptyUniqSet
201 elemRegSet = elementOfUniqSet
202 extendRegSet = addOneToUniqSet
203 deleteFromRegSet = delOneFromUniqSet
205 minusRegSet = minusUniqSet
206 plusRegSet = unionUniqSets
207 timesRegSet = intersectUniqSets
209 class UserOfLocalRegs a where
210 foldRegsUsed :: (b -> LocalReg -> b) -> b -> a -> b
212 class DefinerOfLocalRegs a where
213 foldRegsDefd :: (b -> LocalReg -> b) -> b -> a -> b
215 filterRegsUsed :: UserOfLocalRegs e => (LocalReg -> Bool) -> e -> RegSet
217 foldRegsUsed (\regs r -> if p r then extendRegSet regs r else regs)
220 instance UserOfLocalRegs CmmReg where
221 foldRegsUsed f z (CmmLocal reg) = f z reg
222 foldRegsUsed _ z (CmmGlobal _) = z
224 instance DefinerOfLocalRegs CmmReg where
225 foldRegsDefd f z (CmmLocal reg) = f z reg
226 foldRegsDefd _ z (CmmGlobal _) = z
228 instance UserOfLocalRegs LocalReg where
229 foldRegsUsed f z r = f z r
231 instance DefinerOfLocalRegs LocalReg where
232 foldRegsDefd f z r = f z r
234 instance UserOfLocalRegs RegSet where
235 foldRegsUsed f = foldUniqSet (flip f)
237 instance UserOfLocalRegs CmmExpr where
238 foldRegsUsed f z e = expr z e
239 where expr z (CmmLit _) = z
240 expr z (CmmLoad addr _) = foldRegsUsed f z addr
241 expr z (CmmReg r) = foldRegsUsed f z r
242 expr z (CmmMachOp _ exprs) = foldRegsUsed f z exprs
243 expr z (CmmRegOff r _) = foldRegsUsed f z r
244 expr z (CmmStackSlot _ _) = z
246 instance UserOfLocalRegs a => UserOfLocalRegs [a] where
247 foldRegsUsed _ set [] = set
248 foldRegsUsed f set (x:xs) = foldRegsUsed f (foldRegsUsed f set x) xs
250 instance DefinerOfLocalRegs a => DefinerOfLocalRegs [a] where
251 foldRegsDefd _ set [] = set
252 foldRegsDefd f set (x:xs) = foldRegsDefd f (foldRegsDefd f set x) xs
254 instance DefinerOfLocalRegs a => DefinerOfLocalRegs (Maybe a) where
255 foldRegsDefd _ set Nothing = set
256 foldRegsDefd f set (Just x) = foldRegsDefd f set x
259 -----------------------------------------------------------------------------
261 -----------------------------------------------------------------------------
263 isStackSlotOf :: CmmExpr -> LocalReg -> Bool
264 isStackSlotOf (CmmStackSlot (RegSlot r) _) r' = r == r'
265 isStackSlotOf _ _ = False
267 -----------------------------------------------------------------------------
268 -- Stack slot use information for expressions and other types [_$_]
269 -----------------------------------------------------------------------------
271 -- Fold over the area, the offset into the area, and the width of the subarea.
272 class UserOfSlots a where
273 foldSlotsUsed :: (b -> SubArea -> b) -> b -> a -> b
275 class DefinerOfSlots a where
276 foldSlotsDefd :: (b -> SubArea -> b) -> b -> a -> b
278 instance UserOfSlots CmmExpr where
279 foldSlotsUsed f z e = expr z e
280 where expr z (CmmLit _) = z
281 expr z (CmmLoad (CmmStackSlot a i) ty) = f z (a, i, widthInBytes $ typeWidth ty)
282 expr z (CmmLoad addr _) = foldSlotsUsed f z addr
283 expr z (CmmReg _) = z
284 expr z (CmmMachOp _ exprs) = foldSlotsUsed f z exprs
285 expr z (CmmRegOff _ _) = z
286 expr z (CmmStackSlot _ _) = z
288 instance UserOfSlots a => UserOfSlots [a] where
289 foldSlotsUsed _ set [] = set
290 foldSlotsUsed f set (x:xs) = foldSlotsUsed f (foldSlotsUsed f set x) xs
293 -----------------------------------------------------------------------------
294 -- Global STG registers
295 -----------------------------------------------------------------------------
297 data VGcPtr = VGcPtr | VNonGcPtr deriving( Eq, Show )
300 -----------------------------------------------------------------------------
301 -- Global STG registers
302 -----------------------------------------------------------------------------
303 vgcFlag :: CmmType -> VGcPtr
304 vgcFlag ty | isGcPtrType ty = VGcPtr
305 | otherwise = VNonGcPtr
308 -- Argument and return registers
309 = VanillaReg -- pointers, unboxed ints and chars
310 {-# UNPACK #-} !Int -- its number
313 | FloatReg -- single-precision floating-point registers
314 {-# UNPACK #-} !Int -- its number
316 | DoubleReg -- double-precision floating-point registers
317 {-# UNPACK #-} !Int -- its number
319 | LongReg -- long int registers (64-bit, really)
320 {-# UNPACK #-} !Int -- its number
323 | Sp -- Stack ptr; points to last occupied stack location.
324 | SpLim -- Stack limit
325 | Hp -- Heap ptr; points to last occupied heap location.
326 | HpLim -- Heap limit register
327 | CurrentTSO -- pointer to current thread's TSO
328 | CurrentNursery -- pointer to allocation area
329 | HpAlloc -- allocation count for heap check failure
331 -- We keep the address of some commonly-called
332 -- functions in the register table, to keep code
334 | EagerBlackholeInfo -- stg_EAGER_BLACKHOLE_info
335 | GCEnter1 -- stg_gc_enter_1
336 | GCFun -- stg_gc_fun
338 -- Base offset for the register table, used for accessing registers
339 -- which do not have real registers assigned to them. This register
340 -- will only appear after we have expanded GlobalReg into memory accesses
341 -- (where necessary) in the native code generator.
344 -- Base Register for PIC (position-independent code) calculations
345 -- Only used inside the native code generator. It's exact meaning differs
346 -- from platform to platform (see module PositionIndependentCode).
351 instance Eq GlobalReg where
352 VanillaReg i _ == VanillaReg j _ = i==j -- Ignore type when seeking clashes
353 FloatReg i == FloatReg j = i==j
354 DoubleReg i == DoubleReg j = i==j
355 LongReg i == LongReg j = i==j
357 SpLim == SpLim = True
359 HpLim == HpLim = True
360 CurrentTSO == CurrentTSO = True
361 CurrentNursery == CurrentNursery = True
362 HpAlloc == HpAlloc = True
363 GCEnter1 == GCEnter1 = True
364 GCFun == GCFun = True
365 BaseReg == BaseReg = True
366 PicBaseReg == PicBaseReg = True
369 instance Ord GlobalReg where
370 compare (VanillaReg i _) (VanillaReg j _) = compare i j
371 -- Ignore type when seeking clashes
372 compare (FloatReg i) (FloatReg j) = compare i j
373 compare (DoubleReg i) (DoubleReg j) = compare i j
374 compare (LongReg i) (LongReg j) = compare i j
376 compare SpLim SpLim = EQ
378 compare HpLim HpLim = EQ
379 compare CurrentTSO CurrentTSO = EQ
380 compare CurrentNursery CurrentNursery = EQ
381 compare HpAlloc HpAlloc = EQ
382 compare EagerBlackholeInfo EagerBlackholeInfo = EQ
383 compare GCEnter1 GCEnter1 = EQ
384 compare GCFun GCFun = EQ
385 compare BaseReg BaseReg = EQ
386 compare PicBaseReg PicBaseReg = EQ
387 compare (VanillaReg _ _) _ = LT
388 compare _ (VanillaReg _ _) = GT
389 compare (FloatReg _) _ = LT
390 compare _ (FloatReg _) = GT
391 compare (DoubleReg _) _ = LT
392 compare _ (DoubleReg _) = GT
393 compare (LongReg _) _ = LT
394 compare _ (LongReg _) = GT
403 compare CurrentTSO _ = LT
404 compare _ CurrentTSO = GT
405 compare CurrentNursery _ = LT
406 compare _ CurrentNursery = GT
407 compare HpAlloc _ = LT
408 compare _ HpAlloc = GT
409 compare GCEnter1 _ = LT
410 compare _ GCEnter1 = GT
413 compare BaseReg _ = LT
414 compare _ BaseReg = GT
415 compare EagerBlackholeInfo _ = LT
416 compare _ EagerBlackholeInfo = GT
418 -- convenient aliases
419 spReg, hpReg, spLimReg, nodeReg :: CmmReg
422 spLimReg = CmmGlobal SpLim
423 nodeReg = CmmGlobal node
426 node = VanillaReg 1 VGcPtr
428 globalRegType :: GlobalReg -> CmmType
429 globalRegType (VanillaReg _ VGcPtr) = gcWord
430 globalRegType (VanillaReg _ VNonGcPtr) = bWord
431 globalRegType (FloatReg _) = cmmFloat W32
432 globalRegType (DoubleReg _) = cmmFloat W64
433 globalRegType (LongReg _) = cmmBits W64
434 globalRegType Hp = gcWord -- The initialiser for all
435 -- dynamically allocated closures
436 globalRegType _ = bWord
439 -----------------------------------------------------------------------------
441 -----------------------------------------------------------------------------
443 -- NOTE: CmmType is an abstract type, not exported from this
444 -- module so you can easily change its representation
446 -- However Width is exported in a concrete way,
447 -- and is used extensively in pattern-matching
449 data CmmType -- The important one!
450 = CmmType CmmCat Width
452 data CmmCat -- "Category" (not exported)
453 = GcPtrCat -- GC pointer
454 | BitsCat -- Non-pointer
457 -- See Note [Signed vs unsigned] at the end
459 instance Outputable CmmType where
460 ppr (CmmType cat wid) = ppr cat <> ppr (widthInBits wid)
462 instance Outputable CmmCat where
463 ppr FloatCat = ptext $ sLit("F")
464 ppr _ = ptext $ sLit("I")
466 -- ppr FloatCat = ptext $ sLit("float")
467 -- ppr BitsCat = ptext $ sLit("bits")
468 -- ppr GcPtrCat = ptext $ sLit("gcptr")
470 -- Why is CmmType stratified? For native code generation,
471 -- most of the time you just want to know what sort of register
472 -- to put the thing in, and for this you need to know how
473 -- many bits thing has and whether it goes in a floating-point
474 -- register. By contrast, the distinction between GcPtr and
475 -- GcNonPtr is of interest to only a few parts of the code generator.
477 -------- Equality on CmmType --------------
478 -- CmmType is *not* an instance of Eq; sometimes we care about the
479 -- Gc/NonGc distinction, and sometimes we don't
480 -- So we use an explicit function to force you to think about it
481 cmmEqType :: CmmType -> CmmType -> Bool -- Exact equality
482 cmmEqType (CmmType c1 w1) (CmmType c2 w2) = c1==c2 && w1==w2
484 cmmEqType_ignoring_ptrhood :: CmmType -> CmmType -> Bool
485 -- This equality is temporary; used in CmmLint
486 -- but the RTS files are not yet well-typed wrt pointers
487 cmmEqType_ignoring_ptrhood (CmmType c1 w1) (CmmType c2 w2)
488 = c1 `weak_eq` c2 && w1==w2
490 FloatCat `weak_eq` FloatCat = True
491 FloatCat `weak_eq` _other = False
492 _other `weak_eq` FloatCat = False
493 _word1 `weak_eq` _word2 = True -- Ignores GcPtr
495 --- Simple operations on CmmType -----
496 typeWidth :: CmmType -> Width
497 typeWidth (CmmType _ w) = w
499 cmmBits, cmmFloat :: Width -> CmmType
500 cmmBits = CmmType BitsCat
501 cmmFloat = CmmType FloatCat
503 -------- Common CmmTypes ------------
504 -- Floats and words of specific widths
505 b8, b16, b32, b64, f32, f64 :: CmmType
513 -- CmmTypes of native word widths
514 bWord, bHalfWord, gcWord :: CmmType
515 bWord = cmmBits wordWidth
516 bHalfWord = cmmBits halfWordWidth
517 gcWord = CmmType GcPtrCat wordWidth
519 cInt, cLong :: CmmType
520 cInt = cmmBits cIntWidth
521 cLong = cmmBits cLongWidth
524 ------------ Predicates ----------------
525 isFloatType, isGcPtrType :: CmmType -> Bool
526 isFloatType (CmmType FloatCat _) = True
527 isFloatType _other = False
529 isGcPtrType (CmmType GcPtrCat _) = True
530 isGcPtrType _other = False
532 isWord32, isWord64, isFloat32, isFloat64 :: CmmType -> Bool
533 -- isWord64 is true of 64-bit non-floats (both gc-ptrs and otherwise)
534 -- isFloat32 and 64 are obvious
536 isWord64 (CmmType BitsCat W64) = True
537 isWord64 (CmmType GcPtrCat W64) = True
538 isWord64 _other = False
540 isWord32 (CmmType BitsCat W32) = True
541 isWord32 (CmmType GcPtrCat W32) = True
542 isWord32 _other = False
544 isFloat32 (CmmType FloatCat W32) = True
545 isFloat32 _other = False
547 isFloat64 (CmmType FloatCat W64) = True
548 isFloat64 _other = False
550 -----------------------------------------------------------------------------
552 -----------------------------------------------------------------------------
554 data Width = W8 | W16 | W32 | W64
555 | W80 -- Extended double-precision float,
556 -- used in x86 native codegen only.
557 -- (we use Ord, so it'd better be in this order)
559 deriving (Eq, Ord, Show)
561 instance Outputable Width where
562 ppr rep = ptext (mrStr rep)
564 mrStr :: Width -> LitString
565 mrStr W8 = sLit("W8")
566 mrStr W16 = sLit("W16")
567 mrStr W32 = sLit("W32")
568 mrStr W64 = sLit("W64")
569 mrStr W128 = sLit("W128")
570 mrStr W80 = sLit("W80")
573 -------- Common Widths ------------
574 wordWidth, halfWordWidth :: Width
575 wordWidth | wORD_SIZE == 4 = W32
576 | wORD_SIZE == 8 = W64
577 | otherwise = panic "MachOp.wordRep: Unknown word size"
579 halfWordWidth | wORD_SIZE == 4 = W16
580 | wORD_SIZE == 8 = W32
581 | otherwise = panic "MachOp.halfWordRep: Unknown word size"
583 -- cIntRep is the Width for a C-language 'int'
584 cIntWidth, cLongWidth :: Width
587 #elif SIZEOF_INT == 8
593 #elif SIZEOF_LONG == 8
597 widthInBits :: Width -> Int
602 widthInBits W128 = 128
605 widthInBytes :: Width -> Int
610 widthInBytes W128 = 16
611 widthInBytes W80 = 10
613 widthFromBytes :: Int -> Width
614 widthFromBytes 1 = W8
615 widthFromBytes 2 = W16
616 widthFromBytes 4 = W32
617 widthFromBytes 8 = W64
618 widthFromBytes 16 = W128
619 widthFromBytes 10 = W80
620 widthFromBytes n = pprPanic "no width for given number of bytes" (ppr n)
622 -- log_2 of the width in bytes, useful for generating shifts.
623 widthInLog :: Width -> Int
629 widthInLog W80 = panic "widthInLog: F80"
631 -- widening / narrowing
633 narrowU :: Width -> Integer -> Integer
634 narrowU W8 x = fromIntegral (fromIntegral x :: Word8)
635 narrowU W16 x = fromIntegral (fromIntegral x :: Word16)
636 narrowU W32 x = fromIntegral (fromIntegral x :: Word32)
637 narrowU W64 x = fromIntegral (fromIntegral x :: Word64)
638 narrowU _ _ = panic "narrowTo"
640 narrowS :: Width -> Integer -> Integer
641 narrowS W8 x = fromIntegral (fromIntegral x :: Int8)
642 narrowS W16 x = fromIntegral (fromIntegral x :: Int16)
643 narrowS W32 x = fromIntegral (fromIntegral x :: Int32)
644 narrowS W64 x = fromIntegral (fromIntegral x :: Int64)
645 narrowS _ _ = panic "narrowTo"
647 -----------------------------------------------------------------------------
649 -----------------------------------------------------------------------------
652 Implementation notes:
654 It might suffice to keep just a width, without distinguishing between
655 floating and integer types. However, keeping the distinction will
656 help the native code generator to assign registers more easily.
661 Machine-level primops; ones which we can reasonably delegate to the
662 native code generators to handle. Basically contains C's primops
665 Nomenclature: all ops indicate width and signedness, where
666 appropriate. Widths: 8\/16\/32\/64 means the given size, obviously.
667 Nat means the operation works on STG word sized objects.
668 Signedness: S means signed, U means unsigned. For operations where
669 signedness is irrelevant or makes no difference (for example
670 integer add), the signedness component is omitted.
672 An exception: NatP is a ptr-typed native word. From the point of
673 view of the native code generators this distinction is irrelevant,
674 but the C code generator sometimes needs this info to emit the
679 -- Integer operations (insensitive to signed/unsigned)
684 | MO_Mul Width -- low word of multiply
686 -- Signed multiply/divide
687 | MO_S_MulMayOflo Width -- nonzero if signed multiply overflows
688 | MO_S_Quot Width -- signed / (same semantics as IntQuotOp)
689 | MO_S_Rem Width -- signed % (same semantics as IntRemOp)
690 | MO_S_Neg Width -- unary -
692 -- Unsigned multiply/divide
693 | MO_U_MulMayOflo Width -- nonzero if unsigned multiply overflows
694 | MO_U_Quot Width -- unsigned / (same semantics as WordQuotOp)
695 | MO_U_Rem Width -- unsigned % (same semantics as WordRemOp)
697 -- Signed comparisons
703 -- Unsigned comparisons
709 -- Floating point arithmetic
712 | MO_F_Neg Width -- unary -
716 -- Floating point comparison
724 -- Bitwise operations. Not all of these may be supported
725 -- at all sizes, and only integral Widths are valid.
731 | MO_U_Shr Width -- unsigned shift right
732 | MO_S_Shr Width -- signed shift right
734 -- Conversions. Some of these will be NOPs.
735 -- Floating-point conversions use the signed variant.
736 | MO_SF_Conv Width Width -- Signed int -> Float
737 | MO_FS_Conv Width Width -- Float -> Signed int
738 | MO_SS_Conv Width Width -- Signed int -> Signed int
739 | MO_UU_Conv Width Width -- unsigned int -> unsigned int
740 | MO_FF_Conv Width Width -- Float -> Float
743 pprMachOp :: MachOp -> SDoc
744 pprMachOp mo = text (show mo)
748 -- -----------------------------------------------------------------------------
749 -- Some common MachReps
751 -- A 'wordRep' is a machine word on the target architecture
752 -- Specifically, it is the size of an Int#, Word#, Addr#
753 -- and the unit of allocation on the stack and the heap
754 -- Any pointer is also guaranteed to be a wordRep.
756 mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
757 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
758 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
759 , mo_wordULe, mo_wordUGt, mo_wordULt
760 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
761 , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
762 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
763 , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32
766 mo_wordAdd = MO_Add wordWidth
767 mo_wordSub = MO_Sub wordWidth
768 mo_wordEq = MO_Eq wordWidth
769 mo_wordNe = MO_Ne wordWidth
770 mo_wordMul = MO_Mul wordWidth
771 mo_wordSQuot = MO_S_Quot wordWidth
772 mo_wordSRem = MO_S_Rem wordWidth
773 mo_wordSNeg = MO_S_Neg wordWidth
774 mo_wordUQuot = MO_U_Quot wordWidth
775 mo_wordURem = MO_U_Rem wordWidth
777 mo_wordSGe = MO_S_Ge wordWidth
778 mo_wordSLe = MO_S_Le wordWidth
779 mo_wordSGt = MO_S_Gt wordWidth
780 mo_wordSLt = MO_S_Lt wordWidth
782 mo_wordUGe = MO_U_Ge wordWidth
783 mo_wordULe = MO_U_Le wordWidth
784 mo_wordUGt = MO_U_Gt wordWidth
785 mo_wordULt = MO_U_Lt wordWidth
787 mo_wordAnd = MO_And wordWidth
788 mo_wordOr = MO_Or wordWidth
789 mo_wordXor = MO_Xor wordWidth
790 mo_wordNot = MO_Not wordWidth
791 mo_wordShl = MO_Shl wordWidth
792 mo_wordSShr = MO_S_Shr wordWidth
793 mo_wordUShr = MO_U_Shr wordWidth
795 mo_u_8To32 = MO_UU_Conv W8 W32
796 mo_s_8To32 = MO_SS_Conv W8 W32
797 mo_u_16To32 = MO_UU_Conv W16 W32
798 mo_s_16To32 = MO_SS_Conv W16 W32
800 mo_u_8ToWord = MO_UU_Conv W8 wordWidth
801 mo_s_8ToWord = MO_SS_Conv W8 wordWidth
802 mo_u_16ToWord = MO_UU_Conv W16 wordWidth
803 mo_s_16ToWord = MO_SS_Conv W16 wordWidth
804 mo_s_32ToWord = MO_SS_Conv W32 wordWidth
805 mo_u_32ToWord = MO_UU_Conv W32 wordWidth
807 mo_WordTo8 = MO_UU_Conv wordWidth W8
808 mo_WordTo16 = MO_UU_Conv wordWidth W16
809 mo_WordTo32 = MO_UU_Conv wordWidth W32
811 mo_32To8 = MO_UU_Conv W32 W8
812 mo_32To16 = MO_UU_Conv W32 W16
815 -- ----------------------------------------------------------------------------
816 -- isCommutableMachOp
819 Returns 'True' if the MachOp has commutable arguments. This is used
820 in the platform-independent Cmm optimisations.
822 If in doubt, return 'False'. This generates worse code on the
823 native routes, but is otherwise harmless.
825 isCommutableMachOp :: MachOp -> Bool
826 isCommutableMachOp mop =
832 MO_S_MulMayOflo _ -> True
833 MO_U_MulMayOflo _ -> True
839 -- ----------------------------------------------------------------------------
840 -- isAssociativeMachOp
843 Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
844 This is used in the platform-independent Cmm optimisations.
846 If in doubt, return 'False'. This generates worse code on the
847 native routes, but is otherwise harmless.
849 isAssociativeMachOp :: MachOp -> Bool
850 isAssociativeMachOp mop =
852 MO_Add {} -> True -- NB: does not include
853 MO_Mul {} -> True -- floatint point!
859 -- ----------------------------------------------------------------------------
860 -- isComparisonMachOp
863 Returns 'True' if the MachOp is a comparison.
865 If in doubt, return False. This generates worse code on the
866 native routes, but is otherwise harmless.
868 isComparisonMachOp :: MachOp -> Bool
869 isComparisonMachOp mop =
889 -- -----------------------------------------------------------------------------
890 -- Inverting conditions
892 -- Sometimes it's useful to be able to invert the sense of a
893 -- condition. Not all conditional tests are invertible: in
894 -- particular, floating point conditionals cannot be inverted, because
895 -- there exist floating-point values which return False for both senses
896 -- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).
898 maybeInvertComparison :: MachOp -> Maybe MachOp
899 maybeInvertComparison op
900 = case op of -- None of these Just cases include floating point
901 MO_Eq r -> Just (MO_Ne r)
902 MO_Ne r -> Just (MO_Eq r)
903 MO_U_Lt r -> Just (MO_U_Ge r)
904 MO_U_Gt r -> Just (MO_U_Le r)
905 MO_U_Le r -> Just (MO_U_Gt r)
906 MO_U_Ge r -> Just (MO_U_Lt r)
907 MO_S_Lt r -> Just (MO_S_Ge r)
908 MO_S_Gt r -> Just (MO_S_Le r)
909 MO_S_Le r -> Just (MO_S_Gt r)
910 MO_S_Ge r -> Just (MO_S_Lt r)
911 MO_F_Eq r -> Just (MO_F_Ne r)
912 MO_F_Ne r -> Just (MO_F_Eq r)
913 MO_F_Ge r -> Just (MO_F_Le r)
914 MO_F_Le r -> Just (MO_F_Ge r)
915 MO_F_Gt r -> Just (MO_F_Lt r)
916 MO_F_Lt r -> Just (MO_F_Gt r)
919 -- ----------------------------------------------------------------------------
923 Returns the MachRep of the result of a MachOp.
925 machOpResultType :: MachOp -> [CmmType] -> CmmType
926 machOpResultType mop tys =
928 MO_Add {} -> ty1 -- Preserve GC-ptr-hood
929 MO_Sub {} -> ty1 -- of first arg
930 MO_Mul r -> cmmBits r
931 MO_S_MulMayOflo r -> cmmBits r
932 MO_S_Quot r -> cmmBits r
933 MO_S_Rem r -> cmmBits r
934 MO_S_Neg r -> cmmBits r
935 MO_U_MulMayOflo r -> cmmBits r
936 MO_U_Quot r -> cmmBits r
937 MO_U_Rem r -> cmmBits r
939 MO_Eq {} -> comparisonResultRep
940 MO_Ne {} -> comparisonResultRep
941 MO_S_Ge {} -> comparisonResultRep
942 MO_S_Le {} -> comparisonResultRep
943 MO_S_Gt {} -> comparisonResultRep
944 MO_S_Lt {} -> comparisonResultRep
946 MO_U_Ge {} -> comparisonResultRep
947 MO_U_Le {} -> comparisonResultRep
948 MO_U_Gt {} -> comparisonResultRep
949 MO_U_Lt {} -> comparisonResultRep
951 MO_F_Add r -> cmmFloat r
952 MO_F_Sub r -> cmmFloat r
953 MO_F_Mul r -> cmmFloat r
954 MO_F_Quot r -> cmmFloat r
955 MO_F_Neg r -> cmmFloat r
956 MO_F_Eq {} -> comparisonResultRep
957 MO_F_Ne {} -> comparisonResultRep
958 MO_F_Ge {} -> comparisonResultRep
959 MO_F_Le {} -> comparisonResultRep
960 MO_F_Gt {} -> comparisonResultRep
961 MO_F_Lt {} -> comparisonResultRep
963 MO_And {} -> ty1 -- Used for pointer masking
966 MO_Not r -> cmmBits r
967 MO_Shl r -> cmmBits r
968 MO_U_Shr r -> cmmBits r
969 MO_S_Shr r -> cmmBits r
971 MO_SS_Conv _ to -> cmmBits to
972 MO_UU_Conv _ to -> cmmBits to
973 MO_FS_Conv _ to -> cmmBits to
974 MO_SF_Conv _ to -> cmmFloat to
975 MO_FF_Conv _ to -> cmmFloat to
979 comparisonResultRep :: CmmType
980 comparisonResultRep = bWord -- is it?
983 -- -----------------------------------------------------------------------------
986 -- | This function is used for debugging only: we can check whether an
987 -- application of a MachOp is "type-correct" by checking that the MachReps of
988 -- its arguments are the same as the MachOp expects. This is used when
989 -- linting a CmmExpr.
991 machOpArgReps :: MachOp -> [Width]
999 MO_S_MulMayOflo r -> [r,r]
1000 MO_S_Quot r -> [r,r]
1003 MO_U_MulMayOflo r -> [r,r]
1004 MO_U_Quot r -> [r,r]
1020 MO_F_Quot r -> [r,r]
1033 MO_Shl r -> [r,wordWidth]
1034 MO_U_Shr r -> [r,wordWidth]
1035 MO_S_Shr r -> [r,wordWidth]
1037 MO_SS_Conv from _ -> [from]
1038 MO_UU_Conv from _ -> [from]
1039 MO_SF_Conv from _ -> [from]
1040 MO_FS_Conv from _ -> [from]
1041 MO_FF_Conv from _ -> [from]
1044 -------------------------------------------------------------------------
1045 {- Note [Signed vs unsigned]
1046 ~~~~~~~~~~~~~~~~~~~~~~~~~
1047 Should a CmmType include a signed vs. unsigned distinction?
1049 This is very much like a "hint" in C-- terminology: it isn't necessary
1050 in order to generate correct code, but it might be useful in that the
1051 compiler can generate better code if it has access to higher-level
1052 hints about data. This is important at call boundaries, because the
1053 definition of a function is not visible at all of its call sites, so
1054 the compiler cannot infer the hints.
1056 Here in Cmm, we're taking a slightly different approach. We include
1057 the int vs. float hint in the MachRep, because (a) the majority of
1058 platforms have a strong distinction between float and int registers,
1059 and (b) we don't want to do any heavyweight hint-inference in the
1060 native code backend in order to get good code. We're treating the
1061 hint more like a type: our Cmm is always completely consistent with
1062 respect to hints. All coercions between float and int are explicit.
1064 What about the signed vs. unsigned hint? This information might be
1065 useful if we want to keep sub-word-sized values in word-size
1066 registers, which we must do if we only have word-sized registers.
1068 On such a system, there are two straightforward conventions for
1069 representing sub-word-sized values:
1071 (a) Leave the upper bits undefined. Comparison operations must
1072 sign- or zero-extend both operands before comparing them,
1073 depending on whether the comparison is signed or unsigned.
1075 (b) Always keep the values sign- or zero-extended as appropriate.
1076 Arithmetic operations must narrow the result to the appropriate
1079 A clever compiler might not use either (a) or (b) exclusively, instead
1080 it would attempt to minimize the coercions by analysis: the same kind
1081 of analysis that propagates hints around. In Cmm we don't want to
1082 have to do this, so we plump for having richer types and keeping the
1083 type information consistent.
1085 If signed/unsigned hints are missing from MachRep, then the only
1086 choice we have is (a), because we don't know whether the result of an
1087 operation should be sign- or zero-extended.
1089 Many architectures have extending load operations, which work well
1090 with (b). To make use of them with (a), you need to know whether the
1091 value is going to be sign- or zero-extended by an enclosing comparison
1092 (for example), which involves knowing above the context. This is
1093 doable but more complex.
1095 Further complicating the issue is foreign calls: a foreign calling
1096 convention can specify that signed 8-bit quantities are passed as
1097 sign-extended 32 bit quantities, for example (this is the case on the
1098 PowerPC). So we *do* need sign information on foreign call arguments.
1100 Pros for adding signed vs. unsigned to MachRep:
1102 - It would let us use convention (b) above, and get easier
1103 code generation for extending loads.
1105 - Less information required on foreign calls.
1107 - MachOp type would be simpler
1113 - What is the MachRep for a VanillaReg? Currently it is
1114 always wordRep, but now we have to decide whether it is
1115 signed or unsigned. The same VanillaReg can thus have
1116 different MachReps in different parts of the program.
1118 - Extra coercions cluttering up expressions.
1120 Currently for GHC, the foreign call point is moot, because we do our
1121 own promotion of sub-word-sized values to word-sized values. The Int8
1122 type is represnted by an Int# which is kept sign-extended at all times
1123 (this is slightly naughty, because we're making assumptions about the
1124 C calling convention rather early on in the compiler). However, given
1125 this, the cons outweigh the pros.