Some x86 floating point code works.

We now check the types and number of arguments to a function.
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index e43728e..65b0b39 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -37,7 +37,6 @@
 #define PROVIDE_X64_CODEGEN
 #endif
 
-
 #ifdef PROVIDE_ARM_CODEGEN
 #include "disassem.h"
 #endif
@@ -297,11 +296,8 @@
         /* load immediate value to R0 */
         virtual void li(int i, Type* pType) = 0;
 
-        /* load floating point immediate value to R0 */
-        virtual void lif(float f, Type* pType) = 0;
-
-        /* load double-precision floating point immediate value to R0 */
-        virtual void lid(double d, Type* pType) = 0;
+        /* Load floating point value from global address. */
+        virtual void loadFloat(int address, Type* pType) = 0;
 
         /* Jump to a target, and return the address of the word that
          * holds the target data, in case it needs to be fixed up later.
@@ -389,8 +385,9 @@
         virtual int beginFunctionCallArguments() = 0;
 
         /* Emit code to store R0 to the stack at byte offset l.
+         * Returns stack size of object (typically 4 or 8 bytes)
          */
-        virtual void storeR0ToArg(int l) = 0;
+        virtual size_t storeR0ToArg(int l) = 0;
 
         /* Patch the function call preamble.
          * a is the address returned from beginFunctionCallArguments
@@ -461,6 +458,10 @@
          */
         virtual size_t sizeOf(Type* type) = 0;
 
+        virtual Type* getR0Type() {
+            return mExpressionStack.back();
+        }
+
     protected:
         /*
          * Output a byte. Handles all values, 0..ff.
@@ -494,6 +495,7 @@
 
         void assert(bool test) {
             if (!test) {
+                * (char*) 0 = 0;
                 error("code generator assertion failed.");
             }
         }
@@ -502,10 +504,6 @@
             mExpressionStack.back() = pType;
         }
 
-        Type* getR0Type() {
-            return mExpressionStack.back();
-        }
-
         Type* getTOSType() {
             return mExpressionStack[mExpressionStack.size()-2];
         }
@@ -529,6 +527,15 @@
             return collapsedTag[tag];
         }
 
+        TypeTag collapseTypeR0() {
+            return collapseType(getR0Type()->tag);
+        }
+
+        bool isFloatType(Type* pType) {
+            TypeTag tag = pType->tag;
+            return tag == TY_FLOAT || tag == TY_DOUBLE;
+        }
+
     private:
         Vector<Type*> mExpressionStack;
         CodeBuf* pCodeBuf;
@@ -613,16 +620,8 @@
             setR0Type(pType);
         }
 
-        virtual void lif(float f, Type* pType) {
-            union { float f; int i; } converter;
-            converter.f = f;
-            li(converter.i, pType);
-        }
-
-        virtual void lid(double d, Type* pType) {
-            union { double d; int i[2]; } converter;
-            converter.d = d;
-            error("lid: unimplemented");
+        virtual void loadFloat(int address, Type* pType) {
+            error("Unimplemented.\n");
             setR0Type(pType);
         }
 
@@ -843,7 +842,7 @@
         }
 
         virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
-            LOG_API("loadR0(%d, %d, %d);\n", ea, isIncDec, op);
+            LOG_API("loadR0(%d, %d, %d, %d);\n", ea, isIncDec, op, pType);
             if (ea < LOCAL) {
                 // Local, fp relative
                 if (ea < -4095 || ea > 4095) {
@@ -891,10 +890,16 @@
         }
 
         virtual void convertR0(Type* pType){
-            if (bitsSame(pType, getR0Type())) {
-                return;
+            Type* pR0Type = getR0Type();
+            if (bitsSame(pType, pR0Type)) {
+                // do nothing special
+            } else if (isFloatType(pType) && isFloatType(pR0Type)) {
+                // do nothing special, both held in same register on x87.
+            } else {
+                error("Incompatible types old: %d new: %d",
+                      pR0Type->tag, pType->tag);
             }
-            error("Incompatible types");
+            setR0Type(pType);
         }
 
         virtual int beginFunctionCallArguments() {
@@ -902,12 +907,13 @@
             return o4(0xE24DDF00); // Placeholder
         }
 
-        virtual void storeR0ToArg(int l) {
+        virtual size_t storeR0ToArg(int l) {
             LOG_API("storeR0ToArg(%d);\n", l);
             if (l < 0 || l > 4096-4) {
                 error("l out of range for stack offset: 0x%08x", l);
             }
             o4(0xE58D0000 + l); // str r0, [sp, #4]
+            return 4;
         }
 
         virtual void endFunctionCallArguments(int a, int l) {
@@ -1169,18 +1175,19 @@
             setR0Type(pType);
         }
 
-        virtual void lif(float f, Type* pType) {
-            union { float f; int i; } converter;
-            converter.f = f;
+        virtual void loadFloat(int address, Type* pType) {
             setR0Type(pType);
-            error("unimplemented: lif");
-        }
-
-        virtual void lid(double d, Type* pType) {
-            union { double d; int i[2]; } converter;
-            converter.d = d;
-            setR0Type(pType);
-            error("unimplemented: lid");
+            switch (pType->tag) {
+            case TY_FLOAT:
+                oad(0x05D9, address);      // flds
+                break;
+            case TY_DOUBLE:
+                oad(0x05DD, address);      // fldl
+                break;
+            default:
+                assert(false);
+                break;
+            }
         }
 
         virtual int gjmp(int t) {
@@ -1287,19 +1294,44 @@
         }
 
         virtual void convertR0(Type* pType){
-            if (bitsSame(pType, getR0Type())) {
+            Type* pR0Type = getR0Type();
+            if (pR0Type == NULL) {
+                error("don't know R0Type");
+                setR0Type(pType);
                 return;
             }
-            error("convertR0: unsupported conversion %d <- %d", pType->tag,
-                  getR0Type()->tag);
+            if (bitsSame(pType, pR0Type)) {
+                // do nothing special
+            } else if (isFloatType(pType) && isFloatType(pR0Type)) {
+                // do nothing special, both held in same register on x87.
+            } else {
+                error("Incompatible types old: %d new: %d",
+                      pR0Type->tag, pType->tag);
+            }
+            setR0Type(pType);
         }
 
         virtual int beginFunctionCallArguments() {
             return oad(0xec81, 0); /* sub $xxx, %esp */
         }
 
