Mercurial > projects > ldc
diff dmd2/arrayop.c @ 758:f04dde6e882c
Added initial D2 support, D2 frontend and changes to codegen to make things compile.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 11 Nov 2008 01:38:48 +0100 |
parents | |
children | 638d16625da2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd2/arrayop.c Tue Nov 11 01:38:48 2008 +0100 @@ -0,0 +1,494 @@ + +// 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 + +