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