Loading libacc/acc.cpp +130 −61 Original line number Diff line number Diff line Loading @@ -37,7 +37,6 @@ #define PROVIDE_X64_CODEGEN #endif #ifdef PROVIDE_ARM_CODEGEN #include "disassem.h" #endif Loading Loading @@ -297,11 +296,8 @@ class Compiler : public ErrorSink { /* 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. Loading Loading @@ -389,8 +385,9 @@ class Compiler : public ErrorSink { 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 Loading Loading @@ -461,6 +458,10 @@ class Compiler : public ErrorSink { */ virtual size_t sizeOf(Type* type) = 0; virtual Type* getR0Type() { return mExpressionStack.back(); } protected: /* * Output a byte. Handles all values, 0..ff. Loading Loading @@ -494,6 +495,7 @@ class Compiler : public ErrorSink { void assert(bool test) { if (!test) { * (char*) 0 = 0; error("code generator assertion failed."); } } Loading @@ -502,10 +504,6 @@ class Compiler : public ErrorSink { mExpressionStack.back() = pType; } Type* getR0Type() { return mExpressionStack.back(); } Type* getTOSType() { return mExpressionStack[mExpressionStack.size()-2]; } Loading @@ -529,6 +527,15 @@ class Compiler : public ErrorSink { 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; Loading Loading @@ -613,16 +620,8 @@ class Compiler : public ErrorSink { 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); } Loading Loading @@ -843,7 +842,7 @@ class Compiler : public ErrorSink { } 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) { Loading Loading @@ -891,10 +890,16 @@ class Compiler : public ErrorSink { } 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() { Loading @@ -902,12 +907,13 @@ class Compiler : public ErrorSink { 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) { Loading Loading @@ -1169,18 +1175,19 @@ class Compiler : public ErrorSink { 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"); switch (pType->tag) { case TY_FLOAT: oad(0x05D9, address); // flds break; case TY_DOUBLE: oad(0x05DD, address); // fldl break; default: assert(false); break; } virtual void lid(double d, Type* pType) { union { double d; int i[2]; } converter; converter.d = d; setR0Type(pType); error("unimplemented: lid"); } virtual int gjmp(int t) { Loading Loading @@ -1287,19 +1294,44 @@ class Compiler : public ErrorSink { } 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) { 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) { Loading Loading @@ -1480,14 +1512,9 @@ class Compiler : public ErrorSink { 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) { Loading Loading @@ -1550,7 +1577,7 @@ class Compiler : public ErrorSink { } 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); } Loading @@ -1565,9 +1592,9 @@ class Compiler : public ErrorSink { 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) { Loading Loading @@ -1629,6 +1656,10 @@ class Compiler : public ErrorSink { virtual size_t sizeOf(Type* pType){ return mpBase->sizeOf(pType); } virtual Type* getR0Type() { return mpBase->getR0Type(); } }; #endif // PROVIDE_TRACE_CODEGEN Loading Loading @@ -2185,6 +2216,8 @@ class Compiler : public ErrorSink { Type* mkpIntFn; Type* mkpIntPtr; Type* mkpCharPtr; Type* mkpFloatPtr; Type* mkpDoublePtr; Type* mkpPtrIntFn; InputStream* file; Loading Loading @@ -2742,9 +2775,17 @@ class Compiler : public ErrorSink { 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); Loading Loading @@ -2807,7 +2848,11 @@ class Compiler : public ErrorSink { /* forward reference: try dlsym */ if (!n) { n = (intptr_t) dlsym(RTLD_DEFAULT, nameof(t)); if (tok == '(') { pVI->pType = mkpIntFn; } else { pVI->pType = mkpInt; } pVI->pAddress = (void*) n; } if ((tok == '=') & allowAssignment) { Loading @@ -2830,27 +2875,49 @@ class Compiler : public ErrorSink { /* 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) { Loading Loading @@ -3595,6 +3662,8 @@ public: 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); } Loading libacc/tests/data/float.c 0 → 100644 +6 −0 Original line number Diff line number Diff line int main() { printf("int: %d float: %g double: %g\n", 1, 2.2f, 3.3); return 42; } Loading
libacc/acc.cpp +130 −61 Original line number Diff line number Diff line Loading @@ -37,7 +37,6 @@ #define PROVIDE_X64_CODEGEN #endif #ifdef PROVIDE_ARM_CODEGEN #include "disassem.h" #endif Loading Loading @@ -297,11 +296,8 @@ class Compiler : public ErrorSink { /* 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. Loading Loading @@ -389,8 +385,9 @@ class Compiler : public ErrorSink { 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 Loading Loading @@ -461,6 +458,10 @@ class Compiler : public ErrorSink { */ virtual size_t sizeOf(Type* type) = 0; virtual Type* getR0Type() { return mExpressionStack.back(); } protected: /* * Output a byte. Handles all values, 0..ff. Loading Loading @@ -494,6 +495,7 @@ class Compiler : public ErrorSink { void assert(bool test) { if (!test) { * (char*) 0 = 0; error("code generator assertion failed."); } } Loading @@ -502,10 +504,6 @@ class Compiler : public ErrorSink { mExpressionStack.back() = pType; } Type* getR0Type() { return mExpressionStack.back(); } Type* getTOSType() { return mExpressionStack[mExpressionStack.size()-2]; } Loading @@ -529,6 +527,15 @@ class Compiler : public ErrorSink { 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; Loading Loading @@ -613,16 +620,8 @@ class Compiler : public ErrorSink { 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); } Loading Loading @@ -843,7 +842,7 @@ class Compiler : public ErrorSink { } 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) { Loading Loading @@ -891,10 +890,16 @@ class Compiler : public ErrorSink { } 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() { Loading @@ -902,12 +907,13 @@ class Compiler : public ErrorSink { 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) { Loading Loading @@ -1169,18 +1175,19 @@ class Compiler : public ErrorSink { 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"); switch (pType->tag) { case TY_FLOAT: oad(0x05D9, address); // flds break; case TY_DOUBLE: oad(0x05DD, address); // fldl break; default: assert(false); break; } virtual void lid(double d, Type* pType) { union { double d; int i[2]; } converter; converter.d = d; setR0Type(pType); error("unimplemented: lid"); } virtual int gjmp(int t) { Loading Loading @@ -1287,19 +1294,44 @@ class Compiler : public ErrorSink { } 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) { 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) { Loading Loading @@ -1480,14 +1512,9 @@ class Compiler : public ErrorSink { 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) { Loading Loading @@ -1550,7 +1577,7 @@ class Compiler : public ErrorSink { } 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); } Loading @@ -1565,9 +1592,9 @@ class Compiler : public ErrorSink { 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) { Loading Loading @@ -1629,6 +1656,10 @@ class Compiler : public ErrorSink { virtual size_t sizeOf(Type* pType){ return mpBase->sizeOf(pType); } virtual Type* getR0Type() { return mpBase->getR0Type(); } }; #endif // PROVIDE_TRACE_CODEGEN Loading Loading @@ -2185,6 +2216,8 @@ class Compiler : public ErrorSink { Type* mkpIntFn; Type* mkpIntPtr; Type* mkpCharPtr; Type* mkpFloatPtr; Type* mkpDoublePtr; Type* mkpPtrIntFn; InputStream* file; Loading Loading @@ -2742,9 +2775,17 @@ class Compiler : public ErrorSink { 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); Loading Loading @@ -2807,7 +2848,11 @@ class Compiler : public ErrorSink { /* forward reference: try dlsym */ if (!n) { n = (intptr_t) dlsym(RTLD_DEFAULT, nameof(t)); if (tok == '(') { pVI->pType = mkpIntFn; } else { pVI->pType = mkpInt; } pVI->pAddress = (void*) n; } if ((tok == '=') & allowAssignment) { Loading @@ -2830,27 +2875,49 @@ class Compiler : public ErrorSink { /* 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) { Loading Loading @@ -3595,6 +3662,8 @@ public: 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); } Loading
libacc/tests/data/float.c 0 → 100644 +6 −0 Original line number Diff line number Diff line int main() { printf("int: %d float: %g double: %g\n", 1, 2.2f, 3.3); return 42; }