8e40654352737a98ceb4b95f27ed4f31b5e40de1
[ghc-hetmet.git] / compiler / cmm / CmmExpr.hs
1
2 module CmmExpr
3     ( CmmType   -- Abstract 
4     , b8, b16, b32, b64, f32, f64, bWord, bHalfWord, gcWord
5     , cInt, cLong
6     , cmmBits, cmmFloat
7     , typeWidth, cmmEqType, cmmEqType_ignoring_ptrhood
8     , isFloatType, isGcPtrType, isWord32, isWord64, isFloat64, isFloat32
9  
10     , Width(..)
11     , widthInBits, widthInBytes, widthInLog, widthFromBytes
12     , wordWidth, halfWordWidth, cIntWidth, cLongWidth
13     , narrowU, narrowS
14  
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
26  
27    -- MachOp
28     , MachOp(..) 
29     , pprMachOp, isCommutableMachOp, isAssociativeMachOp
30     , isComparisonMachOp, machOpResultType
31     , machOpArgReps, maybeInvertComparison
32  
33    -- MachOp builders
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
42    )
43 where
44
45 #include "HsVersions.h"
46
47 import BlockId
48 import CLabel
49 import Constants
50 import FastString
51 import FiniteMap
52 import Maybes
53 import Monad
54 import Outputable
55 import Panic
56 import Unique
57 import UniqSet
58
59 import Data.Word
60 import Data.Int
61
62 -----------------------------------------------------------------------------
63 --              CmmExpr
64 -- An expression.  Expressions have no side effects.
65 -----------------------------------------------------------------------------
66
67 data CmmExpr
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        
74         -- CmmRegOff reg i
75         --        ** is shorthand only, meaning **
76         -- CmmMachOp (MO_S_Add rep (CmmReg reg) (CmmLit (CmmInt i rep)))
77         --      where rep = cmmRegType reg
78
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
86   _e1               == _e2               = False
87
88 data CmmReg 
89   = CmmLocal  LocalReg
90   | CmmGlobal GlobalReg
91   deriving( Eq, Ord )
92
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.
95 data Area
96   = RegSlot  LocalReg
97   | CallArea AreaId
98   deriving (Eq, Ord)
99
100 data AreaId
101   = Old -- entry parameters, jumps, and returns share one call area at old end of stack
102   | Young BlockId
103   deriving (Eq, Ord)
104
105 type SubArea    = (Area, Int, Int) -- area, offset, width
106 type SubAreaSet = FiniteMap Area [SubArea]
107 type AreaMap    = FiniteMap Area Int
108
109 data CmmLit
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
119   
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
130   deriving Eq
131
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
139
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
148
149 cmmLabelType :: CLabel -> CmmType
150 cmmLabelType lbl | isGcPtrLabel lbl = gcWord
151                  | otherwise        = bWord
152
153 cmmExprWidth :: CmmExpr -> Width
154 cmmExprWidth e = typeWidth (cmmExprType e)
155
156 --------
157 --- Negation for conditional branches
158
159 maybeInvertCmmExpr :: CmmExpr -> Maybe CmmExpr
160 maybeInvertCmmExpr (CmmMachOp op args) = do op' <- maybeInvertComparison op
161                                             return (CmmMachOp op' args)
162 maybeInvertCmmExpr _ = Nothing
163
164 -----------------------------------------------------------------------------
165 --              Local registers
166 -----------------------------------------------------------------------------
167
168 data LocalReg
169   = LocalReg !Unique CmmType
170     -- ^ Parameters:
171     --   1. Identifier
172     --   2. Type
173
174 instance Eq LocalReg where
175   (LocalReg u1 _) == (LocalReg u2 _) = u1 == u2
176
177 instance Ord LocalReg where
178   compare (LocalReg u1 _) (LocalReg u2 _) = compare u1 u2
179
180 instance Uniquable LocalReg where
181   getUnique (LocalReg uniq _) = uniq
182
183 cmmRegType :: CmmReg -> CmmType
184 cmmRegType (CmmLocal  reg)      = localRegType reg
185 cmmRegType (CmmGlobal reg)      = globalRegType reg
186
187 localRegType :: LocalReg -> CmmType
188 localRegType (LocalReg _ rep) = rep
189
190 -----------------------------------------------------------------------------
191 --    Register-use information for expressions and other types 
192 -----------------------------------------------------------------------------
193
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
202
203 emptyRegSet      = emptyUniqSet
204 elemRegSet       = elementOfUniqSet
205 extendRegSet     = addOneToUniqSet
206 deleteFromRegSet = delOneFromUniqSet
207 mkRegSet         = mkUniqSet
208 minusRegSet      = minusUniqSet
209 plusRegSet       = unionUniqSets
210 timesRegSet      = intersectUniqSets
211
212 class UserOfLocalRegs a where
213   foldRegsUsed :: (b -> LocalReg -> b) -> b -> a -> b
214
215 class DefinerOfLocalRegs a where
216   foldRegsDefd :: (b -> LocalReg -> b) -> b -> a -> b
217
218 filterRegsUsed :: UserOfLocalRegs e => (LocalReg -> Bool) -> e -> RegSet
219 filterRegsUsed p e =
220     foldRegsUsed (\regs r -> if p r then extendRegSet regs r else regs)
221                  emptyRegSet e
222
223 instance UserOfLocalRegs CmmReg where
224     foldRegsUsed f z (CmmLocal reg) = f z reg
225     foldRegsUsed _ z (CmmGlobal _)  = z
226
227 instance DefinerOfLocalRegs CmmReg where
228     foldRegsDefd f z (CmmLocal reg) = f z reg
229     foldRegsDefd _ z (CmmGlobal _)  = z
230
231 instance UserOfLocalRegs LocalReg where
232     foldRegsUsed f z r = f z r
233
234 instance DefinerOfLocalRegs LocalReg where
235     foldRegsDefd f z r = f z r
236
237 instance UserOfLocalRegs RegSet where
238     foldRegsUsed f = foldUniqSet (flip f)
239
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
248
249 instance UserOfLocalRegs a => UserOfLocalRegs [a] where
250   foldRegsUsed _ set [] = set
251   foldRegsUsed f set (x:xs) = foldRegsUsed f (foldRegsUsed f set x) xs
252
253 instance DefinerOfLocalRegs a => DefinerOfLocalRegs [a] where
254   foldRegsDefd _ set [] = set
255   foldRegsDefd f set (x:xs) = foldRegsDefd f (foldRegsDefd f set x) xs
256
257 instance DefinerOfLocalRegs a => DefinerOfLocalRegs (Maybe a) where
258   foldRegsDefd _ set Nothing  = set
259   foldRegsDefd f set (Just x) = foldRegsDefd f set x
260
261
262 -----------------------------------------------------------------------------
263 --    Stack slots
264 -----------------------------------------------------------------------------
265
266 mkVarSlot :: LocalReg -> CmmExpr
267 mkVarSlot r = CmmStackSlot (RegSlot r) 0
268
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
275                   Just s  -> (map, s)
276                   Nothing -> (addToFM map r s, s) where s = mkVarSlot r
277
278 -----------------------------------------------------------------------------
279 --    Stack slot use information for expressions and other types [_$_]
280 -----------------------------------------------------------------------------
281
282
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
286
287 class DefinerOfSlots a where
288   foldSlotsDefd :: (b -> SubArea -> b) -> b -> a -> b
289
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
299
300 instance UserOfSlots a => UserOfSlots [a] where
301   foldSlotsUsed _ set [] = set
302   foldSlotsUsed f set (x:xs) = foldSlotsUsed f (foldSlotsUsed f set x) xs
303
304
305 -----------------------------------------------------------------------------
306 --              Global STG registers
307 -----------------------------------------------------------------------------
308
309 data VGcPtr = VGcPtr | VNonGcPtr deriving( Eq, Show )
310         -- TEMPORARY!!!
311
312 -----------------------------------------------------------------------------
313 --              Global STG registers
314 -----------------------------------------------------------------------------
315 vgcFlag :: CmmType -> VGcPtr
316 vgcFlag ty | isGcPtrType ty = VGcPtr
317            | otherwise      = VNonGcPtr
318
319 data GlobalReg
320   -- Argument and return registers
321   = VanillaReg                  -- pointers, unboxed ints and chars
322         {-# UNPACK #-} !Int     -- its number
323         VGcPtr
324
325   | FloatReg            -- single-precision floating-point registers
326         {-# UNPACK #-} !Int     -- its number
327
328   | DoubleReg           -- double-precision floating-point registers
329         {-# UNPACK #-} !Int     -- its number
330
331   | LongReg             -- long int registers (64-bit, really)
332         {-# UNPACK #-} !Int     -- its number
333
334   -- STG registers
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
342
343                 -- We keep the address of some commonly-called 
344                 -- functions in the register table, to keep code
345                 -- size down:
346   | EagerBlackholeInfo  -- stg_EAGER_BLACKHOLE_info
347   | GCEnter1            -- stg_gc_enter_1
348   | GCFun               -- stg_gc_fun
349
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.
354   | BaseReg
355
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).
359   | PicBaseReg
360
361   deriving( Show )
362
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
368    Sp == Sp = True
369    SpLim == SpLim = True
370    Hp == Hp = 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
379    _r1 == _r2 = False
380
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
387    compare Sp Sp = EQ
388    compare SpLim SpLim = EQ
389    compare Hp Hp = 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
407    compare Sp _ = LT
408    compare _ Sp = GT
409    compare SpLim _ = LT
410    compare _ SpLim = GT
411    compare Hp _ = LT
412    compare _ Hp = GT
413    compare HpLim _ = LT
414    compare _ HpLim = 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
423    compare GCFun _ = LT
424    compare _ GCFun = GT
425    compare BaseReg _ = LT
426    compare _ BaseReg = GT
427    compare EagerBlackholeInfo _ = LT
428    compare _ EagerBlackholeInfo = GT
429
430 -- convenient aliases
431 spReg, hpReg, spLimReg, nodeReg :: CmmReg
432 spReg = CmmGlobal Sp
433 hpReg = CmmGlobal Hp
434 spLimReg = CmmGlobal SpLim
435 nodeReg = CmmGlobal node
436
437 node :: GlobalReg
438 node = VanillaReg 1 VGcPtr
439
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
449
450
451 -----------------------------------------------------------------------------
452 --              CmmType
453 -----------------------------------------------------------------------------
454
455   -- NOTE: CmmType is an abstract type, not exported from this
456   --       module so you can easily change its representation
457   --
458   -- However Width is exported in a concrete way, 
459   -- and is used extensively in pattern-matching
460
461 data CmmType    -- The important one!
462   = CmmType CmmCat Width 
463
464 data CmmCat     -- "Category" (not exported)
465    = GcPtrCat   -- GC pointer
466    | BitsCat    -- Non-pointer
467    | FloatCat   -- Float
468    deriving( Eq )
469         -- See Note [Signed vs unsigned] at the end
470
471 instance Outputable CmmType where
472   ppr (CmmType cat wid) = ppr cat <> ppr (widthInBits wid)
473
474 instance Outputable CmmCat where
475   ppr FloatCat  = ptext $ sLit("F")
476   ppr _         = ptext $ sLit("I")
477 -- Temp Jan 08
478 --  ppr FloatCat        = ptext $ sLit("float")
479 --  ppr BitsCat   = ptext $ sLit("bits")
480 --  ppr GcPtrCat  = ptext $ sLit("gcptr")
481
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.
488
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
495
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
501    where
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
506
507 --- Simple operations on CmmType -----
508 typeWidth :: CmmType -> Width
509 typeWidth (CmmType _ w) = w
510
511 cmmBits, cmmFloat :: Width -> CmmType
512 cmmBits  = CmmType BitsCat
513 cmmFloat = CmmType FloatCat
514
515 -------- Common CmmTypes ------------
516 -- Floats and words of specific widths
517 b8, b16, b32, b64, f32, f64 :: CmmType
518 b8     = cmmBits W8
519 b16    = cmmBits W16
520 b32    = cmmBits W32
521 b64    = cmmBits W64
522 f32    = cmmFloat W32
523 f64    = cmmFloat W64
524
525 -- CmmTypes of native word widths
526 bWord, bHalfWord, gcWord :: CmmType
527 bWord     = cmmBits wordWidth
528 bHalfWord = cmmBits halfWordWidth
529 gcWord    = CmmType GcPtrCat wordWidth
530
531 cInt, cLong :: CmmType
532 cInt  = cmmBits cIntWidth
533 cLong = cmmBits cLongWidth
534
535
536 ------------ Predicates ----------------
537 isFloatType, isGcPtrType :: CmmType -> Bool
538 isFloatType (CmmType FloatCat    _) = True
539 isFloatType _other                  = False
540
541 isGcPtrType (CmmType GcPtrCat _) = True
542 isGcPtrType _other               = False
543
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
547
548 isWord64 (CmmType BitsCat  W64) = True
549 isWord64 (CmmType GcPtrCat W64) = True
550 isWord64 _other                 = False
551
552 isWord32 (CmmType BitsCat  W32) = True
553 isWord32 (CmmType GcPtrCat W32) = True
554 isWord32 _other                 = False
555
556 isFloat32 (CmmType FloatCat W32) = True
557 isFloat32 _other                 = False
558
559 isFloat64 (CmmType FloatCat W64) = True
560 isFloat64 _other                 = False
561
562 -----------------------------------------------------------------------------
563 --              Width
564 -----------------------------------------------------------------------------
565
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)
570              | W128
571              deriving (Eq, Ord, Show)
572
573 instance Outputable Width where
574    ppr rep = ptext (mrStr rep)
575
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")
583
584
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"
590
591 halfWordWidth | wORD_SIZE == 4 = W16
592               | wORD_SIZE == 8 = W32
593               | otherwise      = panic "MachOp.halfWordRep: Unknown word size"
594
595 -- cIntRep is the Width for a C-language 'int'
596 cIntWidth, cLongWidth :: Width
597 #if SIZEOF_INT == 4
598 cIntWidth = W32
599 #elif  SIZEOF_INT == 8
600 cIntWidth = W64
601 #endif
602
603 #if SIZEOF_LONG == 4
604 cLongWidth = W32
605 #elif  SIZEOF_LONG == 8
606 cLongWidth = W64
607 #endif
608
609 widthInBits :: Width -> Int
610 widthInBits W8   = 8
611 widthInBits W16  = 16
612 widthInBits W32  = 32
613 widthInBits W64  = 64
614 widthInBits W128 = 128
615 widthInBits W80  = 80
616
617 widthInBytes :: Width -> Int
618 widthInBytes W8   = 1
619 widthInBytes W16  = 2
620 widthInBytes W32  = 4
621 widthInBytes W64  = 8
622 widthInBytes W128 = 16
623 widthInBytes W80  = 10
624
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)
633
634 -- log_2 of the width in bytes, useful for generating shifts.
635 widthInLog :: Width -> Int
636 widthInLog W8   = 0
637 widthInLog W16  = 1
638 widthInLog W32  = 2
639 widthInLog W64  = 3
640 widthInLog W128 = 4
641 widthInLog W80  = panic "widthInLog: F80"
642
643 -- widening / narrowing
644
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"
651
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"
658
659 -----------------------------------------------------------------------------
660 --              MachOp
661 -----------------------------------------------------------------------------
662
663 {- 
664 Implementation notes:
665
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.
669 -}
670
671
672 {- |
673 Machine-level primops; ones which we can reasonably delegate to the
674 native code generators to handle.  Basically contains C's primops
675 and no others.
676
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.
683
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
687 right casts.  
688 -}
689
690 data MachOp
691   -- Integer operations (insensitive to signed/unsigned)
692   = MO_Add Width
693   | MO_Sub Width
694   | MO_Eq  Width
695   | MO_Ne  Width
696   | MO_Mul Width                -- low word of multiply
697
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 -
703
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)
708
709   -- Signed comparisons
710   | MO_S_Ge Width
711   | MO_S_Le Width
712   | MO_S_Gt Width
713   | MO_S_Lt Width
714
715   -- Unsigned comparisons
716   | MO_U_Ge Width
717   | MO_U_Le Width
718   | MO_U_Gt Width
719   | MO_U_Lt Width
720
721   -- Floating point arithmetic
722   | MO_F_Add  Width
723   | MO_F_Sub  Width
724   | MO_F_Neg  Width             -- unary -
725   | MO_F_Mul  Width
726   | MO_F_Quot Width
727
728   -- Floating point comparison
729   | MO_F_Eq Width
730   | MO_F_Ne Width
731   | MO_F_Ge Width
732   | MO_F_Le Width
733   | MO_F_Gt Width
734   | MO_F_Lt Width
735
736   -- Bitwise operations.  Not all of these may be supported 
737   -- at all sizes, and only integral Widths are valid.
738   | MO_And   Width
739   | MO_Or    Width
740   | MO_Xor   Width
741   | MO_Not   Width
742   | MO_Shl   Width
743   | MO_U_Shr Width      -- unsigned shift right
744   | MO_S_Shr Width      -- signed shift right
745
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
753   deriving (Eq, Show)
754
755 pprMachOp :: MachOp -> SDoc
756 pprMachOp mo = text (show mo)
757
758
759
760 -- -----------------------------------------------------------------------------
761 -- Some common MachReps
762
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.
767
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
776     :: MachOp
777
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
788
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
793
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
798
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 
806
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
811
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
818
819 mo_WordTo8      = MO_UU_Conv wordWidth W8
820 mo_WordTo16     = MO_UU_Conv wordWidth W16
821 mo_WordTo32     = MO_UU_Conv wordWidth W32
822
823 mo_32To8        = MO_UU_Conv W32 W8
824 mo_32To16       = MO_UU_Conv W32 W16
825
826
827 -- ----------------------------------------------------------------------------
828 -- isCommutableMachOp
829
830 {- |
831 Returns 'True' if the MachOp has commutable arguments.  This is used
832 in the platform-independent Cmm optimisations.
833
834 If in doubt, return 'False'.  This generates worse code on the
835 native routes, but is otherwise harmless.
836 -}
837 isCommutableMachOp :: MachOp -> Bool
838 isCommutableMachOp mop = 
839   case mop of
840         MO_Add _                -> True
841         MO_Eq _                 -> True
842         MO_Ne _                 -> True
843         MO_Mul _                -> True
844         MO_S_MulMayOflo _       -> True
845         MO_U_MulMayOflo _       -> True
846         MO_And _                -> True
847         MO_Or _                 -> True
848         MO_Xor _                -> True
849         _other                  -> False
850
851 -- ----------------------------------------------------------------------------
852 -- isAssociativeMachOp
853
854 {- |
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.
857
858 If in doubt, return 'False'.  This generates worse code on the
859 native routes, but is otherwise harmless.
860 -}
861 isAssociativeMachOp :: MachOp -> Bool
862 isAssociativeMachOp mop = 
863   case mop of
864         MO_Add {} -> True       -- NB: does not include
865         MO_Mul {} -> True --     floatint point!
866         MO_And {} -> True
867         MO_Or  {} -> True
868         MO_Xor {} -> True
869         _other    -> False
870
871 -- ----------------------------------------------------------------------------
872 -- isComparisonMachOp
873
874 {- | 
875 Returns 'True' if the MachOp is a comparison.
876
877 If in doubt, return False.  This generates worse code on the
878 native routes, but is otherwise harmless.
879 -}
880 isComparisonMachOp :: MachOp -> Bool
881 isComparisonMachOp mop = 
882   case mop of
883     MO_Eq   _  -> True
884     MO_Ne   _  -> True
885     MO_S_Ge _  -> True
886     MO_S_Le _  -> True
887     MO_S_Gt _  -> True
888     MO_S_Lt _  -> True
889     MO_U_Ge _  -> True
890     MO_U_Le _  -> True
891     MO_U_Gt _  -> True
892     MO_U_Lt _  -> True
893     MO_F_Eq  {} -> True
894     MO_F_Ne  {} -> True
895     MO_F_Ge  {} -> True
896     MO_F_Le  {} -> True
897     MO_F_Gt  {} -> True
898     MO_F_Lt  {} -> True
899     _other     -> False
900
901 -- -----------------------------------------------------------------------------
902 -- Inverting conditions
903
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)).
909
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)   
929         _other    -> Nothing
930
931 -- ----------------------------------------------------------------------------
932 -- machOpResultType
933
934 {- |
935 Returns the MachRep of the result of a MachOp.
936 -}
937 machOpResultType :: MachOp -> [CmmType] -> CmmType
938 machOpResultType mop tys =
939   case mop of
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
950
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
957
958     MO_U_Ge {}          -> comparisonResultRep
959     MO_U_Le {}          -> comparisonResultRep
960     MO_U_Gt {}          -> comparisonResultRep
961     MO_U_Lt {}          -> comparisonResultRep
962
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
974
975     MO_And {}           -> ty1  -- Used for pointer masking
976     MO_Or {}            -> ty1
977     MO_Xor {}           -> ty1
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
982
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
988   where
989     (ty1:_) = tys
990
991 comparisonResultRep :: CmmType
992 comparisonResultRep = bWord  -- is it?
993
994
995 -- -----------------------------------------------------------------------------
996 -- machOpArgReps
997
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.
1002
1003 machOpArgReps :: MachOp -> [Width]
1004 machOpArgReps op = 
1005   case op of
1006     MO_Add    r         -> [r,r]
1007     MO_Sub    r         -> [r,r]
1008     MO_Eq     r         -> [r,r]
1009     MO_Ne     r         -> [r,r]
1010     MO_Mul    r         -> [r,r]
1011     MO_S_MulMayOflo r   -> [r,r]
1012     MO_S_Quot r         -> [r,r]
1013     MO_S_Rem  r         -> [r,r]
1014     MO_S_Neg  r         -> [r]
1015     MO_U_MulMayOflo r   -> [r,r]
1016     MO_U_Quot r         -> [r,r]
1017     MO_U_Rem  r         -> [r,r]
1018
1019     MO_S_Ge r           -> [r,r]
1020     MO_S_Le r           -> [r,r]
1021     MO_S_Gt r           -> [r,r]
1022     MO_S_Lt r           -> [r,r]
1023
1024     MO_U_Ge r           -> [r,r]
1025     MO_U_Le r           -> [r,r]
1026     MO_U_Gt r           -> [r,r]
1027     MO_U_Lt r           -> [r,r]
1028
1029     MO_F_Add r          -> [r,r]
1030     MO_F_Sub r          -> [r,r]
1031     MO_F_Mul r          -> [r,r]
1032     MO_F_Quot r         -> [r,r]
1033     MO_F_Neg r          -> [r]
1034     MO_F_Eq  r          -> [r,r]
1035     MO_F_Ne  r          -> [r,r]
1036     MO_F_Ge  r          -> [r,r]
1037     MO_F_Le  r          -> [r,r]
1038     MO_F_Gt  r          -> [r,r]
1039     MO_F_Lt  r          -> [r,r]
1040
1041     MO_And   r          -> [r,r]
1042     MO_Or    r          -> [r,r]
1043     MO_Xor   r          -> [r,r]
1044     MO_Not   r          -> [r]
1045     MO_Shl   r          -> [r,wordWidth]
1046     MO_U_Shr r          -> [r,wordWidth]
1047     MO_S_Shr r          -> [r,wordWidth]
1048
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]
1054
1055
1056 -------------------------------------------------------------------------
1057 {-      Note [Signed vs unsigned]
1058         ~~~~~~~~~~~~~~~~~~~~~~~~~
1059 Should a CmmType include a signed vs. unsigned distinction?
1060
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.
1067
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.
1075
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.
1079
1080 On such a system, there are two straightforward conventions for
1081 representing sub-word-sized values:
1082
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.
1086
1087 (b) Always keep the values sign- or zero-extended as appropriate.
1088     Arithmetic operations must narrow the result to the appropriate
1089     size.
1090
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.
1096
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.
1100
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.
1106
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.
1111
1112 Pros for adding signed vs. unsigned to MachRep:
1113
1114   - It would let us use convention (b) above, and get easier
1115     code generation for extending loads.
1116
1117   - Less information required on foreign calls.
1118   
1119   - MachOp type would be simpler
1120
1121 Cons:
1122
1123   - More complexity
1124
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.
1129
1130   - Extra coercions cluttering up expressions.
1131
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.
1138
1139 -}
1140