Add support for producing position-independent executables
[ghc.git] / compiler / cmm / CmmMachOp.hs
1 {-# LANGUAGE CPP #-}
2
3 module CmmMachOp
4 ( MachOp(..)
5 , pprMachOp, isCommutableMachOp, isAssociativeMachOp
6 , isComparisonMachOp, maybeIntComparison, machOpResultType
7 , machOpArgReps, maybeInvertComparison
8
9 -- MachOp builders
10 , mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
11 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
12 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
13 , mo_wordULe, mo_wordUGt, mo_wordULt
14 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot
15 , mo_wordShl, mo_wordSShr, mo_wordUShr
16 , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
17 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord
18 , mo_u_32ToWord, mo_s_32ToWord
19 , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32, mo_WordTo64
20
21 -- CallishMachOp
22 , CallishMachOp(..), callishMachOpHints
23 , pprCallishMachOp
24 , machOpMemcpyishAlign
25
26 -- Atomic read-modify-write
27 , AtomicMachOp(..)
28 )
29 where
30
31 #include "HsVersions.h"
32
33 import CmmType
34 import Outputable
35 import DynFlags
36
37 -----------------------------------------------------------------------------
38 -- MachOp
39 -----------------------------------------------------------------------------
40
41 {- |
42 Machine-level primops; ones which we can reasonably delegate to the
43 native code generators to handle.
44
45 Most operations are parameterised by the 'Width' that they operate on.
46 Some operations have separate signed and unsigned versions, and float
47 and integer versions.
48 -}
49
50 data MachOp
51 -- Integer operations (insensitive to signed/unsigned)
52 = MO_Add Width
53 | MO_Sub Width
54 | MO_Eq Width
55 | MO_Ne Width
56 | MO_Mul Width -- low word of multiply
57
58 -- Signed multiply/divide
59 | MO_S_MulMayOflo Width -- nonzero if signed multiply overflows
60 | MO_S_Quot Width -- signed / (same semantics as IntQuotOp)
61 | MO_S_Rem Width -- signed % (same semantics as IntRemOp)
62 | MO_S_Neg Width -- unary -
63
64 -- Unsigned multiply/divide
65 | MO_U_MulMayOflo Width -- nonzero if unsigned multiply overflows
66 | MO_U_Quot Width -- unsigned / (same semantics as WordQuotOp)
67 | MO_U_Rem Width -- unsigned % (same semantics as WordRemOp)
68
69 -- Signed comparisons
70 | MO_S_Ge Width
71 | MO_S_Le Width
72 | MO_S_Gt Width
73 | MO_S_Lt Width
74
75 -- Unsigned comparisons
76 | MO_U_Ge Width
77 | MO_U_Le Width
78 | MO_U_Gt Width
79 | MO_U_Lt Width
80
81 -- Floating point arithmetic
82 | MO_F_Add Width
83 | MO_F_Sub Width
84 | MO_F_Neg Width -- unary -
85 | MO_F_Mul Width
86 | MO_F_Quot Width
87
88 -- Floating point comparison
89 | MO_F_Eq Width
90 | MO_F_Ne Width
91 | MO_F_Ge Width
92 | MO_F_Le Width
93 | MO_F_Gt Width
94 | MO_F_Lt Width
95
96 -- Bitwise operations. Not all of these may be supported
97 -- at all sizes, and only integral Widths are valid.
98 | MO_And Width
99 | MO_Or Width
100 | MO_Xor Width
101 | MO_Not Width
102 | MO_Shl Width
103 | MO_U_Shr Width -- unsigned shift right
104 | MO_S_Shr Width -- signed shift right
105
106 -- Conversions. Some of these will be NOPs.
107 -- Floating-point conversions use the signed variant.
108 | MO_SF_Conv Width Width -- Signed int -> Float
109 | MO_FS_Conv Width Width -- Float -> Signed int
110 | MO_SS_Conv Width Width -- Signed int -> Signed int
111 | MO_UU_Conv Width Width -- unsigned int -> unsigned int
112 | MO_FF_Conv Width Width -- Float -> Float
113
114 -- Vector element insertion and extraction operations
115 | MO_V_Insert Length Width -- Insert scalar into vector
116 | MO_V_Extract Length Width -- Extract scalar from vector
117
118 -- Integer vector operations
119 | MO_V_Add Length Width
120 | MO_V_Sub Length Width
121 | MO_V_Mul Length Width
122
123 -- Signed vector multiply/divide
124 | MO_VS_Quot Length Width
125 | MO_VS_Rem Length Width
126 | MO_VS_Neg Length Width
127
128 -- Unsigned vector multiply/divide
129 | MO_VU_Quot Length Width
130 | MO_VU_Rem Length Width
131
132 -- Floting point vector element insertion and extraction operations
133 | MO_VF_Insert Length Width -- Insert scalar into vector
134 | MO_VF_Extract Length Width -- Extract scalar from vector
135
136 -- Floating point vector operations
137 | MO_VF_Add Length Width
138 | MO_VF_Sub Length Width
139 | MO_VF_Neg Length Width -- unary -
140 | MO_VF_Mul Length Width
141 | MO_VF_Quot Length Width
142 deriving (Eq, Show)
143
144 pprMachOp :: MachOp -> SDoc
145 pprMachOp mo = text (show mo)
146
147
148
149 -- -----------------------------------------------------------------------------
150 -- Some common MachReps
151
152 -- A 'wordRep' is a machine word on the target architecture
153 -- Specifically, it is the size of an Int#, Word#, Addr#
154 -- and the unit of allocation on the stack and the heap
155 -- Any pointer is also guaranteed to be a wordRep.
156
157 mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
158 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
159 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
160 , mo_wordULe, mo_wordUGt, mo_wordULt
161 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
162 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
163 , mo_WordTo8, mo_WordTo16, mo_WordTo32, mo_WordTo64
164 :: DynFlags -> MachOp
165
166 mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
167 , mo_32To8, mo_32To16
168 :: MachOp
169
170 mo_wordAdd dflags = MO_Add (wordWidth dflags)
171 mo_wordSub dflags = MO_Sub (wordWidth dflags)
172 mo_wordEq dflags = MO_Eq (wordWidth dflags)
173 mo_wordNe dflags = MO_Ne (wordWidth dflags)
174 mo_wordMul dflags = MO_Mul (wordWidth dflags)
175 mo_wordSQuot dflags = MO_S_Quot (wordWidth dflags)
176 mo_wordSRem dflags = MO_S_Rem (wordWidth dflags)
177 mo_wordSNeg dflags = MO_S_Neg (wordWidth dflags)
178 mo_wordUQuot dflags = MO_U_Quot (wordWidth dflags)
179 mo_wordURem dflags = MO_U_Rem (wordWidth dflags)
180
181 mo_wordSGe dflags = MO_S_Ge (wordWidth dflags)
182 mo_wordSLe dflags = MO_S_Le (wordWidth dflags)
183 mo_wordSGt dflags = MO_S_Gt (wordWidth dflags)
184 mo_wordSLt dflags = MO_S_Lt (wordWidth dflags)
185
186 mo_wordUGe dflags = MO_U_Ge (wordWidth dflags)
187 mo_wordULe dflags = MO_U_Le (wordWidth dflags)
188 mo_wordUGt dflags = MO_U_Gt (wordWidth dflags)
189 mo_wordULt dflags = MO_U_Lt (wordWidth dflags)
190
191 mo_wordAnd dflags = MO_And (wordWidth dflags)
192 mo_wordOr dflags = MO_Or (wordWidth dflags)
193 mo_wordXor dflags = MO_Xor (wordWidth dflags)
194 mo_wordNot dflags = MO_Not (wordWidth dflags)
195 mo_wordShl dflags = MO_Shl (wordWidth dflags)
196 mo_wordSShr dflags = MO_S_Shr (wordWidth dflags)
197 mo_wordUShr dflags = MO_U_Shr (wordWidth dflags)
198
199 mo_u_8To32 = MO_UU_Conv W8 W32
200 mo_s_8To32 = MO_SS_Conv W8 W32
201 mo_u_16To32 = MO_UU_Conv W16 W32
202 mo_s_16To32 = MO_SS_Conv W16 W32
203
204 mo_u_8ToWord dflags = MO_UU_Conv W8 (wordWidth dflags)
205 mo_s_8ToWord dflags = MO_SS_Conv W8 (wordWidth dflags)
206 mo_u_16ToWord dflags = MO_UU_Conv W16 (wordWidth dflags)
207 mo_s_16ToWord dflags = MO_SS_Conv W16 (wordWidth dflags)
208 mo_s_32ToWord dflags = MO_SS_Conv W32 (wordWidth dflags)
209 mo_u_32ToWord dflags = MO_UU_Conv W32 (wordWidth dflags)
210
211 mo_WordTo8 dflags = MO_UU_Conv (wordWidth dflags) W8
212 mo_WordTo16 dflags = MO_UU_Conv (wordWidth dflags) W16
213 mo_WordTo32 dflags = MO_UU_Conv (wordWidth dflags) W32
214 mo_WordTo64 dflags = MO_UU_Conv (wordWidth dflags) W64
215
216 mo_32To8 = MO_UU_Conv W32 W8
217 mo_32To16 = MO_UU_Conv W32 W16
218
219
220 -- ----------------------------------------------------------------------------
221 -- isCommutableMachOp
222
223 {- |
224 Returns 'True' if the MachOp has commutable arguments. This is used
225 in the platform-independent Cmm optimisations.
226
227 If in doubt, return 'False'. This generates worse code on the
228 native routes, but is otherwise harmless.
229 -}
230 isCommutableMachOp :: MachOp -> Bool
231 isCommutableMachOp mop =
232 case mop of
233 MO_Add _ -> True
234 MO_Eq _ -> True
235 MO_Ne _ -> True
236 MO_Mul _ -> True
237 MO_S_MulMayOflo _ -> True
238 MO_U_MulMayOflo _ -> True
239 MO_And _ -> True
240 MO_Or _ -> True
241 MO_Xor _ -> True
242 MO_F_Add _ -> True
243 MO_F_Mul _ -> True
244 _other -> False
245
246 -- ----------------------------------------------------------------------------
247 -- isAssociativeMachOp
248
249 {- |
250 Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
251 This is used in the platform-independent Cmm optimisations.
252
253 If in doubt, return 'False'. This generates worse code on the
254 native routes, but is otherwise harmless.
255 -}
256 isAssociativeMachOp :: MachOp -> Bool
257 isAssociativeMachOp mop =
258 case mop of
259 MO_Add {} -> True -- NB: does not include
260 MO_Mul {} -> True -- floatint point!
261 MO_And {} -> True
262 MO_Or {} -> True
263 MO_Xor {} -> True
264 _other -> False
265
266
267 -- ----------------------------------------------------------------------------
268 -- isComparisonMachOp
269
270 {- |
271 Returns 'True' if the MachOp is a comparison.
272
273 If in doubt, return False. This generates worse code on the
274 native routes, but is otherwise harmless.
275 -}
276 isComparisonMachOp :: MachOp -> Bool
277 isComparisonMachOp mop =
278 case mop of
279 MO_Eq _ -> True
280 MO_Ne _ -> True
281 MO_S_Ge _ -> True
282 MO_S_Le _ -> True
283 MO_S_Gt _ -> True
284 MO_S_Lt _ -> True
285 MO_U_Ge _ -> True
286 MO_U_Le _ -> True
287 MO_U_Gt _ -> True
288 MO_U_Lt _ -> True
289 MO_F_Eq {} -> True
290 MO_F_Ne {} -> True
291 MO_F_Ge {} -> True
292 MO_F_Le {} -> True
293 MO_F_Gt {} -> True
294 MO_F_Lt {} -> True
295 _other -> False
296
297 {- |
298 Returns @Just w@ if the operation is an integer comparison with width
299 @w@, or @Nothing@ otherwise.
300 -}
301 maybeIntComparison :: MachOp -> Maybe Width
302 maybeIntComparison mop =
303 case mop of
304 MO_Eq w -> Just w
305 MO_Ne w -> Just w
306 MO_S_Ge w -> Just w
307 MO_S_Le w -> Just w
308 MO_S_Gt w -> Just w
309 MO_S_Lt w -> Just w
310 MO_U_Ge w -> Just w
311 MO_U_Le w -> Just w
312 MO_U_Gt w -> Just w
313 MO_U_Lt w -> Just w
314 _ -> Nothing
315
316 -- -----------------------------------------------------------------------------
317 -- Inverting conditions
318
319 -- Sometimes it's useful to be able to invert the sense of a
320 -- condition. Not all conditional tests are invertible: in
321 -- particular, floating point conditionals cannot be inverted, because
322 -- there exist floating-point values which return False for both senses
323 -- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).
324
325 maybeInvertComparison :: MachOp -> Maybe MachOp
326 maybeInvertComparison op
327 = case op of -- None of these Just cases include floating point
328 MO_Eq r -> Just (MO_Ne r)
329 MO_Ne r -> Just (MO_Eq r)
330 MO_U_Lt r -> Just (MO_U_Ge r)
331 MO_U_Gt r -> Just (MO_U_Le r)
332 MO_U_Le r -> Just (MO_U_Gt r)
333 MO_U_Ge r -> Just (MO_U_Lt r)
334 MO_S_Lt r -> Just (MO_S_Ge r)
335 MO_S_Gt r -> Just (MO_S_Le r)
336 MO_S_Le r -> Just (MO_S_Gt r)
337 MO_S_Ge r -> Just (MO_S_Lt r)
338 _other -> Nothing
339
340 -- ----------------------------------------------------------------------------
341 -- machOpResultType
342
343 {- |
344 Returns the MachRep of the result of a MachOp.
345 -}
346 machOpResultType :: DynFlags -> MachOp -> [CmmType] -> CmmType
347 machOpResultType dflags mop tys =
348 case mop of
349 MO_Add {} -> ty1 -- Preserve GC-ptr-hood
350 MO_Sub {} -> ty1 -- of first arg
351 MO_Mul r -> cmmBits r
352 MO_S_MulMayOflo r -> cmmBits r
353 MO_S_Quot r -> cmmBits r
354 MO_S_Rem r -> cmmBits r
355 MO_S_Neg r -> cmmBits r
356 MO_U_MulMayOflo r -> cmmBits r
357 MO_U_Quot r -> cmmBits r
358 MO_U_Rem r -> cmmBits r
359
360 MO_Eq {} -> comparisonResultRep dflags
361 MO_Ne {} -> comparisonResultRep dflags
362 MO_S_Ge {} -> comparisonResultRep dflags
363 MO_S_Le {} -> comparisonResultRep dflags
364 MO_S_Gt {} -> comparisonResultRep dflags
365 MO_S_Lt {} -> comparisonResultRep dflags
366
367 MO_U_Ge {} -> comparisonResultRep dflags
368 MO_U_Le {} -> comparisonResultRep dflags
369 MO_U_Gt {} -> comparisonResultRep dflags
370 MO_U_Lt {} -> comparisonResultRep dflags
371
372 MO_F_Add r -> cmmFloat r
373 MO_F_Sub r -> cmmFloat r
374 MO_F_Mul r -> cmmFloat r
375 MO_F_Quot r -> cmmFloat r
376 MO_F_Neg r -> cmmFloat r
377 MO_F_Eq {} -> comparisonResultRep dflags
378 MO_F_Ne {} -> comparisonResultRep dflags
379 MO_F_Ge {} -> comparisonResultRep dflags
380 MO_F_Le {} -> comparisonResultRep dflags
381 MO_F_Gt {} -> comparisonResultRep dflags
382 MO_F_Lt {} -> comparisonResultRep dflags
383
384 MO_And {} -> ty1 -- Used for pointer masking
385 MO_Or {} -> ty1
386 MO_Xor {} -> ty1
387 MO_Not r -> cmmBits r
388 MO_Shl r -> cmmBits r
389 MO_U_Shr r -> cmmBits r
390 MO_S_Shr r -> cmmBits r
391
392 MO_SS_Conv _ to -> cmmBits to
393 MO_UU_Conv _ to -> cmmBits to
394 MO_FS_Conv _ to -> cmmBits to
395 MO_SF_Conv _ to -> cmmFloat to
396 MO_FF_Conv _ to -> cmmFloat to
397
398 MO_V_Insert l w -> cmmVec l (cmmBits w)
399 MO_V_Extract _ w -> cmmBits w
400
401 MO_V_Add l w -> cmmVec l (cmmBits w)
402 MO_V_Sub l w -> cmmVec l (cmmBits w)
403 MO_V_Mul l w -> cmmVec l (cmmBits w)
404
405 MO_VS_Quot l w -> cmmVec l (cmmBits w)
406 MO_VS_Rem l w -> cmmVec l (cmmBits w)
407 MO_VS_Neg l w -> cmmVec l (cmmBits w)
408
409 MO_VU_Quot l w -> cmmVec l (cmmBits w)
410 MO_VU_Rem l w -> cmmVec l (cmmBits w)
411
412 MO_VF_Insert l w -> cmmVec l (cmmFloat w)
413 MO_VF_Extract _ w -> cmmFloat w
414
415 MO_VF_Add l w -> cmmVec l (cmmFloat w)
416 MO_VF_Sub l w -> cmmVec l (cmmFloat w)
417 MO_VF_Mul l w -> cmmVec l (cmmFloat w)
418 MO_VF_Quot l w -> cmmVec l (cmmFloat w)
419 MO_VF_Neg l w -> cmmVec l (cmmFloat w)
420 where
421 (ty1:_) = tys
422
423 comparisonResultRep :: DynFlags -> CmmType
424 comparisonResultRep = bWord -- is it?
425
426
427 -- -----------------------------------------------------------------------------
428 -- machOpArgReps
429
430 -- | This function is used for debugging only: we can check whether an
431 -- application of a MachOp is "type-correct" by checking that the MachReps of
432 -- its arguments are the same as the MachOp expects. This is used when
433 -- linting a CmmExpr.
434
435 machOpArgReps :: DynFlags -> MachOp -> [Width]
436 machOpArgReps dflags op =
437 case op of
438 MO_Add r -> [r,r]
439 MO_Sub r -> [r,r]
440 MO_Eq r -> [r,r]
441 MO_Ne r -> [r,r]
442 MO_Mul r -> [r,r]
443 MO_S_MulMayOflo r -> [r,r]
444 MO_S_Quot r -> [r,r]
445 MO_S_Rem r -> [r,r]
446 MO_S_Neg r -> [r]
447 MO_U_MulMayOflo r -> [r,r]
448 MO_U_Quot r -> [r,r]
449 MO_U_Rem r -> [r,r]
450
451 MO_S_Ge r -> [r,r]
452 MO_S_Le r -> [r,r]
453 MO_S_Gt r -> [r,r]
454 MO_S_Lt r -> [r,r]
455
456 MO_U_Ge r -> [r,r]
457 MO_U_Le r -> [r,r]
458 MO_U_Gt r -> [r,r]
459 MO_U_Lt r -> [r,r]
460
461 MO_F_Add r -> [r,r]
462 MO_F_Sub r -> [r,r]
463 MO_F_Mul r -> [r,r]
464 MO_F_Quot r -> [r,r]
465 MO_F_Neg r -> [r]
466 MO_F_Eq r -> [r,r]
467 MO_F_Ne r -> [r,r]
468 MO_F_Ge r -> [r,r]
469 MO_F_Le r -> [r,r]
470 MO_F_Gt r -> [r,r]
471 MO_F_Lt r -> [r,r]
472
473 MO_And r -> [r,r]
474 MO_Or r -> [r,r]
475 MO_Xor r -> [r,r]
476 MO_Not r -> [r]
477 MO_Shl r -> [r, wordWidth dflags]
478 MO_U_Shr r -> [r, wordWidth dflags]
479 MO_S_Shr r -> [r, wordWidth dflags]
480
481 MO_SS_Conv from _ -> [from]
482 MO_UU_Conv from _ -> [from]
483 MO_SF_Conv from _ -> [from]
484 MO_FS_Conv from _ -> [from]
485 MO_FF_Conv from _ -> [from]
486
487 MO_V_Insert l r -> [typeWidth (vec l (cmmBits r)),r,wordWidth dflags]
488 MO_V_Extract l r -> [typeWidth (vec l (cmmBits r)),wordWidth dflags]
489
490 MO_V_Add _ r -> [r,r]
491 MO_V_Sub _ r -> [r,r]
492 MO_V_Mul _ r -> [r,r]
493
494 MO_VS_Quot _ r -> [r,r]
495 MO_VS_Rem _ r -> [r,r]
496 MO_VS_Neg _ r -> [r]
497
498 MO_VU_Quot _ r -> [r,r]
499 MO_VU_Rem _ r -> [r,r]
500
501 MO_VF_Insert l r -> [typeWidth (vec l (cmmFloat r)),r,wordWidth dflags]
502 MO_VF_Extract l r -> [typeWidth (vec l (cmmFloat r)),wordWidth dflags]
503
504 MO_VF_Add _ r -> [r,r]
505 MO_VF_Sub _ r -> [r,r]
506 MO_VF_Mul _ r -> [r,r]
507 MO_VF_Quot _ r -> [r,r]
508 MO_VF_Neg _ r -> [r]
509
510 -----------------------------------------------------------------------------
511 -- CallishMachOp
512 -----------------------------------------------------------------------------
513
514 -- CallishMachOps tend to be implemented by foreign calls in some backends,
515 -- so we separate them out. In Cmm, these can only occur in a
516 -- statement position, in contrast to an ordinary MachOp which can occur
517 -- anywhere in an expression.
518 data CallishMachOp
519 = MO_F64_Pwr
520 | MO_F64_Sin
521 | MO_F64_Cos
522 | MO_F64_Tan
523 | MO_F64_Sinh
524 | MO_F64_Cosh
525 | MO_F64_Tanh
526 | MO_F64_Asin
527 | MO_F64_Acos
528 | MO_F64_Atan
529 | MO_F64_Log
530 | MO_F64_Exp
531 | MO_F64_Fabs
532 | MO_F64_Sqrt
533 | MO_F32_Pwr
534 | MO_F32_Sin
535 | MO_F32_Cos
536 | MO_F32_Tan
537 | MO_F32_Sinh
538 | MO_F32_Cosh
539 | MO_F32_Tanh
540 | MO_F32_Asin
541 | MO_F32_Acos
542 | MO_F32_Atan
543 | MO_F32_Log
544 | MO_F32_Exp
545 | MO_F32_Fabs
546 | MO_F32_Sqrt
547
548 | MO_UF_Conv Width
549
550 | MO_S_QuotRem Width
551 | MO_U_QuotRem Width
552 | MO_U_QuotRem2 Width
553 | MO_Add2 Width
554 | MO_SubWordC Width
555 | MO_AddIntC Width
556 | MO_SubIntC Width
557 | MO_U_Mul2 Width
558
559 | MO_WriteBarrier
560 | MO_Touch -- Keep variables live (when using interior pointers)
561
562 -- Prefetch
563 | MO_Prefetch_Data Int -- Prefetch hint. May change program performance but not
564 -- program behavior.
565 -- the Int can be 0-3. Needs to be known at compile time
566 -- to interact with code generation correctly.
567 -- TODO: add support for prefetch WRITES,
568 -- currently only exposes prefetch reads, which
569 -- would the majority of use cases in ghc anyways
570
571
572 -- These three MachOps are parameterised by the known alignment
573 -- of the destination and source (for memcpy/memmove) pointers.
574 -- This information may be used for optimisation in backends.
575 | MO_Memcpy Int
576 | MO_Memset Int
577 | MO_Memmove Int
578
579 | MO_PopCnt Width
580 | MO_Clz Width
581 | MO_Ctz Width
582
583 | MO_BSwap Width
584
585 -- Atomic read-modify-write.
586 | MO_AtomicRMW Width AtomicMachOp
587 | MO_AtomicRead Width
588 | MO_AtomicWrite Width
589 | MO_Cmpxchg Width
590 deriving (Eq, Show)
591
592 -- | The operation to perform atomically.
593 data AtomicMachOp =
594 AMO_Add
595 | AMO_Sub
596 | AMO_And
597 | AMO_Nand
598 | AMO_Or
599 | AMO_Xor
600 deriving (Eq, Show)
601
602 pprCallishMachOp :: CallishMachOp -> SDoc
603 pprCallishMachOp mo = text (show mo)
604
605 callishMachOpHints :: CallishMachOp -> ([ForeignHint], [ForeignHint])
606 callishMachOpHints op = case op of
607 MO_Memcpy _ -> ([], [AddrHint,AddrHint,NoHint])
608 MO_Memset _ -> ([], [AddrHint,NoHint,NoHint])
609 MO_Memmove _ -> ([], [AddrHint,AddrHint,NoHint])
610 _ -> ([],[])
611 -- empty lists indicate NoHint
612
613 -- | The alignment of a 'memcpy'-ish operation.
614 machOpMemcpyishAlign :: CallishMachOp -> Maybe Int
615 machOpMemcpyishAlign op = case op of
616 MO_Memcpy align -> Just align
617 MO_Memset align -> Just align
618 MO_Memmove align -> Just align
619 _ -> Nothing