2 % (c) The AQUA Project, Glasgow University, 1993-1996
6 #include "HsVersions.h"
8 module AsmCodeGen ( writeRealAsm, dumpRealAsm ) where
11 IMPORT_1_3(IO(Handle))
14 #if __GLASGOW_HASKELL__ >= 202
15 import MachRegs hiding (Addr)
22 import AbsCStixGen ( genCodeAbstractC )
23 import AbsCSyn ( AbstractC, MagicId )
24 import AsmRegAlloc ( runRegAllocate )
25 import OrdList ( OrdList )
26 import PrimOp ( commutableOp, PrimOp(..) )
27 import PrimRep ( PrimRep{-instance Eq-} )
28 import RegAllocInfo ( mkMRegsState, MRegsState )
29 import Stix ( StixTree(..), StixReg(..), CodeSegment )
30 import UniqSupply ( returnUs, thenUs, mapUs, SYN_IE(UniqSM), UniqSupply )
31 import Outputable ( printDoc )
32 import Pretty ( Doc, vcat, Mode(..) )
35 The 96/03 native-code generator has machine-independent and
36 machine-dependent modules (those \tr{#include}'ing \tr{NCG.h}).
38 This module (@AsmCodeGen@) is the top-level machine-independent
39 module. It uses @AbsCStixGen.genCodeAbstractC@ to produce @StixTree@s
40 (defined in module @Stix@), using support code from @StixInfo@ (info
41 tables), @StixPrim@ (primitive operations), @StixMacro@ (Abstract C
42 macros), and @StixInteger@ (GMP arbitrary-precision operations).
44 Before entering machine-dependent land, we do some machine-independent
45 @genericOpt@imisations (defined below) on the @StixTree@s.
47 We convert to the machine-specific @Instr@ datatype with
48 @stmt2Instrs@, assuming an ``infinite'' supply of registers. We then
49 use a machine-independent register allocator (@runRegAllocate@) to
50 rejoin reality. Obviously, @runRegAllocate@ has machine-specific
51 helper functions (see about @RegAllocInfo@ below).
53 The machine-dependent bits break down as follows:
55 \item[@MachRegs@:] Everything about the target platform's machine
56 registers (and immediate operands, and addresses, which tend to
57 intermingle/interact with registers).
59 \item[@MachMisc@:] Includes the @Instr@ datatype (possibly should
60 have a module of its own), plus a miscellany of other things
61 (e.g., @targetDoubleSize@, @smStablePtrTable@, ...)
63 \item[@MachCode@:] @stmt2Instrs@ is where @Stix@ stuff turns into
66 \item[@PprMach@:] @pprInstr@ turns an @Instr@ into text (well, really
69 \item[@RegAllocInfo@:] In the register allocator, we manipulate
70 @MRegsState@s, which are @BitSet@s, one bit per machine register.
71 When we want to say something about a specific machine register
72 (e.g., ``it gets clobbered by this instruction''), we set/unset
73 its bit. Obviously, we do this @BitSet@ thing for efficiency
76 The @RegAllocInfo@ module collects together the machine-specific
77 info needed to do register allocation.
82 writeRealAsm :: Handle -> AbstractC -> UniqSupply -> IO ()
83 writeRealAsm handle absC us
84 = _scc_ "writeRealAsm" (printDoc LeftMode handle (runNCG absC us))
86 dumpRealAsm :: AbstractC -> UniqSupply -> String
87 dumpRealAsm absC us = show (runNCG absC us)
90 = genCodeAbstractC absC `thenUs` \ treelists ->
92 stix = map (map genericOpt) treelists
97 @codeGen@ is the top-level code-generation function:
99 codeGen :: [[StixTree]] -> UniqSM Doc
102 = mapUs genMachCode trees `thenUs` \ dynamic_codes ->
104 static_instrs = scheduleMachCode dynamic_codes
106 returnUs (vcat (map pprInstr static_instrs))
109 Top level code generator for a chunk of stix code:
111 genMachCode :: [StixTree] -> UniqSM InstrList
114 = mapUs stmt2Instrs stmts `thenUs` \ blocks ->
115 returnUs (foldr (.) id blocks asmVoid)
118 The next bit does the code scheduling. The scheduler must also deal
119 with register allocation of temporaries. Much parallelism can be
120 exposed via the OrdList, but more might occur, so further analysis
124 scheduleMachCode :: [InstrList] -> [Instr]
127 = concat . map (runRegAllocate freeRegsState reservedRegs)
129 freeRegsState = mkMRegsState (extractMappedRegNos freeRegs)
132 %************************************************************************
134 \subsection[NCOpt]{The Generic Optimiser}
136 %************************************************************************
138 This is called between translating Abstract C to its Tree and actually
139 using the Native Code Generator to generate the annotations. It's a
140 chance to do some strength reductions.
142 ** Remember these all have to be machine independent ***
144 Note that constant-folding should have already happened, but we might
145 have introduced some new opportunities for constant-folding wrt
146 address manipulations.
149 genericOpt :: StixTree -> StixTree
152 For most nodes, just optimize the children.
155 genericOpt (StInd pk addr) = StInd pk (genericOpt addr)
157 genericOpt (StAssign pk dst src)
158 = StAssign pk (genericOpt dst) (genericOpt src)
160 genericOpt (StJump addr) = StJump (genericOpt addr)
162 genericOpt (StCondJump addr test)
163 = StCondJump addr (genericOpt test)
165 genericOpt (StCall fn pk args)
166 = StCall fn pk (map genericOpt args)
169 Fold indices together when the types match:
171 genericOpt (StIndex pk (StIndex pk' base off) off')
173 = StIndex pk (genericOpt base)
174 (genericOpt (StPrim IntAddOp [off, off']))
176 genericOpt (StIndex pk base off)
177 = StIndex pk (genericOpt base) (genericOpt off)
180 For PrimOps, we first optimize the children, and then we try our hand
181 at some constant-folding.
184 genericOpt (StPrim op args) = primOpt op (map genericOpt args)
187 Replace register leaves with appropriate StixTrees for the given
191 genericOpt leaf@(StReg (StixMagicId id))
192 = case (stgReg id) of
193 Always tree -> genericOpt tree
196 genericOpt other = other
199 Now, try to constant-fold the PrimOps. The arguments have already
200 been optimized and folded.
204 :: PrimOp -- The operation from an StPrim
205 -> [StixTree] -- The optimized arguments
208 primOpt op arg@[StInt x]
210 IntNegOp -> StInt (-x)
211 IntAbsOp -> StInt (abs x)
214 primOpt op args@[StInt x, StInt y]
216 CharGtOp -> StInt (if x > y then 1 else 0)
217 CharGeOp -> StInt (if x >= y then 1 else 0)
218 CharEqOp -> StInt (if x == y then 1 else 0)
219 CharNeOp -> StInt (if x /= y then 1 else 0)
220 CharLtOp -> StInt (if x < y then 1 else 0)
221 CharLeOp -> StInt (if x <= y then 1 else 0)
222 IntAddOp -> StInt (x + y)
223 IntSubOp -> StInt (x - y)
224 IntMulOp -> StInt (x * y)
225 IntQuotOp -> StInt (x `quot` y)
226 IntRemOp -> StInt (x `rem` y)
227 IntGtOp -> StInt (if x > y then 1 else 0)
228 IntGeOp -> StInt (if x >= y then 1 else 0)
229 IntEqOp -> StInt (if x == y then 1 else 0)
230 IntNeOp -> StInt (if x /= y then 1 else 0)
231 IntLtOp -> StInt (if x < y then 1 else 0)
232 IntLeOp -> StInt (if x <= y then 1 else 0)
236 When possible, shift the constants to the right-hand side, so that we
237 can match for strength reductions. Note that the code generator will
238 also assume that constants have been shifted to the right when
242 primOpt op [x@(StInt _), y] | commutableOp op = primOpt op [y, x]
245 We can often do something with constants of 0 and 1 ...
248 primOpt op args@[x, y@(StInt 0)]
263 primOpt op args@[x, y@(StInt 1)]
271 Now look for multiplication/division by powers of 2 (integers).
274 primOpt op args@[x, y@(StInt n)]
276 IntMulOp -> case exactLog2 n of
277 Nothing -> StPrim op args
278 Just p -> StPrim SllOp [x, StInt p]
279 IntQuotOp -> case exactLog2 n of
280 Nothing -> StPrim op args
281 Just p -> StPrim SraOp [x, StInt p]
285 Anything else is just too hard.
288 primOpt op args = StPrim op args