-        virtual void storeR0ToArg(int l) {
-            oad(0x248489, l); /* movl %eax, xxx(%esp) */
+        virtual size_t storeR0ToArg(int l) {
+            Type* pR0Type = getR0Type();
+            TypeTag r0ct = collapseType(pR0Type->tag);
+            switch(r0ct) {
+                case TY_INT:
+                    oad(0x248489, l); /* movl %eax, xxx(%esp) */
+                    return 4;
+                case TY_FLOAT:
+                    oad(0x249CD9, l); /* fstps   xxx(%esp) */
+                    return 4;
+                case TY_DOUBLE:
+                    oad(0x249CDD, l); /* fstpl   xxx(%esp) */
+                    return 8;
+                default:
+                    assert(false);
+                    return 0;
+            }
         }
 
         virtual void endFunctionCallArguments(int a, int l) {
@@ -1480,14 +1512,9 @@
             mpBase->li(t, pType);
         }
 
-        virtual void lif(float f, Type* pType) {
-            fprintf(stderr, "lif(%g)\n", f);
-            mpBase->lif(f, pType);
-        }
-
-        virtual void lid(double d, Type* pType) {
-            fprintf(stderr, "lid(%g)\n", d);
-            mpBase->lid(d, pType);
+        virtual void loadFloat(int address, Type* pType) {
+            fprintf(stderr, "loadFloat(%d, type)\n", address);
+            mpBase->loadFloat(address, pType);
         }
 
         virtual int gjmp(int t) {
@@ -1550,7 +1577,7 @@
         }
 
         virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
-            fprintf(stderr, "loadR0(%d, %d, %d)\n", ea, isIncDec, op);
+            fprintf(stderr, "loadR0(%d, %d, %d, pType)\n", ea, isIncDec, op);
             mpBase->loadR0(ea, isIncDec, op, pType);
         }
 
@@ -1565,9 +1592,9 @@
             return result;
         }
 
