Add Cmm support for 256-bit-wide values.
[ghc.git] / compiler / cmm / CmmType.hs
1
2 module CmmType
3 ( CmmType -- Abstract
4 , b8, b16, b32, b64, b128, b256, 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 , halfWordMask
14 , narrowU, narrowS
15 , rEP_CostCentreStack_mem_alloc
16 , rEP_CostCentreStack_scc_count
17 , rEP_StgEntCounter_allocs
18 , rEP_StgEntCounter_allocd
19
20 , ForeignHint(..)
21
22 , Length
23 , vec, vec2, vec4, vec8, vec16
24 , vec2f64, vec2b64, vec4f32, vec4b32, vec8b16, vec16b8
25 , cmmVec
26 , vecLength, vecElemType
27 , isVecType
28 )
29 where
30
31 #include "HsVersions.h"
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 = ptext $ sLit("F")
66 ppr GcPtrCat = ptext $ sLit("P")
67 ppr BitsCat = ptext $ sLit("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, 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 f32 = cmmFloat W32
118 f64 = cmmFloat W64
119
120 -- CmmTypes of native word widths
121 bWord :: DynFlags -> CmmType
122 bWord dflags = cmmBits (wordWidth dflags)
123
124 bHalfWord :: DynFlags -> CmmType
125 bHalfWord dflags = cmmBits (halfWordWidth dflags)
126
127 gcWord :: DynFlags -> CmmType
128 gcWord dflags = CmmType GcPtrCat (wordWidth dflags)
129
130 cInt, cLong :: DynFlags -> CmmType
131 cInt dflags = cmmBits (cIntWidth dflags)
132 cLong dflags = cmmBits (cLongWidth dflags)
133
134
135 ------------ Predicates ----------------
136 isFloatType, isGcPtrType :: CmmType -> Bool
137 isFloatType (CmmType FloatCat _) = True
138 isFloatType _other = False
139
140 isGcPtrType (CmmType GcPtrCat _) = True
141 isGcPtrType _other = False
142
143 isWord32, isWord64, isFloat32, isFloat64 :: CmmType -> Bool
144 -- isWord64 is true of 64-bit non-floats (both gc-ptrs and otherwise)
145 -- isFloat32 and 64 are obvious
146
147 isWord64 (CmmType BitsCat W64) = True
148 isWord64 (CmmType GcPtrCat W64) = True
149 isWord64 _other = False
150
151 isWord32 (CmmType BitsCat W32) = True
152 isWord32 (CmmType GcPtrCat W32) = True
153 isWord32 _other = False
154
155 isFloat32 (CmmType FloatCat W32) = True
156 isFloat32 _other = False
157
158 isFloat64 (CmmType FloatCat W64) = True
159 isFloat64 _other = False
160
161 -----------------------------------------------------------------------------
162 -- Width
163 -----------------------------------------------------------------------------
164
165 data Width = W8 | W16 | W32 | W64
166 | W80 -- Extended double-precision float,
167 -- used in x86 native codegen only.
168 -- (we use Ord, so it'd better be in this order)
169 | W128
170 | W256
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 W80 = sLit("W80")
184
185
186 -------- Common Widths ------------
187 wordWidth :: DynFlags -> Width
188 wordWidth dflags
189 | wORD_SIZE dflags == 4 = W32
190 | wORD_SIZE dflags == 8 = W64
191 | otherwise = panic "MachOp.wordRep: Unknown word size"
192
193 halfWordWidth :: DynFlags -> Width
194 halfWordWidth dflags
195 | wORD_SIZE dflags == 4 = W16
196 | wORD_SIZE dflags == 8 = W32
197 | otherwise = panic "MachOp.halfWordRep: Unknown word size"
198
199 halfWordMask :: DynFlags -> Integer
200 halfWordMask dflags
201 | wORD_SIZE dflags == 4 = 0xFFFF
202 | wORD_SIZE dflags == 8 = 0xFFFFFFFF
203 | otherwise = panic "MachOp.halfWordMask: Unknown word size"
204
205 -- cIntRep is the Width for a C-language 'int'
206 cIntWidth, cLongWidth :: DynFlags -> Width
207 cIntWidth dflags = case cINT_SIZE dflags of
208 4 -> W32
209 8 -> W64
210 s -> panic ("cIntWidth: Unknown cINT_SIZE: " ++ show s)
211 cLongWidth dflags = case cLONG_SIZE dflags of
212 4 -> W32
213 8 -> W64
214 s -> panic ("cIntWidth: Unknown cLONG_SIZE: " ++ show s)
215
216 widthInBits :: Width -> Int
217 widthInBits W8 = 8
218 widthInBits W16 = 16
219 widthInBits W32 = 32
220 widthInBits W64 = 64
221 widthInBits W128 = 128
222 widthInBits W256 = 256
223 widthInBits W80 = 80
224
225 widthInBytes :: Width -> Int
226 widthInBytes W8 = 1
227 widthInBytes W16 = 2
228 widthInBytes W32 = 4
229 widthInBytes W64 = 8
230 widthInBytes W128 = 16
231 widthInBytes W256 = 32
232 widthInBytes W80 = 10
233
234 widthFromBytes :: Int -> Width
235 widthFromBytes 1 = W8
236 widthFromBytes 2 = W16
237 widthFromBytes 4 = W32
238 widthFromBytes 8 = W64
239 widthFromBytes 16 = W128
240 widthFromBytes 32 = W256
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 W80 = panic "widthInLog: F80"
253
254 -- widening / narrowing
255
256 narrowU :: Width -> Integer -> Integer
257 narrowU W8 x = fromIntegral (fromIntegral x :: Word8)
258 narrowU W16 x = fromIntegral (fromIntegral x :: Word16)
259 narrowU W32 x = fromIntegral (fromIntegral x :: Word32)
260 narrowU W64 x = fromIntegral (fromIntegral x :: Word64)
261 narrowU _ _ = panic "narrowTo"
262
263 narrowS :: Width -> Integer -> Integer
264 narrowS W8 x = fromIntegral (fromIntegral x :: Int8)
265 narrowS W16 x = fromIntegral (fromIntegral x :: Int16)
266 narrowS W32 x = fromIntegral (fromIntegral x :: Int32)
267 narrowS W64 x = fromIntegral (fromIntegral x :: Int64)
268 narrowS _ _ = panic "narrowTo"
269
270 -----------------------------------------------------------------------------
271 -- SIMD
272 -----------------------------------------------------------------------------
273
274 type Length = Int
275
276 vec :: Length -> CmmType -> CmmType
277 vec l (CmmType cat w) = CmmType (VecCat l cat) vecw
278 where
279 vecw :: Width
280 vecw = widthFromBytes (l*widthInBytes w)
281
282 vec2, vec4, vec8, vec16 :: CmmType -> CmmType
283 vec2 = vec 2
284 vec4 = vec 4
285 vec8 = vec 8
286 vec16 = vec 16
287
288 vec2f64, vec2b64, vec4f32, vec4b32, vec8b16, vec16b8 :: CmmType
289 vec2f64 = vec 2 f64
290 vec2b64 = vec 2 b64
291 vec4f32 = vec 4 f32
292 vec4b32 = vec 4 b32
293 vec8b16 = vec 8 b16
294 vec16b8 = vec 16 b8
295
296 cmmVec :: Int -> CmmType -> CmmType
297 cmmVec n (CmmType cat w) =
298 CmmType (VecCat n cat) (widthFromBytes (n*widthInBytes w))
299
300 vecLength :: CmmType -> Length
301 vecLength (CmmType (VecCat l _) _) = l
302 vecLength _ = panic "vecLength: not a vector"
303
304 vecElemType :: CmmType -> CmmType
305 vecElemType (CmmType (VecCat l cat) w) = CmmType cat scalw
306 where
307 scalw :: Width
308 scalw = widthFromBytes (widthInBytes w `div` l)
309 vecElemType _ = panic "vecElemType: not a vector"
310
311 isVecType :: CmmType -> Bool
312 isVecType (CmmType (VecCat {}) _) = True
313 isVecType _ = False
314
315 -------------------------------------------------------------------------
316 -- Hints
317
318 -- Hints are extra type information we attach to the arguments and
319 -- results of a foreign call, where more type information is sometimes
320 -- needed by the ABI to make the correct kind of call.
321
322 data ForeignHint
323 = NoHint | AddrHint | SignedHint
324 deriving( Eq )
325 -- Used to give extra per-argument or per-result
326 -- information needed by foreign calling conventions
327
328 -------------------------------------------------------------------------
329
330 -- These don't really belong here, but I don't know where is best to
331 -- put them.
332
333 rEP_CostCentreStack_mem_alloc :: DynFlags -> CmmType
334 rEP_CostCentreStack_mem_alloc dflags
335 = cmmBits (widthFromBytes (pc_REP_CostCentreStack_mem_alloc pc))
336 where pc = sPlatformConstants (settings dflags)
337
338 rEP_CostCentreStack_scc_count :: DynFlags -> CmmType
339 rEP_CostCentreStack_scc_count dflags
340 = cmmBits (widthFromBytes (pc_REP_CostCentreStack_scc_count pc))
341 where pc = sPlatformConstants (settings dflags)
342
343 rEP_StgEntCounter_allocs :: DynFlags -> CmmType
344 rEP_StgEntCounter_allocs dflags
345 = cmmBits (widthFromBytes (pc_REP_StgEntCounter_allocs pc))
346 where pc = sPlatformConstants (settings dflags)
347
348 rEP_StgEntCounter_allocd :: DynFlags -> CmmType
349 rEP_StgEntCounter_allocd dflags
350 = cmmBits (widthFromBytes (pc_REP_StgEntCounter_allocd pc))
351 where pc = sPlatformConstants (settings dflags)
352
353 -------------------------------------------------------------------------
354 {- Note [Signed vs unsigned]
355 ~~~~~~~~~~~~~~~~~~~~~~~~~
356 Should a CmmType include a signed vs. unsigned distinction?
357
358 This is very much like a "hint" in C-- terminology: it isn't necessary
359 in order to generate correct code, but it might be useful in that the
360 compiler can generate better code if it has access to higher-level
361 hints about data. This is important at call boundaries, because the
362 definition of a function is not visible at all of its call sites, so
363 the compiler cannot infer the hints.
364
365 Here in Cmm, we're taking a slightly different approach. We include
366 the int vs. float hint in the CmmType, because (a) the majority of
367 platforms have a strong distinction between float and int registers,
368 and (b) we don't want to do any heavyweight hint-inference in the
369 native code backend in order to get good code. We're treating the
370 hint more like a type: our Cmm is always completely consistent with
371 respect to hints. All coercions between float and int are explicit.
372
373 What about the signed vs. unsigned hint? This information might be
374 useful if we want to keep sub-word-sized values in word-size
375 registers, which we must do if we only have word-sized registers.
376
377 On such a system, there are two straightforward conventions for
378 representing sub-word-sized values:
379
380 (a) Leave the upper bits undefined. Comparison operations must
381 sign- or zero-extend both operands before comparing them,
382 depending on whether the comparison is signed or unsigned.
383
384 (b) Always keep the values sign- or zero-extended as appropriate.
385 Arithmetic operations must narrow the result to the appropriate
386 size.
387
388 A clever compiler might not use either (a) or (b) exclusively, instead
389 it would attempt to minimize the coercions by analysis: the same kind
390 of analysis that propagates hints around. In Cmm we don't want to
391 have to do this, so we plump for having richer types and keeping the
392 type information consistent.
393
394 If signed/unsigned hints are missing from CmmType, then the only
395 choice we have is (a), because we don't know whether the result of an
396 operation should be sign- or zero-extended.
397
398 Many architectures have extending load operations, which work well
399 with (b). To make use of them with (a), you need to know whether the
400 value is going to be sign- or zero-extended by an enclosing comparison
401 (for example), which involves knowing above the context. This is
402 doable but more complex.
403
404 Further complicating the issue is foreign calls: a foreign calling
405 convention can specify that signed 8-bit quantities are passed as
406 sign-extended 32 bit quantities, for example (this is the case on the
407 PowerPC). So we *do* need sign information on foreign call arguments.
408
409 Pros for adding signed vs. unsigned to CmmType:
410
411 - It would let us use convention (b) above, and get easier
412 code generation for extending loads.
413
414 - Less information required on foreign calls.
415
416 - MachOp type would be simpler
417
418 Cons:
419
420 - More complexity
421
422 - What is the CmmType for a VanillaReg? Currently it is
423 always wordRep, but now we have to decide whether it is
424 signed or unsigned. The same VanillaReg can thus have
425 different CmmType in different parts of the program.
426
427 - Extra coercions cluttering up expressions.
428
429 Currently for GHC, the foreign call point is moot, because we do our
430 own promotion of sub-word-sized values to word-sized values. The Int8
431 type is represnted by an Int# which is kept sign-extended at all times
432 (this is slightly naughty, because we're making assumptions about the
433 C calling convention rather early on in the compiler). However, given
434 this, the cons outweigh the pros.
435
436 -}
437