changeset 703:06576ece1a1b

Changed premake.lua to work with mingw. Implemented array operations, not perfect but ok for tonight. closes #89
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Mon, 13 Oct 2008 23:19:32 +0200
parents 353d9d184091
children 43165a082535
files dmd/arrayop.c dmd/declaration.h dmd/func.c dmd/module.h gen/toir.cpp gen/tollvm.cpp premake.lua tests/mini/arrayops1.d tests/mini/arrayops2.d tests/mini/arrayops3.d tests/mini/arrayops4.d
diffstat 11 files changed, 311 insertions(+), 253 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/arrayop.c	Mon Oct 13 21:08:11 2008 +0200
+++ b/dmd/arrayop.c	Mon Oct 13 23:19:32 2008 +0200
@@ -28,17 +28,6 @@
 #include "module.h"
 #include "init.h"
 
-// FIXME
-int binary(const char *p , const char **tab, int high)
-{
-    assert(0);
-}
-
-/**************************************
- * Hash table of array op functions already generated or known about.
- */
-
-StringTable arrayfuncs;
 
 /***********************************
  * Construct the array operation expression.
@@ -46,10 +35,6 @@
 
 Expression *BinExp::arrayOp(Scope *sc)
 {
-    // FIXME
-    error("array operations not yet implemented");
-    fatal();
-
     Expressions *arguments = new Expressions();
 
     /* The expression to generate an array operation for is mangled
@@ -75,243 +60,247 @@
 
     /* Look up name in hash table
      */
-    StringValue *sv = arrayfuncs.update(name, namelen);
+    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",
+//     /* 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
 
-	    "_arrayExpSliceDivass_d",		// T[]/=T
-	    "_arrayExpSliceDivass_f",		// T[]/=T
+        /* 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;
+         */
 
-	    "_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",
+        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);
 
-	    "_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",
+        /* 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;
 
-	    "_arrayExpSliceMulass_d",		// T[]*=T
-	    "_arrayExpSliceMulass_f",		// T[]*=T
-	    "_arrayExpSliceMulass_i",
-	    "_arrayExpSliceMulass_k",
-	    "_arrayExpSliceMulass_s",
-	    "_arrayExpSliceMulass_t",
-	    "_arrayExpSliceMulass_u",
-	    "_arrayExpSliceMulass_w",
+        // special attention for array ops
+        fd->isArrayOp = true;
 
-	    "_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",
+        sc->module->members->push(fd);
 
-	    "_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 = PROTpublic;
-	    fd->linkage = LINKc;
-
-	    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();
-	}
-	else
-	{   /* In library, refer to it.
-	     */
-        // LDC FIXME   
-	    fd = FuncDeclaration::genCfunc(NULL, type, name);
-	}
-	sv->ptrvalue = fd;	// cache symbol in hash table
+        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)
--- a/dmd/declaration.h	Mon Oct 13 21:08:11 2008 +0200
+++ b/dmd/declaration.h	Mon Oct 13 23:19:32 2008 +0200
@@ -651,6 +651,9 @@
     // don't always carry their corresponding statement along ...
     typedef std::map<const char*, LabelStatement*> LabelMap;
     LabelMap labmap;
+
+    // if this is an array operation it gets a little special attention
+    bool isArrayOp;
 };
 
 struct FuncAliasDeclaration : FuncDeclaration
--- a/dmd/func.c	Mon Oct 13 21:08:11 2008 +0200
+++ b/dmd/func.c	Mon Oct 13 23:19:32 2008 +0200
@@ -77,6 +77,9 @@
     nrvo_can = 1;
     nrvo_var = NULL;
     shidden = NULL;
+
+    // LDC
+    isArrayOp = false;
 }
 
 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
--- a/dmd/module.h	Mon Oct 13 21:08:11 2008 +0200
+++ b/dmd/module.h	Mon Oct 13 23:19:32 2008 +0200
@@ -175,6 +175,9 @@
     Module *isModule() { return this; }
     
     bool llvmForceLogging;
+
+    // array ops emitted in this module already
+    StringTable arrayfuncs;
 };
 
 
