blob: 59ce9b4f0964490dc73fb6de72c05f39ca501980 [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;
362 case OP_PLUS:
363 o4(0xE0810000); // add r0,r1,r0
364 break;
365 case OP_MINUS:
366 o4(0xE0410000); // sub r0,r1,r0
367 break;
368 case OP_SHIFT_LEFT:
369 o4(0xE1A00011); // lsl r0,r1,r0
370 break;
371 case OP_SHIFT_RIGHT:
372 o4(0xE1A00051); // asr r0,r1,r0
373 break;
374 case OP_BIT_AND:
375 o4(0xE0010000); // and r0,r1,r0
376 break;
377 case OP_BIT_XOR:
378 o4(0xE0210000); // eor r0,r1,r0
379 break;
380 case OP_BIT_OR:
381 o4(0xE1810000); // orr r0,r1,r0
382 break;
383 case OP_BIT_NOT:
384 o4(0xE1E00000); // mvn r0, r0
385 break;
386 default:
Jack Palevich69796b62009-05-14 15:42:26 -0700387 error("Unimplemented op %d\n", op);
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700388 break;
389 }
Jack Palevich22305132009-05-13 10:58:45 -0700390#if 0
391 o(decodeOp(op));
392 if (op == OP_MOD)
393 o(0x92); /* xchg %edx, %eax */
394#endif
395 }
396
397 virtual void clearECX() {
398 fprintf(stderr, "clearECX();\n");
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700399 o4(0xE3A01000); // mov r1, #0
Jack Palevich22305132009-05-13 10:58:45 -0700400 }
401
402 virtual void pushEAX() {
403 fprintf(stderr, "pushEAX();\n");
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700404 o4(0xE92D0001); // stmfd sp!,{r0}
Jack Palevich22305132009-05-13 10:58:45 -0700405 }
406
407 virtual void popECX() {
408 fprintf(stderr, "popECX();\n");
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700409 o4(0xE8BD0002); // ldmfd sp!,{r1}
Jack Palevich22305132009-05-13 10:58:45 -0700410 }
411
412 virtual void storeEAXToAddressECX(bool isInt) {
413 fprintf(stderr, "storeEAXToAddressECX(%d);\n", isInt);
Jack Palevichbd894902009-05-14 19:35:31 -0700414 if (isInt) {
415 o4(0xE5810000); // str r0, [r1]
416 } else {
417 o4(0xE5C10000); // strb r0, [r1]
418 }
Jack Palevich22305132009-05-13 10:58:45 -0700419 }
420
421 virtual void loadEAXIndirect(bool isInt) {
422 fprintf(stderr, "loadEAXIndirect(%d);\n", isInt);
423 if (isInt)
Jack Palevich69796b62009-05-14 15:42:26 -0700424 o4(0xE5900000); // ldr r0, [r0]
Jack Palevich22305132009-05-13 10:58:45 -0700425 else
Jack Palevich69796b62009-05-14 15:42:26 -0700426 o4(0xE5D00000); // ldrb r0, [r0]
Jack Palevich22305132009-05-13 10:58:45 -0700427 }
428
429 virtual void leaEAX(int ea) {
Jack Palevichbd894902009-05-14 19:35:31 -0700430 fprintf(stderr, "leaEAX(%d);\n", ea);
Jack Palevich4d93f302009-05-15 13:30:00 -0700431 if (ea < LOCAL) {
432 // Local, fp relative
433 if (ea < -1023 || ea > 1023 || ((ea & 3) != 0)) {
434 error("Offset out of range: %08x", ea);
435 }
436 if (ea < 0) {
437 o4(0xE24B0F00 | (0xff & ((-ea) >> 2))); // sub r0, fp, #ea
438 } else {
439 o4(0xE28B0F00 | (0xff & (ea >> 2))); // add r0, fp, #ea
440 }
Jack Palevichbd894902009-05-14 19:35:31 -0700441 } else {
Jack Palevich4d93f302009-05-15 13:30:00 -0700442 // Global, absolute.
443 o4(0xE59F0000); // ldr r0, .L1
444 o4(0xEA000000); // b .L99
445 o4(ea); // .L1: .word 0
446 // .L99:
Jack Palevichbd894902009-05-14 19:35:31 -0700447 }
Jack Palevich22305132009-05-13 10:58:45 -0700448 }
449
450 virtual void storeEAX(int ea) {
451 fprintf(stderr, "storeEAX(%d);\n", ea);
Jack Palevich4d93f302009-05-15 13:30:00 -0700452 if (ea < LOCAL) {
453 // Local, fp relative
454 if (ea < -4095 || ea > 4095) {
455 error("Offset out of range: %08x", ea);
456 }
457 if (ea < 0) {
458 o4(0xE50B0000 | (0xfff & (-ea))); // str r0, [fp,#-ea]
459 } else {
460 o4(0xE58B0000 | (0xfff & ea)); // str r0, [fp,#ea]
461 }
462 } else{
463 // Global, absolute
464 o4(0xE59F1000); // ldr r1, .L1
465 o4(0xEA000000); // b .L99
466 o4(ea); // .L1: .word 0
467 o4(0xE5810000); // .L99: str r0, [r1]
Jack Palevich69796b62009-05-14 15:42:26 -0700468 }
Jack Palevich22305132009-05-13 10:58:45 -0700469 }
470
Jack Palevich4d93f302009-05-15 13:30:00 -0700471 virtual void loadEAX(int ea, bool isIncDec, int op) {
472 fprintf(stderr, "loadEAX(%d, %d, %d);\n", ea, isIncDec, op);
473 if (ea < LOCAL) {
474 // Local, fp relative
475 if (ea < -4095 || ea > 4095) {
476 error("Offset out of range: %08x", ea);
477 }
478 if (ea < 0) {
479 o4(0xE51B0000 | (0xfff & (-ea))); // ldr r0, [fp,#-ea]
480 } else {
481 o4(0xE59B0000 | (0xfff & ea)); // ldr r0, [fp,#ea]
482 }
Jack Palevich69796b62009-05-14 15:42:26 -0700483 } else {
Jack Palevich4d93f302009-05-15 13:30:00 -0700484 // Global, absolute
485 o4(0xE59F2000); // ldr r2, .L1
486 o4(0xEA000000); // b .L99
487 o4(ea); // .L1: .word ea
488 o4(0xE5920000); // .L99: ldr r0, [r2]
Jack Palevich69796b62009-05-14 15:42:26 -0700489 }
Jack Palevich22305132009-05-13 10:58:45 -0700490
Jack Palevich4d93f302009-05-15 13:30:00 -0700491 if (isIncDec) {
492 switch (op) {
493 case OP_INCREMENT:
494 o4(0xE2801001); // add r1, r0, #1
495 break;
496 case OP_DECREMENT:
497 o4(0xE2401001); // sub r1, r0, #1
498 break;
499 default:
500 error("unknown opcode: %d", op);
501 }
502 if (ea < LOCAL) {
503 // Local, fp relative
504 // Don't need range check, was already checked above
505 if (ea < 0) {
506 o4(0xE50B1000 | (0xfff & (-ea))); // str r1, [fp,#-ea]
507 } else {
508 o4(0xE58B1000 | (0xfff & ea)); // str r1, [fp,#ea]
509 }
510 } else{
511 // Global, absolute
512 // r2 is already set up from before.
513 o4(0xE5821000); // str r1, [r2]
514 }
Jack Palevichbd894902009-05-14 19:35:31 -0700515 }
Jack Palevich22305132009-05-13 10:58:45 -0700516 }
517
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700518 virtual int beginFunctionCallArguments() {
519 fprintf(stderr, "beginFunctionCallArguments();\n");
520 return o4(0xE24DDF00); // Placeholder
521 }
522
Jack Palevich7810bc92009-05-15 14:31:47 -0700523 virtual void storeEAToArg(int l) {
524 fprintf(stderr, "storeEAToArg(%d);\n", l);
525 if (l < 0 || l > 4096-4) {
526 error("l out of range for stack offset: 0x%08x", l);
527 }
528 o4(0xE58D0000 + l); // str r0, [sp, #4]
529 }
530
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700531 virtual void endFunctionCallArguments(int a, int l) {
532 fprintf(stderr, "endFunctionCallArguments(0x%08x, %d);\n", a, l);
533 if (l < 0 || l > 0x3FC) {
534 error("L out of range for stack adjustment: 0x%08x", l);
535 }
536 * (int*) a = 0xE24DDF00 | (l >> 2); // sub sp, sp, #0 << 2
537 int argCount = l >> 2;
538 if (argCount > 0) {
539 int regArgCount = argCount > 4 ? 4 : argCount;
540 o4(0xE8BD0000 | ((1 << regArgCount) - 1)); // ldmfd sp!,{}
541 }
Jack Palevich22305132009-05-13 10:58:45 -0700542 }
543
Jack Palevich22305132009-05-13 10:58:45 -0700544 virtual int callForward(int symbol) {
545 fprintf(stderr, "callForward(%d);\n", symbol);
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700546 // Forward calls are always short (local)
547 return o4(0xEB000000 | encodeAddress(symbol));
Jack Palevich22305132009-05-13 10:58:45 -0700548 }
549
550 virtual void callRelative(int t) {
551 fprintf(stderr, "callRelative(%d);\n", t);
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700552 int abs = t + getPC() + jumpOffset();
Jack Palevichbd894902009-05-14 19:35:31 -0700553 fprintf(stderr, "abs=%d (0x%08x)\n", abs, abs);
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700554 if (t >= - (1 << 25) && t < (1 << 25)) {
555 o4(0xEB000000 | encodeAddress(t));
556 } else {
557 // Long call.
558 o4(0xE59FC000); // ldr r12, .L1
559 o4(0xEA000000); // b .L99
Jack Palevichbd894902009-05-14 19:35:31 -0700560 o4(t - 12); // .L1: .word 0
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700561 o4(0xE08CC00F); // .L99: add r12,pc
562 o4(0xE12FFF3C); // blx r12
563 }
Jack Palevich22305132009-05-13 10:58:45 -0700564 }
565
566 virtual void callIndirect(int l) {
567 fprintf(stderr, "callIndirect(%d);\n", l);
Jack Palevich7810bc92009-05-15 14:31:47 -0700568 int argCount = l >> 2;
569 int poppedArgs = argCount > 4 ? 4 : argCount;
570 int adjustedL = l - (poppedArgs << 2);
571 if (adjustedL < 0 || adjustedL > 4096-4) {
572 error("l out of range for stack offset: 0x%08x", l);
573 }
574 o4(0xE59DC000 | (0xfff & adjustedL)); // ldr r12, [sp,#adjustedL]
575 o4(0xE12FFF3C); // blx r12
Jack Palevich22305132009-05-13 10:58:45 -0700576 }
577
Jack Palevich7810bc92009-05-15 14:31:47 -0700578 virtual void adjustStackAfterCall(int l, bool isIndirect) {
579 fprintf(stderr, "adjustStackAfterCall(%d, %d);\n", l, isIndirect);
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700580 int argCount = l >> 2;
Jack Palevich7810bc92009-05-15 14:31:47 -0700581 int stackArgs = argCount > 4 ? argCount - 4 : 0;
582 int stackUse = stackArgs + (isIndirect ? 1 : 0);
583 if (stackUse) {
584 if (stackUse < 0 || stackUse > 255) {
585 error("L out of range for stack adjustment: 0x%08x", l);
586 }
587 o4(0xE28DDF00 | stackUse); // add sp, sp, #stackUse << 2
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700588 }
Jack Palevich22305132009-05-13 10:58:45 -0700589 }
590
Jack Palevicha6535612009-05-13 16:24:17 -0700591 virtual int jumpOffset() {
Jack Palevichbd894902009-05-14 19:35:31 -0700592 return 8;
Jack Palevicha6535612009-05-13 16:24:17 -0700593 }
594
595 /* output a symbol and patch all calls to it */
596 virtual void gsym(int t) {
597 fprintf(stderr, "gsym(0x%x)\n", t);
598 int n;
599 int base = getBase();
600 int pc = getPC();
601 fprintf(stderr, "pc = 0x%x\n", pc);
602 while (t) {
603 int data = * (int*) t;
604 int decodedOffset = ((BRANCH_REL_ADDRESS_MASK & data) << 2);
605 if (decodedOffset == 0) {
606 n = 0;
607 } else {
608 n = base + decodedOffset; /* next value */
609 }
610 *(int *) t = (data & ~BRANCH_REL_ADDRESS_MASK)
611 | encodeRelAddress(pc - t - 8);
612 t = n;
613 }
614 }
615
616 virtual int disassemble(FILE* out) {
617 disasmOut = out;
618 disasm_interface_t di;
619 di.di_readword = disassemble_readword;
620 di.di_printaddr = disassemble_printaddr;
621 di.di_printf = disassemble_printf;
622
623 int base = getBase();
624 int pc = getPC();
625 for(int i = base; i < pc; i += 4) {
626 fprintf(out, "%08x: %08x ", i, *(int*) i);
627 ::disasm(&di, i, 0);
628 }
629 return 0;
630 }
Jack Palevich7810bc92009-05-15 14:31:47 -0700631
Jack Palevich22305132009-05-13 10:58:45 -0700632 private:
Jack Palevicha6535612009-05-13 16:24:17 -0700633 static FILE* disasmOut;
634
635 static u_int
636 disassemble_readword(u_int address)
637 {
638 return(*((u_int *)address));
639 }
640
641 static void
642 disassemble_printaddr(u_int address)
643 {
644 fprintf(disasmOut, "0x%08x", address);
645 }
646
647 static void
648 disassemble_printf(const char *fmt, ...) {
649 va_list ap;
650 va_start(ap, fmt);
651 vfprintf(disasmOut, fmt, ap);
652 va_end(ap);
653 }
654
655 static const int BRANCH_REL_ADDRESS_MASK = 0x00ffffff;
656
657 /** Encode a relative address that might also be
658 * a label.
659 */
660 int encodeAddress(int value) {
661 int base = getBase();
662 if (value >= base && value <= getPC() ) {
663 // This is a label, encode it relative to the base.
664 value = value - base;
665 }
666 return encodeRelAddress(value);
667 }
668
669 int encodeRelAddress(int value) {
670 return BRANCH_REL_ADDRESS_MASK & (value >> 2);
671 }
Jack Palevich22305132009-05-13 10:58:45 -0700672
Jack Palevich546b2242009-05-13 15:10:04 -0700673 void error(const char* fmt,...) {
674 va_list ap;
675 va_start(ap, fmt);
676 vfprintf(stderr, fmt, ap);
677 va_end(ap);
678 exit(12);
679 }
Jack Palevich22305132009-05-13 10:58:45 -0700680 };
681
Jack Palevich21a15a22009-05-11 14:49:29 -0700682 class X86CodeGenerator : public CodeGenerator {
683 public:
684 X86CodeGenerator() {}
685 virtual ~X86CodeGenerator() {}
686
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700687 /* returns address to patch with local variable size
688 */
Jack Palevich546b2242009-05-13 15:10:04 -0700689 virtual int functionEntry(int argCount) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700690 o(0xe58955); /* push %ebp, mov %esp, %ebp */
691 return oad(0xec81, 0); /* sub $xxx, %esp */
692 }
693
Jack Palevich546b2242009-05-13 15:10:04 -0700694 virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700695 o(0xc3c9); /* leave, ret */
Jack Palevich546b2242009-05-13 15:10:04 -0700696 *(int *) localVariableAddress = localVariableSize; /* save local variables */
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700697 }
698
Jack Palevich21a15a22009-05-11 14:49:29 -0700699 /* load immediate value */
Jack Palevich546b2242009-05-13 15:10:04 -0700700 virtual void li(int t) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700701 oad(0xb8, t); /* mov $xx, %eax */
702 }
703
Jack Palevich22305132009-05-13 10:58:45 -0700704 virtual int gjmp(int t) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700705 return psym(0xe9, t);
706 }
707
708 /* l = 0: je, l == 1: jne */
Jack Palevich22305132009-05-13 10:58:45 -0700709 virtual int gtst(bool l, int t) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700710 o(0x0fc085); /* test %eax, %eax, je/jne xxx */
711 return psym(0x84 + l, t);
712 }
713
Jack Palevich22305132009-05-13 10:58:45 -0700714 virtual void gcmp(int op) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700715 int t = decodeOp(op);
Jack Palevich21a15a22009-05-11 14:49:29 -0700716 o(0xc139); /* cmp %eax,%ecx */
717 li(0);
718 o(0x0f); /* setxx %al */
719 o(t + 0x90);
720 o(0xc0);
721 }
722
Jack Palevich546b2242009-05-13 15:10:04 -0700723 virtual void genOp(int op) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700724 o(decodeOp(op));
725 if (op == OP_MOD)
726 o(0x92); /* xchg %edx, %eax */
727 }
728
Jack Palevich22305132009-05-13 10:58:45 -0700729 virtual void clearECX() {
Jack Palevich21a15a22009-05-11 14:49:29 -0700730 oad(0xb9, 0); /* movl $0, %ecx */
731 }
732
Jack Palevich22305132009-05-13 10:58:45 -0700733 virtual void pushEAX() {
Jack Palevich21a15a22009-05-11 14:49:29 -0700734 o(0x50); /* push %eax */
735 }
736
Jack Palevich22305132009-05-13 10:58:45 -0700737 virtual void popECX() {
Jack Palevich21a15a22009-05-11 14:49:29 -0700738 o(0x59); /* pop %ecx */
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700739 }
740
Jack Palevich22305132009-05-13 10:58:45 -0700741 virtual void storeEAXToAddressECX(bool isInt) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700742 o(0x0188 + isInt); /* movl %eax/%al, (%ecx) */
743 }
744
Jack Palevich22305132009-05-13 10:58:45 -0700745 virtual void loadEAXIndirect(bool isInt) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700746 if (isInt)
747 o(0x8b); /* mov (%eax), %eax */
748 else
749 o(0xbe0f); /* movsbl (%eax), %eax */
750 ob(0); /* add zero in code */
751 }
752
Jack Palevich22305132009-05-13 10:58:45 -0700753 virtual void leaEAX(int ea) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700754 gmov(10, ea); /* leal EA, %eax */
755 }
756
Jack Palevich22305132009-05-13 10:58:45 -0700757 virtual void storeEAX(int ea) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700758 gmov(6, ea); /* mov %eax, EA */
759 }
760
Jack Palevich4d93f302009-05-15 13:30:00 -0700761 virtual void loadEAX(int ea, bool isIncDec, int op) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700762 gmov(8, ea); /* mov EA, %eax */
Jack Palevich4d93f302009-05-15 13:30:00 -0700763 if (isIncDec) {
764 /* Implement post-increment or post decrement.
765 */
766 gmov(0, ea); /* 83 ADD */
767 o(decodeOp(op));
768 }
Jack Palevich21a15a22009-05-11 14:49:29 -0700769 }
770
Jack Palevichcb1c9ef2009-05-14 11:38:49 -0700771 virtual int beginFunctionCallArguments() {
Jack Palevich21a15a22009-05-11 14:49:29 -0700772 return oad(0xec81, 0); /* sub $xxx, %esp */
773 }
774
Jack Palevich22305132009-05-13 10:58:45 -0700775 virtual void storeEAToArg(int l) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700776 oad(0x248489, l); /* movl %eax, xxx(%esp) */
777 }
778
Jack Palevich7810bc92009-05-15 14:31:47 -0700779 virtual void endFunctionCallArguments(int a, int l) {
780 * (int*) a = l;
781 }
782
Jack Palevich22305132009-05-13 10:58:45 -0700783 virtual int callForward(int symbol) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700784 return psym(0xe8, symbol); /* call xxx */
785 }
786
Jack Palevich22305132009-05-13 10:58:45 -0700787 virtual void callRelative(int t) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700788 psym(0xe8, t); /* call xxx */
789 }
790
Jack Palevich22305132009-05-13 10:58:45 -0700791 virtual void callIndirect(int l) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700792 oad(0x2494ff, l); /* call *xxx(%esp) */
793 }
794
Jack Palevich7810bc92009-05-15 14:31:47 -0700795 virtual void adjustStackAfterCall(int l, bool isIndirect) {
796 if (isIndirect) {
797 l += 4;
798 }
Jack Palevich21a15a22009-05-11 14:49:29 -0700799 oad(0xc481, l); /* add $xxx, %esp */
800 }
801
Jack Palevicha6535612009-05-13 16:24:17 -0700802 virtual int jumpOffset() {
803 return 5;
804 }
805
806 virtual int disassemble(FILE* out) {
807 return 1;
808 }
809
Jack Palevich21a15a22009-05-11 14:49:29 -0700810 private:
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700811 static const int operatorHelper[];
812
813 int decodeOp(int op) {
814 if (op < 0 || op > OP_COUNT) {
815 fprintf(stderr, "Out-of-range operator: %d\n", op);
816 exit(1);
817 }
818 return operatorHelper[op];
819 }
Jack Palevich21a15a22009-05-11 14:49:29 -0700820
Jack Palevich546b2242009-05-13 15:10:04 -0700821 void gmov(int l, int t) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700822 o(l + 0x83);
823 oad((t < LOCAL) << 7 | 5, t);
824 }
825 };
826
827 /* vars: value of variables
828 loc : local variable index
829 glo : global variable index
830 ind : output code ptr
831 rsym: return symbol
832 prog: output code
833 dstk: define stack
834 dptr, dch: macro state
835 */
836 int tok, tokc, tokl, ch, vars, rsym, loc, glo, sym_stk, dstk,
837 dptr, dch, last_id;
838 void* pSymbolBase;
839 void* pGlobalBase;
840 void* pVarsBase;
841 FILE* file;
842
843 CodeBuf codeBuf;
Jack Palevich22305132009-05-13 10:58:45 -0700844 CodeGenerator* pGen;
Jack Palevich21a15a22009-05-11 14:49:29 -0700845
846 static const int ALLOC_SIZE = 99999;
847
848 /* depends on the init string */
849 static const int TOK_STR_SIZE = 48;
850 static const int TOK_IDENT = 0x100;
851 static const int TOK_INT = 0x100;
852 static const int TOK_IF = 0x120;
853 static const int TOK_ELSE = 0x138;
854 static const int TOK_WHILE = 0x160;
855 static const int TOK_BREAK = 0x190;
856 static const int TOK_RETURN = 0x1c0;
857 static const int TOK_FOR = 0x1f8;
858 static const int TOK_DEFINE = 0x218;
859 static const int TOK_MAIN = 0x250;
860
861 static const int TOK_DUMMY = 1;
862 static const int TOK_NUM = 2;
863
864 static const int LOCAL = 0x200;
865
866 static const int SYM_FORWARD = 0;
867 static const int SYM_DEFINE = 1;
868
869 /* tokens in string heap */
870 static const int TAG_TOK = ' ';
871 static const int TAG_MACRO = 2;
872
Jack Palevichbf42c9c2009-05-12 12:48:35 -0700873 static const int OP_INCREMENT = 0;
874 static const int OP_DECREMENT = 1;
875 static const int OP_MUL = 2;
876 static const int OP_DIV = 3;
877 static const int OP_MOD = 4;
878 static const int OP_PLUS = 5;
879 static const int OP_MINUS = 6;
880 static const int OP_SHIFT_LEFT = 7;
881 static const int OP_SHIFT_RIGHT = 8;
882 static const int OP_LESS_EQUAL = 9;
883 static const int OP_GREATER_EQUAL = 10;
884 static const int OP_LESS = 11;
885 static const int OP_GREATER = 12;
886 static const int OP_EQUALS = 13;
887 static const int OP_NOT_EQUALS = 14;
888 static const int OP_LOGICAL_AND = 15;
889 static const int OP_LOGICAL_OR = 16;
890 static const int OP_BIT_AND = 17;
891 static const int OP_BIT_XOR = 18;
892 static const int OP_BIT_OR = 19;
893 static const int OP_BIT_NOT = 20;
894 static const int OP_LOGICAL_NOT = 21;
895 static const int OP_COUNT = 22;
896
897 /* Operators are searched from front, the two-character operators appear
898 * before the single-character operators with the same first character.
899 * @ is used to pad out single-character operators.
900 */
901 static const char* operatorChars;
902 static const char operatorLevel[];
903
Jack Palevich21a15a22009-05-11 14:49:29 -0700904 void pdef(int t) {
905 *(char *) dstk++ = t;
906 }
907
908 void inp() {
909 if (dptr) {
910 ch = *(char *) dptr++;
911 if (ch == TAG_MACRO) {
912 dptr = 0;
913 ch = dch;
914 }
915 } else
916 ch = fgetc(file);
917 /* printf("ch=%c 0x%x\n", ch, ch); */
918 }
919
920 int isid() {
Jack Palevich546b2242009-05-13 15:10:04 -0700921 return isalnum(ch) | (ch == '_');
Jack Palevich21a15a22009-05-11 14:49:29 -0700922 }
923
924 /* read a character constant */
925 void getq() {
926 if (ch == '\\') {
927 inp();
928 if (ch == 'n')
929 ch = '\n';
930 }
931 }
932
933 void next() {
934 int l, a;
935
Jack Palevich546b2242009-05-13 15:10:04 -0700936 while (isspace(ch) | (ch == '#')) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700937 if (ch == '#') {
938 inp();
939 next();
940 if (tok == TOK_DEFINE) {
941 next();
942 pdef(TAG_TOK); /* fill last ident tag */
943 *(int *) tok = SYM_DEFINE;
944 *(int *) (tok + 4) = dstk; /* define stack */
945 }
946 /* well we always save the values ! */
947 while (ch != '\n') {
948 pdef(ch);
949 inp();
950 }
951 pdef(ch);
952 pdef(TAG_MACRO);
953 }
954 inp();
955 }
956 tokl = 0;
957 tok = ch;
958 /* encode identifiers & numbers */
959 if (isid()) {
960 pdef(TAG_TOK);
961 last_id = dstk;
962 while (isid()) {
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700963 pdef(ch);
964 inp();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700965 }
Jack Palevich21a15a22009-05-11 14:49:29 -0700966 if (isdigit(tok)) {
967 tokc = strtol((char*) last_id, 0, 0);
968 tok = TOK_NUM;
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700969 } else {
Jack Palevich21a15a22009-05-11 14:49:29 -0700970 *(char *) dstk = TAG_TOK; /* no need to mark end of string (we
971 suppose data is initialized to zero by calloc) */
972 tok = (int) (strstr((char*) sym_stk, (char*) (last_id - 1))
973 - sym_stk);
974 *(char *) dstk = 0; /* mark real end of ident for dlsym() */
975 tok = tok * 8 + TOK_IDENT;
976 if (tok > TOK_DEFINE) {
977 tok = vars + tok;
978 /* printf("tok=%s %x\n", last_id, tok); */
979 /* define handling */
980 if (*(int *) tok == SYM_DEFINE) {
981 dptr = *(int *) (tok + 4);
982 dch = ch;
983 inp();
984 next();
985 }
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700986 }
987 }
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700988 } else {
Jack Palevich21a15a22009-05-11 14:49:29 -0700989 inp();
990 if (tok == '\'') {
991 tok = TOK_NUM;
992 getq();
993 tokc = ch;
994 inp();
995 inp();
Jack Palevich546b2242009-05-13 15:10:04 -0700996 } else if ((tok == '/') & (ch == '*')) {
Jack Palevich21a15a22009-05-11 14:49:29 -0700997 inp();
998 while (ch) {
999 while (ch != '*')
1000 inp();
1001 inp();
1002 if (ch == '/')
1003 ch = 0;
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001004 }
Jack Palevich21a15a22009-05-11 14:49:29 -07001005 inp();
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001006 next();
Jack Palevichbd894902009-05-14 19:35:31 -07001007 } else if ((tok == '/') & (ch == '/')) {
1008 inp();
1009 while (ch && (ch != '\n')) {
1010 inp();
1011 }
1012 inp();
1013 next();
Jack Palevich21a15a22009-05-11 14:49:29 -07001014 } else {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001015 const char* t = operatorChars;
1016 int opIndex = 0;
Jack Palevich546b2242009-05-13 15:10:04 -07001017 while ((l = *t++) != 0) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001018 a = *t++;
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001019 tokl = operatorLevel[opIndex];
1020 tokc = opIndex;
Jack Palevich546b2242009-05-13 15:10:04 -07001021 if ((l == tok) & ((a == ch) | (a == '@'))) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001022#if 0
1023 printf("%c%c -> tokl=%d tokc=0x%x\n",
1024 l, a, tokl, tokc);
1025#endif
1026 if (a == ch) {
1027 inp();
1028 tok = TOK_DUMMY; /* dummy token for double tokens */
1029 }
1030 break;
1031 }
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001032 opIndex++;
1033 }
1034 if (l == 0) {
1035 tokl = 0;
1036 tokc = 0;
Jack Palevich21a15a22009-05-11 14:49:29 -07001037 }
1038 }
1039 }
1040#if 0
1041 {
1042 int p;
1043
1044 printf("tok=0x%x ", tok);
1045 if (tok >= TOK_IDENT) {
1046 printf("'");
1047 if (tok> TOK_DEFINE)
1048 p = sym_stk + 1 + (tok - vars - TOK_IDENT) / 8;
1049 else
1050 p = sym_stk + 1 + (tok - TOK_IDENT) / 8;
1051 while (*(char *)p != TAG_TOK && *(char *)p)
1052 printf("%c", *(char *)p++);
1053 printf("'\n");
1054 } else if (tok == TOK_NUM) {
1055 printf("%d\n", tokc);
1056 } else {
1057 printf("'%c'\n", tok);
1058 }
1059 }
1060#endif
1061 }
1062
1063 void error(const char *fmt, ...) {
1064 va_list ap;
1065
1066 va_start(ap, fmt);
1067 fprintf(stderr, "%ld: ", ftell((FILE *) file));
1068 vfprintf(stderr, fmt, ap);
1069 fprintf(stderr, "\n");
1070 va_end(ap);
1071 exit(1);
1072 }
1073
1074 void skip(int c) {
1075 if (tok != c) {
1076 error("'%c' expected", c);
1077 }
1078 next();
1079 }
1080
Jack Palevich21a15a22009-05-11 14:49:29 -07001081 /* l is one if '=' parsing wanted (quick hack) */
1082 void unary(int l) {
1083 int n, t, a, c;
Jack Palevich546b2242009-05-13 15:10:04 -07001084 t = 0;
Jack Palevich21a15a22009-05-11 14:49:29 -07001085 n = 1; /* type of expression 0 = forward, 1 = value, other =
1086 lvalue */
1087 if (tok == '\"') {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001088 pGen->li(glo);
Jack Palevich21a15a22009-05-11 14:49:29 -07001089 while (ch != '\"') {
1090 getq();
1091 *(char *) glo++ = ch;
1092 inp();
1093 }
1094 *(char *) glo = 0;
Jack Palevich546b2242009-05-13 15:10:04 -07001095 glo = (glo + 4) & -4; /* align heap */
Jack Palevich21a15a22009-05-11 14:49:29 -07001096 inp();
1097 next();
1098 } else {
1099 c = tokl;
1100 a = tokc;
1101 t = tok;
1102 next();
1103 if (t == TOK_NUM) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001104 pGen->li(a);
Jack Palevich21a15a22009-05-11 14:49:29 -07001105 } else if (c == 2) {
1106 /* -, +, !, ~ */
1107 unary(0);
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001108 pGen->clearECX();
Jack Palevich21a15a22009-05-11 14:49:29 -07001109 if (t == '!')
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001110 pGen->gcmp(a);
Jack Palevich21a15a22009-05-11 14:49:29 -07001111 else
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001112 pGen->genOp(a);
Jack Palevich21a15a22009-05-11 14:49:29 -07001113 } else if (t == '(') {
1114 expr();
1115 skip(')');
1116 } else if (t == '*') {
1117 /* parse cast */
1118 skip('(');
1119 t = tok; /* get type */
1120 next(); /* skip int/char/void */
1121 next(); /* skip '*' or '(' */
1122 if (tok == '*') {
1123 /* function type */
1124 skip('*');
1125 skip(')');
1126 skip('(');
1127 skip(')');
1128 t = 0;
1129 }
1130 skip(')');
1131 unary(0);
1132 if (tok == '=') {
1133 next();
1134 pGen->pushEAX();
1135 expr();
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001136 pGen->popECX();
1137 pGen->storeEAXToAddressECX(t == TOK_INT);
Jack Palevich21a15a22009-05-11 14:49:29 -07001138 } else if (t) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001139 pGen->loadEAXIndirect(t == TOK_INT);
Jack Palevich21a15a22009-05-11 14:49:29 -07001140 }
1141 } else if (t == '&') {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001142 pGen->leaEAX(*(int *) tok);
Jack Palevich21a15a22009-05-11 14:49:29 -07001143 next();
1144 } else {
1145 n = *(int *) t;
1146 /* forward reference: try dlsym */
Jack Palevichcb1c9ef2009-05-14 11:38:49 -07001147 if (!n) {
1148 n = (int) dlsym(RTLD_DEFAULT, (char*) last_id);
1149 }
Jack Palevich546b2242009-05-13 15:10:04 -07001150 if ((tok == '=') & l) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001151 /* assignment */
1152 next();
1153 expr();
1154 pGen->storeEAX(n);
1155 } else if (tok != '(') {
1156 /* variable */
Jack Palevich4d93f302009-05-15 13:30:00 -07001157 pGen->loadEAX(n, tokl == 11, tokc);
Jack Palevich21a15a22009-05-11 14:49:29 -07001158 if (tokl == 11) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001159 next();
1160 }
1161 }
1162 }
1163 }
1164
1165 /* function call */
1166 if (tok == '(') {
1167 if (n == 1)
1168 pGen->pushEAX();
1169
1170 /* push args and invert order */
Jack Palevichcb1c9ef2009-05-14 11:38:49 -07001171 a = pGen->beginFunctionCallArguments();
Jack Palevich21a15a22009-05-11 14:49:29 -07001172 next();
1173 l = 0;
1174 while (tok != ')') {
1175 expr();
1176 pGen->storeEAToArg(l);
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001177 if (tok == ',')
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001178 next();
Jack Palevich21a15a22009-05-11 14:49:29 -07001179 l = l + 4;
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001180 }
Jack Palevichcb1c9ef2009-05-14 11:38:49 -07001181 pGen->endFunctionCallArguments(a, l);
Jack Palevich21a15a22009-05-11 14:49:29 -07001182 next();
1183 if (!n) {
1184 /* forward reference */
1185 t = t + 4;
1186 *(int *) t = pGen->callForward(*(int *) t);
1187 } else if (n == 1) {
1188 pGen->callIndirect(l);
Jack Palevich21a15a22009-05-11 14:49:29 -07001189 } else {
Jack Palevich7810bc92009-05-15 14:31:47 -07001190 pGen->callRelative(n - codeBuf.getPC() - pGen->jumpOffset());
Jack Palevich21a15a22009-05-11 14:49:29 -07001191 }
Jack Palevich7810bc92009-05-15 14:31:47 -07001192 if (l || n == 1)
1193 pGen->adjustStackAfterCall(l, n == 1);
Jack Palevich21a15a22009-05-11 14:49:29 -07001194 }
1195 }
1196
1197 void sum(int l) {
1198 int t, n, a;
Jack Palevich546b2242009-05-13 15:10:04 -07001199 t = 0;
Jack Palevich21a15a22009-05-11 14:49:29 -07001200 if (l-- == 1)
1201 unary(1);
1202 else {
1203 sum(l);
1204 a = 0;
1205 while (l == tokl) {
1206 n = tok;
1207 t = tokc;
1208 next();
1209
1210 if (l > 8) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001211 a = pGen->gtst(t == OP_LOGICAL_OR, a); /* && and || output code generation */
Jack Palevich21a15a22009-05-11 14:49:29 -07001212 sum(l);
1213 } else {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001214 pGen->pushEAX();
Jack Palevich21a15a22009-05-11 14:49:29 -07001215 sum(l);
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001216 pGen->popECX();
Jack Palevich21a15a22009-05-11 14:49:29 -07001217
Jack Palevich546b2242009-05-13 15:10:04 -07001218 if ((l == 4) | (l == 5)) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001219 pGen->gcmp(t);
Jack Palevich21a15a22009-05-11 14:49:29 -07001220 } else {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001221 pGen->genOp(t);
Jack Palevich21a15a22009-05-11 14:49:29 -07001222 }
1223 }
1224 }
1225 /* && and || output code generation */
1226 if (a && l > 8) {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001227 a = pGen->gtst(t == OP_LOGICAL_OR, a);
1228 pGen->li(t != OP_LOGICAL_OR);
Jack Palevicha6535612009-05-13 16:24:17 -07001229 pGen->gjmp(5); /* jmp $ + 5 (sizeof li, FIXME for ARM) */
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001230 pGen->gsym(a);
1231 pGen->li(t == OP_LOGICAL_OR);
Jack Palevich21a15a22009-05-11 14:49:29 -07001232 }
1233 }
1234 }
1235
1236 void expr() {
1237 sum(11);
1238 }
1239
1240 int test_expr() {
1241 expr();
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001242 return pGen->gtst(0, 0);
Jack Palevich21a15a22009-05-11 14:49:29 -07001243 }
1244
1245 void block(int l) {
1246 int a, n, t;
1247
1248 if (tok == TOK_IF) {
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001249 next();
1250 skip('(');
Jack Palevich21a15a22009-05-11 14:49:29 -07001251 a = test_expr();
1252 skip(')');
1253 block(l);
1254 if (tok == TOK_ELSE) {
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001255 next();
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001256 n = pGen->gjmp(0); /* jmp */
1257 pGen->gsym(a);
Jack Palevich21a15a22009-05-11 14:49:29 -07001258 block(l);
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001259 pGen->gsym(n); /* patch else jmp */
Jack Palevich21a15a22009-05-11 14:49:29 -07001260 } else {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001261 pGen->gsym(a); /* patch if test */
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001262 }
Jack Palevich546b2242009-05-13 15:10:04 -07001263 } else if ((tok == TOK_WHILE) | (tok == TOK_FOR)) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001264 t = tok;
1265 next();
1266 skip('(');
1267 if (t == TOK_WHILE) {
Jack Palevicha6535612009-05-13 16:24:17 -07001268 n = codeBuf.getPC(); // top of loop, target of "next" iteration
Jack Palevich21a15a22009-05-11 14:49:29 -07001269 a = test_expr();
1270 } else {
1271 if (tok != ';')
1272 expr();
1273 skip(';');
1274 n = codeBuf.getPC();
1275 a = 0;
1276 if (tok != ';')
1277 a = test_expr();
1278 skip(';');
1279 if (tok != ')') {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001280 t = pGen->gjmp(0);
Jack Palevich21a15a22009-05-11 14:49:29 -07001281 expr();
Jack Palevicha6535612009-05-13 16:24:17 -07001282 pGen->gjmp(n - codeBuf.getPC() - pGen->jumpOffset());
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001283 pGen->gsym(t);
Jack Palevich21a15a22009-05-11 14:49:29 -07001284 n = t + 4;
1285 }
1286 }
1287 skip(')');
1288 block((int) &a);
Jack Palevicha6535612009-05-13 16:24:17 -07001289 pGen->gjmp(n - codeBuf.getPC() - pGen->jumpOffset()); /* jmp */
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001290 pGen->gsym(a);
Jack Palevich21a15a22009-05-11 14:49:29 -07001291 } else if (tok == '{') {
1292 next();
1293 /* declarations */
1294 decl(1);
1295 while (tok != '}')
1296 block(l);
1297 next();
1298 } else {
1299 if (tok == TOK_RETURN) {
1300 next();
1301 if (tok != ';')
1302 expr();
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001303 rsym = pGen->gjmp(rsym); /* jmp */
Jack Palevich21a15a22009-05-11 14:49:29 -07001304 } else if (tok == TOK_BREAK) {
1305 next();
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001306 *(int *) l = pGen->gjmp(*(int *) l);
Jack Palevich21a15a22009-05-11 14:49:29 -07001307 } else if (tok != ';')
1308 expr();
1309 skip(';');
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001310 }
1311 }
Jack Palevich21a15a22009-05-11 14:49:29 -07001312
1313 /* 'l' is true if local declarations */
1314 void decl(int l) {
1315 int a;
1316
Jack Palevich546b2242009-05-13 15:10:04 -07001317 while ((tok == TOK_INT) | ((tok != -1) & (!l))) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001318 if (tok == TOK_INT) {
1319 next();
1320 while (tok != ';') {
1321 if (l) {
1322 loc = loc + 4;
1323 *(int *) tok = -loc;
1324 } else {
1325 *(int *) tok = glo;
1326 glo = glo + 4;
1327 }
1328 next();
1329 if (tok == ',')
1330 next();
1331 }
1332 skip(';');
1333 } else {
1334 /* patch forward references (XXX: do not work for function
1335 pointers) */
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001336 pGen->gsym(*(int *) (tok + 4));
Jack Palevich21a15a22009-05-11 14:49:29 -07001337 /* put function address */
1338 *(int *) tok = codeBuf.getPC();
1339 next();
1340 skip('(');
1341 a = 8;
Jack Palevich546b2242009-05-13 15:10:04 -07001342 int argCount = 0;
Jack Palevich21a15a22009-05-11 14:49:29 -07001343 while (tok != ')') {
1344 /* read param name and compute offset */
1345 *(int *) tok = a;
1346 a = a + 4;
1347 next();
1348 if (tok == ',')
1349 next();
Jack Palevich546b2242009-05-13 15:10:04 -07001350 argCount++;
Jack Palevich21a15a22009-05-11 14:49:29 -07001351 }
1352 next(); /* skip ')' */
1353 rsym = loc = 0;
Jack Palevich546b2242009-05-13 15:10:04 -07001354 a = pGen->functionEntry(argCount);
Jack Palevich21a15a22009-05-11 14:49:29 -07001355 block(0);
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001356 pGen->gsym(rsym);
Jack Palevich546b2242009-05-13 15:10:04 -07001357 pGen->functionExit(argCount, a, loc);
Jack Palevich21a15a22009-05-11 14:49:29 -07001358 }
1359 }
1360 }
1361
1362 void cleanup() {
1363 if (sym_stk != 0) {
1364 free((void*) sym_stk);
1365 sym_stk = 0;
1366 }
1367 if (pGlobalBase != 0) {
1368 free((void*) pGlobalBase);
1369 pGlobalBase = 0;
1370 }
1371 if (pVarsBase != 0) {
1372 free(pVarsBase);
1373 pVarsBase = 0;
1374 }
1375 if (pGen) {
1376 delete pGen;
1377 pGen = 0;
1378 }
1379 }
1380
1381 void clear() {
1382 tok = 0;
1383 tokc = 0;
1384 tokl = 0;
1385 ch = 0;
1386 vars = 0;
1387 rsym = 0;
1388 loc = 0;
1389 glo = 0;
1390 sym_stk = 0;
1391 dstk = 0;
1392 dptr = 0;
1393 dch = 0;
1394 last_id = 0;
1395 file = 0;
1396 pGlobalBase = 0;
1397 pVarsBase = 0;
1398 pGen = 0;
1399 }
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001400
Jack Palevich22305132009-05-13 10:58:45 -07001401 void setArchitecture(const char* architecture) {
1402 delete pGen;
1403 pGen = 0;
1404
1405 if (architecture != NULL) {
1406 if (strcmp(architecture, "arm") == 0) {
1407 pGen = new ARMCodeGenerator();
1408 } else if (strcmp(architecture, "x86") == 0) {
1409 pGen = new X86CodeGenerator();
1410 } else {
1411 fprintf(stderr, "Unknown architecture %s", architecture);
1412 }
1413 }
1414
1415 if (pGen == NULL) {
1416 pGen = new ARMCodeGenerator();
1417 }
1418 }
1419
Jack Palevich77ae76e2009-05-10 19:59:24 -07001420public:
Jack Palevich22305132009-05-13 10:58:45 -07001421 struct args {
1422 args() {
1423 architecture = 0;
1424 }
1425 const char* architecture;
1426 };
1427
Jack Palevich21a15a22009-05-11 14:49:29 -07001428 compiler() {
1429 clear();
Jack Paleviche27bf3e2009-05-10 14:09:03 -07001430 }
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001431
Jack Palevich21a15a22009-05-11 14:49:29 -07001432 ~compiler() {
1433 cleanup();
1434 }
1435
Jack Palevich22305132009-05-13 10:58:45 -07001436 int compile(FILE* in, args& args) {
Jack Palevich21a15a22009-05-11 14:49:29 -07001437 cleanup();
1438 clear();
1439 codeBuf.init(ALLOC_SIZE);
Jack Palevich22305132009-05-13 10:58:45 -07001440 setArchitecture(args.architecture);
Jack Palevich21a15a22009-05-11 14:49:29 -07001441 pGen->init(&codeBuf);
1442 file = in;
1443 sym_stk = (int) calloc(1, ALLOC_SIZE);
1444 dstk = (int) strcpy((char*) sym_stk,
1445 " int if else while break return for define main ")
1446 + TOK_STR_SIZE;
1447 pGlobalBase = calloc(1, ALLOC_SIZE);
1448 glo = (int) pGlobalBase;
1449 pVarsBase = calloc(1, ALLOC_SIZE);
1450 vars = (int) pVarsBase;
1451 inp();
1452 next();
1453 decl(0);
Jack Palevich546b2242009-05-13 15:10:04 -07001454 pGen->finishCompile();
Jack Palevich21a15a22009-05-11 14:49:29 -07001455 return 0;
1456 }
1457
1458 int run(int argc, char** argv) {
1459 typedef int (*mainPtr)(int argc, char** argv);
1460 mainPtr aMain = (mainPtr) *(int*) (vars + TOK_MAIN);
1461 if (!aMain) {
1462 fprintf(stderr, "Could not find function \"main\".\n");
1463 return -1;
1464 }
1465 return aMain(argc, argv);
1466 }
1467
1468 int dump(FILE* out) {
1469 fwrite(codeBuf.getBase(), 1, codeBuf.getSize(), out);
1470 return 0;
1471 }
Jack Palevich77ae76e2009-05-10 19:59:24 -07001472
Jack Palevicha6535612009-05-13 16:24:17 -07001473 int disassemble(FILE* out) {
1474 return pGen->disassemble(out);
1475 }
1476
Jack Palevich77ae76e2009-05-10 19:59:24 -07001477};
1478
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001479const char* compiler::operatorChars =
1480 "++--*@/@%@+@-@<<>><=>=<@>@==!=&&||&@^@|@~@!@";
1481
1482const char compiler::operatorLevel[] =
1483 {11, 11, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4,
1484 5, 5, /* ==, != */
1485 9, 10, /* &&, || */
1486 6, 7, 8, /* & ^ | */
1487 2, 2 /* ~ ! */
1488 };
1489
Jack Palevicha6535612009-05-13 16:24:17 -07001490FILE* compiler::ARMCodeGenerator::disasmOut;
1491
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001492const int compiler::X86CodeGenerator::operatorHelper[] = {
1493 0x1, // ++
1494 0xff, // --
1495 0xc1af0f, // *
1496 0xf9f79991, // /
1497 0xf9f79991, // % (With manual assist to swap results)
1498 0xc801, // +
1499 0xd8f7c829, // -
1500 0xe0d391, // <<
1501 0xf8d391, // >>
1502 0xe, // <=
1503 0xd, // >=
1504 0xc, // <
1505 0xf, // >
1506 0x4, // ==
1507 0x5, // !=
1508 0x0, // &&
1509 0x1, // ||
1510 0xc821, // &
1511 0xc831, // ^
1512 0xc809, // |
1513 0xd0f7, // ~
1514 0x4 // !
1515};
1516
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001517} // namespace acc
1518
Jack Palevich546b2242009-05-13 15:10:04 -07001519// This is a separate function so it can easily be set by breakpoint in gdb.
1520int run(acc::compiler& c, int argc, char** argv) {
1521 return c.run(argc, argv);
1522}
1523
Jack Palevich77ae76e2009-05-10 19:59:24 -07001524int main(int argc, char** argv) {
Jack Palevich22305132009-05-13 10:58:45 -07001525 bool doDump = false;
Jack Palevicha6535612009-05-13 16:24:17 -07001526 bool doDisassemble = false;
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001527 const char* inFile = NULL;
1528 const char* outFile = NULL;
Jack Palevich22305132009-05-13 10:58:45 -07001529 const char* architecture = "arm";
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001530 int i;
Jack Palevich21a15a22009-05-11 14:49:29 -07001531 for (i = 1; i < argc; i++) {
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001532 char* arg = argv[i];
1533 if (arg[0] == '-') {
1534 switch (arg[1]) {
Jack Palevich22305132009-05-13 10:58:45 -07001535 case 'a':
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001536 if (i + 1 >= argc) {
Jack Palevich22305132009-05-13 10:58:45 -07001537 fprintf(stderr, "Expected architecture after -a\n");
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001538 return 2;
1539 }
Jack Palevich22305132009-05-13 10:58:45 -07001540 architecture = argv[i+1];
1541 i += 1;
1542 break;
1543 case 'd':
1544 if (i + 1 >= argc) {
1545 fprintf(stderr, "Expected filename after -d\n");
1546 return 2;
1547 }
1548 doDump = true;
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001549 outFile = argv[i + 1];
1550 i += 1;
1551 break;
Jack Palevicha6535612009-05-13 16:24:17 -07001552 case 'S':
1553 doDisassemble = true;
1554 break;
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001555 default:
1556 fprintf(stderr, "Unrecognized flag %s\n", arg);
1557 return 3;
1558 }
1559 } else if (inFile == NULL) {
1560 inFile = arg;
1561 } else {
1562 break;
1563 }
1564 }
1565
1566 FILE* in = stdin;
1567 if (inFile) {
1568 in = fopen(inFile, "r");
Jack Palevich21a15a22009-05-11 14:49:29 -07001569 if (!in) {
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001570 fprintf(stderr, "Could not open input file %s\n", inFile);
1571 return 1;
1572 }
1573 }
1574 acc::compiler compiler;
Jack Palevich22305132009-05-13 10:58:45 -07001575 acc::compiler::args args;
1576 args.architecture = architecture;
1577 int compileResult = compiler.compile(in, args);
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001578 if (in != stdin) {
1579 fclose(in);
1580 }
1581 if (compileResult) {
1582 fprintf(stderr, "Compile failed: %d\n", compileResult);
1583 return 6;
1584 }
Jack Palevicha6535612009-05-13 16:24:17 -07001585 if (doDisassemble) {
1586 compiler.disassemble(stderr);
1587 }
Jack Palevich22305132009-05-13 10:58:45 -07001588 if (doDump) {
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001589 FILE* save = fopen(outFile, "w");
Jack Palevich21a15a22009-05-11 14:49:29 -07001590 if (!save) {
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001591 fprintf(stderr, "Could not open output file %s\n", outFile);
1592 return 5;
1593 }
1594 compiler.dump(save);
1595 fclose(save);
1596 } else {
Jack Palevichbf42c9c2009-05-12 12:48:35 -07001597 fprintf(stderr, "Executing compiled code:\n");
Jack Palevich21a15a22009-05-11 14:49:29 -07001598 int codeArgc = argc - i + 1;
1599 char** codeArgv = argv + i - 1;
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001600 codeArgv[0] = (char*) (inFile ? inFile : "stdin");
Jack Palevich546b2242009-05-13 15:10:04 -07001601 int result = run(compiler, codeArgc, codeArgv);
Jack Palevich22305132009-05-13 10:58:45 -07001602 fprintf(stderr, "result: %d\n", result);
1603 return result;
Jack Palevichbbf8ab52009-05-11 11:54:30 -07001604 }
1605
1606 return 0;
1607}