[project @ 2000-05-18 13:55:36 by sewardj]
[ghc-hetmet.git] / ghc / compiler / nativeGen / Stix.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1993-1998
3 %
4
5 \begin{code}
6 module Stix (
7         CodeSegment(..), StixReg(..), StixTree(..), StixTreeList,
8         pprStixTrees, pprStixTree, ppStixReg,
9         stixCountTempUses, stixSubst,
10
11         stgBaseReg, stgNode, stgSp, stgSu, stgSpLim, 
12         stgHp, stgHpLim, stgTagReg, stgR9, stgR10, 
13         stgCurrentTSO, stgCurrentNursery,
14
15         fixedHS, arrWordsHS, arrPtrsHS,
16
17         NatM, initNat, thenNat, returnNat, 
18         mapNat, mapAndUnzipNat, mapAccumLNat,
19         getUniqueNat, getDeltaNat, setDeltaNat,
20         NatM_State, mkNatM_State,
21         uniqOfNatM_State, deltaOfNatM_State,
22
23         getUniqLabelNCG, getNatLabelNCG,
24     ) where
25
26 #include "HsVersions.h"
27
28 import Ratio            ( Rational )
29
30 import AbsCSyn          ( node, tagreg, MagicId(..) )
31 import AbsCUtils        ( magicIdPrimRep )
32 import CallConv         ( CallConv, pprCallConv )
33 import CLabel           ( mkAsmTempLabel, CLabel, pprCLabel, pprCLabel_asm )
34 import PrimRep          ( PrimRep(..), showPrimRep )
35 import PrimOp           ( PrimOp, pprPrimOp )
36 import Unique           ( Unique )
37 import SMRep            ( fixedHdrSize, arrWordsHdrSize, arrPtrsHdrSize )
38 import UniqSupply       ( UniqSupply, splitUniqSupply, uniqFromSupply,
39                           UniqSM, thenUs, returnUs, getUniqueUs )
40 import CmdLineOpts      ( opt_Static )
41 import Outputable
42 \end{code}
43
44 Here is the tag at the nodes of our @StixTree@.  Notice its
45 relationship with @PrimOp@ in prelude/PrimOp.
46
47 \begin{code}
48 data StixTree
49   = -- Segment (text or data)
50
51     StSegment CodeSegment
52
53     -- We can tag the leaves with constants/immediates.
54
55   | StInt       Integer     -- ** add Kind at some point
56   | StDouble    Rational
57   | StString    FAST_STRING
58   | StCLbl      CLabel      -- labels that we might index into
59
60     -- Abstract registers of various kinds
61
62   | StReg StixReg
63
64     -- A typed offset from a base location
65
66   | StIndex PrimRep StixTree StixTree -- kind, base, offset
67
68     -- An indirection from an address to its contents.
69
70   | StInd PrimRep StixTree
71
72     -- Assignment is typed to determine size and register placement
73
74   | StAssign PrimRep StixTree StixTree -- dst, src
75
76     -- A simple assembly label that we might jump to.
77
78   | StLabel CLabel
79
80     -- A function header and footer
81
82   | StFunBegin CLabel
83   | StFunEnd CLabel
84
85     -- An unconditional jump. This instruction is terminal.
86     -- Dynamic targets are allowed
87
88   | StJump StixTree
89
90     -- A fall-through, from slow to fast
91
92   | StFallThrough CLabel
93
94     -- A conditional jump. This instruction can be non-terminal :-)
95     -- Only static, local, forward labels are allowed
96
97   | StCondJump CLabel StixTree
98
99     -- Raw data (as in an info table).
100
101   | StData PrimRep [StixTree]
102
103     -- Primitive Operations
104
105   | StPrim PrimOp [StixTree]
106
107     -- Calls to C functions
108
109   | StCall FAST_STRING CallConv PrimRep [StixTree]
110
111     -- A volatile memory scratch array, which is allocated
112     -- relative to the stack pointer.  It is an array of
113     -- ptr/word/int sized things.  Do not expect to be preserved
114     -- beyond basic blocks or over a ccall.  Current max size
115     -- is 6, used in StixInteger.
116
117   | StScratchWord Int
118
119     -- Assembly-language comments
120
121   | StComment FAST_STRING
122
123
124 pprStixTrees :: [StixTree] -> SDoc
125 pprStixTrees ts 
126   = vcat [
127        vcat (map pprStixTree ts),
128        char ' ',
129        char ' '
130     ]
131
132 paren t = char '(' <> t <> char ')'
133
134 pprStixTree :: StixTree -> SDoc
135 pprStixTree t 
136    = case t of
137        StSegment cseg   -> paren (ppCodeSegment cseg)
138        StInt i          -> paren (integer i)
139        StDouble rat     -> paren (text "Double" <+> rational rat)
140        StString str     -> paren (text "Str" <+> ptext str)
141        StComment str    -> paren (text "Comment" <+> ptext str)
142        StCLbl lbl       -> pprCLabel lbl
143        StReg reg        -> ppStixReg reg
144        StIndex k b o    -> paren (pprStixTree b <+> char '+' <> 
145                                   pprPrimRep k <+> pprStixTree o)
146        StInd k t        -> pprPrimRep k <> char '[' <> pprStixTree t <> char ']'
147        StAssign k d s   -> pprStixTree d <> text "  :=" <> pprPrimRep k 
148                                          <> text "  " <> pprStixTree s
149        StLabel ll       -> pprCLabel ll <+> char ':'
150        StFunBegin ll    -> char ' ' $$ paren (text "FunBegin" <+> pprCLabel ll)
151        StFunEnd ll      -> paren (text "FunEnd" <+> pprCLabel ll)
152        StJump t         -> paren (text "Jump" <+> pprStixTree t)
153        StFallThrough ll -> paren (text "FallThru" <+> pprCLabel ll)
154        StCondJump l t   -> paren (text "JumpC" <+> pprCLabel l 
155                                                <+> pprStixTree t)
156        StData k ds      -> paren (text "Data" <+> pprPrimRep k <+>
157                                   hsep (map pprStixTree ds))
158        StPrim op ts     -> paren (text "Prim" <+> pprPrimOp op <+> 
159                                   hsep (map pprStixTree ts))
160        StCall nm cc k args
161                         -> paren (text "Call" <+> ptext nm <+>
162                                   pprCallConv cc <+> pprPrimRep k <+> 
163                                   hsep (map pprStixTree args))
164        StScratchWord i  -> text "ScratchWord" <> paren (int i)
165
166 pprPrimRep = text . showPrimRep
167 \end{code}
168
169 Stix registers can have two forms.  They {\em may} or {\em may not}
170 map to real, machine-level registers.
171
172 \begin{code}
173 data StixReg
174   = StixMagicId MagicId -- Regs which are part of the abstract machine model
175
176   | StixTemp Unique PrimRep -- "Regs" which model local variables (CTemps) in
177                                         -- the abstract C.
178
179 ppStixReg (StixMagicId mid)
180    = ppMId mid
181 ppStixReg (StixTemp u pr)
182    = hcat [text "Temp(", ppr u, ppr pr, char ')']
183
184
185 ppMId BaseReg              = text "BaseReg"
186 ppMId (VanillaReg kind n)  = hcat [pprPrimRep kind, text "IntReg(", 
187                                    int (I# n), char ')']
188 ppMId (FloatReg n)         = hcat [text "FltReg(", int (I# n), char ')']
189 ppMId (DoubleReg n)        = hcat [text "DblReg(", int (I# n), char ')']
190 ppMId (LongReg kind n)     = hcat [pprPrimRep kind, text "LongReg(", 
191                                    int (I# n), char ')']
192 ppMId Sp                   = text "Sp"
193 ppMId Su                   = text "Su"
194 ppMId SpLim                = text "SpLim"
195 ppMId Hp                   = text "Hp"
196 ppMId HpLim                = text "HpLim"
197 ppMId CurCostCentre        = text "CCC"
198 ppMId VoidReg              = text "VoidReg"
199 \end{code}
200
201 We hope that every machine supports the idea of data segment and text
202 segment (or that it has no segments at all, and we can lump these
203 together).
204
205 \begin{code}
206 data CodeSegment = DataSegment | TextSegment deriving (Eq, Show)
207 ppCodeSegment = text . show
208
209 type StixTreeList = [StixTree] -> [StixTree]
210 \end{code}
211
212 Stix Trees for STG registers:
213 \begin{code}
214 stgBaseReg, stgNode, stgSp, stgSu, stgSpLim, stgHp, stgHpLim 
215         :: StixTree
216
217 stgBaseReg          = StReg (StixMagicId BaseReg)
218 stgNode             = StReg (StixMagicId node)
219 stgTagReg           = StReg (StixMagicId tagreg)
220 stgSp               = StReg (StixMagicId Sp)
221 stgSu               = StReg (StixMagicId Su)
222 stgSpLim            = StReg (StixMagicId SpLim)
223 stgHp               = StReg (StixMagicId Hp)
224 stgHpLim            = StReg (StixMagicId HpLim)
225 stgCurrentTSO       = StReg (StixMagicId CurrentTSO)
226 stgCurrentNursery   = StReg (StixMagicId CurrentNursery)
227 stgR9               = StReg (StixMagicId (VanillaReg WordRep ILIT(9)))
228 stgR10              = StReg (StixMagicId (VanillaReg WordRep ILIT(10)))
229
230 getNatLabelNCG :: NatM CLabel
231 getNatLabelNCG
232   = getUniqueNat `thenNat` \ u ->
233     returnNat (mkAsmTempLabel u)
234
235 getUniqLabelNCG :: UniqSM CLabel
236 getUniqLabelNCG
237   = getUniqueUs `thenUs` \ u ->
238     returnUs (mkAsmTempLabel u)
239
240 fixedHS     = StInt (toInteger fixedHdrSize)
241 arrWordsHS  = StInt (toInteger arrWordsHdrSize)
242 arrPtrsHS   = StInt (toInteger arrPtrsHdrSize)
243 \end{code}
244
245 Stix optimisation passes may wish to find out how many times a
246 given temporary appears in a tree, so as to be able to decide
247 whether or not to inline the assignment's RHS at usage site(s).
248
249 \begin{code}
250 stixCountTempUses :: Unique -> StixTree -> Int
251 stixCountTempUses u t 
252    = let qq = stixCountTempUses u
253      in
254      case t of
255         StReg reg
256            -> case reg of 
257                  StixTemp uu pr  -> if u == uu then 1 else 0
258                  StixMagicId mid -> 0
259
260         StIndex    pk t1 t2       -> qq t1 + qq t2
261         StInd      pk t1          -> qq t1
262         StAssign   pk t1 t2       -> qq t1 + qq t2
263         StJump     t1             -> qq t1
264         StCondJump lbl t1         -> qq t1
265         StData     pk ts          -> sum (map qq ts)
266         StPrim     op ts          -> sum (map qq ts)
267         StCall     nm cconv pk ts -> sum (map qq ts)
268
269         StSegment _      -> 0
270         StInt _          -> 0
271         StDouble _       -> 0
272         StString _       -> 0
273         StCLbl _         -> 0
274         StLabel _        -> 0
275         StFunBegin _     -> 0
276         StFunEnd _       -> 0
277         StFallThrough _  -> 0
278         StScratchWord _  -> 0
279         StComment _      -> 0
280
281
282 stixSubst :: Unique -> StixTree -> StixTree -> StixTree
283 stixSubst u new_u in_this_tree
284    = stixMapUniques f in_this_tree
285      where
286         f :: Unique -> Maybe StixTree
287         f uu = if uu == u then Just new_u else Nothing
288
289
290 stixMapUniques :: (Unique -> Maybe StixTree) -> StixTree -> StixTree
291 stixMapUniques f t
292    = let qq = stixMapUniques f
293      in
294      case t of
295         StReg reg
296            -> case reg of 
297                  StixMagicId mid -> t
298                  StixTemp uu pr  
299                     -> case f uu of
300                           Just xx -> xx
301                           Nothing -> t
302
303         StIndex    pk t1 t2       -> StIndex    pk (qq t1) (qq t2)
304         StInd      pk t1          -> StInd      pk (qq t1)
305         StAssign   pk t1 t2       -> StAssign   pk (qq t1) (qq t2)
306         StJump     t1             -> StJump     (qq t1)
307         StCondJump lbl t1         -> StCondJump lbl (qq t1)
308         StData     pk ts          -> StData     pk (map qq ts)
309         StPrim     op ts          -> StPrim     op (map qq ts)
310         StCall     nm cconv pk ts -> StCall     nm cconv pk (map qq ts)
311
312         StSegment _      -> t
313         StInt _          -> t
314         StDouble _       -> t
315         StString _       -> t
316         StCLbl _         -> t
317         StLabel _        -> t
318         StFunBegin _     -> t
319         StFunEnd _       -> t
320         StFallThrough _  -> t
321         StScratchWord _  -> t
322         StComment _      -> t
323 \end{code}
324
325 \begin{code}
326 data NatM_State = NatM_State UniqSupply Int
327 type NatM result = NatM_State -> (result, NatM_State)
328
329 mkNatM_State :: UniqSupply -> Int -> NatM_State
330 mkNatM_State = NatM_State
331
332 uniqOfNatM_State  (NatM_State us delta) = us
333 deltaOfNatM_State (NatM_State us delta) = delta
334
335
336 initNat :: NatM_State -> NatM a -> (a, NatM_State)
337 initNat init_st m = case m init_st of { (r,st) -> (r,st) }
338
339 thenNat :: NatM a -> (a -> NatM b) -> NatM b
340 thenNat expr cont st
341   = case expr st of { (result, st') -> cont result st' }
342
343 returnNat :: a -> NatM a
344 returnNat result st = (result, st)
345
346 mapNat :: (a -> NatM b) -> [a] -> NatM [b]
347 mapNat f []     = returnNat []
348 mapNat f (x:xs)
349   = f x          `thenNat` \ r  ->
350     mapNat f xs  `thenNat` \ rs ->
351     returnNat (r:rs)
352
353 mapAndUnzipNat :: (a -> NatM (b,c))   -> [a] -> NatM ([b],[c])
354 mapAndUnzipNat f [] = returnNat ([],[])
355 mapAndUnzipNat f (x:xs)
356   = f x                 `thenNat` \ (r1,  r2)  ->
357     mapAndUnzipNat f xs `thenNat` \ (rs1, rs2) ->
358     returnNat (r1:rs1, r2:rs2)
359
360 mapAccumLNat :: (acc -> x -> NatM (acc, y))
361                 -> acc
362                 -> [x]
363                 -> NatM (acc, [y])
364
365 mapAccumLNat f b []
366   = returnNat (b, [])
367 mapAccumLNat f b (x:xs)
368   = f b x                           `thenNat` \ (b__2, x__2) ->
369     mapAccumLNat f b__2 xs          `thenNat` \ (b__3, xs__2) ->
370     returnNat (b__3, x__2:xs__2)
371
372
373 getUniqueNat :: NatM Unique
374 getUniqueNat (NatM_State us delta)
375     = case splitUniqSupply us of
376          (us1,us2) -> (uniqFromSupply us1, (NatM_State us2 delta))
377
378 getDeltaNat :: NatM Int
379 getDeltaNat st@(NatM_State us delta)
380    = (delta, st)
381
382 setDeltaNat :: Int -> NatM ()
383 setDeltaNat delta (NatM_State us _)
384    = ((), NatM_State us delta)
385 \end{code}