-        virtual void storeR0ToArg(int l) {
+        virtual size_t storeR0ToArg(int l) {
             fprintf(stderr, "storeR0ToArg(%d)\n", l);
-            mpBase->storeR0ToArg(l);
+            return mpBase->storeR0ToArg(l);
         }
 
         virtual void endFunctionCallArguments(int a, int l) {
@@ -1629,6 +1656,10 @@
         virtual size_t sizeOf(Type* pType){
             return mpBase->sizeOf(pType);
         }
+
+        virtual Type* getR0Type() {
+            return mpBase->getR0Type();
+        }
     };
 
 #endif // PROVIDE_TRACE_CODEGEN
@@ -2185,6 +2216,8 @@
     Type* mkpIntFn;
     Type* mkpIntPtr;
     Type* mkpCharPtr;
+    Type* mkpFloatPtr;
+    Type* mkpDoublePtr;
     Type* mkpPtrIntFn;
 
     InputStream* file;
@@ -2742,9 +2775,17 @@
             if (t == TOK_NUM) {
                 pGen->li(a, mkpInt);
             } else if (t == TOK_NUM_FLOAT) {
-                pGen->lif(ad, mkpFloat);
+                // Align to 4-byte boundary
+                glo = (char*) (((intptr_t) glo + 3) & -4);
+                * (float*) glo = (float) ad;
+                pGen->loadFloat((int) glo, mkpFloat);
+                glo += 4;
             } else if (t == TOK_NUM_DOUBLE) {
-                pGen->lid(ad, mkpDouble);
+                // Align to 8-byte boundary
+                glo = (char*) (((intptr_t) glo + 7) & -8);
+                * (double*) glo = ad;
+                pGen->loadFloat((int) glo, mkpDouble);
+                glo += 8;
             } else if (c == 2) {
                 /* -, +, !, ~ */
                 unary(false);
@@ -2807,7 +2848,11 @@
                 /* forward reference: try dlsym */
                 if (!n) {
                     n = (intptr_t) dlsym(RTLD_DEFAULT, nameof(t));
-                    pVI->pType = mkpIntFn;
+                    if (tok == '(') {
+                        pVI->pType = mkpIntFn;
+                    } else {
+                        pVI->pType = mkpInt;
+                    }
                     pVI->pAddress = (void*) n;
                 }
                 if ((tok == '=') & allowAssignment) {
@@ -2830,27 +2875,49 @@
 
         /* function call */
         if (accept('(')) {
-            if (n == 1)
+            Type* pArgList = NULL;
+            VariableInfo* pVI = NULL;
+            if (n == 1) { // Indirect function call, push address of fn.
+                pArgList = pGen->getR0Type()->pTail;
                 pGen->pushR0();
-
+            } else {
+                pVI = VI(t);
+                pArgList = pVI->pType->pTail;
+            }
+            bool varArgs = pArgList == NULL;
             /* push args and invert order */
             a = pGen->beginFunctionCallArguments();
             int l = 0;
             while (tok != ')' && tok != EOF) {
+                if (! varArgs && !pArgList) {
+                    error ("Unexpected argument.");
+                }
                 expr();
-                pGen->storeR0ToArg(l);
-                l = l + 4;
+                Type* pTargetType;
+                if (pArgList) {
+                    pTargetType = pArgList->pHead;
+                    pArgList = pArgList->pTail;
+                } else {
+                    pTargetType = pGen->getR0Type();
+                    if (pTargetType->tag == TY_FLOAT) {
+                        pTargetType = mkpDouble;
+                    }
+                }
+                pGen->convertR0(pTargetType);
+                l += pGen->storeR0ToArg(l);
                 if (accept(',')) {
                     // fine
                 } else if ( tok != ')') {
                     error("Expected ',' or ')'");
                 }
             }
+            if (! varArgs && pArgList) {
+                error ("Expected more argument(s).");
+            }
             pGen->endFunctionCallArguments(a, l);
             skip(')');
             if (!n) {
                 /* forward reference */
-                VariableInfo* pVI = VI(t);
                 pVI->pForward = (void*) pGen->callForward((int) pVI->pForward,
                                                           pVI->pType);
             } else if (n == 1) {
@@ -3595,6 +3662,8 @@
         mkpIntFn =  createType(TY_FUNC, mkpInt, NULL, mGlobalArena);
         mkpIntPtr = createPtrType(mkpInt, mGlobalArena);
         mkpCharPtr = createPtrType(mkpChar, mGlobalArena);
+        mkpFloatPtr = createPtrType(mkpFloat, mGlobalArena);
+        mkpDoublePtr = createPtrType(mkpDouble, mGlobalArena);
         mkpPtrIntFn = createPtrType(mkpIntFn, mGlobalArena);
     }
 
diff --git a/libacc/tests/data/float.c b/libacc/tests/data/float.c
new file mode 100644
index 0000000..5f68efc
--- /dev/null
+++ b/libacc/tests/data/float.c
@@ -0,0 +1,6 @@
+
+int main() {
+    printf("int: %d float: %g double: %g\n", 1, 2.2f, 3.3);
+
+    return 42;
+}