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
14 , CmmExpr(..), cmmExprType, cmmExprWidth, maybeInvertCmmExpr
15 , CmmReg(..), cmmRegType
16 , CmmLit(..), cmmLitType
17 , LocalReg(..), localRegType
18 , GlobalReg(..), globalRegType, spReg, hpReg, spLimReg, nodeReg, node
19 , VGcPtr(..), vgcFlag -- Temporary!
20 , DefinerOfLocalRegs, UserOfLocalRegs, foldRegsDefd, foldRegsUsed, filterRegsUsed
21 , DefinerOfSlots, UserOfSlots, foldSlotsDefd, foldSlotsUsed
22 , RegSet, emptyRegSet, elemRegSet, extendRegSet, deleteFromRegSet, mkRegSet
23 , plusRegSet, minusRegSet, timesRegSet
24 , Area(..), AreaId(..), SubArea, SubAreaSet, AreaMap, StackSlotMap, getSlot
28 , pprMachOp, isCommutableMachOp, isAssociativeMachOp
29 , isComparisonMachOp, machOpResultType
30 , machOpArgReps, maybeInvertComparison
33 , mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
34 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
35 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
36 , mo_wordULe, mo_wordUGt, mo_wordULt
37 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
38 , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
39 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
40 , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32
44 #include "HsVersions.h"
58 -----------------------------------------------------------------------------
60 -- An expression. Expressions have no side effects.
61 -----------------------------------------------------------------------------
64 = CmmLit CmmLit -- Literal
65 | CmmLoad CmmExpr CmmType -- Read memory location
66 | CmmReg CmmReg -- Contents of register
67 | CmmMachOp MachOp [CmmExpr] -- Machine operation (+, -, *, etc.)
68 | CmmStackSlot Area Int -- addressing expression of a stack slot
69 | CmmRegOff CmmReg Int
71 -- ** is shorthand only, meaning **
72 -- CmmMachOp (MO_S_Add rep (CmmReg reg) (CmmLit (CmmInt i rep)))
73 -- where rep = cmmRegType reg
75 instance Eq CmmExpr where -- Equality ignores the types
76 CmmLit l1 == CmmLit l2 = l1==l2
77 CmmLoad e1 _ == CmmLoad e2 _ = e1==e2
78 CmmReg r1 == CmmReg r2 = r1==r2
79 CmmRegOff r1 i1 == CmmRegOff r2 i2 = r1==r2 && i1==i2
80 CmmMachOp op1 es1 == CmmMachOp op2 es2 = op1==op2 && es1==es2
81 CmmStackSlot a1 i1 == CmmStackSlot a2 i2 = a1==a2 && i1==i2
89 -- | A stack area is either the stack slot where a variable is spilled
90 -- or the stack space where function arguments and results are passed.
97 = Old -- entry parameters, jumps, and returns share one call area at old end of stack
101 type SubArea = (Area, Int, Int) -- area, offset, width
102 type SubAreaSet = FiniteMap Area [SubArea]
103 type AreaMap = FiniteMap Area Int
106 = CmmInt Integer Width
107 -- Interpretation: the 2's complement representation of the value
108 -- is truncated to the specified size. This is easier than trying
109 -- to keep the value within range, because we don't know whether
110 -- it will be used as a signed or unsigned value (the CmmType doesn't
111 -- distinguish between signed & unsigned).
112 | CmmFloat Rational Width
113 | CmmLabel CLabel -- Address of label
114 | CmmLabelOff CLabel Int -- Address of label + byte offset
116 -- Due to limitations in the C backend, the following
117 -- MUST ONLY be used inside the info table indicated by label2
118 -- (label2 must be the info label), and label1 must be an
119 -- SRT, a slow entrypoint or a large bitmap (see the Mangler)
120 -- Don't use it at all unless tablesNextToCode.
121 -- It is also used inside the NCG during when generating
122 -- position-independent code.
123 | CmmLabelDiffOff CLabel CLabel Int -- label1 - label2 + offset
124 | CmmBlock BlockId -- Code label
125 | CmmHighStackMark -- stands for the max stack space used during a procedure
128 cmmExprType :: CmmExpr -> CmmType
129 cmmExprType (CmmLit lit) = cmmLitType lit
130 cmmExprType (CmmLoad _ rep) = rep
131 cmmExprType (CmmReg reg) = cmmRegType reg
132 cmmExprType (CmmMachOp op args) = machOpResultType op (map cmmExprType args)
133 cmmExprType (CmmRegOff reg _) = cmmRegType reg
134 cmmExprType (CmmStackSlot _ _) = bWord -- an address
136 cmmLitType :: CmmLit -> CmmType
137 cmmLitType (CmmInt _ width) = cmmBits width
138 cmmLitType (CmmFloat _ width) = cmmFloat width
139 cmmLitType (CmmLabel lbl) = cmmLabelType lbl
140 cmmLitType (CmmLabelOff lbl _) = cmmLabelType lbl
141 cmmLitType (CmmLabelDiffOff {}) = bWord
142 cmmLitType (CmmBlock _) = bWord
143 cmmLitType (CmmHighStackMark) = bWord
145 cmmLabelType :: CLabel -> CmmType
146 cmmLabelType lbl | isGcPtrLabel lbl = gcWord
149 cmmExprWidth :: CmmExpr -> Width
150 cmmExprWidth e = typeWidth (cmmExprType e)
153 --- Negation for conditional branches
155 maybeInvertCmmExpr :: CmmExpr -> Maybe CmmExpr
156 maybeInvertCmmExpr (CmmMachOp op args) = do op' <- maybeInvertComparison op
157 return (CmmMachOp op' args)
158 maybeInvertCmmExpr _ = Nothing
160 -----------------------------------------------------------------------------
162 -----------------------------------------------------------------------------
165 = LocalReg !Unique CmmType
170 instance Eq LocalReg where
171 (LocalReg u1 _) == (LocalReg u2 _) = u1 == u2
173 instance Ord LocalReg where
174 compare (LocalReg u1 _) (LocalReg u2 _) = compare u1 u2
176 instance Uniquable LocalReg where
177 getUnique (LocalReg uniq _) = uniq
179 cmmRegType :: CmmReg -> CmmType
180 cmmRegType (CmmLocal reg) = localRegType reg
181 cmmRegType (CmmGlobal reg) = globalRegType reg
183 localRegType :: LocalReg -> CmmType
184 localRegType (LocalReg _ rep) = rep
186 -----------------------------------------------------------------------------
187 -- Register-use information for expressions and other types
188 -----------------------------------------------------------------------------
190 -- | Sets of local registers
191 type RegSet = UniqSet LocalReg
192 emptyRegSet :: RegSet
193 elemRegSet :: LocalReg -> RegSet -> Bool
194 extendRegSet :: RegSet -> LocalReg -> RegSet
195 deleteFromRegSet :: RegSet -> LocalReg -> RegSet
196 mkRegSet :: [LocalReg] -> RegSet
197 minusRegSet, plusRegSet, timesRegSet :: RegSet -> RegSet -> RegSet
199 emptyRegSet = emptyUniqSet
200 elemRegSet = elementOfUniqSet
201 extendRegSet = addOneToUniqSet
202 deleteFromRegSet = delOneFromUniqSet
204 minusRegSet = minusUniqSet
205 plusRegSet = unionUniqSets
206 timesRegSet = intersectUniqSets
208 class UserOfLocalRegs a where
209 foldRegsUsed :: (b -> LocalReg -> b) -> b -> a -> b
211 class DefinerOfLocalRegs a where
212 foldRegsDefd :: (b -> LocalReg -> b) -> b -> a -> b
214 filterRegsUsed :: UserOfLocalRegs e => (LocalReg -> Bool) -> e -> RegSet
216 foldRegsUsed (\regs r -> if p r then extendRegSet regs r else regs)
219 instance UserOfLocalRegs CmmReg where
220 foldRegsUsed f z (CmmLocal reg) = f z reg
221 foldRegsUsed _ z (CmmGlobal _) = z
223 instance DefinerOfLocalRegs CmmReg where
224 foldRegsDefd f z (CmmLocal reg) = f z reg
225 foldRegsDefd _ z (CmmGlobal _) = z
227 instance UserOfLocalRegs LocalReg where
228 foldRegsUsed f z r = f z r
230 instance DefinerOfLocalRegs LocalReg where
231 foldRegsDefd f z r = f z r
233 instance UserOfLocalRegs RegSet where
234 foldRegsUsed f = foldUniqSet (flip f)
236 instance UserOfLocalRegs CmmExpr where
237 foldRegsUsed f z e = expr z e
238 where expr z (CmmLit _) = z
239 expr z (CmmLoad addr _) = foldRegsUsed f z addr
240 expr z (CmmReg r) = foldRegsUsed f z r
241 expr z (CmmMachOp _ exprs) = foldRegsUsed f z exprs
242 expr z (CmmRegOff r _) = foldRegsUsed f z r
243 expr z (CmmStackSlot _ _) = z
245 instance UserOfLocalRegs a => UserOfLocalRegs [a] where
246 foldRegsUsed _ set [] = set
247 foldRegsUsed f set (x:xs) = foldRegsUsed f (foldRegsUsed f set x) xs
249 instance DefinerOfLocalRegs a => DefinerOfLocalRegs [a] where
250 foldRegsDefd _ set [] = set
251 foldRegsDefd f set (x:xs) = foldRegsDefd f (foldRegsDefd f set x) xs
253 instance DefinerOfLocalRegs a => DefinerOfLocalRegs (Maybe a) where
254 foldRegsDefd _ set Nothing = set
255 foldRegsDefd f set (Just x) = foldRegsDefd f set x
258 -----------------------------------------------------------------------------
260 -----------------------------------------------------------------------------
262 mkVarSlot :: LocalReg -> CmmExpr
263 mkVarSlot r = CmmStackSlot (RegSlot r) 0
265 -- Usually, we either want to lookup a variable's spill slot in an environment
266 -- or else allocate it and add it to the environment.
267 -- For a variable, we just need a single area of the appropriate size.
268 type StackSlotMap = FiniteMap LocalReg CmmExpr
269 getSlot :: StackSlotMap -> LocalReg -> (StackSlotMap, CmmExpr)
270 getSlot map r = case lookupFM map r of
272 Nothing -> (addToFM map r s, s) where s = mkVarSlot r
274 -----------------------------------------------------------------------------
275 -- Stack slot use information for expressions and other types [_$_]
276 -----------------------------------------------------------------------------
279 -- Fold over the area, the offset into the area, and the width of the subarea.
280 class UserOfSlots a where
281 foldSlotsUsed :: (b -> SubArea -> b) -> b -> a -> b
283 class DefinerOfSlots a where
284 foldSlotsDefd :: (b -> SubArea -> b) -> b -> a -> b
286 instance UserOfSlots CmmExpr where
287 foldSlotsUsed f z e = expr z e
288 where expr z (CmmLit _) = z
289 expr z (CmmLoad (CmmStackSlot a i) ty) = f z (a, i, widthInBytes $ typeWidth ty)
290 expr z (CmmLoad addr _) = foldSlotsUsed f z addr
291 expr z (CmmReg _) = z
292 expr z (CmmMachOp _ exprs) = foldSlotsUsed f z exprs
293 expr z (CmmRegOff _ _) = z
294 expr z (CmmStackSlot _ _) = z
296 instance UserOfSlots a => UserOfSlots [a] where
297 foldSlotsUsed _ set [] = set
298 foldSlotsUsed f set (x:xs) = foldSlotsUsed f (foldSlotsUsed f set x) xs
301 -----------------------------------------------------------------------------
302 -- Global STG registers
303 -----------------------------------------------------------------------------
305 data VGcPtr = VGcPtr | VNonGcPtr deriving( Eq, Show )
308 -----------------------------------------------------------------------------
309 -- Global STG registers
310 -----------------------------------------------------------------------------
311 vgcFlag :: CmmType -> VGcPtr
312 vgcFlag ty | isGcPtrType ty = VGcPtr
313 | otherwise = VNonGcPtr
316 -- Argument and return registers
317 = VanillaReg -- pointers, unboxed ints and chars
318 {-# UNPACK #-} !Int -- its number
321 | FloatReg -- single-precision floating-point registers
322 {-# UNPACK #-} !Int -- its number
324 | DoubleReg -- double-precision floating-point registers
325 {-# UNPACK #-} !Int -- its number
327 | LongReg -- long int registers (64-bit, really)
328 {-# UNPACK #-} !Int -- its number
331 | Sp -- Stack ptr; points to last occupied stack location.
332 | SpLim -- Stack limit
333 | Hp -- Heap ptr; points to last occupied heap location.
334 | HpLim -- Heap limit register
335 | CurrentTSO -- pointer to current thread's TSO
336 | CurrentNursery -- pointer to allocation area
337 | HpAlloc -- allocation count for heap check failure
339 -- We keep the address of some commonly-called
340 -- functions in the register table, to keep code
342 | EagerBlackholeInfo -- stg_EAGER_BLACKHOLE_info
343 | GCEnter1 -- stg_gc_enter_1
344 | GCFun -- stg_gc_fun
346 -- Base offset for the register table, used for accessing registers
347 -- which do not have real registers assigned to them. This register
348 -- will only appear after we have expanded GlobalReg into memory accesses
349 -- (where necessary) in the native code generator.
352 -- Base Register for PIC (position-independent code) calculations
353 -- Only used inside the native code generator. It's exact meaning differs
354 -- from platform to platform (see module PositionIndependentCode).
359 instance Eq GlobalReg where
360 VanillaReg i _ == VanillaReg j _ = i==j -- Ignore type when seeking clashes
361 FloatReg i == FloatReg j = i==j
362 DoubleReg i == DoubleReg j = i==j
363 LongReg i == LongReg j = i==j
365 SpLim == SpLim = True
367 HpLim == HpLim = True
368 CurrentTSO == CurrentTSO = True
369 CurrentNursery == CurrentNursery = True
370 HpAlloc == HpAlloc = True
371 GCEnter1 == GCEnter1 = True
372 GCFun == GCFun = True
373 BaseReg == BaseReg = True
374 PicBaseReg == PicBaseReg = True
377 instance Ord GlobalReg where
378 compare (VanillaReg i _) (VanillaReg j _) = compare i j
379 -- Ignore type when seeking clashes
380 compare (FloatReg i) (FloatReg j) = compare i j
381 compare (DoubleReg i) (DoubleReg j) = compare i j
382 compare (LongReg i) (LongReg j) = compare i j
384 compare SpLim SpLim = EQ
386 compare HpLim HpLim = EQ
387 compare CurrentTSO CurrentTSO = EQ
388 compare CurrentNursery CurrentNursery = EQ
389 compare HpAlloc HpAlloc = EQ
390 compare EagerBlackholeInfo EagerBlackholeInfo = EQ
391 compare GCEnter1 GCEnter1 = EQ
392 compare GCFun GCFun = EQ
393 compare BaseReg BaseReg = EQ
394 compare PicBaseReg PicBaseReg = EQ
395 compare (VanillaReg _ _) _ = LT
396 compare _ (VanillaReg _ _) = GT
397 compare (FloatReg _) _ = LT
398 compare _ (FloatReg _) = GT
399 compare (DoubleReg _) _ = LT
400 compare _ (DoubleReg _) = GT
401 compare (LongReg _) _ = LT
402 compare _ (LongReg _) = GT
411 compare CurrentTSO _ = LT
412 compare _ CurrentTSO = GT
413 compare CurrentNursery _ = LT
414 compare _ CurrentNursery = GT
415 compare HpAlloc _ = LT
416 compare _ HpAlloc = GT
417 compare GCEnter1 _ = LT
418 compare _ GCEnter1 = GT
421 compare BaseReg _ = LT
422 compare _ BaseReg = GT
423 compare EagerBlackholeInfo _ = LT
424 compare _ EagerBlackholeInfo = GT
426 -- convenient aliases
427 spReg, hpReg, spLimReg, nodeReg :: CmmReg
430 spLimReg = CmmGlobal SpLim
431 nodeReg = CmmGlobal node
434 node = VanillaReg 1 VGcPtr
436 globalRegType :: GlobalReg -> CmmType
437 globalRegType (VanillaReg _ VGcPtr) = gcWord
438 globalRegType (VanillaReg _ VNonGcPtr) = bWord
439 globalRegType (FloatReg _) = cmmFloat W32
440 globalRegType (DoubleReg _) = cmmFloat W64
441 globalRegType (LongReg _) = cmmBits W64
442 globalRegType Hp = gcWord -- The initialiser for all
443 -- dynamically allocated closures
444 globalRegType _ = bWord
447 -----------------------------------------------------------------------------
449 -----------------------------------------------------------------------------
451 -- NOTE: CmmType is an abstract type, not exported from this
452 -- module so you can easily change its representation
454 -- However Width is exported in a concrete way,
455 -- and is used extensively in pattern-matching
457 data CmmType -- The important one!
458 = CmmType CmmCat Width
460 data CmmCat -- "Category" (not exported)
461 = GcPtrCat -- GC pointer
462 | BitsCat -- Non-pointer
465 -- See Note [Signed vs unsigned] at the end
467 instance Outputable CmmType where
468 ppr (CmmType cat wid) = ppr cat <> ppr (widthInBits wid)
470 instance Outputable CmmCat where
471 ppr FloatCat = ptext $ sLit("F")
472 ppr _ = ptext $ sLit("I")
474 -- ppr FloatCat = ptext $ sLit("float")
475 -- ppr BitsCat = ptext $ sLit("bits")
476 -- ppr GcPtrCat = ptext $ sLit("gcptr")
478 -- Why is CmmType stratified? For native code generation,
479 -- most of the time you just want to know what sort of register
480 -- to put the thing in, and for this you need to know how
481 -- many bits thing has and whether it goes in a floating-point
482 -- register. By contrast, the distinction between GcPtr and
483 -- GcNonPtr is of interest to only a few parts of the code generator.
485 -------- Equality on CmmType --------------
486 -- CmmType is *not* an instance of Eq; sometimes we care about the
487 -- Gc/NonGc distinction, and sometimes we don't
488 -- So we use an explicit function to force you to think about it
489 cmmEqType :: CmmType -> CmmType -> Bool -- Exact equality
490 cmmEqType (CmmType c1 w1) (CmmType c2 w2) = c1==c2 && w1==w2
492 cmmEqType_ignoring_ptrhood :: CmmType -> CmmType -> Bool
493 -- This equality is temporary; used in CmmLint
494 -- but the RTS files are not yet well-typed wrt pointers
495 cmmEqType_ignoring_ptrhood (CmmType c1 w1) (CmmType c2 w2)
496 = c1 `weak_eq` c2 && w1==w2
498 FloatCat `weak_eq` FloatCat = True
499 FloatCat `weak_eq` _other = False
500 _other `weak_eq` FloatCat = False
501 _word1 `weak_eq` _word2 = True -- Ignores GcPtr
503 --- Simple operations on CmmType -----
504 typeWidth :: CmmType -> Width
505 typeWidth (CmmType _ w) = w
507 cmmBits, cmmFloat :: Width -> CmmType
508 cmmBits = CmmType BitsCat
509 cmmFloat = CmmType FloatCat
511 -------- Common CmmTypes ------------
512 -- Floats and words of specific widths
513 b8, b16, b32, b64, f32, f64 :: CmmType
521 -- CmmTypes of native word widths
522 bWord, bHalfWord, gcWord :: CmmType
523 bWord = cmmBits wordWidth
524 bHalfWord = cmmBits halfWordWidth
525 gcWord = CmmType GcPtrCat wordWidth
527 cInt, cLong :: CmmType
528 cInt = cmmBits cIntWidth
529 cLong = cmmBits cLongWidth
532 ------------ Predicates ----------------
533 isFloatType, isGcPtrType :: CmmType -> Bool
534 isFloatType (CmmType FloatCat _) = True
535 isFloatType _other = False
537 isGcPtrType (CmmType GcPtrCat _) = True
538 isGcPtrType _other = False
540 isWord32, isWord64, isFloat32, isFloat64 :: CmmType -> Bool
541 -- isWord64 is true of 64-bit non-floats (both gc-ptrs and otherwise)
542 -- isFloat32 and 64 are obvious
544 isWord64 (CmmType BitsCat W64) = True
545 isWord64 (CmmType GcPtrCat W64) = True
546 isWord64 _other = False
548 isWord32 (CmmType BitsCat W32) = True
549 isWord32 (CmmType GcPtrCat W32) = True
550 isWord32 _other = False
552 isFloat32 (CmmType FloatCat W32) = True
553 isFloat32 _other = False
555 isFloat64 (CmmType FloatCat W64) = True
556 isFloat64 _other = False
558 -----------------------------------------------------------------------------
560 -----------------------------------------------------------------------------
562 data Width = W8 | W16 | W32 | W64
563 | W80 -- Extended double-precision float,
564 -- used in x86 native codegen only.
565 -- (we use Ord, so it'd better be in this order)
567 deriving (Eq, Ord, Show)
569 instance Outputable Width where
570 ppr rep = ptext (mrStr rep)
572 mrStr :: Width -> LitString
573 mrStr W8 = sLit("W8")
574 mrStr W16 = sLit("W16")
575 mrStr W32 = sLit("W32")
576 mrStr W64 = sLit("W64")
577 mrStr W128 = sLit("W128")
578 mrStr W80 = sLit("W80")
581 -------- Common Widths ------------
582 wordWidth, halfWordWidth :: Width
583 wordWidth | wORD_SIZE == 4 = W32
584 | wORD_SIZE == 8 = W64
585 | otherwise = panic "MachOp.wordRep: Unknown word size"
587 halfWordWidth | wORD_SIZE == 4 = W16
588 | wORD_SIZE == 8 = W32
589 | otherwise = panic "MachOp.halfWordRep: Unknown word size"
591 -- cIntRep is the Width for a C-language 'int'
592 cIntWidth, cLongWidth :: Width
595 #elif SIZEOF_INT == 8
601 #elif SIZEOF_LONG == 8
605 widthInBits :: Width -> Int
610 widthInBits W128 = 128
613 widthInBytes :: Width -> Int
618 widthInBytes W128 = 16
619 widthInBytes W80 = 10
621 widthFromBytes :: Int -> Width
622 widthFromBytes 1 = W8
623 widthFromBytes 2 = W16
624 widthFromBytes 4 = W32
625 widthFromBytes 8 = W64
626 widthFromBytes 16 = W128
627 widthFromBytes 10 = W80
628 widthFromBytes n = pprPanic "no width for given number of bytes" (ppr n)
630 -- log_2 of the width in bytes, useful for generating shifts.
631 widthInLog :: Width -> Int
637 widthInLog W80 = panic "widthInLog: F80"
640 -----------------------------------------------------------------------------
642 -----------------------------------------------------------------------------
645 Implementation notes:
647 It might suffice to keep just a width, without distinguishing between
648 floating and integer types. However, keeping the distinction will
649 help the native code generator to assign registers more easily.
654 Machine-level primops; ones which we can reasonably delegate to the
655 native code generators to handle. Basically contains C's primops
658 Nomenclature: all ops indicate width and signedness, where
659 appropriate. Widths: 8\/16\/32\/64 means the given size, obviously.
660 Nat means the operation works on STG word sized objects.
661 Signedness: S means signed, U means unsigned. For operations where
662 signedness is irrelevant or makes no difference (for example
663 integer add), the signedness component is omitted.
665 An exception: NatP is a ptr-typed native word. From the point of
666 view of the native code generators this distinction is irrelevant,
667 but the C code generator sometimes needs this info to emit the
672 -- Integer operations (insensitive to signed/unsigned)
677 | MO_Mul Width -- low word of multiply
679 -- Signed multiply/divide
680 | MO_S_MulMayOflo Width -- nonzero if signed multiply overflows
681 | MO_S_Quot Width -- signed / (same semantics as IntQuotOp)
682 | MO_S_Rem Width -- signed % (same semantics as IntRemOp)
683 | MO_S_Neg Width -- unary -
685 -- Unsigned multiply/divide
686 | MO_U_MulMayOflo Width -- nonzero if unsigned multiply overflows
687 | MO_U_Quot Width -- unsigned / (same semantics as WordQuotOp)
688 | MO_U_Rem Width -- unsigned % (same semantics as WordRemOp)
690 -- Signed comparisons
696 -- Unsigned comparisons
702 -- Floating point arithmetic
705 | MO_F_Neg Width -- unary -
709 -- Floating point comparison
717 -- Bitwise operations. Not all of these may be supported
718 -- at all sizes, and only integral Widths are valid.
724 | MO_U_Shr Width -- unsigned shift right
725 | MO_S_Shr Width -- signed shift right
727 -- Conversions. Some of these will be NOPs.
728 -- Floating-point conversions use the signed variant.
729 | MO_SF_Conv Width Width -- Signed int -> Float
730 | MO_FS_Conv Width Width -- Float -> Signed int
731 | MO_SS_Conv Width Width -- Signed int -> Signed int
732 | MO_UU_Conv Width Width -- unsigned int -> unsigned int
733 | MO_FF_Conv Width Width -- Float -> Float
736 pprMachOp :: MachOp -> SDoc
737 pprMachOp mo = text (show mo)
741 -- -----------------------------------------------------------------------------
742 -- Some common MachReps
744 -- A 'wordRep' is a machine word on the target architecture
745 -- Specifically, it is the size of an Int#, Word#, Addr#
746 -- and the unit of allocation on the stack and the heap
747 -- Any pointer is also guaranteed to be a wordRep.
749 mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
750 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
751 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
752 , mo_wordULe, mo_wordUGt, mo_wordULt
753 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
754 , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
755 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
756 , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32
759 mo_wordAdd = MO_Add wordWidth
760 mo_wordSub = MO_Sub wordWidth
761 mo_wordEq = MO_Eq wordWidth
762 mo_wordNe = MO_Ne wordWidth
763 mo_wordMul = MO_Mul wordWidth
764 mo_wordSQuot = MO_S_Quot wordWidth
765 mo_wordSRem = MO_S_Rem wordWidth
766 mo_wordSNeg = MO_S_Neg wordWidth
767 mo_wordUQuot = MO_U_Quot wordWidth
768 mo_wordURem = MO_U_Rem wordWidth
770 mo_wordSGe = MO_S_Ge wordWidth
771 mo_wordSLe = MO_S_Le wordWidth
772 mo_wordSGt = MO_S_Gt wordWidth
773 mo_wordSLt = MO_S_Lt wordWidth
775 mo_wordUGe = MO_U_Ge wordWidth
776 mo_wordULe = MO_U_Le wordWidth
777 mo_wordUGt = MO_U_Gt wordWidth
778 mo_wordULt = MO_U_Lt wordWidth
780 mo_wordAnd = MO_And wordWidth
781 mo_wordOr = MO_Or wordWidth
782 mo_wordXor = MO_Xor wordWidth
783 mo_wordNot = MO_Not wordWidth
784 mo_wordShl = MO_Shl wordWidth
785 mo_wordSShr = MO_S_Shr wordWidth
786 mo_wordUShr = MO_U_Shr wordWidth
788 mo_u_8To32 = MO_UU_Conv W8 W32
789 mo_s_8To32 = MO_SS_Conv W8 W32
790 mo_u_16To32 = MO_UU_Conv W16 W32
791 mo_s_16To32 = MO_SS_Conv W16 W32
793 mo_u_8ToWord = MO_UU_Conv W8 wordWidth
794 mo_s_8ToWord = MO_SS_Conv W8 wordWidth
795 mo_u_16ToWord = MO_UU_Conv W16 wordWidth
796 mo_s_16ToWord = MO_SS_Conv W16 wordWidth
797 mo_s_32ToWord = MO_SS_Conv W32 wordWidth
798 mo_u_32ToWord = MO_UU_Conv W32 wordWidth
800 mo_WordTo8 = MO_UU_Conv wordWidth W8
801 mo_WordTo16 = MO_UU_Conv wordWidth W16
802 mo_WordTo32 = MO_UU_Conv wordWidth W32
804 mo_32To8 = MO_UU_Conv W32 W8
805 mo_32To16 = MO_UU_Conv W32 W16
808 -- ----------------------------------------------------------------------------
809 -- isCommutableMachOp
812 Returns 'True' if the MachOp has commutable arguments. This is used
813 in the platform-independent Cmm optimisations.
815 If in doubt, return 'False'. This generates worse code on the
816 native routes, but is otherwise harmless.
818 isCommutableMachOp :: MachOp -> Bool
819 isCommutableMachOp mop =
825 MO_S_MulMayOflo _ -> True
826 MO_U_MulMayOflo _ -> True
832 -- ----------------------------------------------------------------------------
833 -- isAssociativeMachOp
836 Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
837 This is used in the platform-independent Cmm optimisations.
839 If in doubt, return 'False'. This generates worse code on the
840 native routes, but is otherwise harmless.
842 isAssociativeMachOp :: MachOp -> Bool
843 isAssociativeMachOp mop =
845 MO_Add {} -> True -- NB: does not include
846 MO_Mul {} -> True -- floatint point!
852 -- ----------------------------------------------------------------------------
853 -- isComparisonMachOp
856 Returns 'True' if the MachOp is a comparison.
858 If in doubt, return False. This generates worse code on the
859 native routes, but is otherwise harmless.
861 isComparisonMachOp :: MachOp -> Bool
862 isComparisonMachOp mop =
882 -- -----------------------------------------------------------------------------
883 -- Inverting conditions
885 -- Sometimes it's useful to be able to invert the sense of a
886 -- condition. Not all conditional tests are invertible: in
887 -- particular, floating point conditionals cannot be inverted, because
888 -- there exist floating-point values which return False for both senses
889 -- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).
891 maybeInvertComparison :: MachOp -> Maybe MachOp
892 maybeInvertComparison op
893 = case op of -- None of these Just cases include floating point
894 MO_Eq r -> Just (MO_Ne r)
895 MO_Ne r -> Just (MO_Eq r)
896 MO_U_Lt r -> Just (MO_U_Ge r)
897 MO_U_Gt r -> Just (MO_U_Le r)
898 MO_U_Le r -> Just (MO_U_Gt r)
899 MO_U_Ge r -> Just (MO_U_Lt r)
900 MO_S_Lt r -> Just (MO_S_Ge r)
901 MO_S_Gt r -> Just (MO_S_Le r)
902 MO_S_Le r -> Just (MO_S_Gt r)
903 MO_S_Ge r -> Just (MO_S_Lt r)
904 MO_F_Eq r -> Just (MO_F_Ne r)
905 MO_F_Ne r -> Just (MO_F_Eq r)
906 MO_F_Ge r -> Just (MO_F_Le r)
907 MO_F_Le r -> Just (MO_F_Ge r)
908 MO_F_Gt r -> Just (MO_F_Lt r)
909 MO_F_Lt r -> Just (MO_F_Gt r)
912 -- ----------------------------------------------------------------------------
916 Returns the MachRep of the result of a MachOp.
918 machOpResultType :: MachOp -> [CmmType] -> CmmType
919 machOpResultType mop tys =
921 MO_Add {} -> ty1 -- Preserve GC-ptr-hood
922 MO_Sub {} -> ty1 -- of first arg
923 MO_Mul r -> cmmBits r
924 MO_S_MulMayOflo r -> cmmBits r
925 MO_S_Quot r -> cmmBits r
926 MO_S_Rem r -> cmmBits r
927 MO_S_Neg r -> cmmBits r
928 MO_U_MulMayOflo r -> cmmBits r
929 MO_U_Quot r -> cmmBits r
930 MO_U_Rem r -> cmmBits r
932 MO_Eq {} -> comparisonResultRep
933 MO_Ne {} -> comparisonResultRep
934 MO_S_Ge {} -> comparisonResultRep
935 MO_S_Le {} -> comparisonResultRep
936 MO_S_Gt {} -> comparisonResultRep
937 MO_S_Lt {} -> comparisonResultRep
939 MO_U_Ge {} -> comparisonResultRep
940 MO_U_Le {} -> comparisonResultRep
941 MO_U_Gt {} -> comparisonResultRep
942 MO_U_Lt {} -> comparisonResultRep
944 MO_F_Add r -> cmmFloat r
945 MO_F_Sub r -> cmmFloat r
946 MO_F_Mul r -> cmmFloat r
947 MO_F_Quot r -> cmmFloat r
948 MO_F_Neg r -> cmmFloat r
949 MO_F_Eq {} -> comparisonResultRep
950 MO_F_Ne {} -> comparisonResultRep
951 MO_F_Ge {} -> comparisonResultRep
952 MO_F_Le {} -> comparisonResultRep
953 MO_F_Gt {} -> comparisonResultRep
954 MO_F_Lt {} -> comparisonResultRep
956 MO_And {} -> ty1 -- Used for pointer masking
959 MO_Not r -> cmmBits r
960 MO_Shl r -> cmmBits r
961 MO_U_Shr r -> cmmBits r
962 MO_S_Shr r -> cmmBits r
964 MO_SS_Conv _ to -> cmmBits to
965 MO_UU_Conv _ to -> cmmBits to
966 MO_FS_Conv _ to -> cmmBits to
967 MO_SF_Conv _ to -> cmmFloat to
968 MO_FF_Conv _ to -> cmmFloat to
972 comparisonResultRep :: CmmType
973 comparisonResultRep = bWord -- is it?
976 -- -----------------------------------------------------------------------------
979 -- | This function is used for debugging only: we can check whether an
980 -- application of a MachOp is "type-correct" by checking that the MachReps of
981 -- its arguments are the same as the MachOp expects. This is used when
982 -- linting a CmmExpr.
984 machOpArgReps :: MachOp -> [Width]
992 MO_S_MulMayOflo r -> [r,r]
996 MO_U_MulMayOflo r -> [r,r]
1013 MO_F_Quot r -> [r,r]
1026 MO_Shl r -> [r,wordWidth]
1027 MO_U_Shr r -> [r,wordWidth]
1028 MO_S_Shr r -> [r,wordWidth]
1030 MO_SS_Conv from _ -> [from]
1031 MO_UU_Conv from _ -> [from]
1032 MO_SF_Conv from _ -> [from]
1033 MO_FS_Conv from _ -> [from]
1034 MO_FF_Conv from _ -> [from]
1037 -------------------------------------------------------------------------
1038 {- Note [Signed vs unsigned]
1039 ~~~~~~~~~~~~~~~~~~~~~~~~~
1040 Should a CmmType include a signed vs. unsigned distinction?
1042 This is very much like a "hint" in C-- terminology: it isn't necessary
1043 in order to generate correct code, but it might be useful in that the
1044 compiler can generate better code if it has access to higher-level
1045 hints about data. This is important at call boundaries, because the
1046 definition of a function is not visible at all of its call sites, so
1047 the compiler cannot infer the hints.
1049 Here in Cmm, we're taking a slightly different approach. We include
1050 the int vs. float hint in the MachRep, because (a) the majority of
1051 platforms have a strong distinction between float and int registers,
1052 and (b) we don't want to do any heavyweight hint-inference in the
1053 native code backend in order to get good code. We're treating the
1054 hint more like a type: our Cmm is always completely consistent with
1055 respect to hints. All coercions between float and int are explicit.
1057 What about the signed vs. unsigned hint? This information might be
1058 useful if we want to keep sub-word-sized values in word-size
1059 registers, which we must do if we only have word-sized registers.
1061 On such a system, there are two straightforward conventions for
1062 representing sub-word-sized values:
1064 (a) Leave the upper bits undefined. Comparison operations must
1065 sign- or zero-extend both operands before comparing them,
1066 depending on whether the comparison is signed or unsigned.
1068 (b) Always keep the values sign- or zero-extended as appropriate.
1069 Arithmetic operations must narrow the result to the appropriate
1072 A clever compiler might not use either (a) or (b) exclusively, instead
1073 it would attempt to minimize the coercions by analysis: the same kind
1074 of analysis that propagates hints around. In Cmm we don't want to
1075 have to do this, so we plump for having richer types and keeping the
1076 type information consistent.
1078 If signed/unsigned hints are missing from MachRep, then the only
1079 choice we have is (a), because we don't know whether the result of an
1080 operation should be sign- or zero-extended.
1082 Many architectures have extending load operations, which work well
1083 with (b). To make use of them with (a), you need to know whether the
1084 value is going to be sign- or zero-extended by an enclosing comparison
1085 (for example), which involves knowing above the context. This is
1086 doable but more complex.
1088 Further complicating the issue is foreign calls: a foreign calling
1089 convention can specify that signed 8-bit quantities are passed as
1090 sign-extended 32 bit quantities, for example (this is the case on the
1091 PowerPC). So we *do* need sign information on foreign call arguments.
1093 Pros for adding signed vs. unsigned to MachRep:
1095 - It would let us use convention (b) above, and get easier
1096 code generation for extending loads.
1098 - Less information required on foreign calls.
1100 - MachOp type would be simpler
1106 - What is the MachRep for a VanillaReg? Currently it is
1107 always wordRep, but now we have to decide whether it is
1108 signed or unsigned. The same VanillaReg can thus have
1109 different MachReps in different parts of the program.
1111 - Extra coercions cluttering up expressions.
1113 Currently for GHC, the foreign call point is moot, because we do our
1114 own promotion of sub-word-sized values to word-sized values. The Int8
1115 type is represnted by an Int# which is kept sign-extended at all times
1116 (this is slightly naughty, because we're making assumptions about the
1117 C calling convention rather early on in the compiler). However, given
1118 this, the cons outweigh the pros.