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 GCEnter1 GCEnter1 = EQ
391 compare GCFun GCFun = EQ
392 compare BaseReg BaseReg = EQ
393 compare PicBaseReg PicBaseReg = EQ
394 compare (VanillaReg _ _) _ = LT
395 compare _ (VanillaReg _ _) = GT
396 compare (FloatReg _) _ = LT
397 compare _ (FloatReg _) = GT
398 compare (DoubleReg _) _ = LT
399 compare _ (DoubleReg _) = GT
400 compare (LongReg _) _ = LT
401 compare _ (LongReg _) = GT
410 compare CurrentTSO _ = LT
411 compare _ CurrentTSO = GT
412 compare CurrentNursery _ = LT
413 compare _ CurrentNursery = GT
414 compare HpAlloc _ = LT
415 compare _ HpAlloc = GT
416 compare GCEnter1 _ = LT
417 compare _ GCEnter1 = GT
420 compare BaseReg _ = LT
421 compare _ BaseReg = GT
422 compare EagerBlackholeInfo _ = LT
423 compare _ EagerBlackholeInfo = GT
425 -- convenient aliases
426 spReg, hpReg, spLimReg, nodeReg :: CmmReg
429 spLimReg = CmmGlobal SpLim
430 nodeReg = CmmGlobal node
433 node = VanillaReg 1 VGcPtr
435 globalRegType :: GlobalReg -> CmmType
436 globalRegType (VanillaReg _ VGcPtr) = gcWord
437 globalRegType (VanillaReg _ VNonGcPtr) = bWord
438 globalRegType (FloatReg _) = cmmFloat W32
439 globalRegType (DoubleReg _) = cmmFloat W64
440 globalRegType (LongReg _) = cmmBits W64
441 globalRegType Hp = gcWord -- The initialiser for all
442 -- dynamically allocated closures
443 globalRegType _ = bWord
446 -----------------------------------------------------------------------------
448 -----------------------------------------------------------------------------
450 -- NOTE: CmmType is an abstract type, not exported from this
451 -- module so you can easily change its representation
453 -- However Width is exported in a concrete way,
454 -- and is used extensively in pattern-matching
456 data CmmType -- The important one!
457 = CmmType CmmCat Width
459 data CmmCat -- "Category" (not exported)
460 = GcPtrCat -- GC pointer
461 | BitsCat -- Non-pointer
464 -- See Note [Signed vs unsigned] at the end
466 instance Outputable CmmType where
467 ppr (CmmType cat wid) = ppr cat <> ppr (widthInBits wid)
469 instance Outputable CmmCat where
470 ppr FloatCat = ptext $ sLit("F")
471 ppr _ = ptext $ sLit("I")
473 -- ppr FloatCat = ptext $ sLit("float")
474 -- ppr BitsCat = ptext $ sLit("bits")
475 -- ppr GcPtrCat = ptext $ sLit("gcptr")
477 -- Why is CmmType stratified? For native code generation,
478 -- most of the time you just want to know what sort of register
479 -- to put the thing in, and for this you need to know how
480 -- many bits thing has and whether it goes in a floating-point
481 -- register. By contrast, the distinction between GcPtr and
482 -- GcNonPtr is of interest to only a few parts of the code generator.
484 -------- Equality on CmmType --------------
485 -- CmmType is *not* an instance of Eq; sometimes we care about the
486 -- Gc/NonGc distinction, and sometimes we don't
487 -- So we use an explicit function to force you to think about it
488 cmmEqType :: CmmType -> CmmType -> Bool -- Exact equality
489 cmmEqType (CmmType c1 w1) (CmmType c2 w2) = c1==c2 && w1==w2
491 cmmEqType_ignoring_ptrhood :: CmmType -> CmmType -> Bool
492 -- This equality is temporary; used in CmmLint
493 -- but the RTS files are not yet well-typed wrt pointers
494 cmmEqType_ignoring_ptrhood (CmmType c1 w1) (CmmType c2 w2)
495 = c1 `weak_eq` c2 && w1==w2
497 FloatCat `weak_eq` FloatCat = True
498 FloatCat `weak_eq` _other = False
499 _other `weak_eq` FloatCat = False
500 _word1 `weak_eq` _word2 = True -- Ignores GcPtr
502 --- Simple operations on CmmType -----
503 typeWidth :: CmmType -> Width
504 typeWidth (CmmType _ w) = w
506 cmmBits, cmmFloat :: Width -> CmmType
507 cmmBits = CmmType BitsCat
508 cmmFloat = CmmType FloatCat
510 -------- Common CmmTypes ------------
511 -- Floats and words of specific widths
512 b8, b16, b32, b64, f32, f64 :: CmmType
520 -- CmmTypes of native word widths
521 bWord, bHalfWord, gcWord :: CmmType
522 bWord = cmmBits wordWidth
523 bHalfWord = cmmBits halfWordWidth
524 gcWord = CmmType GcPtrCat wordWidth
526 cInt, cLong :: CmmType
527 cInt = cmmBits cIntWidth
528 cLong = cmmBits cLongWidth
531 ------------ Predicates ----------------
532 isFloatType, isGcPtrType :: CmmType -> Bool
533 isFloatType (CmmType FloatCat _) = True
534 isFloatType _other = False
536 isGcPtrType (CmmType GcPtrCat _) = True
537 isGcPtrType _other = False
539 isWord32, isWord64, isFloat32, isFloat64 :: CmmType -> Bool
540 -- isWord64 is true of 64-bit non-floats (both gc-ptrs and otherwise)
541 -- isFloat32 and 64 are obvious
543 isWord64 (CmmType BitsCat W64) = True
544 isWord64 (CmmType GcPtrCat W64) = True
545 isWord64 _other = False
547 isWord32 (CmmType BitsCat W32) = True
548 isWord32 (CmmType GcPtrCat W32) = True
549 isWord32 _other = False
551 isFloat32 (CmmType FloatCat W32) = True
552 isFloat32 _other = False
554 isFloat64 (CmmType FloatCat W64) = True
555 isFloat64 _other = False
557 -----------------------------------------------------------------------------
559 -----------------------------------------------------------------------------
561 data Width = W8 | W16 | W32 | W64
562 | W80 -- Extended double-precision float,
563 -- used in x86 native codegen only.
564 -- (we use Ord, so it'd better be in this order)
566 deriving (Eq, Ord, Show)
568 instance Outputable Width where
569 ppr rep = ptext (mrStr rep)
571 mrStr :: Width -> LitString
572 mrStr W8 = sLit("W8")
573 mrStr W16 = sLit("W16")
574 mrStr W32 = sLit("W32")
575 mrStr W64 = sLit("W64")
576 mrStr W128 = sLit("W128")
577 mrStr W80 = sLit("W80")
580 -------- Common Widths ------------
581 wordWidth, halfWordWidth :: Width
582 wordWidth | wORD_SIZE == 4 = W32
583 | wORD_SIZE == 8 = W64
584 | otherwise = panic "MachOp.wordRep: Unknown word size"
586 halfWordWidth | wORD_SIZE == 4 = W16
587 | wORD_SIZE == 8 = W32
588 | otherwise = panic "MachOp.halfWordRep: Unknown word size"
590 -- cIntRep is the Width for a C-language 'int'
591 cIntWidth, cLongWidth :: Width
594 #elif SIZEOF_INT == 8
600 #elif SIZEOF_LONG == 8
604 widthInBits :: Width -> Int
609 widthInBits W128 = 128
612 widthInBytes :: Width -> Int
617 widthInBytes W128 = 16
618 widthInBytes W80 = 10
620 widthFromBytes :: Int -> Width
621 widthFromBytes 1 = W8
622 widthFromBytes 2 = W16
623 widthFromBytes 4 = W32
624 widthFromBytes 8 = W64
625 widthFromBytes 16 = W128
626 widthFromBytes 10 = W80
627 widthFromBytes n = pprPanic "no width for given number of bytes" (ppr n)
629 -- log_2 of the width in bytes, useful for generating shifts.
630 widthInLog :: Width -> Int
636 widthInLog W80 = panic "widthInLog: F80"
639 -----------------------------------------------------------------------------
641 -----------------------------------------------------------------------------
644 Implementation notes:
646 It might suffice to keep just a width, without distinguishing between
647 floating and integer types. However, keeping the distinction will
648 help the native code generator to assign registers more easily.
653 Machine-level primops; ones which we can reasonably delegate to the
654 native code generators to handle. Basically contains C's primops
657 Nomenclature: all ops indicate width and signedness, where
658 appropriate. Widths: 8\/16\/32\/64 means the given size, obviously.
659 Nat means the operation works on STG word sized objects.
660 Signedness: S means signed, U means unsigned. For operations where
661 signedness is irrelevant or makes no difference (for example
662 integer add), the signedness component is omitted.
664 An exception: NatP is a ptr-typed native word. From the point of
665 view of the native code generators this distinction is irrelevant,
666 but the C code generator sometimes needs this info to emit the
671 -- Integer operations (insensitive to signed/unsigned)
676 | MO_Mul Width -- low word of multiply
678 -- Signed multiply/divide
679 | MO_S_MulMayOflo Width -- nonzero if signed multiply overflows
680 | MO_S_Quot Width -- signed / (same semantics as IntQuotOp)
681 | MO_S_Rem Width -- signed % (same semantics as IntRemOp)
682 | MO_S_Neg Width -- unary -
684 -- Unsigned multiply/divide
685 | MO_U_MulMayOflo Width -- nonzero if unsigned multiply overflows
686 | MO_U_Quot Width -- unsigned / (same semantics as WordQuotOp)
687 | MO_U_Rem Width -- unsigned % (same semantics as WordRemOp)
689 -- Signed comparisons
695 -- Unsigned comparisons
701 -- Floating point arithmetic
704 | MO_F_Neg Width -- unary -
708 -- Floating point comparison
716 -- Bitwise operations. Not all of these may be supported
717 -- at all sizes, and only integral Widths are valid.
723 | MO_U_Shr Width -- unsigned shift right
724 | MO_S_Shr Width -- signed shift right
726 -- Conversions. Some of these will be NOPs.
727 -- Floating-point conversions use the signed variant.
728 | MO_SF_Conv Width Width -- Signed int -> Float
729 | MO_FS_Conv Width Width -- Float -> Signed int
730 | MO_SS_Conv Width Width -- Signed int -> Signed int
731 | MO_UU_Conv Width Width -- unsigned int -> unsigned int
732 | MO_FF_Conv Width Width -- Float -> Float
735 pprMachOp :: MachOp -> SDoc
736 pprMachOp mo = text (show mo)
740 -- -----------------------------------------------------------------------------
741 -- Some common MachReps
743 -- A 'wordRep' is a machine word on the target architecture
744 -- Specifically, it is the size of an Int#, Word#, Addr#
745 -- and the unit of allocation on the stack and the heap
746 -- Any pointer is also guaranteed to be a wordRep.
748 mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
749 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
750 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
751 , mo_wordULe, mo_wordUGt, mo_wordULt
752 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
753 , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
754 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
755 , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32
758 mo_wordAdd = MO_Add wordWidth
759 mo_wordSub = MO_Sub wordWidth
760 mo_wordEq = MO_Eq wordWidth
761 mo_wordNe = MO_Ne wordWidth
762 mo_wordMul = MO_Mul wordWidth
763 mo_wordSQuot = MO_S_Quot wordWidth
764 mo_wordSRem = MO_S_Rem wordWidth
765 mo_wordSNeg = MO_S_Neg wordWidth
766 mo_wordUQuot = MO_U_Quot wordWidth
767 mo_wordURem = MO_U_Rem wordWidth
769 mo_wordSGe = MO_S_Ge wordWidth
770 mo_wordSLe = MO_S_Le wordWidth
771 mo_wordSGt = MO_S_Gt wordWidth
772 mo_wordSLt = MO_S_Lt wordWidth
774 mo_wordUGe = MO_U_Ge wordWidth
775 mo_wordULe = MO_U_Le wordWidth
776 mo_wordUGt = MO_U_Gt wordWidth
777 mo_wordULt = MO_U_Lt wordWidth
779 mo_wordAnd = MO_And wordWidth
780 mo_wordOr = MO_Or wordWidth
781 mo_wordXor = MO_Xor wordWidth
782 mo_wordNot = MO_Not wordWidth
783 mo_wordShl = MO_Shl wordWidth
784 mo_wordSShr = MO_S_Shr wordWidth
785 mo_wordUShr = MO_U_Shr wordWidth
787 mo_u_8To32 = MO_UU_Conv W8 W32
788 mo_s_8To32 = MO_SS_Conv W8 W32
789 mo_u_16To32 = MO_UU_Conv W16 W32
790 mo_s_16To32 = MO_SS_Conv W16 W32
792 mo_u_8ToWord = MO_UU_Conv W8 wordWidth
793 mo_s_8ToWord = MO_SS_Conv W8 wordWidth
794 mo_u_16ToWord = MO_UU_Conv W16 wordWidth
795 mo_s_16ToWord = MO_SS_Conv W16 wordWidth
796 mo_s_32ToWord = MO_SS_Conv W32 wordWidth
797 mo_u_32ToWord = MO_UU_Conv W32 wordWidth
799 mo_WordTo8 = MO_UU_Conv wordWidth W8
800 mo_WordTo16 = MO_UU_Conv wordWidth W16
801 mo_WordTo32 = MO_UU_Conv wordWidth W32
803 mo_32To8 = MO_UU_Conv W32 W8
804 mo_32To16 = MO_UU_Conv W32 W16
807 -- ----------------------------------------------------------------------------
808 -- isCommutableMachOp
811 Returns 'True' if the MachOp has commutable arguments. This is used
812 in the platform-independent Cmm optimisations.
814 If in doubt, return 'False'. This generates worse code on the
815 native routes, but is otherwise harmless.
817 isCommutableMachOp :: MachOp -> Bool
818 isCommutableMachOp mop =
824 MO_S_MulMayOflo _ -> True
825 MO_U_MulMayOflo _ -> True
831 -- ----------------------------------------------------------------------------
832 -- isAssociativeMachOp
835 Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
836 This is used in the platform-independent Cmm optimisations.
838 If in doubt, return 'False'. This generates worse code on the
839 native routes, but is otherwise harmless.
841 isAssociativeMachOp :: MachOp -> Bool
842 isAssociativeMachOp mop =
844 MO_Add {} -> True -- NB: does not include
845 MO_Mul {} -> True -- floatint point!
851 -- ----------------------------------------------------------------------------
852 -- isComparisonMachOp
855 Returns 'True' if the MachOp is a comparison.
857 If in doubt, return False. This generates worse code on the
858 native routes, but is otherwise harmless.
860 isComparisonMachOp :: MachOp -> Bool
861 isComparisonMachOp mop =
881 -- -----------------------------------------------------------------------------
882 -- Inverting conditions
884 -- Sometimes it's useful to be able to invert the sense of a
885 -- condition. Not all conditional tests are invertible: in
886 -- particular, floating point conditionals cannot be inverted, because
887 -- there exist floating-point values which return False for both senses
888 -- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).
890 maybeInvertComparison :: MachOp -> Maybe MachOp
891 maybeInvertComparison op
892 = case op of -- None of these Just cases include floating point
893 MO_Eq r -> Just (MO_Ne r)
894 MO_Ne r -> Just (MO_Eq r)
895 MO_U_Lt r -> Just (MO_U_Ge r)
896 MO_U_Gt r -> Just (MO_U_Le r)
897 MO_U_Le r -> Just (MO_U_Gt r)
898 MO_U_Ge r -> Just (MO_U_Lt r)
899 MO_S_Lt r -> Just (MO_S_Ge r)
900 MO_S_Gt r -> Just (MO_S_Le r)
901 MO_S_Le r -> Just (MO_S_Gt r)
902 MO_S_Ge r -> Just (MO_S_Lt r)
903 MO_F_Eq r -> Just (MO_F_Ne r)
904 MO_F_Ne r -> Just (MO_F_Eq r)
905 MO_F_Ge r -> Just (MO_F_Le r)
906 MO_F_Le r -> Just (MO_F_Ge r)
907 MO_F_Gt r -> Just (MO_F_Lt r)
908 MO_F_Lt r -> Just (MO_F_Gt r)
911 -- ----------------------------------------------------------------------------
915 Returns the MachRep of the result of a MachOp.
917 machOpResultType :: MachOp -> [CmmType] -> CmmType
918 machOpResultType mop tys =
920 MO_Add {} -> ty1 -- Preserve GC-ptr-hood
921 MO_Sub {} -> ty1 -- of first arg
922 MO_Mul r -> cmmBits r
923 MO_S_MulMayOflo r -> cmmBits r
924 MO_S_Quot r -> cmmBits r
925 MO_S_Rem r -> cmmBits r
926 MO_S_Neg r -> cmmBits r
927 MO_U_MulMayOflo r -> cmmBits r
928 MO_U_Quot r -> cmmBits r
929 MO_U_Rem r -> cmmBits r
931 MO_Eq {} -> comparisonResultRep
932 MO_Ne {} -> comparisonResultRep
933 MO_S_Ge {} -> comparisonResultRep
934 MO_S_Le {} -> comparisonResultRep
935 MO_S_Gt {} -> comparisonResultRep
936 MO_S_Lt {} -> comparisonResultRep
938 MO_U_Ge {} -> comparisonResultRep
939 MO_U_Le {} -> comparisonResultRep
940 MO_U_Gt {} -> comparisonResultRep
941 MO_U_Lt {} -> comparisonResultRep
943 MO_F_Add r -> cmmFloat r
944 MO_F_Sub r -> cmmFloat r
945 MO_F_Mul r -> cmmFloat r
946 MO_F_Quot r -> cmmFloat r
947 MO_F_Neg r -> cmmFloat r
948 MO_F_Eq {} -> comparisonResultRep
949 MO_F_Ne {} -> comparisonResultRep
950 MO_F_Ge {} -> comparisonResultRep
951 MO_F_Le {} -> comparisonResultRep
952 MO_F_Gt {} -> comparisonResultRep
953 MO_F_Lt {} -> comparisonResultRep
955 MO_And {} -> ty1 -- Used for pointer masking
958 MO_Not r -> cmmBits r
959 MO_Shl r -> cmmBits r
960 MO_U_Shr r -> cmmBits r
961 MO_S_Shr r -> cmmBits r
963 MO_SS_Conv _ to -> cmmBits to
964 MO_UU_Conv _ to -> cmmBits to
965 MO_FS_Conv _ to -> cmmBits to
966 MO_SF_Conv _ to -> cmmFloat to
967 MO_FF_Conv _ to -> cmmFloat to
971 comparisonResultRep :: CmmType
972 comparisonResultRep = bWord -- is it?
975 -- -----------------------------------------------------------------------------
978 -- | This function is used for debugging only: we can check whether an
979 -- application of a MachOp is "type-correct" by checking that the MachReps of
980 -- its arguments are the same as the MachOp expects. This is used when
981 -- linting a CmmExpr.
983 machOpArgReps :: MachOp -> [Width]
991 MO_S_MulMayOflo r -> [r,r]
995 MO_U_MulMayOflo r -> [r,r]
1012 MO_F_Quot r -> [r,r]
1025 MO_Shl r -> [r,wordWidth]
1026 MO_U_Shr r -> [r,wordWidth]
1027 MO_S_Shr r -> [r,wordWidth]
1029 MO_SS_Conv from _ -> [from]
1030 MO_UU_Conv from _ -> [from]
1031 MO_SF_Conv from _ -> [from]
1032 MO_FS_Conv from _ -> [from]
1033 MO_FF_Conv from _ -> [from]
1036 -------------------------------------------------------------------------
1037 {- Note [Signed vs unsigned]
1038 ~~~~~~~~~~~~~~~~~~~~~~~~~
1039 Should a CmmType include a signed vs. unsigned distinction?
1041 This is very much like a "hint" in C-- terminology: it isn't necessary
1042 in order to generate correct code, but it might be useful in that the
1043 compiler can generate better code if it has access to higher-level
1044 hints about data. This is important at call boundaries, because the
1045 definition of a function is not visible at all of its call sites, so
1046 the compiler cannot infer the hints.
1048 Here in Cmm, we're taking a slightly different approach. We include
1049 the int vs. float hint in the MachRep, because (a) the majority of
1050 platforms have a strong distinction between float and int registers,
1051 and (b) we don't want to do any heavyweight hint-inference in the
1052 native code backend in order to get good code. We're treating the
1053 hint more like a type: our Cmm is always completely consistent with
1054 respect to hints. All coercions between float and int are explicit.
1056 What about the signed vs. unsigned hint? This information might be
1057 useful if we want to keep sub-word-sized values in word-size
1058 registers, which we must do if we only have word-sized registers.
1060 On such a system, there are two straightforward conventions for
1061 representing sub-word-sized values:
1063 (a) Leave the upper bits undefined. Comparison operations must
1064 sign- or zero-extend both operands before comparing them,
1065 depending on whether the comparison is signed or unsigned.
1067 (b) Always keep the values sign- or zero-extended as appropriate.
1068 Arithmetic operations must narrow the result to the appropriate
1071 A clever compiler might not use either (a) or (b) exclusively, instead
1072 it would attempt to minimize the coercions by analysis: the same kind
1073 of analysis that propagates hints around. In Cmm we don't want to
1074 have to do this, so we plump for having richer types and keeping the
1075 type information consistent.
1077 If signed/unsigned hints are missing from MachRep, then the only
1078 choice we have is (a), because we don't know whether the result of an
1079 operation should be sign- or zero-extended.
1081 Many architectures have extending load operations, which work well
1082 with (b). To make use of them with (a), you need to know whether the
1083 value is going to be sign- or zero-extended by an enclosing comparison
1084 (for example), which involves knowing above the context. This is
1085 doable but more complex.
1087 Further complicating the issue is foreign calls: a foreign calling
1088 convention can specify that signed 8-bit quantities are passed as
1089 sign-extended 32 bit quantities, for example (this is the case on the
1090 PowerPC). So we *do* need sign information on foreign call arguments.
1092 Pros for adding signed vs. unsigned to MachRep:
1094 - It would let us use convention (b) above, and get easier
1095 code generation for extending loads.
1097 - Less information required on foreign calls.
1099 - MachOp type would be simpler
1105 - What is the MachRep for a VanillaReg? Currently it is
1106 always wordRep, but now we have to decide whether it is
1107 signed or unsigned. The same VanillaReg can thus have
1108 different MachReps in different parts of the program.
1110 - Extra coercions cluttering up expressions.
1112 Currently for GHC, the foreign call point is moot, because we do our
1113 own promotion of sub-word-sized values to word-sized values. The Int8
1114 type is represnted by an Int# which is kept sign-extended at all times
1115 (this is slightly naughty, because we're making assumptions about the
1116 C calling convention rather early on in the compiler). However, given
1117 this, the cons outweigh the pros.