2 % (c) The AQUA Project, Glasgow University, 1993-1995
6 #include "HsVersions.h"
7 #include "../../includes/platform.h"
8 #include "../../includes/GhcConstants.h"
11 #ifdef __GLASGOW_HASKELL__
16 -- And, I guess we need these...
17 AbstractC, GlobalSwitch, SwitchResult,
18 SplitUniqSupply, SUniqSM(..)
21 import AbsCSyn ( AbstractC )
22 import AbsCStixGen ( genCodeAbstractC )
23 import AbsPrel ( PrimKind, PrimOp(..)
24 IF_ATTACK_PRAGMAS(COMMA tagOf_PrimOp)
25 IF_ATTACK_PRAGMAS(COMMA pprPrimOp)
27 import CmdLineOpts ( GlobalSwitch(..), stringSwitchSet, switchIsOn, SwitchResult(..) )
29 import Maybes ( Maybe(..) )
31 #if alpha_dec_osf1_TARGET
32 import AlphaDesc ( mkAlpha )
35 import SparcDesc ( mkSparc )
49 This is a generic assembly language generator for the Glasgow Haskell
50 Compiler. It has been a long time in germinating, basically due to
51 time constraints and the large spectrum of design possibilities.
52 Presently it generates code for:
56 In the pipeline (sic) are plans and/or code for 680x0, 386/486.
58 The code generator presumes the presence of a working C port. This is
59 because any code that cannot be compiled (e.g. @casm@s) is re-directed
60 via this route. It also help incremental development. Because this
61 code generator is specially written for the Abstract C produced by the
62 Glasgow Haskell Compiler, several optimisation opportunities are open
63 to us that are not open to @gcc@. In particular, we know that the A
64 and B stacks and the Heap are all mutually exclusive wrt. aliasing,
65 and that expressions have no side effects (all state transformations
66 are top level objects).
68 There are two main components to the code generator.
70 \item Abstract C is considered in statements,
71 with a Twig-like system handling each statement in turn.
72 \item A scheduler turns the tree of assembly language orderings
73 into a sequence suitable for input to an assembler.
75 The @codeGenerate@ function returns the final assembly language output
76 (as a String). We can return a string, because there is only one way
77 of printing the output suitable for assembler consumption. It also
78 allows limited abstraction of different machines from the Main module.
80 The first part is the actual assembly language generation. First we
81 split up the Abstract C into individual functions, then consider
82 chunks in isolation, giving back an @OrdList@ of assembly language
83 instructions. The generic algorithm is heavily inspired by Twig
84 (ref), but also draws concepts from (ref). The basic idea is to
85 (dynamically) walk the Abstract C syntax tree, annotating it with
86 possible code matches. For example, on the Sparc, a possible match
87 (with its translation) could be
95 where @r1,r2@ are registers, and @i@ is an indirection. The Twig
96 bit twiddling algorithm for tree matching has been abandoned. It is
97 replaced with a more direct scheme. This is because, after careful
98 consideration it is felt that the overhead of handling many bit
99 patterns would be heavier that simply looking at the syntax of the
100 tree at the node being considered, and dynamically choosing and
103 The ultimate result of the first part is a Set of ordering lists of
104 ordering lists of assembly language instructions (yes, really!), where
105 each element in the set is basic chunk. Now several (generic)
106 simplifications and transformations can be performed. This includes
107 ones that turn the the ordering of orderings into just a single
108 ordering list. (The equivalent of applying @concat@ to a list of
109 lists.) A lot of the re-ordering and optimisation is actually done
110 (generically) here! The final part, the scheduler, can now be used on
111 this structure. The code sequence is optimised (obviously) to avoid
112 stalling the pipeline. This part {\em has} to be heavily machine
115 [The above seems to describe mostly dreamware. -- JSM]
117 The flag that needs to be added is -fasm-<platform> where platform is one of
122 #ifdef __GLASGOW_HASKELL__
123 # if __GLASGOW_HASKELL__ < 23
126 writeRealAsm :: (GlobalSwitch -> SwitchResult) -> _FILE -> AbstractC -> SplitUniqSupply -> PrimIO ()
128 writeRealAsm flags file absC uniq_supply
129 = uppAppendFile file 80 (runNCG (code flags absC) uniq_supply)
133 dumpRealAsm :: (GlobalSwitch -> SwitchResult) -> AbstractC -> SplitUniqSupply -> String
135 dumpRealAsm flags absC uniq_supply = uppShow 80 (runNCG (code flags absC) uniq_supply)
137 runNCG m uniq_supply = m uniq_supply
140 genCodeAbstractC target absC `thenSUs` \ treelists ->
142 stix = map (map (genericOpt target)) treelists
144 codeGen target sty stix
146 sty = PprForAsm (switchIsOn flags) (underscore target) (fmtAsmLbl target)
148 target = case stringSwitchSet flags AsmTarget of
149 #if ! OMIT_NATIVE_CODEGEN
150 #if sparc_sun_sunos4_TARGET
151 Just _ {-???"sparc-sun-sunos4"-} -> mkSparc True flags
153 #if sparc_sun_solaris2_TARGET
154 Just _ {-???"sparc-sun-solaris2"-} -> mkSparc False flags
156 #if alpha_TARGET_ARCH
157 Just _ {-???"alpha-dec-osf1"-} -> mkAlpha flags
161 ("ERROR:Trying to generate assembly language for an unsupported architecture\n"++
162 "(or one for which this build is not configured).")
166 %************************************************************************
168 \subsection[NCOpt]{The Generic Optimiser}
170 %************************************************************************
172 This is called between translating Abstract C to its Tree
173 and actually using the Native Code Generator to generate
174 the annotations. It's a chance to do some strength reductions.
176 ** Remember these all have to be machine independent ***
178 Note that constant-folding should have already happened, but we might have
179 introduced some new opportunities for constant-folding wrt address manipulations.
190 For most nodes, just optimize the children.
194 genericOpt target (StInd pk addr) =
195 StInd pk (genericOpt target addr)
197 genericOpt target (StAssign pk dst src) =
198 StAssign pk (genericOpt target dst) (genericOpt target src)
200 genericOpt target (StJump addr) =
201 StJump (genericOpt target addr)
203 genericOpt target (StCondJump addr test) =
204 StCondJump addr (genericOpt target test)
206 genericOpt target (StCall fn pk args) =
207 StCall fn pk (map (genericOpt target) args)
211 Fold indices together when the types match.
215 genericOpt target (StIndex pk (StIndex pk' base off) off')
217 StIndex pk (genericOpt target base)
218 (genericOpt target (StPrim IntAddOp [off, off']))
220 genericOpt target (StIndex pk base off) =
221 StIndex pk (genericOpt target base)
222 (genericOpt target off)
226 For primOps, we first optimize the children, and then we try our hand
227 at some constant-folding.
231 genericOpt target (StPrim op args) =
232 primOpt op (map (genericOpt target) args)
236 Replace register leaves with appropriate StixTrees for the given target.
237 (Oh, so this is why we've been hauling the target around!)
241 genericOpt target leaf@(StReg (StixMagicId id)) =
242 case stgReg target id of
243 Always tree -> genericOpt target tree
246 genericOpt target other = other
250 Now, try to constant-fold the primOps. The arguments have
251 already been optimized and folded.
256 :: PrimOp -- The operation from an StPrim
257 -> [StixTree] -- The optimized arguments
260 primOpt op arg@[StInt x] =
262 IntNegOp -> StInt (-x)
263 IntAbsOp -> StInt (abs x)
266 primOpt op args@[StInt x, StInt y] =
268 CharGtOp -> StInt (if x > y then 1 else 0)
269 CharGeOp -> StInt (if x >= y then 1 else 0)
270 CharEqOp -> StInt (if x == y then 1 else 0)
271 CharNeOp -> StInt (if x /= y then 1 else 0)
272 CharLtOp -> StInt (if x < y then 1 else 0)
273 CharLeOp -> StInt (if x <= y then 1 else 0)
274 IntAddOp -> StInt (x + y)
275 IntSubOp -> StInt (x - y)
276 IntMulOp -> StInt (x * y)
277 IntQuotOp -> StInt (x `quot` y)
278 IntDivOp -> StInt (x `div` y)
279 IntRemOp -> StInt (x `rem` y)
280 IntGtOp -> StInt (if x > y then 1 else 0)
281 IntGeOp -> StInt (if x >= y then 1 else 0)
282 IntEqOp -> StInt (if x == y then 1 else 0)
283 IntNeOp -> StInt (if x /= y then 1 else 0)
284 IntLtOp -> StInt (if x < y then 1 else 0)
285 IntLeOp -> StInt (if x <= y then 1 else 0)
290 When possible, shift the constants to the right-hand side, so that we
291 can match for strength reductions. Note that the code generator will
292 also assume that constants have been shifted to the right when possible.
296 primOpt op [x@(StInt _), y] | commutableOp op = primOpt op [y, x]
298 --primOpt op [x@(StDouble _), y] | commutableOp op = primOpt op [y, x]
302 We can often do something with constants of 0 and 1 ...
306 primOpt op args@[x, y@(StInt 0)] =
321 primOpt op args@[x, y@(StInt 1)] =
329 -- The following code tweaks a bug in early versions of GHC (pre-0.21)
331 {- OLD: (death to constant folding in ncg)
332 primOpt op args@[x, y@(StDouble 0.0)] =
342 primOpt op args@[x, y@(StDouble 1.0)] =
350 primOpt op args@[x, y@(StDouble 2.0)] =
352 FloatMulOp -> StPrim FloatAddOp [x, x]
353 DoubleMulOp -> StPrim DoubleAddOp [x, x]
359 Now look for multiplication/division by powers of 2 (integers).
363 primOpt op args@[x, y@(StInt n)] =
365 IntMulOp -> case exact_log2 n of
366 Nothing -> StPrim op args
367 Just p -> StPrim SllOp [x, StInt p]
368 IntQuotOp -> case exact_log2 n of
369 Nothing -> StPrim op args
370 Just p -> StPrim SraOp [x, StInt p]
375 Anything else is just too hard.
379 primOpt op args = StPrim op args
383 The commutable ops are those for which we will try to move constants to the
384 right hand side for strength reduction.
388 commutableOp :: PrimOp -> Bool
389 commutableOp CharEqOp = True
390 commutableOp CharNeOp = True
391 commutableOp IntAddOp = True
392 commutableOp IntMulOp = True
393 commutableOp AndOp = True
394 commutableOp OrOp = True
395 commutableOp IntEqOp = True
396 commutableOp IntNeOp = True
397 commutableOp IntegerAddOp = True
398 commutableOp IntegerMulOp = True
399 commutableOp FloatAddOp = True
400 commutableOp FloatMulOp = True
401 commutableOp FloatEqOp = True
402 commutableOp FloatNeOp = True
403 commutableOp DoubleAddOp = True
404 commutableOp DoubleMulOp = True
405 commutableOp DoubleEqOp = True
406 commutableOp DoubleNeOp = True
407 commutableOp _ = False
411 This algorithm for determining the $\log_2$ of exact powers of 2 comes from gcc. It
412 requires bit manipulation primitives, so we have a ghc version and an hbc version.
413 Other Haskell compilers are on their own.
417 #ifdef __GLASGOW_HASKELL__
423 exact_log2 :: Integer -> Maybe Integer
425 | x <= 0 || x >= 2147483648 = Nothing
426 | otherwise = case fromInteger x of
427 I# x# -> if (w2i ((i2w x#) `and#` (i2w (0# -# x#))) /=# x#) then Nothing
428 else Just (toInteger (I# (pow2 x#)))
430 where pow2 x# | x# ==# 1# = 0#
431 | otherwise = 1# +# pow2 (w2i (i2w x# `shiftr` i2w_s 1#))
433 # if __GLASGOW_HASKELL__ >= 23
434 shiftr x y = shiftRA# x y
436 shiftr x y = shiftR# x y
439 #else {-probably HBC-}
441 exact_log2 :: Integer -> Maybe Integer
443 | x <= 0 || x >= 2147483648 = Nothing
445 if x' `bitAnd` (-x') /= x' then Nothing
446 else Just (toInteger (pow2 x'))
448 where x' = ((fromInteger x) :: Word)
449 pow2 x | x == bit0 = 0 :: Int
450 | otherwise = 1 + pow2 (x `bitRsh` 1)
452 #endif {-probably HBC-}