diff dmd2/arrayop.c @ 1452:638d16625da2

LDC 2 compiles again.
author Robert Clipsham <robert@octarineparrot.com>
date Sat, 30 May 2009 17:23:32 +0100
parents f04dde6e882c
children 54b3c1394d62
line wrap: on
line diff
--- a/dmd2/arrayop.c	Thu May 28 00:07:21 2009 +0200
+++ b/dmd2/arrayop.c	Sat May 30 17:23:32 2009 +0100
@@ -1,494 +1,505 @@
-
-// Copyright (c) 1999-2008 by Digital Mars
-// All Rights Reserved
-// written by Walter Bright
-// http://www.digitalmars.com
-// License for redistribution is by either the Artistic License
-// in artistic.txt, or the GNU General Public License in gnu.txt.
-// See the included readme.txt for details.
-
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#if _WIN32 || IN_GCC  || IN_LLVM
-#include "mem.h"
-#else
-#include "../root/mem.h"
-#endif
-
-#include "stringtable.h"
-
-#include "expression.h"
-#include "statement.h"
-#include "mtype.h"
-#include "declaration.h"
-#include "scope.h"
-#include "id.h"
-#include "module.h"
-#include "init.h"
-
-
-/***********************************
- * Construct the array operation expression.
- */
-
-Expression *BinExp::arrayOp(Scope *sc)
-{
-    Expressions *arguments = new Expressions();
-
-    /* The expression to generate an array operation for is mangled
-     * into a name to use as the array operation function name.
-     * Mangle in the operands and operators in RPN order, and type.
-     */
-    OutBuffer buf;
-    buf.writestring("_array");
-    buildArrayIdent(&buf, arguments);
-    buf.writeByte('_');
-
-    /* Append deco of array element type
-     */
-#if DMDV2
-    buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
-#else
-    buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
-#endif
-
-    size_t namelen = buf.offset;
-    buf.writeByte(0);
-    char *name = (char *)buf.extractData();
-
-    /* Look up name in hash table
-     */
-    StringValue *sv = sc->module->arrayfuncs.update(name, namelen);
-    FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue;
-    if (!fd)
-    {
-//     /* Some of the array op functions are written as library functions,
-//      * presumably to optimize them with special CPU vector instructions.
-//      * List those library functions here, in alpha order.
-//      */
-//     static const char *libArrayopFuncs[] =
-//     {
-//         "_arrayExpSliceAddass_a",
-//         "_arrayExpSliceAddass_d",       // T[]+=T
-//         "_arrayExpSliceAddass_f",       // T[]+=T
-//         "_arrayExpSliceAddass_g",
-//         "_arrayExpSliceAddass_h",
-//         "_arrayExpSliceAddass_i",
-//         "_arrayExpSliceAddass_k",
-//         "_arrayExpSliceAddass_s",
-//         "_arrayExpSliceAddass_t",
-//         "_arrayExpSliceAddass_u",
-//         "_arrayExpSliceAddass_w",
-// 
-//         "_arrayExpSliceDivass_d",       // T[]/=T
-//         "_arrayExpSliceDivass_f",       // T[]/=T
-// 
-//         "_arrayExpSliceMinSliceAssign_a",
-//         "_arrayExpSliceMinSliceAssign_d",   // T[]=T-T[]
-//         "_arrayExpSliceMinSliceAssign_f",   // T[]=T-T[]
-//         "_arrayExpSliceMinSliceAssign_g",
-//         "_arrayExpSliceMinSliceAssign_h",
-//         "_arrayExpSliceMinSliceAssign_i",
-//         "_arrayExpSliceMinSliceAssign_k",
-//         "_arrayExpSliceMinSliceAssign_s",
-//         "_arrayExpSliceMinSliceAssign_t",
-//         "_arrayExpSliceMinSliceAssign_u",
-//         "_arrayExpSliceMinSliceAssign_w",
-// 
-//         "_arrayExpSliceMinass_a",
-//         "_arrayExpSliceMinass_d",       // T[]-=T
-//         "_arrayExpSliceMinass_f",       // T[]-=T
-//         "_arrayExpSliceMinass_g",
-//         "_arrayExpSliceMinass_h",
-//         "_arrayExpSliceMinass_i",
-//         "_arrayExpSliceMinass_k",
-//         "_arrayExpSliceMinass_s",
-//         "_arrayExpSliceMinass_t",
-//         "_arrayExpSliceMinass_u",
-//         "_arrayExpSliceMinass_w",
-// 
-//         "_arrayExpSliceMulass_d",       // T[]*=T
-//         "_arrayExpSliceMulass_f",       // T[]*=T
-//         "_arrayExpSliceMulass_i",
-//         "_arrayExpSliceMulass_k",
-//         "_arrayExpSliceMulass_s",
-//         "_arrayExpSliceMulass_t",
-//         "_arrayExpSliceMulass_u",
-//         "_arrayExpSliceMulass_w",
-// 
-//         "_arraySliceExpAddSliceAssign_a",
-//         "_arraySliceExpAddSliceAssign_d",   // T[]=T[]+T
-//         "_arraySliceExpAddSliceAssign_f",   // T[]=T[]+T
-//         "_arraySliceExpAddSliceAssign_g",
-//         "_arraySliceExpAddSliceAssign_h",
-//         "_arraySliceExpAddSliceAssign_i",
-//         "_arraySliceExpAddSliceAssign_k",
-//         "_arraySliceExpAddSliceAssign_s",
-//         "_arraySliceExpAddSliceAssign_t",
-//         "_arraySliceExpAddSliceAssign_u",
-//         "_arraySliceExpAddSliceAssign_w",
-// 
-//         "_arraySliceExpDivSliceAssign_d",   // T[]=T[]/T
-//         "_arraySliceExpDivSliceAssign_f",   // T[]=T[]/T
-// 
-//         "_arraySliceExpMinSliceAssign_a",
-//         "_arraySliceExpMinSliceAssign_d",   // T[]=T[]-T
-//         "_arraySliceExpMinSliceAssign_f",   // T[]=T[]-T
-//         "_arraySliceExpMinSliceAssign_g",
-//         "_arraySliceExpMinSliceAssign_h",
-//         "_arraySliceExpMinSliceAssign_i",
-//         "_arraySliceExpMinSliceAssign_k",
-//         "_arraySliceExpMinSliceAssign_s",
-//         "_arraySliceExpMinSliceAssign_t",
-//         "_arraySliceExpMinSliceAssign_u",
-//         "_arraySliceExpMinSliceAssign_w",
-// 
-//         "_arraySliceExpMulSliceAddass_d",   // T[] += T[]*T
-//         "_arraySliceExpMulSliceAddass_f",
-//         "_arraySliceExpMulSliceAddass_r",
-// 
-//         "_arraySliceExpMulSliceAssign_d",   // T[]=T[]*T
-//         "_arraySliceExpMulSliceAssign_f",   // T[]=T[]*T
-//         "_arraySliceExpMulSliceAssign_i",
-//         "_arraySliceExpMulSliceAssign_k",
-//         "_arraySliceExpMulSliceAssign_s",
-//         "_arraySliceExpMulSliceAssign_t",
-//         "_arraySliceExpMulSliceAssign_u",
-//         "_arraySliceExpMulSliceAssign_w",
-// 
-//         "_arraySliceExpMulSliceMinass_d",   // T[] -= T[]*T
-//         "_arraySliceExpMulSliceMinass_f",
-//         "_arraySliceExpMulSliceMinass_r",
-// 
-//         "_arraySliceSliceAddSliceAssign_a",
-//         "_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[]
-//         "_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[]
-//         "_arraySliceSliceAddSliceAssign_g",
-//         "_arraySliceSliceAddSliceAssign_h",
-//         "_arraySliceSliceAddSliceAssign_i",
-//         "_arraySliceSliceAddSliceAssign_k",
-//         "_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[]
-//         "_arraySliceSliceAddSliceAssign_s",
-//         "_arraySliceSliceAddSliceAssign_t",
-//         "_arraySliceSliceAddSliceAssign_u",
-//         "_arraySliceSliceAddSliceAssign_w",
-// 
-//         "_arraySliceSliceAddass_a",
-//         "_arraySliceSliceAddass_d",     // T[]+=T[]
-//         "_arraySliceSliceAddass_f",     // T[]+=T[]
-//         "_arraySliceSliceAddass_g",
-//         "_arraySliceSliceAddass_h",
-//         "_arraySliceSliceAddass_i",
-//         "_arraySliceSliceAddass_k",
-//         "_arraySliceSliceAddass_s",
-//         "_arraySliceSliceAddass_t",
-//         "_arraySliceSliceAddass_u",
-//         "_arraySliceSliceAddass_w",
-// 
-//         "_arraySliceSliceMinSliceAssign_a",
-//         "_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[]
-//         "_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[]
-//         "_arraySliceSliceMinSliceAssign_g",
-//         "_arraySliceSliceMinSliceAssign_h",
-//         "_arraySliceSliceMinSliceAssign_i",
-//         "_arraySliceSliceMinSliceAssign_k",
-//         "_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[]
-//         "_arraySliceSliceMinSliceAssign_s",
-//         "_arraySliceSliceMinSliceAssign_t",
-//         "_arraySliceSliceMinSliceAssign_u",
-//         "_arraySliceSliceMinSliceAssign_w",
-// 
-//         "_arraySliceSliceMinass_a",
-//         "_arraySliceSliceMinass_d",     // T[]-=T[]
-//         "_arraySliceSliceMinass_f",     // T[]-=T[]
-//         "_arraySliceSliceMinass_g",
-//         "_arraySliceSliceMinass_h",
-//         "_arraySliceSliceMinass_i",
-//         "_arraySliceSliceMinass_k",
-//         "_arraySliceSliceMinass_s",
-//         "_arraySliceSliceMinass_t",
-//         "_arraySliceSliceMinass_u",
-//         "_arraySliceSliceMinass_w",
-// 
-//         "_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[]
-//         "_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[]
-//         "_arraySliceSliceMulSliceAssign_i",
-//         "_arraySliceSliceMulSliceAssign_k",
-//         "_arraySliceSliceMulSliceAssign_s",
-//         "_arraySliceSliceMulSliceAssign_t",
-//         "_arraySliceSliceMulSliceAssign_u",
-//         "_arraySliceSliceMulSliceAssign_w",
-// 
-//         "_arraySliceSliceMulass_d",     // T[]*=T[]
-//         "_arraySliceSliceMulass_f",     // T[]*=T[]
-//         "_arraySliceSliceMulass_i",
-//         "_arraySliceSliceMulass_k",
-//         "_arraySliceSliceMulass_s",
-//         "_arraySliceSliceMulass_t",
-//         "_arraySliceSliceMulass_u",
-//         "_arraySliceSliceMulass_w",
-//     };
-// 
-//     int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *));
-//     if (i == -1)
-//     {
-// #ifdef DEBUG    // Make sure our array is alphabetized
-//         for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++)
-//         {
-//         if (strcmp(name, libArrayopFuncs[i]) == 0)
-//             assert(0);
-//         }
-// #endif
-
-        /* Not in library, so generate it.
-         * Construct the function body:
-         *  foreach (i; 0 .. p.length)    for (size_t i = 0; i < p.length; i++)
-         *      loopbody;
-         *  return p;
-         */
-
-        Arguments *fparams = new Arguments();
-        Expression *loopbody = buildArrayLoop(fparams);
-        Argument *p = (Argument *)fparams->data[0 /*fparams->dim - 1*/];
-#if DMDV1
-        // for (size_t i = 0; i < p.length; i++)
-        Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
-        Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
-        Statement *s1 = new ForStatement(0,
-        new DeclarationStatement(0, d),
-        new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
-        new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
-        new ExpStatement(0, loopbody));
-#else
-        // foreach (i; 0 .. p.length)
-        Statement *s1 = new ForeachRangeStatement(0, TOKforeach,
-        new Argument(0, NULL, Id::p, NULL),
-        new IntegerExp(0, 0, Type::tint32),
-        new ArrayLengthExp(0, new IdentifierExp(0, p->ident)),
-        new ExpStatement(0, loopbody));
-#endif
-        Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident));
-        //printf("s2: %s\n", s2->toChars());
-        Statement *fbody = new CompoundStatement(0, s1, s2);
-
-        /* Construct the function
-         */
-        TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
-        //printf("ftype: %s\n", ftype->toChars());
-        fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype);
-        fd->fbody = fbody;
-        fd->protection = PROTprotected;
-        fd->linkage = LINKd;
-
-        // special attention for array ops
-        fd->isArrayOp = true;
-
-        sc->module->members->push(fd);
-
-        sc = sc->push();
-        sc->parent = sc->module;
-        sc->stc = 0;
-        sc->linkage = LINKd;
-        fd->semantic(sc);
-        sc->pop();
-//     }
-//     else
-//     {   /* In library, refer to it.
-//          */
-//         // FIXME
-//         fd = FuncDeclaration::genCfunc(NULL, type, name);
-//     }
-    sv->ptrvalue = fd;  // cache symbol in hash table
-    }
-
-    /* Call the function fd(arguments)
-     */
-    Expression *ec = new VarExp(0, fd);
-    Expression *e = new CallExp(loc, ec, arguments);
-    e->type = type;
-    return e;
-}
-
-/******************************************
- * Construct the identifier for the array operation function,
- * and build the argument list to pass to it.
- */
-
-void Expression::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
-{
-    buf->writestring("Exp");
-    arguments->shift(this);
-}
-
-void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
-{
-    buf->writestring("Slice");
-    arguments->shift(this);
-}
-
-void AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
-{
-    /* Evaluate assign expressions right to left
-     */
-    e2->buildArrayIdent(buf, arguments);
-    e1->buildArrayIdent(buf, arguments);
-    buf->writestring("Assign");
-}
-
-#define X(Str) \
-void Str##AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
-{							\
-    /* Evaluate assign expressions right to left	\
-     */							\
-    e2->buildArrayIdent(buf, arguments);		\
-    e1->buildArrayIdent(buf, arguments);		\
-    buf->writestring(#Str);				\
-    buf->writestring("ass");				\
-}
-
-X(Add)
-X(Min)
-X(Mul)
-X(Div)
-X(Mod)
-X(Xor)
-X(And)
-X(Or)
-
-#undef X
-
-void NegExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
-{
-    e1->buildArrayIdent(buf, arguments);
-    buf->writestring("Neg");
-}
-
-void ComExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
-{
-    e1->buildArrayIdent(buf, arguments);
-    buf->writestring("Com");
-}
-
-#define X(Str) \
-void Str##Exp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)	\
-{									\
-    /* Evaluate assign expressions left to right			\
-     */									\
-    e1->buildArrayIdent(buf, arguments);				\
-    e2->buildArrayIdent(buf, arguments);				\
-    buf->writestring(#Str);						\
-}
-
-X(Add)
-X(Min)
-X(Mul)
-X(Div)
-X(Mod)
-X(Xor)
-X(And)
-X(Or)
-
-#undef X
-
-/******************************************
- * Construct the inner loop for the array operation function,
- * and build the parameter list.
- */
-
-Expression *Expression::buildArrayLoop(Arguments *fparams)
-{
-    Identifier *id = Identifier::generateId("c", fparams->dim);
-    Argument *param = new Argument(0, type, id, NULL);
-    fparams->shift(param);
-    Expression *e = new IdentifierExp(0, id);
-    return e;
-}
-
-Expression *SliceExp::buildArrayLoop(Arguments *fparams)
-{
-    Identifier *id = Identifier::generateId("p", fparams->dim);
-    Argument *param = new Argument(STCconst, type, id, NULL);
-    fparams->shift(param);
-    Expression *e = new IdentifierExp(0, id);
-    Expressions *arguments = new Expressions();
-    Expression *index = new IdentifierExp(0, Id::p);
-    arguments->push(index);
-    e = new ArrayExp(0, e, arguments);
-    return e;
-}
-
-Expression *AssignExp::buildArrayLoop(Arguments *fparams)
-{
-    /* Evaluate assign expressions right to left
-     */
-    Expression *ex2 = e2->buildArrayLoop(fparams);
-    Expression *ex1 = e1->buildArrayLoop(fparams);
-    Argument *param = (Argument *)fparams->data[0];
-    param->storageClass = 0;
-    Expression *e = new AssignExp(0, ex1, ex2);
-    return e;
-}
-
-#define X(Str) \
-Expression *Str##AssignExp::buildArrayLoop(Arguments *fparams)	\
-{								\
-    /* Evaluate assign expressions right to left		\
-     */								\
-    Expression *ex2 = e2->buildArrayLoop(fparams);		\
-    Expression *ex1 = e1->buildArrayLoop(fparams);		\
-    Argument *param = (Argument *)fparams->data[0];		\
-    param->storageClass = 0;					\
-    Expression *e = new Str##AssignExp(0, ex1, ex2);		\
-    return e;							\
-}
-
-X(Add)
-X(Min)
-X(Mul)
-X(Div)
-X(Mod)
-X(Xor)
-X(And)
-X(Or)
-
-#undef X
-
-Expression *NegExp::buildArrayLoop(Arguments *fparams)
-{
-    Expression *ex1 = e1->buildArrayLoop(fparams);
-    Expression *e = new NegExp(0, ex1);
-    return e;
-}
-
-Expression *ComExp::buildArrayLoop(Arguments *fparams)
-{
-    Expression *ex1 = e1->buildArrayLoop(fparams);
-    Expression *e = new ComExp(0, ex1);
-    return e;
-}
-
-#define X(Str) \
-Expression *Str##Exp::buildArrayLoop(Arguments *fparams)	\
-{								\
-    /* Evaluate assign expressions left to right		\
-     */								\
-    Expression *ex1 = e1->buildArrayLoop(fparams);		\
-    Expression *ex2 = e2->buildArrayLoop(fparams);		\
-    Expression *e = new Str##Exp(0, ex1, ex2);			\
-    return e;							\
-}
-
-X(Add)
-X(Min)
-X(Mul)
-X(Div)
-X(Mod)
-X(Xor)
-X(And)
-X(Or)
-
-#undef X
-
-
+
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "rmem.h"
+
+#include "stringtable.h"
+
+#include "expression.h"
+#include "statement.h"
+#include "mtype.h"
+#include "declaration.h"
+#include "scope.h"
+#include "id.h"
+#include "module.h"
+#include "init.h"
+
+#if IN_DMD
+extern int binary(const char *p , const char **tab, int high);
+
+/**************************************
+ * Hash table of array op functions already generated or known about.
+ */
+
+StringTable arrayfuncs;
+#endif
+
+/***********************************
+ * Construct the array operation expression.
+ */
+
+Expression *BinExp::arrayOp(Scope *sc)
+{
+    Expressions *arguments = new Expressions();
+
+    /* The expression to generate an array operation for is mangled
+     * into a name to use as the array operation function name.
+     * Mangle in the operands and operators in RPN order, and type.
+     */
+    OutBuffer buf;
+    buf.writestring("_array");
+    buildArrayIdent(&buf, arguments);
+    buf.writeByte('_');
+
+    /* Append deco of array element type
+     */
+#if DMDV2
+    buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
+#else
+    buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
+#endif
+
+    size_t namelen = buf.offset;
+    buf.writeByte(0);
+    char *name = (char *)buf.extractData();
+
+    /* Look up name in hash table
+     */
+#if IN_LLVM
+    StringValue *sv = sc->module->arrayfuncs.update(name, namelen);
+#else
+    StringValue *sv = arrayfuncs.update(name, namelen);
+#endif
+    FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue;
+    if (!fd)
+    {
+#if IN_DMD
+	/* Some of the array op functions are written as library functions,
+	 * presumably to optimize them with special CPU vector instructions.
+	 * List those library functions here, in alpha order.
+	 */
+	static const char *libArrayopFuncs[] =
+	{
+	    "_arrayExpSliceAddass_a",
+	    "_arrayExpSliceAddass_d",		// T[]+=T
+	    "_arrayExpSliceAddass_f",		// T[]+=T
+	    "_arrayExpSliceAddass_g",
+	    "_arrayExpSliceAddass_h",
+	    "_arrayExpSliceAddass_i",
+	    "_arrayExpSliceAddass_k",
+	    "_arrayExpSliceAddass_s",
+	    "_arrayExpSliceAddass_t",
+	    "_arrayExpSliceAddass_u",
+	    "_arrayExpSliceAddass_w",
+
+	    "_arrayExpSliceDivass_d",		// T[]/=T
+	    "_arrayExpSliceDivass_f",		// T[]/=T
+
+	    "_arrayExpSliceMinSliceAssign_a",
+	    "_arrayExpSliceMinSliceAssign_d",	// T[]=T-T[]
+	    "_arrayExpSliceMinSliceAssign_f",	// T[]=T-T[]
+	    "_arrayExpSliceMinSliceAssign_g",
+	    "_arrayExpSliceMinSliceAssign_h",
+	    "_arrayExpSliceMinSliceAssign_i",
+	    "_arrayExpSliceMinSliceAssign_k",
+	    "_arrayExpSliceMinSliceAssign_s",
+	    "_arrayExpSliceMinSliceAssign_t",
+	    "_arrayExpSliceMinSliceAssign_u",
+	    "_arrayExpSliceMinSliceAssign_w",
+
+	    "_arrayExpSliceMinass_a",
+	    "_arrayExpSliceMinass_d",		// T[]-=T
+	    "_arrayExpSliceMinass_f",		// T[]-=T
+	    "_arrayExpSliceMinass_g",
+	    "_arrayExpSliceMinass_h",
+	    "_arrayExpSliceMinass_i",
+	    "_arrayExpSliceMinass_k",
+	    "_arrayExpSliceMinass_s",
+	    "_arrayExpSliceMinass_t",
+	    "_arrayExpSliceMinass_u",
+	    "_arrayExpSliceMinass_w",
+
+	    "_arrayExpSliceMulass_d",		// T[]*=T
+	    "_arrayExpSliceMulass_f",		// T[]*=T
+	    "_arrayExpSliceMulass_i",
+	    "_arrayExpSliceMulass_k",
+	    "_arrayExpSliceMulass_s",
+	    "_arrayExpSliceMulass_t",
+	    "_arrayExpSliceMulass_u",
+	    "_arrayExpSliceMulass_w",
+
+	    "_arraySliceExpAddSliceAssign_a",
+	    "_arraySliceExpAddSliceAssign_d",	// T[]=T[]+T
+	    "_arraySliceExpAddSliceAssign_f",	// T[]=T[]+T
+	    "_arraySliceExpAddSliceAssign_g",
+	    "_arraySliceExpAddSliceAssign_h",
+	    "_arraySliceExpAddSliceAssign_i",
+	    "_arraySliceExpAddSliceAssign_k",
+	    "_arraySliceExpAddSliceAssign_s",
+	    "_arraySliceExpAddSliceAssign_t",
+	    "_arraySliceExpAddSliceAssign_u",
+	    "_arraySliceExpAddSliceAssign_w",
+
+	    "_arraySliceExpDivSliceAssign_d",	// T[]=T[]/T
+	    "_arraySliceExpDivSliceAssign_f",	// T[]=T[]/T
+
+	    "_arraySliceExpMinSliceAssign_a",
+	    "_arraySliceExpMinSliceAssign_d",	// T[]=T[]-T
+	    "_arraySliceExpMinSliceAssign_f",	// T[]=T[]-T
+	    "_arraySliceExpMinSliceAssign_g",
+	    "_arraySliceExpMinSliceAssign_h",
+	    "_arraySliceExpMinSliceAssign_i",
+	    "_arraySliceExpMinSliceAssign_k",
+	    "_arraySliceExpMinSliceAssign_s",
+	    "_arraySliceExpMinSliceAssign_t",
+	    "_arraySliceExpMinSliceAssign_u",
+	    "_arraySliceExpMinSliceAssign_w",
+
+	    "_arraySliceExpMulSliceAddass_d",	// T[] += T[]*T
+	    "_arraySliceExpMulSliceAddass_f",
+	    "_arraySliceExpMulSliceAddass_r",
+
+	    "_arraySliceExpMulSliceAssign_d",	// T[]=T[]*T
+	    "_arraySliceExpMulSliceAssign_f",	// T[]=T[]*T
+	    "_arraySliceExpMulSliceAssign_i",
+	    "_arraySliceExpMulSliceAssign_k",
+	    "_arraySliceExpMulSliceAssign_s",
+	    "_arraySliceExpMulSliceAssign_t",
+	    "_arraySliceExpMulSliceAssign_u",
+	    "_arraySliceExpMulSliceAssign_w",
+
+	    "_arraySliceExpMulSliceMinass_d",	// T[] -= T[]*T
+	    "_arraySliceExpMulSliceMinass_f",
+	    "_arraySliceExpMulSliceMinass_r",
+
+	    "_arraySliceSliceAddSliceAssign_a",
+	    "_arraySliceSliceAddSliceAssign_d",	// T[]=T[]+T[]
+	    "_arraySliceSliceAddSliceAssign_f",	// T[]=T[]+T[]
+	    "_arraySliceSliceAddSliceAssign_g",
+	    "_arraySliceSliceAddSliceAssign_h",
+	    "_arraySliceSliceAddSliceAssign_i",
+	    "_arraySliceSliceAddSliceAssign_k",
+	    "_arraySliceSliceAddSliceAssign_r",	// T[]=T[]+T[]
+	    "_arraySliceSliceAddSliceAssign_s",
+	    "_arraySliceSliceAddSliceAssign_t",
+	    "_arraySliceSliceAddSliceAssign_u",
+	    "_arraySliceSliceAddSliceAssign_w",
+
+	    "_arraySliceSliceAddass_a",
+	    "_arraySliceSliceAddass_d",		// T[]+=T[]
+	    "_arraySliceSliceAddass_f",		// T[]+=T[]
+	    "_arraySliceSliceAddass_g",
+	    "_arraySliceSliceAddass_h",
+	    "_arraySliceSliceAddass_i",
+	    "_arraySliceSliceAddass_k",
+	    "_arraySliceSliceAddass_s",
+	    "_arraySliceSliceAddass_t",
+	    "_arraySliceSliceAddass_u",
+	    "_arraySliceSliceAddass_w",
+
+	    "_arraySliceSliceMinSliceAssign_a",
+	    "_arraySliceSliceMinSliceAssign_d",	// T[]=T[]-T[]
+	    "_arraySliceSliceMinSliceAssign_f",	// T[]=T[]-T[]
+	    "_arraySliceSliceMinSliceAssign_g",
+	    "_arraySliceSliceMinSliceAssign_h",
+	    "_arraySliceSliceMinSliceAssign_i",
+	    "_arraySliceSliceMinSliceAssign_k",
+	    "_arraySliceSliceMinSliceAssign_r",	// T[]=T[]-T[]
+	    "_arraySliceSliceMinSliceAssign_s",
+	    "_arraySliceSliceMinSliceAssign_t",
+	    "_arraySliceSliceMinSliceAssign_u",
+	    "_arraySliceSliceMinSliceAssign_w",
+
+	    "_arraySliceSliceMinass_a",
+	    "_arraySliceSliceMinass_d",		// T[]-=T[]
+	    "_arraySliceSliceMinass_f",		// T[]-=T[]
+	    "_arraySliceSliceMinass_g",
+	    "_arraySliceSliceMinass_h",
+	    "_arraySliceSliceMinass_i",
+	    "_arraySliceSliceMinass_k",
+	    "_arraySliceSliceMinass_s",
+	    "_arraySliceSliceMinass_t",
+	    "_arraySliceSliceMinass_u",
+	    "_arraySliceSliceMinass_w",
+
+	    "_arraySliceSliceMulSliceAssign_d",	// T[]=T[]*T[]
+	    "_arraySliceSliceMulSliceAssign_f",	// T[]=T[]*T[]
+	    "_arraySliceSliceMulSliceAssign_i",
+	    "_arraySliceSliceMulSliceAssign_k",
+	    "_arraySliceSliceMulSliceAssign_s",
+	    "_arraySliceSliceMulSliceAssign_t",
+	    "_arraySliceSliceMulSliceAssign_u",
+	    "_arraySliceSliceMulSliceAssign_w",
+
+	    "_arraySliceSliceMulass_d",		// T[]*=T[]
+	    "_arraySliceSliceMulass_f",		// T[]*=T[]
+	    "_arraySliceSliceMulass_i",
+	    "_arraySliceSliceMulass_k",
+	    "_arraySliceSliceMulass_s",
+	    "_arraySliceSliceMulass_t",
+	    "_arraySliceSliceMulass_u",
+	    "_arraySliceSliceMulass_w",
+	};
+
+	int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *));
+	if (i == -1)
+	{
+#ifdef DEBUG	// Make sure our array is alphabetized
+	    for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++)
+	    {
+		if (strcmp(name, libArrayopFuncs[i]) == 0)
+		    assert(0);
+	    }
+#endif
+#endif
+	    /* Not in library, so generate it.
+	     * Construct the function body:
+	     *	foreach (i; 0 .. p.length)    for (size_t i = 0; i < p.length; i++)
+	     *	    loopbody;
+	     *	return p;
+	     */
+
+	    Arguments *fparams = new Arguments();
+	    Expression *loopbody = buildArrayLoop(fparams);
+	    Argument *p = (Argument *)fparams->data[0 /*fparams->dim - 1*/];
+#if DMDV1
+	    // for (size_t i = 0; i < p.length; i++)
+	    Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
+	    Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
+	    Statement *s1 = new ForStatement(0,
+		new DeclarationStatement(0, d),
+		new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
+		new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
+		new ExpStatement(0, loopbody));
+#else
+	    // foreach (i; 0 .. p.length)
+	    Statement *s1 = new ForeachRangeStatement(0, TOKforeach,
+		new Argument(0, NULL, Id::p, NULL),
+		new IntegerExp(0, 0, Type::tint32),
+		new ArrayLengthExp(0, new IdentifierExp(0, p->ident)),
+		new ExpStatement(0, loopbody));
+#endif
+	    Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident));
+	    //printf("s2: %s\n", s2->toChars());
+	    Statement *fbody = new CompoundStatement(0, s1, s2);
+
+	    /* Construct the function
+	     */
+	    TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
+	    //printf("ftype: %s\n", ftype->toChars());
+	    fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype);
+	    fd->fbody = fbody;
+	    fd->protection = PROTpublic;
+	    fd->linkage = LINKd;
+
+   		// special attention for array ops
+        fd->isArrayOp = true;
+
+	    sc->module->importedFrom->members->push(fd);
+
+	    sc = sc->push();
+	    sc->parent = sc->module->importedFrom;
+	    sc->stc = 0;
+	    sc->linkage = LINKc;
+	    fd->semantic(sc);
+	    sc->pop();
+#if IN_DMD
+	}
+	else
+	{   /* In library, refer to it.
+	     */
+	    fd = FuncDeclaration::genCfunc(type, name);
+	}
+#endif
+	sv->ptrvalue = fd;	// cache symbol in hash table
+    }
+
+    /* Call the function fd(arguments)
+     */
+    Expression *ec = new VarExp(0, fd);
+    Expression *e = new CallExp(loc, ec, arguments);
+    e->type = type;
+    return e;
+}
+
+/******************************************
+ * Construct the identifier for the array operation function,
+ * and build the argument list to pass to it.
+ */
+
+void Expression::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    buf->writestring("Exp");
+    arguments->shift(this);
+}
+
+void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    buf->writestring("Slice");
+    arguments->shift(this);
+}
+
+void AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    /* Evaluate assign expressions right to left
+     */
+    e2->buildArrayIdent(buf, arguments);
+    e1->buildArrayIdent(buf, arguments);
+    buf->writestring("Assign");
+}
+
+#define X(Str) \
+void Str##AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
+{							\
+    /* Evaluate assign expressions right to left	\
+     */							\
+    e2->buildArrayIdent(buf, arguments);		\
+    e1->buildArrayIdent(buf, arguments);		\
+    buf->writestring(#Str);				\
+    buf->writestring("ass");				\
+}
+
+X(Add)
+X(Min)
+X(Mul)
+X(Div)
+X(Mod)
+X(Xor)
+X(And)
+X(Or)
+
+#undef X
+
+void NegExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    e1->buildArrayIdent(buf, arguments);
+    buf->writestring("Neg");
+}
+
+void ComExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    e1->buildArrayIdent(buf, arguments);
+    buf->writestring("Com");
+}
+
+#define X(Str) \
+void Str##Exp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)	\
+{									\
+    /* Evaluate assign expressions left to right			\
+     */									\
+    e1->buildArrayIdent(buf, arguments);				\
+    e2->buildArrayIdent(buf, arguments);				\
+    buf->writestring(#Str);						\
+}
+
+X(Add)
+X(Min)
+X(Mul)
+X(Div)
+X(Mod)
+X(Xor)
+X(And)
+X(Or)
+
+#undef X
+
+/******************************************
+ * Construct the inner loop for the array operation function,
+ * and build the parameter list.
+ */
+
+Expression *Expression::buildArrayLoop(Arguments *fparams)
+{
+    Identifier *id = Identifier::generateId("c", fparams->dim);
+    Argument *param = new Argument(0, type, id, NULL);
+    fparams->shift(param);
+    Expression *e = new IdentifierExp(0, id);
+    return e;
+}
+
+Expression *SliceExp::buildArrayLoop(Arguments *fparams)
+{
+    Identifier *id = Identifier::generateId("p", fparams->dim);
+    Argument *param = new Argument(STCconst, type, id, NULL);
+    fparams->shift(param);
+    Expression *e = new IdentifierExp(0, id);
+    Expressions *arguments = new Expressions();
+    Expression *index = new IdentifierExp(0, Id::p);
+    arguments->push(index);
+    e = new ArrayExp(0, e, arguments);
+    return e;
+}
+
+Expression *AssignExp::buildArrayLoop(Arguments *fparams)
+{
+    /* Evaluate assign expressions right to left
+     */
+    Expression *ex2 = e2->buildArrayLoop(fparams);
+    Expression *ex1 = e1->buildArrayLoop(fparams);
+    Argument *param = (Argument *)fparams->data[0];
+    param->storageClass = 0;
+    Expression *e = new AssignExp(0, ex1, ex2);
+    return e;
+}
+
+#define X(Str) \
+Expression *Str##AssignExp::buildArrayLoop(Arguments *fparams)	\
+{								\
+    /* Evaluate assign expressions right to left		\
+     */								\
+    Expression *ex2 = e2->buildArrayLoop(fparams);		\
+    Expression *ex1 = e1->buildArrayLoop(fparams);		\
+    Argument *param = (Argument *)fparams->data[0];		\
+    param->storageClass = 0;					\
+    Expression *e = new Str##AssignExp(0, ex1, ex2);		\
+    return e;							\
+}
+
+X(Add)
+X(Min)
+X(Mul)
+X(Div)
+X(Mod)
+X(Xor)
+X(And)
+X(Or)
+
+#undef X
+
+Expression *NegExp::buildArrayLoop(Arguments *fparams)
+{
+    Expression *ex1 = e1->buildArrayLoop(fparams);
+    Expression *e = new NegExp(0, ex1);
+    return e;
+}
+
+Expression *ComExp::buildArrayLoop(Arguments *fparams)
+{
+    Expression *ex1 = e1->buildArrayLoop(fparams);
+    Expression *e = new ComExp(0, ex1);
+    return e;
+}
+
+#define X(Str) \
+Expression *Str##Exp::buildArrayLoop(Arguments *fparams)	\
+{								\
+    /* Evaluate assign expressions left to right		\
+     */								\
+    Expression *ex1 = e1->buildArrayLoop(fparams);		\
+    Expression *ex2 = e2->buildArrayLoop(fparams);		\
+    Expression *e = new Str##Exp(0, ex1, ex2);			\
+    return e;							\
+}
+
+X(Add)
+X(Min)
+X(Mul)
+X(Div)
+X(Mod)
+X(Xor)
+X(And)
+X(Or)
+
+#undef X
+
+