root/trunk/rebuild/arrayop.c

Revision 915, 14.0 kB (checked in by Gregor, 3 months ago)

MERGE: dmdfe-2.0 r914 (DMD 2.019)

  • Property svn:eol-style set to native
Line 
1 // Copyright (c) 1999-2008 by Digital Mars
2 // All Rights Reserved
3 // written by Walter Bright
4 // http://www.digitalmars.com
5 // License for redistribution is by either the Artistic License
6 // in artistic.txt, or the GNU General Public License in gnu.txt.
7 // See the included readme.txt for details.
8
9 #include <stdio.h>
10 #include <string.h>
11 #include <assert.h>
12
13 #include "mem.h"
14
15 #include "stringtable.h"
16
17 #include "expression.h"
18 #include "statement.h"
19 #include "mtype.h"
20 #include "declaration.h"
21 #include "scope.h"
22 #include "id.h"
23 #include "module.h"
24 #include "init.h"
25
26 extern int binary(const char *p , const char **tab, int high);
27
28 /**************************************
29  * Hash table of array op functions already generated or known about.
30  */
31
32 StringTable arrayfuncs;
33
34 /***********************************
35  * Construct the array operation expression.
36  */
37
38 Expression *BinExp::arrayOp(Scope *sc)
39 {
40     Expressions *arguments = new Expressions();
41
42     /* The expression to generate an array operation for is mangled
43      * into a name to use as the array operation function name.
44      * Mangle in the operands and operators in RPN order, and type.
45      */
46     OutBuffer buf;
47     buf.writestring("_array");
48     buildArrayIdent(&buf, arguments);
49     buf.writeByte('_');
50
51     /* Append deco of array element type
52      */
53 #if V2
54     buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
55 #else
56     buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
57 #endif
58
59     size_t namelen = buf.offset;
60     buf.writeByte(0);
61     char *name = (char *)buf.extractData();
62
63     /* Look up name in hash table
64      */
65     StringValue *sv = arrayfuncs.update(name, namelen);
66     FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue;
67     if (!fd)
68     {
69     /* Some of the array op functions are written as library functions,
70      * presumably to optimize them with special CPU vector instructions.
71      * List those library functions here, in alpha order.
72      */
73     static const char *libArrayopFuncs[] =
74     {
75         "_arrayExpSliceAddass_a",
76         "_arrayExpSliceAddass_d",       // T[]+=T
77         "_arrayExpSliceAddass_f",       // T[]+=T
78         "_arrayExpSliceAddass_g",
79         "_arrayExpSliceAddass_h",
80         "_arrayExpSliceAddass_i",
81         "_arrayExpSliceAddass_k",
82         "_arrayExpSliceAddass_s",
83         "_arrayExpSliceAddass_t",
84         "_arrayExpSliceAddass_u",
85         "_arrayExpSliceAddass_w",
86
87         "_arrayExpSliceDivass_d",       // T[]/=T
88         "_arrayExpSliceDivass_f",       // T[]/=T
89
90         "_arrayExpSliceMinSliceAssign_a",
91         "_arrayExpSliceMinSliceAssign_d",   // T[]=T-T[]
92         "_arrayExpSliceMinSliceAssign_f",   // T[]=T-T[]
93         "_arrayExpSliceMinSliceAssign_g",
94         "_arrayExpSliceMinSliceAssign_h",
95         "_arrayExpSliceMinSliceAssign_i",
96         "_arrayExpSliceMinSliceAssign_k",
97         "_arrayExpSliceMinSliceAssign_s",
98         "_arrayExpSliceMinSliceAssign_t",
99         "_arrayExpSliceMinSliceAssign_u",
100         "_arrayExpSliceMinSliceAssign_w",
101
102         "_arrayExpSliceMinass_a",
103         "_arrayExpSliceMinass_d",       // T[]-=T
104         "_arrayExpSliceMinass_f",       // T[]-=T
105         "_arrayExpSliceMinass_g",
106         "_arrayExpSliceMinass_h",
107         "_arrayExpSliceMinass_i",
108         "_arrayExpSliceMinass_k",
109         "_arrayExpSliceMinass_s",
110         "_arrayExpSliceMinass_t",
111         "_arrayExpSliceMinass_u",
112         "_arrayExpSliceMinass_w",
113
114         "_arrayExpSliceMulass_d",       // T[]*=T
115         "_arrayExpSliceMulass_f",       // T[]*=T
116         "_arrayExpSliceMulass_i",
117         "_arrayExpSliceMulass_k",
118         "_arrayExpSliceMulass_s",
119         "_arrayExpSliceMulass_t",
120         "_arrayExpSliceMulass_u",
121         "_arrayExpSliceMulass_w",
122
123         "_arraySliceExpAddSliceAssign_a",
124         "_arraySliceExpAddSliceAssign_d",   // T[]=T[]+T
125         "_arraySliceExpAddSliceAssign_f",   // T[]=T[]+T
126         "_arraySliceExpAddSliceAssign_g",
127         "_arraySliceExpAddSliceAssign_h",
128         "_arraySliceExpAddSliceAssign_i",
129         "_arraySliceExpAddSliceAssign_k",
130         "_arraySliceExpAddSliceAssign_s",
131         "_arraySliceExpAddSliceAssign_t",
132         "_arraySliceExpAddSliceAssign_u",
133         "_arraySliceExpAddSliceAssign_w",
134
135         "_arraySliceExpDivSliceAssign_d",   // T[]=T[]/T
136         "_arraySliceExpDivSliceAssign_f",   // T[]=T[]/T
137
138         "_arraySliceExpMinSliceAssign_a",
139         "_arraySliceExpMinSliceAssign_d",   // T[]=T[]-T
140         "_arraySliceExpMinSliceAssign_f",   // T[]=T[]-T
141         "_arraySliceExpMinSliceAssign_g",
142         "_arraySliceExpMinSliceAssign_h",
143         "_arraySliceExpMinSliceAssign_i",
144         "_arraySliceExpMinSliceAssign_k",
145         "_arraySliceExpMinSliceAssign_s",
146         "_arraySliceExpMinSliceAssign_t",
147         "_arraySliceExpMinSliceAssign_u",
148         "_arraySliceExpMinSliceAssign_w",
149
150         "_arraySliceExpMulSliceAddass_d",   // T[] += T[]*T
151         "_arraySliceExpMulSliceAddass_f",
152         "_arraySliceExpMulSliceAddass_r",
153
154         "_arraySliceExpMulSliceAssign_d",   // T[]=T[]*T
155         "_arraySliceExpMulSliceAssign_f",   // T[]=T[]*T
156         "_arraySliceExpMulSliceAssign_i",
157         "_arraySliceExpMulSliceAssign_k",
158         "_arraySliceExpMulSliceAssign_s",
159         "_arraySliceExpMulSliceAssign_t",
160         "_arraySliceExpMulSliceAssign_u",
161         "_arraySliceExpMulSliceAssign_w",
162
163         "_arraySliceExpMulSliceMinass_d",   // T[] -= T[]*T
164         "_arraySliceExpMulSliceMinass_f",
165         "_arraySliceExpMulSliceMinass_r",
166
167         "_arraySliceSliceAddSliceAssign_a",
168         "_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[]
169         "_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[]
170         "_arraySliceSliceAddSliceAssign_g",
171         "_arraySliceSliceAddSliceAssign_h",
172         "_arraySliceSliceAddSliceAssign_i",
173         "_arraySliceSliceAddSliceAssign_k",
174         "_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[]
175         "_arraySliceSliceAddSliceAssign_s",
176         "_arraySliceSliceAddSliceAssign_t",
177         "_arraySliceSliceAddSliceAssign_u",
178         "_arraySliceSliceAddSliceAssign_w",
179
180         "_arraySliceSliceAddass_a",
181         "_arraySliceSliceAddass_d",     // T[]+=T[]
182         "_arraySliceSliceAddass_f",     // T[]+=T[]
183         "_arraySliceSliceAddass_g",
184         "_arraySliceSliceAddass_h",
185         "_arraySliceSliceAddass_i",
186         "_arraySliceSliceAddass_k",
187         "_arraySliceSliceAddass_s",
188         "_arraySliceSliceAddass_t",
189         "_arraySliceSliceAddass_u",
190         "_arraySliceSliceAddass_w",
191
192         "_arraySliceSliceMinSliceAssign_a",
193         "_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[]
194         "_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[]
195         "_arraySliceSliceMinSliceAssign_g",
196         "_arraySliceSliceMinSliceAssign_h",
197         "_arraySliceSliceMinSliceAssign_i",
198         "_arraySliceSliceMinSliceAssign_k",
199         "_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[]
200         "_arraySliceSliceMinSliceAssign_s",
201         "_arraySliceSliceMinSliceAssign_t",
202         "_arraySliceSliceMinSliceAssign_u",
203         "_arraySliceSliceMinSliceAssign_w",
204
205         "_arraySliceSliceMinass_a",
206         "_arraySliceSliceMinass_d",     // T[]-=T[]
207         "_arraySliceSliceMinass_f",     // T[]-=T[]
208         "_arraySliceSliceMinass_g",
209         "_arraySliceSliceMinass_h",
210         "_arraySliceSliceMinass_i",
211         "_arraySliceSliceMinass_k",
212         "_arraySliceSliceMinass_s",
213         "_arraySliceSliceMinass_t",
214         "_arraySliceSliceMinass_u",
215         "_arraySliceSliceMinass_w",
216
217         "_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[]
218         "_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[]
219         "_arraySliceSliceMulSliceAssign_i",
220         "_arraySliceSliceMulSliceAssign_k",
221         "_arraySliceSliceMulSliceAssign_s",
222         "_arraySliceSliceMulSliceAssign_t",
223         "_arraySliceSliceMulSliceAssign_u",
224         "_arraySliceSliceMulSliceAssign_w",
225
226         "_arraySliceSliceMulass_d",     // T[]*=T[]
227         "_arraySliceSliceMulass_f",     // T[]*=T[]
228         "_arraySliceSliceMulass_i",
229         "_arraySliceSliceMulass_k",
230         "_arraySliceSliceMulass_s",
231         "_arraySliceSliceMulass_t",
232         "_arraySliceSliceMulass_u",
233         "_arraySliceSliceMulass_w",
234     };
235
236     //int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *));
237         int i = -1;
238     if (i == -1)
239     {
240 #ifdef DEBUG    // Make sure our array is alphabetized
241         for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++)
242         {
243         if (strcmp(name, libArrayopFuncs[i]) == 0)
244             assert(0);
245         }
246 #endif
247         /* Not in library, so generate it.
248          * Construct the function body:
249          *  foreach (i; 0 .. p.length)    for (size_t i = 0; i < p.length; i++)
250          *      loopbody;
251          *  return p;
252          */
253
254         Arguments *fparams = new Arguments();
255         Expression *loopbody = buildArrayLoop(fparams);
256         Argument *p = (Argument *)fparams->data[0 /*fparams->dim - 1*/];
257 #if V1
258         // for (size_t i = 0; i < p.length; i++)
259         Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
260         Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
261         Statement *s1 = new ForStatement(0,
262         new DeclarationStatement(0, d),
263         new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
264         new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
265         new ExpStatement(0, loopbody));
266 #else
267         // foreach (i; 0 .. p.length)
268         Statement *s1 = new ForeachRangeStatement(0, TOKforeach,
269         new Argument(0, NULL, Id::p, NULL),
270         new IntegerExp(0, 0, Type::tint32),
271         new ArrayLengthExp(0, new IdentifierExp(0, p->ident)),
272         new ExpStatement(0, loopbody));
273 #endif
274         Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident));
275         //printf("s2: %s\n", s2->toChars());
276         Statement *fbody = new CompoundStatement(0, s1, s2);
277
278         /* Construct the function
279          */
280         TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
281         //printf("ftype: %s\n", ftype->toChars());
282         fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype);
283         fd->fbody = fbody;
284         fd->protection = PROTpublic;
285         fd->linkage = LINKc;
286
287         sc->module->importedFrom->members->push(fd);
288
289         sc = sc->push();
290         sc->parent = sc->module->importedFrom;
291         sc->stc = 0;
292         sc->linkage = LINKc;
293         fd->semantic(sc);
294         sc->pop();
295     }
296     else
297     {   /* In library, refer to it.
298          */
299         fd = FuncDeclaration::genCfunc(type, name);
300     }
301     sv->ptrvalue = fd;  // cache symbol in hash table
302     }
303
304     /* Call the function fd(arguments)
305      */
306     Expression *ec = new VarExp(0, fd);
307     Expression *e = new CallExp(loc, ec, arguments);
308     e->type = type;
309     return e;
310 }
311
312 /******************************************
313  * Construct the identifier for the array operation function,
314  * and build the argument list to pass to it.
315  */
316
317 void Expression::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
318 {
319     buf->writestring("Exp");
320     arguments->shift(this);
321 }
322
323 void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
324 {
325     buf->writestring("Slice");
326     arguments->shift(this);
327 }
328
329 void AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
330 {
331     /* Evaluate assign expressions right to left
332      */
333     e2->buildArrayIdent(buf, arguments);
334     e1->buildArrayIdent(buf, arguments);
335     buf->writestring("Assign");
336 }
337
338 #define X(Str) \
339 void Str##AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
340 {                           \
341     /* Evaluate assign expressions right to left    \
342      */                         \
343     e2->buildArrayIdent(buf, arguments);        \
344     e1->buildArrayIdent(buf, arguments);        \
345     buf->writestring(#Str);             \
346     buf->writestring("ass");                \
347 }
348
349 X(Add)
350 X(Min)
351 X(Mul)
352 X(Div)
353 X(Mod)
354 X(Xor)
355 X(And)
356 X(Or)
357
358 #undef X
359
360 void NegExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
361 {
362     e1->buildArrayIdent(buf, arguments);
363     buf->writestring("Neg");
364 }
365
366 void ComExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
367 {
368     e1->buildArrayIdent(buf, arguments);
369     buf->writestring("Com");
370 }
371
372 #define X(Str) \
373 void Str##Exp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)  \
374 {                                   \
375     /* Evaluate assign expressions left to right            \
376      */                                 \
377     e1->buildArrayIdent(buf, arguments);                \
378     e2->buildArrayIdent(buf, arguments);                \
379     buf->writestring(#Str);                     \
380 }
381
382 X(Add)
383 X(Min)
384 X(Mul)
385 X(Div)
386 X(Mod)
387 X(Xor)
388 X(And)
389 X(Or)
390
391 #undef X
392
393 /******************************************
394  * Construct the inner loop for the array operation function,
395  * and build the parameter list.
396  */
397
398 Expression *Expression::buildArrayLoop(Arguments *fparams)
399 {
400     Identifier *id = Identifier::generateId("c", fparams->dim);
401     Argument *param = new Argument(0, type, id, NULL);
402     fparams->shift(param);
403     Expression *e = new IdentifierExp(0, id);
404     return e;
405 }
406
407 Expression *SliceExp::buildArrayLoop(Arguments *fparams)
408 {
409     Identifier *id = Identifier::generateId("p", fparams->dim);
410     Argument *param = new Argument(STCconst, type, id, NULL);
411     fparams->shift(param);
412     Expression *e = new IdentifierExp(0, id);
413     Expressions *arguments = new Expressions();
414     Expression *index = new IdentifierExp(0, Id::p);
415     arguments->push(index);
416     e = new ArrayExp(0, e, arguments);
417     return e;
418 }
419
420 Expression *AssignExp::buildArrayLoop(Arguments *fparams)
421 {
422     /* Evaluate assign expressions right to left
423      */
424     Expression *ex2 = e2->buildArrayLoop(fparams);
425     Expression *ex1 = e1->buildArrayLoop(fparams);
426     Argument *param = (Argument *)fparams->data[0];
427     param->storageClass = 0;
428     Expression *e = new AssignExp(0, ex1, ex2);
429     return e;
430 }
431
432 #define X(Str) \
433 Expression *Str##AssignExp::buildArrayLoop(Arguments *fparams)  \
434 {                               \
435     /* Evaluate assign expressions right to left        \
436      */                             \
437     Expression *ex2 = e2->buildArrayLoop(fparams);      \
438     Expression *ex1 = e1->buildArrayLoop(fparams);      \
439     Argument *param = (Argument *)fparams->data[0];     \
440     param->storageClass = 0;                    \
441     Expression *e = new Str##AssignExp(0, ex1, ex2);        \
442     return e;                           \
443 }
444
445 X(Add)
446 X(Min)
447 X(Mul)
448 X(Div)
449 X(Mod)
450 X(Xor)
451 X(And)
452 X(Or)
453
454 #undef X
455
456 Expression *NegExp::buildArrayLoop(Arguments *fparams)
457 {
458     Expression *ex1 = e1->buildArrayLoop(fparams);
459     Expression *e = new NegExp(0, ex1);
460     return e;
461 }
462
463 Expression *ComExp::buildArrayLoop(Arguments *fparams)
464 {
465     Expression *ex1 = e1->buildArrayLoop(fparams);
466     Expression *e = new ComExp(0, ex1);
467     return e;
468 }
469
470 #define X(Str) \
471 Expression *Str##Exp::buildArrayLoop(Arguments *fparams)    \
472 {                               \
473     /* Evaluate assign expressions left to right        \
474      */                             \
475     Expression *ex1 = e1->buildArrayLoop(fparams);      \
476     Expression *ex2 = e2->buildArrayLoop(fparams);      \
477     Expression *e = new Str##Exp(0, ex1, ex2);          \
478     return e;                           \
479 }
480
481 X(Add)
482 X(Min)
483 X(Mul)
484 X(Div)
485 X(Mod)
486 X(Xor)
487 X(And)
488 X(Or)
489
490 #undef X
Note: See TracBrowser for help on using the browser.