blob: 567e25e1d5043d1c8939392dde25e82387b8586d [file] [log] [blame]
Jack Palevichae54f1f2009-05-08 14:54:15 -07001/*
Jack Palevich21a15a22009-05-11 14:49:29 -07002 Obfuscated Tiny C Compiler
Jack Palevich88311482009-05-08 13:57:37 -07003
Jack Palevich21a15a22009-05-11 14:49:29 -07004 Copyright (C) 2001-2003 Fabrice Bellard
Jack Palevichae54f1f2009-05-08 14:54:15 -07005
Jack Palevich21a15a22009-05-11 14:49:29 -07006 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
Jack Paleviche27bf3e2009-05-10 14:09:03 -07009
Jack Palevich21a15a22009-05-11 14:49:29 -070010 Permission is granted to anyone to use this software for any purpose,
11 including commercial applications, and to alter it and redistribute it
12 freely, subject to the following restrictions:
Jack Paleviche27bf3e2009-05-10 14:09:03 -070013
Jack Palevich21a15a22009-05-11 14:49:29 -070014 1. The origin of this software must not be misrepresented; you must not
15 claim that you wrote the original software. If you use this software
16 in a product, an acknowledgment in the product and its documentation
17 *is* required.
18 2. Altered source versions must be plainly marked as such, and must not be
19 misrepresented as being the original software.
20 3. This notice may not be removed or altered from any source distribution.
21 */
Jack Paleviche27bf3e2009-05-10 14:09:03 -070022
Jack Palevich77ae76e2009-05-10 19:59:24 -070023#include <ctype.h>
24#include <dlfcn.h>
Jack Paleviche27bf3e2009-05-10 14:09:03 -070025#include <stdarg.h>
Jack Palevichae54f1f2009-05-08 14:54:15 -070026#include <stdio.h>
Jack Palevichf6b5a532009-05-10 19:16:42 -070027#include <stdlib.h>
28#include <string.h>
Jack Palevichae54f1f2009-05-08 14:54:15 -070029
Jack Palevich546b2242009-05-13 15:10:04 -070030#if defined(__arm__)
31#include <unistd.h>
32#endif
33
Jack Palevicha6535612009-05-13 16:24:17 -070034#include "disassem.h"
35
Jack Palevichbbf8ab52009-05-11 11:54:30 -070036namespace acc {
37
Jack Palevich77ae76e2009-05-10 19:59:24 -070038class compiler {
Jack Palevich21a15a22009-05-11 14:49:29 -070039 class CodeBuf {
40 char* ind;
41 char* pProgramBase;
Jack Palevichf0cbc922009-05-08 16:35:13 -070042
Jack Palevich21a15a22009-05-11 14:49:29 -070043 void release() {
44 if (pProgramBase != 0) {
45 free(pProgramBase);
46 pProgramBase = 0;
Jack Palevichae54f1f2009-05-08 14:54:15 -070047 }
Jack Palevich21a15a22009-05-11 14:49:29 -070048 }
49
50 public:
51 CodeBuf() {
52 pProgramBase = 0;
53 ind = 0;
54 }
55
56 ~CodeBuf() {
57 release();
58 }
59
60 void init(int size) {
61 release();
62 pProgramBase = (char*) calloc(1, size);
63 ind = pProgramBase;
64 }
65
66 void o(int n) {
67 /* cannot use unsigned, so we must do a hack */
68 while (n && n != -1) {
69 *ind++ = n;
70 n = n >> 8;
71 }
72 }
73
Jack Palevich546b2242009-05-13 15:10:04 -070074 int o4(int n) {
75 int result = (int) ind;
76 * (int*) ind = n;
77 ind += 4;
78 return result;
79 }
80
Jack Palevich21a15a22009-05-11 14:49:29 -070081 /*
82 * Output a byte. Handles all values, 0..ff.
83 */
84 void ob(int n) {
85 *ind++ = n;
86 }
87
88 /* output a symbol and patch all calls to it */
89 void gsym(int t) {
90 int n;
91 while (t) {
92 n = *(int *) t; /* next value */
93 *(int *) t = ((int) ind) - t - 4;
94 t = n;
95 }
96 }
97
98 /* psym is used to put an instruction with a data field which is a
99 reference to a symbol. It is in fact the same as oad ! */
100 int psym(int n, int t) {
101 return oad(n, t);
102 }
103
104 /* instruction + address */
105 int oad(int n, int t) {
106 o(n);
107 *(int *) ind = t;
108 t = (int) ind;
109 ind = ind + 4;
110 return t;
111 }
112
113 inline void* getBase() {
114 return (void*) pProgramBase;
115 }
116
117 int getSize() {
118 return ind - pProgramBase;
119 }
120
121 int getPC() {
122 return (int) ind;
123 }
124 };
125
126 class CodeGenerator {
127 public:
128 CodeGenerator() {}
129 virtual ~CodeGenerator() {}
130
Jack Palevich22305132009-05-13 10:58:45 -0700131 virtual void init(CodeBuf* pCodeBuf) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700132 this->pCodeBuf = pCodeBuf;
133 }
134
Jack Palevich22305132009-05-13 10:58:45 -0700135 /* returns address to patch with local variable size
136 */
Jack Palevich546b2242009-05-13 15:10:04 -0700137 virtual int functionEntry(int argCount) = 0;
Jack Palevich22305132009-05-13 10:58:45 -0700138
Jack Palevich546b2242009-05-13 15:10:04 -0700139 virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) = 0;
Jack Palevich22305132009-05-13 10:58:45 -0700140
141 /* load immediate value */
Jack Palevich546b2242009-05-13 15:10:04 -0700142 virtual void li(int t) = 0;
Jack Palevich22305132009-05-13 10:58:45 -0700143
144 virtual int gjmp(int t) = 0;
145
146 /* l = 0: je, l == 1: jne */
147 virtual int gtst(bool l, int t) = 0;
148
149 virtual void gcmp(int op) = 0;
150
Jack Palevich546b2242009-05-13 15:10:04 -0700151 virtual void genOp(int op) = 0;
Jack Palevich22305132009-05-13 10:58:45 -0700152
153 virtual void clearECX() = 0;
154
155 virtual void pushEAX() = 0;
156
157 virtual void popECX() = 0;
158
159 virtual void storeEAXToAddressECX(bool isInt) = 0;
160
161 virtual void loadEAXIndirect(bool isInt) = 0;
162
163 virtual void leaEAX(int ea) = 0;
164
165 virtual void storeEAX(int ea) = 0;
166
Jack Palevich4d93f302009-05-15 13:30:00 -0700167 virtual void loadEAX(int ea, bool isIncDec, int op) = 0;
Jack Palevich22305132009-05-13 10:58:45 -0700168
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700169 virtual int beginFunctionCallArguments() = 0;
170
Jack Palevich7810bc92009-05-15 14:31:47 -0700171 virtual void storeEAToArg(int l) = 0;
172
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700173 virtual void endFunctionCallArguments(int a, int l) = 0;
Jack Palevich22305132009-05-13 10:58:45 -0700174
Jack Palevich22305132009-05-13 10:58:45 -0700175
176 virtual int callForward(int symbol) = 0;
177
178 virtual void callRelative(int t) = 0;
179
180 virtual void callIndirect(int l) = 0;
181
Jack Palevich7810bc92009-05-15 14:31:47 -0700182 virtual void adjustStackAfterCall(int l, bool isIndirect) = 0;
Jack Palevich22305132009-05-13 10:58:45 -0700183
Jack Palevicha6535612009-05-13 16:24:17 -0700184 virtual int disassemble(FILE* out) = 0;
185
Jack Palevich21a15a22009-05-11 14:49:29 -0700186 /* output a symbol and patch all calls to it */
Jack Palevich22305132009-05-13 10:58:45 -0700187 virtual void gsym(int t) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700188 pCodeBuf->gsym(t);
189 }
190
Jack Palevich546b2242009-05-13 15:10:04 -0700191 virtual int finishCompile() {
192#if defined(__arm__)
Jack Palevicha6535612009-05-13 16:24:17 -0700193 const long base = long(pCodeBuf->getBase());
194 const long curr = base + long(pCodeBuf->getSize());
195 int err = cacheflush(base, curr, 0);
196 return err;
Jack Palevich546b2242009-05-13 15:10:04 -0700197#else
Jack Palevicha6535612009-05-13 16:24:17 -0700198 return 0;
Jack Palevich546b2242009-05-13 15:10:04 -0700199#endif
200 }
201
Jack Palevicha6535612009-05-13 16:24:17 -0700202 /**
203 * Adjust relative branches by this amount.
204 */
205 virtual int jumpOffset() = 0;
206
Jack Palevich21a15a22009-05-11 14:49:29 -0700207 protected:
208 void o(int n) {
209 pCodeBuf->o(n);
210 }
211
212 /*
213 * Output a byte. Handles all values, 0..ff.
214 */
215 void ob(int n) {
216 pCodeBuf->ob(n);
217 }
218
219 /* psym is used to put an instruction with a data field which is a
220 reference to a symbol. It is in fact the same as oad ! */
221 int psym(int n, int t) {
222 return oad(n, t);
223 }
224
225 /* instruction + address */
226 int oad(int n, int t) {
227 return pCodeBuf->oad(n,t);
228 }
229
Jack Palevicha6535612009-05-13 16:24:17 -0700230 int getBase() {
231 return (int) pCodeBuf->getBase();
232 }
233
Jack Palevich21a15a22009-05-11 14:49:29 -0700234 int getPC() {
235 return pCodeBuf->getPC();
236 }
237
Jack Palevich546b2242009-05-13 15:10:04 -0700238 int o4(int data) {
239 return pCodeBuf->o4(data);
240 }
Jack Palevich21a15a22009-05-11 14:49:29 -0700241 private:
242 CodeBuf* pCodeBuf;
243 };
244
Jack Palevich22305132009-05-13 10:58:45 -0700245 class ARMCodeGenerator : public CodeGenerator {
246 public:
247 ARMCodeGenerator() {}
248 virtual ~ARMCodeGenerator() {}
249
250 /* returns address to patch with local variable size
251 */
Jack Palevich546b2242009-05-13 15:10:04 -0700252 virtual int functionEntry(int argCount) {
253 fprintf(stderr, "functionEntry(%d);\n", argCount);
Jack Palevich69796b62009-05-14 15:42:26 -0700254 // sp -> arg4 arg5 ...
255 // Push our register-based arguments back on the stack
256 if (argCount > 0) {
257 int regArgCount = argCount <= 4 ? argCount : 4;
258 o4(0xE92D0000 | ((1 << argCount) - 1)); // stmfd sp!, {}
259 }
260 // sp -> arg0 arg1 ...
261 o4(0xE92D4800); // stmfd sp!, {fp, lr}
262 // sp, fp -> oldfp, retadr, arg0 arg1 ....
263 o4(0xE1A0B00D); // mov fp, sp
264 return o4(0xE24DD000); // sub sp, sp, # <local variables>
Jack Palevich22305132009-05-13 10:58:45 -0700265 }
266
Jack Palevich546b2242009-05-13 15:10:04 -0700267 virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
268 fprintf(stderr, "functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize);
Jack Palevich69796b62009-05-14 15:42:26 -0700269 // Patch local variable allocation code:
270 if (localVariableSize < 0 || localVariableSize > 255) {
Jack Palevich8de461d2009-05-14 17:21:45 -0700271 error("localVariables out of range: %d", localVariableSize);
Jack Palevich546b2242009-05-13 15:10:04 -0700272 }
Jack Palevich69796b62009-05-14 15:42:26 -0700273 *(char*) (localVariableAddress) = localVariableSize;
274
275 // sp -> locals .... fp -> oldfp, retadr, arg0, arg1, ...
276 o4(0xE1A0E00B); // mov lr, fp
277 o4(0xE59BB000); // ldr fp, [fp]
278 o4(0xE28ED004); // add sp, lr, #4
279 // sp -> retadr, arg0, ...
280 o4(0xE8BD4000); // ldmfd sp!, {lr}
281 // sp -> arg0 ....
282 if (argCount > 0) {
283 // We store the PC into the lr so we can adjust the sp before
Jack Palevich8de461d2009-05-14 17:21:45 -0700284 // returning. We need to pull off the registers we pushed
Jack Palevich69796b62009-05-14 15:42:26 -0700285 // earlier. We don't need to actually store them anywhere,
286 // just adjust the stack.
287 int regArgCount = argCount <= 4 ? argCount : 4;
288 o4(0xE28DD000 | (regArgCount << 2)); // add sp, sp, #argCount << 2
289 }
290 o4(0xE12FFF1E); // bx lr
Jack Palevich22305132009-05-13 10:58:45 -0700291 }
292
293 /* load immediate value */
Jack Palevich546b2242009-05-13 15:10:04 -0700294 virtual void li(int t) {
Jack Palevich22305132009-05-13 10:58:45 -0700295 fprintf(stderr, "li(%d);\n", t);
Jack Palevicha6535612009-05-13 16:24:17 -0700296 if (t >= 0 && t < 255) {
Jack Palevich69796b62009-05-14 15:42:26 -0700297 o4(0xE3A00000 + t); // mov r0, #0
Jack Palevicha6535612009-05-13 16:24:17 -0700298 } else if (t >= -256 && t < 0) {
299 // mvn means move constant ^ ~0
Jack Palevich69796b62009-05-14 15:42:26 -0700300 o4(0xE3E00001 - t); // mvn r0, #0
Jack Palevicha6535612009-05-13 16:24:17 -0700301 } else {
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700302 o4(0xE51F0000); // ldr r0, .L3
303 o4(0xEA000000); // b .L99
304 o4(t); // .L3: .word 0
305 // .L99:
Jack Palevicha6535612009-05-13 16:24:17 -0700306 }
Jack Palevich22305132009-05-13 10:58:45 -0700307 }
308
309 virtual int gjmp(int t) {
310 fprintf(stderr, "gjmp(%d);\n", t);
Jack Palevich8de461d2009-05-14 17:21:45 -0700311 return o4(0xEA000000 | encodeAddress(t)); // b .L33
Jack Palevich22305132009-05-13 10:58:45 -0700312 }
313
314 /* l = 0: je, l == 1: jne */
315 virtual int gtst(bool l, int t) {
316 fprintf(stderr, "gtst(%d, %d);\n", l, t);
Jack Palevich8de461d2009-05-14 17:21:45 -0700317 o4(0xE3500000); // cmp r0,#0
318 int branch = l ? 0x1A000000 : 0x0A000000; // bne : beq
319 return o4(branch | encodeAddress(t));
Jack Palevich22305132009-05-13 10:58:45 -0700320 }
321
322 virtual void gcmp(int op) {
323 fprintf(stderr, "gcmp(%d);\n", op);
Jack Palevich8de461d2009-05-14 17:21:45 -0700324 o4(0xE1510000); // cmp r1, r1
325 switch(op) {
326 case OP_EQUALS:
327 o4(0x03A00001); // moveq r0,#1
328 o4(0x13A00000); // movne r0,#0
329 break;
330 case OP_NOT_EQUALS:
331 o4(0x03A00000); // moveq r0,#0
332 o4(0x13A00001); // movne r0,#1
333 break;
334 case OP_LESS_EQUAL:
335 o4(0xD3A00001); // movle r0,#1
336 o4(0xC3A00000); // movgt r0,#0
337 break;
338 case OP_GREATER:
339 o4(0xD3A00000); // movle r0,#0
340 o4(0xC3A00001); // movgt r0,#1
341 break;
342 case OP_GREATER_EQUAL:
343 o4(0xA3A00001); // movge r0,#1
344 o4(0xB3A00000); // movlt r0,#0
345 break;
346 case OP_LESS:
347 o4(0xA3A00000); // movge r0,#0
348 o4(0xB3A00001); // movlt r0,#1
349 break;
350 default:
351 error("Unknown comparison op %d", op);
352 break;
353 }
Jack Palevich22305132009-05-13 10:58:45 -0700354 }
355
Jack Palevich546b2242009-05-13 15:10:04 -0700356 virtual void genOp(int op) {
Jack Palevich22305132009-05-13 10:58:45 -0700357 fprintf(stderr, "genOp(%d);\n", op);
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700358 switch(op) {
359 case OP_MUL:
360 o4(0x0E0000091); // mul r0,r1,r0
361 break;
Jack Palevich3d474a72009-05-15 15:12:38 -0700362 case OP_DIV:
363 callRuntime(runtime_DIV);
364 break;
365 case OP_MOD:
366 callRuntime(runtime_MOD);
367 break;
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700368 case OP_PLUS:
369 o4(0xE0810000); // add r0,r1,r0
370 break;
371 case OP_MINUS:
372 o4(0xE0410000); // sub r0,r1,r0
373 break;
374 case OP_SHIFT_LEFT:
375 o4(0xE1A00011); // lsl r0,r1,r0
376 break;
377 case OP_SHIFT_RIGHT:
378 o4(0xE1A00051); // asr r0,r1,r0
379 break;
380 case OP_BIT_AND:
381 o4(0xE0010000); // and r0,r1,r0
382 break;
383 case OP_BIT_XOR:
384 o4(0xE0210000); // eor r0,r1,r0
385 break;
386 case OP_BIT_OR:
387 o4(0xE1810000); // orr r0,r1,r0
388 break;
389 case OP_BIT_NOT:
390 o4(0xE1E00000); // mvn r0, r0
391 break;
392 default:
Jack Palevich69796b62009-05-14 15:42:26 -0700393 error("Unimplemented op %d\n", op);
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700394 break;
395 }
Jack Palevich22305132009-05-13 10:58:45 -0700396#if 0
397 o(decodeOp(op));
398 if (op == OP_MOD)
399 o(0x92); /* xchg %edx, %eax */
400#endif
401 }
402
403 virtual void clearECX() {
404 fprintf(stderr, "clearECX();\n");
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700405 o4(0xE3A01000); // mov r1, #0
Jack Palevich22305132009-05-13 10:58:45 -0700406 }
407
408 virtual void pushEAX() {
409 fprintf(stderr, "pushEAX();\n");
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700410 o4(0xE92D0001); // stmfd sp!,{r0}
Jack Palevich22305132009-05-13 10:58:45 -0700411 }
412
413 virtual void popECX() {
414 fprintf(stderr, "popECX();\n");
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700415 o4(0xE8BD0002); // ldmfd sp!,{r1}
Jack Palevich22305132009-05-13 10:58:45 -0700416 }
417
418 virtual void storeEAXToAddressECX(bool isInt) {
419 fprintf(stderr, "storeEAXToAddressECX(%d);\n", isInt);
Jack Palevichbd894902009-05-14 19:35:31 -0700420 if (isInt) {
421 o4(0xE5810000); // str r0, [r1]
422 } else {
423 o4(0xE5C10000); // strb r0, [r1]
424 }
Jack Palevich22305132009-05-13 10:58:45 -0700425 }
426
427 virtual void loadEAXIndirect(bool isInt) {
428 fprintf(stderr, "loadEAXIndirect(%d);\n", isInt);
429 if (isInt)
Jack Palevich69796b62009-05-14 15:42:26 -0700430 o4(0xE5900000); // ldr r0, [r0]
Jack Palevich22305132009-05-13 10:58:45 -0700431 else
Jack Palevich69796b62009-05-14 15:42:26 -0700432 o4(0xE5D00000); // ldrb r0, [r0]
Jack Palevich22305132009-05-13 10:58:45 -0700433 }
434
435 virtual void leaEAX(int ea) {
Jack Palevichbd894902009-05-14 19:35:31 -0700436 fprintf(stderr, "leaEAX(%d);\n", ea);
Jack Palevich4d93f302009-05-15 13:30:00 -0700437 if (ea < LOCAL) {
438 // Local, fp relative
439 if (ea < -1023 || ea > 1023 || ((ea & 3) != 0)) {
440 error("Offset out of range: %08x", ea);
441 }
442 if (ea < 0) {
443 o4(0xE24B0F00 | (0xff & ((-ea) >> 2))); // sub r0, fp, #ea
444 } else {
445 o4(0xE28B0F00 | (0xff & (ea >> 2))); // add r0, fp, #ea
446 }
Jack Palevichbd894902009-05-14 19:35:31 -0700447 } else {
Jack Palevich4d93f302009-05-15 13:30:00 -0700448 // Global, absolute.
449 o4(0xE59F0000); // ldr r0, .L1
450 o4(0xEA000000); // b .L99
451 o4(ea); // .L1: .word 0
452 // .L99:
Jack Palevichbd894902009-05-14 19:35:31 -0700453 }
Jack Palevich22305132009-05-13 10:58:45 -0700454 }
455
456 virtual void storeEAX(int ea) {
457 fprintf(stderr, "storeEAX(%d);\n", ea);
Jack Palevich4d93f302009-05-15 13:30:00 -0700458 if (ea < LOCAL) {
459 // Local, fp relative
460 if (ea < -4095 || ea > 4095) {
461 error("Offset out of range: %08x", ea);
462 }
463 if (ea < 0) {
464 o4(0xE50B0000 | (0xfff & (-ea))); // str r0, [fp,#-ea]
465 } else {
466 o4(0xE58B0000 | (0xfff & ea)); // str r0, [fp,#ea]
467 }
468 } else{
469 // Global, absolute
470 o4(0xE59F1000); // ldr r1, .L1
471 o4(0xEA000000); // b .L99
472 o4(ea); // .L1: .word 0
473 o4(0xE5810000); // .L99: str r0, [r1]
Jack Palevich69796b62009-05-14 15:42:26 -0700474 }
Jack Palevich22305132009-05-13 10:58:45 -0700475 }
476
Jack Palevich4d93f302009-05-15 13:30:00 -0700477 virtual void loadEAX(int ea, bool isIncDec, int op) {
478 fprintf(stderr, "loadEAX(%d, %d, %d);\n", ea, isIncDec, op);
479 if (ea < LOCAL) {
480 // Local, fp relative
481 if (ea < -4095 || ea > 4095) {
482 error("Offset out of range: %08x", ea);
483 }
484 if (ea < 0) {
485 o4(0xE51B0000 | (0xfff & (-ea))); // ldr r0, [fp,#-ea]
486 } else {
487 o4(0xE59B0000 | (0xfff & ea)); // ldr r0, [fp,#ea]
488 }
Jack Palevich69796b62009-05-14 15:42:26 -0700489 } else {
Jack Palevich4d93f302009-05-15 13:30:00 -0700490 // Global, absolute
491 o4(0xE59F2000); // ldr r2, .L1
492 o4(0xEA000000); // b .L99
493 o4(ea); // .L1: .word ea
494 o4(0xE5920000); // .L99: ldr r0, [r2]
Jack Palevich69796b62009-05-14 15:42:26 -0700495 }
Jack Palevich22305132009-05-13 10:58:45 -0700496
Jack Palevich4d93f302009-05-15 13:30:00 -0700497 if (isIncDec) {
498 switch (op) {
499 case OP_INCREMENT:
500 o4(0xE2801001); // add r1, r0, #1
501 break;
502 case OP_DECREMENT:
503 o4(0xE2401001); // sub r1, r0, #1
504 break;
505 default:
506 error("unknown opcode: %d", op);
507 }
508 if (ea < LOCAL) {
509 // Local, fp relative
510 // Don't need range check, was already checked above
511 if (ea < 0) {
512 o4(0xE50B1000 | (0xfff & (-ea))); // str r1, [fp,#-ea]
513 } else {
514 o4(0xE58B1000 | (0xfff & ea)); // str r1, [fp,#ea]
515 }
516 } else{
517 // Global, absolute
518 // r2 is already set up from before.
519 o4(0xE5821000); // str r1, [r2]
520 }
Jack Palevichbd894902009-05-14 19:35:31 -0700521 }
Jack Palevich22305132009-05-13 10:58:45 -0700522 }
523
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700524 virtual int beginFunctionCallArguments() {
525 fprintf(stderr, "beginFunctionCallArguments();\n");
526 return o4(0xE24DDF00); // Placeholder
527 }
528
Jack Palevich7810bc92009-05-15 14:31:47 -0700529 virtual void storeEAToArg(int l) {
530 fprintf(stderr, "storeEAToArg(%d);\n", l);
531 if (l < 0 || l > 4096-4) {
532 error("l out of range for stack offset: 0x%08x", l);
533 }
534 o4(0xE58D0000 + l); // str r0, [sp, #4]
535 }
536
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700537 virtual void endFunctionCallArguments(int a, int l) {
538 fprintf(stderr, "endFunctionCallArguments(0x%08x, %d);\n", a, l);
539 if (l < 0 || l > 0x3FC) {
540 error("L out of range for stack adjustment: 0x%08x", l);
541 }
542 * (int*) a = 0xE24DDF00 | (l >> 2); // sub sp, sp, #0 << 2
543 int argCount = l >> 2;
544 if (argCount > 0) {
545 int regArgCount = argCount > 4 ? 4 : argCount;
546 o4(0xE8BD0000 | ((1 << regArgCount) - 1)); // ldmfd sp!,{}
547 }
Jack Palevich22305132009-05-13 10:58:45 -0700548 }
549
Jack Palevich22305132009-05-13 10:58:45 -0700550 virtual int callForward(int symbol) {
551 fprintf(stderr, "callForward(%d);\n", symbol);
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700552 // Forward calls are always short (local)
553 return o4(0xEB000000 | encodeAddress(symbol));
Jack Palevich22305132009-05-13 10:58:45 -0700554 }
555
556 virtual void callRelative(int t) {
557 fprintf(stderr, "callRelative(%d);\n", t);
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700558 int abs = t + getPC() + jumpOffset();
Jack Palevichbd894902009-05-14 19:35:31 -0700559 fprintf(stderr, "abs=%d (0x%08x)\n", abs, abs);
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700560 if (t >= - (1 << 25) && t < (1 << 25)) {
561 o4(0xEB000000 | encodeAddress(t));
562 } else {
563 // Long call.
564 o4(0xE59FC000); // ldr r12, .L1
565 o4(0xEA000000); // b .L99
Jack Palevichbd894902009-05-14 19:35:31 -0700566 o4(t - 12); // .L1: .word 0
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700567 o4(0xE08CC00F); // .L99: add r12,pc
568 o4(0xE12FFF3C); // blx r12
569 }
Jack Palevich22305132009-05-13 10:58:45 -0700570 }
571
572 virtual void callIndirect(int l) {
573 fprintf(stderr, "callIndirect(%d);\n", l);
Jack Palevich7810bc92009-05-15 14:31:47 -0700574 int argCount = l >> 2;
575 int poppedArgs = argCount > 4 ? 4 : argCount;
576 int adjustedL = l - (poppedArgs << 2);
577 if (adjustedL < 0 || adjustedL > 4096-4) {
578 error("l out of range for stack offset: 0x%08x", l);
579 }
580 o4(0xE59DC000 | (0xfff & adjustedL)); // ldr r12, [sp,#adjustedL]
581 o4(0xE12FFF3C); // blx r12
Jack Palevich22305132009-05-13 10:58:45 -0700582 }
583
Jack Palevich7810bc92009-05-15 14:31:47 -0700584 virtual void adjustStackAfterCall(int l, bool isIndirect) {
585 fprintf(stderr, "adjustStackAfterCall(%d, %d);\n", l, isIndirect);
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700586 int argCount = l >> 2;
Jack Palevich7810bc92009-05-15 14:31:47 -0700587 int stackArgs = argCount > 4 ? argCount - 4 : 0;
588 int stackUse = stackArgs + (isIndirect ? 1 : 0);
589 if (stackUse) {
590 if (stackUse < 0 || stackUse > 255) {
591 error("L out of range for stack adjustment: 0x%08x", l);
592 }
593 o4(0xE28DDF00 | stackUse); // add sp, sp, #stackUse << 2
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700594 }
Jack Palevich22305132009-05-13 10:58:45 -0700595 }
596
Jack Palevicha6535612009-05-13 16:24:17 -0700597 virtual int jumpOffset() {
Jack Palevichbd894902009-05-14 19:35:31 -0700598 return 8;
Jack Palevicha6535612009-05-13 16:24:17 -0700599 }
600
601 /* output a symbol and patch all calls to it */
602 virtual void gsym(int t) {
603 fprintf(stderr, "gsym(0x%x)\n", t);
604 int n;
605 int base = getBase();
606 int pc = getPC();
607 fprintf(stderr, "pc = 0x%x\n", pc);
608 while (t) {
609 int data = * (int*) t;
610 int decodedOffset = ((BRANCH_REL_ADDRESS_MASK & data) << 2);
611 if (decodedOffset == 0) {
612 n = 0;
613 } else {
614 n = base + decodedOffset; /* next value */
615 }
616 *(int *) t = (data & ~BRANCH_REL_ADDRESS_MASK)
617 | encodeRelAddress(pc - t - 8);
618 t = n;
619 }
620 }
621
622 virtual int disassemble(FILE* out) {
623 disasmOut = out;
624 disasm_interface_t di;
625 di.di_readword = disassemble_readword;
626 di.di_printaddr = disassemble_printaddr;
627 di.di_printf = disassemble_printf;
628
629 int base = getBase();
630 int pc = getPC();
631 for(int i = base; i < pc; i += 4) {
632 fprintf(out, "%08x: %08x ", i, *(int*) i);
633 ::disasm(&di, i, 0);
634 }
635 return 0;
636 }
Jack Palevich7810bc92009-05-15 14:31:47 -0700637
Jack Palevich22305132009-05-13 10:58:45 -0700638 private:
Jack Palevicha6535612009-05-13 16:24:17 -0700639 static FILE* disasmOut;
640
641 static u_int
642 disassemble_readword(u_int address)
643 {
644 return(*((u_int *)address));
645 }
646
647 static void
648 disassemble_printaddr(u_int address)
649 {
650 fprintf(disasmOut, "0x%08x", address);
651 }
652
653 static void
654 disassemble_printf(const char *fmt, ...) {
655 va_list ap;
656 va_start(ap, fmt);
657 vfprintf(disasmOut, fmt, ap);
658 va_end(ap);
659 }
660
661 static const int BRANCH_REL_ADDRESS_MASK = 0x00ffffff;
662
663 /** Encode a relative address that might also be
664 * a label.
665 */
666 int encodeAddress(int value) {
667 int base = getBase();
668 if (value >= base && value <= getPC() ) {
669 // This is a label, encode it relative to the base.
670 value = value - base;
671 }
672 return encodeRelAddress(value);
673 }
674
675 int encodeRelAddress(int value) {
676 return BRANCH_REL_ADDRESS_MASK & (value >> 2);
677 }
Jack Palevich22305132009-05-13 10:58:45 -0700678
Jack Palevich3d474a72009-05-15 15:12:38 -0700679 typedef int (*int2FnPtr)(int a, int b);
680 void callRuntime(int2FnPtr fn) {
681 o4(0xE59F2000); // ldr r2, .L1
682 o4(0xEA000000); // b .L99
683 o4((int) fn); //.L1: .word fn
684 o4(0xE12FFF32); //.L99: blx r2
685 }
686
687 static int runtime_DIV(int a, int b) {
688 return b / a;
689 }
690
691 static int runtime_MOD(int a, int b) {
692 return b % a;
693 }
694
Jack Palevich546b2242009-05-13 15:10:04 -0700695 void error(const char* fmt,...) {
696 va_list ap;
697 va_start(ap, fmt);
698 vfprintf(stderr, fmt, ap);
699 va_end(ap);
700 exit(12);
701 }
Jack Palevich22305132009-05-13 10:58:45 -0700702 };
703
Jack Palevich21a15a22009-05-11 14:49:29 -0700704 class X86CodeGenerator : public CodeGenerator {
705 public:
706 X86CodeGenerator() {}
707 virtual ~X86CodeGenerator() {}
708
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700709 /* returns address to patch with local variable size
710 */
Jack Palevich546b2242009-05-13 15:10:04 -0700711 virtual int functionEntry(int argCount) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700712 o(0xe58955); /* push %ebp, mov %esp, %ebp */
713 return oad(0xec81, 0); /* sub $xxx, %esp */
714 }
715
Jack Palevich546b2242009-05-13 15:10:04 -0700716 virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700717 o(0xc3c9); /* leave, ret */
Jack Palevich546b2242009-05-13 15:10:04 -0700718 *(int *) localVariableAddress = localVariableSize; /* save local variables */
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700719 }
720
Jack Palevich21a15a22009-05-11 14:49:29 -0700721 /* load immediate value */
Jack Palevich546b2242009-05-13 15:10:04 -0700722 virtual void li(int t) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700723 oad(0xb8, t); /* mov $xx, %eax */
724 }
725
Jack Palevich22305132009-05-13 10:58:45 -0700726 virtual int gjmp(int t) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700727 return psym(0xe9, t);
728 }
729
730 /* l = 0: je, l == 1: jne */
Jack Palevich22305132009-05-13 10:58:45 -0700731 virtual int gtst(bool l, int t) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700732 o(0x0fc085); /* test %eax, %eax, je/jne xxx */
733 return psym(0x84 + l, t);
734 }
735
Jack Palevich22305132009-05-13 10:58:45 -0700736 virtual void gcmp(int op) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700737 int t = decodeOp(op);
Jack Palevich21a15a22009-05-11 14:49:29 -0700738 o(0xc139); /* cmp %eax,%ecx */
739 li(0);
740 o(0x0f); /* setxx %al */
741 o(t + 0x90);
742 o(0xc0);
743 }
744
Jack Palevich546b2242009-05-13 15:10:04 -0700745 virtual void genOp(int op) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700746 o(decodeOp(op));
747 if (op == OP_MOD)
748 o(0x92); /* xchg %edx, %eax */
749 }
750
Jack Palevich22305132009-05-13 10:58:45 -0700751 virtual void clearECX() {
Jack Palevich21a15a22009-05-11 14:49:29 -0700752 oad(0xb9, 0); /* movl $0, %ecx */
753 }
754
Jack Palevich22305132009-05-13 10:58:45 -0700755 virtual void pushEAX() {
Jack Palevich21a15a22009-05-11 14:49:29 -0700756 o(0x50); /* push %eax */
757 }
758
Jack Palevich22305132009-05-13 10:58:45 -0700759 virtual void popECX() {
Jack Palevich21a15a22009-05-11 14:49:29 -0700760 o(0x59); /* pop %ecx */
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700761 }
762
Jack Palevich22305132009-05-13 10:58:45 -0700763 virtual void storeEAXToAddressECX(bool isInt) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700764 o(0x0188 + isInt); /* movl %eax/%al, (%ecx) */
765 }
766
Jack Palevich22305132009-05-13 10:58:45 -0700767 virtual void loadEAXIndirect(bool isInt) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700768 if (isInt)
769 o(0x8b); /* mov (%eax), %eax */
770 else
771 o(0xbe0f); /* movsbl (%eax), %eax */
772 ob(0); /* add zero in code */
773 }
774
Jack Palevich22305132009-05-13 10:58:45 -0700775 virtual void leaEAX(int ea) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700776 gmov(10, ea); /* leal EA, %eax */
777 }
778
Jack Palevich22305132009-05-13 10:58:45 -0700779 virtual void storeEAX(int ea) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700780 gmov(6, ea); /* mov %eax, EA */
781 }
782
Jack Palevich4d93f302009-05-15 13:30:00 -0700783 virtual void loadEAX(int ea, bool isIncDec, int op) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700784 gmov(8, ea); /* mov EA, %eax */
Jack Palevich4d93f302009-05-15 13:30:00 -0700785 if (isIncDec) {
786 /* Implement post-increment or post decrement.
787 */
788 gmov(0, ea); /* 83 ADD */
789 o(decodeOp(op));
790 }
Jack Palevich21a15a22009-05-11 14:49:29 -0700791 }
792
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700793 virtual int beginFunctionCallArguments() {
Jack Palevich21a15a22009-05-11 14:49:29 -0700794 return oad(0xec81, 0); /* sub $xxx, %esp */
795 }
796
Jack Palevich22305132009-05-13 10:58:45 -0700797 virtual void storeEAToArg(int l) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700798 oad(0x248489, l); /* movl %eax, xxx(%esp) */
799 }
800
Jack Palevich7810bc92009-05-15 14:31:47 -0700801 virtual void endFunctionCallArguments(int a, int l) {
802 * (int*) a = l;
803 }
804
Jack Palevich22305132009-05-13 10:58:45 -0700805 virtual int callForward(int symbol) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700806 return psym(0xe8, symbol); /* call xxx */
807 }
808
Jack Palevich22305132009-05-13 10:58:45 -0700809 virtual void callRelative(int t) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700810 psym(0xe8, t); /* call xxx */
811 }
812
Jack Palevich22305132009-05-13 10:58:45 -0700813 virtual void callIndirect(int l) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700814 oad(0x2494ff, l); /* call *xxx(%esp) */
815 }
816
Jack Palevich7810bc92009-05-15 14:31:47 -0700817 virtual void adjustStackAfterCall(int l, bool isIndirect) {
818 if (isIndirect) {
819 l += 4;
820 }
Jack Palevich21a15a22009-05-11 14:49:29 -0700821 oad(0xc481, l); /* add $xxx, %esp */
822 }
823
Jack Palevicha6535612009-05-13 16:24:17 -0700824 virtual int jumpOffset() {
825 return 5;
826 }
827
828 virtual int disassemble(FILE* out) {
829 return 1;
830 }
831
Jack Palevich21a15a22009-05-11 14:49:29 -0700832 private:
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700833 static const int operatorHelper[];
834
835 int decodeOp(int op) {
836 if (op < 0 || op > OP_COUNT) {
837 fprintf(stderr, "Out-of-range operator: %d\n", op);
838 exit(1);
839 }
840 return operatorHelper[op];
841 }
Jack Palevich21a15a22009-05-11 14:49:29 -0700842
Jack Palevich546b2242009-05-13 15:10:04 -0700843 void gmov(int l, int t) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700844 o(l + 0x83);
845 oad((t < LOCAL) << 7 | 5, t);
846 }
847 };
848
849 /* vars: value of variables
850 loc : local variable index
851 glo : global variable index
852 ind : output code ptr
853 rsym: return symbol
854 prog: output code
855 dstk: define stack
856 dptr, dch: macro state
857 */
858 int tok, tokc, tokl, ch, vars, rsym, loc, glo, sym_stk, dstk,
859 dptr, dch, last_id;
860 void* pSymbolBase;
861 void* pGlobalBase;
862 void* pVarsBase;
863 FILE* file;
864
865 CodeBuf codeBuf;
Jack Palevich22305132009-05-13 10:58:45 -0700866 CodeGenerator* pGen;
Jack Palevich21a15a22009-05-11 14:49:29 -0700867
868 static const int ALLOC_SIZE = 99999;
869
870 /* depends on the init string */
871 static const int TOK_STR_SIZE = 48;
872 static const int TOK_IDENT = 0x100;
873 static const int TOK_INT = 0x100;
874 static const int TOK_IF = 0x120;
875 static const int TOK_ELSE = 0x138;
876 static const int TOK_WHILE = 0x160;
877 static const int TOK_BREAK = 0x190;
878 static const int TOK_RETURN = 0x1c0;
879 static const int TOK_FOR = 0x1f8;
880 static const int TOK_DEFINE = 0x218;
881 static const int TOK_MAIN = 0x250;
882
883 static const int TOK_DUMMY = 1;
884 static const int TOK_NUM = 2;
885
886 static const int LOCAL = 0x200;
887
888 static const int SYM_FORWARD = 0;
889 static const int SYM_DEFINE = 1;
890
891 /* tokens in string heap */
892 static const int TAG_TOK = ' ';
893 static const int TAG_MACRO = 2;
894
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700895 static const int OP_INCREMENT = 0;
896 static const int OP_DECREMENT = 1;
897 static const int OP_MUL = 2;
898 static const int OP_DIV = 3;
899 static const int OP_MOD = 4;
900 static const int OP_PLUS = 5;
901 static const int OP_MINUS = 6;
902 static const int OP_SHIFT_LEFT = 7;
903 static const int OP_SHIFT_RIGHT = 8;
904 static const int OP_LESS_EQUAL = 9;
905 static const int OP_GREATER_EQUAL = 10;
906 static const int OP_LESS = 11;
907 static const int OP_GREATER = 12;
908 static const int OP_EQUALS = 13;
909 static const int OP_NOT_EQUALS = 14;
910 static const int OP_LOGICAL_AND = 15;
911 static const int OP_LOGICAL_OR = 16;
912 static const int OP_BIT_AND = 17;
913 static const int OP_BIT_XOR = 18;
914 static const int OP_BIT_OR = 19;
915 static const int OP_BIT_NOT = 20;
916 static const int OP_LOGICAL_NOT = 21;
917 static const int OP_COUNT = 22;
918
919 /* Operators are searched from front, the two-character operators appear
920 * before the single-character operators with the same first character.
921 * @ is used to pad out single-character operators.
922 */
923 static const char* operatorChars;
924 static const char operatorLevel[];
925
Jack Palevich21a15a22009-05-11 14:49:29 -0700926 void pdef(int t) {
927 *(char *) dstk++ = t;
928 }
929
930 void inp() {
931 if (dptr) {
932 ch = *(char *) dptr++;
933 if (ch == TAG_MACRO) {
934 dptr = 0;
935 ch = dch;
936 }
937 } else
938 ch = fgetc(file);
939 /* printf("ch=%c 0x%x\n", ch, ch); */
940 }
941
942 int isid() {
Jack Palevich546b2242009-05-13 15:10:04 -0700943 return isalnum(ch) | (ch == '_');
Jack Palevich21a15a22009-05-11 14:49:29 -0700944 }
945
946 /* read a character constant */
947 void getq() {
948 if (ch == '\\') {
949 inp();
950 if (ch == 'n')
951 ch = '\n';
952 }
953 }
954
955 void next() {
956 int l, a;
957
Jack Palevich546b2242009-05-13 15:10:04 -0700958 while (isspace(ch) | (ch == '#')) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700959 if (ch == '#') {
960 inp();
961 next();
962 if (tok == TOK_DEFINE) {
963 next();
964 pdef(TAG_TOK); /* fill last ident tag */
965 *(int *) tok = SYM_DEFINE;
966 *(int *) (tok + 4) = dstk; /* define stack */
967 }
968 /* well we always save the values ! */
969 while (ch != '\n') {
970 pdef(ch);
971 inp();
972 }
973 pdef(ch);
974 pdef(TAG_MACRO);
975 }
976 inp();
977 }
978 tokl = 0;
979 tok = ch;
980 /* encode identifiers & numbers */
981 if (isid()) {
982 pdef(TAG_TOK);
983 last_id = dstk;
984 while (isid()) {
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700985 pdef(ch);
986 inp();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700987 }
Jack Palevich21a15a22009-05-11 14:49:29 -0700988 if (isdigit(tok)) {
989 tokc = strtol((char*) last_id, 0, 0);
990 tok = TOK_NUM;
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700991 } else {
Jack Palevich21a15a22009-05-11 14:49:29 -0700992 *(char *) dstk = TAG_TOK; /* no need to mark end of string (we
993 suppose data is initialized to zero by calloc) */
994 tok = (int) (strstr((char*) sym_stk, (char*) (last_id - 1))
995 - sym_stk);
996 *(char *) dstk = 0; /* mark real end of ident for dlsym() */
997 tok = tok * 8 + TOK_IDENT;
998 if (tok > TOK_DEFINE) {
999 tok = vars + tok;
1000 /* printf("tok=%s %x\n", last_id, tok); */
1001 /* define handling */
1002 if (*(int *) tok == SYM_DEFINE) {
1003 dptr = *(int *) (tok + 4);
1004 dch = ch;
1005 inp();
1006 next();
1007 }
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001008 }
1009 }
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001010 } else {
Jack Palevich21a15a22009-05-11 14:49:29 -07001011 inp();
1012 if (tok == '\'') {
1013 tok = TOK_NUM;
1014 getq();
1015 tokc = ch;
1016 inp();
1017 inp();
Jack Palevich546b2242009-05-13 15:10:04 -07001018 } else if ((tok == '/') & (ch == '*')) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001019 inp();
1020 while (ch) {
1021 while (ch != '*')
1022 inp();
1023 inp();
1024 if (ch == '/')
1025 ch = 0;
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001026 }
Jack Palevich21a15a22009-05-11 14:49:29 -07001027 inp();
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001028 next();
Jack Palevichbd894902009-05-14 19:35:31 -07001029 } else if ((tok == '/') & (ch == '/')) {
1030 inp();
1031 while (ch && (ch != '\n')) {
1032 inp();
1033 }
1034 inp();
1035 next();
Jack Palevich21a15a22009-05-11 14:49:29 -07001036 } else {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001037 const char* t = operatorChars;
1038 int opIndex = 0;
Jack Palevich546b2242009-05-13 15:10:04 -07001039 while ((l = *t++) != 0) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001040 a = *t++;
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001041 tokl = operatorLevel[opIndex];
1042 tokc = opIndex;
Jack Palevich546b2242009-05-13 15:10:04 -07001043 if ((l == tok) & ((a == ch) | (a == '@'))) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001044#if 0
1045 printf("%c%c -> tokl=%d tokc=0x%x\n",
1046 l, a, tokl, tokc);
1047#endif
1048 if (a == ch) {
1049 inp();
1050 tok = TOK_DUMMY; /* dummy token for double tokens */
1051 }
1052 break;
1053 }
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001054 opIndex++;
1055 }
1056 if (l == 0) {
1057 tokl = 0;
1058 tokc = 0;
Jack Palevich21a15a22009-05-11 14:49:29 -07001059 }
1060 }
1061 }
1062#if 0
1063 {
1064 int p;
1065
1066 printf("tok=0x%x ", tok);
1067 if (tok >= TOK_IDENT) {
1068 printf("'");
1069 if (tok> TOK_DEFINE)
1070 p = sym_stk + 1 + (tok - vars - TOK_IDENT) / 8;
1071 else
1072 p = sym_stk + 1 + (tok - TOK_IDENT) / 8;
1073 while (*(char *)p != TAG_TOK && *(char *)p)
1074 printf("%c", *(char *)p++);
1075 printf("'\n");
1076 } else if (tok == TOK_NUM) {
1077 printf("%d\n", tokc);
1078 } else {
1079 printf("'%c'\n", tok);
1080 }
1081 }
1082#endif
1083 }
1084
1085 void error(const char *fmt, ...) {
1086 va_list ap;
1087
1088 va_start(ap, fmt);
1089 fprintf(stderr, "%ld: ", ftell((FILE *) file));
1090 vfprintf(stderr, fmt, ap);
1091 fprintf(stderr, "\n");
1092 va_end(ap);
1093 exit(1);
1094 }
1095
1096 void skip(int c) {
1097 if (tok != c) {
1098 error("'%c' expected", c);
1099 }
1100 next();
1101 }
1102
Jack Palevich21a15a22009-05-11 14:49:29 -07001103 /* l is one if '=' parsing wanted (quick hack) */
1104 void unary(int l) {
1105 int n, t, a, c;
Jack Palevich546b2242009-05-13 15:10:04 -07001106 t = 0;
Jack Palevich21a15a22009-05-11 14:49:29 -07001107 n = 1; /* type of expression 0 = forward, 1 = value, other =
1108 lvalue */
1109 if (tok == '\"') {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001110 pGen->li(glo);
Jack Palevich21a15a22009-05-11 14:49:29 -07001111 while (ch != '\"') {
1112 getq();
1113 *(char *) glo++ = ch;
1114 inp();
1115 }
1116 *(char *) glo = 0;
Jack Palevich546b2242009-05-13 15:10:04 -07001117 glo = (glo + 4) & -4; /* align heap */
Jack Palevich21a15a22009-05-11 14:49:29 -07001118 inp();
1119 next();
1120 } else {
1121 c = tokl;
1122 a = tokc;
1123 t = tok;
1124 next();
1125 if (t == TOK_NUM) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001126 pGen->li(a);
Jack Palevich21a15a22009-05-11 14:49:29 -07001127 } else if (c == 2) {
1128 /* -, +, !, ~ */
1129 unary(0);
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001130 pGen->clearECX();
Jack Palevich21a15a22009-05-11 14:49:29 -07001131 if (t == '!')
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001132 pGen->gcmp(a);
Jack Palevich21a15a22009-05-11 14:49:29 -07001133 else
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001134 pGen->genOp(a);
Jack Palevich21a15a22009-05-11 14:49:29 -07001135 } else if (t == '(') {
1136 expr();
1137 skip(')');
1138 } else if (t == '*') {
1139 /* parse cast */
1140 skip('(');
1141 t = tok; /* get type */
1142 next(); /* skip int/char/void */
1143 next(); /* skip '*' or '(' */
1144 if (tok == '*') {
1145 /* function type */
1146 skip('*');
1147 skip(')');
1148 skip('(');
1149 skip(')');
1150 t = 0;
1151 }
1152 skip(')');
1153 unary(0);
1154 if (tok == '=') {
1155 next();
1156 pGen->pushEAX();
1157 expr();
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001158 pGen->popECX();
1159 pGen->storeEAXToAddressECX(t == TOK_INT);
Jack Palevich21a15a22009-05-11 14:49:29 -07001160 } else if (t) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001161 pGen->loadEAXIndirect(t == TOK_INT);
Jack Palevich21a15a22009-05-11 14:49:29 -07001162 }
1163 } else if (t == '&') {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001164 pGen->leaEAX(*(int *) tok);
Jack Palevich21a15a22009-05-11 14:49:29 -07001165 next();
1166 } else {
1167 n = *(int *) t;
1168 /* forward reference: try dlsym */
Jack Palevichcb1c9ef2009-05-14 11:38:49 -07001169 if (!n) {
1170 n = (int) dlsym(RTLD_DEFAULT, (char*) last_id);
1171 }
Jack Palevich546b2242009-05-13 15:10:04 -07001172 if ((tok == '=') & l) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001173 /* assignment */
1174 next();
1175 expr();
1176 pGen->storeEAX(n);
1177 } else if (tok != '(') {
1178 /* variable */
Jack Palevich4d93f302009-05-15 13:30:00 -07001179 pGen->loadEAX(n, tokl == 11, tokc);
Jack Palevich21a15a22009-05-11 14:49:29 -07001180 if (tokl == 11) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001181 next();
1182 }
1183 }
1184 }
1185 }
1186
1187 /* function call */
1188 if (tok == '(') {
1189 if (n == 1)
1190 pGen->pushEAX();
1191
1192 /* push args and invert order */
Jack Palevichcb1c9ef2009-05-14 11:38:49 -07001193 a = pGen->beginFunctionCallArguments();
Jack Palevich21a15a22009-05-11 14:49:29 -07001194 next();
1195 l = 0;
1196 while (tok != ')') {
1197 expr();
1198 pGen->storeEAToArg(l);
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001199 if (tok == ',')
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001200 next();
Jack Palevich21a15a22009-05-11 14:49:29 -07001201 l = l + 4;
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001202 }
Jack Palevichcb1c9ef2009-05-14 11:38:49 -07001203 pGen->endFunctionCallArguments(a, l);
Jack Palevich21a15a22009-05-11 14:49:29 -07001204 next();
1205 if (!n) {
1206 /* forward reference */
1207 t = t + 4;
1208 *(int *) t = pGen->callForward(*(int *) t);
1209 } else if (n == 1) {
1210 pGen->callIndirect(l);
Jack Palevich21a15a22009-05-11 14:49:29 -07001211 } else {
Jack Palevich7810bc92009-05-15 14:31:47 -07001212 pGen->callRelative(n - codeBuf.getPC() - pGen->jumpOffset());
Jack Palevich21a15a22009-05-11 14:49:29 -07001213 }
Jack Palevich3d474a72009-05-15 15:12:38 -07001214 if (l | (n == 1))
Jack Palevich7810bc92009-05-15 14:31:47 -07001215 pGen->adjustStackAfterCall(l, n == 1);
Jack Palevich21a15a22009-05-11 14:49:29 -07001216 }
1217 }
1218
1219 void sum(int l) {
1220 int t, n, a;
Jack Palevich546b2242009-05-13 15:10:04 -07001221 t = 0;
Jack Palevich21a15a22009-05-11 14:49:29 -07001222 if (l-- == 1)
1223 unary(1);
1224 else {
1225 sum(l);
1226 a = 0;
1227 while (l == tokl) {
1228 n = tok;
1229 t = tokc;
1230 next();
1231
1232 if (l > 8) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001233 a = pGen->gtst(t == OP_LOGICAL_OR, a); /* && and || output code generation */
Jack Palevich21a15a22009-05-11 14:49:29 -07001234 sum(l);
1235 } else {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001236 pGen->pushEAX();
Jack Palevich21a15a22009-05-11 14:49:29 -07001237 sum(l);
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001238 pGen->popECX();
Jack Palevich21a15a22009-05-11 14:49:29 -07001239
Jack Palevich546b2242009-05-13 15:10:04 -07001240 if ((l == 4) | (l == 5)) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001241 pGen->gcmp(t);
Jack Palevich21a15a22009-05-11 14:49:29 -07001242 } else {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001243 pGen->genOp(t);
Jack Palevich21a15a22009-05-11 14:49:29 -07001244 }
1245 }
1246 }
1247 /* && and || output code generation */
1248 if (a && l > 8) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001249 a = pGen->gtst(t == OP_LOGICAL_OR, a);
1250 pGen->li(t != OP_LOGICAL_OR);
Jack Palevicha6535612009-05-13 16:24:17 -07001251 pGen->gjmp(5); /* jmp $ + 5 (sizeof li, FIXME for ARM) */
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001252 pGen->gsym(a);
1253 pGen->li(t == OP_LOGICAL_OR);
Jack Palevich21a15a22009-05-11 14:49:29 -07001254 }
1255 }
1256 }
1257
1258 void expr() {
1259 sum(11);
1260 }
1261
1262 int test_expr() {
1263 expr();
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001264 return pGen->gtst(0, 0);
Jack Palevich21a15a22009-05-11 14:49:29 -07001265 }
1266
1267 void block(int l) {
1268 int a, n, t;
1269
1270 if (tok == TOK_IF) {
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001271 next();
1272 skip('(');
Jack Palevich21a15a22009-05-11 14:49:29 -07001273 a = test_expr();
1274 skip(')');
1275 block(l);
1276 if (tok == TOK_ELSE) {
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001277 next();
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001278 n = pGen->gjmp(0); /* jmp */
1279 pGen->gsym(a);
Jack Palevich21a15a22009-05-11 14:49:29 -07001280 block(l);
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001281 pGen->gsym(n); /* patch else jmp */
Jack Palevich21a15a22009-05-11 14:49:29 -07001282 } else {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001283 pGen->gsym(a); /* patch if test */
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001284 }
Jack Palevich546b2242009-05-13 15:10:04 -07001285 } else if ((tok == TOK_WHILE) | (tok == TOK_FOR)) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001286 t = tok;
1287 next();
1288 skip('(');
1289 if (t == TOK_WHILE) {
Jack Palevicha6535612009-05-13 16:24:17 -07001290 n = codeBuf.getPC(); // top of loop, target of "next" iteration
Jack Palevich21a15a22009-05-11 14:49:29 -07001291 a = test_expr();
1292 } else {
1293 if (tok != ';')
1294 expr();
1295 skip(';');
1296 n = codeBuf.getPC();
1297 a = 0;
1298 if (tok != ';')
1299 a = test_expr();
1300 skip(';');
1301 if (tok != ')') {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001302 t = pGen->gjmp(0);
Jack Palevich21a15a22009-05-11 14:49:29 -07001303 expr();
Jack Palevicha6535612009-05-13 16:24:17 -07001304 pGen->gjmp(n - codeBuf.getPC() - pGen->jumpOffset());
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001305 pGen->gsym(t);
Jack Palevich21a15a22009-05-11 14:49:29 -07001306 n = t + 4;
1307 }
1308 }
1309 skip(')');
1310 block((int) &a);
Jack Palevicha6535612009-05-13 16:24:17 -07001311 pGen->gjmp(n - codeBuf.getPC() - pGen->jumpOffset()); /* jmp */
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001312 pGen->gsym(a);
Jack Palevich21a15a22009-05-11 14:49:29 -07001313 } else if (tok == '{') {
1314 next();
1315 /* declarations */
1316 decl(1);
1317 while (tok != '}')
1318 block(l);
1319 next();
1320 } else {
1321 if (tok == TOK_RETURN) {
1322 next();
1323 if (tok != ';')
1324 expr();
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001325 rsym = pGen->gjmp(rsym); /* jmp */
Jack Palevich21a15a22009-05-11 14:49:29 -07001326 } else if (tok == TOK_BREAK) {
1327 next();
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001328 *(int *) l = pGen->gjmp(*(int *) l);
Jack Palevich21a15a22009-05-11 14:49:29 -07001329 } else if (tok != ';')
1330 expr();
1331 skip(';');
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001332 }
1333 }
Jack Palevich21a15a22009-05-11 14:49:29 -07001334
1335 /* 'l' is true if local declarations */
1336 void decl(int l) {
1337 int a;
1338
Jack Palevich546b2242009-05-13 15:10:04 -07001339 while ((tok == TOK_INT) | ((tok != -1) & (!l))) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001340 if (tok == TOK_INT) {
1341 next();
1342 while (tok != ';') {
1343 if (l) {
1344 loc = loc + 4;
1345 *(int *) tok = -loc;
1346 } else {
1347 *(int *) tok = glo;
1348 glo = glo + 4;
1349 }
1350 next();
1351 if (tok == ',')
1352 next();
1353 }
1354 skip(';');
1355 } else {
1356 /* patch forward references (XXX: do not work for function
1357 pointers) */
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001358 pGen->gsym(*(int *) (tok + 4));
Jack Palevich21a15a22009-05-11 14:49:29 -07001359 /* put function address */
1360 *(int *) tok = codeBuf.getPC();
1361 next();
1362 skip('(');
1363 a = 8;
Jack Palevich546b2242009-05-13 15:10:04 -07001364 int argCount = 0;
Jack Palevich21a15a22009-05-11 14:49:29 -07001365 while (tok != ')') {
1366 /* read param name and compute offset */
1367 *(int *) tok = a;
1368 a = a + 4;
1369 next();
1370 if (tok == ',')
1371 next();
Jack Palevich546b2242009-05-13 15:10:04 -07001372 argCount++;
Jack Palevich21a15a22009-05-11 14:49:29 -07001373 }
1374 next(); /* skip ')' */
1375 rsym = loc = 0;
Jack Palevich546b2242009-05-13 15:10:04 -07001376 a = pGen->functionEntry(argCount);
Jack Palevich21a15a22009-05-11 14:49:29 -07001377 block(0);
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001378 pGen->gsym(rsym);
Jack Palevich546b2242009-05-13 15:10:04 -07001379 pGen->functionExit(argCount, a, loc);
Jack Palevich21a15a22009-05-11 14:49:29 -07001380 }
1381 }
1382 }
1383
1384 void cleanup() {
1385 if (sym_stk != 0) {
1386 free((void*) sym_stk);
1387 sym_stk = 0;
1388 }
1389 if (pGlobalBase != 0) {
1390 free((void*) pGlobalBase);
1391 pGlobalBase = 0;
1392 }
1393 if (pVarsBase != 0) {
1394 free(pVarsBase);
1395 pVarsBase = 0;
1396 }
1397 if (pGen) {
1398 delete pGen;
1399 pGen = 0;
1400 }
1401 }
1402
1403 void clear() {
1404 tok = 0;
1405 tokc = 0;
1406 tokl = 0;
1407 ch = 0;
1408 vars = 0;
1409 rsym = 0;
1410 loc = 0;
1411 glo = 0;
1412 sym_stk = 0;
1413 dstk = 0;
1414 dptr = 0;
1415 dch = 0;
1416 last_id = 0;
1417 file = 0;
1418 pGlobalBase = 0;
1419 pVarsBase = 0;
1420 pGen = 0;
1421 }
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001422
Jack Palevich22305132009-05-13 10:58:45 -07001423 void setArchitecture(const char* architecture) {
1424 delete pGen;
1425 pGen = 0;
1426
1427 if (architecture != NULL) {
1428 if (strcmp(architecture, "arm") == 0) {
1429 pGen = new ARMCodeGenerator();
1430 } else if (strcmp(architecture, "x86") == 0) {
1431 pGen = new X86CodeGenerator();
1432 } else {
1433 fprintf(stderr, "Unknown architecture %s", architecture);
1434 }
1435 }
1436
1437 if (pGen == NULL) {
1438 pGen = new ARMCodeGenerator();
1439 }
1440 }
1441
Jack Palevich77ae76e2009-05-10 19:59:24 -07001442public:
Jack Palevich22305132009-05-13 10:58:45 -07001443 struct args {
1444 args() {
1445 architecture = 0;
1446 }
1447 const char* architecture;
1448 };
1449
Jack Palevich21a15a22009-05-11 14:49:29 -07001450 compiler() {
1451 clear();
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001452 }
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001453
Jack Palevich21a15a22009-05-11 14:49:29 -07001454 ~compiler() {
1455 cleanup();
1456 }
1457
Jack Palevich22305132009-05-13 10:58:45 -07001458 int compile(FILE* in, args& args) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001459 cleanup();
1460 clear();
1461 codeBuf.init(ALLOC_SIZE);
Jack Palevich22305132009-05-13 10:58:45 -07001462 setArchitecture(args.architecture);
Jack Palevich21a15a22009-05-11 14:49:29 -07001463 pGen->init(&codeBuf);
1464 file = in;
1465 sym_stk = (int) calloc(1, ALLOC_SIZE);
1466 dstk = (int) strcpy((char*) sym_stk,
1467 " int if else while break return for define main ")
1468 + TOK_STR_SIZE;
1469 pGlobalBase = calloc(1, ALLOC_SIZE);
1470 glo = (int) pGlobalBase;
1471 pVarsBase = calloc(1, ALLOC_SIZE);
1472 vars = (int) pVarsBase;
1473 inp();
1474 next();
1475 decl(0);
Jack Palevich546b2242009-05-13 15:10:04 -07001476 pGen->finishCompile();
Jack Palevich21a15a22009-05-11 14:49:29 -07001477 return 0;
1478 }
1479
1480 int run(int argc, char** argv) {
1481 typedef int (*mainPtr)(int argc, char** argv);
1482 mainPtr aMain = (mainPtr) *(int*) (vars + TOK_MAIN);
1483 if (!aMain) {
1484 fprintf(stderr, "Could not find function \"main\".\n");
1485 return -1;
1486 }
1487 return aMain(argc, argv);
1488 }
1489
1490 int dump(FILE* out) {
1491 fwrite(codeBuf.getBase(), 1, codeBuf.getSize(), out);
1492 return 0;
1493 }
Jack Palevich77ae76e2009-05-10 19:59:24 -07001494
Jack Palevicha6535612009-05-13 16:24:17 -07001495 int disassemble(FILE* out) {
1496 return pGen->disassemble(out);
1497 }
1498
Jack Palevich77ae76e2009-05-10 19:59:24 -07001499};
1500
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001501const char* compiler::operatorChars =
1502 "++--*@/@%@+@-@<<>><=>=<@>@==!=&&||&@^@|@~@!@";
1503
1504const char compiler::operatorLevel[] =
1505 {11, 11, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4,
1506 5, 5, /* ==, != */
1507 9, 10, /* &&, || */
1508 6, 7, 8, /* & ^ | */
1509 2, 2 /* ~ ! */
1510 };
1511
Jack Palevicha6535612009-05-13 16:24:17 -07001512FILE* compiler::ARMCodeGenerator::disasmOut;
1513
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001514const int compiler::X86CodeGenerator::operatorHelper[] = {
1515 0x1, // ++
1516 0xff, // --
1517 0xc1af0f, // *
1518 0xf9f79991, // /
1519 0xf9f79991, // % (With manual assist to swap results)
1520 0xc801, // +
1521 0xd8f7c829, // -
1522 0xe0d391, // <<
1523 0xf8d391, // >>
1524 0xe, // <=
1525 0xd, // >=
1526 0xc, // <
1527 0xf, // >
1528 0x4, // ==
1529 0x5, // !=
1530 0x0, // &&
1531 0x1, // ||
1532 0xc821, // &
1533 0xc831, // ^
1534 0xc809, // |
1535 0xd0f7, // ~
1536 0x4 // !
1537};
1538
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001539} // namespace acc
1540
Jack Palevich546b2242009-05-13 15:10:04 -07001541// This is a separate function so it can easily be set by breakpoint in gdb.
1542int run(acc::compiler& c, int argc, char** argv) {
1543 return c.run(argc, argv);
1544}
1545
Jack Palevich77ae76e2009-05-10 19:59:24 -07001546int main(int argc, char** argv) {
Jack Palevich22305132009-05-13 10:58:45 -07001547 bool doDump = false;
Jack Palevicha6535612009-05-13 16:24:17 -07001548 bool doDisassemble = false;
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001549 const char* inFile = NULL;
1550 const char* outFile = NULL;
Jack Palevich22305132009-05-13 10:58:45 -07001551 const char* architecture = "arm";
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001552 int i;
Jack Palevich21a15a22009-05-11 14:49:29 -07001553 for (i = 1; i < argc; i++) {
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001554 char* arg = argv[i];
1555 if (arg[0] == '-') {
1556 switch (arg[1]) {
Jack Palevich22305132009-05-13 10:58:45 -07001557 case 'a':
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001558 if (i + 1 >= argc) {
Jack Palevich22305132009-05-13 10:58:45 -07001559 fprintf(stderr, "Expected architecture after -a\n");
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001560 return 2;
1561 }
Jack Palevich22305132009-05-13 10:58:45 -07001562 architecture = argv[i+1];
1563 i += 1;
1564 break;
1565 case 'd':
1566 if (i + 1 >= argc) {
1567 fprintf(stderr, "Expected filename after -d\n");
1568 return 2;
1569 }
1570 doDump = true;
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001571 outFile = argv[i + 1];
1572 i += 1;
1573 break;
Jack Palevicha6535612009-05-13 16:24:17 -07001574 case 'S':
1575 doDisassemble = true;
1576 break;
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001577 default:
1578 fprintf(stderr, "Unrecognized flag %s\n", arg);
1579 return 3;
1580 }
1581 } else if (inFile == NULL) {
1582 inFile = arg;
1583 } else {
1584 break;
1585 }
1586 }
1587
1588 FILE* in = stdin;
1589 if (inFile) {
1590 in = fopen(inFile, "r");
Jack Palevich21a15a22009-05-11 14:49:29 -07001591 if (!in) {
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001592 fprintf(stderr, "Could not open input file %s\n", inFile);
1593 return 1;
1594 }
1595 }
1596 acc::compiler compiler;
Jack Palevich22305132009-05-13 10:58:45 -07001597 acc::compiler::args args;
1598 args.architecture = architecture;
1599 int compileResult = compiler.compile(in, args);
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001600 if (in != stdin) {
1601 fclose(in);
1602 }
1603 if (compileResult) {
1604 fprintf(stderr, "Compile failed: %d\n", compileResult);
1605 return 6;
1606 }
Jack Palevicha6535612009-05-13 16:24:17 -07001607 if (doDisassemble) {
1608 compiler.disassemble(stderr);
1609 }
Jack Palevich22305132009-05-13 10:58:45 -07001610 if (doDump) {
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001611 FILE* save = fopen(outFile, "w");
Jack Palevich21a15a22009-05-11 14:49:29 -07001612 if (!save) {
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001613 fprintf(stderr, "Could not open output file %s\n", outFile);
1614 return 5;
1615 }
1616 compiler.dump(save);
1617 fclose(save);
1618 } else {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001619 fprintf(stderr, "Executing compiled code:\n");
Jack Palevich21a15a22009-05-11 14:49:29 -07001620 int codeArgc = argc - i + 1;
1621 char** codeArgv = argv + i - 1;
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001622 codeArgv[0] = (char*) (inFile ? inFile : "stdin");
Jack Palevich546b2242009-05-13 15:10:04 -07001623 int result = run(compiler, codeArgc, codeArgv);
Jack Palevich22305132009-05-13 10:58:45 -07001624 fprintf(stderr, "result: %d\n", result);
1625 return result;
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001626 }
1627
1628 return 0;
1629}