2 % (c) The AQUA Project, Glasgow University, 1993-1996
6 module AsmCodeGen ( writeRealAsm, dumpRealAsm ) where
8 #include "HsVersions.h"
17 import AbsCStixGen ( genCodeAbstractC )
18 import AbsCSyn ( AbstractC, MagicId )
19 import AsmRegAlloc ( runRegAllocate )
20 import OrdList ( OrdList )
21 import PrimOp ( commutableOp, PrimOp(..) )
22 import PrimRep ( PrimRep{-instance Eq-} )
23 import RegAllocInfo ( mkMRegsState, MRegsState )
24 import Stix ( StixTree(..), StixReg(..), CodeSegment )
25 import UniqSupply ( returnUs, thenUs, mapUs, UniqSM, UniqSupply )
29 The 96/03 native-code generator has machine-independent and
30 machine-dependent modules (those \tr{#include}'ing \tr{NCG.h}).
32 This module (@AsmCodeGen@) is the top-level machine-independent
33 module. It uses @AbsCStixGen.genCodeAbstractC@ to produce @StixTree@s
34 (defined in module @Stix@), using support code from @StixInfo@ (info
35 tables), @StixPrim@ (primitive operations), @StixMacro@ (Abstract C
36 macros), and @StixInteger@ (GMP arbitrary-precision operations).
38 Before entering machine-dependent land, we do some machine-independent
39 @genericOpt@imisations (defined below) on the @StixTree@s.
41 We convert to the machine-specific @Instr@ datatype with
42 @stmt2Instrs@, assuming an ``infinite'' supply of registers. We then
43 use a machine-independent register allocator (@runRegAllocate@) to
44 rejoin reality. Obviously, @runRegAllocate@ has machine-specific
45 helper functions (see about @RegAllocInfo@ below).
47 The machine-dependent bits break down as follows:
49 \item[@MachRegs@:] Everything about the target platform's machine
50 registers (and immediate operands, and addresses, which tend to
51 intermingle/interact with registers).
53 \item[@MachMisc@:] Includes the @Instr@ datatype (possibly should
54 have a module of its own), plus a miscellany of other things
55 (e.g., @targetDoubleSize@, @smStablePtrTable@, ...)
57 \item[@MachCode@:] @stmt2Instrs@ is where @Stix@ stuff turns into
60 \item[@PprMach@:] @pprInstr@ turns an @Instr@ into text (well, really
63 \item[@RegAllocInfo@:] In the register allocator, we manipulate
64 @MRegsState@s, which are @BitSet@s, one bit per machine register.
65 When we want to say something about a specific machine register
66 (e.g., ``it gets clobbered by this instruction''), we set/unset
67 its bit. Obviously, we do this @BitSet@ thing for efficiency
70 The @RegAllocInfo@ module collects together the machine-specific
71 info needed to do register allocation.
76 writeRealAsm :: Handle -> AbstractC -> UniqSupply -> IO ()
77 writeRealAsm handle absC us
78 = _scc_ "writeRealAsm" (printForAsm handle (runNCG absC us))
80 dumpRealAsm :: AbstractC -> UniqSupply -> SDoc
84 = genCodeAbstractC absC `thenUs` \ treelists ->
86 stix = map (map genericOpt) treelists
91 @codeGen@ is the top-level code-generation function:
93 codeGen :: [[StixTree]] -> UniqSM SDoc
96 = mapUs genMachCode trees `thenUs` \ dynamic_codes ->
98 static_instrs = scheduleMachCode dynamic_codes
100 returnUs (vcat (map pprInstr static_instrs))
103 Top level code generator for a chunk of stix code:
105 genMachCode :: [StixTree] -> UniqSM InstrList
108 = mapUs stmt2Instrs stmts `thenUs` \ blocks ->
109 returnUs (foldr (.) id blocks asmVoid)
112 The next bit does the code scheduling. The scheduler must also deal
113 with register allocation of temporaries. Much parallelism can be
114 exposed via the OrdList, but more might occur, so further analysis
118 scheduleMachCode :: [InstrList] -> [Instr]
121 = concat . map (runRegAllocate freeRegsState reservedRegs)
123 freeRegsState = mkMRegsState (extractMappedRegNos freeRegs)
126 %************************************************************************
128 \subsection[NCOpt]{The Generic Optimiser}
130 %************************************************************************
132 This is called between translating Abstract C to its Tree and actually
133 using the Native Code Generator to generate the annotations. It's a
134 chance to do some strength reductions.
136 ** Remember these all have to be machine independent ***
138 Note that constant-folding should have already happened, but we might
139 have introduced some new opportunities for constant-folding wrt
140 address manipulations.
143 genericOpt :: StixTree -> StixTree
146 For most nodes, just optimize the children.
149 genericOpt (StInd pk addr) = StInd pk (genericOpt addr)
151 genericOpt (StAssign pk dst src)
152 = StAssign pk (genericOpt dst) (genericOpt src)
154 genericOpt (StJump addr) = StJump (genericOpt addr)
156 genericOpt (StCondJump addr test)
157 = StCondJump addr (genericOpt test)
159 genericOpt (StCall fn pk args)
160 = StCall fn pk (map genericOpt args)
163 Fold indices together when the types match:
165 genericOpt (StIndex pk (StIndex pk' base off) off')
167 = StIndex pk (genericOpt base)
168 (genericOpt (StPrim IntAddOp [off, off']))
170 genericOpt (StIndex pk base off)
171 = StIndex pk (genericOpt base) (genericOpt off)
174 For PrimOps, we first optimize the children, and then we try our hand
175 at some constant-folding.
178 genericOpt (StPrim op args) = primOpt op (map genericOpt args)
181 Replace register leaves with appropriate StixTrees for the given
185 genericOpt leaf@(StReg (StixMagicId id))
186 = case (stgReg id) of
187 Always tree -> genericOpt tree
190 genericOpt other = other
193 Now, try to constant-fold the PrimOps. The arguments have already
194 been optimized and folded.
198 :: PrimOp -- The operation from an StPrim
199 -> [StixTree] -- The optimized arguments
202 primOpt op arg@[StInt x]
204 IntNegOp -> StInt (-x)
205 IntAbsOp -> StInt (abs x)
208 primOpt op args@[StInt x, StInt y]
210 CharGtOp -> StInt (if x > y then 1 else 0)
211 CharGeOp -> StInt (if x >= y then 1 else 0)
212 CharEqOp -> StInt (if x == y then 1 else 0)
213 CharNeOp -> StInt (if x /= y then 1 else 0)
214 CharLtOp -> StInt (if x < y then 1 else 0)
215 CharLeOp -> StInt (if x <= y then 1 else 0)
216 IntAddOp -> StInt (x + y)
217 IntSubOp -> StInt (x - y)
218 IntMulOp -> StInt (x * y)
219 IntQuotOp -> StInt (x `quot` y)
220 IntRemOp -> StInt (x `rem` y)
221 IntGtOp -> StInt (if x > y then 1 else 0)
222 IntGeOp -> StInt (if x >= y then 1 else 0)
223 IntEqOp -> StInt (if x == y then 1 else 0)
224 IntNeOp -> StInt (if x /= y then 1 else 0)
225 IntLtOp -> StInt (if x < y then 1 else 0)
226 IntLeOp -> StInt (if x <= y then 1 else 0)
227 -- ToDo: WordQuotOp, WordRemOp.
231 When possible, shift the constants to the right-hand side, so that we
232 can match for strength reductions. Note that the code generator will
233 also assume that constants have been shifted to the right when
237 primOpt op [x@(StInt _), y] | commutableOp op = primOpt op [y, x]
240 We can often do something with constants of 0 and 1 ...
243 primOpt op args@[x, y@(StInt 0)]
259 primOpt op args@[x, y@(StInt 1)]
267 Now look for multiplication/division by powers of 2 (integers).
270 primOpt op args@[x, y@(StInt n)]
272 IntMulOp -> case exactLog2 n of
273 Nothing -> StPrim op args
274 Just p -> StPrim SllOp [x, StInt p]
275 IntQuotOp -> case exactLog2 n of
276 Nothing -> StPrim op args
277 Just p -> StPrim SraOp [x, StInt p]
281 Anything else is just too hard.
284 primOpt op args = StPrim op args