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, flattenOrdList )
23 import PrimOp ( commutableOp, PrimOp(..) )
24 import RegAllocInfo ( mkMRegsState, MRegsState, findReservedRegs )
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 -- for debugging only
110 docs_prealloc = map (vcat . map pprInstr . flattenOrdList)
112 text_prealloc = vcat (intersperse (char ' ' $$ char ' ') docs_prealloc)
114 -- trace (showSDoc text_prealloc) (
115 returnUs (vcat (intersperse (char ' '
116 $$ text "# ___stg_split_marker"
122 Top level code generator for a chunk of stix code:
124 genMachCode :: [StixTree] -> UniqSM InstrList
127 = mapUs stmt2Instrs stmts `thenUs` \ blocks ->
128 returnUs (foldr (.) id blocks asmVoid)
131 The next bit does the code scheduling. The scheduler must also deal
132 with register allocation of temporaries. Much parallelism can be
133 exposed via the OrdList, but more might occur, so further analysis
137 scheduleMachCode :: [InstrList] -> [[Instr]]
140 = map (runRegAllocate freeRegsState findReservedRegs)
142 freeRegsState = mkMRegsState (extractMappedRegNos freeRegs)
145 %************************************************************************
147 \subsection[NCOpt]{The Generic Optimiser}
149 %************************************************************************
151 This is called between translating Abstract C to its Tree and actually
152 using the Native Code Generator to generate the annotations. It's a
153 chance to do some strength reductions.
155 ** Remember these all have to be machine independent ***
157 Note that constant-folding should have already happened, but we might
158 have introduced some new opportunities for constant-folding wrt
159 address manipulations.
162 genericOpt :: StixTree -> StixTree
165 For most nodes, just optimize the children.
168 genericOpt (StInd pk addr) = StInd pk (genericOpt addr)
170 genericOpt (StAssign pk dst src)
171 = StAssign pk (genericOpt dst) (genericOpt src)
173 genericOpt (StJump addr) = StJump (genericOpt addr)
175 genericOpt (StCondJump addr test)
176 = StCondJump addr (genericOpt test)
178 genericOpt (StCall fn cconv pk args)
179 = StCall fn cconv pk (map genericOpt args)
182 Fold indices together when the types match:
184 genericOpt (StIndex pk (StIndex pk' base off) off')
186 = StIndex pk (genericOpt base)
187 (genericOpt (StPrim IntAddOp [off, off']))
189 genericOpt (StIndex pk base off)
190 = StIndex pk (genericOpt base) (genericOpt off)
193 For PrimOps, we first optimize the children, and then we try our hand
194 at some constant-folding.
197 genericOpt (StPrim op args) = primOpt op (map genericOpt args)
200 Replace register leaves with appropriate StixTrees for the given
204 genericOpt leaf@(StReg (StixMagicId id))
205 = case (stgReg id) of
206 Always tree -> genericOpt tree
209 genericOpt other = other
212 Now, try to constant-fold the PrimOps. The arguments have already
213 been optimized and folded.
217 :: PrimOp -- The operation from an StPrim
218 -> [StixTree] -- The optimized arguments
221 primOpt op arg@[StInt x]
223 IntNegOp -> StInt (-x)
226 primOpt op args@[StInt x, StInt y]
228 CharGtOp -> StInt (if x > y then 1 else 0)
229 CharGeOp -> StInt (if x >= y then 1 else 0)
230 CharEqOp -> StInt (if x == y then 1 else 0)
231 CharNeOp -> StInt (if x /= y then 1 else 0)
232 CharLtOp -> StInt (if x < y then 1 else 0)
233 CharLeOp -> StInt (if x <= y then 1 else 0)
234 IntAddOp -> StInt (x + y)
235 IntSubOp -> StInt (x - y)
236 IntMulOp -> StInt (x * y)
237 IntQuotOp -> StInt (x `quot` y)
238 IntRemOp -> StInt (x `rem` y)
239 IntGtOp -> StInt (if x > y then 1 else 0)
240 IntGeOp -> StInt (if x >= y then 1 else 0)
241 IntEqOp -> StInt (if x == y then 1 else 0)
242 IntNeOp -> StInt (if x /= y then 1 else 0)
243 IntLtOp -> StInt (if x < y then 1 else 0)
244 IntLeOp -> StInt (if x <= y then 1 else 0)
245 -- ToDo: WordQuotOp, WordRemOp.
249 When possible, shift the constants to the right-hand side, so that we
250 can match for strength reductions. Note that the code generator will
251 also assume that constants have been shifted to the right when
255 primOpt op [x@(StInt _), y] | commutableOp op = primOpt op [y, x]
258 We can often do something with constants of 0 and 1 ...
261 primOpt op args@[x, y@(StInt 0)]
276 primOpt op args@[x, y@(StInt 1)]
284 Now look for multiplication/division by powers of 2 (integers).
287 primOpt op args@[x, y@(StInt n)]
289 IntMulOp -> case exactLog2 n of
290 Nothing -> StPrim op args
291 Just p -> StPrim ISllOp [x, StInt p]
292 IntQuotOp -> case exactLog2 n of
293 Nothing -> StPrim op args
294 Just p -> StPrim ISrlOp [x, StInt p]
298 Anything else is just too hard.
301 primOpt op args = StPrim op args