acc.cpp revision 96138992ac98f8962dc2345d9ba3e99006af80b2
1/*
2 * Android "Almost" C Compiler.
3 * This is a compiler for a small subset of the C language, intended for use
4 * in scripting environments where speed and memory footprint are important.
5 *
6 * This code is based upon the "unobfuscated" version of the
7 * Obfuscated Tiny C compiler, see the file LICENSE for details.
8 *
9 */
10
11#include <ctype.h>
12#include <errno.h>
13#include <stdarg.h>
14#include <stdint.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <cutils/hashmap.h>
19
20#if defined(__i386__)
21#include <sys/mman.h>
22#endif
23
24#if defined(__arm__)
25#include <unistd.h>
26#endif
27
28#if defined(__arm__)
29#define DEFAULT_ARM_CODEGEN
30#define PROVIDE_ARM_CODEGEN
31#elif defined(__i386__)
32#define DEFAULT_X86_CODEGEN
33#define PROVIDE_X86_CODEGEN
34#elif defined(__x86_64__)
35#define DEFAULT_X64_CODEGEN
36#define PROVIDE_X64_CODEGEN
37#endif
38
39#ifdef PROVIDE_ARM_CODEGEN
40#include "disassem.h"
41#endif
42
43#include <acc/acc.h>
44
45#define LOG_API(...) do {} while(0)
46// #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
47
48#define LOG_STACK(...) do {} while(0)
49// #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__)
50
51#define ENABLE_ARM_DISASSEMBLY
52// #define PROVIDE_TRACE_CODEGEN
53
54namespace acc {
55
56// Subset of STL vector.
57template<class E> class Vector {
58    public:
59    Vector() {
60        mpBase = 0;
61        mUsed = 0;
62        mSize = 0;
63    }
64
65    ~Vector() {
66        if (mpBase) {
67            for(size_t i = 0; i < mUsed; i++)  {
68                mpBase[mUsed].~E();
69            }
70            free(mpBase);
71        }
72    }
73
74    inline E& operator[](size_t i) {
75        return mpBase[i];
76    }
77
78    inline E& front() {
79        return mpBase[0];
80    }
81
82    inline E& back() {
83        return mpBase[mUsed - 1];
84    }
85
86    void pop_back() {
87        mUsed -= 1;
88        mpBase[mUsed].~E();
89    }
90
91    void push_back(const E& item) {
92        * ensure(1) = item;
93    }
94
95    size_t size() {
96        return mUsed;
97    }
98
99private:
100    E* ensure(int n) {
101        size_t newUsed = mUsed + n;
102        if (newUsed > mSize) {
103            size_t newSize = mSize * 2 + 10;
104            if (newSize < newUsed) {
105                newSize = newUsed;
106            }
107            mpBase = (E*) realloc(mpBase, sizeof(E) * newSize);
108            mSize = newSize;
109        }
110        E* result = mpBase + mUsed;
111        mUsed = newUsed;
112        return result;
113    }
114
115    E* mpBase;
116    size_t mUsed;
117    size_t mSize;
118};
119
120class ErrorSink {
121public:
122    void error(const char *fmt, ...) {
123        va_list ap;
124        va_start(ap, fmt);
125        verror(fmt, ap);
126        va_end(ap);
127    }
128
129    virtual ~ErrorSink() {}
130    virtual void verror(const char* fmt, va_list ap) = 0;
131};
132
133class Compiler : public ErrorSink {
134    typedef int tokenid_t;
135    enum TypeTag {
136        TY_INT, TY_CHAR, TY_VOID, TY_FLOAT, TY_DOUBLE,
137        TY_POINTER, TY_FUNC, TY_PARAM
138    };
139
140    struct Type {
141        TypeTag tag;
142        tokenid_t id; // For function arguments
143        Type* pHead;
144        Type* pTail;
145    };
146
147    enum ExpressionType {
148        ET_RVALUE,
149        ET_LVALUE
150    };
151
152    struct ExpressionValue {
153        ExpressionValue() {
154            et = ET_RVALUE;
155            pType = NULL;
156        }
157        ExpressionType et;
158        Type* pType;
159    };
160
161    class CodeBuf {
162        char* ind; // Output code pointer
163        char* pProgramBase;
164        ErrorSink* mErrorSink;
165        int mSize;
166        bool mOverflowed;
167
168        void release() {
169            if (pProgramBase != 0) {
170                free(pProgramBase);
171                pProgramBase = 0;
172            }
173        }
174
175        bool check(int n) {
176            int newSize = ind - pProgramBase + n;
177            bool overflow = newSize > mSize;
178            if (overflow && !mOverflowed) {
179                mOverflowed = true;
180                if (mErrorSink) {
181                    mErrorSink->error("Code too large: %d bytes", newSize);
182                }
183            }
184            return overflow;
185        }
186
187    public:
188        CodeBuf() {
189            pProgramBase = 0;
190            ind = 0;
191            mErrorSink = 0;
192            mSize = 0;
193            mOverflowed = false;
194        }
195
196        ~CodeBuf() {
197            release();
198        }
199
200        void init(int size) {
201            release();
202            mSize = size;
203            pProgramBase = (char*) calloc(1, size);
204            ind = pProgramBase;
205        }
206
207        void setErrorSink(ErrorSink* pErrorSink) {
208            mErrorSink = pErrorSink;
209        }
210
211        int o4(int n) {
212            if(check(4)) {
213                return 0;
214            }
215            intptr_t result = (intptr_t) ind;
216            * (int*) ind = n;
217            ind += 4;
218            return result;
219        }
220
221        /*
222         * Output a byte. Handles all values, 0..ff.
223         */
224        void ob(int n) {
225            if(check(1)) {
226                return;
227            }
228            *ind++ = n;
229        }
230
231        inline void* getBase() {
232            return (void*) pProgramBase;
233        }
234
235        intptr_t getSize() {
236            return ind - pProgramBase;
237        }
238
239        intptr_t getPC() {
240            return (intptr_t) ind;
241        }
242    };
243
244    /**
245     * A code generator creates an in-memory program, generating the code on
246     * the fly. There is one code generator implementation for each supported
247     * architecture.
248     *
249     * The code generator implements the following abstract machine:
250     * R0 - the accumulator.
251     * FP - a frame pointer for accessing function arguments and local
252     *      variables.
253     * SP - a stack pointer for storing intermediate results while evaluating
254     *      expressions. The stack pointer grows downwards.
255     *
256     * The function calling convention is that all arguments are placed on the
257     * stack such that the first argument has the lowest address.
258     * After the call, the result is in R0. The caller is responsible for
259     * removing the arguments from the stack.
260     * The R0 register is not saved across function calls. The
261     * FP and SP registers are saved.
262     */
263
264    class CodeGenerator {
265    public:
266        CodeGenerator() {
267            mErrorSink = 0;
268            pCodeBuf = 0;
269            pushType();
270        }
271        virtual ~CodeGenerator() {}
272
273        virtual void init(CodeBuf* pCodeBuf) {
274            this->pCodeBuf = pCodeBuf;
275            pCodeBuf->setErrorSink(mErrorSink);
276        }
277
278        virtual void setErrorSink(ErrorSink* pErrorSink) {
279            mErrorSink = pErrorSink;
280            if (pCodeBuf) {
281                pCodeBuf->setErrorSink(mErrorSink);
282            }
283        }
284
285        /* Give the code generator some utility types so it can
286         * use its own types as needed for the results of some
287         * operations like gcmp.
288         */
289
290        void setTypes(Type* pInt) {
291            mkpInt = pInt;
292        }
293
294        /* Emit a function prolog.
295         * pDecl is the function declaration, which gives the arguments.
296         * Save the old value of the FP.
297         * Set the new value of the FP.
298         * Convert from the native platform calling convention to
299         * our stack-based calling convention. This may require
300         * pushing arguments from registers to the stack.
301         * Allocate "N" bytes of stack space. N isn't known yet, so
302         * just emit the instructions for adjusting the stack, and return
303         * the address to patch up. The patching will be done in
304         * functionExit().
305         * returns address to patch with local variable size.
306        */
307        virtual int functionEntry(Type* pDecl) = 0;
308
309        /* Emit a function epilog.
310         * Restore the old SP and FP register values.
311         * Return to the calling function.
312         * argCount - the number of arguments to the function.
313         * localVariableAddress - returned from functionEntry()
314         * localVariableSize - the size in bytes of the local variables.
315         */
316        virtual void functionExit(Type* pDecl, int localVariableAddress,
317                                  int localVariableSize) = 0;
318
319        /* load immediate value to R0 */
320        virtual void li(int i) = 0;
321
322        /* Load floating point value from global address. */
323        virtual void loadFloat(int address, Type* pType) = 0;
324
325        /* Jump to a target, and return the address of the word that
326         * holds the target data, in case it needs to be fixed up later.
327         */
328        virtual int gjmp(int t) = 0;
329
330        /* Test R0 and jump to a target if the test succeeds.
331         * l = 0: je, l == 1: jne
332         * Return the address of the word that holds the targed data, in
333         * case it needs to be fixed up later.
334         */
335        virtual int gtst(bool l, int t) = 0;
336
337        /* Compare TOS against R0, and store the boolean result in R0.
338         * Pops TOS.
339         * op specifies the comparison.
340         */
341        virtual void gcmp(int op) = 0;
342
343        /* Perform the arithmetic op specified by op. TOS is the
344         * left argument, R0 is the right argument.
345         * Pops TOS.
346         */
347        virtual void genOp(int op) = 0;
348
349        /* Compare 0 against R0, and store the boolean result in R0.
350         * op specifies the comparison.
351         */
352        virtual void gUnaryCmp(int op) = 0;
353
354        /* Perform the arithmetic op specified by op. 0 is the
355         * left argument, R0 is the right argument.
356         */
357        virtual void genUnaryOp(int op) = 0;
358
359        /* Push R0 onto the stack. (Also known as "dup" for duplicate.)
360         */
361        virtual void pushR0() = 0;
362
363        /* Turn R0, TOS into R0 TOS R0 */
364
365        virtual void over() = 0;
366
367        /* Pop R0 from the stack. (Also known as "drop")
368         */
369        virtual void popR0() = 0;
370
371        /* Store R0 to the address stored in TOS.
372         * The TOS is popped.
373         */
374        virtual void storeR0ToTOS() = 0;
375
376        /* Load R0 from the address stored in R0.
377         */
378        virtual void loadR0FromR0() = 0;
379
380        /* Load the absolute address of a variable to R0.
381         * If ea <= LOCAL, then this is a local variable, or an
382         * argument, addressed relative to FP.
383         * else it is an absolute global address.
384         *
385         * et is ET_RVALUE for things like string constants, ET_LVALUE for
386         * variables.
387         */
388        virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) = 0;
389
390        /* Load the pc-relative address of a forward-referenced variable to R0.
391         * Return the address of the 4-byte constant so that it can be filled
392         * in later.
393         */
394        virtual int leaForward(int ea, Type* pPointerType) = 0;
395
396        /**
397         * Convert R0 to the given type.
398         */
399        virtual void convertR0(Type* pType) = 0;
400
401        /* Emit code to adjust the stack for a function call. Return the
402         * label for the address of the instruction that adjusts the
403         * stack size. This will be passed as argument "a" to
404         * endFunctionCallArguments.
405         */
406        virtual int beginFunctionCallArguments() = 0;
407
408        /* Emit code to store R0 to the stack at byte offset l.
409         * Returns stack size of object (typically 4 or 8 bytes)
410         */
411        virtual size_t storeR0ToArg(int l, Type* pArgType) = 0;
412
413        /* Patch the function call preamble.
414         * a is the address returned from beginFunctionCallArguments
415         * l is the number of bytes the arguments took on the stack.
416         * Typically you would also emit code to convert the argument
417         * list into whatever the native function calling convention is.
418         * On ARM for example you would pop the first 5 arguments into
419         * R0..R4
420         */
421        virtual void endFunctionCallArguments(Type* pDecl, int a, int l) = 0;
422
423        /* Emit a call to an unknown function. The argument "symbol" needs to
424         * be stored in the location where the address should go. It forms
425         * a chain. The address will be patched later.
426         * Return the address of the word that has to be patched.
427         */
428        virtual int callForward(int symbol, Type* pFunc) = 0;
429
430        /* Call a function pointer. L is the number of bytes the arguments
431         * take on the stack. The address of the function is stored at
432         * location SP + l.
433         */
434        virtual void callIndirect(int l, Type* pFunc) = 0;
435
436        /* Adjust SP after returning from a function call. l is the
437         * number of bytes of arguments stored on the stack. isIndirect
438         * is true if this was an indirect call. (In which case the
439         * address of the function is stored at location SP + l.)
440         */
441        virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) = 0;
442
443        /* Print a disassembly of the assembled code to out. Return
444         * non-zero if there is an error.
445         */
446        virtual int disassemble(FILE* out) = 0;
447
448        /* Generate a symbol at the current PC. t is the head of a
449         * linked list of addresses to patch.
450         */
451        virtual void gsym(int t) = 0;
452
453        /* Resolve a forward reference function at the current PC.
454         * t is the head of a
455         * linked list of addresses to patch.
456         * (Like gsym, but using absolute address, not PC relative address.)
457         */
458        virtual void resolveForward(int t) = 0;
459
460        /*
461         * Do any cleanup work required at the end of a compile.
462         * For example, an instruction cache might need to be
463         * invalidated.
464         * Return non-zero if there is an error.
465         */
466        virtual int finishCompile() = 0;
467
468        /**
469         * Adjust relative branches by this amount.
470         */
471        virtual int jumpOffset() = 0;
472
473        /**
474         * Memory alignment (in bytes) for this type of data
475         */
476        virtual size_t alignmentOf(Type* type) = 0;
477
478        /**
479         * Array element alignment (in bytes) for this type of data.
480         */
481        virtual size_t sizeOf(Type* type) = 0;
482
483        /**
484         * Stack alignment of this type of data
485         */
486        virtual size_t stackAlignmentOf(Type* pType) = 0;
487
488        /**
489         * Argument stack argument size of this data type.
490         */
491        virtual size_t stackSizeOf(Type* pType) = 0;
492
493        virtual Type* getR0Type() {
494            return mExpressionStack.back().pType;
495        }
496
497        virtual ExpressionType getR0ExpressionType() {
498            return mExpressionStack.back().et;
499        }
500
501        virtual void setR0ExpressionType(ExpressionType et) {
502            mExpressionStack.back().et = et;
503        }
504
505        virtual size_t getExpressionStackDepth() {
506            return mExpressionStack.size();
507        }
508
509        virtual void forceR0RVal() {
510            if (getR0ExpressionType() == ET_LVALUE) {
511                loadR0FromR0();
512            }
513        }
514
515    protected:
516        /*
517         * Output a byte. Handles all values, 0..ff.
518         */
519        void ob(int n) {
520            pCodeBuf->ob(n);
521        }
522
523        intptr_t o4(int data) {
524            return pCodeBuf->o4(data);
525        }
526
527        intptr_t getBase() {
528            return (intptr_t) pCodeBuf->getBase();
529        }
530
531        intptr_t getPC() {
532            return pCodeBuf->getPC();
533        }
534
535        intptr_t getSize() {
536            return pCodeBuf->getSize();
537        }
538
539        void error(const char* fmt,...) {
540            va_list ap;
541            va_start(ap, fmt);
542            mErrorSink->verror(fmt, ap);
543            va_end(ap);
544        }
545
546        void assert(bool test) {
547            if (!test) {
548                * (char*) 0 = 0;
549                error("code generator assertion failed.");
550            }
551        }
552
553        void setR0Type(Type* pType) {
554            assert(pType != NULL);
555            mExpressionStack.back().pType = pType;
556            mExpressionStack.back().et = ET_RVALUE;
557        }
558
559        void setR0Type(Type* pType, ExpressionType et) {
560            assert(pType != NULL);
561            mExpressionStack.back().pType = pType;
562            mExpressionStack.back().et = et;
563        }
564
565        Type* getTOSType() {
566            return mExpressionStack[mExpressionStack.size()-2].pType;
567        }
568
569        void pushType() {
570            if (mExpressionStack.size()) {
571                mExpressionStack.push_back(mExpressionStack.back());
572            } else {
573                mExpressionStack.push_back(ExpressionValue());
574            }
575
576        }
577
578        void overType() {
579            size_t size = mExpressionStack.size();
580            if (size >= 2) {
581                mExpressionStack.push_back(mExpressionStack.back());
582                mExpressionStack[size-1] = mExpressionStack[size-2];
583                mExpressionStack[size-2] = mExpressionStack[size];
584            }
585        }
586
587        void popType() {
588            mExpressionStack.pop_back();
589        }
590
591        bool bitsSame(Type* pA, Type* pB) {
592            return collapseType(pA->tag) == collapseType(pB->tag);
593        }
594
595        TypeTag collapseType(TypeTag tag) {
596            static const TypeTag collapsedTag[] = {
597                    TY_INT, TY_INT, TY_VOID, TY_FLOAT, TY_DOUBLE, TY_INT,
598                    TY_VOID, TY_VOID};
599            return collapsedTag[tag];
600        }
601
602        TypeTag collapseTypeR0() {
603            return collapseType(getR0Type()->tag);
604        }
605
606        bool isFloatType(Type* pType) {
607            return isFloatTag(pType->tag);
608        }
609
610        bool isFloatTag(TypeTag tag) {
611            return tag == TY_FLOAT || tag == TY_DOUBLE;
612        }
613
614        Type* mkpInt;
615
616    private:
617        Vector<ExpressionValue> mExpressionStack;
618        CodeBuf* pCodeBuf;
619        ErrorSink* mErrorSink;
620    };
621
622#ifdef PROVIDE_ARM_CODEGEN
623
624    class ARMCodeGenerator : public CodeGenerator {
625    public:
626        ARMCodeGenerator() {}
627
628        virtual ~ARMCodeGenerator() {}
629
630        /* returns address to patch with local variable size
631        */
632        virtual int functionEntry(Type* pDecl) {
633            mStackUse = 0;
634            // sp -> arg4 arg5 ...
635            // Push our register-based arguments back on the stack
636            int regArgCount = calcRegArgCount(pDecl);
637            if (regArgCount > 0) {
638                mStackUse += regArgCount * 4;
639                o4(0xE92D0000 | ((1 << regArgCount) - 1)); // stmfd    sp!, {}
640            }
641            // sp -> arg0 arg1 ...
642            o4(0xE92D4800); // stmfd sp!, {fp, lr}
643            mStackUse += 2 * 4;
644            // sp, fp -> oldfp, retadr, arg0 arg1 ....
645            o4(0xE1A0B00D); // mov    fp, sp
646            LOG_STACK("functionEntry: %d\n", mStackUse);
647            return o4(0xE24DD000); // sub    sp, sp, # <local variables>
648            // We don't know how many local variables we are going to use,
649            // but we will round the allocation up to a multiple of
650            // STACK_ALIGNMENT, so it won't affect the stack alignment.
651        }
652
653        virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) {
654            // Round local variable size up to a multiple of stack alignment
655            localVariableSize = ((localVariableSize + STACK_ALIGNMENT - 1) /
656                STACK_ALIGNMENT) * STACK_ALIGNMENT;
657            // Patch local variable allocation code:
658            if (localVariableSize < 0 || localVariableSize > 255) {
659                error("localVariables out of range: %d", localVariableSize);
660            }
661            *(char*) (localVariableAddress) = localVariableSize;
662
663            // sp -> locals .... fp -> oldfp, retadr, arg0, arg1, ...
664            o4(0xE1A0E00B); // mov lr, fp
665            o4(0xE59BB000); // ldr fp, [fp]
666            o4(0xE28ED004); // add sp, lr, #4
667            // sp -> retadr, arg0, ...
668            o4(0xE8BD4000); // ldmfd    sp!, {lr}
669            // sp -> arg0 ....
670
671            // We store the PC into the lr so we can adjust the sp before
672            // returning. We need to pull off the registers we pushed
673            // earlier. We don't need to actually store them anywhere,
674            // just adjust the stack.
675            int regArgCount = calcRegArgCount(pDecl);
676            if (regArgCount) {
677                o4(0xE28DD000 | (regArgCount << 2)); // add sp, sp, #argCount << 2
678            }
679            o4(0xE12FFF1E); // bx lr
680        }
681
682        /* load immediate value */
683        virtual void li(int t) {
684            liReg(t, 0);
685            setR0Type(mkpInt);
686        }
687
688        virtual void loadFloat(int address, Type* pType) {
689            setR0Type(pType);
690            // Global, absolute address
691            o4(0xE59F0000); //        ldr r0, .L1
692            o4(0xEA000000); //        b .L99
693            o4(address);         // .L1:   .word ea
694                                 // .L99:
695
696            switch (pType->tag) {
697            case TY_FLOAT:
698                o4(0xE5900000);      // ldr r0, [r0]
699                break;
700            case TY_DOUBLE:
701                o4(0xE1C000D0);      // ldrd r0, [r0]
702                break;
703            default:
704                assert(false);
705                break;
706            }
707        }
708
709        virtual int gjmp(int t) {
710            return o4(0xEA000000 | encodeAddress(t)); // b .L33
711        }
712
713        /* l = 0: je, l == 1: jne */
714        virtual int gtst(bool l, int t) {
715            Type* pR0Type = getR0Type();
716            TypeTag tagR0 = pR0Type->tag;
717            switch(tagR0) {
718                case TY_FLOAT:
719                    callRuntime((void*) runtime_is_non_zero_f);
720                    break;
721                case TY_DOUBLE:
722                    callRuntime((void*) runtime_is_non_zero_d);
723                    break;
724                default:
725                    break;
726            }
727            o4(0xE3500000); // cmp r0,#0
728            int branch = l ? 0x1A000000 : 0x0A000000; // bne : beq
729            return o4(branch | encodeAddress(t));
730        }
731
732        virtual void gcmp(int op) {
733            Type* pR0Type = getR0Type();
734            Type* pTOSType = getTOSType();
735            TypeTag tagR0 = collapseType(pR0Type->tag);
736            TypeTag tagTOS = collapseType(pTOSType->tag);
737            if (tagR0 == TY_INT && tagTOS == TY_INT) {
738                setupIntPtrArgs();
739                o4(0xE1510000); // cmp r1, r1
740                switch(op) {
741                case OP_EQUALS:
742                    o4(0x03A00001); // moveq r0,#1
743                    o4(0x13A00000); // movne r0,#0
744                    break;
745                case OP_NOT_EQUALS:
746                    o4(0x03A00000); // moveq r0,#0
747                    o4(0x13A00001); // movne r0,#1
748                    break;
749                case OP_LESS_EQUAL:
750                    o4(0xD3A00001); // movle r0,#1
751                    o4(0xC3A00000); // movgt r0,#0
752                    break;
753                case OP_GREATER:
754                    o4(0xD3A00000); // movle r0,#0
755                    o4(0xC3A00001); // movgt r0,#1
756                    break;
757                case OP_GREATER_EQUAL:
758                    o4(0xA3A00001); // movge r0,#1
759                    o4(0xB3A00000); // movlt r0,#0
760                    break;
761                case OP_LESS:
762                    o4(0xA3A00000); // movge r0,#0
763                    o4(0xB3A00001); // movlt r0,#1
764                    break;
765                default:
766                    error("Unknown comparison op %d", op);
767                    break;
768                }
769            } else if (tagR0 == TY_DOUBLE || tagTOS == TY_DOUBLE) {
770                setupDoubleArgs();
771                switch(op) {
772                    case OP_EQUALS:
773                        callRuntime((void*) runtime_cmp_eq_dd);
774                        break;
775                    case OP_NOT_EQUALS:
776                        callRuntime((void*) runtime_cmp_ne_dd);
777                        break;
778                    case OP_LESS_EQUAL:
779                        callRuntime((void*) runtime_cmp_le_dd);
780                        break;
781                    case OP_GREATER:
782                        callRuntime((void*) runtime_cmp_gt_dd);
783                        break;
784                    case OP_GREATER_EQUAL:
785                        callRuntime((void*) runtime_cmp_ge_dd);
786                        break;
787                    case OP_LESS:
788                        callRuntime((void*) runtime_cmp_lt_dd);
789                        break;
790                    default:
791                        error("Unknown comparison op %d", op);
792                        break;
793                }
794            } else {
795                setupFloatArgs();
796                switch(op) {
797                    case OP_EQUALS:
798                        callRuntime((void*) runtime_cmp_eq_ff);
799                        break;
800                    case OP_NOT_EQUALS:
801                        callRuntime((void*) runtime_cmp_ne_ff);
802                        break;
803                    case OP_LESS_EQUAL:
804                        callRuntime((void*) runtime_cmp_le_ff);
805                        break;
806                    case OP_GREATER:
807                        callRuntime((void*) runtime_cmp_gt_ff);
808                        break;
809                    case OP_GREATER_EQUAL:
810                        callRuntime((void*) runtime_cmp_ge_ff);
811                        break;
812                    case OP_LESS:
813                        callRuntime((void*) runtime_cmp_lt_ff);
814                        break;
815                    default:
816                        error("Unknown comparison op %d", op);
817                        break;
818                }
819            }
820            setR0Type(mkpInt);
821        }
822
823        virtual void genOp(int op) {
824            Type* pR0Type = getR0Type();
825            Type* pTOSType = getTOSType();
826            TypeTag tagR0 = pR0Type->tag;
827            TypeTag tagTOS = pTOSType->tag;
828            bool isFloatR0 = isFloatTag(tagR0);
829            bool isFloatTOS = isFloatTag(tagTOS);
830            if (!isFloatR0 && !isFloatTOS) {
831                setupIntPtrArgs();
832                bool isPtrR0 = tagR0 == TY_POINTER;
833                bool isPtrTOS = tagTOS == TY_POINTER;
834                if (isPtrR0 || isPtrTOS) {
835                    if (isPtrR0 && isPtrTOS) {
836                        if (op != OP_MINUS) {
837                            error("Unsupported pointer-pointer operation %d.", op);
838                        }
839                        if (! typeEqual(pR0Type, pTOSType)) {
840                            error("Incompatible pointer types for subtraction.");
841                        }
842                        o4(0xE0410000); // sub     r0,r1,r0
843                        setR0Type(mkpInt);
844                        int size = sizeOf(pR0Type->pHead);
845                        if (size != 1) {
846                            pushR0();
847                            li(size);
848                            // TODO: Optimize for power-of-two.
849                            genOp(OP_DIV);
850                        }
851                    } else {
852                        if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) {
853                            error("Unsupported pointer-scalar operation %d", op);
854                        }
855                        Type* pPtrType = isPtrR0 ? pR0Type : pTOSType;
856                        int size = sizeOf(pPtrType->pHead);
857                        if (size != 1) {
858                            // TODO: Optimize for power-of-two.
859                            liReg(size, 2);
860                            if (isPtrR0) {
861                                o4(0x0E0010192); // mul     r1,r2,r1
862                            } else {
863                                o4(0x0E0000092); // mul     r0,r2,r0
864                            }
865                        }
866                        switch(op) {
867                            case OP_PLUS:
868                            o4(0xE0810000); // add     r0,r1,r0
869                            break;
870                            case OP_MINUS:
871                            o4(0xE0410000); // sub     r0,r1,r0
872                            break;
873                        }
874                        setR0Type(pPtrType);
875                    }
876                } else {
877                    switch(op) {
878                        case OP_MUL:
879                        o4(0x0E0000091); // mul     r0,r1,r0
880                        break;
881                        case OP_DIV:
882                        callRuntime((void*) runtime_DIV);
883                        break;
884                        case OP_MOD:
885                        callRuntime((void*) runtime_MOD);
886                        break;
887                        case OP_PLUS:
888                        o4(0xE0810000); // add     r0,r1,r0
889                        break;
890                        case OP_MINUS:
891                        o4(0xE0410000); // sub     r0,r1,r0
892                        break;
893                        case OP_SHIFT_LEFT:
894                        o4(0xE1A00011); // lsl     r0,r1,r0
895                        break;
896                        case OP_SHIFT_RIGHT:
897                        o4(0xE1A00051); // asr     r0,r1,r0
898                        break;
899                        case OP_BIT_AND:
900                        o4(0xE0010000); // and     r0,r1,r0
901                        break;
902                        case OP_BIT_XOR:
903                        o4(0xE0210000); // eor     r0,r1,r0
904                        break;
905                        case OP_BIT_OR:
906                        o4(0xE1810000); // orr     r0,r1,r0
907                        break;
908                        case OP_BIT_NOT:
909                        o4(0xE1E00000); // mvn     r0, r0
910                        break;
911                        default:
912                        error("Unimplemented op %d\n", op);
913                        break;
914                    }
915                }
916            } else {
917                Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType;
918                if (pResultType->tag == TY_DOUBLE) {
919                    setupDoubleArgs();
920                    switch(op) {
921                    case OP_MUL:
922                        callRuntime((void*) runtime_op_mul_dd);
923                        break;
924                    case OP_DIV:
925                        callRuntime((void*) runtime_op_div_dd);
926                        break;
927                    case OP_PLUS:
928                        callRuntime((void*) runtime_op_add_dd);
929                        break;
930                    case OP_MINUS:
931                        callRuntime((void*) runtime_op_sub_dd);
932                        break;
933                    default:
934                        error("Unsupported binary floating operation %d\n", op);
935                        break;
936                    }
937                } else {
938                    setupFloatArgs();
939                    switch(op) {
940                    case OP_MUL:
941                        callRuntime((void*) runtime_op_mul_ff);
942                        break;
943                    case OP_DIV:
944                        callRuntime((void*) runtime_op_div_ff);
945                        break;
946                    case OP_PLUS:
947                        callRuntime((void*) runtime_op_add_ff);
948                        break;
949                    case OP_MINUS:
950                        callRuntime((void*) runtime_op_sub_ff);
951                        break;
952                    default:
953                        error("Unsupported binary floating operation %d\n", op);
954                        break;
955                    }
956                }
957                setR0Type(pResultType);
958            }
959        }
960
961        virtual void gUnaryCmp(int op) {
962            if (op != OP_LOGICAL_NOT) {
963                error("Unknown unary cmp %d", op);
964            } else {
965                Type* pR0Type = getR0Type();
966                TypeTag tag = collapseType(pR0Type->tag);
967                switch(tag) {
968                    case TY_INT:
969                        o4(0xE3A01000); // mov    r1, #0
970                        o4(0xE1510000); // cmp r1, r0
971                        o4(0x03A00001); // moveq r0,#1
972                        o4(0x13A00000); // movne r0,#0
973                        break;
974                    case TY_FLOAT:
975                        callRuntime((void*) runtime_is_zero_f);
976                        break;
977                    case TY_DOUBLE:
978                        callRuntime((void*) runtime_is_zero_d);
979                        break;
980                    default:
981                        error("gUnaryCmp unsupported type");
982                        break;
983                }
984            }
985            setR0Type(mkpInt);
986        }
987
988        virtual void genUnaryOp(int op) {
989            Type* pR0Type = getR0Type();
990            TypeTag tag = collapseType(pR0Type->tag);
991            switch(tag) {
992                case TY_INT:
993                    switch(op) {
994                    case OP_MINUS:
995                        o4(0xE3A01000);  // mov    r1, #0
996                        o4(0xE0410000);  // sub     r0,r1,r0
997                        break;
998                    case OP_BIT_NOT:
999                        o4(0xE1E00000);  // mvn     r0, r0
1000                        break;
1001                    default:
1002                        error("Unknown unary op %d\n", op);
1003                        break;
1004                    }
1005                    break;
1006                case TY_FLOAT:
1007                case TY_DOUBLE:
1008                    switch (op) {
1009                        case OP_MINUS:
1010                            if (tag == TY_FLOAT) {
1011                                callRuntime((void*) runtime_op_neg_f);
1012                            } else {
1013                                callRuntime((void*) runtime_op_neg_d);
1014                            }
1015                            break;
1016                        case OP_BIT_NOT:
1017                            error("Can't apply '~' operator to a float or double.");
1018                            break;
1019                        default:
1020                            error("Unknown unary op %d\n", op);
1021                            break;
1022                        }
1023                    break;
1024                default:
1025                    error("genUnaryOp unsupported type");
1026                    break;
1027            }
1028        }
1029
1030        virtual void pushR0() {
1031            Type* pR0Type = getR0Type();
1032            TypeTag r0ct = collapseType(pR0Type->tag);
1033            if (r0ct != TY_DOUBLE) {
1034                    o4(0xE92D0001);  // stmfd   sp!,{r0}
1035                    mStackUse += 4;
1036            } else {
1037                    o4(0xE92D0003);  // stmfd   sp!,{r0,r1}
1038                    mStackUse += 8;
1039            }
1040            pushType();
1041            LOG_STACK("pushR0: %d\n", mStackUse);
1042        }
1043
1044        virtual void over() {
1045            // We know it's only used for int-ptr ops (++/--)
1046
1047            Type* pR0Type = getR0Type();
1048            TypeTag r0ct = collapseType(pR0Type->tag);
1049
1050            Type* pTOSType = getTOSType();
1051            TypeTag tosct = collapseType(pTOSType->tag);
1052
1053            assert (r0ct == TY_INT  && tosct == TY_INT);
1054
1055            o4(0xE8BD0002);  // ldmfd   sp!,{r1}
1056            o4(0xE92D0001);  // stmfd   sp!,{r0}
1057            o4(0xE92D0002);  // stmfd   sp!,{r1}
1058            overType();
1059            mStackUse += 4;
1060        }
1061
1062        virtual void popR0() {
1063            Type* pTOSType = getTOSType();
1064            switch (collapseType(pTOSType->tag)){
1065                case TY_INT:
1066                case TY_FLOAT:
1067                    o4(0xE8BD0001);  // ldmfd   sp!,{r0}
1068                    mStackUse -= 4;
1069                    break;
1070                case TY_DOUBLE:
1071                    o4(0xE8BD0003);  // ldmfd   sp!,{r0, r1}  // Restore R0
1072                        mStackUse -= 8;
1073                    break;
1074                default:
1075                    error("Can't pop this type.");
1076                    break;
1077            }
1078            popType();
1079            LOG_STACK("popR0: %d\n", mStackUse);
1080        }
1081
1082        virtual void storeR0ToTOS() {
1083            Type* pPointerType = getTOSType();
1084            assert(pPointerType->tag == TY_POINTER);
1085            Type* pDestType = pPointerType->pHead;
1086            convertR0(pDestType);
1087            o4(0xE8BD0004);  // ldmfd   sp!,{r2}
1088            popType();
1089            mStackUse -= 4;
1090            switch (pDestType->tag) {
1091                case TY_POINTER:
1092                case TY_INT:
1093                case TY_FLOAT:
1094                    o4(0xE5820000); // str r0, [r2]
1095                    break;
1096                case TY_CHAR:
1097                    o4(0xE5C20000); // strb r0, [r2]
1098                    break;
1099                case TY_DOUBLE:
1100                    o4(0xE1C200F0); // strd r0, [r2]
1101                    break;
1102                default:
1103                    error("storeR0ToTOS: unimplemented type %d",
1104                            pDestType->tag);
1105                    break;
1106            }
1107        }
1108
1109        virtual void loadR0FromR0() {
1110            Type* pPointerType = getR0Type();
1111            assert(pPointerType->tag == TY_POINTER);
1112            switch (pPointerType->pHead->tag) {
1113                case TY_POINTER:
1114                case TY_INT:
1115                case TY_FLOAT:
1116                    o4(0xE5900000); // ldr r0, [r0]
1117                    break;
1118                case TY_CHAR:
1119                    o4(0xE5D00000); // ldrb r0, [r0]
1120                    break;
1121                case TY_DOUBLE:
1122                    o4(0xE1C000D0); // ldrd   r0, [r0]
1123                    break;
1124                default:
1125                    error("loadR0FromR0: unimplemented type");
1126                    break;
1127            }
1128            setR0Type(pPointerType->pHead);
1129        }
1130
1131        virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) {
1132            if (ea > -LOCAL && ea < LOCAL) {
1133                // Local, fp relative
1134                if (ea < -1023 || ea > 1023 || ((ea & 3) != 0)) {
1135                    error("Offset out of range: %08x", ea);
1136                }
1137                if (ea < 0) {
1138                    o4(0xE24B0F00 | (0xff & ((-ea) >> 2))); // sub    r0, fp, #ea
1139                } else {
1140                    o4(0xE28B0F00 | (0xff & (ea >> 2))); // add    r0, fp, #ea
1141                }
1142            } else {
1143                // Global, absolute.
1144                o4(0xE59F0000); //        ldr    r0, .L1
1145                o4(0xEA000000); //        b .L99
1146                o4(ea);         // .L1:   .word 0
1147                                // .L99:
1148            }
1149            setR0Type(pPointerType, et);
1150        }
1151
1152        virtual int leaForward(int ea, Type* pPointerType) {
1153            setR0Type(pPointerType);
1154            int result = ea;
1155            int pc = getPC();
1156            int offset = 0;
1157            if (ea) {
1158                offset = (pc - ea - 8) >> 2;
1159                if ((offset & 0xffff) != offset) {
1160                    error("function forward reference out of bounds");
1161                }
1162            } else {
1163                offset = 0;
1164            }
1165            o4(0xE59F0000 | offset); //        ldr    r0, .L1
1166
1167            if (ea == 0) {
1168                o4(0xEA000000); //        b .L99
1169                result = o4(ea);         // .L1:   .word 0
1170                            // .L99:
1171            }
1172            return result;
1173        }
1174
1175        virtual void convertR0(Type* pType){
1176            Type* pR0Type = getR0Type();
1177            if (bitsSame(pType, pR0Type)) {
1178                // do nothing special
1179            } else {
1180                TypeTag r0Tag = collapseType(pR0Type->tag);
1181                TypeTag destTag = collapseType(pType->tag);
1182                if (r0Tag == TY_INT) {
1183                    if (destTag == TY_FLOAT) {
1184                        callRuntime((void*) runtime_int_to_float);
1185                    } else {
1186                        assert(destTag == TY_DOUBLE);
1187                        callRuntime((void*) runtime_int_to_double);
1188                    }
1189                } else if (r0Tag == TY_FLOAT) {
1190                    if (destTag == TY_INT) {
1191                        callRuntime((void*) runtime_float_to_int);
1192                    } else {
1193                        assert(destTag == TY_DOUBLE);
1194                        callRuntime((void*) runtime_float_to_double);
1195                    }
1196                } else {
1197                    assert (r0Tag == TY_DOUBLE);
1198                    if (destTag == TY_INT) {
1199                        callRuntime((void*) runtime_double_to_int);
1200                    } else {
1201                        assert(destTag == TY_FLOAT);
1202                        callRuntime((void*) runtime_double_to_float);
1203                    }
1204                }
1205            }
1206            setR0Type(pType);
1207        }
1208
1209        virtual int beginFunctionCallArguments() {
1210            return o4(0xE24DDF00); // Placeholder
1211        }
1212
1213        virtual size_t storeR0ToArg(int l, Type* pArgType) {
1214            convertR0(pArgType);
1215            Type* pR0Type = getR0Type();
1216            TypeTag r0ct = collapseType(pR0Type->tag);
1217            switch(r0ct) {
1218                case TY_INT:
1219                case TY_FLOAT:
1220                    if (l < 0 || l > 4096-4) {
1221                        error("l out of range for stack offset: 0x%08x", l);
1222                    }
1223                    o4(0xE58D0000 + l); // str r0, [sp, #l]
1224                    return 4;
1225                case TY_DOUBLE: {
1226                    // Align to 8 byte boundary
1227                    int l2 = (l + 7) & ~7;
1228                    if (l2 < 0 || l2 > 4096-8) {
1229                        error("l out of range for stack offset: 0x%08x", l);
1230                    }
1231                    o4(0xE58D0000 + l2); // str r0, [sp, #l]
1232                    o4(0xE58D1000 + l2 + 4); // str r1, [sp, #l+4]
1233                    return (l2 - l) + 8;
1234                }
1235                default:
1236                    assert(false);
1237                    return 0;
1238            }
1239        }
1240
1241        virtual void endFunctionCallArguments(Type* pDecl, int a, int l) {
1242            int argumentStackUse = l;
1243            // Have to calculate register arg count from actual stack size,
1244            // in order to properly handle ... functions.
1245            int regArgCount = l >> 2;
1246            if (regArgCount > 4) {
1247                regArgCount = 4;
1248            }
1249            if (regArgCount > 0) {
1250                argumentStackUse -= regArgCount * 4;
1251                o4(0xE8BD0000 | ((1 << regArgCount) - 1)); // ldmfd   sp!,{}
1252            }
1253            mStackUse += argumentStackUse;
1254
1255            // Align stack.
1256            int missalignment = mStackUse - ((mStackUse / STACK_ALIGNMENT)
1257                    * STACK_ALIGNMENT);
1258            mStackAlignmentAdjustment = 0;
1259            if (missalignment > 0) {
1260                mStackAlignmentAdjustment = STACK_ALIGNMENT - missalignment;
1261            }
1262            l += mStackAlignmentAdjustment;
1263
1264            if (l < 0 || l > 0x3FC) {
1265                error("L out of range for stack adjustment: 0x%08x", l);
1266            }
1267            * (int*) a = 0xE24DDF00 | (l >> 2); // sub    sp, sp, #0 << 2
1268            mStackUse += mStackAlignmentAdjustment;
1269            LOG_STACK("endFunctionCallArguments mStackUse: %d, mStackAlignmentAdjustment %d\n",
1270                      mStackUse, mStackAlignmentAdjustment);
1271        }
1272
1273        virtual int callForward(int symbol, Type* pFunc) {
1274            setR0Type(pFunc->pHead);
1275            // Forward calls are always short (local)
1276            return o4(0xEB000000 | encodeAddress(symbol));
1277        }
1278
1279        virtual void callIndirect(int l, Type* pFunc) {
1280            assert(pFunc->tag == TY_FUNC);
1281            popType(); // Get rid of indirect fn pointer type
1282            setR0Type(pFunc->pHead);
1283            int argCount = l >> 2;
1284            int poppedArgs = argCount > 4 ? 4 : argCount;
1285            int adjustedL = l - (poppedArgs << 2) + mStackAlignmentAdjustment;
1286            if (adjustedL < 0 || adjustedL > 4096-4) {
1287                error("l out of range for stack offset: 0x%08x", l);
1288            }
1289            o4(0xE59DC000 | (0xfff & adjustedL)); // ldr    r12, [sp,#adjustedL]
1290            o4(0xE12FFF3C); // blx r12
1291        }
1292
1293        virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) {
1294            int argCount = l >> 2;
1295            // Have to calculate register arg count from actual stack size,
1296            // in order to properly handle ... functions.
1297            int regArgCount = l >> 2;
1298            if (regArgCount > 4) {
1299                regArgCount = 4;
1300            }
1301            int stackArgs = argCount - regArgCount;
1302            int stackUse =  stackArgs + (isIndirect ? 1 : 0)
1303                + (mStackAlignmentAdjustment >> 2);
1304            if (stackUse) {
1305                if (stackUse < 0 || stackUse > 255) {
1306                    error("L out of range for stack adjustment: 0x%08x", l);
1307                }
1308                o4(0xE28DDF00 | stackUse); // add    sp, sp, #stackUse << 2
1309                mStackUse -= stackUse * 4;
1310                LOG_STACK("adjustStackAfterCall: %d\n", mStackUse);
1311            }
1312        }
1313
1314        virtual int jumpOffset() {
1315            return 8;
1316        }
1317
1318        /* output a symbol and patch all calls to it */
1319        virtual void gsym(int t) {
1320            int n;
1321            int base = getBase();
1322            int pc = getPC();
1323            while (t) {
1324                int data = * (int*) t;
1325                int decodedOffset = ((BRANCH_REL_ADDRESS_MASK & data) << 2);
1326                if (decodedOffset == 0) {
1327                    n = 0;
1328                } else {
1329                    n = base + decodedOffset; /* next value */
1330                }
1331                *(int *) t = (data & ~BRANCH_REL_ADDRESS_MASK)
1332                    | encodeRelAddress(pc - t - 8);
1333                t = n;
1334            }
1335        }
1336
1337        /* output a symbol and patch all calls to it */
1338        virtual void resolveForward(int t) {
1339            if (t) {
1340                int pc = getPC();
1341                *(int *) t = pc;
1342            }
1343        }
1344
1345        virtual int finishCompile() {
1346#if defined(__arm__)
1347            const long base = long(getBase());
1348            const long curr = long(getPC());
1349            int err = cacheflush(base, curr, 0);
1350            return err;
1351#else
1352            return 0;
1353#endif
1354        }
1355
1356        virtual int disassemble(FILE* out) {
1357#ifdef ENABLE_ARM_DISASSEMBLY
1358            disasmOut = out;
1359            disasm_interface_t  di;
1360            di.di_readword = disassemble_readword;
1361            di.di_printaddr = disassemble_printaddr;
1362            di.di_printf = disassemble_printf;
1363
1364            int base = getBase();
1365            int pc = getPC();
1366            for(int i = base; i < pc; i += 4) {
1367                fprintf(out, "%08x: %08x  ", i, *(int*) i);
1368                ::disasm(&di, i, 0);
1369            }
1370#endif
1371            return 0;
1372        }
1373
1374        /**
1375         * alignment (in bytes) for this type of data
1376         */
1377        virtual size_t alignmentOf(Type* pType){
1378            switch(pType->tag) {
1379                case TY_CHAR:
1380                    return 1;
1381                case TY_DOUBLE:
1382                    return 8;
1383                default:
1384                    return 4;
1385            }
1386        }
1387
1388        /**
1389         * Array element alignment (in bytes) for this type of data.
1390         */
1391        virtual size_t sizeOf(Type* pType){
1392            switch(pType->tag) {
1393                case TY_INT:
1394                    return 4;
1395                case TY_CHAR:
1396                    return 1;
1397                default:
1398                    return 0;
1399                case TY_FLOAT:
1400                    return 4;
1401                case TY_DOUBLE:
1402                    return 8;
1403                case TY_POINTER:
1404                    return 4;
1405            }
1406        }
1407
1408        virtual size_t stackAlignmentOf(Type* pType) {
1409            switch(pType->tag) {
1410                case TY_DOUBLE:
1411                    return 8;
1412                default:
1413                    return 4;
1414            }
1415        }
1416
1417        virtual size_t stackSizeOf(Type* pType) {
1418            switch(pType->tag) {
1419                case TY_DOUBLE:
1420                    return 8;
1421                default:
1422                    return 4;
1423            }
1424        }
1425
1426    private:
1427        static FILE* disasmOut;
1428
1429        static u_int
1430        disassemble_readword(u_int address)
1431        {
1432            return(*((u_int *)address));
1433        }
1434
1435        static void
1436        disassemble_printaddr(u_int address)
1437        {
1438            fprintf(disasmOut, "0x%08x", address);
1439        }
1440
1441        static void
1442        disassemble_printf(const char *fmt, ...) {
1443            va_list ap;
1444            va_start(ap, fmt);
1445            vfprintf(disasmOut, fmt, ap);
1446            va_end(ap);
1447        }
1448
1449        static const int BRANCH_REL_ADDRESS_MASK = 0x00ffffff;
1450
1451        /** Encode a relative address that might also be
1452         * a label.
1453         */
1454        int encodeAddress(int value) {
1455            int base = getBase();
1456            if (value >= base && value <= getPC() ) {
1457                // This is a label, encode it relative to the base.
1458                value = value - base;
1459            }
1460            return encodeRelAddress(value);
1461        }
1462
1463        int encodeRelAddress(int value) {
1464            return BRANCH_REL_ADDRESS_MASK & (value >> 2);
1465        }
1466
1467        int calcRegArgCount(Type* pDecl) {
1468            int reg = 0;
1469            Type* pArgs = pDecl->pTail;
1470            while (pArgs && reg < 4) {
1471                Type* pArg = pArgs->pHead;
1472                if ( pArg->tag == TY_DOUBLE) {
1473                    int evenReg = (reg + 1) & ~1;
1474                    if (evenReg >= 4) {
1475                        break;
1476                    }
1477                    reg = evenReg + 2;
1478                } else {
1479                    reg++;
1480                }
1481                pArgs = pArgs->pTail;
1482            }
1483            return reg;
1484        }
1485
1486        void setupIntPtrArgs() {
1487            o4(0xE8BD0002);  // ldmfd   sp!,{r1}
1488            mStackUse -= 4;
1489            popType();
1490        }
1491
1492        /* Pop TOS to R1
1493         * Make sure both R0 and TOS are floats. (Could be ints)
1494         * We know that at least one of R0 and TOS is already a float
1495         */
1496        void setupFloatArgs() {
1497            Type* pR0Type = getR0Type();
1498            Type* pTOSType = getTOSType();
1499            TypeTag tagR0 = collapseType(pR0Type->tag);
1500            TypeTag tagTOS = collapseType(pTOSType->tag);
1501            if (tagR0 != TY_FLOAT) {
1502                assert(tagR0 == TY_INT);
1503                callRuntime((void*) runtime_int_to_float);
1504            }
1505            if (tagTOS != TY_FLOAT) {
1506                assert(tagTOS == TY_INT);
1507                assert(tagR0 == TY_FLOAT);
1508                o4(0xE92D0001);  // stmfd   sp!,{r0}  // push R0
1509                o4(0xE59D0004);  // ldr     r0, [sp, #4]
1510                callRuntime((void*) runtime_int_to_float);
1511                o4(0xE1A01000);  // mov r1, r0
1512                o4(0xE8BD0001);  // ldmfd   sp!,{r0}  // pop R0
1513                o4(0xE28DD004);  // add sp, sp, #4 // Pop sp
1514            } else {
1515                // Pop TOS
1516                o4(0xE8BD0002);  // ldmfd   sp!,{r1}
1517            }
1518            mStackUse -= 4;
1519            popType();
1520        }
1521
1522        /* Pop TOS into R2..R3
1523         * Make sure both R0 and TOS are doubles. Could be floats or ints.
1524         * We know that at least one of R0 and TOS are already a double.
1525         */
1526
1527        void setupDoubleArgs() {
1528            Type* pR0Type = getR0Type();
1529            Type* pTOSType = getTOSType();
1530            TypeTag tagR0 = collapseType(pR0Type->tag);
1531            TypeTag tagTOS = collapseType(pTOSType->tag);
1532            if (tagR0 != TY_DOUBLE) {
1533                if (tagR0 == TY_INT) {
1534                    callRuntime((void*) runtime_int_to_double);
1535                } else {
1536                    assert(tagR0 == TY_FLOAT);
1537                    callRuntime((void*) runtime_float_to_double);
1538                }
1539            }
1540            if (tagTOS != TY_DOUBLE) {
1541                o4(0xE92D0003);  // stmfd   sp!,{r0,r1}  // push r0,r1
1542                o4(0xE59D0008);  // ldr     r0, [sp, #8]
1543                if (tagTOS == TY_INT) {
1544                    callRuntime((void*) runtime_int_to_double);
1545                } else {
1546                    assert(tagTOS == TY_FLOAT);
1547                    callRuntime((void*) runtime_float_to_double);
1548                }
1549                o4(0xE1A02000);  // mov r2, r0
1550                o4(0xE1A03001);  // mov r3, r1
1551                o4(0xE8BD0003);  // ldmfd   sp!,{r0, r1}  // Restore R0
1552                o4(0xE28DD004);  // add sp, sp, #4 // Pop sp
1553                mStackUse -= 4;
1554            } else {
1555                o4(0xE8BD000C);  // ldmfd   sp!,{r2,r3}
1556                mStackUse -= 8;
1557            }
1558            popType();
1559        }
1560
1561        void liReg(int t, int reg) {
1562            assert(reg >= 0 && reg < 16);
1563            int rN = (reg & 0xf) << 12;
1564            if (t >= 0 && t < 255) {
1565                 o4((0xE3A00000 + t) | rN); // mov    rN, #0
1566            } else if (t >= -256 && t < 0) {
1567                // mvn means move constant ^ ~0
1568                o4((0xE3E00000 - (t+1)) | rN); // mvn    rN, #0
1569            } else {
1570                  o4(0xE51F0000 | rN); //         ldr    rN, .L3
1571                  o4(0xEA000000); //         b .L99
1572                  o4(t);          // .L3:   .word 0
1573                                  // .L99:
1574            }
1575        }
1576
1577        void callRuntime(void* fn) {
1578            o4(0xE59FC000); // ldr    r12, .L1
1579            o4(0xEA000000); // b      .L99
1580            o4((int) fn);   //.L1:  .word  fn
1581            o4(0xE12FFF3C); //.L99: blx    r12
1582        }
1583
1584        // Integer math:
1585
1586        static int runtime_DIV(int b, int a) {
1587            return a / b;
1588        }
1589
1590        static int runtime_MOD(int b, int a) {
1591            return a % b;
1592        }
1593
1594        // Comparison to zero
1595
1596        static int runtime_is_non_zero_f(float a) {
1597            return a != 0;
1598        }
1599
1600        static int runtime_is_non_zero_d(double a) {
1601            return a != 0;
1602        }
1603
1604        // Comparison to zero
1605
1606        static int runtime_is_zero_f(float a) {
1607            return a == 0;
1608        }
1609
1610        static int runtime_is_zero_d(double a) {
1611            return a == 0;
1612        }
1613
1614        // Type conversion
1615
1616        static int runtime_float_to_int(float a) {
1617            return (int) a;
1618        }
1619
1620        static double runtime_float_to_double(float a) {
1621            return (double) a;
1622        }
1623
1624        static int runtime_double_to_int(double a) {
1625            return (int) a;
1626        }
1627
1628        static float runtime_double_to_float(double a) {
1629            return (float) a;
1630        }
1631
1632        static float runtime_int_to_float(int a) {
1633            return (float) a;
1634        }
1635
1636        static double runtime_int_to_double(int a) {
1637            return (double) a;
1638        }
1639
1640        // Comparisons float
1641
1642        static int runtime_cmp_eq_ff(float b, float a) {
1643            return a == b;
1644        }
1645
1646        static int runtime_cmp_ne_ff(float b, float a) {
1647            return a != b;
1648        }
1649
1650        static int runtime_cmp_lt_ff(float b, float a) {
1651            return a < b;
1652        }
1653
1654        static int runtime_cmp_le_ff(float b, float a) {
1655            return a <= b;
1656        }
1657
1658        static int runtime_cmp_ge_ff(float b, float a) {
1659            return a >= b;
1660        }
1661
1662        static int runtime_cmp_gt_ff(float b, float a) {
1663            return a > b;
1664        }
1665
1666        // Comparisons double
1667
1668        static int runtime_cmp_eq_dd(double b, double a) {
1669            return a == b;
1670        }
1671
1672        static int runtime_cmp_ne_dd(double b, double a) {
1673            return a != b;
1674        }
1675
1676        static int runtime_cmp_lt_dd(double b, double a) {
1677            return a < b;
1678        }
1679
1680        static int runtime_cmp_le_dd(double b, double a) {
1681            return a <= b;
1682        }
1683
1684        static int runtime_cmp_ge_dd(double b, double a) {
1685            return a >= b;
1686        }
1687
1688        static int runtime_cmp_gt_dd(double b, double a) {
1689            return a > b;
1690        }
1691
1692        // Math float
1693
1694        static float runtime_op_add_ff(float b, float a) {
1695            return a + b;
1696        }
1697
1698        static float runtime_op_sub_ff(float b, float a) {
1699            return a - b;
1700        }
1701
1702        static float runtime_op_mul_ff(float b, float a) {
1703            return a * b;
1704        }
1705
1706        static float runtime_op_div_ff(float b, float a) {
1707            return a / b;
1708        }
1709
1710        static float runtime_op_neg_f(float a) {
1711            return -a;
1712        }
1713
1714        // Math double
1715
1716        static double runtime_op_add_dd(double b, double a) {
1717            return a + b;
1718        }
1719
1720        static double runtime_op_sub_dd(double b, double a) {
1721            return a - b;
1722        }
1723
1724        static double runtime_op_mul_dd(double b, double a) {
1725            return a * b;
1726        }
1727
1728        static double runtime_op_div_dd(double b, double a) {
1729            return a / b;
1730        }
1731
1732        static double runtime_op_neg_d(double a) {
1733            return -a;
1734        }
1735
1736        static const int STACK_ALIGNMENT = 8;
1737        int mStackUse;
1738        // This variable holds the amount we adjusted the stack in the most
1739        // recent endFunctionCallArguments call. It's examined by the
1740        // following adjustStackAfterCall call.
1741        int mStackAlignmentAdjustment;
1742    };
1743
1744#endif // PROVIDE_ARM_CODEGEN
1745
1746#ifdef PROVIDE_X86_CODEGEN
1747
1748    class X86CodeGenerator : public CodeGenerator {
1749    public:
1750        X86CodeGenerator() {}
1751        virtual ~X86CodeGenerator() {}
1752
1753        /* returns address to patch with local variable size
1754        */
1755        virtual int functionEntry(Type* pDecl) {
1756            o(0xe58955); /* push   %ebp, mov %esp, %ebp */
1757            return oad(0xec81, 0); /* sub $xxx, %esp */
1758        }
1759
1760        virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) {
1761            o(0xc3c9); /* leave, ret */
1762            *(int *) localVariableAddress = localVariableSize; /* save local variables */
1763        }
1764
1765        /* load immediate value */
1766        virtual void li(int i) {
1767            oad(0xb8, i); /* mov $xx, %eax */
1768            setR0Type(mkpInt);
1769        }
1770
1771        virtual void loadFloat(int address, Type* pType) {
1772            setR0Type(pType);
1773            switch (pType->tag) {
1774            case TY_FLOAT:
1775                oad(0x05D9, address);      // flds
1776                break;
1777            case TY_DOUBLE:
1778                oad(0x05DD, address);      // fldl
1779                break;
1780            default:
1781                assert(false);
1782                break;
1783            }
1784        }
1785
1786        virtual int gjmp(int t) {
1787            return psym(0xe9, t);
1788        }
1789
1790        /* l = 0: je, l == 1: jne */
1791        virtual int gtst(bool l, int t) {
1792            Type* pR0Type = getR0Type();
1793            TypeTag tagR0 = pR0Type->tag;
1794            bool isFloatR0 = isFloatTag(tagR0);
1795            if (isFloatR0) {
1796                o(0xeed9); // fldz
1797                o(0xe9da); // fucompp
1798                o(0xe0df); // fnstsw %ax
1799                o(0x9e);   // sahf
1800            } else {
1801                o(0xc085); // test %eax, %eax
1802            }
1803            // Use two output statements to generate one instruction.
1804            o(0x0f);   // je/jne xxx
1805            return psym(0x84 + l, t);
1806        }
1807
1808        virtual void gcmp(int op) {
1809            Type* pR0Type = getR0Type();
1810            Type* pTOSType = getTOSType();
1811            TypeTag tagR0 = pR0Type->tag;
1812            TypeTag tagTOS = pTOSType->tag;
1813            bool isFloatR0 = isFloatTag(tagR0);
1814            bool isFloatTOS = isFloatTag(tagTOS);
1815            if (!isFloatR0 && !isFloatTOS) {
1816                int t = decodeOp(op);
1817                o(0x59); /* pop %ecx */
1818                o(0xc139); /* cmp %eax,%ecx */
1819                li(0);
1820                o(0x0f); /* setxx %al */
1821                o(t + 0x90);
1822                o(0xc0);
1823                popType();
1824            } else {
1825                setupFloatOperands();
1826                switch (op) {
1827                    case OP_EQUALS:
1828                        o(0xe9da);   // fucompp
1829                        o(0xe0df);   // fnstsw %ax
1830                        o(0x9e);     // sahf
1831                        o(0xc0940f); // sete %al
1832                        o(0xc29b0f); // setnp %dl
1833                        o(0xd021);   // andl %edx, %eax
1834                        break;
1835                    case OP_NOT_EQUALS:
1836                        o(0xe9da);   // fucompp
1837                        o(0xe0df);   // fnstsw %ax
1838                        o(0x9e);     // sahf
1839                        o(0xc0950f); // setne %al
1840                        o(0xc29a0f); // setp %dl
1841                        o(0xd009);   // orl %edx, %eax
1842                        break;
1843                    case OP_GREATER_EQUAL:
1844                        o(0xe9da);   // fucompp
1845                        o(0xe0df);   // fnstsw %ax
1846                        o(0x05c4f6); // testb $5, %ah
1847                        o(0xc0940f); // sete %al
1848                        break;
1849                    case OP_LESS:
1850                        o(0xc9d9);   // fxch %st(1)
1851                        o(0xe9da);   // fucompp
1852                        o(0xe0df);   // fnstsw %ax
1853                        o(0x9e);     // sahf
1854                        o(0xc0970f); // seta %al
1855                        break;
1856                    case OP_LESS_EQUAL:
1857                        o(0xc9d9);   // fxch %st(1)
1858                        o(0xe9da);   // fucompp
1859                        o(0xe0df);   // fnstsw %ax
1860                        o(0x9e);     // sahf
1861                        o(0xc0930f); // setea %al
1862                        break;
1863                    case OP_GREATER:
1864                        o(0xe9da);   // fucompp
1865                        o(0xe0df);   // fnstsw %ax
1866                        o(0x45c4f6); // testb $69, %ah
1867                        o(0xc0940f); // sete %al
1868                        break;
1869                    default:
1870                        error("Unknown comparison op");
1871                }
1872                o(0xc0b60f); // movzbl %al, %eax
1873            }
1874            setR0Type(mkpInt);
1875        }
1876
1877        virtual void genOp(int op) {
1878            Type* pR0Type = getR0Type();
1879            Type* pTOSType = getTOSType();
1880            TypeTag tagR0 = pR0Type->tag;
1881            TypeTag tagTOS = pTOSType->tag;
1882            bool isFloatR0 = isFloatTag(tagR0);
1883            bool isFloatTOS = isFloatTag(tagTOS);
1884            if (!isFloatR0 && !isFloatTOS) {
1885                bool isPtrR0 = tagR0 == TY_POINTER;
1886                bool isPtrTOS = tagTOS == TY_POINTER;
1887                if (isPtrR0 || isPtrTOS) {
1888                    if (isPtrR0 && isPtrTOS) {
1889                        if (op != OP_MINUS) {
1890                            error("Unsupported pointer-pointer operation %d.", op);
1891                        }
1892                        if (! typeEqual(pR0Type, pTOSType)) {
1893                            error("Incompatible pointer types for subtraction.");
1894                        }
1895                        o(0x59); /* pop %ecx */
1896                        o(decodeOp(op));
1897                        popType();
1898                        setR0Type(mkpInt);
1899                        int size = sizeOf(pR0Type->pHead);
1900                        if (size != 1) {
1901                            pushR0();
1902                            li(size);
1903                            // TODO: Optimize for power-of-two.
1904                            genOp(OP_DIV);
1905                        }
1906                    } else {
1907                        if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) {
1908                            error("Unsupported pointer-scalar operation %d", op);
1909                        }
1910                        Type* pPtrType = isPtrR0 ? pR0Type : pTOSType;
1911                        o(0x59); /* pop %ecx */
1912                        int size = sizeOf(pPtrType->pHead);
1913                        if (size != 1) {
1914                            // TODO: Optimize for power-of-two.
1915                            if (isPtrR0) {
1916                                oad(0xC969, size); // imull $size, %ecx
1917                            } else {
1918                                oad(0xC069, size); // mul $size, %eax
1919                            }
1920                        }
1921                        o(decodeOp(op));
1922                        popType();
1923                        setR0Type(pPtrType);
1924                    }
1925                } else {
1926                    o(0x59); /* pop %ecx */
1927                    o(decodeOp(op));
1928                    if (op == OP_MOD)
1929                        o(0x92); /* xchg %edx, %eax */
1930                    popType();
1931                }
1932            } else {
1933                Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType;
1934                setupFloatOperands();
1935                // Both float. x87 R0 == left hand, x87 R1 == right hand
1936                switch (op) {
1937                    case OP_MUL:
1938                        o(0xc9de); // fmulp
1939                        break;
1940                    case OP_DIV:
1941                        o(0xf1de); // fdivp
1942                        break;
1943                    case OP_PLUS:
1944                        o(0xc1de); // faddp
1945                        break;
1946                    case OP_MINUS:
1947                        o(0xe1de); // fsubp
1948                        break;
1949                    default:
1950                        error("Unsupported binary floating operation.");
1951                        break;
1952                }
1953                setR0Type(pResultType);
1954            }
1955        }
1956
1957        virtual void gUnaryCmp(int op) {
1958            if (op != OP_LOGICAL_NOT) {
1959                error("Unknown unary cmp %d", op);
1960            } else {
1961                Type* pR0Type = getR0Type();
1962                TypeTag tag = collapseType(pR0Type->tag);
1963                switch(tag) {
1964                    case TY_INT: {
1965                            oad(0xb9, 0); /* movl $0, %ecx */
1966                            int t = decodeOp(op);
1967                            o(0xc139); /* cmp %eax,%ecx */
1968                            li(0);
1969                            o(0x0f); /* setxx %al */
1970                            o(t + 0x90);
1971                            o(0xc0);
1972                        }
1973                        break;
1974                    case TY_FLOAT:
1975                    case TY_DOUBLE:
1976                        o(0xeed9);   // fldz
1977                        o(0xe9da);   // fucompp
1978                        o(0xe0df);   // fnstsw %ax
1979                        o(0x9e);     // sahf
1980                        o(0xc0950f); // setne %al
1981                        o(0xc29a0f); // setp %dl
1982                        o(0xd009);   // orl %edx, %eax
1983                        o(0xc0b60f); // movzbl %al, %eax
1984                        o(0x01f083); // xorl $1,  %eax
1985                        break;
1986                    default:
1987                        error("gUnaryCmp unsupported type");
1988                        break;
1989                }
1990            }
1991            setR0Type(mkpInt);
1992        }
1993
1994        virtual void genUnaryOp(int op) {
1995            Type* pR0Type = getR0Type();
1996            TypeTag tag = collapseType(pR0Type->tag);
1997            switch(tag) {
1998                case TY_INT:
1999                    oad(0xb9, 0); /* movl $0, %ecx */
2000                    o(decodeOp(op));
2001                    break;
2002                case TY_FLOAT:
2003                case TY_DOUBLE:
2004                    switch (op) {
2005                        case OP_MINUS:
2006                            o(0xe0d9);  // fchs
2007                            break;
2008                        case OP_BIT_NOT:
2009                            error("Can't apply '~' operator to a float or double.");
2010                            break;
2011                        default:
2012                            error("Unknown unary op %d\n", op);
2013                            break;
2014                        }
2015                    break;
2016                default:
2017                    error("genUnaryOp unsupported type");
2018                    break;
2019            }
2020        }
2021
2022        virtual void pushR0() {
2023            Type* pR0Type = getR0Type();
2024            TypeTag r0ct = collapseType(pR0Type->tag);
2025            switch(r0ct) {
2026                case TY_INT:
2027                    o(0x50); /* push %eax */
2028                    break;
2029                case TY_FLOAT:
2030                    o(0x50); /* push %eax */
2031                    o(0x241cd9); // fstps 0(%esp)
2032                    break;
2033                case TY_DOUBLE:
2034                    o(0x50); /* push %eax */
2035                    o(0x50); /* push %eax */
2036                    o(0x241cdd); // fstpl 0(%esp)
2037                    break;
2038                default:
2039                    error("pushR0 unsupported type %d", r0ct);
2040                    break;
2041            }
2042            pushType();
2043        }
2044
2045        virtual void over() {
2046            // We know it's only used for int-ptr ops (++/--)
2047
2048            Type* pR0Type = getR0Type();
2049            TypeTag r0ct = collapseType(pR0Type->tag);
2050
2051            Type* pTOSType = getTOSType();
2052            TypeTag tosct = collapseType(pTOSType->tag);
2053
2054            assert (r0ct == TY_INT && tosct == TY_INT);
2055
2056            o(0x59); /* pop %ecx */
2057            o(0x50); /* push %eax */
2058            o(0x51); /* push %ecx */
2059
2060            overType();
2061        }
2062
2063        virtual void popR0() {
2064            Type* pR0Type = getR0Type();
2065            TypeTag r0ct = collapseType(pR0Type->tag);
2066            switch(r0ct) {
2067                case TY_INT:
2068                    o(0x58); /* popl %eax */
2069                    break;
2070                case TY_FLOAT:
2071                    o(0x2404d9); // flds (%esp)
2072                    o(0x58); /* popl %eax */
2073                    break;
2074                case TY_DOUBLE:
2075                    o(0x2404dd); // fldl (%esp)
2076                    o(0x58); /* popl %eax */
2077                    o(0x58); /* popl %eax */
2078                    break;
2079                default:
2080                    error("popR0 unsupported type %d", r0ct);
2081                    break;
2082            }
2083            popType();
2084        }
2085
2086        virtual void storeR0ToTOS() {
2087            Type* pPointerType = getTOSType();
2088            assert(pPointerType->tag == TY_POINTER);
2089            Type* pTargetType = pPointerType->pHead;
2090            convertR0(pTargetType);
2091            o(0x59); /* pop %ecx */
2092            popType();
2093            switch (pTargetType->tag) {
2094                case TY_POINTER:
2095                case TY_INT:
2096                    o(0x0189); /* movl %eax/%al, (%ecx) */
2097                    break;
2098                case TY_CHAR:
2099                    o(0x0188); /* movl %eax/%al, (%ecx) */
2100                    break;
2101                case TY_FLOAT:
2102                    o(0x19d9); /* fstps (%ecx) */
2103                    break;
2104                case TY_DOUBLE:
2105                    o(0x19dd); /* fstpl (%ecx) */
2106                    break;
2107                default:
2108                    error("storeR0ToTOS: unsupported type %d",
2109                            pTargetType->tag);
2110                    break;
2111            }
2112        }
2113
2114        virtual void loadR0FromR0() {
2115            Type* pPointerType = getR0Type();
2116            assert(pPointerType->tag == TY_POINTER);
2117            switch (pPointerType->pHead->tag) {
2118                case TY_POINTER:
2119                case TY_INT:
2120                    o2(0x008b); /* mov (%eax), %eax */
2121                    break;
2122                case TY_CHAR:
2123                    o(0xbe0f); /* movsbl (%eax), %eax */
2124                    ob(0); /* add zero in code */
2125                    break;
2126                case TY_FLOAT:
2127                    o2(0x00d9); // flds (%eax)
2128                    break;
2129                case TY_DOUBLE:
2130                    o2(0x00dd); // fldl (%eax)
2131                    break;
2132                default:
2133                    error("loadR0FromR0: unsupported type");
2134                    break;
2135            }
2136            setR0Type(pPointerType->pHead);
2137        }
2138
2139        virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) {
2140            gmov(10, ea); /* leal EA, %eax */
2141            setR0Type(pPointerType, et);
2142        }
2143
2144        virtual int leaForward(int ea, Type* pPointerType) {
2145            oad(0xb8, ea); /* mov $xx, %eax */
2146            setR0Type(pPointerType);
2147            return getPC() - 4;
2148        }
2149
2150        virtual void convertR0(Type* pType){
2151            Type* pR0Type = getR0Type();
2152            if (pR0Type == NULL) {
2153                assert(false);
2154                setR0Type(pType);
2155                return;
2156            }
2157            if (bitsSame(pType, pR0Type)) {
2158                // do nothing special
2159            } else if (isFloatType(pType) && isFloatType(pR0Type)) {
2160                // do nothing special, both held in same register on x87.
2161            } else {
2162                TypeTag r0Tag = collapseType(pR0Type->tag);
2163                TypeTag destTag = collapseType(pType->tag);
2164                if (r0Tag == TY_INT && isFloatTag(destTag)) {
2165                    // Convert R0 from int to float
2166                    o(0x50);      // push %eax
2167                    o(0x2404DB);  // fildl 0(%esp)
2168                    o(0x58);      // pop %eax
2169                } else if (isFloatTag(r0Tag) && destTag == TY_INT) {
2170                    // Convert R0 from float to int. Complicated because
2171                    // need to save and restore the rounding mode.
2172                    o(0x50);       // push %eax
2173                    o(0x50);       // push %eax
2174                    o(0x02247cD9); // fnstcw 2(%esp)
2175                    o(0x2444b70f); // movzwl 2(%esp), %eax
2176                    o(0x02);
2177                    o(0x0cb4);     // movb $12, %ah
2178                    o(0x24048966); // movw %ax, 0(%esp)
2179                    o(0x242cd9);   // fldcw 0(%esp)
2180                    o(0x04245cdb); // fistpl 4(%esp)
2181                    o(0x02246cd9); // fldcw  2(%esp)
2182                    o(0x58); // pop %eax
2183                    o(0x58); // pop %eax
2184                } else {
2185                    error("Incompatible types old: %d new: %d",
2186                          pR0Type->tag, pType->tag);
2187                }
2188            }
2189            setR0Type(pType);
2190        }
2191
2192        virtual int beginFunctionCallArguments() {
2193            return oad(0xec81, 0); /* sub $xxx, %esp */
2194        }
2195
2196        virtual size_t storeR0ToArg(int l, Type* pArgType) {
2197            convertR0(pArgType);
2198            Type* pR0Type = getR0Type();
2199            TypeTag r0ct = collapseType(pR0Type->tag);
2200            switch(r0ct) {
2201                case TY_INT:
2202                    oad(0x248489, l); /* movl %eax, xxx(%esp) */
2203                    return 4;
2204                case TY_FLOAT:
2205                    oad(0x249CD9, l); /* fstps   xxx(%esp) */
2206                    return 4;
2207                case TY_DOUBLE:
2208                    oad(0x249CDD, l); /* fstpl   xxx(%esp) */
2209                    return 8;
2210                default:
2211                    assert(false);
2212                    return 0;
2213            }
2214        }
2215
2216        virtual void endFunctionCallArguments(Type* pDecl, int a, int l) {
2217            * (int*) a = l;
2218        }
2219
2220        virtual int callForward(int symbol, Type* pFunc) {
2221            assert(pFunc->tag == TY_FUNC);
2222            setR0Type(pFunc->pHead);
2223            return psym(0xe8, symbol); /* call xxx */
2224        }
2225
2226        virtual void callIndirect(int l, Type* pFunc) {
2227            assert(pFunc->tag == TY_FUNC);
2228            popType(); // Get rid of indirect fn pointer type
2229            setR0Type(pFunc->pHead);
2230            oad(0x2494ff, l); /* call *xxx(%esp) */
2231        }
2232
2233        virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) {
2234            assert(pDecl->tag == TY_FUNC);
2235            if (isIndirect) {
2236                l += 4;
2237            }
2238            if (l > 0) {
2239                oad(0xc481, l); /* add $xxx, %esp */
2240            }
2241        }
2242
2243        virtual int jumpOffset() {
2244            return 5;
2245        }
2246
2247        virtual int disassemble(FILE* out) {
2248            return 0;
2249        }
2250
2251        /* output a symbol and patch all calls to it */
2252        virtual void gsym(int t) {
2253            int n;
2254            int pc = getPC();
2255            while (t) {
2256                n = *(int *) t; /* next value */
2257                *(int *) t = pc - t - 4;
2258                t = n;
2259            }
2260        }
2261
2262        /* output a symbol and patch all calls to it, using absolute address */
2263        virtual void resolveForward(int t) {
2264            int n;
2265            int pc = getPC();
2266            while (t) {
2267                n = *(int *) t; /* next value */
2268                *(int *) t = pc;
2269                t = n;
2270            }
2271        }
2272
2273        virtual int finishCompile() {
2274            size_t pagesize = 4096;
2275            size_t base = (size_t) getBase() & ~ (pagesize - 1);
2276            size_t top =  ((size_t) getPC() + pagesize - 1) & ~ (pagesize - 1);
2277            int err = mprotect((void*) base, top - base, PROT_READ | PROT_WRITE | PROT_EXEC);
2278            if (err) {
2279               error("mprotect() failed: %d", errno);
2280            }
2281            return err;
2282        }
2283
2284        /**
2285         * Alignment (in bytes) for this type of data
2286         */
2287        virtual size_t alignmentOf(Type* pType){
2288            switch (pType->tag) {
2289            case TY_CHAR:
2290                return 1;
2291            default:
2292                return 4;
2293            }
2294        }
2295
2296        /**
2297         * Array element alignment (in bytes) for this type of data.
2298         */
2299        virtual size_t sizeOf(Type* pType){
2300            switch(pType->tag) {
2301                case TY_INT:
2302                    return 4;
2303                case TY_CHAR:
2304                    return 1;
2305                default:
2306                    return 0;
2307                case TY_FLOAT:
2308                    return 4;
2309                case TY_DOUBLE:
2310                    return 8;
2311                case TY_POINTER:
2312                    return 4;
2313            }
2314        }
2315
2316        virtual size_t stackAlignmentOf(Type* pType){
2317            return 4;
2318        }
2319
2320        virtual size_t stackSizeOf(Type* pType) {
2321            switch(pType->tag) {
2322                case TY_DOUBLE:
2323                    return 8;
2324                default:
2325                    return 4;
2326            }
2327        }
2328
2329    private:
2330
2331        /** Output 1 to 4 bytes.
2332         *
2333         */
2334        void o(int n) {
2335            /* cannot use unsigned, so we must do a hack */
2336            while (n && n != -1) {
2337                ob(n & 0xff);
2338                n = n >> 8;
2339            }
2340        }
2341
2342        /* Output exactly 2 bytes
2343         */
2344        void o2(int n) {
2345            ob(n & 0xff);
2346            ob(0xff & (n >> 8));
2347        }
2348
2349        /* psym is used to put an instruction with a data field which is a
2350         reference to a symbol. It is in fact the same as oad ! */
2351        int psym(int n, int t) {
2352            return oad(n, t);
2353        }
2354
2355        /* instruction + address */
2356        int oad(int n, int t) {
2357            o(n);
2358            int result = getPC();
2359            o4(t);
2360            return result;
2361        }
2362
2363        static const int operatorHelper[];
2364
2365        int decodeOp(int op) {
2366            if (op < 0 || op > OP_COUNT) {
2367                error("Out-of-range operator: %d\n", op);
2368                op = 0;
2369            }
2370            return operatorHelper[op];
2371        }
2372
2373        void gmov(int l, int t) {
2374            o(l + 0x83);
2375            oad((t > -LOCAL && t < LOCAL) << 7 | 5, t);
2376        }
2377
2378        void setupFloatOperands() {
2379            Type* pR0Type = getR0Type();
2380            Type* pTOSType = getTOSType();
2381            TypeTag tagR0 = pR0Type->tag;
2382            TypeTag tagTOS = pTOSType->tag;
2383            bool isFloatR0 = isFloatTag(tagR0);
2384            bool isFloatTOS = isFloatTag(tagTOS);
2385            if (! isFloatR0) {
2386                // Convert R0 from int to float
2387                o(0x50);      // push %eax
2388                o(0x2404DB);  // fildl 0(%esp)
2389                o(0x58);      // pop %eax
2390            }
2391            if (! isFloatTOS){
2392                o(0x2404DB);  // fildl 0(%esp);
2393                o(0x58);      // pop %eax
2394            } else {
2395                if (tagTOS == TY_FLOAT) {
2396                    o(0x2404d9);  // flds (%esp)
2397                    o(0x58);      // pop %eax
2398                } else {
2399                    o(0x2404dd);  // fldl (%esp)
2400                    o(0x58);      // pop %eax
2401                    o(0x58);      // pop %eax
2402                }
2403            }
2404            popType();
2405        }
2406    };
2407
2408#endif // PROVIDE_X86_CODEGEN
2409
2410#ifdef PROVIDE_TRACE_CODEGEN
2411    class TraceCodeGenerator : public CodeGenerator {
2412    private:
2413        CodeGenerator* mpBase;
2414
2415    public:
2416        TraceCodeGenerator(CodeGenerator* pBase) {
2417            mpBase = pBase;
2418        }
2419
2420        virtual ~TraceCodeGenerator() {
2421            delete mpBase;
2422        }
2423
2424        virtual void init(CodeBuf* pCodeBuf) {
2425            mpBase->init(pCodeBuf);
2426        }
2427
2428        void setErrorSink(ErrorSink* pErrorSink) {
2429            mpBase->setErrorSink(pErrorSink);
2430        }
2431
2432        /* returns address to patch with local variable size
2433        */
2434        virtual int functionEntry(Type* pDecl) {
2435            int result = mpBase->functionEntry(pDecl);
2436            fprintf(stderr, "functionEntry(pDecl) -> %d\n", result);
2437            return result;
2438        }
2439
2440        virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) {
2441            fprintf(stderr, "functionExit(pDecl, %d, %d)\n",
2442                    localVariableAddress, localVariableSize);
2443            mpBase->functionExit(pDecl, localVariableAddress, localVariableSize);
2444        }
2445
2446        /* load immediate value */
2447        virtual void li(int t) {
2448            fprintf(stderr, "li(%d)\n", t);
2449            mpBase->li(t);
2450        }
2451
2452        virtual void loadFloat(int address, Type* pType) {
2453            fprintf(stderr, "loadFloat(%d, type=%d)\n", address, pType->tag);
2454            mpBase->loadFloat(address, pType);
2455        }
2456
2457        virtual int gjmp(int t) {
2458            int result = mpBase->gjmp(t);
2459            fprintf(stderr, "gjmp(%d) = %d\n", t, result);
2460            return result;
2461        }
2462
2463        /* l = 0: je, l == 1: jne */
2464        virtual int gtst(bool l, int t) {
2465            int result = mpBase->gtst(l, t);
2466            fprintf(stderr, "gtst(%d,%d) = %d\n", l, t, result);
2467            return result;
2468        }
2469
2470        virtual void gcmp(int op) {
2471            fprintf(stderr, "gcmp(%d)\n", op);
2472            mpBase->gcmp(op);
2473        }
2474
2475        virtual void genOp(int op) {
2476            fprintf(stderr, "genOp(%d)\n", op);
2477            mpBase->genOp(op);
2478        }
2479
2480
2481        virtual void gUnaryCmp(int op) {
2482            fprintf(stderr, "gUnaryCmp(%d)\n", op);
2483            mpBase->gUnaryCmp(op);
2484        }
2485
2486        virtual void genUnaryOp(int op) {
2487            fprintf(stderr, "genUnaryOp(%d)\n", op);
2488            mpBase->genUnaryOp(op);
2489        }
2490
2491        virtual void pushR0() {
2492            fprintf(stderr, "pushR0()\n");
2493            mpBase->pushR0();
2494        }
2495
2496        virtual void over() {
2497            fprintf(stderr, "over()\n");
2498            mpBase->over();
2499        }
2500
2501        virtual void popR0() {
2502            fprintf(stderr, "popR0()\n");
2503            mpBase->popR0();
2504        }
2505
2506        virtual void storeR0ToTOS() {
2507            fprintf(stderr, "storeR0ToTOS()\n");
2508            mpBase->storeR0ToTOS();
2509        }
2510
2511        virtual void loadR0FromR0() {
2512            fprintf(stderr, "loadR0FromR0()\n");
2513            mpBase->loadR0FromR0();
2514        }
2515
2516        virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) {
2517            fprintf(stderr, "leaR0(%d, %d, %d)\n", ea,
2518                    pPointerType->pHead->tag, et);
2519            mpBase->leaR0(ea, pPointerType, et);
2520        }
2521
2522        virtual int leaForward(int ea, Type* pPointerType) {
2523            fprintf(stderr, "leaForward(%d)\n", ea);
2524            return mpBase->leaForward(ea, pPointerType);
2525        }
2526
2527        virtual void convertR0(Type* pType){
2528            fprintf(stderr, "convertR0(pType tag=%d)\n",  pType->tag);
2529            mpBase->convertR0(pType);
2530        }
2531
2532        virtual int beginFunctionCallArguments() {
2533            int result = mpBase->beginFunctionCallArguments();
2534            fprintf(stderr, "beginFunctionCallArguments() = %d\n", result);
2535            return result;
2536        }
2537
2538        virtual size_t storeR0ToArg(int l, Type* pArgType) {
2539            fprintf(stderr, "storeR0ToArg(%d, pArgType=%d)\n", l,
2540                    pArgType->tag);
2541            return mpBase->storeR0ToArg(l, pArgType);
2542        }
2543
2544        virtual void endFunctionCallArguments(Type* pDecl, int a, int l) {
2545            fprintf(stderr, "endFunctionCallArguments(%d, %d)\n", a, l);
2546            mpBase->endFunctionCallArguments(pDecl, a, l);
2547        }
2548
2549        virtual int callForward(int symbol, Type* pFunc) {
2550            int result = mpBase->callForward(symbol, pFunc);
2551            fprintf(stderr, "callForward(%d) = %d\n", symbol, result);
2552            return result;
2553        }
2554
2555        virtual void callIndirect(int l, Type* pFunc) {
2556            fprintf(stderr, "callIndirect(%d returntype = %d)\n", l,
2557                    pFunc->pHead->tag);
2558            mpBase->callIndirect(l, pFunc);
2559        }
2560
2561        virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) {
2562            fprintf(stderr, "adjustStackAfterCall(pType, %d, %d)\n", l, isIndirect);
2563            mpBase->adjustStackAfterCall(pDecl, l, isIndirect);
2564        }
2565
2566        virtual int jumpOffset() {
2567            return mpBase->jumpOffset();
2568        }
2569
2570        virtual int disassemble(FILE* out) {
2571            return mpBase->disassemble(out);
2572        }
2573
2574        /* output a symbol and patch all calls to it */
2575        virtual void gsym(int t) {
2576            fprintf(stderr, "gsym(%d)\n", t);
2577            mpBase->gsym(t);
2578        }
2579
2580        virtual void resolveForward(int t) {
2581            mpBase->resolveForward(t);
2582        }
2583
2584        virtual int finishCompile() {
2585            int result = mpBase->finishCompile();
2586            fprintf(stderr, "finishCompile() = %d\n", result);
2587            return result;
2588        }
2589
2590        /**
2591         * Alignment (in bytes) for this type of data
2592         */
2593        virtual size_t alignmentOf(Type* pType){
2594            return mpBase->alignmentOf(pType);
2595        }
2596
2597        /**
2598         * Array element alignment (in bytes) for this type of data.
2599         */
2600        virtual size_t sizeOf(Type* pType){
2601            return mpBase->sizeOf(pType);
2602        }
2603
2604
2605        virtual size_t stackAlignmentOf(Type* pType) {
2606            return mpBase->stackAlignmentOf(pType);
2607        }
2608
2609
2610        virtual size_t stackSizeOf(Type* pType) {
2611            return mpBase->stackSizeOf(pType);
2612        }
2613
2614        virtual Type* getR0Type() {
2615            return mpBase->getR0Type();
2616        }
2617
2618        virtual ExpressionType getR0ExpressionType() {
2619            return mpBase->getR0ExpressionType();
2620        }
2621
2622        virtual void setR0ExpressionType(ExpressionType et) {
2623            mpBase->setR0ExpressionType(et);
2624        }
2625
2626        virtual size_t getExpressionStackDepth() {
2627            return mpBase->getExpressionStackDepth();
2628        }
2629
2630        virtual void forceR0RVal() {
2631            return mpBase->forceR0RVal();
2632        }
2633    };
2634
2635#endif // PROVIDE_TRACE_CODEGEN
2636
2637    class Arena {
2638    public:
2639        // Used to record a given allocation amount.
2640        // Used:
2641        // Mark mark = arena.mark();
2642        // ... lots of arena.allocate()
2643        // arena.free(mark);
2644
2645        struct Mark {
2646            size_t chunk;
2647            size_t offset;
2648        };
2649
2650        Arena() {
2651            mCurrentChunk = 0;
2652            Chunk start(CHUNK_SIZE);
2653            mData.push_back(start);
2654        }
2655
2656        ~Arena() {
2657            for(size_t i = 0; i < mData.size(); i++) {
2658                mData[i].free();
2659            }
2660        }
2661
2662        // Alloc using the standard alignment size safe for any variable
2663        void* alloc(size_t size) {
2664            return alloc(size, 8);
2665        }
2666
2667        Mark mark(){
2668            Mark result;
2669            result.chunk = mCurrentChunk;
2670            result.offset = mData[mCurrentChunk].mOffset;
2671            return result;
2672        }
2673
2674        void freeToMark(const Mark& mark) {
2675            mCurrentChunk = mark.chunk;
2676            mData[mCurrentChunk].mOffset = mark.offset;
2677        }
2678
2679    private:
2680        // Allocate memory aligned to a given size
2681        // and a given power-of-two-sized alignment (e.g. 1,2,4,8,...)
2682        // Memory is not zero filled.
2683
2684        void* alloc(size_t size, size_t alignment) {
2685            while (size > mData[mCurrentChunk].remainingCapacity(alignment)) {
2686                if (mCurrentChunk + 1 < mData.size()) {
2687                    mCurrentChunk++;
2688                } else {
2689                    size_t allocSize = CHUNK_SIZE;
2690                    if (allocSize < size + alignment - 1) {
2691                        allocSize = size + alignment - 1;
2692                    }
2693                    Chunk chunk(allocSize);
2694                    mData.push_back(chunk);
2695                    mCurrentChunk++;
2696                }
2697            }
2698            return mData[mCurrentChunk].allocate(size, alignment);
2699        }
2700
2701        static const size_t CHUNK_SIZE = 128*1024;
2702        // Note: this class does not deallocate its
2703        // memory when it's destroyed. It depends upon
2704        // its parent to deallocate the memory.
2705        struct Chunk {
2706            Chunk() {
2707                mpData = 0;
2708                mSize = 0;
2709                mOffset = 0;
2710            }
2711
2712            Chunk(size_t size) {
2713                mSize = size;
2714                mpData = (char*) malloc(size);
2715                mOffset = 0;
2716            }
2717
2718            ~Chunk() {
2719                // Doesn't deallocate memory.
2720            }
2721
2722            void* allocate(size_t size, size_t alignment) {
2723                size_t alignedOffset = aligned(mOffset, alignment);
2724                void* result = mpData + alignedOffset;
2725                mOffset = alignedOffset + size;
2726                return result;
2727            }
2728
2729            void free() {
2730                if (mpData) {
2731                    ::free(mpData);
2732                    mpData = 0;
2733                }
2734            }
2735
2736            size_t remainingCapacity(size_t alignment) {
2737                return aligned(mSize, alignment) - aligned(mOffset, alignment);
2738            }
2739
2740            // Assume alignment is a power of two
2741            inline size_t aligned(size_t v, size_t alignment) {
2742                size_t mask = alignment-1;
2743                return (v + mask) & ~mask;
2744            }
2745
2746            char* mpData;
2747            size_t mSize;
2748            size_t mOffset;
2749        };
2750
2751        size_t mCurrentChunk;
2752
2753        Vector<Chunk> mData;
2754    };
2755
2756    struct VariableInfo;
2757
2758    struct Token {
2759        int hash;
2760        size_t length;
2761        char* pText;
2762        tokenid_t id;
2763
2764        // Current values for the token
2765        char* mpMacroDefinition;
2766        VariableInfo* mpVariableInfo;
2767    };
2768
2769    class TokenTable {
2770    public:
2771        // Don't use 0..0xff, allows characters and operators to be tokens too.
2772
2773        static const int TOKEN_BASE = 0x100;
2774        TokenTable() {
2775            mpMap = hashmapCreate(128, hashFn, equalsFn);
2776        }
2777
2778        ~TokenTable() {
2779            hashmapFree(mpMap);
2780        }
2781
2782        void setArena(Arena* pArena) {
2783            mpArena = pArena;
2784        }
2785
2786        // Returns a token for a given string of characters.
2787        tokenid_t intern(const char* pText, size_t length) {
2788            Token probe;
2789            int hash = hashmapHash((void*) pText, length);
2790            {
2791                Token probe;
2792                probe.hash = hash;
2793                probe.length = length;
2794                probe.pText = (char*) pText;
2795                Token* pValue = (Token*) hashmapGet(mpMap, &probe);
2796                if (pValue) {
2797                    return pValue->id;
2798                }
2799            }
2800
2801            Token* pToken = (Token*) mpArena->alloc(sizeof(Token));
2802            memset(pToken, 0, sizeof(*pToken));
2803            pToken->hash = hash;
2804            pToken->length = length;
2805            pToken->pText = (char*) mpArena->alloc(length + 1);
2806            memcpy(pToken->pText, pText, length);
2807            pToken->pText[length] = 0;
2808            pToken->id = mTokens.size() + TOKEN_BASE;
2809            mTokens.push_back(pToken);
2810            hashmapPut(mpMap, pToken, pToken);
2811            return pToken->id;
2812        }
2813
2814        // Return the Token for a given tokenid.
2815        Token& operator[](tokenid_t id) {
2816            return *mTokens[id - TOKEN_BASE];
2817        }
2818
2819        inline size_t size() {
2820            return mTokens.size();
2821        }
2822
2823    private:
2824
2825        static int hashFn(void* pKey) {
2826            Token* pToken = (Token*) pKey;
2827            return pToken->hash;
2828        }
2829
2830        static bool equalsFn(void* keyA, void* keyB) {
2831            Token* pTokenA = (Token*) keyA;
2832            Token* pTokenB = (Token*) keyB;
2833            // Don't need to compare hash values, they should always be equal
2834            return pTokenA->length == pTokenB->length
2835                && strcmp(pTokenA->pText, pTokenB->pText) == 0;
2836        }
2837
2838        Hashmap* mpMap;
2839        Vector<Token*> mTokens;
2840        Arena* mpArena;
2841    };
2842
2843    class InputStream {
2844    public:
2845        virtual ~InputStream() {}
2846        virtual int getChar() = 0;
2847    };
2848
2849    class TextInputStream : public InputStream {
2850    public:
2851        TextInputStream(const char* text, size_t textLength)
2852            : pText(text), mTextLength(textLength), mPosition(0) {
2853        }
2854
2855        virtual int getChar() {
2856            return mPosition < mTextLength ? pText[mPosition++] : EOF;
2857        }
2858
2859    private:
2860        const char* pText;
2861        size_t mTextLength;
2862        size_t mPosition;
2863    };
2864
2865    class String {
2866    public:
2867        String() {
2868            mpBase = 0;
2869            mUsed = 0;
2870            mSize = 0;
2871        }
2872
2873        String(const char* item, int len, bool adopt) {
2874            if (len < 0) {
2875                len = strlen(item);
2876            }
2877            if (adopt) {
2878                mpBase = (char*) item;
2879                mUsed = len;
2880                mSize = len + 1;
2881            } else {
2882                mpBase = 0;
2883                mUsed = 0;
2884                mSize = 0;
2885                appendBytes(item, len);
2886            }
2887        }
2888
2889        String(const String& other) {
2890            mpBase = 0;
2891            mUsed = 0;
2892            mSize = 0;
2893            appendBytes(other.getUnwrapped(), other.len());
2894        }
2895
2896        ~String() {
2897            if (mpBase) {
2898                free(mpBase);
2899            }
2900        }
2901
2902        String& operator=(const String& other) {
2903            clear();
2904            appendBytes(other.getUnwrapped(), other.len());
2905            return *this;
2906        }
2907
2908        inline char* getUnwrapped() const {
2909            return mpBase;
2910        }
2911
2912        void clear() {
2913            mUsed = 0;
2914            if (mSize > 0) {
2915                mpBase[0] = 0;
2916            }
2917        }
2918
2919        void appendCStr(const char* s) {
2920            appendBytes(s, strlen(s));
2921        }
2922
2923        void appendBytes(const char* s, int n) {
2924            memcpy(ensure(n), s, n + 1);
2925        }
2926
2927        void append(char c) {
2928            * ensure(1) = c;
2929        }
2930
2931        void append(String& other) {
2932            appendBytes(other.getUnwrapped(), other.len());
2933        }
2934
2935        char* orphan() {
2936            char* result = mpBase;
2937            mpBase = 0;
2938            mUsed = 0;
2939            mSize = 0;
2940            return result;
2941        }
2942
2943        void printf(const char* fmt,...) {
2944            va_list ap;
2945            va_start(ap, fmt);
2946            vprintf(fmt, ap);
2947            va_end(ap);
2948        }
2949
2950        void vprintf(const char* fmt, va_list ap) {
2951            char* temp;
2952            int numChars = vasprintf(&temp, fmt, ap);
2953            memcpy(ensure(numChars), temp, numChars+1);
2954            free(temp);
2955        }
2956
2957        inline size_t len() const {
2958            return mUsed;
2959        }
2960
2961    private:
2962        char* ensure(int n) {
2963            size_t newUsed = mUsed + n;
2964            if (newUsed > mSize) {
2965                size_t newSize = mSize * 2 + 10;
2966                if (newSize < newUsed) {
2967                    newSize = newUsed;
2968                }
2969                mpBase = (char*) realloc(mpBase, newSize + 1);
2970                mSize = newSize;
2971            }
2972            mpBase[newUsed] = '\0';
2973            char* result = mpBase + mUsed;
2974            mUsed = newUsed;
2975            return result;
2976        }
2977
2978        char* mpBase;
2979        size_t mUsed;
2980        size_t mSize;
2981    };
2982
2983    void internKeywords() {
2984        // Note: order has to match TOK_ constants
2985        static const char* keywords[] = {
2986            "int",
2987            "char",
2988            "void",
2989            "if",
2990            "else",
2991            "while",
2992            "break",
2993            "return",
2994            "for",
2995            "auto",
2996            "case",
2997            "const",
2998            "continue",
2999            "default",
3000            "do",
3001            "double",
3002            "enum",
3003            "extern",
3004            "float",
3005            "goto",
3006            "long",
3007            "register",
3008            "short",
3009            "signed",
3010            "sizeof",
3011            "static",
3012            "struct",
3013            "switch",
3014            "typedef",
3015            "union",
3016            "unsigned",
3017            "volatile",
3018            "_Bool",
3019            "_Complex",
3020            "_Imaginary",
3021            "inline",
3022            "restrict",
3023
3024            // predefined tokens that can also be symbols start here:
3025            "pragma",
3026            "define",
3027            "line",
3028            0};
3029
3030        for(int i = 0; keywords[i]; i++) {
3031            mTokenTable.intern(keywords[i], strlen(keywords[i]));
3032        }
3033    }
3034
3035    struct InputState {
3036        InputStream* pStream;
3037        int oldCh;
3038    };
3039
3040    struct VariableInfo {
3041        void* pAddress;
3042        void* pForward; // For a forward direction, linked list of data to fix up
3043        tokenid_t tok;
3044        size_t level;
3045        VariableInfo* pOldDefinition;
3046        Type* pType;
3047    };
3048
3049    class SymbolStack {
3050    public:
3051        SymbolStack() {
3052            mpArena = 0;
3053            mpTokenTable = 0;
3054        }
3055
3056        void setArena(Arena* pArena) {
3057            mpArena = pArena;
3058        }
3059
3060        void setTokenTable(TokenTable* pTokenTable) {
3061            mpTokenTable = pTokenTable;
3062        }
3063
3064        void pushLevel() {
3065            Mark mark;
3066            mark.mArenaMark = mpArena->mark();
3067            mark.mSymbolHead = mStack.size();
3068            mLevelStack.push_back(mark);
3069        }
3070
3071        void popLevel() {
3072            // Undo any shadowing that was done:
3073            Mark mark = mLevelStack.back();
3074            mLevelStack.pop_back();
3075            while (mStack.size() > mark.mSymbolHead) {
3076                VariableInfo* pV = mStack.back();
3077                mStack.pop_back();
3078                (*mpTokenTable)[pV->tok].mpVariableInfo = pV->pOldDefinition;
3079            }
3080            mpArena->freeToMark(mark.mArenaMark);
3081        }
3082
3083        bool isDefinedAtCurrentLevel(tokenid_t tok) {
3084            VariableInfo* pV = (*mpTokenTable)[tok].mpVariableInfo;
3085            return pV && pV->level == level();
3086        }
3087
3088        VariableInfo* add(tokenid_t tok) {
3089            Token& token = (*mpTokenTable)[tok];
3090            VariableInfo* pOldV = token.mpVariableInfo;
3091            VariableInfo* pNewV =
3092                (VariableInfo*) mpArena->alloc(sizeof(VariableInfo));
3093            memset(pNewV, 0, sizeof(VariableInfo));
3094            pNewV->tok = tok;
3095            pNewV->level = level();
3096            pNewV->pOldDefinition = pOldV;
3097            token.mpVariableInfo = pNewV;
3098            mStack.push_back(pNewV);
3099            return pNewV;
3100        }
3101
3102        VariableInfo* add(Type* pType) {
3103            VariableInfo* pVI = add(pType->id);
3104            pVI->pType = pType;
3105            return pVI;
3106        }
3107
3108        void forEach(bool (*fn)(VariableInfo*, void*), void* context) {
3109            for (size_t i = 0; i < mStack.size(); i++) {
3110                if (! fn(mStack[i], context)) {
3111                    break;
3112                }
3113            }
3114        }
3115
3116    private:
3117        inline size_t level() {
3118            return mLevelStack.size();
3119        }
3120
3121        struct Mark {
3122            Arena::Mark mArenaMark;
3123            size_t mSymbolHead;
3124        };
3125
3126        Arena* mpArena;
3127        TokenTable* mpTokenTable;
3128        Vector<VariableInfo*> mStack;
3129        Vector<Mark> mLevelStack;
3130    };
3131
3132    int ch; // Current input character, or EOF
3133    tokenid_t tok;      // token
3134    intptr_t tokc;    // token extra info
3135    double tokd;     // floating point constant value
3136    int tokl;         // token operator level
3137    intptr_t rsym; // return symbol
3138    Type* pReturnType; // type of the current function's return.
3139    intptr_t loc; // local variable index
3140    char* glo;  // global variable index
3141    String mTokenString;
3142    char* dptr; // Macro state: Points to macro text during macro playback.
3143    int dch;    // Macro state: Saves old value of ch during a macro playback.
3144    char* pGlobalBase;
3145    ACCSymbolLookupFn mpSymbolLookupFn;
3146    void* mpSymbolLookupContext;
3147
3148    // Arena for the duration of the compile
3149    Arena mGlobalArena;
3150    // Arena for data that's only needed when compiling a single function
3151    Arena mLocalArena;
3152
3153    Arena* mpCurrentArena;
3154
3155    TokenTable mTokenTable;
3156    SymbolStack mGlobals;
3157    SymbolStack mLocals;
3158
3159    // Prebuilt types, makes things slightly faster.
3160    Type* mkpInt;        // int
3161    Type* mkpChar;       // char
3162    Type* mkpVoid;       // void
3163    Type* mkpFloat;
3164    Type* mkpDouble;
3165    Type* mkpIntFn;
3166    Type* mkpIntPtr;
3167    Type* mkpCharPtr;
3168    Type* mkpFloatPtr;
3169    Type* mkpDoublePtr;
3170    Type* mkpPtrIntFn;
3171
3172    InputStream* file;
3173    int mLineNumber;
3174    bool mbBumpLine;
3175
3176    CodeBuf codeBuf;
3177    CodeGenerator* pGen;
3178
3179    String mErrorBuf;
3180
3181    String mPragmas;
3182    int mPragmaStringCount;
3183    int mCompileResult;
3184
3185    static const int ALLOC_SIZE = 99999;
3186
3187    static const int TOK_DUMMY = 1;
3188    static const int TOK_NUM = 2;
3189    static const int TOK_NUM_FLOAT = 3;
3190    static const int TOK_NUM_DOUBLE = 4;
3191    static const int TOK_OP_ASSIGNMENT = 5;
3192
3193    // 3..255 are character and/or operators
3194
3195    // Keywords start at 0x100 and increase by 1
3196    // Order has to match string list in "internKeywords".
3197    enum {
3198        TOK_KEYWORD = TokenTable::TOKEN_BASE,
3199        TOK_INT = TOK_KEYWORD,
3200        TOK_CHAR,
3201        TOK_VOID,
3202        TOK_IF,
3203        TOK_ELSE,
3204        TOK_WHILE,
3205        TOK_BREAK,
3206        TOK_RETURN,
3207        TOK_FOR,
3208        TOK_AUTO,
3209        TOK_CASE,
3210        TOK_CONST,
3211        TOK_CONTINUE,
3212        TOK_DEFAULT,
3213        TOK_DO,
3214        TOK_DOUBLE,
3215        TOK_ENUM,
3216        TOK_EXTERN,
3217        TOK_FLOAT,
3218        TOK_GOTO,
3219        TOK_LONG,
3220        TOK_REGISTER,
3221        TOK_SHORT,
3222        TOK_SIGNED,
3223        TOK_SIZEOF,
3224        TOK_STATIC,
3225        TOK_STRUCT,
3226        TOK_SWITCH,
3227        TOK_TYPEDEF,
3228        TOK_UNION,
3229        TOK_UNSIGNED,
3230        TOK_VOLATILE,
3231        TOK__BOOL,
3232        TOK__COMPLEX,
3233        TOK__IMAGINARY,
3234        TOK_INLINE,
3235        TOK_RESTRICT,
3236
3237        // Symbols start after keywords
3238
3239        TOK_SYMBOL,
3240        TOK_PRAGMA = TOK_SYMBOL,
3241        TOK_DEFINE,
3242        TOK_LINE
3243    };
3244
3245    static const int LOCAL = 0x200;
3246
3247    static const int SYM_FORWARD = 0;
3248    static const int SYM_DEFINE = 1;
3249
3250    /* tokens in string heap */
3251    static const int TAG_TOK = ' ';
3252
3253    static const int OP_INCREMENT = 0;
3254    static const int OP_DECREMENT = 1;
3255    static const int OP_MUL = 2;
3256    static const int OP_DIV = 3;
3257    static const int OP_MOD = 4;
3258    static const int OP_PLUS = 5;
3259    static const int OP_MINUS = 6;
3260    static const int OP_SHIFT_LEFT = 7;
3261    static const int OP_SHIFT_RIGHT = 8;
3262    static const int OP_LESS_EQUAL = 9;
3263    static const int OP_GREATER_EQUAL = 10;
3264    static const int OP_LESS = 11;
3265    static const int OP_GREATER = 12;
3266    static const int OP_EQUALS = 13;
3267    static const int OP_NOT_EQUALS = 14;
3268    static const int OP_LOGICAL_AND = 15;
3269    static const int OP_LOGICAL_OR = 16;
3270    static const int OP_BIT_AND = 17;
3271    static const int OP_BIT_XOR = 18;
3272    static const int OP_BIT_OR = 19;
3273    static const int OP_BIT_NOT = 20;
3274    static const int OP_LOGICAL_NOT = 21;
3275    static const int OP_COUNT = 22;
3276
3277    /* Operators are searched from front, the two-character operators appear
3278     * before the single-character operators with the same first character.
3279     * @ is used to pad out single-character operators.
3280     */
3281    static const char* operatorChars;
3282    static const char operatorLevel[];
3283
3284    /* Called when we detect an internal problem. Does nothing in production.
3285     *
3286     */
3287    void internalError() {
3288        * (char*) 0 = 0;
3289    }
3290
3291    void assert(bool isTrue) {
3292        if (!isTrue) {
3293            internalError();
3294        }
3295    }
3296
3297    bool isSymbol(tokenid_t t) {
3298        return t >= TOK_SYMBOL &&
3299            ((size_t) (t-TOK_SYMBOL)) < mTokenTable.size();
3300    }
3301
3302    bool isSymbolOrKeyword(tokenid_t t) {
3303        return t >= TOK_KEYWORD &&
3304            ((size_t) (t-TOK_KEYWORD)) < mTokenTable.size();
3305    }
3306
3307    VariableInfo* VI(tokenid_t t) {
3308        assert(isSymbol(t));
3309        VariableInfo* pV = mTokenTable[t].mpVariableInfo;
3310        if (pV && pV->tok != t) {
3311            internalError();
3312        }
3313        return pV;
3314    }
3315
3316    inline bool isDefined(tokenid_t t) {
3317        return t >= TOK_SYMBOL && VI(t) != 0;
3318    }
3319
3320    const char* nameof(tokenid_t t) {
3321        assert(isSymbolOrKeyword(t));
3322        return mTokenTable[t].pText;
3323    }
3324
3325    void pdef(int t) {
3326        mTokenString.append(t);
3327    }
3328
3329    void inp() {
3330        if (dptr) {
3331            ch = *dptr++;
3332            if (ch == 0) {
3333                dptr = 0;
3334                ch = dch;
3335            }
3336        } else {
3337            if (mbBumpLine) {
3338                mLineNumber++;
3339                mbBumpLine = false;
3340            }
3341            ch = file->getChar();
3342            if (ch == '\n') {
3343                mbBumpLine = true;
3344            }
3345        }
3346#if 0
3347        printf("ch='%c' 0x%x\n", ch, ch);
3348#endif
3349    }
3350
3351    int isid() {
3352        return isalnum(ch) | (ch == '_');
3353    }
3354
3355    int decodeHex(int c) {
3356        if (isdigit(c)) {
3357            c -= '0';
3358        } else if (c <= 'F') {
3359            c = c - 'A' + 10;
3360        } else {
3361            c =c - 'a' + 10;
3362        }
3363        return c;
3364    }
3365
3366    /* read a character constant, advances ch to after end of constant */
3367    int getq() {
3368        int val = ch;
3369        if (ch == '\\') {
3370            inp();
3371            if (isoctal(ch)) {
3372                // 1 to 3 octal characters.
3373                val = 0;
3374                for(int i = 0; i < 3; i++) {
3375                    if (isoctal(ch)) {
3376                        val = (val << 3) + ch - '0';
3377                        inp();
3378                    }
3379                }
3380                return val;
3381            } else if (ch == 'x' || ch == 'X') {
3382                // N hex chars
3383                inp();
3384                if (! isxdigit(ch)) {
3385                    error("'x' character escape requires at least one digit.");
3386                } else {
3387                    val = 0;
3388                    while (isxdigit(ch)) {
3389                        val = (val << 4) + decodeHex(ch);
3390                        inp();
3391                    }
3392                }
3393            } else {
3394                int val = ch;
3395                switch (ch) {
3396                    case 'a':
3397                        val = '\a';
3398                        break;
3399                    case 'b':
3400                        val = '\b';
3401                        break;
3402                    case 'f':
3403                        val = '\f';
3404                        break;
3405                    case 'n':
3406                        val = '\n';
3407                        break;
3408                    case 'r':
3409                        val = '\r';
3410                        break;
3411                    case 't':
3412                        val = '\t';
3413                        break;
3414                    case 'v':
3415                        val = '\v';
3416                        break;
3417                    case '\\':
3418                        val = '\\';
3419                        break;
3420                    case '\'':
3421                        val = '\'';
3422                        break;
3423                    case '"':
3424                        val = '"';
3425                        break;
3426                    case '?':
3427                        val = '?';
3428                        break;
3429                    default:
3430                        error("Undefined character escape %c", ch);
3431                        break;
3432                }
3433                inp();
3434                return val;
3435            }
3436        } else {
3437            inp();
3438        }
3439        return val;
3440    }
3441
3442    static bool isoctal(int ch) {
3443        return ch >= '0' && ch <= '7';
3444    }
3445
3446    bool acceptCh(int c) {
3447        bool result = c == ch;
3448        if (result) {
3449            pdef(ch);
3450            inp();
3451        }
3452        return result;
3453    }
3454
3455    bool acceptDigitsCh() {
3456        bool result = false;
3457        while (isdigit(ch)) {
3458            result = true;
3459            pdef(ch);
3460            inp();
3461        }
3462        return result;
3463    }
3464
3465    void parseFloat() {
3466        tok = TOK_NUM_DOUBLE;
3467        // mTokenString already has the integral part of the number.
3468        if(mTokenString.len() == 0) {
3469            mTokenString.append('0');
3470        }
3471        acceptCh('.');
3472        acceptDigitsCh();
3473        if (acceptCh('e') || acceptCh('E')) {
3474            acceptCh('-') || acceptCh('+');
3475            acceptDigitsCh();
3476        }
3477        if (ch == 'f' || ch == 'F') {
3478            tok = TOK_NUM_FLOAT;
3479            inp();
3480        } else if (ch == 'l' || ch == 'L') {
3481            inp();
3482            error("Long floating point constants not supported.");
3483        }
3484        char* pText = mTokenString.getUnwrapped();
3485        char* pEnd = pText + strlen(pText);
3486        char* pEndPtr = 0;
3487        errno = 0;
3488        if (tok == TOK_NUM_FLOAT) {
3489            tokd = strtof(pText, &pEndPtr);
3490        } else {
3491            tokd = strtod(pText, &pEndPtr);
3492        }
3493        if (errno || pEndPtr != pEnd) {
3494            error("Can't parse constant: %s", pText);
3495        }
3496        // fprintf(stderr, "float constant: %s (%d) %g\n", pText, tok, tokd);
3497    }
3498
3499    void next() {
3500        int l, a;
3501
3502        while (isspace(ch) | (ch == '#')) {
3503            if (ch == '#') {
3504                inp();
3505                next();
3506                if (tok == TOK_DEFINE) {
3507                    doDefine();
3508                } else if (tok == TOK_PRAGMA) {
3509                    doPragma();
3510                } else if (tok == TOK_LINE) {
3511                    doLine();
3512                } else {
3513                    error("Unsupported preprocessor directive \"%s\"",
3514                          mTokenString.getUnwrapped());
3515                }
3516            }
3517            inp();
3518        }
3519        tokl = 0;
3520        tok = ch;
3521        /* encode identifiers & numbers */
3522        if (isdigit(ch) || ch == '.') {
3523            // Start of a numeric constant. Could be integer, float, or
3524            // double, won't know until we look further.
3525            mTokenString.clear();
3526            pdef(ch);
3527            inp();
3528            int base = 10;
3529            if (tok == '0') {
3530                if (ch == 'x' || ch == 'X') {
3531                    base = 16;
3532                    tok = TOK_NUM;
3533                    tokc = 0;
3534                    inp();
3535                    while ( isxdigit(ch) ) {
3536                        tokc = (tokc << 4) + decodeHex(ch);
3537                        inp();
3538                    }
3539                } else if (isoctal(ch)){
3540                    base = 8;
3541                    tok = TOK_NUM;
3542                    tokc = 0;
3543                    while ( isoctal(ch) ) {
3544                        tokc = (tokc << 3) + (ch - '0');
3545                        inp();
3546                    }
3547                }
3548            } else if (isdigit(tok)){
3549                acceptDigitsCh();
3550            }
3551            if (base == 10) {
3552                if (tok == '.' || ch == '.' || ch == 'e' || ch == 'E') {
3553                    parseFloat();
3554                } else {
3555                    // It's an integer constant
3556                    char* pText = mTokenString.getUnwrapped();
3557                    char* pEnd = pText + strlen(pText);
3558                    char* pEndPtr = 0;
3559                    errno = 0;
3560                    tokc = strtol(pText, &pEndPtr, base);
3561                    if (errno || pEndPtr != pEnd) {
3562                        error("Can't parse constant: %s %d %d", pText, base, errno);
3563                    }
3564                    tok = TOK_NUM;
3565                }
3566            }
3567        } else if (isid()) {
3568            mTokenString.clear();
3569            while (isid()) {
3570                pdef(ch);
3571                inp();
3572            }
3573            tok = mTokenTable.intern(mTokenString.getUnwrapped(), mTokenString.len());
3574            // Is this a macro?
3575            char* pMacroDefinition = mTokenTable[tok].mpMacroDefinition;
3576            if (pMacroDefinition) {
3577                // Yes, it is a macro
3578                dptr = pMacroDefinition;
3579                dch = ch;
3580                inp();
3581                next();
3582            }
3583        } else {
3584            inp();
3585            if (tok == '\'') {
3586                tok = TOK_NUM;
3587                tokc = getq();
3588                if (ch != '\'') {
3589                    error("Expected a ' character, got %c", ch);
3590                } else {
3591                  inp();
3592                }
3593            } else if ((tok == '/') & (ch == '*')) {
3594                inp();
3595                while (ch && ch != EOF) {
3596                    while (ch != '*' && ch != EOF)
3597                        inp();
3598                    inp();
3599                    if (ch == '/')
3600                        ch = 0;
3601                }
3602                if (ch == EOF) {
3603                    error("End of file inside comment.");
3604                }
3605                inp();
3606                next();
3607            } else if ((tok == '/') & (ch == '/')) {
3608                inp();
3609                while (ch && (ch != '\n') && (ch != EOF)) {
3610                    inp();
3611                }
3612                inp();
3613                next();
3614            } else {
3615                const char* t = operatorChars;
3616                int opIndex = 0;
3617                while ((l = *t++) != 0) {
3618                    a = *t++;
3619                    tokl = operatorLevel[opIndex];
3620                    tokc = opIndex;
3621                    if ((l == tok) & ((a == ch) | (a == '@'))) {
3622#if 0
3623                        printf("%c%c -> tokl=%d tokc=0x%x\n",
3624                                l, a, tokl, tokc);
3625#endif
3626                        if (a == ch) {
3627                            inp();
3628                            tok = TOK_DUMMY; /* dummy token for double tokens */
3629                        }
3630                        /* check for op=, valid for * / % + - << >> & ^ | */
3631                        if (ch == '=' &&
3632                                ((tokl >= 1 && tokl <= 3)
3633                                        || (tokl >=6 && tokl <= 8)) ) {
3634                            inp();
3635                            tok = TOK_OP_ASSIGNMENT;
3636                        }
3637                        break;
3638                    }
3639                    opIndex++;
3640                }
3641                if (l == 0) {
3642                    tokl = 0;
3643                    tokc = 0;
3644                }
3645            }
3646        }
3647#if 0
3648        {
3649            String buf;
3650            decodeToken(buf, tok, true);
3651            fprintf(stderr, "%s\n", buf.getUnwrapped());
3652        }
3653#endif
3654    }
3655
3656    void doDefine() {
3657        next();
3658        tokenid_t name = tok;
3659        String* pName = new String();
3660        while (isspace(ch)) {
3661            inp();
3662        }
3663        if (ch == '(') {
3664            delete pName;
3665            error("Defines with arguments not supported");
3666            return;
3667        }
3668        while (isspace(ch)) {
3669            inp();
3670        }
3671        String value;
3672        while (ch != '\n' && ch != EOF) {
3673            value.append(ch);
3674            inp();
3675        }
3676        char* pDefn = (char*)mGlobalArena.alloc(value.len() + 1);
3677        memcpy(pDefn, value.getUnwrapped(), value.len());
3678        pDefn[value.len()] = 0;
3679        mTokenTable[name].mpMacroDefinition = pDefn;
3680    }
3681
3682    void doPragma() {
3683        // # pragma name(val)
3684        int state = 0;
3685        while(ch != EOF && ch != '\n' && state < 10) {
3686            switch(state) {
3687                case 0:
3688                    if (isspace(ch)) {
3689                        inp();
3690                    } else {
3691                        state++;
3692                    }
3693                    break;
3694                case 1:
3695                    if (isalnum(ch)) {
3696                        mPragmas.append(ch);
3697                        inp();
3698                    } else if (ch == '(') {
3699                        mPragmas.append(0);
3700                        inp();
3701                        state++;
3702                    } else {
3703                        state = 11;
3704                    }
3705                    break;
3706                case 2:
3707                    if (isalnum(ch)) {
3708                        mPragmas.append(ch);
3709                        inp();
3710                    } else if (ch == ')') {
3711                        mPragmas.append(0);
3712                        inp();
3713                        state = 10;
3714                    } else {
3715                        state = 11;
3716                    }
3717                    break;
3718            }
3719        }
3720        if(state != 10) {
3721            error("Unexpected pragma syntax");
3722        }
3723        mPragmaStringCount += 2;
3724    }
3725
3726    void doLine() {
3727        // # line number { "filename "}
3728        next();
3729        if (tok != TOK_NUM) {
3730            error("Expected a line-number");
3731        } else {
3732            mLineNumber = tokc-1; // The end-of-line will increment it.
3733        }
3734        while(ch != EOF && ch != '\n') {
3735            inp();
3736        }
3737    }
3738
3739    virtual void verror(const char* fmt, va_list ap) {
3740        mErrorBuf.printf("%ld: ", mLineNumber);
3741        mErrorBuf.vprintf(fmt, ap);
3742        mErrorBuf.printf("\n");
3743    }
3744
3745    void skip(intptr_t c) {
3746        if (tok != c) {
3747            error("'%c' expected", c);
3748        }
3749        next();
3750    }
3751
3752    bool accept(intptr_t c) {
3753        if (tok == c) {
3754            next();
3755            return true;
3756        }
3757        return false;
3758    }
3759
3760    bool acceptStringLiteral() {
3761        if (tok == '"') {
3762            pGen->leaR0((int) glo, mkpCharPtr, ET_RVALUE);
3763            // This while loop merges multiple adjacent string constants.
3764            while (tok == '"') {
3765                while (ch != '"' && ch != EOF) {
3766                    *allocGlobalSpace(1,1) = getq();
3767                }
3768                if (ch != '"') {
3769                    error("Unterminated string constant.");
3770                }
3771                inp();
3772                next();
3773            }
3774            /* Null terminate */
3775            *glo = 0;
3776            /* align heap */
3777            allocGlobalSpace(1,(char*) (((intptr_t) glo + 4) & -4) - glo);
3778
3779            return true;
3780        }
3781        return false;
3782    }
3783
3784    void linkGlobal(tokenid_t t, bool isFunction) {
3785        VariableInfo* pVI = VI(t);
3786        void* n = NULL;
3787        if (mpSymbolLookupFn) {
3788            n = mpSymbolLookupFn(mpSymbolLookupContext, nameof(t));
3789        }
3790        if (pVI->pType == NULL) {
3791            if (isFunction) {
3792                pVI->pType = mkpIntFn;
3793            } else {
3794                pVI->pType = mkpInt;
3795            }
3796        }
3797        pVI->pAddress = n;
3798    }
3799
3800    void unaryOrAssignment() {
3801        unary();
3802        if (accept('=')) {
3803            checkLVal();
3804            pGen->pushR0();
3805            expr();
3806            pGen->forceR0RVal();
3807            pGen->storeR0ToTOS();
3808        } else if (tok == TOK_OP_ASSIGNMENT) {
3809            int t = tokc;
3810            next();
3811            checkLVal();
3812            pGen->pushR0();
3813            pGen->forceR0RVal();
3814            pGen->pushR0();
3815            expr();
3816            pGen->forceR0RVal();
3817            pGen->genOp(t);
3818            pGen->storeR0ToTOS();
3819        }
3820    }
3821
3822    /* Parse and evaluate a unary expression.
3823     */
3824    void unary() {
3825        tokenid_t t;
3826        intptr_t a;
3827        t = 0;
3828        if (acceptStringLiteral()) {
3829            // Nothing else to do.
3830        } else {
3831            int c = tokl;
3832            a = tokc;
3833            double ad = tokd;
3834            t = tok;
3835            next();
3836            if (t == TOK_NUM) {
3837                pGen->li(a);
3838            } else if (t == TOK_NUM_FLOAT) {
3839                // Align to 4-byte boundary
3840                glo = (char*) (((intptr_t) glo + 3) & -4);
3841                * (float*) glo = (float) ad;
3842                pGen->loadFloat((int) glo, mkpFloat);
3843                glo += 4;
3844            } else if (t == TOK_NUM_DOUBLE) {
3845                // Align to 8-byte boundary
3846                glo = (char*) (((intptr_t) glo + 7) & -8);
3847                * (double*) glo = ad;
3848                pGen->loadFloat((int) glo, mkpDouble);
3849                glo += 8;
3850            } else if (c == 2) {
3851                /* -, +, !, ~ */
3852                unary();
3853                pGen->forceR0RVal();
3854                if (t == '!')
3855                    pGen->gUnaryCmp(a);
3856                else if (t == '+') {
3857                    // ignore unary plus.
3858                } else {
3859                    pGen->genUnaryOp(a);
3860                }
3861            } else if (c == 11) {
3862                // pre increment / pre decrement
3863                unary();
3864                doIncDec(a == OP_INCREMENT, 0);
3865            }
3866            else if (t == '(') {
3867                // It's either a cast or an expression
3868                Type* pCast = acceptCastTypeDeclaration();
3869                if (pCast) {
3870                    skip(')');
3871                    unary();
3872                    pGen->forceR0RVal();
3873                    pGen->convertR0(pCast);
3874                } else {
3875                    commaExpr();
3876                    skip(')');
3877                }
3878            } else if (t == '*') {
3879                /* This is a pointer dereference.
3880                 */
3881                unary();
3882                doPointer();
3883            } else if (t == '&') {
3884                VariableInfo* pVI = VI(tok);
3885                pGen->leaR0((int) pVI->pAddress, createPtrType(pVI->pType),
3886                        ET_RVALUE);
3887                next();
3888            } else if (t == EOF ) {
3889                error("Unexpected EOF.");
3890            } else if (t == ';') {
3891                error("Unexpected ';'");
3892            } else if (!checkSymbol(t)) {
3893                // Don't have to do anything special here, the error
3894                // message was printed by checkSymbol() above.
3895            } else {
3896                if (!isDefined(t)) {
3897                    mGlobals.add(t);
3898                    // printf("Adding new global function %s\n", nameof(t));
3899                }
3900                VariableInfo* pVI = VI(t);
3901                int n = (intptr_t) pVI->pAddress;
3902                /* forward reference: try our lookup function */
3903                if (!n) {
3904                    linkGlobal(t, tok == '(');
3905                    n = (intptr_t) pVI->pAddress;
3906                    if (!n && tok != '(') {
3907                        error("Undeclared variable %s\n", nameof(t));
3908                    }
3909                }
3910                if (tok != '(') {
3911                    /* variable or function name */
3912                    if (!n) {
3913                        linkGlobal(t, false);
3914                        n = (intptr_t) pVI->pAddress;
3915                        if (!n) {
3916                            error("Undeclared variable %s\n", nameof(t));
3917                        }
3918                    }
3919                }
3920                // load a variable
3921                Type* pVal = createPtrType(pVI->pType);
3922                if (n) {
3923                    ExpressionType et = ET_LVALUE;
3924                    if (pVal->pHead->tag == TY_FUNC) {
3925                        et = ET_RVALUE;
3926                    }
3927                    pGen->leaR0(n, pVal, et);
3928                } else {
3929                    pVI->pForward = (void*) pGen->leaForward(
3930                            (int) pVI->pForward, pVal);
3931                }
3932            }
3933        }
3934
3935        /* Now handle postfix operators */
3936        for(;;) {
3937            if (tokl == 11) {
3938                // post inc / post dec
3939                doIncDec(tokc == OP_INCREMENT, true);
3940                next();
3941            } else if (accept('[')) {
3942                // Array reference
3943                pGen->forceR0RVal();
3944                pGen->pushR0();
3945                commaExpr();
3946                pGen->forceR0RVal();
3947                pGen->genOp(OP_PLUS);
3948                doPointer();
3949                skip(']');
3950            } else  if (accept('(')) {
3951                /* function call */
3952                Type* pDecl = NULL;
3953                VariableInfo* pVI = NULL;
3954                Type* pFn = pGen->getR0Type();
3955                assert(pFn->tag == TY_POINTER);
3956                assert(pFn->pHead->tag == TY_FUNC);
3957                pDecl = pFn->pHead;
3958                pGen->pushR0();
3959                Type* pArgList = pDecl->pTail;
3960                bool varArgs = pArgList == NULL;
3961                /* push args and invert order */
3962                a = pGen->beginFunctionCallArguments();
3963                int l = 0;
3964                int argCount = 0;
3965                while (tok != ')' && tok != EOF) {
3966                    if (! varArgs && !pArgList) {
3967                        error("Unexpected argument.");
3968                    }
3969                    expr();
3970                    pGen->forceR0RVal();
3971                    Type* pTargetType;
3972                    if (pArgList) {
3973                        pTargetType = pArgList->pHead;
3974                        pArgList = pArgList->pTail;
3975                    } else {
3976                        // This is a ... function, just pass arguments in their
3977                        // natural type.
3978                        pTargetType = pGen->getR0Type();
3979                        if (pTargetType->tag == TY_FLOAT) {
3980                            pTargetType = mkpDouble;
3981                        }
3982                    }
3983                    if (pTargetType->tag == TY_VOID) {
3984                        error("Can't pass void value for argument %d",
3985                              argCount + 1);
3986                    } else {
3987                        l += pGen->storeR0ToArg(l, pTargetType);
3988                    }
3989                    if (accept(',')) {
3990                        // fine
3991                    } else if ( tok != ')') {
3992                        error("Expected ',' or ')'");
3993                    }
3994                    argCount += 1;
3995                }
3996                if (! varArgs && pArgList) {
3997                    error("Expected more argument(s). Saw %d", argCount);
3998                }
3999                pGen->endFunctionCallArguments(pDecl, a, l);
4000                skip(')');
4001                pGen->callIndirect(l, pDecl);
4002                pGen->adjustStackAfterCall(pDecl, l, true);
4003            } else {
4004                break;
4005            }
4006        }
4007    }
4008
4009    void doIncDec(int isInc, int isPost) {
4010        // R0 already has the lval
4011        checkLVal();
4012        int lit = isInc ? 1 : -1;
4013        pGen->pushR0();
4014        pGen->loadR0FromR0();
4015        int tag = pGen->getR0Type()->tag;
4016        if (!(tag == TY_INT || tag == TY_CHAR || tag == TY_POINTER)) {
4017            error("++/-- illegal for this type. %d", tag);
4018        }
4019        if (isPost) {
4020            pGen->over();
4021            pGen->pushR0();
4022            pGen->li(lit);
4023            pGen->genOp(OP_PLUS);
4024            pGen->storeR0ToTOS();
4025            pGen->popR0();
4026        } else {
4027            pGen->pushR0();
4028            pGen->li(lit);
4029            pGen->genOp(OP_PLUS);
4030            pGen->over();
4031            pGen->storeR0ToTOS();
4032            pGen->popR0();
4033        }
4034    }
4035
4036    void doPointer() {
4037        pGen->forceR0RVal();
4038        Type* pR0Type = pGen->getR0Type();
4039        if (pR0Type->tag != TY_POINTER) {
4040            error("Expected a pointer type.");
4041        } else {
4042            if (pR0Type->pHead->tag != TY_FUNC) {
4043                pGen->setR0ExpressionType(ET_LVALUE);
4044            }
4045        }
4046    }
4047
4048    /* Recursive descent parser for binary operations.
4049     */
4050    void binaryOp(int level) {
4051        intptr_t t, a;
4052        t = 0;
4053        if (level-- == 1)
4054            unaryOrAssignment();
4055        else {
4056            binaryOp(level);
4057            a = 0;
4058            while (level == tokl) {
4059                t = tokc;
4060                next();
4061                pGen->forceR0RVal();
4062                if (level > 8) {
4063                    a = pGen->gtst(t == OP_LOGICAL_OR, a); /* && and || output code generation */
4064                    binaryOp(level);
4065                } else {
4066                    pGen->pushR0();
4067                    binaryOp(level);
4068                    // Check for syntax error.
4069                    if (pGen->getR0Type() == NULL) {
4070                        // We failed to parse a right-hand argument.
4071                        // Push a dummy value so we don't fail
4072                        pGen->li(0);
4073                    }
4074                    pGen->forceR0RVal();
4075                    if ((level == 4) | (level == 5)) {
4076                        pGen->gcmp(t);
4077                    } else {
4078                        pGen->genOp(t);
4079                    }
4080                }
4081            }
4082            /* && and || output code generation */
4083            if (a && level > 8) {
4084                pGen->forceR0RVal();
4085                a = pGen->gtst(t == OP_LOGICAL_OR, a);
4086                pGen->li(t != OP_LOGICAL_OR);
4087                int b = pGen->gjmp(0);
4088                pGen->gsym(a);
4089                pGen->li(t == OP_LOGICAL_OR);
4090                pGen->gsym(b);
4091            }
4092        }
4093    }
4094
4095    void commaExpr() {
4096        for(;;) {
4097            expr();
4098            if (!accept(',')) {
4099                break;
4100            }
4101        }
4102    }
4103
4104    void expr() {
4105        binaryOp(11);
4106    }
4107
4108    int test_expr() {
4109        commaExpr();
4110        pGen->forceR0RVal();
4111        return pGen->gtst(0, 0);
4112    }
4113
4114    void block(intptr_t l, bool outermostFunctionBlock) {
4115        intptr_t a, n, t;
4116
4117        Type* pBaseType;
4118        if ((pBaseType = acceptPrimitiveType())) {
4119            /* declarations */
4120            localDeclarations(pBaseType);
4121        } else if (tok == TOK_IF) {
4122            next();
4123            skip('(');
4124            a = test_expr();
4125            skip(')');
4126            block(l, false);
4127            if (tok == TOK_ELSE) {
4128                next();
4129                n = pGen->gjmp(0); /* jmp */
4130                pGen->gsym(a);
4131                block(l, false);
4132                pGen->gsym(n); /* patch else jmp */
4133            } else {
4134                pGen->gsym(a); /* patch if test */
4135            }
4136        } else if ((tok == TOK_WHILE) | (tok == TOK_FOR)) {
4137            t = tok;
4138            next();
4139            skip('(');
4140            if (t == TOK_WHILE) {
4141                n = codeBuf.getPC(); // top of loop, target of "next" iteration
4142                a = test_expr();
4143            } else {
4144                if (tok != ';')
4145                    commaExpr();
4146                skip(';');
4147                n = codeBuf.getPC();
4148                a = 0;
4149                if (tok != ';')
4150                    a = test_expr();
4151                skip(';');
4152                if (tok != ')') {
4153                    t = pGen->gjmp(0);
4154                    commaExpr();
4155                    pGen->gjmp(n - codeBuf.getPC() - pGen->jumpOffset());
4156                    pGen->gsym(t);
4157                    n = t + 4;
4158                }
4159            }
4160            skip(')');
4161            block((intptr_t) &a, false);
4162            pGen->gjmp(n - codeBuf.getPC() - pGen->jumpOffset()); /* jmp */
4163            pGen->gsym(a);
4164        } else if (tok == '{') {
4165            if (! outermostFunctionBlock) {
4166                mLocals.pushLevel();
4167            }
4168            next();
4169            while (tok != '}' && tok != EOF)
4170                block(l, false);
4171            skip('}');
4172            if (! outermostFunctionBlock) {
4173                mLocals.popLevel();
4174            }
4175        } else {
4176            if (accept(TOK_RETURN)) {
4177                if (tok != ';') {
4178                    commaExpr();
4179                    pGen->forceR0RVal();
4180                    if (pReturnType->tag == TY_VOID) {
4181                        error("Must not return a value from a void function");
4182                    } else {
4183                        pGen->convertR0(pReturnType);
4184                    }
4185                } else {
4186                    if (pReturnType->tag != TY_VOID) {
4187                        error("Must specify a value here");
4188                    }
4189                }
4190                rsym = pGen->gjmp(rsym); /* jmp */
4191            } else if (accept(TOK_BREAK)) {
4192                *(int *) l = pGen->gjmp(*(int *) l);
4193            } else if (tok != ';')
4194                commaExpr();
4195            skip(';');
4196        }
4197    }
4198
4199    static bool typeEqual(Type* a, Type* b) {
4200        if (a == b) {
4201            return true;
4202        }
4203        if (a == NULL || b == NULL) {
4204            return false;
4205        }
4206        TypeTag at = a->tag;
4207        if (at != b->tag) {
4208            return false;
4209        }
4210        if (at == TY_POINTER) {
4211            return typeEqual(a->pHead, b->pHead);
4212        } else if (at == TY_FUNC || at == TY_PARAM) {
4213            return typeEqual(a->pHead, b->pHead)
4214                && typeEqual(a->pTail, b->pTail);
4215        }
4216        return true;
4217    }
4218
4219    Type* createType(TypeTag tag, Type* pHead, Type* pTail) {
4220        assert(tag >= TY_INT && tag <= TY_PARAM);
4221        Type* pType = (Type*) mpCurrentArena->alloc(sizeof(Type));
4222        memset(pType, 0, sizeof(*pType));
4223        pType->tag = tag;
4224        pType->pHead = pHead;
4225        pType->pTail = pTail;
4226        return pType;
4227    }
4228
4229    Type* createPtrType(Type* pType) {
4230        return createType(TY_POINTER, pType, NULL);
4231    }
4232
4233    /**
4234     * Try to print a type in declaration order
4235     */
4236    void decodeType(String& buffer, Type* pType) {
4237        buffer.clear();
4238        if (pType == NULL) {
4239            buffer.appendCStr("null");
4240            return;
4241        }
4242        decodeTypeImp(buffer, pType);
4243    }
4244
4245    void decodeTypeImp(String& buffer, Type* pType) {
4246        decodeTypeImpPrefix(buffer, pType);
4247
4248        String temp;
4249        if (pType->id != 0) {
4250            decodeToken(temp, pType->id, false);
4251            buffer.append(temp);
4252        }
4253
4254        decodeTypeImpPostfix(buffer, pType);
4255    }
4256
4257    void decodeTypeImpPrefix(String& buffer, Type* pType) {
4258        TypeTag tag = pType->tag;
4259
4260        if (tag >= TY_INT && tag <= TY_DOUBLE) {
4261            switch (tag) {
4262                case TY_INT:
4263                    buffer.appendCStr("int");
4264                    break;
4265                case TY_CHAR:
4266                    buffer.appendCStr("char");
4267                    break;
4268                case TY_VOID:
4269                    buffer.appendCStr("void");
4270                    break;
4271                case TY_FLOAT:
4272                    buffer.appendCStr("float");
4273                    break;
4274                case TY_DOUBLE:
4275                    buffer.appendCStr("double");
4276                    break;
4277                default:
4278                    break;
4279            }
4280            buffer.append(' ');
4281        }
4282
4283        switch (tag) {
4284            case TY_INT:
4285                break;
4286            case TY_CHAR:
4287                break;
4288            case TY_VOID:
4289                 break;
4290            case TY_FLOAT:
4291                 break;
4292            case TY_DOUBLE:
4293                break;
4294            case TY_POINTER:
4295                decodeTypeImpPrefix(buffer, pType->pHead);
4296                if(pType->pHead && pType->pHead->tag == TY_FUNC) {
4297                    buffer.append('(');
4298                }
4299                buffer.append('*');
4300                break;
4301            case TY_FUNC:
4302                decodeTypeImp(buffer, pType->pHead);
4303                break;
4304            case TY_PARAM:
4305                decodeTypeImp(buffer, pType->pHead);
4306                break;
4307            default:
4308                String temp;
4309                temp.printf("Unknown tag %d", pType->tag);
4310                buffer.append(temp);
4311                break;
4312        }
4313    }
4314
4315    void decodeTypeImpPostfix(String& buffer, Type* pType) {
4316        TypeTag tag = pType->tag;
4317
4318        switch(tag) {
4319            case TY_POINTER:
4320                if(pType->pHead && pType->pHead->tag == TY_FUNC) {
4321                    buffer.append(')');
4322                }
4323                decodeTypeImpPostfix(buffer, pType->pHead);
4324                break;
4325            case TY_FUNC:
4326                buffer.append('(');
4327                for(Type* pArg = pType->pTail; pArg; pArg = pArg->pTail) {
4328                    decodeTypeImp(buffer, pArg);
4329                    if (pArg->pTail) {
4330                        buffer.appendCStr(", ");
4331                    }
4332                }
4333                buffer.append(')');
4334                break;
4335            default:
4336                break;
4337        }
4338    }
4339
4340    void printType(Type* pType) {
4341        String buffer;
4342        decodeType(buffer, pType);
4343        fprintf(stderr, "%s\n", buffer.getUnwrapped());
4344    }
4345
4346    Type* acceptPrimitiveType() {
4347        Type* pType;
4348        if (tok == TOK_INT) {
4349            pType = mkpInt;
4350        } else if (tok == TOK_CHAR) {
4351            pType = mkpChar;
4352        } else if (tok == TOK_VOID) {
4353            pType = mkpVoid;
4354        } else if (tok == TOK_FLOAT) {
4355            pType = mkpFloat;
4356        } else if (tok == TOK_DOUBLE) {
4357            pType = mkpDouble;
4358        } else {
4359            return NULL;
4360        }
4361        next();
4362        return pType;
4363    }
4364
4365    Type* acceptDeclaration(Type* pType, bool nameAllowed, bool nameRequired) {
4366        tokenid_t declName = 0;
4367        bool reportFailure = false;
4368        pType = acceptDecl2(pType, declName, nameAllowed,
4369                                  nameRequired, reportFailure);
4370        if (declName) {
4371            // Clone the parent type so we can set a unique ID
4372            pType = createType(pType->tag, pType->pHead, pType->pTail);
4373
4374            pType->id = declName;
4375        }
4376        // fprintf(stderr, "Parsed a declaration:       ");
4377        // printType(pType);
4378        if (reportFailure) {
4379            return NULL;
4380        }
4381        return pType;
4382    }
4383
4384    Type* expectDeclaration(Type* pBaseType) {
4385        Type* pType = acceptDeclaration(pBaseType, true, true);
4386        if (! pType) {
4387            error("Expected a declaration");
4388        }
4389        return pType;
4390    }
4391
4392    /* Used for accepting types that appear in casts */
4393    Type* acceptCastTypeDeclaration() {
4394        Type* pType = acceptPrimitiveType();
4395        if (pType) {
4396            pType = acceptDeclaration(pType, false, false);
4397        }
4398        return pType;
4399    }
4400
4401    Type* expectCastTypeDeclaration() {
4402        Type* pType = acceptCastTypeDeclaration();
4403        if (! pType) {
4404            error("Expected a declaration");
4405        }
4406        return pType;
4407    }
4408
4409    Type* acceptDecl2(Type* pType, tokenid_t& declName,
4410                      bool nameAllowed, bool nameRequired,
4411                      bool& reportFailure) {
4412        while (accept('*')) {
4413            pType = createType(TY_POINTER, pType, NULL);
4414        }
4415        pType = acceptDecl3(pType, declName, nameAllowed, nameRequired,
4416                            reportFailure);
4417        return pType;
4418    }
4419
4420    Type* acceptDecl3(Type* pType, tokenid_t& declName,
4421                      bool nameAllowed, bool nameRequired,
4422                      bool& reportFailure) {
4423        // direct-dcl :
4424        //   name
4425        //  (dcl)
4426        //   direct-dcl()
4427        //   direct-dcl[]
4428        Type* pNewHead = NULL;
4429        if (accept('(')) {
4430            pNewHead = acceptDecl2(pNewHead, declName, nameAllowed,
4431                                nameRequired, reportFailure);
4432            skip(')');
4433        } else if ((declName = acceptSymbol()) != 0) {
4434            if (nameAllowed == false && declName) {
4435                error("Symbol %s not allowed here", nameof(declName));
4436                reportFailure = true;
4437            }
4438        } else if (nameRequired && ! declName) {
4439            String temp;
4440            decodeToken(temp, tok, true);
4441            error("Expected name. Got %s", temp.getUnwrapped());
4442            reportFailure = true;
4443        }
4444        while (accept('(')) {
4445            // Function declaration
4446            Type* pTail = acceptArgs(nameAllowed);
4447            pType = createType(TY_FUNC, pType, pTail);
4448            skip(')');
4449        }
4450
4451        if (pNewHead) {
4452            Type* pA = pNewHead;
4453            while (pA->pHead) {
4454                pA = pA->pHead;
4455            }
4456            pA->pHead = pType;
4457            pType = pNewHead;
4458        }
4459        return pType;
4460    }
4461
4462    Type* acceptArgs(bool nameAllowed) {
4463        Type* pHead = NULL;
4464        Type* pTail = NULL;
4465        for(;;) {
4466            Type* pBaseArg = acceptPrimitiveType();
4467            if (pBaseArg) {
4468                Type* pArg = acceptDeclaration(pBaseArg, nameAllowed, false);
4469                if (pArg) {
4470                    Type* pParam = createType(TY_PARAM, pArg, NULL);
4471                    if (!pHead) {
4472                        pHead = pParam;
4473                        pTail = pParam;
4474                    } else {
4475                        pTail->pTail = pParam;
4476                        pTail = pParam;
4477                    }
4478                }
4479            }
4480            if (! accept(',')) {
4481                break;
4482            }
4483        }
4484        return pHead;
4485    }
4486
4487    Type* expectPrimitiveType() {
4488        Type* pType = acceptPrimitiveType();
4489        if (!pType) {
4490            String buf;
4491            decodeToken(buf, tok, true);
4492            error("Expected a type, got %s", buf.getUnwrapped());
4493        }
4494        return pType;
4495    }
4496
4497    void checkLVal() {
4498        if (pGen->getR0ExpressionType() != ET_LVALUE) {
4499            error("Expected an lval");
4500        }
4501    }
4502
4503    void addGlobalSymbol(Type* pDecl) {
4504        tokenid_t t = pDecl->id;
4505        VariableInfo* pVI = VI(t);
4506        if(pVI && pVI->pAddress) {
4507            reportDuplicate(t);
4508        }
4509        mGlobals.add(pDecl);
4510    }
4511
4512    void reportDuplicate(tokenid_t t) {
4513        error("Duplicate definition of %s", nameof(t));
4514    }
4515
4516    void addLocalSymbol(Type* pDecl) {
4517        tokenid_t t = pDecl->id;
4518        if (mLocals.isDefinedAtCurrentLevel(t)) {
4519            reportDuplicate(t);
4520        }
4521        mLocals.add(pDecl);
4522    }
4523
4524    void localDeclarations(Type* pBaseType) {
4525        intptr_t a;
4526
4527        while (pBaseType) {
4528            while (tok != ';' && tok != EOF) {
4529                Type* pDecl = expectDeclaration(pBaseType);
4530                if (!pDecl) {
4531                    break;
4532                }
4533                int variableAddress = 0;
4534                addLocalSymbol(pDecl);
4535                size_t alignment = pGen->stackAlignmentOf(pDecl);
4536                size_t alignmentMask = ~ (alignment - 1);
4537                size_t sizeOf = pGen->sizeOf(pDecl);
4538                loc = (loc + alignment - 1) & alignmentMask;
4539                size_t alignedSize = (sizeOf + alignment - 1) & alignmentMask;
4540                loc = loc + alignedSize;
4541                variableAddress = -loc;
4542                VI(pDecl->id)->pAddress = (void*) variableAddress;
4543                if (accept('=')) {
4544                    /* assignment */
4545                    pGen->leaR0(variableAddress, createPtrType(pDecl), ET_LVALUE);
4546                    pGen->pushR0();
4547                    expr();
4548                    pGen->forceR0RVal();
4549                    pGen->storeR0ToTOS();
4550                }
4551                if (tok == ',')
4552                    next();
4553            }
4554            skip(';');
4555            pBaseType = acceptPrimitiveType();
4556        }
4557    }
4558
4559    bool checkSymbol() {
4560        return checkSymbol(tok);
4561    }
4562
4563    void decodeToken(String& buffer, tokenid_t token, bool quote) {
4564        if (token == EOF ) {
4565            buffer.printf("EOF");
4566        } else if (token == TOK_NUM) {
4567            buffer.printf("numeric constant");
4568        } else if (token >= 0 && token < 256) {
4569            if (token < 32) {
4570                buffer.printf("'\\x%02x'", token);
4571            } else {
4572                buffer.printf("'%c'", token);
4573            }
4574        } else {
4575            if (quote) {
4576                if (token >= TOK_KEYWORD && token < TOK_SYMBOL) {
4577                    buffer.printf("keyword \"%s\"", nameof(token));
4578                } else {
4579                    buffer.printf("symbol \"%s\"", nameof(token));
4580                }
4581            } else {
4582                buffer.printf("%s", nameof(token));
4583            }
4584        }
4585    }
4586
4587    bool checkSymbol(tokenid_t token) {
4588        bool result = token >= TOK_SYMBOL;
4589        if (!result) {
4590            String temp;
4591            decodeToken(temp, token, true);
4592            error("Expected symbol. Got %s", temp.getUnwrapped());
4593        }
4594        return result;
4595    }
4596
4597    tokenid_t acceptSymbol() {
4598        tokenid_t result = 0;
4599        if (tok >= TOK_SYMBOL) {
4600            result = tok;
4601            next();
4602        }
4603        return result;
4604    }
4605
4606    void globalDeclarations() {
4607        while (tok != EOF) {
4608            Type* pBaseType = expectPrimitiveType();
4609            if (!pBaseType) {
4610                break;
4611            }
4612            Type* pDecl = expectDeclaration(pBaseType);
4613            if (!pDecl) {
4614                break;
4615            }
4616            if (! isDefined(pDecl->id)) {
4617                addGlobalSymbol(pDecl);
4618            }
4619            VariableInfo* name = VI(pDecl->id);
4620            if (name && name->pAddress) {
4621                error("Already defined global %s", nameof(pDecl->id));
4622            }
4623            if (pDecl->tag < TY_FUNC) {
4624                // it's a variable declaration
4625                for(;;) {
4626                    if (name && !name->pAddress) {
4627                        name->pAddress = (int*) allocGlobalSpace(
4628                                                   pGen->alignmentOf(name->pType),
4629                                                   pGen->sizeOf(name->pType));
4630                    }
4631                    if (accept('=')) {
4632                        if (tok == TOK_NUM) {
4633                            if (name) {
4634                                * (int*) name->pAddress = tokc;
4635                            }
4636                            next();
4637                        } else {
4638                            error("Expected an integer constant");
4639                        }
4640                    }
4641                    if (!accept(',')) {
4642                        break;
4643                    }
4644                    pDecl = expectDeclaration(pBaseType);
4645                    if (!pDecl) {
4646                        break;
4647                    }
4648                    if (! isDefined(pDecl->id)) {
4649                        addGlobalSymbol(pDecl);
4650                    }
4651                    name = VI(pDecl->id);
4652                }
4653                skip(';');
4654            } else {
4655                // Function declaration
4656                if (accept(';')) {
4657                    // forward declaration.
4658                } else if (tok != '{') {
4659                    error("expected '{'");
4660                } else {
4661                    mpCurrentArena = &mLocalArena;
4662                    if (name) {
4663                        /* patch forward references */
4664                        pGen->resolveForward((int) name->pForward);
4665                        /* put function address */
4666                        name->pAddress = (void*) codeBuf.getPC();
4667                    }
4668                    // Calculate stack offsets for parameters
4669                    mLocals.pushLevel();
4670                    intptr_t a = 8;
4671                    int argCount = 0;
4672                    for (Type* pP = pDecl->pTail; pP; pP = pP->pTail) {
4673                        Type* pArg = pP->pHead;
4674                        addLocalSymbol(pArg);
4675                        /* read param name and compute offset */
4676                        size_t alignment = pGen->stackAlignmentOf(pArg);
4677                        a = (a + alignment - 1) & ~ (alignment-1);
4678                        VI(pArg->id)->pAddress = (void*) a;
4679                        a = a + pGen->stackSizeOf(pArg);
4680                        argCount++;
4681                    }
4682                    rsym = loc = 0;
4683                    pReturnType = pDecl->pHead;
4684                    a = pGen->functionEntry(pDecl);
4685                    block(0, true);
4686                    pGen->gsym(rsym);
4687                    pGen->functionExit(pDecl, a, loc);
4688                    mLocals.popLevel();
4689                    mpCurrentArena = &mGlobalArena;
4690                }
4691            }
4692        }
4693    }
4694
4695    char* allocGlobalSpace(size_t alignment, size_t bytes) {
4696        size_t base = (((size_t) glo) + alignment - 1) & ~(alignment-1);
4697        size_t end = base + bytes;
4698        if ((end - (size_t) pGlobalBase) > (size_t) ALLOC_SIZE) {
4699            error("Global space exhausted");
4700            return NULL;
4701        }
4702        char* result = (char*) base;
4703        glo = (char*) end;
4704        return result;
4705    }
4706
4707    void cleanup() {
4708        if (pGlobalBase != 0) {
4709            free(pGlobalBase);
4710            pGlobalBase = 0;
4711        }
4712        if (pGen) {
4713            delete pGen;
4714            pGen = 0;
4715        }
4716        if (file) {
4717            delete file;
4718            file = 0;
4719        }
4720    }
4721
4722    // One-time initialization, when class is constructed.
4723    void init() {
4724        mpSymbolLookupFn = 0;
4725        mpSymbolLookupContext = 0;
4726    }
4727
4728    void clear() {
4729        tok = 0;
4730        tokc = 0;
4731        tokl = 0;
4732        ch = 0;
4733        rsym = 0;
4734        loc = 0;
4735        glo = 0;
4736        dptr = 0;
4737        dch = 0;
4738        file = 0;
4739        pGlobalBase = 0;
4740        pGen = 0;
4741        mPragmaStringCount = 0;
4742        mCompileResult = 0;
4743        mLineNumber = 1;
4744        mbBumpLine = false;
4745    }
4746
4747    void setArchitecture(const char* architecture) {
4748        delete pGen;
4749        pGen = 0;
4750
4751        if (architecture != NULL) {
4752#ifdef PROVIDE_ARM_CODEGEN
4753            if (! pGen && strcmp(architecture, "arm") == 0) {
4754                pGen = new ARMCodeGenerator();
4755            }
4756#endif
4757#ifdef PROVIDE_X86_CODEGEN
4758            if (! pGen && strcmp(architecture, "x86") == 0) {
4759                pGen = new X86CodeGenerator();
4760            }
4761#endif
4762            if (!pGen ) {
4763                error("Unknown architecture %s\n", architecture);
4764            }
4765        }
4766
4767        if (pGen == NULL) {
4768#if defined(DEFAULT_ARM_CODEGEN)
4769            pGen = new ARMCodeGenerator();
4770#elif defined(DEFAULT_X86_CODEGEN)
4771            pGen = new X86CodeGenerator();
4772#endif
4773        }
4774        if (pGen == NULL) {
4775            error("No code generator defined.");
4776        } else {
4777            pGen->setErrorSink(this);
4778            pGen->setTypes(mkpInt);
4779        }
4780    }
4781
4782public:
4783    struct args {
4784        args() {
4785            architecture = 0;
4786        }
4787        const char* architecture;
4788    };
4789
4790    Compiler() {
4791        init();
4792        clear();
4793    }
4794
4795    ~Compiler() {
4796        cleanup();
4797    }
4798
4799    void registerSymbolCallback(ACCSymbolLookupFn pFn, ACCvoid* pContext) {
4800        mpSymbolLookupFn = pFn;
4801        mpSymbolLookupContext = pContext;
4802    }
4803
4804    int compile(const char* text, size_t textLength) {
4805        int result;
4806
4807        mpCurrentArena = &mGlobalArena;
4808        createPrimitiveTypes();
4809        cleanup();
4810        clear();
4811        mTokenTable.setArena(&mGlobalArena);
4812        mGlobals.setArena(&mGlobalArena);
4813        mGlobals.setTokenTable(&mTokenTable);
4814        mLocals.setArena(&mLocalArena);
4815        mLocals.setTokenTable(&mTokenTable);
4816
4817        internKeywords();
4818        codeBuf.init(ALLOC_SIZE);
4819        setArchitecture(NULL);
4820        if (!pGen) {
4821            return -1;
4822        }
4823#ifdef PROVIDE_TRACE_CODEGEN
4824            pGen = new TraceCodeGenerator(pGen);
4825#endif
4826            pGen->setErrorSink(this);
4827        pGen->init(&codeBuf);
4828        file = new TextInputStream(text, textLength);
4829        pGlobalBase = (char*) calloc(1, ALLOC_SIZE);
4830        glo = pGlobalBase;
4831        inp();
4832        next();
4833        globalDeclarations();
4834        checkForUndefinedForwardReferences();
4835        result = pGen->finishCompile();
4836        if (result == 0) {
4837            if (mErrorBuf.len()) {
4838                result = -2;
4839            }
4840        }
4841        mCompileResult = result;
4842        return result;
4843    }
4844
4845    void createPrimitiveTypes() {
4846        mkpInt = createType(TY_INT, NULL, NULL);
4847        mkpChar = createType(TY_CHAR, NULL, NULL);
4848        mkpVoid = createType(TY_VOID, NULL, NULL);
4849        mkpFloat = createType(TY_FLOAT, NULL, NULL);
4850        mkpDouble = createType(TY_DOUBLE, NULL, NULL);
4851        mkpIntFn =  createType(TY_FUNC, mkpInt, NULL);
4852        mkpIntPtr = createPtrType(mkpInt);
4853        mkpCharPtr = createPtrType(mkpChar);
4854        mkpFloatPtr = createPtrType(mkpFloat);
4855        mkpDoublePtr = createPtrType(mkpDouble);
4856        mkpPtrIntFn = createPtrType(mkpIntFn);
4857    }
4858
4859    void checkForUndefinedForwardReferences() {
4860        mGlobals.forEach(static_ufrcFn, this);
4861    }
4862
4863    static bool static_ufrcFn(VariableInfo* value, void* context) {
4864        Compiler* pCompiler = (Compiler*) context;
4865        return pCompiler->undefinedForwardReferenceCheck(value);
4866    }
4867
4868    bool undefinedForwardReferenceCheck(VariableInfo* value) {
4869        if (!value->pAddress && value->pForward) {
4870            error("Undefined forward reference: %s",
4871                  mTokenTable[value->tok].pText);
4872        }
4873        return true;
4874    }
4875
4876    int dump(FILE* out) {
4877        fwrite(codeBuf.getBase(), 1, codeBuf.getSize(), out);
4878        return 0;
4879    }
4880
4881    int disassemble(FILE* out) {
4882        return pGen->disassemble(out);
4883    }
4884
4885    /* Look through the symbol table to find a symbol.
4886     * If found, return its value.
4887     */
4888    void* lookup(const char* name) {
4889        if (mCompileResult == 0) {
4890            tokenid_t tok = mTokenTable.intern(name, strlen(name));
4891            VariableInfo* pVariableInfo = VI(tok);
4892            if (pVariableInfo) {
4893                return pVariableInfo->pAddress;
4894            }
4895        }
4896        return NULL;
4897    }
4898
4899    void getPragmas(ACCsizei* actualStringCount,
4900                    ACCsizei maxStringCount, ACCchar** strings) {
4901        int stringCount = mPragmaStringCount;
4902        if (actualStringCount) {
4903            *actualStringCount = stringCount;
4904        }
4905        if (stringCount > maxStringCount) {
4906            stringCount = maxStringCount;
4907        }
4908        if (strings) {
4909            char* pPragmas = mPragmas.getUnwrapped();
4910            while (stringCount-- > 0) {
4911                *strings++ = pPragmas;
4912                pPragmas += strlen(pPragmas) + 1;
4913            }
4914        }
4915    }
4916
4917    char* getErrorMessage() {
4918        return mErrorBuf.getUnwrapped();
4919    }
4920
4921};
4922
4923const char* Compiler::operatorChars =
4924    "++--*@/@%@+@-@<<>><=>=<@>@==!=&&||&@^@|@~@!@";
4925
4926const char Compiler::operatorLevel[] =
4927    {11, 11, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4,
4928            5, 5, /* ==, != */
4929            9, 10, /* &&, || */
4930            6, 7, 8, /* & ^ | */
4931            2, 2 /* ~ ! */
4932            };
4933
4934#ifdef PROVIDE_ARM_CODEGEN
4935FILE* Compiler::ARMCodeGenerator::disasmOut;
4936#endif
4937
4938#ifdef PROVIDE_X86_CODEGEN
4939const int Compiler::X86CodeGenerator::operatorHelper[] = {
4940        0x1,     // ++
4941        0xff,    // --
4942        0xc1af0f, // *
4943        0xf9f79991, // /
4944        0xf9f79991, // % (With manual assist to swap results)
4945        0xc801, // +
4946        0xd8f7c829, // -
4947        0xe0d391, // <<
4948        0xf8d391, // >>
4949        0xe, // <=
4950        0xd, // >=
4951        0xc, // <
4952        0xf, // >
4953        0x4, // ==
4954        0x5, // !=
4955        0x0, // &&
4956        0x1, // ||
4957        0xc821, // &
4958        0xc831, // ^
4959        0xc809, // |
4960        0xd0f7, // ~
4961        0x4     // !
4962};
4963#endif
4964
4965struct ACCscript {
4966    ACCscript() {
4967        text = 0;
4968        textLength = 0;
4969        accError = ACC_NO_ERROR;
4970    }
4971
4972    ~ACCscript() {
4973        delete text;
4974    }
4975
4976    void registerSymbolCallback(ACCSymbolLookupFn pFn, ACCvoid* pContext) {
4977        compiler.registerSymbolCallback(pFn, pContext);
4978    }
4979
4980    void setError(ACCenum error) {
4981        if (accError == ACC_NO_ERROR && error != ACC_NO_ERROR) {
4982            accError = error;
4983        }
4984    }
4985
4986    ACCenum getError() {
4987        ACCenum result = accError;
4988        accError = ACC_NO_ERROR;
4989        return result;
4990    }
4991
4992    Compiler compiler;
4993    char* text;
4994    int textLength;
4995    ACCenum accError;
4996};
4997
4998
4999extern "C"
5000ACCscript* accCreateScript() {
5001    return new ACCscript();
5002}
5003
5004extern "C"
5005ACCenum accGetError( ACCscript* script ) {
5006    return script->getError();
5007}
5008
5009extern "C"
5010void accDeleteScript(ACCscript* script) {
5011    delete script;
5012}
5013
5014extern "C"
5015void accRegisterSymbolCallback(ACCscript* script, ACCSymbolLookupFn pFn,
5016                               ACCvoid* pContext) {
5017    script->registerSymbolCallback(pFn, pContext);
5018}
5019
5020extern "C"
5021void accScriptSource(ACCscript* script,
5022    ACCsizei count,
5023    const ACCchar ** string,
5024    const ACCint * length) {
5025    int totalLength = 0;
5026    for(int i = 0; i < count; i++) {
5027        int len = -1;
5028        const ACCchar* s = string[i];
5029        if (length) {
5030            len = length[i];
5031        }
5032        if (len < 0) {
5033            len = strlen(s);
5034        }
5035        totalLength += len;
5036    }
5037    delete script->text;
5038    char* text = new char[totalLength + 1];
5039    script->text = text;
5040    script->textLength = totalLength;
5041    char* dest = text;
5042    for(int i = 0; i < count; i++) {
5043        int len = -1;
5044        const ACCchar* s = string[i];
5045        if (length) {
5046            len = length[i];
5047        }
5048        if (len < 0) {
5049            len = strlen(s);
5050        }
5051        memcpy(dest, s, len);
5052        dest += len;
5053    }
5054    text[totalLength] = '\0';
5055}
5056
5057extern "C"
5058void accCompileScript(ACCscript* script) {
5059    int result = script->compiler.compile(script->text, script->textLength);
5060    if (result) {
5061        script->setError(ACC_INVALID_OPERATION);
5062    }
5063}
5064
5065extern "C"
5066void accGetScriptiv(ACCscript* script,
5067    ACCenum pname,
5068    ACCint * params) {
5069    switch (pname) {
5070        case ACC_INFO_LOG_LENGTH:
5071            *params = 0;
5072            break;
5073    }
5074}
5075
5076extern "C"
5077void accGetScriptInfoLog(ACCscript* script,
5078    ACCsizei maxLength,
5079    ACCsizei * length,
5080    ACCchar * infoLog) {
5081    char* message = script->compiler.getErrorMessage();
5082    int messageLength = strlen(message) + 1;
5083    if (length) {
5084        *length = messageLength;
5085    }
5086    if (infoLog && maxLength > 0) {
5087        int trimmedLength = maxLength < messageLength ?
5088                maxLength : messageLength;
5089        memcpy(infoLog, message, trimmedLength);
5090        infoLog[trimmedLength] = 0;
5091    }
5092}
5093
5094extern "C"
5095void accGetScriptLabel(ACCscript* script, const ACCchar * name,
5096                       ACCvoid ** address) {
5097    void* value = script->compiler.lookup(name);
5098    if (value) {
5099        *address = value;
5100    } else {
5101        script->setError(ACC_INVALID_VALUE);
5102    }
5103}
5104
5105extern "C"
5106void accGetPragmas(ACCscript* script, ACCsizei* actualStringCount,
5107                   ACCsizei maxStringCount, ACCchar** strings){
5108    script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
5109}
5110
5111extern "C"
5112void accDisassemble(ACCscript* script) {
5113    script->compiler.disassemble(stderr);
5114}
5115
5116
5117} // namespace acc
5118
5119