a4d07c2c60316f6956af3e51d0241fa7219800ba
[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, isStackSlotOf
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 Outputable
53 import Unique
54 import UniqSet
55
56 import Data.Word
57 import Data.Int
58
59 -----------------------------------------------------------------------------
60 --              CmmExpr
61 -- An expression.  Expressions have no side effects.
62 -----------------------------------------------------------------------------
63
64 data CmmExpr
65   = CmmLit CmmLit               -- Literal
66   | CmmLoad CmmExpr CmmType     -- Read memory location
67   | CmmReg CmmReg               -- Contents of register
68   | CmmMachOp MachOp [CmmExpr]  -- Machine operation (+, -, *, etc.)
69   | CmmStackSlot Area Int       -- addressing expression of a stack slot
70   | CmmRegOff CmmReg Int        
71         -- CmmRegOff reg i
72         --        ** is shorthand only, meaning **
73         -- CmmMachOp (MO_S_Add rep (CmmReg reg) (CmmLit (CmmInt i rep)))
74         --      where rep = cmmRegType reg
75
76 instance Eq CmmExpr where       -- Equality ignores the types
77   CmmLit l1         == CmmLit l2         = l1==l2
78   CmmLoad e1 _      == CmmLoad e2 _      = e1==e2
79   CmmReg r1         == CmmReg r2         = r1==r2
80   CmmRegOff r1 i1   == CmmRegOff r2 i2   = r1==r2 && i1==i2
81   CmmMachOp op1 es1 == CmmMachOp op2 es2 = op1==op2 && es1==es2
82   CmmStackSlot a1 i1 == CmmStackSlot a2 i2 = a1==a2 && i1==i2
83   _e1               == _e2               = False
84
85 data CmmReg 
86   = CmmLocal  LocalReg
87   | CmmGlobal GlobalReg
88   deriving( Eq, Ord )
89
90 -- | A stack area is either the stack slot where a variable is spilled
91 -- or the stack space where function arguments and results are passed.
92 data Area
93   = RegSlot  LocalReg
94   | CallArea AreaId
95   deriving (Eq, Ord)
96
97 data AreaId
98   = Old            -- See Note [Old Area]
99   | Young BlockId
100   deriving (Eq, Ord)
101
102 {- Note [Old Area] 
103 ~~~~~~~~~~~~~~~~~~
104 There is a single call area 'Old', allocated at the extreme old
105 end of the stack frame (ie just younger than the return address)
106 which holds:
107   * incoming (overflow) parameters, 
108   * outgoing (overflow) parameter to tail calls,
109   * outgoing (overflow) result values 
110   * the update frame (if any)
111
112 Its size is the max of all these requirements.  On entry, the stack
113 pointer will point to the youngest incoming parameter, which is not
114 necessarily at the young end of the Old area.
115
116 End of note -}
117
118 type SubArea    = (Area, Int, Int) -- area, offset, width
119 type SubAreaSet = FiniteMap Area [SubArea]
120
121 type AreaMap    = FiniteMap Area Int
122      -- Byte offset of the oldest byte of the Area, 
123      -- relative to the oldest byte of the Old Area
124
125 data CmmLit
126   = CmmInt Integer  Width
127         -- Interpretation: the 2's complement representation of the value
128         -- is truncated to the specified size.  This is easier than trying
129         -- to keep the value within range, because we don't know whether
130         -- it will be used as a signed or unsigned value (the CmmType doesn't
131         -- distinguish between signed & unsigned).
132   | CmmFloat  Rational Width
133   | CmmLabel    CLabel                  -- Address of label
134   | CmmLabelOff CLabel Int              -- Address of label + byte offset
135   
136         -- Due to limitations in the C backend, the following
137         -- MUST ONLY be used inside the info table indicated by label2
138         -- (label2 must be the info label), and label1 must be an
139         -- SRT, a slow entrypoint or a large bitmap (see the Mangler)
140         -- Don't use it at all unless tablesNextToCode.
141         -- It is also used inside the NCG during when generating
142         -- position-independent code. 
143   | CmmLabelDiffOff CLabel CLabel Int   -- label1 - label2 + offset
144   | CmmBlock BlockId                    -- Code label
145   | CmmHighStackMark -- stands for the max stack space used during a procedure
146   deriving Eq
147
148 cmmExprType :: CmmExpr -> CmmType
149 cmmExprType (CmmLit lit)        = cmmLitType lit
150 cmmExprType (CmmLoad _ rep)     = rep
151 cmmExprType (CmmReg reg)        = cmmRegType reg
152 cmmExprType (CmmMachOp op args) = machOpResultType op (map cmmExprType args)
153 cmmExprType (CmmRegOff reg _)   = cmmRegType reg
154 cmmExprType (CmmStackSlot _ _)  = bWord -- an address
155
156 cmmLitType :: CmmLit -> CmmType
157 cmmLitType (CmmInt _ width)     = cmmBits  width
158 cmmLitType (CmmFloat _ width)   = cmmFloat width
159 cmmLitType (CmmLabel lbl)       = cmmLabelType lbl
160 cmmLitType (CmmLabelOff lbl _)  = cmmLabelType lbl
161 cmmLitType (CmmLabelDiffOff {}) = bWord
162 cmmLitType (CmmBlock _)         = bWord
163 cmmLitType (CmmHighStackMark)   = bWord
164
165 cmmLabelType :: CLabel -> CmmType
166 cmmLabelType lbl | isGcPtrLabel lbl = gcWord
167                  | otherwise        = bWord
168
169 cmmExprWidth :: CmmExpr -> Width
170 cmmExprWidth e = typeWidth (cmmExprType e)
171
172 --------
173 --- Negation for conditional branches
174
175 maybeInvertCmmExpr :: CmmExpr -> Maybe CmmExpr
176 maybeInvertCmmExpr (CmmMachOp op args) = do op' <- maybeInvertComparison op
177                                             return (CmmMachOp op' args)
178 maybeInvertCmmExpr _ = Nothing
179
180 -----------------------------------------------------------------------------
181 --              Local registers
182 -----------------------------------------------------------------------------
183
184 data LocalReg
185   = LocalReg !Unique CmmType
186     -- ^ Parameters:
187     --   1. Identifier
188     --   2. Type
189
190 instance Eq LocalReg where
191   (LocalReg u1 _) == (LocalReg u2 _) = u1 == u2
192
193 instance Ord LocalReg where
194   compare (LocalReg u1 _) (LocalReg u2 _) = compare u1 u2
195
196 instance Uniquable LocalReg where
197   getUnique (LocalReg uniq _) = uniq
198
199 cmmRegType :: CmmReg -> CmmType
200 cmmRegType (CmmLocal  reg)      = localRegType reg
201 cmmRegType (CmmGlobal reg)      = globalRegType reg
202
203 localRegType :: LocalReg -> CmmType
204 localRegType (LocalReg _ rep) = rep
205
206 -----------------------------------------------------------------------------
207 --    Register-use information for expressions and other types 
208 -----------------------------------------------------------------------------
209
210 -- | Sets of local registers
211 type RegSet              =  UniqSet LocalReg
212 emptyRegSet             :: RegSet
213 elemRegSet              :: LocalReg -> RegSet -> Bool
214 extendRegSet            :: RegSet -> LocalReg -> RegSet
215 deleteFromRegSet        :: RegSet -> LocalReg -> RegSet
216 mkRegSet                :: [LocalReg] -> RegSet
217 minusRegSet, plusRegSet, timesRegSet :: RegSet -> RegSet -> RegSet
218
219 emptyRegSet      = emptyUniqSet
220 elemRegSet       = elementOfUniqSet
221 extendRegSet     = addOneToUniqSet
222 deleteFromRegSet = delOneFromUniqSet
223 mkRegSet         = mkUniqSet
224 minusRegSet      = minusUniqSet
225 plusRegSet       = unionUniqSets
226 timesRegSet      = intersectUniqSets
227
228 class UserOfLocalRegs a where
229   foldRegsUsed :: (b -> LocalReg -> b) -> b -> a -> b
230
231 class DefinerOfLocalRegs a where
232   foldRegsDefd :: (b -> LocalReg -> b) -> b -> a -> b
233
234 filterRegsUsed :: UserOfLocalRegs e => (LocalReg -> Bool) -> e -> RegSet
235 filterRegsUsed p e =
236     foldRegsUsed (\regs r -> if p r then extendRegSet regs r else regs)
237                  emptyRegSet e
238
239 instance UserOfLocalRegs CmmReg where
240     foldRegsUsed f z (CmmLocal reg) = f z reg
241     foldRegsUsed _ z (CmmGlobal _)  = z
242
243 instance DefinerOfLocalRegs CmmReg where
244     foldRegsDefd f z (CmmLocal reg) = f z reg
245     foldRegsDefd _ z (CmmGlobal _)  = z
246
247 instance UserOfLocalRegs LocalReg where
248     foldRegsUsed f z r = f z r
249
250 instance DefinerOfLocalRegs LocalReg where
251     foldRegsDefd f z r = f z r
252
253 instance UserOfLocalRegs RegSet where
254     foldRegsUsed f = foldUniqSet (flip f)
255
256 instance UserOfLocalRegs CmmExpr where
257   foldRegsUsed f z e = expr z e
258     where expr z (CmmLit _)          = z
259           expr z (CmmLoad addr _)    = foldRegsUsed f z addr
260           expr z (CmmReg r)          = foldRegsUsed f z r
261           expr z (CmmMachOp _ exprs) = foldRegsUsed f z exprs
262           expr z (CmmRegOff r _)     = foldRegsUsed f z r
263           expr z (CmmStackSlot _ _)  = z
264
265 instance UserOfLocalRegs a => UserOfLocalRegs [a] where
266   foldRegsUsed _ set [] = set
267   foldRegsUsed f set (x:xs) = foldRegsUsed f (foldRegsUsed f set x) xs
268
269 instance DefinerOfLocalRegs a => DefinerOfLocalRegs [a] where
270   foldRegsDefd _ set [] = set
271   foldRegsDefd f set (x:xs) = foldRegsDefd f (foldRegsDefd f set x) xs
272
273 instance DefinerOfLocalRegs a => DefinerOfLocalRegs (Maybe a) where
274   foldRegsDefd _ set Nothing  = set
275   foldRegsDefd f set (Just x) = foldRegsDefd f set x
276
277
278 -----------------------------------------------------------------------------
279 --    Stack slots
280 -----------------------------------------------------------------------------
281
282 isStackSlotOf :: CmmExpr -> LocalReg -> Bool
283 isStackSlotOf (CmmStackSlot (RegSlot r) _) r' = r == r'
284 isStackSlotOf _ _ = False
285
286 -----------------------------------------------------------------------------
287 --    Stack slot use information for expressions and other types [_$_]
288 -----------------------------------------------------------------------------
289
290 -- Fold over the area, the offset into the area, and the width of the subarea.
291 class UserOfSlots a where
292   foldSlotsUsed :: (b -> SubArea -> b) -> b -> a -> b
293
294 class DefinerOfSlots a where
295   foldSlotsDefd :: (b -> SubArea -> b) -> b -> a -> b
296
297 instance UserOfSlots CmmExpr where
298   foldSlotsUsed f z e = expr z e
299     where expr z (CmmLit _)          = z
300           expr z (CmmLoad (CmmStackSlot a i) ty) = f z (a, i, widthInBytes $ typeWidth ty)
301           expr z (CmmLoad addr _)    = foldSlotsUsed f z addr
302           expr z (CmmReg _)          = z
303           expr z (CmmMachOp _ exprs) = foldSlotsUsed f z exprs
304           expr z (CmmRegOff _ _)     = z
305           expr z (CmmStackSlot _ _)  = z
306
307 instance UserOfSlots a => UserOfSlots [a] where
308   foldSlotsUsed _ set [] = set
309   foldSlotsUsed f set (x:xs) = foldSlotsUsed f (foldSlotsUsed f set x) xs
310
311
312 -----------------------------------------------------------------------------
313 --              Global STG registers
314 -----------------------------------------------------------------------------
315
316 data VGcPtr = VGcPtr | VNonGcPtr deriving( Eq, Show )
317         -- TEMPORARY!!!
318
319 -----------------------------------------------------------------------------
320 --              Global STG registers
321 -----------------------------------------------------------------------------
322 vgcFlag :: CmmType -> VGcPtr
323 vgcFlag ty | isGcPtrType ty = VGcPtr
324            | otherwise      = VNonGcPtr
325
326 data GlobalReg
327   -- Argument and return registers
328   = VanillaReg                  -- pointers, unboxed ints and chars
329         {-# UNPACK #-} !Int     -- its number
330         VGcPtr
331
332   | FloatReg            -- single-precision floating-point registers
333         {-# UNPACK #-} !Int     -- its number
334
335   | DoubleReg           -- double-precision floating-point registers
336         {-# UNPACK #-} !Int     -- its number
337
338   | LongReg             -- long int registers (64-bit, really)
339         {-# UNPACK #-} !Int     -- its number
340
341   -- STG registers
342   | Sp                  -- Stack ptr; points to last occupied stack location.
343   | SpLim               -- Stack limit
344   | Hp                  -- Heap ptr; points to last occupied heap location.
345   | HpLim               -- Heap limit register
346   | CurrentTSO          -- pointer to current thread's TSO
347   | CurrentNursery      -- pointer to allocation area
348   | HpAlloc             -- allocation count for heap check failure
349
350                 -- We keep the address of some commonly-called 
351                 -- functions in the register table, to keep code
352                 -- size down:
353   | EagerBlackholeInfo  -- stg_EAGER_BLACKHOLE_info
354   | GCEnter1            -- stg_gc_enter_1
355   | GCFun               -- stg_gc_fun
356
357   -- Base offset for the register table, used for accessing registers
358   -- which do not have real registers assigned to them.  This register
359   -- will only appear after we have expanded GlobalReg into memory accesses
360   -- (where necessary) in the native code generator.
361   | BaseReg
362
363   -- Base Register for PIC (position-independent code) calculations
364   -- Only used inside the native code generator. It's exact meaning differs
365   -- from platform to platform (see module PositionIndependentCode).
366   | PicBaseReg
367
368   deriving( Show )
369
370 instance Eq GlobalReg where
371    VanillaReg i _ == VanillaReg j _ = i==j      -- Ignore type when seeking clashes
372    FloatReg i == FloatReg j = i==j
373    DoubleReg i == DoubleReg j = i==j
374    LongReg i == LongReg j = i==j
375    Sp == Sp = True
376    SpLim == SpLim = True
377    Hp == Hp = True
378    HpLim == HpLim = True
379    CurrentTSO == CurrentTSO = True
380    CurrentNursery == CurrentNursery = True
381    HpAlloc == HpAlloc = True
382    GCEnter1 == GCEnter1 = True
383    GCFun == GCFun = True
384    BaseReg == BaseReg = True
385    PicBaseReg == PicBaseReg = True
386    _r1 == _r2 = False
387
388 instance Ord GlobalReg where
389    compare (VanillaReg i _) (VanillaReg j _) = compare i j
390      -- Ignore type when seeking clashes
391    compare (FloatReg i)  (FloatReg  j) = compare i j
392    compare (DoubleReg i) (DoubleReg j) = compare i j
393    compare (LongReg i)   (LongReg   j) = compare i j
394    compare Sp Sp = EQ
395    compare SpLim SpLim = EQ
396    compare Hp Hp = EQ
397    compare HpLim HpLim = EQ
398    compare CurrentTSO CurrentTSO = EQ
399    compare CurrentNursery CurrentNursery = EQ
400    compare HpAlloc HpAlloc = EQ
401    compare EagerBlackholeInfo EagerBlackholeInfo = EQ
402    compare GCEnter1 GCEnter1 = EQ
403    compare GCFun GCFun = EQ
404    compare BaseReg BaseReg = EQ
405    compare PicBaseReg PicBaseReg = EQ
406    compare (VanillaReg _ _) _ = LT
407    compare _ (VanillaReg _ _) = GT
408    compare (FloatReg _) _     = LT
409    compare _ (FloatReg _)     = GT
410    compare (DoubleReg _) _    = LT
411    compare _ (DoubleReg _)    = GT
412    compare (LongReg _) _      = LT
413    compare _ (LongReg _)      = GT
414    compare Sp _ = LT
415    compare _ Sp = GT
416    compare SpLim _ = LT
417    compare _ SpLim = GT
418    compare Hp _ = LT
419    compare _ Hp = GT
420    compare HpLim _ = LT
421    compare _ HpLim = GT
422    compare CurrentTSO _ = LT
423    compare _ CurrentTSO = GT
424    compare CurrentNursery _ = LT
425    compare _ CurrentNursery = GT
426    compare HpAlloc _ = LT
427    compare _ HpAlloc = GT
428    compare GCEnter1 _ = LT
429    compare _ GCEnter1 = GT
430    compare GCFun _ = LT
431    compare _ GCFun = GT
432    compare BaseReg _ = LT
433    compare _ BaseReg = GT
434    compare EagerBlackholeInfo _ = LT
435    compare _ EagerBlackholeInfo = GT
436
437 -- convenient aliases
438 spReg, hpReg, spLimReg, nodeReg :: CmmReg
439 spReg = CmmGlobal Sp
440 hpReg = CmmGlobal Hp
441 spLimReg = CmmGlobal SpLim
442 nodeReg = CmmGlobal node
443
444 node :: GlobalReg
445 node = VanillaReg 1 VGcPtr
446
447 globalRegType :: GlobalReg -> CmmType
448 globalRegType (VanillaReg _ VGcPtr)    = gcWord
449 globalRegType (VanillaReg _ VNonGcPtr) = bWord
450 globalRegType (FloatReg _)      = cmmFloat W32
451 globalRegType (DoubleReg _)     = cmmFloat W64
452 globalRegType (LongReg _)       = cmmBits W64
453 globalRegType Hp                = gcWord        -- The initialiser for all 
454                                                 -- dynamically allocated closures
455 globalRegType _                 = bWord
456
457
458 -----------------------------------------------------------------------------
459 --              CmmType
460 -----------------------------------------------------------------------------
461
462   -- NOTE: CmmType is an abstract type, not exported from this
463   --       module so you can easily change its representation
464   --
465   -- However Width is exported in a concrete way, 
466   -- and is used extensively in pattern-matching
467
468 data CmmType    -- The important one!
469   = CmmType CmmCat Width 
470
471 data CmmCat     -- "Category" (not exported)
472    = GcPtrCat   -- GC pointer
473    | BitsCat    -- Non-pointer
474    | FloatCat   -- Float
475    deriving( Eq )
476         -- See Note [Signed vs unsigned] at the end
477
478 instance Outputable CmmType where
479   ppr (CmmType cat wid) = ppr cat <> ppr (widthInBits wid)
480
481 instance Outputable CmmCat where
482   ppr FloatCat  = ptext $ sLit("F")
483   ppr _         = ptext $ sLit("I")
484 -- Temp Jan 08
485 --  ppr FloatCat        = ptext $ sLit("float")
486 --  ppr BitsCat   = ptext $ sLit("bits")
487 --  ppr GcPtrCat  = ptext $ sLit("gcptr")
488
489 -- Why is CmmType stratified?  For native code generation, 
490 -- most of the time you just want to know what sort of register
491 -- to put the thing in, and for this you need to know how
492 -- many bits thing has and whether it goes in a floating-point
493 -- register.  By contrast, the distinction between GcPtr and
494 -- GcNonPtr is of interest to only a few parts of the code generator.
495
496 -------- Equality on CmmType --------------
497 -- CmmType is *not* an instance of Eq; sometimes we care about the
498 -- Gc/NonGc distinction, and sometimes we don't
499 -- So we use an explicit function to force you to think about it
500 cmmEqType :: CmmType -> CmmType -> Bool -- Exact equality
501 cmmEqType (CmmType c1 w1) (CmmType c2 w2) = c1==c2 && w1==w2
502
503 cmmEqType_ignoring_ptrhood :: CmmType -> CmmType -> Bool
504   -- This equality is temporary; used in CmmLint
505   -- but the RTS files are not yet well-typed wrt pointers
506 cmmEqType_ignoring_ptrhood (CmmType c1 w1) (CmmType c2 w2)
507    = c1 `weak_eq` c2 && w1==w2
508    where
509       FloatCat `weak_eq` FloatCat = True 
510       FloatCat `weak_eq` _other   = False
511       _other   `weak_eq` FloatCat = False
512       _word1   `weak_eq` _word2   = True        -- Ignores GcPtr
513
514 --- Simple operations on CmmType -----
515 typeWidth :: CmmType -> Width
516 typeWidth (CmmType _ w) = w
517
518 cmmBits, cmmFloat :: Width -> CmmType
519 cmmBits  = CmmType BitsCat
520 cmmFloat = CmmType FloatCat
521
522 -------- Common CmmTypes ------------
523 -- Floats and words of specific widths
524 b8, b16, b32, b64, f32, f64 :: CmmType
525 b8     = cmmBits W8
526 b16    = cmmBits W16
527 b32    = cmmBits W32
528 b64    = cmmBits W64
529 f32    = cmmFloat W32
530 f64    = cmmFloat W64
531
532 -- CmmTypes of native word widths
533 bWord, bHalfWord, gcWord :: CmmType
534 bWord     = cmmBits wordWidth
535 bHalfWord = cmmBits halfWordWidth
536 gcWord    = CmmType GcPtrCat wordWidth
537
538 cInt, cLong :: CmmType
539 cInt  = cmmBits cIntWidth
540 cLong = cmmBits cLongWidth
541
542
543 ------------ Predicates ----------------
544 isFloatType, isGcPtrType :: CmmType -> Bool
545 isFloatType (CmmType FloatCat    _) = True
546 isFloatType _other                  = False
547
548 isGcPtrType (CmmType GcPtrCat _) = True
549 isGcPtrType _other               = False
550
551 isWord32, isWord64, isFloat32, isFloat64 :: CmmType -> Bool
552 -- isWord64 is true of 64-bit non-floats (both gc-ptrs and otherwise)
553 -- isFloat32 and 64 are obvious
554
555 isWord64 (CmmType BitsCat  W64) = True
556 isWord64 (CmmType GcPtrCat W64) = True
557 isWord64 _other                 = False
558
559 isWord32 (CmmType BitsCat  W32) = True
560 isWord32 (CmmType GcPtrCat W32) = True
561 isWord32 _other                 = False
562
563 isFloat32 (CmmType FloatCat W32) = True
564 isFloat32 _other                 = False
565
566 isFloat64 (CmmType FloatCat W64) = True
567 isFloat64 _other                 = False
568
569 -----------------------------------------------------------------------------
570 --              Width
571 -----------------------------------------------------------------------------
572
573 data Width   = W8 | W16 | W32 | W64 
574              | W80      -- Extended double-precision float, 
575                         -- used in x86 native codegen only.
576                         -- (we use Ord, so it'd better be in this order)
577              | W128
578              deriving (Eq, Ord, Show)
579
580 instance Outputable Width where
581    ppr rep = ptext (mrStr rep)
582
583 mrStr :: Width -> LitString
584 mrStr W8   = sLit("W8")
585 mrStr W16  = sLit("W16")
586 mrStr W32  = sLit("W32")
587 mrStr W64  = sLit("W64")
588 mrStr W128 = sLit("W128")
589 mrStr W80  = sLit("W80")
590
591
592 -------- Common Widths  ------------
593 wordWidth, halfWordWidth :: Width
594 wordWidth | wORD_SIZE == 4 = W32
595           | wORD_SIZE == 8 = W64
596           | otherwise      = panic "MachOp.wordRep: Unknown word size"
597
598 halfWordWidth | wORD_SIZE == 4 = W16
599               | wORD_SIZE == 8 = W32
600               | otherwise      = panic "MachOp.halfWordRep: Unknown word size"
601
602 -- cIntRep is the Width for a C-language 'int'
603 cIntWidth, cLongWidth :: Width
604 #if SIZEOF_INT == 4
605 cIntWidth = W32
606 #elif  SIZEOF_INT == 8
607 cIntWidth = W64
608 #endif
609
610 #if SIZEOF_LONG == 4
611 cLongWidth = W32
612 #elif  SIZEOF_LONG == 8
613 cLongWidth = W64
614 #endif
615
616 widthInBits :: Width -> Int
617 widthInBits W8   = 8
618 widthInBits W16  = 16
619 widthInBits W32  = 32
620 widthInBits W64  = 64
621 widthInBits W128 = 128
622 widthInBits W80  = 80
623
624 widthInBytes :: Width -> Int
625 widthInBytes W8   = 1
626 widthInBytes W16  = 2
627 widthInBytes W32  = 4
628 widthInBytes W64  = 8
629 widthInBytes W128 = 16
630 widthInBytes W80  = 10
631
632 widthFromBytes :: Int -> Width
633 widthFromBytes 1  = W8
634 widthFromBytes 2  = W16
635 widthFromBytes 4  = W32
636 widthFromBytes 8  = W64
637 widthFromBytes 16 = W128
638 widthFromBytes 10 = W80
639 widthFromBytes n  = pprPanic "no width for given number of bytes" (ppr n)
640
641 -- log_2 of the width in bytes, useful for generating shifts.
642 widthInLog :: Width -> Int
643 widthInLog W8   = 0
644 widthInLog W16  = 1
645 widthInLog W32  = 2
646 widthInLog W64  = 3
647 widthInLog W128 = 4
648 widthInLog W80  = panic "widthInLog: F80"
649
650 -- widening / narrowing
651
652 narrowU :: Width -> Integer -> Integer
653 narrowU W8  x = fromIntegral (fromIntegral x :: Word8)
654 narrowU W16 x = fromIntegral (fromIntegral x :: Word16)
655 narrowU W32 x = fromIntegral (fromIntegral x :: Word32)
656 narrowU W64 x = fromIntegral (fromIntegral x :: Word64)
657 narrowU _ _ = panic "narrowTo"
658
659 narrowS :: Width -> Integer -> Integer
660 narrowS W8  x = fromIntegral (fromIntegral x :: Int8)
661 narrowS W16 x = fromIntegral (fromIntegral x :: Int16)
662 narrowS W32 x = fromIntegral (fromIntegral x :: Int32)
663 narrowS W64 x = fromIntegral (fromIntegral x :: Int64)
664 narrowS _ _ = panic "narrowTo"
665
666 -----------------------------------------------------------------------------
667 --              MachOp
668 -----------------------------------------------------------------------------
669
670 {- 
671 Implementation notes:
672
673 It might suffice to keep just a width, without distinguishing between
674 floating and integer types.  However, keeping the distinction will
675 help the native code generator to assign registers more easily.
676 -}
677
678
679 {- |
680 Machine-level primops; ones which we can reasonably delegate to the
681 native code generators to handle.  Basically contains C's primops
682 and no others.
683
684 Nomenclature: all ops indicate width and signedness, where
685 appropriate.  Widths: 8\/16\/32\/64 means the given size, obviously.
686 Nat means the operation works on STG word sized objects.
687 Signedness: S means signed, U means unsigned.  For operations where
688 signedness is irrelevant or makes no difference (for example
689 integer add), the signedness component is omitted.
690
691 An exception: NatP is a ptr-typed native word.  From the point of
692 view of the native code generators this distinction is irrelevant,
693 but the C code generator sometimes needs this info to emit the
694 right casts.  
695 -}
696
697 data MachOp
698   -- Integer operations (insensitive to signed/unsigned)
699   = MO_Add Width
700   | MO_Sub Width
701   | MO_Eq  Width
702   | MO_Ne  Width
703   | MO_Mul Width                -- low word of multiply
704
705   -- Signed multiply/divide
706   | MO_S_MulMayOflo Width       -- nonzero if signed multiply overflows
707   | MO_S_Quot Width             -- signed / (same semantics as IntQuotOp)
708   | MO_S_Rem  Width             -- signed % (same semantics as IntRemOp)
709   | MO_S_Neg  Width             -- unary -
710
711   -- Unsigned multiply/divide
712   | MO_U_MulMayOflo Width       -- nonzero if unsigned multiply overflows
713   | MO_U_Quot Width             -- unsigned / (same semantics as WordQuotOp)
714   | MO_U_Rem  Width             -- unsigned % (same semantics as WordRemOp)
715
716   -- Signed comparisons
717   | MO_S_Ge Width
718   | MO_S_Le Width
719   | MO_S_Gt Width
720   | MO_S_Lt Width
721
722   -- Unsigned comparisons
723   | MO_U_Ge Width
724   | MO_U_Le Width
725   | MO_U_Gt Width
726   | MO_U_Lt Width
727
728   -- Floating point arithmetic
729   | MO_F_Add  Width
730   | MO_F_Sub  Width
731   | MO_F_Neg  Width             -- unary -
732   | MO_F_Mul  Width
733   | MO_F_Quot Width
734
735   -- Floating point comparison
736   | MO_F_Eq Width
737   | MO_F_Ne Width
738   | MO_F_Ge Width
739   | MO_F_Le Width
740   | MO_F_Gt Width
741   | MO_F_Lt Width
742
743   -- Bitwise operations.  Not all of these may be supported 
744   -- at all sizes, and only integral Widths are valid.
745   | MO_And   Width
746   | MO_Or    Width
747   | MO_Xor   Width
748   | MO_Not   Width
749   | MO_Shl   Width
750   | MO_U_Shr Width      -- unsigned shift right
751   | MO_S_Shr Width      -- signed shift right
752
753   -- Conversions.  Some of these will be NOPs.
754   -- Floating-point conversions use the signed variant.
755   | MO_SF_Conv Width Width      -- Signed int -> Float
756   | MO_FS_Conv Width Width      -- Float -> Signed int
757   | MO_SS_Conv Width Width      -- Signed int -> Signed int
758   | MO_UU_Conv Width Width      -- unsigned int -> unsigned int
759   | MO_FF_Conv Width Width      -- Float -> Float
760   deriving (Eq, Show)
761
762 pprMachOp :: MachOp -> SDoc
763 pprMachOp mo = text (show mo)
764
765
766
767 -- -----------------------------------------------------------------------------
768 -- Some common MachReps
769
770 -- A 'wordRep' is a machine word on the target architecture
771 -- Specifically, it is the size of an Int#, Word#, Addr# 
772 -- and the unit of allocation on the stack and the heap
773 -- Any pointer is also guaranteed to be a wordRep.
774
775 mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
776     , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
777     , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe 
778     , mo_wordULe, mo_wordUGt, mo_wordULt
779     , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
780     , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
781     , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
782     , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32
783     :: MachOp
784
785 mo_wordAdd      = MO_Add wordWidth
786 mo_wordSub      = MO_Sub wordWidth
787 mo_wordEq       = MO_Eq  wordWidth
788 mo_wordNe       = MO_Ne  wordWidth
789 mo_wordMul      = MO_Mul wordWidth
790 mo_wordSQuot    = MO_S_Quot wordWidth
791 mo_wordSRem     = MO_S_Rem wordWidth
792 mo_wordSNeg     = MO_S_Neg wordWidth
793 mo_wordUQuot    = MO_U_Quot wordWidth
794 mo_wordURem     = MO_U_Rem wordWidth
795
796 mo_wordSGe      = MO_S_Ge  wordWidth
797 mo_wordSLe      = MO_S_Le  wordWidth
798 mo_wordSGt      = MO_S_Gt  wordWidth
799 mo_wordSLt      = MO_S_Lt  wordWidth
800
801 mo_wordUGe      = MO_U_Ge  wordWidth
802 mo_wordULe      = MO_U_Le  wordWidth
803 mo_wordUGt      = MO_U_Gt  wordWidth
804 mo_wordULt      = MO_U_Lt  wordWidth
805
806 mo_wordAnd      = MO_And wordWidth
807 mo_wordOr       = MO_Or  wordWidth
808 mo_wordXor      = MO_Xor wordWidth
809 mo_wordNot      = MO_Not wordWidth
810 mo_wordShl      = MO_Shl wordWidth
811 mo_wordSShr     = MO_S_Shr wordWidth 
812 mo_wordUShr     = MO_U_Shr wordWidth 
813
814 mo_u_8To32      = MO_UU_Conv W8 W32
815 mo_s_8To32      = MO_SS_Conv W8 W32
816 mo_u_16To32     = MO_UU_Conv W16 W32
817 mo_s_16To32     = MO_SS_Conv W16 W32
818
819 mo_u_8ToWord    = MO_UU_Conv W8  wordWidth
820 mo_s_8ToWord    = MO_SS_Conv W8  wordWidth
821 mo_u_16ToWord   = MO_UU_Conv W16 wordWidth
822 mo_s_16ToWord   = MO_SS_Conv W16 wordWidth
823 mo_s_32ToWord   = MO_SS_Conv W32 wordWidth
824 mo_u_32ToWord   = MO_UU_Conv W32 wordWidth
825
826 mo_WordTo8      = MO_UU_Conv wordWidth W8
827 mo_WordTo16     = MO_UU_Conv wordWidth W16
828 mo_WordTo32     = MO_UU_Conv wordWidth W32
829
830 mo_32To8        = MO_UU_Conv W32 W8
831 mo_32To16       = MO_UU_Conv W32 W16
832
833
834 -- ----------------------------------------------------------------------------
835 -- isCommutableMachOp
836
837 {- |
838 Returns 'True' if the MachOp has commutable arguments.  This is used
839 in the platform-independent Cmm optimisations.
840
841 If in doubt, return 'False'.  This generates worse code on the
842 native routes, but is otherwise harmless.
843 -}
844 isCommutableMachOp :: MachOp -> Bool
845 isCommutableMachOp mop = 
846   case mop of
847         MO_Add _                -> True
848         MO_Eq _                 -> True
849         MO_Ne _                 -> True
850         MO_Mul _                -> True
851         MO_S_MulMayOflo _       -> True
852         MO_U_MulMayOflo _       -> True
853         MO_And _                -> True
854         MO_Or _                 -> True
855         MO_Xor _                -> True
856         _other                  -> False
857
858 -- ----------------------------------------------------------------------------
859 -- isAssociativeMachOp
860
861 {- |
862 Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
863 This is used in the platform-independent Cmm optimisations.
864
865 If in doubt, return 'False'.  This generates worse code on the
866 native routes, but is otherwise harmless.
867 -}
868 isAssociativeMachOp :: MachOp -> Bool
869 isAssociativeMachOp mop = 
870   case mop of
871         MO_Add {} -> True       -- NB: does not include
872         MO_Mul {} -> True --     floatint point!
873         MO_And {} -> True
874         MO_Or  {} -> True
875         MO_Xor {} -> True
876         _other    -> False
877
878 -- ----------------------------------------------------------------------------
879 -- isComparisonMachOp
880
881 {- | 
882 Returns 'True' if the MachOp is a comparison.
883
884 If in doubt, return False.  This generates worse code on the
885 native routes, but is otherwise harmless.
886 -}
887 isComparisonMachOp :: MachOp -> Bool
888 isComparisonMachOp mop = 
889   case mop of
890     MO_Eq   _  -> True
891     MO_Ne   _  -> True
892     MO_S_Ge _  -> True
893     MO_S_Le _  -> True
894     MO_S_Gt _  -> True
895     MO_S_Lt _  -> True
896     MO_U_Ge _  -> True
897     MO_U_Le _  -> True
898     MO_U_Gt _  -> True
899     MO_U_Lt _  -> True
900     MO_F_Eq  {} -> True
901     MO_F_Ne  {} -> True
902     MO_F_Ge  {} -> True
903     MO_F_Le  {} -> True
904     MO_F_Gt  {} -> True
905     MO_F_Lt  {} -> True
906     _other     -> False
907
908 -- -----------------------------------------------------------------------------
909 -- Inverting conditions
910
911 -- Sometimes it's useful to be able to invert the sense of a
912 -- condition.  Not all conditional tests are invertible: in
913 -- particular, floating point conditionals cannot be inverted, because
914 -- there exist floating-point values which return False for both senses
915 -- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).
916
917 maybeInvertComparison :: MachOp -> Maybe MachOp
918 maybeInvertComparison op
919   = case op of  -- None of these Just cases include floating point
920         MO_Eq r   -> Just (MO_Ne r)
921         MO_Ne r   -> Just (MO_Eq r)
922         MO_U_Lt r -> Just (MO_U_Ge r)
923         MO_U_Gt r -> Just (MO_U_Le r)
924         MO_U_Le r -> Just (MO_U_Gt r)
925         MO_U_Ge r -> Just (MO_U_Lt r)
926         MO_S_Lt r -> Just (MO_S_Ge r)
927         MO_S_Gt r -> Just (MO_S_Le r)
928         MO_S_Le r -> Just (MO_S_Gt r)
929         MO_S_Ge r -> Just (MO_S_Lt r)
930         MO_F_Eq r -> Just (MO_F_Ne r)
931         MO_F_Ne r -> Just (MO_F_Eq r)
932         MO_F_Ge r -> Just (MO_F_Le r)
933         MO_F_Le r -> Just (MO_F_Ge r)   
934         MO_F_Gt r -> Just (MO_F_Lt r)   
935         MO_F_Lt r -> Just (MO_F_Gt r)   
936         _other    -> Nothing
937
938 -- ----------------------------------------------------------------------------
939 -- machOpResultType
940
941 {- |
942 Returns the MachRep of the result of a MachOp.
943 -}
944 machOpResultType :: MachOp -> [CmmType] -> CmmType
945 machOpResultType mop tys =
946   case mop of
947     MO_Add {}           -> ty1  -- Preserve GC-ptr-hood
948     MO_Sub {}           -> ty1  -- of first arg
949     MO_Mul    r         -> cmmBits r
950     MO_S_MulMayOflo r   -> cmmBits r
951     MO_S_Quot r         -> cmmBits r
952     MO_S_Rem  r         -> cmmBits r
953     MO_S_Neg  r         -> cmmBits r
954     MO_U_MulMayOflo r   -> cmmBits r
955     MO_U_Quot r         -> cmmBits r
956     MO_U_Rem  r         -> cmmBits r
957
958     MO_Eq {}            -> comparisonResultRep
959     MO_Ne {}            -> comparisonResultRep
960     MO_S_Ge {}          -> comparisonResultRep
961     MO_S_Le {}          -> comparisonResultRep
962     MO_S_Gt {}          -> comparisonResultRep
963     MO_S_Lt {}          -> comparisonResultRep
964
965     MO_U_Ge {}          -> comparisonResultRep
966     MO_U_Le {}          -> comparisonResultRep
967     MO_U_Gt {}          -> comparisonResultRep
968     MO_U_Lt {}          -> comparisonResultRep
969
970     MO_F_Add r          -> cmmFloat r
971     MO_F_Sub r          -> cmmFloat r
972     MO_F_Mul r          -> cmmFloat r
973     MO_F_Quot r         -> cmmFloat r
974     MO_F_Neg r          -> cmmFloat r
975     MO_F_Eq  {}         -> comparisonResultRep
976     MO_F_Ne  {}         -> comparisonResultRep
977     MO_F_Ge  {}         -> comparisonResultRep
978     MO_F_Le  {}         -> comparisonResultRep
979     MO_F_Gt  {}         -> comparisonResultRep
980     MO_F_Lt  {}         -> comparisonResultRep
981
982     MO_And {}           -> ty1  -- Used for pointer masking
983     MO_Or {}            -> ty1
984     MO_Xor {}           -> ty1
985     MO_Not   r          -> cmmBits r
986     MO_Shl   r          -> cmmBits r
987     MO_U_Shr r          -> cmmBits r
988     MO_S_Shr r          -> cmmBits r
989
990     MO_SS_Conv _ to     -> cmmBits to
991     MO_UU_Conv _ to     -> cmmBits to
992     MO_FS_Conv _ to     -> cmmBits to
993     MO_SF_Conv _ to     -> cmmFloat to
994     MO_FF_Conv _ to     -> cmmFloat to
995   where
996     (ty1:_) = tys
997
998 comparisonResultRep :: CmmType
999 comparisonResultRep = bWord  -- is it?
1000
1001
1002 -- -----------------------------------------------------------------------------
1003 -- machOpArgReps
1004
1005 -- | This function is used for debugging only: we can check whether an
1006 -- application of a MachOp is "type-correct" by checking that the MachReps of
1007 -- its arguments are the same as the MachOp expects.  This is used when 
1008 -- linting a CmmExpr.
1009
1010 machOpArgReps :: MachOp -> [Width]
1011 machOpArgReps op = 
1012   case op of
1013     MO_Add    r         -> [r,r]
1014     MO_Sub    r         -> [r,r]
1015     MO_Eq     r         -> [r,r]
1016     MO_Ne     r         -> [r,r]
1017     MO_Mul    r         -> [r,r]
1018     MO_S_MulMayOflo r   -> [r,r]
1019     MO_S_Quot r         -> [r,r]
1020     MO_S_Rem  r         -> [r,r]
1021     MO_S_Neg  r         -> [r]
1022     MO_U_MulMayOflo r   -> [r,r]
1023     MO_U_Quot r         -> [r,r]
1024     MO_U_Rem  r         -> [r,r]
1025
1026     MO_S_Ge r           -> [r,r]
1027     MO_S_Le r           -> [r,r]
1028     MO_S_Gt r           -> [r,r]
1029     MO_S_Lt r           -> [r,r]
1030
1031     MO_U_Ge r           -> [r,r]
1032     MO_U_Le r           -> [r,r]
1033     MO_U_Gt r           -> [r,r]
1034     MO_U_Lt r           -> [r,r]
1035
1036     MO_F_Add r          -> [r,r]
1037     MO_F_Sub r          -> [r,r]
1038     MO_F_Mul r          -> [r,r]
1039     MO_F_Quot r         -> [r,r]
1040     MO_F_Neg r          -> [r]
1041     MO_F_Eq  r          -> [r,r]
1042     MO_F_Ne  r          -> [r,r]
1043     MO_F_Ge  r          -> [r,r]
1044     MO_F_Le  r          -> [r,r]
1045     MO_F_Gt  r          -> [r,r]
1046     MO_F_Lt  r          -> [r,r]
1047
1048     MO_And   r          -> [r,r]
1049     MO_Or    r          -> [r,r]
1050     MO_Xor   r          -> [r,r]
1051     MO_Not   r          -> [r]
1052     MO_Shl   r          -> [r,wordWidth]
1053     MO_U_Shr r          -> [r,wordWidth]
1054     MO_S_Shr r          -> [r,wordWidth]
1055
1056     MO_SS_Conv from _   -> [from]
1057     MO_UU_Conv from _   -> [from]
1058     MO_SF_Conv from _   -> [from]
1059     MO_FS_Conv from _   -> [from]
1060     MO_FF_Conv from _   -> [from]
1061
1062
1063 -------------------------------------------------------------------------
1064 {-      Note [Signed vs unsigned]
1065         ~~~~~~~~~~~~~~~~~~~~~~~~~
1066 Should a CmmType include a signed vs. unsigned distinction?
1067
1068 This is very much like a "hint" in C-- terminology: it isn't necessary
1069 in order to generate correct code, but it might be useful in that the
1070 compiler can generate better code if it has access to higher-level
1071 hints about data.  This is important at call boundaries, because the
1072 definition of a function is not visible at all of its call sites, so
1073 the compiler cannot infer the hints.
1074
1075 Here in Cmm, we're taking a slightly different approach.  We include
1076 the int vs. float hint in the MachRep, because (a) the majority of
1077 platforms have a strong distinction between float and int registers,
1078 and (b) we don't want to do any heavyweight hint-inference in the
1079 native code backend in order to get good code.  We're treating the
1080 hint more like a type: our Cmm is always completely consistent with
1081 respect to hints.  All coercions between float and int are explicit.
1082
1083 What about the signed vs. unsigned hint?  This information might be
1084 useful if we want to keep sub-word-sized values in word-size
1085 registers, which we must do if we only have word-sized registers.
1086
1087 On such a system, there are two straightforward conventions for
1088 representing sub-word-sized values:
1089
1090 (a) Leave the upper bits undefined.  Comparison operations must
1091     sign- or zero-extend both operands before comparing them,
1092     depending on whether the comparison is signed or unsigned.
1093
1094 (b) Always keep the values sign- or zero-extended as appropriate.
1095     Arithmetic operations must narrow the result to the appropriate
1096     size.
1097
1098 A clever compiler might not use either (a) or (b) exclusively, instead
1099 it would attempt to minimize the coercions by analysis: the same kind
1100 of analysis that propagates hints around.  In Cmm we don't want to
1101 have to do this, so we plump for having richer types and keeping the
1102 type information consistent.
1103
1104 If signed/unsigned hints are missing from MachRep, then the only
1105 choice we have is (a), because we don't know whether the result of an
1106 operation should be sign- or zero-extended.
1107
1108 Many architectures have extending load operations, which work well
1109 with (b).  To make use of them with (a), you need to know whether the
1110 value is going to be sign- or zero-extended by an enclosing comparison
1111 (for example), which involves knowing above the context.  This is
1112 doable but more complex.
1113
1114 Further complicating the issue is foreign calls: a foreign calling
1115 convention can specify that signed 8-bit quantities are passed as
1116 sign-extended 32 bit quantities, for example (this is the case on the
1117 PowerPC).  So we *do* need sign information on foreign call arguments.
1118
1119 Pros for adding signed vs. unsigned to MachRep:
1120
1121   - It would let us use convention (b) above, and get easier
1122     code generation for extending loads.
1123
1124   - Less information required on foreign calls.
1125   
1126   - MachOp type would be simpler
1127
1128 Cons:
1129
1130   - More complexity
1131
1132   - What is the MachRep for a VanillaReg?  Currently it is
1133     always wordRep, but now we have to decide whether it is
1134     signed or unsigned.  The same VanillaReg can thus have
1135     different MachReps in different parts of the program.
1136
1137   - Extra coercions cluttering up expressions.
1138
1139 Currently for GHC, the foreign call point is moot, because we do our
1140 own promotion of sub-word-sized values to word-sized values.  The Int8
1141 type is represnted by an Int# which is kept sign-extended at all times
1142 (this is slightly naughty, because we're making assumptions about the
1143 C calling convention rather early on in the compiler).  However, given
1144 this, the cons outweigh the pros.
1145
1146 -}
1147