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, StackSlotMap, getSlot
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 mkVarSlot :: LocalReg -> CmmExpr
267 mkVarSlot r = CmmStackSlot (RegSlot r) 0
269 -- Usually, we either want to lookup a variable's spill slot in an environment
270 -- or else allocate it and add it to the environment.
271 -- For a variable, we just need a single area of the appropriate size.
272 type StackSlotMap = FiniteMap LocalReg CmmExpr
273 getSlot :: StackSlotMap -> LocalReg -> (StackSlotMap, CmmExpr)
274 getSlot map r = case lookupFM map r of
276 Nothing -> (addToFM map r s, s) where s = mkVarSlot r
278 -----------------------------------------------------------------------------
279 -- Stack slot use information for expressions and other types [_$_]
280 -----------------------------------------------------------------------------
283 -- Fold over the area, the offset into the area, and the width of the subarea.
284 class UserOfSlots a where
285 foldSlotsUsed :: (b -> SubArea -> b) -> b -> a -> b
287 class DefinerOfSlots a where
288 foldSlotsDefd :: (b -> SubArea -> b) -> b -> a -> b
290 instance UserOfSlots CmmExpr where
291 foldSlotsUsed f z e = expr z e
292 where expr z (CmmLit _) = z
293 expr z (CmmLoad (CmmStackSlot a i) ty) = f z (a, i, widthInBytes $ typeWidth ty)
294 expr z (CmmLoad addr _) = foldSlotsUsed f z addr
295 expr z (CmmReg _) = z
296 expr z (CmmMachOp _ exprs) = foldSlotsUsed f z exprs
297 expr z (CmmRegOff _ _) = z
298 expr z (CmmStackSlot _ _) = z
300 instance UserOfSlots a => UserOfSlots [a] where
301 foldSlotsUsed _ set [] = set
302 foldSlotsUsed f set (x:xs) = foldSlotsUsed f (foldSlotsUsed f set x) xs
305 -----------------------------------------------------------------------------
306 -- Global STG registers
307 -----------------------------------------------------------------------------
309 data VGcPtr = VGcPtr | VNonGcPtr deriving( Eq, Show )
312 -----------------------------------------------------------------------------
313 -- Global STG registers
314 -----------------------------------------------------------------------------
315 vgcFlag :: CmmType -> VGcPtr
316 vgcFlag ty | isGcPtrType ty = VGcPtr
317 | otherwise = VNonGcPtr
320 -- Argument and return registers
321 = VanillaReg -- pointers, unboxed ints and chars
322 {-# UNPACK #-} !Int -- its number
325 | FloatReg -- single-precision floating-point registers
326 {-# UNPACK #-} !Int -- its number
328 | DoubleReg -- double-precision floating-point registers
329 {-# UNPACK #-} !Int -- its number
331 | LongReg -- long int registers (64-bit, really)
332 {-# UNPACK #-} !Int -- its number
335 | Sp -- Stack ptr; points to last occupied stack location.
336 | SpLim -- Stack limit
337 | Hp -- Heap ptr; points to last occupied heap location.
338 | HpLim -- Heap limit register
339 | CurrentTSO -- pointer to current thread's TSO
340 | CurrentNursery -- pointer to allocation area
341 | HpAlloc -- allocation count for heap check failure
343 -- We keep the address of some commonly-called
344 -- functions in the register table, to keep code
346 | EagerBlackholeInfo -- stg_EAGER_BLACKHOLE_info
347 | GCEnter1 -- stg_gc_enter_1
348 | GCFun -- stg_gc_fun
350 -- Base offset for the register table, used for accessing registers
351 -- which do not have real registers assigned to them. This register
352 -- will only appear after we have expanded GlobalReg into memory accesses
353 -- (where necessary) in the native code generator.
356 -- Base Register for PIC (position-independent code) calculations
357 -- Only used inside the native code generator. It's exact meaning differs
358 -- from platform to platform (see module PositionIndependentCode).
363 instance Eq GlobalReg where
364 VanillaReg i _ == VanillaReg j _ = i==j -- Ignore type when seeking clashes
365 FloatReg i == FloatReg j = i==j
366 DoubleReg i == DoubleReg j = i==j
367 LongReg i == LongReg j = i==j
369 SpLim == SpLim = True
371 HpLim == HpLim = True
372 CurrentTSO == CurrentTSO = True
373 CurrentNursery == CurrentNursery = True
374 HpAlloc == HpAlloc = True
375 GCEnter1 == GCEnter1 = True
376 GCFun == GCFun = True
377 BaseReg == BaseReg = True
378 PicBaseReg == PicBaseReg = True
381 instance Ord GlobalReg where
382 compare (VanillaReg i _) (VanillaReg j _) = compare i j
383 -- Ignore type when seeking clashes
384 compare (FloatReg i) (FloatReg j) = compare i j
385 compare (DoubleReg i) (DoubleReg j) = compare i j
386 compare (LongReg i) (LongReg j) = compare i j
388 compare SpLim SpLim = EQ
390 compare HpLim HpLim = EQ
391 compare CurrentTSO CurrentTSO = EQ
392 compare CurrentNursery CurrentNursery = EQ
393 compare HpAlloc HpAlloc = EQ
394 compare EagerBlackholeInfo EagerBlackholeInfo = EQ
395 compare GCEnter1 GCEnter1 = EQ
396 compare GCFun GCFun = EQ
397 compare BaseReg BaseReg = EQ
398 compare PicBaseReg PicBaseReg = EQ
399 compare (VanillaReg _ _) _ = LT
400 compare _ (VanillaReg _ _) = GT
401 compare (FloatReg _) _ = LT
402 compare _ (FloatReg _) = GT
403 compare (DoubleReg _) _ = LT
404 compare _ (DoubleReg _) = GT
405 compare (LongReg _) _ = LT
406 compare _ (LongReg _) = GT
415 compare CurrentTSO _ = LT
416 compare _ CurrentTSO = GT
417 compare CurrentNursery _ = LT
418 compare _ CurrentNursery = GT
419 compare HpAlloc _ = LT
420 compare _ HpAlloc = GT
421 compare GCEnter1 _ = LT
422 compare _ GCEnter1 = GT
425 compare BaseReg _ = LT
426 compare _ BaseReg = GT
427 compare EagerBlackholeInfo _ = LT
428 compare _ EagerBlackholeInfo = GT
430 -- convenient aliases
431 spReg, hpReg, spLimReg, nodeReg :: CmmReg
434 spLimReg = CmmGlobal SpLim
435 nodeReg = CmmGlobal node
438 node = VanillaReg 1 VGcPtr
440 globalRegType :: GlobalReg -> CmmType
441 globalRegType (VanillaReg _ VGcPtr) = gcWord
442 globalRegType (VanillaReg _ VNonGcPtr) = bWord
443 globalRegType (FloatReg _) = cmmFloat W32
444 globalRegType (DoubleReg _) = cmmFloat W64
445 globalRegType (LongReg _) = cmmBits W64
446 globalRegType Hp = gcWord -- The initialiser for all
447 -- dynamically allocated closures
448 globalRegType _ = bWord
451 -----------------------------------------------------------------------------
453 -----------------------------------------------------------------------------
455 -- NOTE: CmmType is an abstract type, not exported from this
456 -- module so you can easily change its representation
458 -- However Width is exported in a concrete way,
459 -- and is used extensively in pattern-matching
461 data CmmType -- The important one!
462 = CmmType CmmCat Width
464 data CmmCat -- "Category" (not exported)
465 = GcPtrCat -- GC pointer
466 | BitsCat -- Non-pointer
469 -- See Note [Signed vs unsigned] at the end
471 instance Outputable CmmType where
472 ppr (CmmType cat wid) = ppr cat <> ppr (widthInBits wid)
474 instance Outputable CmmCat where
475 ppr FloatCat = ptext $ sLit("F")
476 ppr _ = ptext $ sLit("I")
478 -- ppr FloatCat = ptext $ sLit("float")
479 -- ppr BitsCat = ptext $ sLit("bits")
480 -- ppr GcPtrCat = ptext $ sLit("gcptr")
482 -- Why is CmmType stratified? For native code generation,
483 -- most of the time you just want to know what sort of register
484 -- to put the thing in, and for this you need to know how
485 -- many bits thing has and whether it goes in a floating-point
486 -- register. By contrast, the distinction between GcPtr and
487 -- GcNonPtr is of interest to only a few parts of the code generator.
489 -------- Equality on CmmType --------------
490 -- CmmType is *not* an instance of Eq; sometimes we care about the
491 -- Gc/NonGc distinction, and sometimes we don't
492 -- So we use an explicit function to force you to think about it
493 cmmEqType :: CmmType -> CmmType -> Bool -- Exact equality
494 cmmEqType (CmmType c1 w1) (CmmType c2 w2) = c1==c2 && w1==w2
496 cmmEqType_ignoring_ptrhood :: CmmType -> CmmType -> Bool
497 -- This equality is temporary; used in CmmLint
498 -- but the RTS files are not yet well-typed wrt pointers
499 cmmEqType_ignoring_ptrhood (CmmType c1 w1) (CmmType c2 w2)
500 = c1 `weak_eq` c2 && w1==w2
502 FloatCat `weak_eq` FloatCat = True
503 FloatCat `weak_eq` _other = False
504 _other `weak_eq` FloatCat = False
505 _word1 `weak_eq` _word2 = True -- Ignores GcPtr
507 --- Simple operations on CmmType -----
508 typeWidth :: CmmType -> Width
509 typeWidth (CmmType _ w) = w
511 cmmBits, cmmFloat :: Width -> CmmType
512 cmmBits = CmmType BitsCat
513 cmmFloat = CmmType FloatCat
515 -------- Common CmmTypes ------------
516 -- Floats and words of specific widths
517 b8, b16, b32, b64, f32, f64 :: CmmType
525 -- CmmTypes of native word widths
526 bWord, bHalfWord, gcWord :: CmmType
527 bWord = cmmBits wordWidth
528 bHalfWord = cmmBits halfWordWidth
529 gcWord = CmmType GcPtrCat wordWidth
531 cInt, cLong :: CmmType
532 cInt = cmmBits cIntWidth
533 cLong = cmmBits cLongWidth
536 ------------ Predicates ----------------
537 isFloatType, isGcPtrType :: CmmType -> Bool
538 isFloatType (CmmType FloatCat _) = True
539 isFloatType _other = False
541 isGcPtrType (CmmType GcPtrCat _) = True
542 isGcPtrType _other = False
544 isWord32, isWord64, isFloat32, isFloat64 :: CmmType -> Bool
545 -- isWord64 is true of 64-bit non-floats (both gc-ptrs and otherwise)
546 -- isFloat32 and 64 are obvious
548 isWord64 (CmmType BitsCat W64) = True
549 isWord64 (CmmType GcPtrCat W64) = True
550 isWord64 _other = False
552 isWord32 (CmmType BitsCat W32) = True
553 isWord32 (CmmType GcPtrCat W32) = True
554 isWord32 _other = False
556 isFloat32 (CmmType FloatCat W32) = True
557 isFloat32 _other = False
559 isFloat64 (CmmType FloatCat W64) = True
560 isFloat64 _other = False
562 -----------------------------------------------------------------------------
564 -----------------------------------------------------------------------------
566 data Width = W8 | W16 | W32 | W64
567 | W80 -- Extended double-precision float,
568 -- used in x86 native codegen only.
569 -- (we use Ord, so it'd better be in this order)
571 deriving (Eq, Ord, Show)
573 instance Outputable Width where
574 ppr rep = ptext (mrStr rep)
576 mrStr :: Width -> LitString
577 mrStr W8 = sLit("W8")
578 mrStr W16 = sLit("W16")
579 mrStr W32 = sLit("W32")
580 mrStr W64 = sLit("W64")
581 mrStr W128 = sLit("W128")
582 mrStr W80 = sLit("W80")
585 -------- Common Widths ------------
586 wordWidth, halfWordWidth :: Width
587 wordWidth | wORD_SIZE == 4 = W32
588 | wORD_SIZE == 8 = W64
589 | otherwise = panic "MachOp.wordRep: Unknown word size"
591 halfWordWidth | wORD_SIZE == 4 = W16
592 | wORD_SIZE == 8 = W32
593 | otherwise = panic "MachOp.halfWordRep: Unknown word size"
595 -- cIntRep is the Width for a C-language 'int'
596 cIntWidth, cLongWidth :: Width
599 #elif SIZEOF_INT == 8
605 #elif SIZEOF_LONG == 8
609 widthInBits :: Width -> Int
614 widthInBits W128 = 128
617 widthInBytes :: Width -> Int
622 widthInBytes W128 = 16
623 widthInBytes W80 = 10
625 widthFromBytes :: Int -> Width
626 widthFromBytes 1 = W8
627 widthFromBytes 2 = W16
628 widthFromBytes 4 = W32
629 widthFromBytes 8 = W64
630 widthFromBytes 16 = W128
631 widthFromBytes 10 = W80
632 widthFromBytes n = pprPanic "no width for given number of bytes" (ppr n)
634 -- log_2 of the width in bytes, useful for generating shifts.
635 widthInLog :: Width -> Int
641 widthInLog W80 = panic "widthInLog: F80"
643 -- widening / narrowing
645 narrowU :: Width -> Integer -> Integer
646 narrowU W8 x = fromIntegral (fromIntegral x :: Word8)
647 narrowU W16 x = fromIntegral (fromIntegral x :: Word16)
648 narrowU W32 x = fromIntegral (fromIntegral x :: Word32)
649 narrowU W64 x = fromIntegral (fromIntegral x :: Word64)
650 narrowU _ _ = panic "narrowTo"
652 narrowS :: Width -> Integer -> Integer
653 narrowS W8 x = fromIntegral (fromIntegral x :: Int8)
654 narrowS W16 x = fromIntegral (fromIntegral x :: Int16)
655 narrowS W32 x = fromIntegral (fromIntegral x :: Int32)
656 narrowS W64 x = fromIntegral (fromIntegral x :: Int64)
657 narrowS _ _ = panic "narrowTo"
659 -----------------------------------------------------------------------------
661 -----------------------------------------------------------------------------
664 Implementation notes:
666 It might suffice to keep just a width, without distinguishing between
667 floating and integer types. However, keeping the distinction will
668 help the native code generator to assign registers more easily.
673 Machine-level primops; ones which we can reasonably delegate to the
674 native code generators to handle. Basically contains C's primops
677 Nomenclature: all ops indicate width and signedness, where
678 appropriate. Widths: 8\/16\/32\/64 means the given size, obviously.
679 Nat means the operation works on STG word sized objects.
680 Signedness: S means signed, U means unsigned. For operations where
681 signedness is irrelevant or makes no difference (for example
682 integer add), the signedness component is omitted.
684 An exception: NatP is a ptr-typed native word. From the point of
685 view of the native code generators this distinction is irrelevant,
686 but the C code generator sometimes needs this info to emit the
691 -- Integer operations (insensitive to signed/unsigned)
696 | MO_Mul Width -- low word of multiply
698 -- Signed multiply/divide
699 | MO_S_MulMayOflo Width -- nonzero if signed multiply overflows
700 | MO_S_Quot Width -- signed / (same semantics as IntQuotOp)
701 | MO_S_Rem Width -- signed % (same semantics as IntRemOp)
702 | MO_S_Neg Width -- unary -
704 -- Unsigned multiply/divide
705 | MO_U_MulMayOflo Width -- nonzero if unsigned multiply overflows
706 | MO_U_Quot Width -- unsigned / (same semantics as WordQuotOp)
707 | MO_U_Rem Width -- unsigned % (same semantics as WordRemOp)
709 -- Signed comparisons
715 -- Unsigned comparisons
721 -- Floating point arithmetic
724 | MO_F_Neg Width -- unary -
728 -- Floating point comparison
736 -- Bitwise operations. Not all of these may be supported
737 -- at all sizes, and only integral Widths are valid.
743 | MO_U_Shr Width -- unsigned shift right
744 | MO_S_Shr Width -- signed shift right
746 -- Conversions. Some of these will be NOPs.
747 -- Floating-point conversions use the signed variant.
748 | MO_SF_Conv Width Width -- Signed int -> Float
749 | MO_FS_Conv Width Width -- Float -> Signed int
750 | MO_SS_Conv Width Width -- Signed int -> Signed int
751 | MO_UU_Conv Width Width -- unsigned int -> unsigned int
752 | MO_FF_Conv Width Width -- Float -> Float
755 pprMachOp :: MachOp -> SDoc
756 pprMachOp mo = text (show mo)
760 -- -----------------------------------------------------------------------------
761 -- Some common MachReps
763 -- A 'wordRep' is a machine word on the target architecture
764 -- Specifically, it is the size of an Int#, Word#, Addr#
765 -- and the unit of allocation on the stack and the heap
766 -- Any pointer is also guaranteed to be a wordRep.
768 mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
769 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
770 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
771 , mo_wordULe, mo_wordUGt, mo_wordULt
772 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
773 , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
774 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
775 , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32
778 mo_wordAdd = MO_Add wordWidth
779 mo_wordSub = MO_Sub wordWidth
780 mo_wordEq = MO_Eq wordWidth
781 mo_wordNe = MO_Ne wordWidth
782 mo_wordMul = MO_Mul wordWidth
783 mo_wordSQuot = MO_S_Quot wordWidth
784 mo_wordSRem = MO_S_Rem wordWidth
785 mo_wordSNeg = MO_S_Neg wordWidth
786 mo_wordUQuot = MO_U_Quot wordWidth
787 mo_wordURem = MO_U_Rem wordWidth
789 mo_wordSGe = MO_S_Ge wordWidth
790 mo_wordSLe = MO_S_Le wordWidth
791 mo_wordSGt = MO_S_Gt wordWidth
792 mo_wordSLt = MO_S_Lt wordWidth
794 mo_wordUGe = MO_U_Ge wordWidth
795 mo_wordULe = MO_U_Le wordWidth
796 mo_wordUGt = MO_U_Gt wordWidth
797 mo_wordULt = MO_U_Lt wordWidth
799 mo_wordAnd = MO_And wordWidth
800 mo_wordOr = MO_Or wordWidth
801 mo_wordXor = MO_Xor wordWidth
802 mo_wordNot = MO_Not wordWidth
803 mo_wordShl = MO_Shl wordWidth
804 mo_wordSShr = MO_S_Shr wordWidth
805 mo_wordUShr = MO_U_Shr wordWidth
807 mo_u_8To32 = MO_UU_Conv W8 W32
808 mo_s_8To32 = MO_SS_Conv W8 W32
809 mo_u_16To32 = MO_UU_Conv W16 W32
810 mo_s_16To32 = MO_SS_Conv W16 W32
812 mo_u_8ToWord = MO_UU_Conv W8 wordWidth
813 mo_s_8ToWord = MO_SS_Conv W8 wordWidth
814 mo_u_16ToWord = MO_UU_Conv W16 wordWidth
815 mo_s_16ToWord = MO_SS_Conv W16 wordWidth
816 mo_s_32ToWord = MO_SS_Conv W32 wordWidth
817 mo_u_32ToWord = MO_UU_Conv W32 wordWidth
819 mo_WordTo8 = MO_UU_Conv wordWidth W8
820 mo_WordTo16 = MO_UU_Conv wordWidth W16
821 mo_WordTo32 = MO_UU_Conv wordWidth W32
823 mo_32To8 = MO_UU_Conv W32 W8
824 mo_32To16 = MO_UU_Conv W32 W16
827 -- ----------------------------------------------------------------------------
828 -- isCommutableMachOp
831 Returns 'True' if the MachOp has commutable arguments. This is used
832 in the platform-independent Cmm optimisations.
834 If in doubt, return 'False'. This generates worse code on the
835 native routes, but is otherwise harmless.
837 isCommutableMachOp :: MachOp -> Bool
838 isCommutableMachOp mop =
844 MO_S_MulMayOflo _ -> True
845 MO_U_MulMayOflo _ -> True
851 -- ----------------------------------------------------------------------------
852 -- isAssociativeMachOp
855 Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
856 This is used in the platform-independent Cmm optimisations.
858 If in doubt, return 'False'. This generates worse code on the
859 native routes, but is otherwise harmless.
861 isAssociativeMachOp :: MachOp -> Bool
862 isAssociativeMachOp mop =
864 MO_Add {} -> True -- NB: does not include
865 MO_Mul {} -> True -- floatint point!
871 -- ----------------------------------------------------------------------------
872 -- isComparisonMachOp
875 Returns 'True' if the MachOp is a comparison.
877 If in doubt, return False. This generates worse code on the
878 native routes, but is otherwise harmless.
880 isComparisonMachOp :: MachOp -> Bool
881 isComparisonMachOp mop =
901 -- -----------------------------------------------------------------------------
902 -- Inverting conditions
904 -- Sometimes it's useful to be able to invert the sense of a
905 -- condition. Not all conditional tests are invertible: in
906 -- particular, floating point conditionals cannot be inverted, because
907 -- there exist floating-point values which return False for both senses
908 -- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).
910 maybeInvertComparison :: MachOp -> Maybe MachOp
911 maybeInvertComparison op
912 = case op of -- None of these Just cases include floating point
913 MO_Eq r -> Just (MO_Ne r)
914 MO_Ne r -> Just (MO_Eq r)
915 MO_U_Lt r -> Just (MO_U_Ge r)
916 MO_U_Gt r -> Just (MO_U_Le r)
917 MO_U_Le r -> Just (MO_U_Gt r)
918 MO_U_Ge r -> Just (MO_U_Lt r)
919 MO_S_Lt r -> Just (MO_S_Ge r)
920 MO_S_Gt r -> Just (MO_S_Le r)
921 MO_S_Le r -> Just (MO_S_Gt r)
922 MO_S_Ge r -> Just (MO_S_Lt r)
923 MO_F_Eq r -> Just (MO_F_Ne r)
924 MO_F_Ne r -> Just (MO_F_Eq r)
925 MO_F_Ge r -> Just (MO_F_Le r)
926 MO_F_Le r -> Just (MO_F_Ge r)
927 MO_F_Gt r -> Just (MO_F_Lt r)
928 MO_F_Lt r -> Just (MO_F_Gt r)
931 -- ----------------------------------------------------------------------------
935 Returns the MachRep of the result of a MachOp.
937 machOpResultType :: MachOp -> [CmmType] -> CmmType
938 machOpResultType mop tys =
940 MO_Add {} -> ty1 -- Preserve GC-ptr-hood
941 MO_Sub {} -> ty1 -- of first arg
942 MO_Mul r -> cmmBits r
943 MO_S_MulMayOflo r -> cmmBits r
944 MO_S_Quot r -> cmmBits r
945 MO_S_Rem r -> cmmBits r
946 MO_S_Neg r -> cmmBits r
947 MO_U_MulMayOflo r -> cmmBits r
948 MO_U_Quot r -> cmmBits r
949 MO_U_Rem r -> cmmBits r
951 MO_Eq {} -> comparisonResultRep
952 MO_Ne {} -> comparisonResultRep
953 MO_S_Ge {} -> comparisonResultRep
954 MO_S_Le {} -> comparisonResultRep
955 MO_S_Gt {} -> comparisonResultRep
956 MO_S_Lt {} -> comparisonResultRep
958 MO_U_Ge {} -> comparisonResultRep
959 MO_U_Le {} -> comparisonResultRep
960 MO_U_Gt {} -> comparisonResultRep
961 MO_U_Lt {} -> comparisonResultRep
963 MO_F_Add r -> cmmFloat r
964 MO_F_Sub r -> cmmFloat r
965 MO_F_Mul r -> cmmFloat r
966 MO_F_Quot r -> cmmFloat r
967 MO_F_Neg r -> cmmFloat r
968 MO_F_Eq {} -> comparisonResultRep
969 MO_F_Ne {} -> comparisonResultRep
970 MO_F_Ge {} -> comparisonResultRep
971 MO_F_Le {} -> comparisonResultRep
972 MO_F_Gt {} -> comparisonResultRep
973 MO_F_Lt {} -> comparisonResultRep
975 MO_And {} -> ty1 -- Used for pointer masking
978 MO_Not r -> cmmBits r
979 MO_Shl r -> cmmBits r
980 MO_U_Shr r -> cmmBits r
981 MO_S_Shr r -> cmmBits r
983 MO_SS_Conv _ to -> cmmBits to
984 MO_UU_Conv _ to -> cmmBits to
985 MO_FS_Conv _ to -> cmmBits to
986 MO_SF_Conv _ to -> cmmFloat to
987 MO_FF_Conv _ to -> cmmFloat to
991 comparisonResultRep :: CmmType
992 comparisonResultRep = bWord -- is it?
995 -- -----------------------------------------------------------------------------
998 -- | This function is used for debugging only: we can check whether an
999 -- application of a MachOp is "type-correct" by checking that the MachReps of
1000 -- its arguments are the same as the MachOp expects. This is used when
1001 -- linting a CmmExpr.
1003 machOpArgReps :: MachOp -> [Width]
1011 MO_S_MulMayOflo r -> [r,r]
1012 MO_S_Quot r -> [r,r]
1015 MO_U_MulMayOflo r -> [r,r]
1016 MO_U_Quot r -> [r,r]
1032 MO_F_Quot r -> [r,r]
1045 MO_Shl r -> [r,wordWidth]
1046 MO_U_Shr r -> [r,wordWidth]
1047 MO_S_Shr r -> [r,wordWidth]
1049 MO_SS_Conv from _ -> [from]
1050 MO_UU_Conv from _ -> [from]
1051 MO_SF_Conv from _ -> [from]
1052 MO_FS_Conv from _ -> [from]
1053 MO_FF_Conv from _ -> [from]
1056 -------------------------------------------------------------------------
1057 {- Note [Signed vs unsigned]
1058 ~~~~~~~~~~~~~~~~~~~~~~~~~
1059 Should a CmmType include a signed vs. unsigned distinction?
1061 This is very much like a "hint" in C-- terminology: it isn't necessary
1062 in order to generate correct code, but it might be useful in that the
1063 compiler can generate better code if it has access to higher-level
1064 hints about data. This is important at call boundaries, because the
1065 definition of a function is not visible at all of its call sites, so
1066 the compiler cannot infer the hints.
1068 Here in Cmm, we're taking a slightly different approach. We include
1069 the int vs. float hint in the MachRep, because (a) the majority of
1070 platforms have a strong distinction between float and int registers,
1071 and (b) we don't want to do any heavyweight hint-inference in the
1072 native code backend in order to get good code. We're treating the
1073 hint more like a type: our Cmm is always completely consistent with
1074 respect to hints. All coercions between float and int are explicit.
1076 What about the signed vs. unsigned hint? This information might be
1077 useful if we want to keep sub-word-sized values in word-size
1078 registers, which we must do if we only have word-sized registers.
1080 On such a system, there are two straightforward conventions for
1081 representing sub-word-sized values:
1083 (a) Leave the upper bits undefined. Comparison operations must
1084 sign- or zero-extend both operands before comparing them,
1085 depending on whether the comparison is signed or unsigned.
1087 (b) Always keep the values sign- or zero-extended as appropriate.
1088 Arithmetic operations must narrow the result to the appropriate
1091 A clever compiler might not use either (a) or (b) exclusively, instead
1092 it would attempt to minimize the coercions by analysis: the same kind
1093 of analysis that propagates hints around. In Cmm we don't want to
1094 have to do this, so we plump for having richer types and keeping the
1095 type information consistent.
1097 If signed/unsigned hints are missing from MachRep, then the only
1098 choice we have is (a), because we don't know whether the result of an
1099 operation should be sign- or zero-extended.
1101 Many architectures have extending load operations, which work well
1102 with (b). To make use of them with (a), you need to know whether the
1103 value is going to be sign- or zero-extended by an enclosing comparison
1104 (for example), which involves knowing above the context. This is
1105 doable but more complex.
1107 Further complicating the issue is foreign calls: a foreign calling
1108 convention can specify that signed 8-bit quantities are passed as
1109 sign-extended 32 bit quantities, for example (this is the case on the
1110 PowerPC). So we *do* need sign information on foreign call arguments.
1112 Pros for adding signed vs. unsigned to MachRep:
1114 - It would let us use convention (b) above, and get easier
1115 code generation for extending loads.
1117 - Less information required on foreign calls.
1119 - MachOp type would be simpler
1125 - What is the MachRep for a VanillaReg? Currently it is
1126 always wordRep, but now we have to decide whether it is
1127 signed or unsigned. The same VanillaReg can thus have
1128 different MachReps in different parts of the program.
1130 - Extra coercions cluttering up expressions.
1132 Currently for GHC, the foreign call point is moot, because we do our
1133 own promotion of sub-word-sized values to word-sized values. The Int8
1134 type is represnted by an Int# which is kept sign-extended at all times
1135 (this is slightly naughty, because we're making assumptions about the
1136 C calling convention rather early on in the compiler). However, given
1137 this, the cons outweigh the pros.