2 % (c) The AQUA Project, Glasgow University, 1993-1998
7 CodeSegment(..), StixReg(..), StixTree(..), StixTreeList,
8 sStLitLbl, pprStixTrees, ppStixTree, ppStixReg,
9 stixCountTempUses, stixSubst,
11 stgBaseReg, stgNode, stgSp, stgSu, stgSpLim,
12 stgHp, stgHpLim, stgTagReg, stgR9, stgR10,
14 fixedHS, arrWordsHS, arrPtrsHS,
16 NatM, initNat, thenNat, returnNat,
17 mapNat, mapAndUnzipNat,
18 getUniqueNat, getDeltaNat, setDeltaNat,
19 NatM_State, mkNatM_State,
20 uniqOfNatM_State, deltaOfNatM_State,
22 getUniqLabelNCG, getNatLabelNCG,
25 #include "HsVersions.h"
27 import Ratio ( Rational )
29 import AbsCSyn ( node, tagreg, MagicId(..) )
30 import AbsCUtils ( magicIdPrimRep )
31 import CallConv ( CallConv, pprCallConv )
32 import CLabel ( mkAsmTempLabel, CLabel, pprCLabel, pprCLabel_asm )
33 import PrimRep ( PrimRep(..), showPrimRep )
34 import PrimOp ( PrimOp, pprPrimOp )
35 import Unique ( Unique )
36 import SMRep ( fixedHdrSize, arrWordsHdrSize, arrPtrsHdrSize )
37 import UniqSupply ( UniqSupply, splitUniqSupply, uniqFromSupply,
38 UniqSM, thenUs, returnUs, getUniqueUs )
42 Here is the tag at the nodes of our @StixTree@. Notice its
43 relationship with @PrimOp@ in prelude/PrimOp.
47 = -- Segment (text or data)
51 -- We can tag the leaves with constants/immediates.
53 | StInt Integer -- ** add Kind at some point
55 | StString FAST_STRING
56 | StLitLbl SDoc -- literal labels
57 -- (will be _-prefixed on some machines)
59 | StCLbl CLabel -- labels that we might index into
61 -- Abstract registers of various kinds
65 -- A typed offset from a base location
67 | StIndex PrimRep StixTree StixTree -- kind, base, offset
69 -- An indirection from an address to its contents.
71 | StInd PrimRep StixTree
73 -- Assignment is typed to determine size and register placement
75 | StAssign PrimRep StixTree StixTree -- dst, src
77 -- A simple assembly label that we might jump to.
81 -- A function header and footer
86 -- An unconditional jump. This instruction is terminal.
87 -- Dynamic targets are allowed
91 -- A fall-through, from slow to fast
93 | StFallThrough CLabel
95 -- A conditional jump. This instruction can be non-terminal :-)
96 -- Only static, local, forward labels are allowed
98 | StCondJump CLabel StixTree
100 -- Raw data (as in an info table).
102 | StData PrimRep [StixTree]
104 -- Primitive Operations
106 | StPrim PrimOp [StixTree]
108 -- Calls to C functions
110 | StCall FAST_STRING CallConv PrimRep [StixTree]
112 -- A volatile memory scratch array, which is allocated
113 -- relative to the stack pointer. It is an array of
114 -- ptr/word/int sized things. Do not expect to be preserved
115 -- beyond basic blocks or over a ccall. Current max size
116 -- is 6, used in StixInteger.
120 -- Assembly-language comments
122 | StComment FAST_STRING
124 sStLitLbl :: FAST_STRING -> StixTree
125 sStLitLbl s = StLitLbl (ptext s)
128 pprStixTrees :: [StixTree] -> SDoc
131 vcat (map ppStixTree ts),
136 paren t = char '(' <> t <> char ')'
138 ppStixTree :: StixTree -> SDoc
141 StSegment cseg -> paren (ppCodeSegment cseg)
142 StInt i -> paren (integer i)
143 StDouble rat -> paren (text "Double" <+> rational rat)
144 StString str -> paren (text "Str" <+> ptext str)
145 StComment str -> paren (text "Comment" <+> ptext str)
147 StCLbl lbl -> pprCLabel lbl
148 StReg reg -> ppStixReg reg
149 StIndex k b o -> paren (ppStixTree b <+> char '+' <>
150 pprPrimRep k <+> ppStixTree o)
151 StInd k t -> pprPrimRep k <> char '[' <> ppStixTree t <> char ']'
152 StAssign k d s -> ppStixTree d <> text " :=" <> pprPrimRep k
153 <> text " " <> ppStixTree s
154 StLabel ll -> pprCLabel ll <+> char ':'
155 StFunBegin ll -> char ' ' $$ paren (text "FunBegin" <+> pprCLabel ll)
156 StFunEnd ll -> paren (text "FunEnd" <+> pprCLabel ll)
157 StJump t -> paren (text "Jump" <+> ppStixTree t)
158 StFallThrough ll -> paren (text "FallThru" <+> pprCLabel ll)
159 StCondJump l t -> paren (text "JumpC" <+> pprCLabel l
161 StData k ds -> paren (text "Data" <+> pprPrimRep k <+>
162 hsep (map ppStixTree ds))
163 StPrim op ts -> paren (text "Prim" <+> pprPrimOp op <+>
164 hsep (map ppStixTree ts))
166 -> paren (text "Call" <+> ptext nm <+>
167 pprCallConv cc <+> pprPrimRep k <+>
168 hsep (map ppStixTree args))
169 StScratchWord i -> text "ScratchWord" <> paren (int i)
171 pprPrimRep = text . showPrimRep
174 Stix registers can have two forms. They {\em may} or {\em may not}
175 map to real, machine-level registers.
179 = StixMagicId MagicId -- Regs which are part of the abstract machine model
181 | StixTemp Unique PrimRep -- "Regs" which model local variables (CTemps) in
184 ppStixReg (StixMagicId mid)
186 ppStixReg (StixTemp u pr)
187 = hcat [text "Temp(", ppr u, ppr pr, char ')']
190 ppMId BaseReg = text "BaseReg"
191 ppMId (VanillaReg kind n) = hcat [pprPrimRep kind, text "IntReg(",
192 int (I# n), char ')']
193 ppMId (FloatReg n) = hcat [text "FltReg(", int (I# n), char ')']
194 ppMId (DoubleReg n) = hcat [text "DblReg(", int (I# n), char ')']
195 ppMId (LongReg kind n) = hcat [pprPrimRep kind, text "LongReg(",
196 int (I# n), char ')']
199 ppMId SpLim = text "SpLim"
201 ppMId HpLim = text "HpLim"
202 ppMId CurCostCentre = text "CCC"
203 ppMId VoidReg = text "VoidReg"
206 We hope that every machine supports the idea of data segment and text
207 segment (or that it has no segments at all, and we can lump these
211 data CodeSegment = DataSegment | TextSegment deriving (Eq, Show)
212 ppCodeSegment = text . show
214 type StixTreeList = [StixTree] -> [StixTree]
217 Stix Trees for STG registers:
219 stgBaseReg, stgNode, stgSp, stgSu, stgSpLim, stgHp, stgHpLim
222 stgBaseReg = StReg (StixMagicId BaseReg)
223 stgNode = StReg (StixMagicId node)
224 stgTagReg = StReg (StixMagicId tagreg)
225 stgSp = StReg (StixMagicId Sp)
226 stgSu = StReg (StixMagicId Su)
227 stgSpLim = StReg (StixMagicId SpLim)
228 stgHp = StReg (StixMagicId Hp)
229 stgHpLim = StReg (StixMagicId HpLim)
230 stgR9 = StReg (StixMagicId (VanillaReg WordRep ILIT(9)))
231 stgR10 = StReg (StixMagicId (VanillaReg WordRep ILIT(10)))
233 getNatLabelNCG :: NatM CLabel
235 = getUniqueNat `thenNat` \ u ->
236 returnNat (mkAsmTempLabel u)
238 getUniqLabelNCG :: UniqSM CLabel
240 = getUniqueUs `thenUs` \ u ->
241 returnUs (mkAsmTempLabel u)
243 fixedHS = StInt (toInteger fixedHdrSize)
244 arrWordsHS = StInt (toInteger arrWordsHdrSize)
245 arrPtrsHS = StInt (toInteger arrPtrsHdrSize)
248 Stix optimisation passes may wish to find out how many times a
249 given temporary appears in a tree, so as to be able to decide
250 whether or not to inline the assignment's RHS at usage site(s).
253 stixCountTempUses :: Unique -> StixTree -> Int
254 stixCountTempUses u t
255 = let qq = stixCountTempUses u
260 StixTemp uu pr -> if u == uu then 1 else 0
263 StIndex pk t1 t2 -> qq t1 + qq t2
265 StAssign pk t1 t2 -> qq t1 + qq t2
267 StCondJump lbl t1 -> qq t1
268 StData pk ts -> sum (map qq ts)
269 StPrim op ts -> sum (map qq ts)
270 StCall nm cconv pk ts -> sum (map qq ts)
286 stixSubst :: Unique -> StixTree -> StixTree -> StixTree
287 stixSubst u new_u in_this_tree
288 = stixMapUniques f in_this_tree
290 f :: Unique -> Maybe StixTree
291 f uu = if uu == u then Just new_u else Nothing
294 stixMapUniques :: (Unique -> Maybe StixTree) -> StixTree -> StixTree
296 = let qq = stixMapUniques f
307 StIndex pk t1 t2 -> StIndex pk (qq t1) (qq t2)
308 StInd pk t1 -> StInd pk (qq t1)
309 StAssign pk t1 t2 -> StAssign pk (qq t1) (qq t2)
310 StJump t1 -> StJump (qq t1)
311 StCondJump lbl t1 -> StCondJump lbl (qq t1)
312 StData pk ts -> StData pk (map qq ts)
313 StPrim op ts -> StPrim op (map qq ts)
314 StCall nm cconv pk ts -> StCall nm cconv pk (map qq ts)
331 data NatM_State = NatM_State UniqSupply Int
332 type NatM result = NatM_State -> (result, NatM_State)
334 mkNatM_State :: UniqSupply -> Int -> NatM_State
335 mkNatM_State = NatM_State
337 uniqOfNatM_State (NatM_State us delta) = us
338 deltaOfNatM_State (NatM_State us delta) = delta
341 initNat :: NatM_State -> NatM a -> (a, NatM_State)
342 initNat init_st m = case m init_st of { (r,st) -> (r,st) }
344 thenNat :: NatM a -> (a -> NatM b) -> NatM b
346 = case expr st of { (result, st') -> cont result st' }
348 returnNat :: a -> NatM a
349 returnNat result st = (result, st)
351 mapNat :: (a -> NatM b) -> [a] -> NatM [b]
352 mapNat f [] = returnNat []
354 = f x `thenNat` \ r ->
355 mapNat f xs `thenNat` \ rs ->
358 mapAndUnzipNat :: (a -> NatM (b,c)) -> [a] -> NatM ([b],[c])
359 mapAndUnzipNat f [] = returnNat ([],[])
360 mapAndUnzipNat f (x:xs)
361 = f x `thenNat` \ (r1, r2) ->
362 mapAndUnzipNat f xs `thenNat` \ (rs1, rs2) ->
363 returnNat (r1:rs1, r2:rs2)
366 getUniqueNat :: NatM Unique
367 getUniqueNat (NatM_State us delta)
368 = case splitUniqSupply us of
369 (us1,us2) -> (uniqFromSupply us1, (NatM_State us2 delta))
371 getDeltaNat :: NatM Int
372 getDeltaNat st@(NatM_State us delta)
375 setDeltaNat :: Int -> NatM ()
376 setDeltaNat delta (NatM_State us _)
377 = ((), NatM_State us delta)