2 % (c) The University of Glasgow 2000
4 \section[ByteCodeItbls]{Generate infotables for interpreter-made bytecodes}
7 module ByteCodeItbls ( ItblEnv, mkITbls ) where
9 #include "HsVersions.h"
11 import Name ( Name, getName )
12 import FiniteMap ( FiniteMap, listToFM, emptyFM, plusFM )
13 import Type ( typePrimRep )
14 import DataCon ( DataCon, dataConRepArgTys )
15 import TyCon ( TyCon, tyConFamilySize, isDataTyCon, tyConDataCons )
16 import Constants ( mIN_SIZE_NonUpdHeapObject )
17 import ClosureInfo ( mkVirtHeapOffsets )
18 import FastString ( FastString(..) )
20 import Foreign ( Storable(..), Word8, Word16, Word32, Ptr(..),
21 malloc, castPtr, plusPtr )
22 import Addr ( addrToInt )
23 import Bits ( Bits(..), shiftR )
25 import PrelBase ( Int(..) )
26 import PrelAddr ( Addr(..) )
27 import PrelIOBase ( IO(..) )
31 %************************************************************************
33 \subsection{Manufacturing of info tables for DataCons}
35 %************************************************************************
39 type ItblEnv = FiniteMap Name (Ptr StgInfoTable)
41 #if __GLASGOW_HASKELL__ <= 408
44 type ItblPtr = Ptr StgInfoTable
47 -- Make info tables for the data decls in this module
48 mkITbls :: [TyCon] -> IO ItblEnv
49 mkITbls [] = return emptyFM
50 mkITbls (tc:tcs) = do itbls <- mkITbl tc
52 return (itbls `plusFM` itbls2)
54 mkITbl :: TyCon -> IO ItblEnv
56 | not (isDataTyCon tc)
58 | n == length dcs -- paranoia; this is an assertion.
59 = make_constr_itbls dcs
61 dcs = tyConDataCons tc
62 n = tyConFamilySize tc
65 cONSTR = 1 -- as defined in ghc/includes/ClosureTypes.h
67 -- Assumes constructors are numbered from zero, not one
68 make_constr_itbls :: [DataCon] -> IO ItblEnv
69 make_constr_itbls cons
71 = do is <- mapM mk_vecret_itbl (zip cons [0..])
74 = do is <- mapM mk_dirret_itbl (zip cons [0..])
77 mk_vecret_itbl (dcon, conNo)
78 = mk_itbl dcon conNo (vecret_entry conNo)
79 mk_dirret_itbl (dcon, conNo)
80 = mk_itbl dcon conNo stg_interp_constr_entry
82 mk_itbl :: DataCon -> Int -> Addr -> IO (Name,ItblPtr)
83 mk_itbl dcon conNo entry_addr
84 = let (tot_wds, ptr_wds, _)
85 = mkVirtHeapOffsets typePrimRep (dataConRepArgTys dcon)
87 nptrs = tot_wds - ptr_wds
89 | ptrs + nptrs >= mIN_SIZE_NonUpdHeapObject = nptrs
90 | otherwise = mIN_SIZE_NonUpdHeapObject - ptrs
92 ptrs = fromIntegral ptrs,
93 nptrs = fromIntegral nptrs_really,
94 tipe = fromIntegral cONSTR,
95 srtlen = fromIntegral conNo,
96 code0 = fromIntegral code0, code1 = fromIntegral code1,
97 code2 = fromIntegral code2, code3 = fromIntegral code3,
98 code4 = fromIntegral code4, code5 = fromIntegral code5,
99 code6 = fromIntegral code6, code7 = fromIntegral code7
101 -- Make a piece of code to jump to "entry_label".
102 -- This is the only arch-dependent bit.
103 -- On x86, if entry_label has an address 0xWWXXYYZZ,
104 -- emit movl $0xWWXXYYZZ,%eax ; jmp *%eax
106 -- B8 ZZ YY XX WW FF E0
107 (code0,code1,code2,code3,code4,code5,code6,code7)
108 = (0xB8, byte 0 entry_addr_w, byte 1 entry_addr_w,
109 byte 2 entry_addr_w, byte 3 entry_addr_w,
113 entry_addr_w :: Word32
114 entry_addr_w = fromIntegral (addrToInt entry_addr)
117 --putStrLn ("SIZE of itbl is " ++ show (sizeOf itbl))
118 --putStrLn ("# ptrs of itbl is " ++ show ptrs)
119 --putStrLn ("# nptrs of itbl is " ++ show nptrs_really)
121 return (getName dcon, addr `plusPtr` 8)
124 byte :: Int -> Word32 -> Word32
125 byte 0 w = w .&. 0xFF
126 byte 1 w = (w `shiftR` 8) .&. 0xFF
127 byte 2 w = (w `shiftR` 16) .&. 0xFF
128 byte 3 w = (w `shiftR` 24) .&. 0xFF
131 vecret_entry 0 = stg_interp_constr1_entry
132 vecret_entry 1 = stg_interp_constr2_entry
133 vecret_entry 2 = stg_interp_constr3_entry
134 vecret_entry 3 = stg_interp_constr4_entry
135 vecret_entry 4 = stg_interp_constr5_entry
136 vecret_entry 5 = stg_interp_constr6_entry
137 vecret_entry 6 = stg_interp_constr7_entry
138 vecret_entry 7 = stg_interp_constr8_entry
140 -- entry point for direct returns for created constr itbls
141 foreign label "stg_interp_constr_entry" stg_interp_constr_entry :: Addr
142 -- and the 8 vectored ones
143 foreign label "stg_interp_constr1_entry" stg_interp_constr1_entry :: Addr
144 foreign label "stg_interp_constr2_entry" stg_interp_constr2_entry :: Addr
145 foreign label "stg_interp_constr3_entry" stg_interp_constr3_entry :: Addr
146 foreign label "stg_interp_constr4_entry" stg_interp_constr4_entry :: Addr
147 foreign label "stg_interp_constr5_entry" stg_interp_constr5_entry :: Addr
148 foreign label "stg_interp_constr6_entry" stg_interp_constr6_entry :: Addr
149 foreign label "stg_interp_constr7_entry" stg_interp_constr7_entry :: Addr
150 foreign label "stg_interp_constr8_entry" stg_interp_constr8_entry :: Addr
156 -- Ultra-minimalist version specially for constructors
157 data StgInfoTable = StgInfoTable {
162 code0, code1, code2, code3, code4, code5, code6, code7 :: Word8
166 instance Storable StgInfoTable where
169 = (sum . map (\f -> f itbl))
170 [fieldSz ptrs, fieldSz nptrs, fieldSz srtlen, fieldSz tipe,
171 fieldSz code0, fieldSz code1, fieldSz code2, fieldSz code3,
172 fieldSz code4, fieldSz code5, fieldSz code6, fieldSz code7]
175 = (sum . map (\f -> f itbl))
176 [fieldAl ptrs, fieldAl nptrs, fieldAl srtlen, fieldAl tipe,
177 fieldAl code0, fieldAl code1, fieldAl code2, fieldAl code3,
178 fieldAl code4, fieldAl code5, fieldAl code6, fieldAl code7]
181 = do a1 <- store (ptrs itbl) (castPtr a0)
182 a2 <- store (nptrs itbl) a1
183 a3 <- store (tipe itbl) a2
184 a4 <- store (srtlen itbl) a3
185 a5 <- store (code0 itbl) a4
186 a6 <- store (code1 itbl) a5
187 a7 <- store (code2 itbl) a6
188 a8 <- store (code3 itbl) a7
189 a9 <- store (code4 itbl) a8
190 aA <- store (code5 itbl) a9
191 aB <- store (code6 itbl) aA
192 aC <- store (code7 itbl) aB
196 = do (a1,ptrs) <- load (castPtr a0)
197 (a2,nptrs) <- load a1
199 (a4,srtlen) <- load a3
200 (a5,code0) <- load a4
201 (a6,code1) <- load a5
202 (a7,code2) <- load a6
203 (a8,code3) <- load a7
204 (a9,code4) <- load a8
205 (aA,code5) <- load a9
206 (aB,code6) <- load aA
207 (aC,code7) <- load aB
208 return StgInfoTable { ptrs = ptrs, nptrs = nptrs,
209 srtlen = srtlen, tipe = tipe,
210 code0 = code0, code1 = code1, code2 = code2,
211 code3 = code3, code4 = code4, code5 = code5,
212 code6 = code6, code7 = code7 }
214 fieldSz :: (Storable a, Storable b) => (a -> b) -> a -> Int
215 fieldSz sel x = sizeOf (sel x)
217 fieldAl :: (Storable a, Storable b) => (a -> b) -> a -> Int
218 fieldAl sel x = alignment (sel x)
220 store :: Storable a => a -> Ptr a -> IO (Ptr b)
221 store x addr = do poke addr x
222 return (castPtr (addr `plusPtr` sizeOf x))
224 load :: Storable a => Ptr a -> IO (Ptr b, a)
225 load addr = do x <- peek addr
226 return (castPtr (addr `plusPtr` sizeOf x), x)