Be more selective in which conditionals we invert
[ghc.git] / compiler / cmm / CmmType.hs
1 module CmmType
2 ( CmmType -- Abstract
3 , b8, b16, b32, b64, b128, b256, b512, f32, f64, bWord, bHalfWord, gcWord
4 , cInt
5 , cmmBits, cmmFloat
6 , typeWidth, cmmEqType, cmmEqType_ignoring_ptrhood
7 , isFloatType, isGcPtrType, isWord32, isWord64, isFloat64, isFloat32
8
9 , Width(..)
10 , widthInBits, widthInBytes, widthInLog, widthFromBytes
11 , wordWidth, halfWordWidth, cIntWidth
12 , halfWordMask
13 , narrowU, narrowS
14 , rEP_CostCentreStack_mem_alloc
15 , rEP_CostCentreStack_scc_count
16 , rEP_StgEntCounter_allocs
17 , rEP_StgEntCounter_allocd
18
19 , ForeignHint(..)
20
21 , Length
22 , vec, vec2, vec4, vec8, vec16
23 , vec2f64, vec2b64, vec4f32, vec4b32, vec8b16, vec16b8
24 , cmmVec
25 , vecLength, vecElemType
26 , isVecType
27 )
28 where
29
30
31 import GhcPrelude
32
33 import DynFlags
34 import FastString
35 import Outputable
36
37 import Data.Word
38 import Data.Int
39
40 -----------------------------------------------------------------------------
41 -- CmmType
42 -----------------------------------------------------------------------------
43
44 -- NOTE: CmmType is an abstract type, not exported from this
45 -- module so you can easily change its representation
46 --
47 -- However Width is exported in a concrete way,
48 -- and is used extensively in pattern-matching
49
50 data CmmType -- The important one!
51 = CmmType CmmCat Width
52
53 data CmmCat -- "Category" (not exported)
54 = GcPtrCat -- GC pointer
55 | BitsCat -- Non-pointer
56 | FloatCat -- Float
57 | VecCat Length CmmCat -- Vector
58 deriving( Eq )
59 -- See Note [Signed vs unsigned] at the end
60
61 instance Outputable CmmType where
62 ppr (CmmType cat wid) = ppr cat <> ppr (widthInBits wid)
63
64 instance Outputable CmmCat where
65 ppr FloatCat = text "F"
66 ppr GcPtrCat = text "P"
67 ppr BitsCat = text "I"
68 ppr (VecCat n cat) = ppr cat <> text "x" <> ppr n <> text "V"
69
70 -- Why is CmmType stratified? For native code generation,
71 -- most of the time you just want to know what sort of register
72 -- to put the thing in, and for this you need to know how
73 -- many bits thing has and whether it goes in a floating-point
74 -- register. By contrast, the distinction between GcPtr and
75 -- GcNonPtr is of interest to only a few parts of the code generator.
76
77 -------- Equality on CmmType --------------
78 -- CmmType is *not* an instance of Eq; sometimes we care about the
79 -- Gc/NonGc distinction, and sometimes we don't
80 -- So we use an explicit function to force you to think about it
81 cmmEqType :: CmmType -> CmmType -> Bool -- Exact equality
82 cmmEqType (CmmType c1 w1) (CmmType c2 w2) = c1==c2 && w1==w2
83
84 cmmEqType_ignoring_ptrhood :: CmmType -> CmmType -> Bool
85 -- This equality is temporary; used in CmmLint
86 -- but the RTS files are not yet well-typed wrt pointers
87 cmmEqType_ignoring_ptrhood (CmmType c1 w1) (CmmType c2 w2)
88 = c1 `weak_eq` c2 && w1==w2
89 where
90 weak_eq :: CmmCat -> CmmCat -> Bool
91 FloatCat `weak_eq` FloatCat = True
92 FloatCat `weak_eq` _other = False
93 _other `weak_eq` FloatCat = False
94 (VecCat l1 cat1) `weak_eq` (VecCat l2 cat2) = l1 == l2
95 && cat1 `weak_eq` cat2
96 (VecCat {}) `weak_eq` _other = False
97 _other `weak_eq` (VecCat {}) = False
98 _word1 `weak_eq` _word2 = True -- Ignores GcPtr
99
100 --- Simple operations on CmmType -----
101 typeWidth :: CmmType -> Width
102 typeWidth (CmmType _ w) = w
103
104 cmmBits, cmmFloat :: Width -> CmmType
105 cmmBits = CmmType BitsCat
106 cmmFloat = CmmType FloatCat
107
108 -------- Common CmmTypes ------------
109 -- Floats and words of specific widths
110 b8, b16, b32, b64, b128, b256, b512, f32, f64 :: CmmType
111 b8 = cmmBits W8
112 b16 = cmmBits W16
113 b32 = cmmBits W32
114 b64 = cmmBits W64
115 b128 = cmmBits W128
116 b256 = cmmBits W256
117 b512 = cmmBits W512
118 f32 = cmmFloat W32
119 f64 = cmmFloat W64
120
121 -- CmmTypes of native word widths
122 bWord :: DynFlags -> CmmType
123 bWord dflags = cmmBits (wordWidth dflags)
124
125 bHalfWord :: DynFlags -> CmmType
126 bHalfWord dflags = cmmBits (halfWordWidth dflags)
127
128 gcWord :: DynFlags -> CmmType
129 gcWord dflags = CmmType GcPtrCat (wordWidth dflags)
130
131 cInt :: DynFlags -> CmmType
132 cInt dflags = cmmBits (cIntWidth dflags)
133
134 ------------ Predicates ----------------
135 isFloatType, isGcPtrType :: CmmType -> Bool
136 isFloatType (CmmType FloatCat _) = True
137 isFloatType _other = False
138
139 isGcPtrType (CmmType GcPtrCat _) = True
140 isGcPtrType _other = False
141
142 isWord32, isWord64, isFloat32, isFloat64 :: CmmType -> Bool
143 -- isWord64 is true of 64-bit non-floats (both gc-ptrs and otherwise)
144 -- isFloat32 and 64 are obvious
145
146 isWord64 (CmmType BitsCat W64) = True
147 isWord64 (CmmType GcPtrCat W64) = True
148 isWord64 _other = False
149
150 isWord32 (CmmType BitsCat W32) = True
151 isWord32 (CmmType GcPtrCat W32) = True
152 isWord32 _other = False
153
154 isFloat32 (CmmType FloatCat W32) = True
155 isFloat32 _other = False
156
157 isFloat64 (CmmType FloatCat W64) = True
158 isFloat64 _other = False
159
160 -----------------------------------------------------------------------------
161 -- Width
162 -----------------------------------------------------------------------------
163
164 data Width = W8 | W16 | W32 | W64
165 | W80 -- Extended double-precision float,
166 -- used in x86 native codegen only.
167 -- (we use Ord, so it'd better be in this order)
168 | W128
169 | W256
170 | W512
171 deriving (Eq, Ord, Show)
172
173 instance Outputable Width where
174 ppr rep = ptext (mrStr rep)
175
176 mrStr :: Width -> LitString
177 mrStr W8 = sLit("W8")
178 mrStr W16 = sLit("W16")
179 mrStr W32 = sLit("W32")
180 mrStr W64 = sLit("W64")
181 mrStr W128 = sLit("W128")
182 mrStr W256 = sLit("W256")
183 mrStr W512 = sLit("W512")
184 mrStr W80 = sLit("W80")
185
186
187 -------- Common Widths ------------
188 wordWidth :: DynFlags -> Width
189 wordWidth dflags
190 | wORD_SIZE dflags == 4 = W32
191 | wORD_SIZE dflags == 8 = W64
192 | otherwise = panic "MachOp.wordRep: Unknown word size"
193
194 halfWordWidth :: DynFlags -> Width
195 halfWordWidth dflags
196 | wORD_SIZE dflags == 4 = W16
197 | wORD_SIZE dflags == 8 = W32
198 | otherwise = panic "MachOp.halfWordRep: Unknown word size"
199
200 halfWordMask :: DynFlags -> Integer
201 halfWordMask dflags
202 | wORD_SIZE dflags == 4 = 0xFFFF
203 | wORD_SIZE dflags == 8 = 0xFFFFFFFF
204 | otherwise = panic "MachOp.halfWordMask: Unknown word size"
205
206 -- cIntRep is the Width for a C-language 'int'
207 cIntWidth :: DynFlags -> Width
208 cIntWidth dflags = case cINT_SIZE dflags of
209 4 -> W32
210 8 -> W64
211 s -> panic ("cIntWidth: Unknown cINT_SIZE: " ++ show s)
212
213 widthInBits :: Width -> Int
214 widthInBits W8 = 8
215 widthInBits W16 = 16
216 widthInBits W32 = 32
217 widthInBits W64 = 64
218 widthInBits W128 = 128
219 widthInBits W256 = 256
220 widthInBits W512 = 512
221 widthInBits W80 = 80
222
223 widthInBytes :: Width -> Int
224 widthInBytes W8 = 1
225 widthInBytes W16 = 2
226 widthInBytes W32 = 4
227 widthInBytes W64 = 8
228 widthInBytes W128 = 16
229 widthInBytes W256 = 32
230 widthInBytes W512 = 64
231 widthInBytes W80 = 10
232
233 widthFromBytes :: Int -> Width
234 widthFromBytes 1 = W8
235 widthFromBytes 2 = W16
236 widthFromBytes 4 = W32
237 widthFromBytes 8 = W64
238 widthFromBytes 16 = W128
239 widthFromBytes 32 = W256
240 widthFromBytes 64 = W512
241 widthFromBytes 10 = W80
242 widthFromBytes n = pprPanic "no width for given number of bytes" (ppr n)
243
244 -- log_2 of the width in bytes, useful for generating shifts.
245 widthInLog :: Width -> Int
246 widthInLog W8 = 0
247 widthInLog W16 = 1
248 widthInLog W32 = 2
249 widthInLog W64 = 3
250 widthInLog W128 = 4
251 widthInLog W256 = 5
252 widthInLog W512 = 6
253 widthInLog W80 = panic "widthInLog: F80"
254
255 -- widening / narrowing
256
257 narrowU :: Width -> Integer -> Integer
258 narrowU W8 x = fromIntegral (fromIntegral x :: Word8)
259 narrowU W16 x = fromIntegral (fromIntegral x :: Word16)
260 narrowU W32 x = fromIntegral (fromIntegral x :: Word32)
261 narrowU W64 x = fromIntegral (fromIntegral x :: Word64)
262 narrowU _ _ = panic "narrowTo"
263
264 narrowS :: Width -> Integer -> Integer
265 narrowS W8 x = fromIntegral (fromIntegral x :: Int8)
266 narrowS W16 x = fromIntegral (fromIntegral x :: Int16)
267 narrowS W32 x = fromIntegral (fromIntegral x :: Int32)
268 narrowS W64 x = fromIntegral (fromIntegral x :: Int64)
269 narrowS _ _ = panic "narrowTo"
270
271 -----------------------------------------------------------------------------
272 -- SIMD
273 -----------------------------------------------------------------------------
274
275 type Length = Int
276
277 vec :: Length -> CmmType -> CmmType
278 vec l (CmmType cat w) = CmmType (VecCat l cat) vecw
279 where
280 vecw :: Width
281 vecw = widthFromBytes (l*widthInBytes w)
282
283 vec2, vec4, vec8, vec16 :: CmmType -> CmmType
284 vec2 = vec 2
285 vec4 = vec 4
286 vec8 = vec 8
287 vec16 = vec 16
288
289 vec2f64, vec2b64, vec4f32, vec4b32, vec8b16, vec16b8 :: CmmType
290 vec2f64 = vec 2 f64
291 vec2b64 = vec 2 b64
292 vec4f32 = vec 4 f32
293 vec4b32 = vec 4 b32
294 vec8b16 = vec 8 b16
295 vec16b8 = vec 16 b8
296
297 cmmVec :: Int -> CmmType -> CmmType
298 cmmVec n (CmmType cat w) =
299 CmmType (VecCat n cat) (widthFromBytes (n*widthInBytes w))
300
301 vecLength :: CmmType -> Length
302 vecLength (CmmType (VecCat l _) _) = l
303 vecLength _ = panic "vecLength: not a vector"
304
305 vecElemType :: CmmType -> CmmType
306 vecElemType (CmmType (VecCat l cat) w) = CmmType cat scalw
307 where
308 scalw :: Width
309 scalw = widthFromBytes (widthInBytes w `div` l)
310 vecElemType _ = panic "vecElemType: not a vector"
311
312 isVecType :: CmmType -> Bool
313 isVecType (CmmType (VecCat {}) _) = True
314 isVecType _ = False
315
316 -------------------------------------------------------------------------
317 -- Hints
318
319 -- Hints are extra type information we attach to the arguments and
320 -- results of a foreign call, where more type information is sometimes
321 -- needed by the ABI to make the correct kind of call.
322
323 data ForeignHint
324 = NoHint | AddrHint | SignedHint
325 deriving( Eq )
326 -- Used to give extra per-argument or per-result
327 -- information needed by foreign calling conventions
328
329 -------------------------------------------------------------------------
330
331 -- These don't really belong here, but I don't know where is best to
332 -- put them.
333
334 rEP_CostCentreStack_mem_alloc :: DynFlags -> CmmType
335 rEP_CostCentreStack_mem_alloc dflags
336 = cmmBits (widthFromBytes (pc_REP_CostCentreStack_mem_alloc pc))
337 where pc = sPlatformConstants (settings dflags)
338
339 rEP_CostCentreStack_scc_count :: DynFlags -> CmmType
340 rEP_CostCentreStack_scc_count dflags
341 = cmmBits (widthFromBytes (pc_REP_CostCentreStack_scc_count pc))
342 where pc = sPlatformConstants (settings dflags)
343
344 rEP_StgEntCounter_allocs :: DynFlags -> CmmType
345 rEP_StgEntCounter_allocs dflags
346 = cmmBits (widthFromBytes (pc_REP_StgEntCounter_allocs pc))
347 where pc = sPlatformConstants (settings dflags)
348
349 rEP_StgEntCounter_allocd :: DynFlags -> CmmType
350 rEP_StgEntCounter_allocd dflags
351 = cmmBits (widthFromBytes (pc_REP_StgEntCounter_allocd pc))
352 where pc = sPlatformConstants (settings dflags)
353
354 -------------------------------------------------------------------------
355 {- Note [Signed vs unsigned]
356 ~~~~~~~~~~~~~~~~~~~~~~~~~
357 Should a CmmType include a signed vs. unsigned distinction?
358
359 This is very much like a "hint" in C-- terminology: it isn't necessary
360 in order to generate correct code, but it might be useful in that the
361 compiler can generate better code if it has access to higher-level
362 hints about data. This is important at call boundaries, because the
363 definition of a function is not visible at all of its call sites, so
364 the compiler cannot infer the hints.
365
366 Here in Cmm, we're taking a slightly different approach. We include
367 the int vs. float hint in the CmmType, because (a) the majority of
368 platforms have a strong distinction between float and int registers,
369 and (b) we don't want to do any heavyweight hint-inference in the
370 native code backend in order to get good code. We're treating the
371 hint more like a type: our Cmm is always completely consistent with
372 respect to hints. All coercions between float and int are explicit.
373
374 What about the signed vs. unsigned hint? This information might be
375 useful if we want to keep sub-word-sized values in word-size
376 registers, which we must do if we only have word-sized registers.
377
378 On such a system, there are two straightforward conventions for
379 representing sub-word-sized values:
380
381 (a) Leave the upper bits undefined. Comparison operations must
382 sign- or zero-extend both operands before comparing them,
383 depending on whether the comparison is signed or unsigned.
384
385 (b) Always keep the values sign- or zero-extended as appropriate.
386 Arithmetic operations must narrow the result to the appropriate
387 size.
388
389 A clever compiler might not use either (a) or (b) exclusively, instead
390 it would attempt to minimize the coercions by analysis: the same kind
391 of analysis that propagates hints around. In Cmm we don't want to
392 have to do this, so we plump for having richer types and keeping the
393 type information consistent.
394
395 If signed/unsigned hints are missing from CmmType, then the only
396 choice we have is (a), because we don't know whether the result of an
397 operation should be sign- or zero-extended.
398
399 Many architectures have extending load operations, which work well
400 with (b). To make use of them with (a), you need to know whether the
401 value is going to be sign- or zero-extended by an enclosing comparison
402 (for example), which involves knowing above the context. This is
403 doable but more complex.
404
405 Further complicating the issue is foreign calls: a foreign calling
406 convention can specify that signed 8-bit quantities are passed as
407 sign-extended 32 bit quantities, for example (this is the case on the
408 PowerPC). So we *do* need sign information on foreign call arguments.
409
410 Pros for adding signed vs. unsigned to CmmType:
411
412 - It would let us use convention (b) above, and get easier
413 code generation for extending loads.
414
415 - Less information required on foreign calls.
416
417 - MachOp type would be simpler
418
419 Cons:
420
421 - More complexity
422
423 - What is the CmmType for a VanillaReg? Currently it is
424 always wordRep, but now we have to decide whether it is
425 signed or unsigned. The same VanillaReg can thus have
426 different CmmType in different parts of the program.
427
428 - Extra coercions cluttering up expressions.
429
430 Currently for GHC, the foreign call point is moot, because we do our
431 own promotion of sub-word-sized values to word-sized values. The Int8
432 type is represented by an Int# which is kept sign-extended at all times
433 (this is slightly naughty, because we're making assumptions about the
434 C calling convention rather early on in the compiler). However, given
435 this, the cons outweigh the pros.
436
437 -}
438