bc45d80a5b53f7c3ad4e356be5c987582cc54fac
[hs-java.git] / JVM / Assembler.hs
1 {-# LANGUAGE TypeFamilies, StandaloneDeriving, FlexibleInstances, FlexibleContexts, UndecidableInstances, RecordWildCards, OverloadedStrings, TypeSynonymInstances, MultiParamTypeClasses #-}
2 module JVM.Assembler where
3
4 import Control.Monad
5 import Control.Applicative
6 import Data.Ix (inRange)
7 import Data.List
8 import Data.Word
9 import Data.Bits
10 import qualified Data.Binary as Binary
11 import qualified Data.Binary.Get as Get
12 import Data.Char
13 import Data.String
14 import qualified Data.ByteString.Lazy as B
15 import Data.Array
16 import qualified Data.Set as S
17 import qualified Data.Map as M
18
19 import Data.BinaryState
20 import JVM.Types
21
22 data IMM =
23     I0
24   | I1
25   | I2
26   | I3
27   deriving (Eq, Ord, Enum, Show)
28
29 data CMP =
30     C_EQ
31   | C_NE
32   | C_LT
33   | C_GE
34   | C_GT
35   | C_LE
36   deriving (Eq, Ord, Enum, Show)
37
38 newtype Code = Code [Instruction]
39   deriving (Eq, Show)
40
41 instance BinaryState Integer Code where
42   put (Code list) = forM_ list put
43
44   get = do
45     end <- isEmpty
46     if end
47       then return $ Code []
48       else do
49            x <- get
50            (Code next) <- get
51            return $ Code (x: next)
52
53 data Instruction =
54     NOP            -- 0
55   | ACONST_NULL    -- 1
56   | ICONST_M1      -- 2
57   | ICONST_0       -- 3
58   | ICONST_1       -- 4
59   | ICONST_2       -- 5
60   | ICONST_3       -- 6
61   | ICONST_4       -- 7
62   | ICONST_5       -- 8
63   | LCONST_0       -- 9
64   | LCONST_1       -- 10
65   | FCONST_0       -- 11
66   | FCONST_1       -- 12
67   | FCONST_2       -- 13
68   | DCONST_0       -- 14
69   | DCONST_1       -- 15
70   | BIPUSH Word8   -- 16
71   | SIPUSH Word16  -- 17
72   | LDC1 Word8     -- 18
73   | LDC2 Word16    -- 19
74   | LDC2W Word16   -- 20
75   | ILOAD Word8    -- 21
76   | LLOAD Word8    -- 22
77   | FLOAD Word8    -- 23
78   | DLOAD Word8    -- 24
79   | ALOAD Word8    -- 25
80   | ILOAD_ IMM     -- 26, 27, 28, 29
81   | LLOAD_ IMM     -- 30, 31, 32, 33
82   | FLOAD_ IMM     -- 34, 35, 36, 37
83   | DLOAD_ IMM     -- 38, 39, 40, 41
84   | ALOAD_ IMM     -- 42, 43, 44, 45
85   | IALOAD         -- 46
86   | LALOAD         -- 47
87   | FALOAD         -- 48
88   | DALOAD         -- 49
89   | AALOAD         -- 50
90   | BALOAD         -- 51
91   | CALOAD         -- 52
92   | SALOAD         -- 53
93   | ISTORE Word8   -- 54
94   | LSTORE Word8   -- 55
95   | FSTORE Word8   -- 56
96   | DSTORE Word8   -- 57
97   | ASTORE Word8   -- 58
98   | ISTORE_ IMM    -- 59, 60, 61, 62
99   | LSTORE_ IMM    -- 63, 64, 65, 66
100   | FSTORE_ IMM    -- 67, 68, 69, 70
101   | DSTORE_ IMM    -- 71, 72, 73, 74
102   | ASTORE_ IMM    -- 75, 76, 77, 78
103   | IASTORE        -- 79
104   | LASTORE        -- 80
105   | FASTORE        -- 81
106   | DASTORE        -- 82
107   | AASTORE        -- 83
108   | BASTORE        -- 84
109   | CASTORE        -- 85
110   | SASTORE        -- 86
111   | POP            -- 87
112   | POP2           -- 88
113   | DUP            -- 89
114   | DUP_X1         -- 90
115   | DUP_X2         -- 91
116   | DUP2           -- 92
117   | DUP2_X1        -- 93 
118   | DUP2_X2        -- 94
119   | SWAP           -- 95
120   | IADD           -- 96
121   | LADD           -- 97
122   | FADD           -- 98
123   | DADD           -- 99
124   | ISUB           -- 100
125   | LSUB           -- 101
126   | FSUB           -- 102
127   | DSUB           -- 103
128   | IMUL           -- 104
129   | LMUL           -- 105
130   | FMUL           -- 106
131   | DMUL           -- 107
132   | IDIV           -- 108
133   | LDIV           -- 109
134   | FDIV           -- 110
135   | DDIV           -- 111
136   | IREM           -- 112
137   | LREM           -- 113
138   | FREM           -- 114
139   | DREM           -- 115
140   | INEG           -- 116
141   | LNEG           -- 117
142   | FNEG           -- 118
143   | DNEG           -- 119
144   | ISHL           -- 120
145   | LSHL           -- 121
146   | ISHR           -- 122
147   | LSHR           -- 123
148   | IUSHR          -- 124
149   | LUSHR          -- 125
150   | IAND           -- 126
151   | LAND           -- 127
152   | IOR            -- 128
153   | LOR            -- 129
154   | IXOR           -- 130
155   | LXOR           -- 131
156   | IINC Word8 Word8       -- 132
157   | I2L                    -- 133
158   | I2F                    -- 134
159   | I2D                    -- 135
160   | L2I                    -- 136
161   | L2F                    -- 137
162   | L2D                    -- 138
163   | F2I                    -- 139
164   | F2L                    -- 140
165   | F2D                    -- 141
166   | D2I                    -- 142
167   | D2L                    -- 143
168   | D2F                    -- 144
169   | I2B                    -- 145
170   | I2C                    -- 146
171   | I2S                    -- 147
172   | LCMP                   -- 148
173   | FCMP CMP               -- 149, 150
174   | DCMP CMP               -- 151, 152
175   | IF CMP                 -- 153, 154, 155, 156, 157, 158
176   | IF_ACMP CMP Word16     -- 165, 166
177   | IF_ICMP CMP Word16     -- 159, 160, 161, 162, 163, 164
178   | GOTO                   -- 167
179   | JSR Word16             -- 168
180   | RET                    -- 169
181   | TABLESWITCH Word32 Word32 Word32 [Word32]     -- 170
182   | LOOKUPSWITCH Word32 Word32 [(Word32, Word32)] -- 171
183   | IRETURN                -- 172
184   | LRETURN                -- 173
185   | FRETURN                -- 174
186   | DRETURN                -- 175
187   | RETURN                 -- 177
188   | GETSTATIC Word16       -- 178
189   | PUTSTATIC Word16       -- 179
190   | GETFIELD Word16        -- 180
191   | PUTFIELD Word16        -- 181
192   | INVOKEVIRTUAL Word16   -- 182
193   | INVOKESPECIAL Word16   -- 183
194   | INVOKESTATIC Word16    -- 184
195   | INVOKEINTERFACE Word16 Word8 -- 185
196   | NEW Word16             -- 187
197   | NEWARRAY Word8         -- 188, see ArrayType
198   | ANEWARRAY Word16       -- 189
199   | ARRAYLENGTH            -- 190
200   | ATHROW                 -- 191
201   | CHECKCAST Word16       -- 192
202   | INSTANCEOF Word16      -- 193
203   | MONITORENTER           -- 194
204   | MONITOREXIT            -- 195
205   | WIDE Word8 Instruction -- 196
206   | MULTINANEWARRAY Word16 Word8 -- 197
207   | IFNULL Word16          -- 198
208   | IFNONNULL Word16       -- 199
209   | GOTO_W Word32          -- 200
210   | JSR_W Word32           -- 201
211   deriving (Eq, Show)
212
213 data ArrayType =
214     T_BOOLEAN  -- 4
215   | T_CHAR     -- 5
216   | T_FLOAT    -- 6
217   | T_DOUBLE   -- 7
218   | T_BYTE     -- 8
219   | T_SHORT    -- 9
220   | T_INT      -- 10
221   | T_LONG     -- 11
222   deriving (Eq, Show, Enum)
223
224 imm :: Word8 -> (IMM -> Instruction) -> Word8 -> GetState s Instruction
225 imm base constr x = return $ constr $ toEnum $ fromIntegral (x-base)
226
227 putImm :: Word8 -> IMM -> PutState Integer ()
228 putImm base i = putByte $ base + (fromIntegral $ fromEnum i)
229
230 atype2byte :: ArrayType -> Word8
231 atype2byte T_BOOLEAN  = 4
232 atype2byte T_CHAR     = 5
233 atype2byte T_FLOAT    = 6
234 atype2byte T_DOUBLE   = 7
235 atype2byte T_BYTE     = 8
236 atype2byte T_SHORT    = 9
237 atype2byte T_INT      = 10
238 atype2byte T_LONG     = 11
239
240 byte2atype :: Word8 -> GetState s ArrayType
241 byte2atype 4  = return T_BOOLEAN
242 byte2atype 5  = return T_CHAR
243 byte2atype 6  = return T_FLOAT
244 byte2atype 7  = return T_DOUBLE
245 byte2atype 8  = return T_BYTE
246 byte2atype 9  = return T_SHORT
247 byte2atype 10 = return T_INT
248 byte2atype 11 = return T_LONG
249 byte2atype x  = fail $ "Unknown array type byte: " ++ show x
250
251 instance BinaryState Integer ArrayType where
252   get = do
253     x <- getByte
254     byte2atype x
255
256   put t = putByte (atype2byte t)
257
258 put1 :: (BinaryState Integer a) => Word8 -> a -> PutState Integer ()
259 put1 code x = do
260   putByte code
261   put x
262
263 put2 :: (BinaryState Integer a, BinaryState Integer b) => Word8 -> a -> b -> PutState Integer ()
264 put2 code x y = do
265   putByte code
266   put x
267   put y
268
269 instance BinaryState Integer Instruction where
270   put  NOP         = putByte 0
271   put  ACONST_NULL = putByte 1
272   put  ICONST_M1   = putByte 2
273   put  ICONST_0    = putByte 3
274   put  ICONST_1    = putByte 4
275   put  ICONST_2    = putByte 5
276   put  ICONST_3    = putByte 6
277   put  ICONST_4    = putByte 7
278   put  ICONST_5    = putByte 8
279   put  LCONST_0    = putByte 9
280   put  LCONST_1    = putByte 10
281   put  FCONST_0    = putByte 11
282   put  FCONST_1    = putByte 12
283   put  FCONST_2    = putByte 13
284   put  DCONST_0    = putByte 14
285   put  DCONST_1    = putByte 15
286   put (BIPUSH x)   = put1 16 x
287   put (SIPUSH x)   = put1 17 x
288   put (LDC1 x)     = put1 18 x
289   put (LDC2 x)     = put1 19 x
290   put (LDC2W x)    = put1 20 x
291   put (ILOAD x)    = put1 21 x
292   put (LLOAD x)    = put1 22 x
293   put (FLOAD x)    = put1 23 x
294   put (DLOAD x)    = put1 24 x
295   put (ALOAD x)    = put1 25 x
296   put (ILOAD_ i)   = putImm 26 i
297   put (LLOAD_ i)   = putImm 30 i
298   put (FLOAD_ i)   = putImm 34 i
299   put (DLOAD_ i)   = putImm 38 i
300   put (ALOAD_ i)   = putImm 42 i
301   put  IALOAD      = putByte 46
302   put  LALOAD      = putByte 47
303   put  FALOAD      = putByte 48
304   put  DALOAD      = putByte 49
305   put  AALOAD      = putByte 50
306   put  BALOAD      = putByte 51
307   put  CALOAD      = putByte 52
308   put  SALOAD      = putByte 53
309   put (ISTORE x)   = put1  54 x
310   put (LSTORE x)   = put1  55 x
311   put (FSTORE x)   = put1  56 x
312   put (DSTORE x)   = put1  57 x
313   put (ASTORE x)   = put1  58 x
314   put (ISTORE_ i)  = putImm 59 i
315   put (LSTORE_ i)  = putImm 63 i
316   put (FSTORE_ i)  = putImm 67 i
317   put (DSTORE_ i)  = putImm 71 i
318   put (ASTORE_ i)  = putImm 75 i
319   put  IASTORE     = putByte 79
320   put  LASTORE     = putByte 80
321   put  FASTORE     = putByte 81
322   put  DASTORE     = putByte 82
323   put  AASTORE     = putByte 83
324   put  BASTORE     = putByte 84
325   put  CASTORE     = putByte 85
326   put  SASTORE     = putByte 86
327   put  POP         = putByte 87
328   put  POP2        = putByte 88
329   put  DUP         = putByte 89
330   put  DUP_X1      = putByte 90
331   put  DUP_X2      = putByte 91
332   put  DUP2        = putByte 92
333   put  DUP2_X1     = putByte 93 
334   put  DUP2_X2     = putByte 94
335   put  SWAP        = putByte 95
336   put  IADD        = putByte 96
337   put  LADD        = putByte 97
338   put  FADD        = putByte 98
339   put  DADD        = putByte 99
340   put  ISUB        = putByte 100
341   put  LSUB        = putByte 101
342   put  FSUB        = putByte 102
343   put  DSUB        = putByte 103
344   put  IMUL        = putByte 104
345   put  LMUL        = putByte 105
346   put  FMUL        = putByte 106
347   put  DMUL        = putByte 107
348   put  IDIV        = putByte 108
349   put  LDIV        = putByte 109
350   put  FDIV        = putByte 110
351   put  DDIV        = putByte 111
352   put  IREM        = putByte 112
353   put  LREM        = putByte 113
354   put  FREM        = putByte 114
355   put  DREM        = putByte 115
356   put  INEG        = putByte 116
357   put  LNEG        = putByte 117
358   put  FNEG        = putByte 118
359   put  DNEG        = putByte 119
360   put  ISHL        = putByte 120
361   put  LSHL        = putByte 121
362   put  ISHR        = putByte 122
363   put  LSHR        = putByte 123
364   put  IUSHR       = putByte 124
365   put  LUSHR       = putByte 125
366   put  IAND        = putByte 126
367   put  LAND        = putByte 127
368   put  IOR         = putByte 128
369   put  LOR         = putByte 129
370   put  IXOR        = putByte 130
371   put  LXOR        = putByte 131
372   put (IINC x y)      = put2 132 x y
373   put  I2L            = putByte 133
374   put  I2F            = putByte 134
375   put  I2D            = putByte 135
376   put  L2I            = putByte 136
377   put  L2F            = putByte 137
378   put  L2D            = putByte 138
379   put  F2I            = putByte 139
380   put  F2L            = putByte 140
381   put  F2D            = putByte 141
382   put  D2I            = putByte 142
383   put  D2L            = putByte 143
384   put  D2F            = putByte 144
385   put  I2B            = putByte 145
386   put  I2C            = putByte 146
387   put  I2S            = putByte 147
388   put  LCMP           = putByte 148
389   put (FCMP C_LT)     = putByte 149
390   put (FCMP C_GT)     = putByte 150
391   put (FCMP c)        = fail $ "No such instruction: FCMP " ++ show c
392   put (DCMP C_LT)     = putByte 151
393   put (DCMP C_GT)     = putByte 152
394   put (DCMP c)        = fail $ "No such instruction: DCMP " ++ show c
395   put (IF c)          = putByte (fromIntegral $ 153 + fromEnum c)
396   put (IF_ACMP C_EQ x) = put1 165 x
397   put (IF_ACMP C_NE x) = put1 166 x
398   put (IF_ACMP c _)   = fail $ "No such instruction: IF_ACMP " ++ show c
399   put (IF_ICMP c x)   = putByte (fromIntegral $ 159 + fromEnum c) >> put x
400   put  GOTO           = putByte 167
401   put (JSR x)         = put1 168 x
402   put  RET            = putByte 169
403   put (TABLESWITCH def low high offs) = do
404                                    putByte 170
405                                    offset <- getOffset
406                                    let pads = 4 - (offset `mod` 4)
407                                    replicateM (fromIntegral pads) (putByte 0)
408                                    put low
409                                    put high
410                                    forM_ offs put
411   put (LOOKUPSWITCH def n pairs) = do
412                                    putByte 171
413                                    offset <- getOffset
414                                    let pads = 4 - (offset `mod` 4)
415                                    replicateM (fromIntegral pads) (putByte 0)
416                                    put def
417                                    put n
418                                    forM_ pairs put
419   put  IRETURN        = putByte 172
420   put  LRETURN        = putByte 173
421   put  FRETURN        = putByte 174
422   put  DRETURN        = putByte 175
423   put  RETURN         = putByte 177
424   put (GETSTATIC x)   = put1 178 x
425   put (PUTSTATIC x)   = put1 179 x
426   put (GETFIELD x)    = put1 180 x
427   put (PUTFIELD x)    = put1 181 x
428   put (INVOKEVIRTUAL x)     = put1 182 x
429   put (INVOKESPECIAL x)     = put1 183 x
430   put (INVOKESTATIC x)      = put1 184 x
431   put (INVOKEINTERFACE x c) = put2 185 x c >> putByte 0
432   put (NEW x)         = put1 187 x
433   put (NEWARRAY x)    = put1 188 x
434   put (ANEWARRAY x)   = put1 189 x
435   put  ARRAYLENGTH    = putByte 190
436   put  ATHROW         = putByte 191
437   put (CHECKCAST x)   = put1 192 x
438   put (INSTANCEOF x)  = put1 193 x
439   put  MONITORENTER   = putByte 194
440   put  MONITOREXIT    = putByte 195
441   put (WIDE x inst)   = put2 196 x inst
442   put (MULTINANEWARRAY x y) = put2 197 x y
443   put (IFNULL x)      = put1 198 x
444   put (IFNONNULL x)   = put1 199 x
445   put (GOTO_W x)      = put1 200 x
446   put (JSR_W x)       = put1 201 x
447
448   get = do
449     c <- getByte
450     case c of
451       0 -> return NOP
452       1 -> return ACONST_NULL
453       2 -> return ICONST_M1
454       3 -> return ICONST_0
455       4 -> return ICONST_1
456       5 -> return ICONST_2
457       6 -> return ICONST_3
458       7 -> return ICONST_4
459       8 -> return ICONST_5
460       9 -> return LCONST_0
461       10 -> return LCONST_1
462       11 -> return FCONST_0
463       12 -> return FCONST_1
464       13 -> return FCONST_2
465       14 -> return DCONST_0
466       15 -> return DCONST_1
467       16 -> BIPUSH <$> get
468       17 -> SIPUSH <$> get
469       18 -> LDC1 <$> get
470       19 -> LDC2 <$> get
471       20 -> LDC2W <$> get
472       21 -> ILOAD <$> get
473       22 -> LLOAD <$> get
474       23 -> FLOAD <$> get
475       24 -> DLOAD <$> get
476       25 -> ALOAD <$> get
477       46 -> return IALOAD
478       47 -> return LALOAD
479       48 -> return FALOAD
480       49 -> return DALOAD
481       50 -> return AALOAD
482       51 -> return BALOAD
483       52 -> return CALOAD
484       53 -> return SALOAD
485       54 -> ISTORE <$> get
486       55 -> LSTORE <$> get
487       56 -> FSTORE <$> get
488       57 -> DSTORE <$> get
489       58 -> ASTORE <$> get
490       79 -> return IASTORE
491       80 -> return LASTORE
492       81 -> return FASTORE
493       82 -> return DASTORE
494       83 -> return AASTORE
495       84 -> return BASTORE
496       85 -> return CASTORE
497       86 -> return SASTORE
498       87 -> return POP
499       88 -> return POP2
500       89 -> return DUP
501       90 -> return DUP_X1
502       91 -> return DUP_X2
503       92 -> return DUP2
504       93 -> return DUP2_X1 
505       94 -> return DUP2_X2
506       95 -> return SWAP
507       96 -> return IADD
508       97 -> return LADD
509       98 -> return FADD
510       99 -> return DADD
511       100 -> return ISUB
512       101 -> return LSUB
513       102 -> return FSUB
514       103 -> return DSUB
515       104 -> return IMUL
516       105 -> return LMUL
517       106 -> return FMUL
518       107 -> return DMUL
519       108 -> return IDIV
520       109 -> return LDIV
521       110 -> return FDIV
522       111 -> return DDIV
523       112 -> return IREM
524       113 -> return LREM
525       114 -> return FREM
526       115 -> return DREM
527       116 -> return INEG
528       117 -> return LNEG
529       118 -> return FNEG
530       119 -> return DNEG
531       120 -> return ISHL
532       121 -> return LSHL
533       122 -> return ISHR
534       123 -> return LSHR
535       124 -> return IUSHR
536       125 -> return LUSHR
537       126 -> return IAND
538       127 -> return LAND
539       128 -> return IOR
540       129 -> return LOR
541       130 -> return IXOR
542       131 -> return LXOR
543       132 -> IINC <$> get <*> get
544       133 -> return I2L
545       134 -> return I2F
546       135 -> return I2D
547       136 -> return L2I
548       137 -> return L2F
549       138 -> return L2D
550       139 -> return F2I
551       140 -> return F2L
552       141 -> return F2D
553       142 -> return D2I
554       143 -> return D2L
555       144 -> return D2F
556       145 -> return I2B
557       146 -> return I2C
558       147 -> return I2S
559       148 -> return LCMP
560       149 -> return $ FCMP C_LT
561       150 -> return $ FCMP C_GT
562       151 -> return $ DCMP C_LT
563       152 -> return $ DCMP C_GT
564       165 -> IF_ACMP C_EQ <$> get
565       166 -> IF_ACMP C_NE <$> get
566       167 -> return GOTO
567       168 -> JSR <$> get
568       169 -> return RET
569       170 -> do
570              offset <- bytesRead
571              let pads = 4 - (offset `mod` 4)
572              skip (fromIntegral pads)
573              def <- get
574              low <- get
575              high <- get
576              offs <- replicateM (fromIntegral $ high - low + 1) get
577              return $ TABLESWITCH def low high offs
578       171 -> do
579              offset <- bytesRead
580              let pads = 4 - (offset `mod` 4)
581              skip (fromIntegral pads)
582              def <- get
583              n <- get
584              pairs <- replicateM (fromIntegral n) get
585              return $ LOOKUPSWITCH def n pairs
586       172 -> return IRETURN
587       173 -> return LRETURN
588       174 -> return FRETURN
589       175 -> return DRETURN
590       177 -> return RETURN
591       178 -> GETSTATIC <$> get
592       179 -> PUTSTATIC <$> get
593       180 -> GETFIELD <$> get
594       181 -> PUTFIELD <$> get
595       182 -> INVOKEVIRTUAL <$> get
596       183 -> INVOKESPECIAL <$> get
597       184 -> INVOKESTATIC <$> get
598       185 -> (INVOKEINTERFACE <$> get <*> get) <* skip 1
599       187 -> NEW <$> get
600       188 -> NEWARRAY <$> get
601       189 -> ANEWARRAY <$> get
602       190 -> return ARRAYLENGTH
603       191 -> return ATHROW
604       192 -> CHECKCAST <$> get
605       193 -> INSTANCEOF <$> get
606       194 -> return MONITORENTER
607       195 -> return MONITOREXIT
608       196 -> WIDE <$> get <*> get
609       197 -> MULTINANEWARRAY <$> get <*> get
610       198 -> IFNULL <$> get
611       199 -> IFNONNULL <$> get
612       200 -> GOTO_W <$> get
613       201 -> JSR_W <$> get
614       _ | inRange (59, 62) c -> imm 59 ISTORE_ c
615         | inRange (63, 66) c -> imm 63 LSTORE_ c
616         | inRange (67, 70) c -> imm 67 FSTORE_ c
617         | inRange (71, 74) c -> imm 71 DSTORE_ c
618         | inRange (75, 78) c -> imm 75 ASTORE_ c
619         | inRange (26, 29) c -> imm 26 ILOAD_ c
620         | inRange (30, 33) c -> imm 30 LLOAD_ c
621         | inRange (34, 37) c -> imm 34 FLOAD_ c
622         | inRange (38, 41) c -> imm 38 DLOAD_ c
623         | inRange (42, 45) c -> imm 42 ALOAD_ c
624         | inRange (153, 158) c -> return $ IF (toEnum $ fromIntegral $ c-153)
625         | inRange (159, 164) c -> IF_ICMP (toEnum $ fromIntegral $ c-159) <$> get
626         | otherwise -> fail $ "Unknown instruction byte code: " ++ show c
627