Commits

Iain Buclaw committed 431f375

Implement math intrinsics into the compiler.

  • Participants
  • Parent commits 8f5627c

Comments (0)

Files changed (9)

File d/d-asm-i386.h

     {
         if (exp->op == TOKint64)
             return 1;
-#if 0   // %% TODO: review
+#if 0
+        /* This can't be right. A const variable does not guarentee
+           it's value is known at compile-time.
+
+           Should be instead checking fromConstInitializer?
+         */
         if (exp->op == TOKvar)
         {
             Declaration * v = ((VarExp *) exp)->var;
          */
 
         bool is_offset = false;
+        exp = exp->optimize(WANTvalue | WANTinterpret);
         if (exp->op == TOKaddress)
         {
             exp = ((AddrExp *) exp)->e1;

File d/d-builtins2.cc

         }
         case ARRAY_TYPE:
         {
-            for (unsigned i = 0; i < builtin_converted_types.dim; i += 2)
-            {
-                tree ti = (tree) builtin_converted_types.data[i];
-                if (ti == t)
-                    return (Type *) builtin_converted_types.data[i + 1];
-            }
-
             d = gcc_type_to_d_type(TREE_TYPE(t));
             if (d)
             {
                             Type::tindex));
                 d = d->semantic(0, NULL);
                 d->ctype = t;
-
-                builtin_converted_types.push(t);
-                builtin_converted_types.push(d);
                 return d;
             }
             break;
 
     Type * d = NULL;
 
-    d = gcc_type_to_d_type(va_list_type_node);
+    /* va_list should already be built, so no need to convert to D type again. */
+    d = d_gcc_builtin_va_list_d_type;
     if (d)
     {
         funcs->push(new AliasDeclaration(0,
         {
             if (! strcmp(md->id->string, "intrinsic"))
                 IRState::setIntrinsicModule(m);
+            else if (! strcmp(md->id->string, "math"))
+                IRState::setMathModule(m);
         }
 #else
         else if (! strcmp(((Identifier *) md->packages->data[0])->string, "std"))
                 d_gcc_magic_stdarg_module(m, false);
             else if (! strcmp(md->id->string, "intrinsic"))
                 IRState::setIntrinsicModule(m);
+            else if (! strcmp(md->id->string, "math"))
+                IRState::setMathModule(m);
         }
 #endif
     }

File d/d-codegen.cc

                 break;
 #endif
 
+            case INTRINSIC_COS:
+                // Math intrinsics just map to their GCC equivalents.
+                op1 = ce.nextArg();
+                return buildCall(built_in_decls[BUILT_IN_COSL], 1, op1);
+
+            case INTRINSIC_SIN:
+                op1 = ce.nextArg();
+                return buildCall(built_in_decls[BUILT_IN_SINL], 1, op1);
+
+            case INTRINSIC_RNDTOL:
+                // %% not sure if llroundl stands as a good replacement
+                // for the expected behaviour of rndtol.
+                op1 = ce.nextArg();
+                return buildCall(built_in_decls[BUILT_IN_LLROUNDL], 1, op1);
+
+            case INTRINSIC_SQRT:
+                // Have float, double and real variants of sqrt.
+                op1 = ce.nextArg();
+                exp = mathfn_built_in(TREE_TYPE(op1), BUILT_IN_SQRT);
+                gcc_assert(exp);    // Should never trigger.
+                return buildCall(exp, 1, op1);
+
+            case INTRINSIC_LDEXP:
+                op1 = ce.nextArg();
+                return buildCall(built_in_decls[BUILT_IN_LDEXPL], 1, op1);
+
+            case INTRINSIC_FABS:
+                op1 = ce.nextArg();
+                return buildCall(built_in_decls[BUILT_IN_FABSL], 1, op1);
+
+            case INTRINSIC_RINT:
+                op1 = ce.nextArg();
+                return buildCall(built_in_decls[BUILT_IN_RINTL], 1, op1);
+
+
             case INTRINSIC_C_VA_ARG:
                 // %% should_check c_promotes_to as in va_arg now
                 // just drop though for now...
 
 Module * IRState::builtinsModule = 0;
 Module * IRState::intrinsicModule = 0;
+Module * IRState::mathModule = 0;
 TemplateDeclaration * IRState::stdargTemplateDecl = 0;
 TemplateDeclaration * IRState::cstdargStartTemplateDecl = 0;
 TemplateDeclaration * IRState::cstdargArgTemplateDecl = 0;
     if (! dsym)
         return false;
 
-    if (intrinsicModule && dsym->getModule() == intrinsicModule)
+    if ((intrinsicModule && dsym->getModule() == intrinsicModule)
+        || (mathModule && dsym->getModule() == mathModule))
+
     {   // Matches order of Intrinsic enum
         static const char * intrinsic_names[] = {
             "bsf", "bsr",
             "bswap",
             "bt", "btc", "btr", "bts",
+            "cos", "ldexp",
             "inp", "inpl", "inpw",
+            "ldexp",
             "outp", "outpl", "outpw",
+            "rint", "rndtol",
+            "sin", "sqrt",
         };
         const size_t sz = sizeof(intrinsic_names) / sizeof(char *);
         int i = binary(decl->ident->string, intrinsic_names, sz);
             return false;
 
         // Make sure 'i' is within the range we require.
-        gcc_assert(i >= INTRINSIC_BSF && i <= INTRINSIC_OUTPW);
+        gcc_assert(i >= INTRINSIC_BSF && i <= INTRINSIC_SQRT);
         tree t = decl->toSymbol()->Stree;
 
         DECL_BUILT_IN_CLASS(t) = BUILT_IN_FRONTEND;

File d/d-codegen.h

 
 struct IRState : IRBase
 {
+    // %% intrinsic and math functions in alphabetical order for bsearch
     enum Intrinsic
     {
         INTRINSIC_BSF, INTRINSIC_BSR,
         INTRINSIC_BSWAP,
         INTRINSIC_BT, INTRINSIC_BTC, INTRINSIC_BTR, INTRINSIC_BTS,
+        INTRINSIC_COS, INTRINSIC_FABS,
         INTRINSIC_INP, INTRINSIC_INPL, INTRINSIC_INPW,
+        INTRINSIC_LDEXP,
         INTRINSIC_OUTP, INTRINSIC_OUTPL, INTRINSIC_OUTPW,
+        INTRINSIC_RINT, INTRINSIC_RNDTOL,
+        INTRINSIC_SIN, INTRINSIC_SQRT,
         INTRINSIC_STD_VA_ARG,
         INTRINSIC_C_VA_ARG,
         INTRINSIC_C_VA_START,
 
     static Module * builtinsModule;
     static Module * intrinsicModule;
+    static Module * mathModule;
     static TemplateDeclaration * stdargTemplateDecl;
     static TemplateDeclaration * cstdargStartTemplateDecl;
     static TemplateDeclaration * cstdargArgTemplateDecl;
         intrinsicModule = mod;
     }
 
+    static void setMathModule(Module * mod)
+    {
+        mathModule = mod;
+    }
+
     static void setStdArg(TemplateDeclaration * td)
     {
         stdargTemplateDecl = td;
     gcc_assert(g.ofile);
 
     g.ofile->beginModule(this);
+    g.ofile->setupStaticStorage(this, toSymbol()->Stree);
 
     if (members) {
         for (unsigned i = 0; i < members->dim; i++) {

File d/dmd2/builtin.c

  */
 enum BUILTIN FuncDeclaration::isBuiltin()
 {
-#ifdef IN_GCC
-    //printf("FuncDeclaration::isBuiltin() %s\n", toChars());
-    if (builtin == BUILTINunknown)
-    {
-        builtin = BUILTINnot;
-        if (parent && parent->isModule())
-        {
-            // If it's in the gcc.builtins package
-            if (strcmp(parent->ident->string, "builtins") == 0 && parent->parent &&
-                strcmp(parent->parent->ident->string, "gcc") == 0 &&
-                !parent->parent->parent)
-            {
-                //printf("deco = %s\n", type->deco);
-                builtin = BUILTINgcc;
-            }
-        }
-#else
     static const char FeZe [] = "FNaNbNfeZe";      // @safe pure nothrow real function(real)
     static const char FeZe2[] = "FNaNbNeeZe";      // @trusted pure nothrow real function(real)
 
                         builtin = BUILTINsqrt;
                 }
             }
+#ifdef IN_GCC
+            // If it's in the gcc.builtins package
+            else if (strcmp(parent->ident->string, "builtins") == 0 && parent->parent &&
+                strcmp(parent->parent->ident->string, "gcc") == 0 &&
+                !parent->parent->parent)
+            {
+                //printf("deco = %s\n", type->deco);
+                builtin = BUILTINgcc;
+            }
+#endif
         }
-#endif  
     }
     return builtin;
 }

File d/dmd2/declaration.h

 {
     BUILTINunknown = -1,        // not known if this is a builtin
     BUILTINnot,                 // this is not a builtin
-#if IN_GCC
-    BUILTINgcc,                 // GCC builtin
-#else
     BUILTINsin,                 // std.math.sin
     BUILTINcos,                 // std.math.cos
     BUILTINtan,                 // std.math.tan
     BUILTINsqrt,                // std.math.sqrt
     BUILTINfabs,                // std.math.fabs
+#if IN_GCC
+    BUILTINgcc,                 // GCC builtin
 #endif
 };
 

File d/phobos/std/math.d

  *      Results are undefined if |x| >= $(POWER 2,64).
  */
 
-version(GNU) alias std.c.math.cosl cos; else
 real cos(real x);       /* intrinsic */
 
 /***********************************
  *      Results are undefined if |x| >= $(POWER 2,64).
  */
 
-version(GNU) alias std.c.math.sinl sin; else
 real sin(real x);       /* intrinsic */
 
 
  * greater than long.max, the result is
  * indeterminate.
  */
-version(GNU) alias std.c.math.llroundl rndtol; else
 long rndtol(real x);    /* intrinsic */
 
 
  *      )
  */
 
-version(GNU) float sqrt(float x) { return std.c.math.sqrtf(x); } else
 float sqrt(float x);    /* intrinsic */
-version(GNU) double sqrt(double x) { return std.c.math.sqrt(x); } else /// ditto
 double sqrt(double x);  /* intrinsic */ /// ditto
-version(GNU) real sqrt(real x) { return std.c.math.sqrtl(x); } else /// ditto
 real sqrt(real x);      /* intrinsic */ /// ditto
 
 creal sqrt(creal z)
  * References: frexp
  */
 
-version(GNU) alias std.c.math.ldexpl ldexp; else
 real ldexp(real n, int exp);    /* intrinsic */
 
 /**************************************
  *      $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) )
  *      )
  */
-version (GNU) alias std.c.math.fabsl fabs; else
 real fabs(real x);      /* intrinsic */
 
 
  * $(B nearbyint ) performs
  * the same operation, but does not set the FE_INEXACT exception.
  */
-version(GNU) alias std.c.math.rintl rint; else
 real rint(real x);      /* intrinsic */
 /***************************************
  * Rounds x to the nearest integer value, using the current rounding

File d/phobos2/std/math.d

  *      Results are undefined if |x| >= $(POWER 2,64).
  */
 
-version(GNU)
-{
-    real cos(real x) @safe pure nothrow
-    {
-        return core.stdc.math.cosl(x);
-    }
-} else
 real cos(real x) @safe pure nothrow;       /* intrinsic */
 
 /***********************************
  *      Results are undefined if |x| >= $(POWER 2,64).
  */
 
-version(GNU)
-{
-    real sin(real x) @safe pure nothrow
-    {
-        return core.stdc.math.sinl(x);
-    }
-} else
 real sin(real x) @safe pure nothrow;       /* intrinsic */
 
 
  * greater than long.max, the result is
  * indeterminate.
  */
-version(GNU)
-{
-    long rndtol(real x) @safe pure nothrow
-    {
-        return core.stdc.math.llroundl(x);
-    }
-} else
 long rndtol(real x) @safe pure nothrow;    /* intrinsic */
 
 
 
 @safe pure nothrow
 {
-    version(GNU)
-    {
-        float sqrt(float x)
-        {
-            return core.stdc.math.sqrtf(x);
-        }
-        double sqrt(double x)
-        {
-            return core.stdc.math.sqrt(x);
-        }
-        real sqrt(real x)
-        {
-            return core.stdc.math.sqrtl(x);
-        }
-    }
-    else
-    {
-        float sqrt(float x);    /* intrinsic */
-        double sqrt(double x);  /* intrinsic */ /// ditto
-        real sqrt(real x);      /* intrinsic */ /// ditto
-    }
+    float sqrt(float x);    /* intrinsic */
+    double sqrt(double x);  /* intrinsic */ /// ditto
+    real sqrt(real x);      /* intrinsic */ /// ditto
 }
 
 @trusted pure nothrow {  // Should be @safe.  See bugs 4628, 4630.
  * References: frexp
  */
 
-version(GNU)
-{
-    real ldexp(real n, int exp) @safe pure nothrow
-    {
-        return core.stdc.math.ldexpl(n, exp);
-    }
-} else
 real ldexp(real n, int exp) @safe pure nothrow;    /* intrinsic */
 
 unittest {
  *      $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) )
  *      )
  */
-version(GNU)
-{
-    real fabs(real x) @safe pure nothrow
-    {
-        return core.stdc.math.fabsl(x);
-    }
-} else
 real fabs(real x) @safe pure nothrow;      /* intrinsic */
 
 
  * $(B nearbyint) performs
  * the same operation, but does not set the FE_INEXACT exception.
  */
-version(GNU)
-{
-    real rint(real x) @safe pure nothrow
-    {
-        return core.stdc.math.rintl(x);
-    }
-} else
 real rint(real x) @safe pure nothrow;      /* intrinsic */
 
 /***************************************