OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE.md file. | |
4 | |
5 main() { | |
6 print(""" | |
7 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file | |
8 // for details. All rights reserved. Use of this source code is governed by a | |
9 // BSD-style license that can be found in the LICENSE.md file. | |
10 | |
11 // WARNING: Generated file, do not edit! | |
12 | |
13 part of fletch.bytecodes; | |
14 """); | |
15 | |
16 print("enum Opcode {"); | |
17 doBytecodes((String name, bool isBranching, String format, int size, | |
18 spDiff, String formatString) { | |
19 print(" $name,"); | |
20 }); | |
21 print("}"); | |
22 | |
23 doBytecodes((String name, bool isBranching, String format, int size, | |
24 spDiff, String formatString) { | |
25 List<String> fields = <String>[]; | |
26 List<String> encode = <String>[]; | |
27 | |
28 for (int i = 0; i < format.length; i++) { | |
29 String code = format[i]; | |
30 switch (code) { | |
31 case "B": | |
32 String field = "uint8Argument$i"; | |
33 fields.add(field); | |
34 encode.add(" ..addUint8($field)\n"); | |
35 break; | |
36 case "I": | |
37 String field = "uint32Argument$i"; | |
38 fields.add(field); | |
39 encode.add(" ..addUint32($field)\n"); | |
40 break; | |
41 default: | |
42 throw "Unknown format: $code"; | |
43 } | |
44 } | |
45 | |
46 String toStringExpression = formatString; | |
47 if (fields.isNotEmpty) { | |
48 List<String> parts = formatString.split("%d"); | |
49 StringBuffer buffer = new StringBuffer(); | |
50 Iterator iterator = fields.iterator; | |
51 for (String part in parts) { | |
52 buffer.write(part); | |
53 if (iterator.moveNext()) { | |
54 buffer.write(r'${'); | |
55 buffer.write(iterator.current); | |
56 buffer.write('}'); | |
57 } | |
58 } | |
59 toStringExpression = '$buffer'; | |
60 } | |
61 | |
62 String equals = ''; | |
63 if (fields.isNotEmpty) { | |
64 StringBuffer equalsBuffer = | |
65 new StringBuffer('\n\n operator==(Bytecode other) {\n'); | |
66 equalsBuffer.writeln(' if (!(super==(other))) return false;'); | |
67 equalsBuffer.writeln(' $name rhs = other;'); | |
68 for (String field in fields) { | |
69 equalsBuffer.writeln(' if ($field != rhs.$field) return false;'); | |
70 } | |
71 equalsBuffer.writeln(' return true;'); | |
72 equalsBuffer.write(' }'); | |
73 equals = '$equalsBuffer'; | |
74 } | |
75 | |
76 String hashCode = ''; | |
77 if (fields.isNotEmpty) { | |
78 StringBuffer hashCodeBuffer = | |
79 new StringBuffer('\n\n int get hashCode {\n'); | |
80 hashCodeBuffer.writeln(' int value = super.hashCode;'); | |
81 for (String field in fields) { | |
82 hashCodeBuffer.writeln(' value += $field;'); | |
83 } | |
84 hashCodeBuffer.writeln(' return value;'); | |
85 hashCodeBuffer.write(' }'); | |
86 hashCode = '$hashCodeBuffer'; | |
87 } | |
88 | |
89 print(""" | |
90 | |
91 class $name extends Bytecode { | |
92 ${ | |
93 fields.map((a) => ' final int $a;\n').join('') | |
94 } const $name(${fields.map((a) => 'this.$a').join(', ')}) | |
95 : super(); | |
96 | |
97 Opcode get opcode => Opcode.$name; | |
98 | |
99 String get name => '$name'; | |
100 | |
101 bool get isBranching => $isBranching; | |
102 | |
103 String get format => '$format'; | |
104 | |
105 int get size => $size; | |
106 | |
107 int get stackPointerDifference => $spDiff; | |
108 | |
109 String get formatString => '$formatString'; | |
110 | |
111 void addTo(Sink<List<int>> sink) { | |
112 new BytecodeBuffer() | |
113 ..addUint8(opcode.index) | |
114 ${ | |
115 encode.join("") | |
116 } ..sendOn(sink); | |
117 } | |
118 | |
119 String toString() => '$toStringExpression';$equals$hashCode | |
120 }"""); | |
121 }); | |
122 } | |
123 | |
124 void doBytecodes(V(String name, bool isBranching, String format, int size, | |
125 spDiff, String formatString)) { | |
126 // Code below was copied from src/shared/bytecodes.h. | |
127 var kVarDiff = "VAR_DIFF"; | |
128 | |
129 void INVOKE(V, name, diff, desc, suffix, type) { | |
130 V("Invoke${name}${suffix}", true, "I", 5, diff, "invoke ${type}${desc}%d"); | |
131 } | |
132 | |
133 void INVOKES_DO(V, suffix, type) { | |
134 INVOKE(V, "Method", kVarDiff, "method ", suffix, type); | |
135 INVOKE(V, "Test", 0, "test ", suffix, type); | |
136 | |
137 INVOKE(V, "Eq", -1, "eq ", suffix, type); | |
138 INVOKE(V, "Lt", -1, "lt ", suffix, type); | |
139 INVOKE(V, "Le", -1, "le ", suffix, type); | |
140 INVOKE(V, "Gt", -1, "gt ", suffix, type); | |
141 INVOKE(V, "Ge", -1, "ge ", suffix, type); | |
142 | |
143 INVOKE(V, "Add", -1, "add ", suffix, type); | |
144 INVOKE(V, "Sub", -1, "sub ", suffix, type); | |
145 INVOKE(V, "Mod", -1, "mod ", suffix, type); | |
146 INVOKE(V, "Mul", -1, "mul ", suffix, type); | |
147 INVOKE(V, "TruncDiv", -1, "trunc div ", suffix, type); | |
148 | |
149 INVOKE(V, "BitNot", 0, "bit not ", suffix, type); | |
150 INVOKE(V, "BitAnd", -1, "bit and ", suffix, type); | |
151 INVOKE(V, "BitOr", -1, "bit or ", suffix, type); | |
152 INVOKE(V, "BitXor", -1, "bit xor ", suffix, type); | |
153 INVOKE(V, "BitShr", -1, "bit shr ", suffix, type); | |
154 INVOKE(V, "BitShl", -1, "bit shl ", suffix, type); | |
155 } | |
156 | |
157 /* Name Branching Format Size SP-diff format-string */ | |
158 V("LoadLocal0", false, "", 1, 1, "load local 0"); | |
159 V("LoadLocal1", false, "", 1, 1, "load local 1"); | |
160 V("LoadLocal2", false, "", 1, 1, "load local 2"); | |
161 V("LoadLocal3", false, "", 1, 1, "load local 3"); | |
162 V("LoadLocal4", false, "", 1, 1, "load local 4"); | |
163 V("LoadLocal5", false, "", 1, 1, "load local 5"); | |
164 V("LoadLocal", false, "B", 2, 1, "load local %d"); | |
165 V("LoadLocalWide", false, "I", 5, 1, "load local %d"); | |
166 | |
167 V("LoadBoxed", false, "B", 2, 1, "load boxed %d"); | |
168 V("LoadStatic", false, "I", 5, 1, "load static %d"); | |
169 V("LoadStaticInit", false, "I", 5, 1, "load static init %d"); | |
170 V("LoadField", false, "B", 2, 0, "load field %d"); | |
171 V("LoadFieldWide", false, "I", 5, 0, "load field %d"); | |
172 | |
173 V("StoreLocal", false, "B", 2, 0, "store local %d"); | |
174 V("StoreBoxed", false, "B", 2, 0, "store boxed %d"); | |
175 V("StoreStatic", false, "I", 5, 0, "store static %d"); | |
176 V("StoreField", false, "B", 2, -1, "store field %d"); | |
177 V("StoreFieldWide", false, "I", 5, -1, "store field %d"); | |
178 | |
179 V("LoadLiteralNull", false, "", 1, 1, "load literal null"); | |
180 V("LoadLiteralTrue", false, "", 1, 1, "load literal true"); | |
181 V("LoadLiteralFalse", false, "", 1, 1, "load literal false"); | |
182 V("LoadLiteral0", false, "", 1, 1, "load literal 0"); | |
183 V("LoadLiteral1", false, "", 1, 1, "load literal 1"); | |
184 V("LoadLiteral", false, "B", 2, 1, "load literal %d"); | |
185 // TODO(ahe): The argument to LoadLiteralWide is probably signed. | |
186 V("LoadLiteralWide", false, "I", 5, 1, "load literal %d"); | |
187 | |
188 INVOKES_DO(V, "", ""); | |
189 INVOKE(V, "Static", kVarDiff, "static ", "", ""); | |
190 INVOKE(V, "Factory", kVarDiff, "factory ", "", ""); | |
191 V("Allocate", false, "I", 5, kVarDiff, "allocate %d"); | |
192 V("AllocateImmutable", false, "I", 5, kVarDiff, "allocateim %d"); | |
193 | |
194 V("InvokeNoSuchMethod", true, "I", 5, kVarDiff, "invoke no such method %d"); | |
195 V("InvokeTestNoSuchMethod", true, "I", 5, 0, "invoke test no such method %d"); | |
196 | |
197 V("InvokeNative", true, "BB", 3, 1, "invoke native %d %d")
; | |
198 V("InvokeDetachableNative", true, "BB", 3, 1, | |
199 "invoke detachable native %d %d"); | |
200 V("InvokeNativeYield", true, "BB", 3, 1, "invoke native yield %d %d"
); | |
201 | |
202 V("InvokeSelector", true, "I", 5, kVarDiff, "invoke selector"); | |
203 | |
204 V("Pop", false, "", 1, -1, "pop"); | |
205 V("Drop", false, "B", 2, kVarDiff, "drop %d"); | |
206 V("Return", true, "", 1, -1, "return"); | |
207 V("ReturnNull", true, "", 1, 0, "return null"); | |
208 | |
209 V("BranchWide", true, "I", 5, 0, "branch +%d"); | |
210 V("BranchIfTrueWide", true, "I", 5, -1, "branch if true +%d"); | |
211 V("BranchIfFalseWide", true, "I", 5, -1, "branch if false +%d"); | |
212 | |
213 V("BranchBack", true, "B", 2, 0, "branch -%d"); | |
214 V("BranchBackIfTrue", true, "B", 2, -1, "branch if true -%d"); | |
215 V("BranchBackIfFalse", true, "B", 2, -1, "branch if false -%d"); | |
216 | |
217 V("BranchBackWide", true, "I", 5, 0, "branch -%d"); | |
218 V("BranchBackIfTrueWide", true, "I", 5, -1, "branch if true -%d"); | |
219 V("BranchBackIfFalseWide", true, "I", 5, -1, "branch if false -%d"); | |
220 | |
221 V("PopAndBranchWide", true, "BI", 6, 0, "pop %d and branch +%d"
); | |
222 V("PopAndBranchBackWide", true, "BI", 6, 0, "pop %d and branch -%d"
); | |
223 | |
224 V("AllocateBoxed", false, "", 1, 0, "allocate boxed"); | |
225 | |
226 V("Negate", false, "", 1, 0, "negate"); | |
227 | |
228 V("StackOverflowCheck", true, "I", 5, 0, "stack overflow check %d"
); | |
229 | |
230 V("Throw", true, "", 1, 0, "throw"); | |
231 V("SubroutineCall", true, "II", 9, kVarDiff, "subroutine call +%d -%d"
); | |
232 V("SubroutineReturn", true, "", 1, -1, "subroutine return"); | |
233 | |
234 V("ProcessYield", true, "", 1, 0, "process yield"); | |
235 V("CoroutineChange", true, "", 1, -1, "coroutine change"); | |
236 | |
237 V("Identical", true, "", 1, -1, "identical"); | |
238 V("IdenticalNonNumeric", true, "", 1, -1, "identical non numeric"
); | |
239 | |
240 V("EnterNoSuchMethod", true, "B", 2, kVarDiff, "enter noSuchMethod +%d
"); | |
241 V("ExitNoSuchMethod", true, "", 1, -1, "exit noSuchMethod"); | |
242 | |
243 INVOKES_DO(V, "Unfold", "unfold "); | |
244 V("LoadConst", false, "I", 5, 1, "load const @%d"); | |
245 | |
246 V("MethodEnd", false, "I", 5, 0, "method end %d"); | |
247 } | |
OLD | NEW |