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