URI:
       cc1: Add support for c99 float arithmetic - scc - simple c99 compiler
  HTML git clone git://git.simple-cc.org/scc
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
   DIR commit c3b8a3ef1ef7df8ae85b1d0b9061725a02c356dc
   DIR parent b057d1fdf510c655916a99184421b0197c5da056
  HTML Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
       Date:   Fri, 30 Jan 2026 12:49:24 +0100
       
       cc1: Add support for c99 float arithmetic
       
       C99 allows arithmetic operations to be performed in floats, while K&R and C90
       promoted floats to double. This was the behaviour of scc until now, but this
       commit enables operations in float and also add folding of long double constants.
       
       Diffstat:
         M include/scc/bits/amd64/arch/float.h |       6 ++++++
         M include/scc/float.h                 |       6 ++++++
         M src/cmd/scc-cc/cc1/cc1.h            |       4 +++-
         M src/cmd/scc-cc/cc1/cpp.c            |       1 +
         M src/cmd/scc-cc/cc1/expr.c           |       8 +++-----
         M src/cmd/scc-cc/cc1/fold.c           |     111 +++++++++++++++++++++++++++++--
       
       6 files changed, 124 insertions(+), 12 deletions(-)
       ---
   DIR diff --git a/include/scc/bits/amd64/arch/float.h b/include/scc/bits/amd64/arch/float.h
       @@ -1,3 +1,9 @@
       +#ifdef __FLT_EVAL_METHOD__
       +#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
       +#else
       +#define FLT_EVAL_METHOD 1
       +#endif
       +
        #define FLT_RADIX      2
        #define FLT_MANT_DIG   24
        #define FLT_DIG        6
   DIR diff --git a/include/scc/float.h b/include/scc/float.h
       @@ -1,6 +1,12 @@
        #ifndef _FLOAT_H
        #define _FLOAT_H
        
       +#ifdef __FLT_EVAL_METHOD__
       +#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
       +#else
       +#define FLT_EVAL_METHOD 0
       +#endif
       +
        #include <arch/float.h>
        
        #endif
   DIR diff --git a/src/cmd/scc-cc/cc1/cc1.h b/src/cmd/scc-cc/cc1/cc1.h
       @@ -344,7 +344,9 @@ struct symbol {
                union {
                        long long i;
                        unsigned long long u;
       -                double f;
       +                float f;
       +                double d;
       +                long double ld;
                        char *s;
                        unsigned char token;
                        Node **init;
   DIR diff --git a/src/cmd/scc-cc/cc1/cpp.c b/src/cmd/scc-cc/cc1/cpp.c
       @@ -75,6 +75,7 @@ icpp(void)
                        {"__STDC_VERSION__", STDC_VERSION},
                        {"__LINE__", NULL},
                        {"__FILE__", NULL},
       +                {"__FLT_EVAL_METHOD__", 0},
                        {NULL, NULL}
                };
        
   DIR diff --git a/src/cmd/scc-cc/cc1/expr.c b/src/cmd/scc-cc/cc1/expr.c
       @@ -52,8 +52,8 @@ cmpnode(Node *np, unsigned long long val)
                        mask = (val > 1) ? ones(np->type->size) : -1;
                        nodeval = (tp->prop & TSIGNED) ? sym->u.i : sym->u.u;
                        return (nodeval & mask) == (val & mask);
       -        case FLOAT:
       -                return sym->u.f == val;
       +        default:
       +                abort();
                }
                return 0;
        }
       @@ -77,9 +77,7 @@ promote(Node *np)
                        tp = (lim->max.i <= ilim->max.i) ? inttype : uinttype;
                        break;
                case FLOAT:
       -                /* TODO: Add support for C99 float math */
       -                tp = doubletype;
       -                break;
       +                return np;
                default:
                        abort();
                }
   DIR diff --git a/src/cmd/scc-cc/cc1/fold.c b/src/cmd/scc-cc/cc1/fold.c
       @@ -236,7 +236,50 @@ sign:
        }
        
        static int
       -foldfloat(int op, Symbol *res, double l, double r)
       +foldldouble(int op, Symbol *res, long double l, long double r)
       +{
       +        long double f;
       +        long long i;
       +        int (*validate)(double, double, Type *tp);
       +
       +        switch (op) {
       +        case OADD: validate = addf; break;
       +        case OSUB: validate = subf; break;
       +        case OMUL: validate = mulf; break;
       +        case ODIV: validate = divf; break;
       +        default:   validate = NULL; break;
       +        }
       +
       +        if (validate && !(*validate)(l, r, res->type))
       +                return 0;
       +
       +        switch (op) {
       +        case OADD: f = l + r;  break;
       +        case OSUB: f = l - r;  break;
       +        case OMUL: f = l * r;  break;
       +        case ODIV: f = l / r;  break;
       +        case OLT:  i = l < r;  goto comparison;
       +        case OGT:  i = l > r;  goto comparison;
       +        case OGE:  i = l >= r; goto comparison;
       +        case OLE:  i = l <= r; goto comparison;
       +        case OEQ:  i = l == r; goto comparison;
       +        case ONE:  i = l != r; goto comparison;
       +        default:   return 0;
       +        }
       +        res->u.ld = f;
       +
       +        DBG("FOLD f l=%llf %d r=%llf = %llf", l, op, r, f);
       +        return 1;
       +
       +comparison:
       +        res->u.i = i;
       +
       +        DBG("FOLD if l=%lf %d r=%lf = %lld", l, op, r, i);
       +        return 1;
       +}
       +
       +static int
       +folddouble(int op, Symbol *res, double l, double r)
        {
                double f;
                long long i;
       @@ -266,7 +309,7 @@ foldfloat(int op, Symbol *res, double l, double r)
                case ONE:  i = l != r; goto comparison;
                default:   return 0;
                }
       -        res->u.f = f;
       +        res->u.d = f;
        
                DBG("FOLD f l=%lf %d r=%lf = %lf", l, op, r, f);
                return 1;
       @@ -278,13 +321,59 @@ comparison:
                return 1;
        }
        
       +static int
       +foldfloat(int op, Symbol *res, float l, float r)
       +{
       +        float f;
       +        long long i;
       +        int (*validate)(double, double, Type *tp);
       +
       +        switch (op) {
       +        case OADD: validate = addf; break;
       +        case OSUB: validate = subf; break;
       +        case OMUL: validate = mulf; break;
       +        case ODIV: validate = divf; break;
       +        default:   validate = NULL; break;
       +        }
       +
       +        if (validate && !(*validate)(l, r, res->type))
       +                return 0;
       +
       +        switch (op) {
       +        case OADD: f = l + r;  break;
       +        case OSUB: f = l - r;  break;
       +        case OMUL: f = l * r;  break;
       +        case ODIV: f = l / r;  break;
       +        case OLT:  i = l < r;  goto comparison;
       +        case OGT:  i = l > r;  goto comparison;
       +        case OGE:  i = l >= r; goto comparison;
       +        case OLE:  i = l <= r; goto comparison;
       +        case OEQ:  i = l == r; goto comparison;
       +        case ONE:  i = l != r; goto comparison;
       +        default:   return 0;
       +        }
       +        res->u.f = f;
       +
       +        DBG("FOLD f l=%f %d r=%f = %f", l, op, r, f);
       +        return 1;
       +
       +comparison:
       +        res->u.i = i;
       +
       +        DBG("FOLD if l=%lf %d r=%lf = %lld", l, op, r, i);
       +        return 1;
       +}
       +
       +
        static Node *
        foldconst(int type, int op, Type *tp, Symbol *ls, Symbol *rs)
        {
                Symbol *sym, aux;
                long long i;
                unsigned long long u;
       -        double f;
       +        float f;
       +        double d;
       +        long double ld;
        
                aux.type = tp;
                switch (type) {
       @@ -300,9 +389,19 @@ foldconst(int type, int op, Type *tp, Symbol *ls, Symbol *rs)
                                return NULL;
                        break;
                case FLOAT:
       -                f = (rs) ? rs->u.f : 0.0;
       -                if (!foldfloat(op, &aux, ls->u.f, f))
       -                        return NULL;
       +                if (tp == floattype) {
       +                        f = (rs) ? rs->u.f : 0.0;
       +                        if (!foldfloat(op, &aux, ls->u.f, f))
       +                                return NULL;
       +                } else if (tp == doubletype) {
       +                        d = (rs) ? rs->u.d : 0.0;
       +                        if (!folddouble(op, &aux, ls->u.d, d))
       +                                return NULL;
       +                } else {
       +                        ld = (rs) ? rs->u.ld : 0.0;
       +                        if (!foldldouble(op, &aux, ls->u.ld, ld))
       +                                return NULL;
       +                }
                        break;
                default:
                        abort();