--- a/gen/toir.cpp	Mon Oct 13 21:08:11 2008 +0200
+++ b/gen/toir.cpp	Mon Oct 13 23:19:32 2008 +0200
@@ -471,15 +471,6 @@
         DtoAssign(loc, &arrval, slice);
         return newlen;
     }
-    else if (e1->op == TOKslice && !ismemset &&
-        (e2->op == TOKadd || e2->op == TOKmin ||
-        e2->op == TOKmul || e2->op == TOKdiv ||
-        e2->op == TOKmod || e2->op == TOKxor ||
-        e2->op == TOKand || e2->op == TOKor  ||
-        e2->op == TOKtilde || e2->op == TOKneg))
-    {
-        assert(0 && "array op assignment is TODO");
-    }
 
     Logger::println("performing normal assignment");
 
--- a/gen/tollvm.cpp	Mon Oct 13 21:08:11 2008 +0200
+++ b/gen/tollvm.cpp	Mon Oct 13 23:19:32 2008 +0200
@@ -280,6 +280,9 @@
         assert(fdecl->type->ty == Tfunction);
         TypeFunction* ft = (TypeFunction*)fdecl->type;
 
+        // array operations are always internal
+        if (fdecl->isArrayOp)
+            return llvm::GlobalValue::InternalLinkage;
         // intrinsics are always external
         if (fdecl->llvmInternal == LLVMintrinsic)
             return llvm::GlobalValue::ExternalLinkage;
--- a/premake.lua	Mon Oct 13 21:08:11 2008 +0200
+++ b/premake.lua	Mon Oct 13 23:19:32 2008 +0200
@@ -31,7 +31,7 @@
 if options["target-override"] then
     TRIPLE = options["target-override"]
 else
-    local p = io.popen("./config.guess")
+    local p = io.popen("sh config.guess")
     TRIPLE = p:read()
 end
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/mini/arrayops1.d	Mon Oct 13 23:19:32 2008 +0200
@@ -0,0 +1,17 @@
+extern(C) int printf(char*, ...);
+
+void main()
+{
+    int[3] a = [1, 2, 3];
+    int[3] b = [4, 5, 6];
+    int[3] c;
+
+    c[] = a[] + b[];
+
+    printf("c.ptr = %p\n", c.ptr);
+    printf("c.length = %lu\n", c.length);
+
+    assert(c[0] == 5);
+    assert(c[1] == 7);
+    assert(c[2] == 9);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/mini/arrayops2.d	Mon Oct 13 23:19:32 2008 +0200
@@ -0,0 +1,10 @@
+void main()
+{
+    int[4] a = [1,2,3,4];
+    int[4] b = [5,6,7,8];
+    a[] += b[];
+    assert(a[0] == 6);
+    assert(a[1] == 8);
+    assert(a[2] == 10);
+    assert(a[3] == 12);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/mini/arrayops3.d	Mon Oct 13 23:19:32 2008 +0200
@@ -0,0 +1,10 @@
+void main()
+{
+    int[4] a = [1,2,3,4];
+    int[4] b = [5,6,7,8];
+    a[] += b[] / 2;
+    assert(a[0] == 3);
+    assert(a[1] == 5);
+    assert(a[2] == 6);
+    assert(a[3] == 8);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/mini/arrayops4.d	Mon Oct 13 23:19:32 2008 +0200
@@ -0,0 +1,29 @@
+void main()
+{
+    auto a = new float[1024];
+    auto b = new float[1024];
+    auto c = new float[1024];
+
+    for (auto i=0; i<1024; i++)
+    {
+        a[i] = i;
+        b[i] = i*2;
+        c[i] = i*4;
+    }
+
+    a[] = b[] + c[] / 2;
+
+    foreach(i,v; a)
+    {
+        assert(eq(v, b[i] + c[i] / 2));
+    }
+}
+
+float abs(float x)
+{
+    return x<0?-x:x;
+}
+bool eq(float a, float b)
+{
+    return abs(a-b) <= float.epsilon;
+}