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