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"
62 -----------------------------------------------------------------------------
64 -- An expression. Expressions have no side effects.
65 -----------------------------------------------------------------------------
68 = CmmLit CmmLit -- Literal
69 | CmmLoad CmmExpr CmmType -- Read memory location
70 | CmmReg CmmReg -- Contents of register
71 | CmmMachOp MachOp [CmmExpr] -- Machine operation (+, -, *, etc.)
72 | CmmStackSlot Area Int -- addressing expression of a stack slot
73 | CmmRegOff CmmReg Int
75 -- ** is shorthand only, meaning **
76 -- CmmMachOp (MO_S_Add rep (CmmReg reg) (CmmLit (CmmInt i rep)))
77 -- where rep = cmmRegType reg
79 instance Eq CmmExpr where -- Equality ignores the types
80 CmmLit l1 == CmmLit l2 = l1==l2
81 CmmLoad e1 _ == CmmLoad e2 _ = e1==e2
82 CmmReg r1 == CmmReg r2 = r1==r2
83 CmmRegOff r1 i1 == CmmRegOff r2 i2 = r1==r2 && i1==i2
84 CmmMachOp op1 es1 == CmmMachOp op2 es2 = op1==op2 && es1==es2
85 CmmStackSlot a1 i1 == CmmStackSlot a2 i2 = a1==a2 && i1==i2
93 -- | A stack area is either the stack slot where a variable is spilled
94 -- or the stack space where function arguments and results are passed.
101 = Old -- entry parameters, jumps, and returns share one call area at old end of stack
105 type SubArea = (Area, Int, Int) -- area, offset, width
106 type SubAreaSet = FiniteMap Area [SubArea]
107 type AreaMap = FiniteMap Area Int
110 = CmmInt Integer Width
111 -- Interpretation: the 2's complement representation of the value
112 -- is truncated to the specified size. This is easier than trying
113 -- to keep the value within range, because we don't know whether
114 -- it will be used as a signed or unsigned value (the CmmType doesn't
115 -- distinguish between signed & unsigned).
116 | CmmFloat Rational Width
117 | CmmLabel CLabel -- Address of label
118 | CmmLabelOff CLabel Int -- Address of label + byte offset
120 -- Due to limitations in the C backend, the following
121 -- MUST ONLY be used inside the info table indicated by label2
122 -- (label2 must be the info label), and label1 must be an
123 -- SRT, a slow entrypoint or a large bitmap (see the Mangler)
124 -- Don't use it at all unless tablesNextToCode.
125 -- It is also used inside the NCG during when generating
126 -- position-independent code.
127 | CmmLabelDiffOff CLabel CLabel Int -- label1 - label2 + offset
128 | CmmBlock BlockId -- Code label
129 | CmmHighStackMark -- stands for the max stack space used during a procedure
132 cmmExprType :: CmmExpr -> CmmType
133 cmmExprType (CmmLit lit) = cmmLitType lit
134 cmmExprType (CmmLoad _ rep) = rep
135 cmmExprType (CmmReg reg) = cmmRegType reg
136 cmmExprType (CmmMachOp op args) = machOpResultType op (map cmmExprType args)
137 cmmExprType (CmmRegOff reg _) = cmmRegType reg
138 cmmExprType (CmmStackSlot _ _) = bWord -- an address
140 cmmLitType :: CmmLit -> CmmType
141 cmmLitType (CmmInt _ width) = cmmBits width
142 cmmLitType (CmmFloat _ width) = cmmFloat width
143 cmmLitType (CmmLabel lbl) = cmmLabelType lbl
144 cmmLitType (CmmLabelOff lbl _) = cmmLabelType lbl
145 cmmLitType (CmmLabelDiffOff {}) = bWord
146 cmmLitType (CmmBlock _) = bWord
147 cmmLitType (CmmHighStackMark) = bWord
149 cmmLabelType :: CLabel -> CmmType
150 cmmLabelType lbl | isGcPtrLabel lbl = gcWord
153 cmmExprWidth :: CmmExpr -> Width
154 cmmExprWidth e = typeWidth (cmmExprType e)
157 --- Negation for conditional branches
159 maybeInvertCmmExpr :: CmmExpr -> Maybe CmmExpr
160 maybeInvertCmmExpr (CmmMachOp op args) = do op' <- maybeInvertComparison op
161 return (CmmMachOp op' args)
162 maybeInvertCmmExpr _ = Nothing
164 -----------------------------------------------------------------------------
166 -----------------------------------------------------------------------------
169 = LocalReg !Unique CmmType
174 instance Eq LocalReg where
175 (LocalReg u1 _) == (LocalReg u2 _) = u1 == u2
177 instance Ord LocalReg where
178 compare (LocalReg u1 _) (LocalReg u2 _) = compare u1 u2
180 instance Uniquable LocalReg where
181 getUnique (LocalReg uniq _) = uniq
183 cmmRegType :: CmmReg -> CmmType
184 cmmRegType (CmmLocal reg) = localRegType reg
185 cmmRegType (CmmGlobal reg) = globalRegType reg
187 localRegType :: LocalReg -> CmmType
188 localRegType (LocalReg _ rep) = rep
190 -----------------------------------------------------------------------------
191 -- Register-use information for expressions and other types
192 -----------------------------------------------------------------------------
194 -- | Sets of local registers
195 type RegSet = UniqSet LocalReg
196 emptyRegSet :: RegSet
197 elemRegSet :: LocalReg -> RegSet -> Bool
198 extendRegSet :: RegSet -> LocalReg -> RegSet
199 deleteFromRegSet :: RegSet -> LocalReg -> RegSet
200 mkRegSet :: [LocalReg] -> RegSet
201 minusRegSet, plusRegSet, timesRegSet :: RegSet -> RegSet -> RegSet
203 emptyRegSet = emptyUniqSet
204 elemRegSet = elementOfUniqSet
205 extendRegSet = addOneToUniqSet
206 deleteFromRegSet = delOneFromUniqSet
208 minusRegSet = minusUniqSet
209 plusRegSet = unionUniqSets
210 timesRegSet = intersectUniqSets
212 class UserOfLocalRegs a where
213 foldRegsUsed :: (b -> LocalReg -> b) -> b -> a -> b
215 class DefinerOfLocalRegs a where
216 foldRegsDefd :: (b -> LocalReg -> b) -> b -> a -> b
218 filterRegsUsed :: UserOfLocalRegs e => (LocalReg -> Bool) -> e -> RegSet
220 foldRegsUsed (\regs r -> if p r then extendRegSet regs r else regs)
223 instance UserOfLocalRegs CmmReg where
224 foldRegsUsed f z (CmmLocal reg) = f z reg
225 foldRegsUsed _ z (CmmGlobal _) = z
227 instance DefinerOfLocalRegs CmmReg where
228 foldRegsDefd f z (CmmLocal reg) = f z reg
229 foldRegsDefd _ z (CmmGlobal _) = z
231 instance UserOfLocalRegs LocalReg where
232 foldRegsUsed f z r = f z r
234 instance DefinerOfLocalRegs LocalReg where
235 foldRegsDefd f z r = f z r
237 instance UserOfLocalRegs RegSet where
238 foldRegsUsed f = foldUniqSet (flip f)
240 instance UserOfLocalRegs CmmExpr where
241 foldRegsUsed f z e = expr z e
242 where expr z (CmmLit _) = z
243 expr z (CmmLoad addr _) = foldRegsUsed f z addr
244 expr z (CmmReg r) = foldRegsUsed f z r
245 expr z (CmmMachOp _ exprs) = foldRegsUsed f z exprs
246 expr z (CmmRegOff r _) = foldRegsUsed f z r
247 expr z (CmmStackSlot _ _) = z
249 instance UserOfLocalRegs a => UserOfLocalRegs [a] where
250 foldRegsUsed _ set [] = set
251 foldRegsUsed f set (x:xs) = foldRegsUsed f (foldRegsUsed f set x) xs
253 instance DefinerOfLocalRegs a => DefinerOfLocalRegs [a] where
254 foldRegsDefd _ set [] = set
255 foldRegsDefd f set (x:xs) = foldRegsDefd f (foldRegsDefd f set x) xs
257 instance DefinerOfLocalRegs a => DefinerOfLocalRegs (Maybe a) where
258 foldRegsDefd _ set Nothing = set
259 foldRegsDefd f set (Just x) = foldRegsDefd f set x
262 -----------------------------------------------------------------------------
264 -----------------------------------------------------------------------------
266 isStackSlotOf :: CmmExpr -> LocalReg -> Bool
267 isStackSlotOf (CmmStackSlot (RegSlot r) _) r' = r == r'
268 isStackSlotOf _ _ = False
270 -----------------------------------------------------------------------------
271 -- Stack slot use information for expressions and other types [_$_]
272 -----------------------------------------------------------------------------
274 -- Fold over the area, the offset into the area, and the width of the subarea.
275 class UserOfSlots a where
276 foldSlotsUsed :: (b -> SubArea -> b) -> b -> a -> b
278 class DefinerOfSlots a where
279 foldSlotsDefd :: (b -> SubArea -> b) -> b -> a -> b
281 instance UserOfSlots CmmExpr where
282 foldSlotsUsed f z e = expr z e
283 where expr z (CmmLit _) = z
284 expr z (CmmLoad (CmmStackSlot a i) ty) = f z (a, i, widthInBytes $ typeWidth ty)
285 expr z (CmmLoad addr _) = foldSlotsUsed f z addr
286 expr z (CmmReg _) = z
287 expr z (CmmMachOp _ exprs) = foldSlotsUsed f z exprs
288 expr z (CmmRegOff _ _) = z
289 expr z (CmmStackSlot _ _) = z
291 instance UserOfSlots a => UserOfSlots [a] where
292 foldSlotsUsed _ set [] = set
293 foldSlotsUsed f set (x:xs) = foldSlotsUsed f (foldSlotsUsed f set x) xs
296 -----------------------------------------------------------------------------
297 -- Global STG registers
298 -----------------------------------------------------------------------------
300 data VGcPtr = VGcPtr | VNonGcPtr deriving( Eq, Show )
303 -----------------------------------------------------------------------------
304 -- Global STG registers
305 -----------------------------------------------------------------------------
306 vgcFlag :: CmmType -> VGcPtr
307 vgcFlag ty | isGcPtrType ty = VGcPtr
308 | otherwise = VNonGcPtr
311 -- Argument and return registers
312 = VanillaReg -- pointers, unboxed ints and chars
313 {-# UNPACK #-} !Int -- its number
316 | FloatReg -- single-precision floating-point registers
317 {-# UNPACK #-} !Int -- its number
319 | DoubleReg -- double-precision floating-point registers
320 {-# UNPACK #-} !Int -- its number
322 | LongReg -- long int registers (64-bit, really)
323 {-# UNPACK #-} !Int -- its number
326 | Sp -- Stack ptr; points to last occupied stack location.
327 | SpLim -- Stack limit
328 | Hp -- Heap ptr; points to last occupied heap location.
329 | HpLim -- Heap limit register
330 | CurrentTSO -- pointer to current thread's TSO
331 | CurrentNursery -- pointer to allocation area
332 | HpAlloc -- allocation count for heap check failure
334 -- We keep the address of some commonly-called
335 -- functions in the register table, to keep code
337 | EagerBlackholeInfo -- stg_EAGER_BLACKHOLE_info
338 | GCEnter1 -- stg_gc_enter_1
339 | GCFun -- stg_gc_fun
341 -- Base offset for the register table, used for accessing registers
342 -- which do not have real registers assigned to them. This register
343 -- will only appear after we have expanded GlobalReg into memory accesses
344 -- (where necessary) in the native code generator.
347 -- Base Register for PIC (position-independent code) calculations
348 -- Only used inside the native code generator. It's exact meaning differs
349 -- from platform to platform (see module PositionIndependentCode).
354 instance Eq GlobalReg where
355 VanillaReg i _ == VanillaReg j _ = i==j -- Ignore type when seeking clashes
356 FloatReg i == FloatReg j = i==j
357 DoubleReg i == DoubleReg j = i==j
358 LongReg i == LongReg j = i==j
360 SpLim == SpLim = True
362 HpLim == HpLim = True
363 CurrentTSO == CurrentTSO = True
364 CurrentNursery == CurrentNursery = True
365 HpAlloc == HpAlloc = True
366 GCEnter1 == GCEnter1 = True
367 GCFun == GCFun = True
368 BaseReg == BaseReg = True
369 PicBaseReg == PicBaseReg = True
372 instance Ord GlobalReg where
373 compare (VanillaReg i _) (VanillaReg j _) = compare i j
374 -- Ignore type when seeking clashes
375 compare (FloatReg i) (FloatReg j) = compare i j
376 compare (DoubleReg i) (DoubleReg j) = compare i j
377 compare (LongReg i) (LongReg j) = compare i j
379 compare SpLim SpLim = EQ
381 compare HpLim HpLim = EQ
382 compare CurrentTSO CurrentTSO = EQ
383 compare CurrentNursery CurrentNursery = EQ
384 compare HpAlloc HpAlloc = EQ
385 compare EagerBlackholeInfo EagerBlackholeInfo = EQ
386 compare GCEnter1 GCEnter1 = EQ
387 compare GCFun GCFun = EQ
388 compare BaseReg BaseReg = EQ
389 compare PicBaseReg PicBaseReg = EQ
390 compare (VanillaReg _ _) _ = LT
391 compare _ (VanillaReg _ _) = GT
392 compare (FloatReg _) _ = LT
393 compare _ (FloatReg _) = GT
394 compare (DoubleReg _) _ = LT
395 compare _ (DoubleReg _) = GT
396 compare (LongReg _) _ = LT
397 compare _ (LongReg _) = GT
406 compare CurrentTSO _ = LT
407 compare _ CurrentTSO = GT
408 compare CurrentNursery _ = LT
409 compare _ CurrentNursery = GT
410 compare HpAlloc _ = LT
411 compare _ HpAlloc = GT
412 compare GCEnter1 _ = LT
413 compare _ GCEnter1 = GT
416 compare BaseReg _ = LT
417 compare _ BaseReg = GT
418 compare EagerBlackholeInfo _ = LT
419 compare _ EagerBlackholeInfo = GT
421 -- convenient aliases
422 spReg, hpReg, spLimReg, nodeReg :: CmmReg
425 spLimReg = CmmGlobal SpLim
426 nodeReg = CmmGlobal node
429 node = VanillaReg 1 VGcPtr
431 globalRegType :: GlobalReg -> CmmType
432 globalRegType (VanillaReg _ VGcPtr) = gcWord
433 globalRegType (VanillaReg _ VNonGcPtr) = bWord
434 globalRegType (FloatReg _) = cmmFloat W32
435 globalRegType (DoubleReg _) = cmmFloat W64
436 globalRegType (LongReg _) = cmmBits W64
437 globalRegType Hp = gcWord -- The initialiser for all
438 -- dynamically allocated closures
439 globalRegType _ = bWord
442 -----------------------------------------------------------------------------
444 -----------------------------------------------------------------------------
446 -- NOTE: CmmType is an abstract type, not exported from this
447 -- module so you can easily change its representation
449 -- However Width is exported in a concrete way,
450 -- and is used extensively in pattern-matching
452 data CmmType -- The important one!
453 = CmmType CmmCat Width
455 data CmmCat -- "Category" (not exported)
456 = GcPtrCat -- GC pointer
457 | BitsCat -- Non-pointer
460 -- See Note [Signed vs unsigned] at the end
462 instance Outputable CmmType where
463 ppr (CmmType cat wid) = ppr cat <> ppr (widthInBits wid)
465 instance Outputable CmmCat where
466 ppr FloatCat = ptext $ sLit("F")
467 ppr _ = ptext $ sLit("I")
469 -- ppr FloatCat = ptext $ sLit("float")
470 -- ppr BitsCat = ptext $ sLit("bits")
471 -- ppr GcPtrCat = ptext $ sLit("gcptr")
473 -- Why is CmmType stratified? For native code generation,
474 -- most of the time you just want to know what sort of register
475 -- to put the thing in, and for this you need to know how
476 -- many bits thing has and whether it goes in a floating-point
477 -- register. By contrast, the distinction between GcPtr and
478 -- GcNonPtr is of interest to only a few parts of the code generator.
480 -------- Equality on CmmType --------------
481 -- CmmType is *not* an instance of Eq; sometimes we care about the
482 -- Gc/NonGc distinction, and sometimes we don't
483 -- So we use an explicit function to force you to think about it
484 cmmEqType :: CmmType -> CmmType -> Bool -- Exact equality
485 cmmEqType (CmmType c1 w1) (CmmType c2 w2) = c1==c2 && w1==w2
487 cmmEqType_ignoring_ptrhood :: CmmType -> CmmType -> Bool
488 -- This equality is temporary; used in CmmLint
489 -- but the RTS files are not yet well-typed wrt pointers
490 cmmEqType_ignoring_ptrhood (CmmType c1 w1) (CmmType c2 w2)
491 = c1 `weak_eq` c2 && w1==w2
493 FloatCat `weak_eq` FloatCat = True
494 FloatCat `weak_eq` _other = False
495 _other `weak_eq` FloatCat = False
496 _word1 `weak_eq` _word2 = True -- Ignores GcPtr
498 --- Simple operations on CmmType -----
499 typeWidth :: CmmType -> Width
500 typeWidth (CmmType _ w) = w
502 cmmBits, cmmFloat :: Width -> CmmType
503 cmmBits = CmmType BitsCat
504 cmmFloat = CmmType FloatCat
506 -------- Common CmmTypes ------------
507 -- Floats and words of specific widths
508 b8, b16, b32, b64, f32, f64 :: CmmType
516 -- CmmTypes of native word widths
517 bWord, bHalfWord, gcWord :: CmmType
518 bWord = cmmBits wordWidth
519 bHalfWord = cmmBits halfWordWidth
520 gcWord = CmmType GcPtrCat wordWidth
522 cInt, cLong :: CmmType
523 cInt = cmmBits cIntWidth
524 cLong = cmmBits cLongWidth
527 ------------ Predicates ----------------
528 isFloatType, isGcPtrType :: CmmType -> Bool
529 isFloatType (CmmType FloatCat _) = True
530 isFloatType _other = False
532 isGcPtrType (CmmType GcPtrCat _) = True
533 isGcPtrType _other = False
535 isWord32, isWord64, isFloat32, isFloat64 :: CmmType -> Bool
536 -- isWord64 is true of 64-bit non-floats (both gc-ptrs and otherwise)
537 -- isFloat32 and 64 are obvious
539 isWord64 (CmmType BitsCat W64) = True
540 isWord64 (CmmType GcPtrCat W64) = True
541 isWord64 _other = False
543 isWord32 (CmmType BitsCat W32) = True
544 isWord32 (CmmType GcPtrCat W32) = True
545 isWord32 _other = False
547 isFloat32 (CmmType FloatCat W32) = True
548 isFloat32 _other = False
550 isFloat64 (CmmType FloatCat W64) = True
551 isFloat64 _other = False
553 -----------------------------------------------------------------------------
555 -----------------------------------------------------------------------------
557 data Width = W8 | W16 | W32 | W64
558 | W80 -- Extended double-precision float,
559 -- used in x86 native codegen only.
560 -- (we use Ord, so it'd better be in this order)
562 deriving (Eq, Ord, Show)
564 instance Outputable Width where
565 ppr rep = ptext (mrStr rep)
567 mrStr :: Width -> LitString
568 mrStr W8 = sLit("W8")
569 mrStr W16 = sLit("W16")
570 mrStr W32 = sLit("W32")
571 mrStr W64 = sLit("W64")
572 mrStr W128 = sLit("W128")
573 mrStr W80 = sLit("W80")
576 -------- Common Widths ------------
577 wordWidth, halfWordWidth :: Width
578 wordWidth | wORD_SIZE == 4 = W32
579 | wORD_SIZE == 8 = W64
580 | otherwise = panic "MachOp.wordRep: Unknown word size"
582 halfWordWidth | wORD_SIZE == 4 = W16
583 | wORD_SIZE == 8 = W32
584 | otherwise = panic "MachOp.halfWordRep: Unknown word size"
586 -- cIntRep is the Width for a C-language 'int'
587 cIntWidth, cLongWidth :: Width
590 #elif SIZEOF_INT == 8
596 #elif SIZEOF_LONG == 8
600 widthInBits :: Width -> Int
605 widthInBits W128 = 128
608 widthInBytes :: Width -> Int
613 widthInBytes W128 = 16
614 widthInBytes W80 = 10
616 widthFromBytes :: Int -> Width
617 widthFromBytes 1 = W8
618 widthFromBytes 2 = W16
619 widthFromBytes 4 = W32
620 widthFromBytes 8 = W64
621 widthFromBytes 16 = W128
622 widthFromBytes 10 = W80
623 widthFromBytes n = pprPanic "no width for given number of bytes" (ppr n)
625 -- log_2 of the width in bytes, useful for generating shifts.
626 widthInLog :: Width -> Int
632 widthInLog W80 = panic "widthInLog: F80"
634 -- widening / narrowing
636 narrowU :: Width -> Integer -> Integer
637 narrowU W8 x = fromIntegral (fromIntegral x :: Word8)
638 narrowU W16 x = fromIntegral (fromIntegral x :: Word16)
639 narrowU W32 x = fromIntegral (fromIntegral x :: Word32)
640 narrowU W64 x = fromIntegral (fromIntegral x :: Word64)
641 narrowU _ _ = panic "narrowTo"
643 narrowS :: Width -> Integer -> Integer
644 narrowS W8 x = fromIntegral (fromIntegral x :: Int8)
645 narrowS W16 x = fromIntegral (fromIntegral x :: Int16)
646 narrowS W32 x = fromIntegral (fromIntegral x :: Int32)
647 narrowS W64 x = fromIntegral (fromIntegral x :: Int64)
648 narrowS _ _ = panic "narrowTo"
650 -----------------------------------------------------------------------------
652 -----------------------------------------------------------------------------
655 Implementation notes:
657 It might suffice to keep just a width, without distinguishing between
658 floating and integer types. However, keeping the distinction will
659 help the native code generator to assign registers more easily.
664 Machine-level primops; ones which we can reasonably delegate to the
665 native code generators to handle. Basically contains C's primops
668 Nomenclature: all ops indicate width and signedness, where
669 appropriate. Widths: 8\/16\/32\/64 means the given size, obviously.
670 Nat means the operation works on STG word sized objects.
671 Signedness: S means signed, U means unsigned. For operations where
672 signedness is irrelevant or makes no difference (for example
673 integer add), the signedness component is omitted.
675 An exception: NatP is a ptr-typed native word. From the point of
676 view of the native code generators this distinction is irrelevant,
677 but the C code generator sometimes needs this info to emit the
682 -- Integer operations (insensitive to signed/unsigned)
687 | MO_Mul Width -- low word of multiply
689 -- Signed multiply/divide
690 | MO_S_MulMayOflo Width -- nonzero if signed multiply overflows
691 | MO_S_Quot Width -- signed / (same semantics as IntQuotOp)
692 | MO_S_Rem Width -- signed % (same semantics as IntRemOp)
693 | MO_S_Neg Width -- unary -
695 -- Unsigned multiply/divide
696 | MO_U_MulMayOflo Width -- nonzero if unsigned multiply overflows
697 | MO_U_Quot Width -- unsigned / (same semantics as WordQuotOp)
698 | MO_U_Rem Width -- unsigned % (same semantics as WordRemOp)
700 -- Signed comparisons
706 -- Unsigned comparisons
712 -- Floating point arithmetic
715 | MO_F_Neg Width -- unary -
719 -- Floating point comparison
727 -- Bitwise operations. Not all of these may be supported
728 -- at all sizes, and only integral Widths are valid.
734 | MO_U_Shr Width -- unsigned shift right
735 | MO_S_Shr Width -- signed shift right
737 -- Conversions. Some of these will be NOPs.
738 -- Floating-point conversions use the signed variant.
739 | MO_SF_Conv Width Width -- Signed int -> Float
740 | MO_FS_Conv Width Width -- Float -> Signed int
741 | MO_SS_Conv Width Width -- Signed int -> Signed int
742 | MO_UU_Conv Width Width -- unsigned int -> unsigned int
743 | MO_FF_Conv Width Width -- Float -> Float
746 pprMachOp :: MachOp -> SDoc
747 pprMachOp mo = text (show mo)
751 -- -----------------------------------------------------------------------------
752 -- Some common MachReps
754 -- A 'wordRep' is a machine word on the target architecture
755 -- Specifically, it is the size of an Int#, Word#, Addr#
756 -- and the unit of allocation on the stack and the heap
757 -- Any pointer is also guaranteed to be a wordRep.
759 mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
760 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
761 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
762 , mo_wordULe, mo_wordUGt, mo_wordULt
763 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
764 , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
765 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
766 , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32
769 mo_wordAdd = MO_Add wordWidth
770 mo_wordSub = MO_Sub wordWidth
771 mo_wordEq = MO_Eq wordWidth
772 mo_wordNe = MO_Ne wordWidth
773 mo_wordMul = MO_Mul wordWidth
774 mo_wordSQuot = MO_S_Quot wordWidth
775 mo_wordSRem = MO_S_Rem wordWidth
776 mo_wordSNeg = MO_S_Neg wordWidth
777 mo_wordUQuot = MO_U_Quot wordWidth
778 mo_wordURem = MO_U_Rem wordWidth
780 mo_wordSGe = MO_S_Ge wordWidth
781 mo_wordSLe = MO_S_Le wordWidth
782 mo_wordSGt = MO_S_Gt wordWidth
783 mo_wordSLt = MO_S_Lt wordWidth
785 mo_wordUGe = MO_U_Ge wordWidth
786 mo_wordULe = MO_U_Le wordWidth
787 mo_wordUGt = MO_U_Gt wordWidth
788 mo_wordULt = MO_U_Lt wordWidth
790 mo_wordAnd = MO_And wordWidth
791 mo_wordOr = MO_Or wordWidth
792 mo_wordXor = MO_Xor wordWidth
793 mo_wordNot = MO_Not wordWidth
794 mo_wordShl = MO_Shl wordWidth
795 mo_wordSShr = MO_S_Shr wordWidth
796 mo_wordUShr = MO_U_Shr wordWidth
798 mo_u_8To32 = MO_UU_Conv W8 W32
799 mo_s_8To32 = MO_SS_Conv W8 W32
800 mo_u_16To32 = MO_UU_Conv W16 W32
801 mo_s_16To32 = MO_SS_Conv W16 W32
803 mo_u_8ToWord = MO_UU_Conv W8 wordWidth
804 mo_s_8ToWord = MO_SS_Conv W8 wordWidth
805 mo_u_16ToWord = MO_UU_Conv W16 wordWidth
806 mo_s_16ToWord = MO_SS_Conv W16 wordWidth
807 mo_s_32ToWord = MO_SS_Conv W32 wordWidth
808 mo_u_32ToWord = MO_UU_Conv W32 wordWidth
810 mo_WordTo8 = MO_UU_Conv wordWidth W8
811 mo_WordTo16 = MO_UU_Conv wordWidth W16
812 mo_WordTo32 = MO_UU_Conv wordWidth W32
814 mo_32To8 = MO_UU_Conv W32 W8
815 mo_32To16 = MO_UU_Conv W32 W16
818 -- ----------------------------------------------------------------------------
819 -- isCommutableMachOp
822 Returns 'True' if the MachOp has commutable arguments. This is used
823 in the platform-independent Cmm optimisations.
825 If in doubt, return 'False'. This generates worse code on the
826 native routes, but is otherwise harmless.
828 isCommutableMachOp :: MachOp -> Bool
829 isCommutableMachOp mop =
835 MO_S_MulMayOflo _ -> True
836 MO_U_MulMayOflo _ -> True
842 -- ----------------------------------------------------------------------------
843 -- isAssociativeMachOp
846 Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
847 This is used in the platform-independent Cmm optimisations.
849 If in doubt, return 'False'. This generates worse code on the
850 native routes, but is otherwise harmless.
852 isAssociativeMachOp :: MachOp -> Bool
853 isAssociativeMachOp mop =
855 MO_Add {} -> True -- NB: does not include
856 MO_Mul {} -> True -- floatint point!
862 -- ----------------------------------------------------------------------------
863 -- isComparisonMachOp
866 Returns 'True' if the MachOp is a comparison.
868 If in doubt, return False. This generates worse code on the
869 native routes, but is otherwise harmless.
871 isComparisonMachOp :: MachOp -> Bool
872 isComparisonMachOp mop =
892 -- -----------------------------------------------------------------------------
893 -- Inverting conditions
895 -- Sometimes it's useful to be able to invert the sense of a
896 -- condition. Not all conditional tests are invertible: in
897 -- particular, floating point conditionals cannot be inverted, because
898 -- there exist floating-point values which return False for both senses
899 -- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).
901 maybeInvertComparison :: MachOp -> Maybe MachOp
902 maybeInvertComparison op
903 = case op of -- None of these Just cases include floating point
904 MO_Eq r -> Just (MO_Ne r)
905 MO_Ne r -> Just (MO_Eq r)
906 MO_U_Lt r -> Just (MO_U_Ge r)
907 MO_U_Gt r -> Just (MO_U_Le r)
908 MO_U_Le r -> Just (MO_U_Gt r)
909 MO_U_Ge r -> Just (MO_U_Lt r)
910 MO_S_Lt r -> Just (MO_S_Ge r)
911 MO_S_Gt r -> Just (MO_S_Le r)
912 MO_S_Le r -> Just (MO_S_Gt r)
913 MO_S_Ge r -> Just (MO_S_Lt r)
914 MO_F_Eq r -> Just (MO_F_Ne r)
915 MO_F_Ne r -> Just (MO_F_Eq r)
916 MO_F_Ge r -> Just (MO_F_Le r)
917 MO_F_Le r -> Just (MO_F_Ge r)
918 MO_F_Gt r -> Just (MO_F_Lt r)
919 MO_F_Lt r -> Just (MO_F_Gt r)
922 -- ----------------------------------------------------------------------------
926 Returns the MachRep of the result of a MachOp.
928 machOpResultType :: MachOp -> [CmmType] -> CmmType
929 machOpResultType mop tys =
931 MO_Add {} -> ty1 -- Preserve GC-ptr-hood
932 MO_Sub {} -> ty1 -- of first arg
933 MO_Mul r -> cmmBits r
934 MO_S_MulMayOflo r -> cmmBits r
935 MO_S_Quot r -> cmmBits r
936 MO_S_Rem r -> cmmBits r
937 MO_S_Neg r -> cmmBits r
938 MO_U_MulMayOflo r -> cmmBits r
939 MO_U_Quot r -> cmmBits r
940 MO_U_Rem r -> cmmBits r
942 MO_Eq {} -> comparisonResultRep
943 MO_Ne {} -> comparisonResultRep
944 MO_S_Ge {} -> comparisonResultRep
945 MO_S_Le {} -> comparisonResultRep
946 MO_S_Gt {} -> comparisonResultRep
947 MO_S_Lt {} -> comparisonResultRep
949 MO_U_Ge {} -> comparisonResultRep
950 MO_U_Le {} -> comparisonResultRep
951 MO_U_Gt {} -> comparisonResultRep
952 MO_U_Lt {} -> comparisonResultRep
954 MO_F_Add r -> cmmFloat r
955 MO_F_Sub r -> cmmFloat r
956 MO_F_Mul r -> cmmFloat r
957 MO_F_Quot r -> cmmFloat r
958 MO_F_Neg r -> cmmFloat r
959 MO_F_Eq {} -> comparisonResultRep
960 MO_F_Ne {} -> comparisonResultRep
961 MO_F_Ge {} -> comparisonResultRep
962 MO_F_Le {} -> comparisonResultRep
963 MO_F_Gt {} -> comparisonResultRep
964 MO_F_Lt {} -> comparisonResultRep
966 MO_And {} -> ty1 -- Used for pointer masking
969 MO_Not r -> cmmBits r
970 MO_Shl r -> cmmBits r
971 MO_U_Shr r -> cmmBits r
972 MO_S_Shr r -> cmmBits r
974 MO_SS_Conv _ to -> cmmBits to
975 MO_UU_Conv _ to -> cmmBits to
976 MO_FS_Conv _ to -> cmmBits to
977 MO_SF_Conv _ to -> cmmFloat to
978 MO_FF_Conv _ to -> cmmFloat to
982 comparisonResultRep :: CmmType
983 comparisonResultRep = bWord -- is it?
986 -- -----------------------------------------------------------------------------
989 -- | This function is used for debugging only: we can check whether an
990 -- application of a MachOp is "type-correct" by checking that the MachReps of
991 -- its arguments are the same as the MachOp expects. This is used when
992 -- linting a CmmExpr.
994 machOpArgReps :: MachOp -> [Width]
1002 MO_S_MulMayOflo r -> [r,r]
1003 MO_S_Quot r -> [r,r]
1006 MO_U_MulMayOflo r -> [r,r]
1007 MO_U_Quot r -> [r,r]
1023 MO_F_Quot r -> [r,r]
1036 MO_Shl r -> [r,wordWidth]
1037 MO_U_Shr r -> [r,wordWidth]
1038 MO_S_Shr r -> [r,wordWidth]
1040 MO_SS_Conv from _ -> [from]
1041 MO_UU_Conv from _ -> [from]
1042 MO_SF_Conv from _ -> [from]
1043 MO_FS_Conv from _ -> [from]
1044 MO_FF_Conv from _ -> [from]
1047 -------------------------------------------------------------------------
1048 {- Note [Signed vs unsigned]
1049 ~~~~~~~~~~~~~~~~~~~~~~~~~
1050 Should a CmmType include a signed vs. unsigned distinction?
1052 This is very much like a "hint" in C-- terminology: it isn't necessary
1053 in order to generate correct code, but it might be useful in that the
1054 compiler can generate better code if it has access to higher-level
1055 hints about data. This is important at call boundaries, because the
1056 definition of a function is not visible at all of its call sites, so
1057 the compiler cannot infer the hints.
1059 Here in Cmm, we're taking a slightly different approach. We include
1060 the int vs. float hint in the MachRep, because (a) the majority of
1061 platforms have a strong distinction between float and int registers,
1062 and (b) we don't want to do any heavyweight hint-inference in the
1063 native code backend in order to get good code. We're treating the
1064 hint more like a type: our Cmm is always completely consistent with
1065 respect to hints. All coercions between float and int are explicit.
1067 What about the signed vs. unsigned hint? This information might be
1068 useful if we want to keep sub-word-sized values in word-size
1069 registers, which we must do if we only have word-sized registers.
1071 On such a system, there are two straightforward conventions for
1072 representing sub-word-sized values:
1074 (a) Leave the upper bits undefined. Comparison operations must
1075 sign- or zero-extend both operands before comparing them,
1076 depending on whether the comparison is signed or unsigned.
1078 (b) Always keep the values sign- or zero-extended as appropriate.
1079 Arithmetic operations must narrow the result to the appropriate
1082 A clever compiler might not use either (a) or (b) exclusively, instead
1083 it would attempt to minimize the coercions by analysis: the same kind
1084 of analysis that propagates hints around. In Cmm we don't want to
1085 have to do this, so we plump for having richer types and keeping the
1086 type information consistent.
1088 If signed/unsigned hints are missing from MachRep, then the only
1089 choice we have is (a), because we don't know whether the result of an
1090 operation should be sign- or zero-extended.
1092 Many architectures have extending load operations, which work well
1093 with (b). To make use of them with (a), you need to know whether the
1094 value is going to be sign- or zero-extended by an enclosing comparison
1095 (for example), which involves knowing above the context. This is
1096 doable but more complex.
1098 Further complicating the issue is foreign calls: a foreign calling
1099 convention can specify that signed 8-bit quantities are passed as
1100 sign-extended 32 bit quantities, for example (this is the case on the
1101 PowerPC). So we *do* need sign information on foreign call arguments.
1103 Pros for adding signed vs. unsigned to MachRep:
1105 - It would let us use convention (b) above, and get easier
1106 code generation for extending loads.
1108 - Less information required on foreign calls.
1110 - MachOp type would be simpler
1116 - What is the MachRep for a VanillaReg? Currently it is
1117 always wordRep, but now we have to decide whether it is
1118 signed or unsigned. The same VanillaReg can thus have
1119 different MachReps in different parts of the program.
1121 - Extra coercions cluttering up expressions.
1123 Currently for GHC, the foreign call point is moot, because we do our
1124 own promotion of sub-word-sized values to word-sized values. The Int8
1125 type is represnted by an Int# which is kept sign-extended at all times
1126 (this is slightly naughty, because we're making assumptions about the
1127 C calling convention rather early on in the compiler). However, given
1128 this, the cons outweigh the pros.