Mercurial > projects > ldc
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 + +