2 % (c) The AQUA Project, Glasgow University, 1993-1998
6 module AsmCodeGen ( nativeCodeGen ) where
8 #include "HsVersions.h"
9 #include "nativeGen/NCG.h"
12 import List ( intersperse )
19 import AbsCStixGen ( genCodeAbstractC )
20 import AbsCSyn ( AbstractC, MagicId )
21 import AsmRegAlloc ( runRegAllocate )
22 import OrdList ( OrdList )
23 import PrimOp ( commutableOp, PrimOp(..) )
24 import RegAllocInfo ( mkMRegsState, MRegsState )
25 import Stix ( StixTree(..), StixReg(..),
26 pprStixTrees, CodeSegment(..) )
27 import PrimRep ( isFloatingRep, PrimRep(..) )
28 import UniqSupply ( returnUs, thenUs, mapUs, initUs,
29 initUs_, UniqSM, UniqSupply )
30 import UniqFM ( UniqFM, emptyUFM, addToUFM, lookupUFM )
31 import MachMisc ( IF_ARCH_i386(i386_insert_ffrees,) )
37 The 96/03 native-code generator has machine-independent and
38 machine-dependent modules (those \tr{#include}'ing \tr{NCG.h}).
40 This module (@AsmCodeGen@) is the top-level machine-independent
41 module. It uses @AbsCStixGen.genCodeAbstractC@ to produce @StixTree@s
42 (defined in module @Stix@), using support code from @StixInfo@ (info
43 tables), @StixPrim@ (primitive operations), @StixMacro@ (Abstract C
44 macros), and @StixInteger@ (GMP arbitrary-precision operations).
46 Before entering machine-dependent land, we do some machine-independent
47 @genericOpt@imisations (defined below) on the @StixTree@s.
49 We convert to the machine-specific @Instr@ datatype with
50 @stmt2Instrs@, assuming an ``infinite'' supply of registers. We then
51 use a machine-independent register allocator (@runRegAllocate@) to
52 rejoin reality. Obviously, @runRegAllocate@ has machine-specific
53 helper functions (see about @RegAllocInfo@ below).
55 The machine-dependent bits break down as follows:
57 \item[@MachRegs@:] Everything about the target platform's machine
58 registers (and immediate operands, and addresses, which tend to
59 intermingle/interact with registers).
61 \item[@MachMisc@:] Includes the @Instr@ datatype (possibly should
62 have a module of its own), plus a miscellany of other things
63 (e.g., @targetDoubleSize@, @smStablePtrTable@, ...)
65 \item[@MachCode@:] @stmt2Instrs@ is where @Stix@ stuff turns into
68 \item[@PprMach@:] @pprInstr@ turns an @Instr@ into text (well, really
71 \item[@RegAllocInfo@:] In the register allocator, we manipulate
72 @MRegsState@s, which are @BitSet@s, one bit per machine register.
73 When we want to say something about a specific machine register
74 (e.g., ``it gets clobbered by this instruction''), we set/unset
75 its bit. Obviously, we do this @BitSet@ thing for efficiency
78 The @RegAllocInfo@ module collects together the machine-specific
79 info needed to do register allocation.
85 nativeCodeGen :: AbstractC -> UniqSupply -> (SDoc, SDoc)
87 = let (stixRaw, us1) = initUs us (genCodeAbstractC absC)
88 stixOpt = map (map genericOpt) stixRaw
89 insns = initUs_ us1 (codeGen stixOpt)
90 debug_stix = vcat (map pprStixTrees stixOpt)
95 @codeGen@ is the top-level code-generation function:
97 codeGen :: [[StixTree]] -> UniqSM SDoc
100 = mapUs genMachCode stixFinal `thenUs` \ dynamic_codes ->
102 fp_kludge :: [Instr] -> [Instr]
103 fp_kludge = IF_ARCH_i386(i386_insert_ffrees,id)
105 static_instrss :: [[Instr]]
106 static_instrss = map fp_kludge (scheduleMachCode dynamic_codes)
107 docs = map (vcat . map pprInstr) static_instrss
109 returnUs (vcat (intersperse (char ' '
110 $$ text "# ___stg_split_marker"
115 Top level code generator for a chunk of stix code:
117 genMachCode :: [StixTree] -> UniqSM InstrList
120 = mapUs stmt2Instrs stmts `thenUs` \ blocks ->
121 returnUs (foldr (.) id blocks asmVoid)
124 The next bit does the code scheduling. The scheduler must also deal
125 with register allocation of temporaries. Much parallelism can be
126 exposed via the OrdList, but more might occur, so further analysis
130 scheduleMachCode :: [InstrList] -> [[Instr]]
133 = map (runRegAllocate freeRegsState reservedRegs)
135 freeRegsState = mkMRegsState (extractMappedRegNos freeRegs)
138 %************************************************************************
140 \subsection[NCOpt]{The Generic Optimiser}
142 %************************************************************************
144 This is called between translating Abstract C to its Tree and actually
145 using the Native Code Generator to generate the annotations. It's a
146 chance to do some strength reductions.
148 ** Remember these all have to be machine independent ***
150 Note that constant-folding should have already happened, but we might
151 have introduced some new opportunities for constant-folding wrt
152 address manipulations.
155 genericOpt :: StixTree -> StixTree
158 For most nodes, just optimize the children.
161 genericOpt (StInd pk addr) = StInd pk (genericOpt addr)
163 genericOpt (StAssign pk dst src)
164 = StAssign pk (genericOpt dst) (genericOpt src)
166 genericOpt (StJump addr) = StJump (genericOpt addr)
168 genericOpt (StCondJump addr test)
169 = StCondJump addr (genericOpt test)
171 genericOpt (StCall fn cconv pk args)
172 = StCall fn cconv pk (map genericOpt args)
175 Fold indices together when the types match:
177 genericOpt (StIndex pk (StIndex pk' base off) off')
179 = StIndex pk (genericOpt base)
180 (genericOpt (StPrim IntAddOp [off, off']))
182 genericOpt (StIndex pk base off)
183 = StIndex pk (genericOpt base) (genericOpt off)
186 For PrimOps, we first optimize the children, and then we try our hand
187 at some constant-folding.
190 genericOpt (StPrim op args) = primOpt op (map genericOpt args)
193 Replace register leaves with appropriate StixTrees for the given
197 genericOpt leaf@(StReg (StixMagicId id))
198 = case (stgReg id) of
199 Always tree -> genericOpt tree
202 genericOpt other = other
205 Now, try to constant-fold the PrimOps. The arguments have already
206 been optimized and folded.
210 :: PrimOp -- The operation from an StPrim
211 -> [StixTree] -- The optimized arguments
214 primOpt op arg@[StInt x]
216 IntNegOp -> StInt (-x)
219 primOpt op args@[StInt x, StInt y]
221 CharGtOp -> StInt (if x > y then 1 else 0)
222 CharGeOp -> StInt (if x >= y then 1 else 0)
223 CharEqOp -> StInt (if x == y then 1 else 0)
224 CharNeOp -> StInt (if x /= y then 1 else 0)
225 CharLtOp -> StInt (if x < y then 1 else 0)
226 CharLeOp -> StInt (if x <= y then 1 else 0)
227 IntAddOp -> StInt (x + y)
228 IntSubOp -> StInt (x - y)
229 IntMulOp -> StInt (x * y)
230 IntQuotOp -> StInt (x `quot` y)
231 IntRemOp -> StInt (x `rem` y)
232 IntGtOp -> StInt (if x > y then 1 else 0)
233 IntGeOp -> StInt (if x >= y then 1 else 0)
234 IntEqOp -> StInt (if x == y then 1 else 0)
235 IntNeOp -> StInt (if x /= y then 1 else 0)
236 IntLtOp -> StInt (if x < y then 1 else 0)
237 IntLeOp -> StInt (if x <= y then 1 else 0)
238 -- ToDo: WordQuotOp, WordRemOp.
242 When possible, shift the constants to the right-hand side, so that we
243 can match for strength reductions. Note that the code generator will
244 also assume that constants have been shifted to the right when
248 primOpt op [x@(StInt _), y] | commutableOp op = primOpt op [y, x]
251 We can often do something with constants of 0 and 1 ...
254 primOpt op args@[x, y@(StInt 0)]
269 primOpt op args@[x, y@(StInt 1)]
277 Now look for multiplication/division by powers of 2 (integers).
280 primOpt op args@[x, y@(StInt n)]
282 IntMulOp -> case exactLog2 n of
283 Nothing -> StPrim op args
284 Just p -> StPrim ISllOp [x, StInt p]
285 IntQuotOp -> case exactLog2 n of
286 Nothing -> StPrim op args
287 Just p -> StPrim ISrlOp [x, StInt p]
291 Anything else is just too hard.
294 primOpt op args = StPrim op args