Mercurial > projects > ddmd
comparison dmd/codegen/Util.d @ 174:af724d3510d7
lot os toCBuffer methods implemented
moved shared Type.* stuff into Global
author | korDen |
---|---|
date | Sun, 10 Oct 2010 03:47:23 +0400 |
parents | 31c086f76669 |
children | 1475fd394c9e |
comparison
equal
deleted
inserted
replaced
173:d237b38b5858 | 174:af724d3510d7 |
---|---|
76 | 76 |
77 | 77 |
78 /************************************ | 78 /************************************ |
79 * Call a function. | 79 * Call a function. |
80 */ | 80 */ |
81 elem* callfunc(Loc loc, | 81 elem* callfunc(Loc loc, |
82 IRState* irs, | 82 IRState* irs, |
83 int directcall, // 1: don't do virtual call | 83 int directcall, // 1: don't do virtual call |
84 Type tret, // return type | 84 Type tret, // return type |
85 elem *ec, // evaluates to function address | 85 elem *ec, // evaluates to function address |
86 Type ectype, // original type of ec | 86 Type ectype, // original type of ec |
122 ethis = el_una(OPER.OP64_32, TYM.TYnptr, ethis); // get this | 122 ethis = el_una(OPER.OP64_32, TYM.TYnptr, ethis); // get this |
123 ec = array_toPtr(t, ec); // get funcptr | 123 ec = array_toPtr(t, ec); // get funcptr |
124 ec = el_una(OPER.OPind, tf.totym(), ec); | 124 ec = el_una(OPER.OPind, tf.totym(), ec); |
125 } | 125 } |
126 else | 126 else |
127 { | 127 { |
128 assert(t.ty == TY.Tfunction); | 128 assert(t.ty == TY.Tfunction); |
129 tf = cast(TypeFunction)t; | 129 tf = cast(TypeFunction)t; |
130 } | 130 } |
131 | 131 |
132 retmethod = tf.retStyle(); | 132 retmethod = tf.retStyle(); |
139 { | 139 { |
140 // j=1 if _arguments[] is first argument | 140 // j=1 if _arguments[] is first argument |
141 int j = (tf.linkage == LINK.LINKd && tf.varargs == 1); | 141 int j = (tf.linkage == LINK.LINKd && tf.varargs == 1); |
142 | 142 |
143 foreach (size_t i, Expression arg; arguments) | 143 foreach (size_t i, Expression arg; arguments) |
144 { | 144 { |
145 elem* ea; | 145 elem* ea; |
146 | 146 |
147 //writef("\targ[%d]: %s\n", i, arg.toChars()); | 147 //writef("\targ[%d]: %s\n", i, arg.toChars()); |
148 | 148 |
149 size_t nparams = Parameter.dim(tf.parameters); | 149 size_t nparams = Parameter.dim(tf.parameters); |
176 } | 176 } |
177 | 177 |
178 if (retmethod == RET.RETstack) | 178 if (retmethod == RET.RETstack) |
179 { | 179 { |
180 if (!ehidden) | 180 if (!ehidden) |
181 { | 181 { |
182 // Don't have one, so create one | 182 // Don't have one, so create one |
183 type* tt; | 183 type* tt; |
184 | 184 |
185 Type tret2 = tf.next; // in dmd tret is shadowed here, so -> tret2 | 185 Type tret2 = tf.next; // in dmd tret is shadowed here, so -> tret2 |
186 if (tret2.toBasetype().ty == Tstruct || | 186 if (tret2.toBasetype().ty == Tstruct || |
334 /************************************** | 334 /************************************** |
335 * Fake a struct symbol. | 335 * Fake a struct symbol. |
336 */ | 336 */ |
337 | 337 |
338 Classsym* fake_classsym(Identifier id) | 338 Classsym* fake_classsym(Identifier id) |
339 { | 339 { |
340 TYPE* t; | 340 TYPE* t; |
341 Classsym* scc; | 341 Classsym* scc; |
342 | 342 |
343 scc = cast(Classsym*)symbol_calloc(toStringz(id.toChars())); | 343 scc = cast(Classsym*)symbol_calloc(toStringz(id.toChars())); |
344 scc.Sclass = SC.SCstruct; | 344 scc.Sclass = SC.SCstruct; |
376 /* These two are compiler generated functions for the in and out contracts, | 376 /* These two are compiler generated functions for the in and out contracts, |
377 * and are called from an overriding function, not just the one they're | 377 * and are called from an overriding function, not just the one they're |
378 * nested inside, so this hack is so they'll pass | 378 * nested inside, so this hack is so they'll pass |
379 */ | 379 */ |
380 fd.ident == Id.require || fd.ident == Id.ensure) | 380 fd.ident == Id.require || fd.ident == Id.ensure) |
381 { | 381 { |
382 /* Going down one nesting level, i.e. we're calling | 382 /* Going down one nesting level, i.e. we're calling |
383 * a nested function from its enclosing function. | 383 * a nested function from its enclosing function. |
384 */ | 384 */ |
385 ///version (DMDV2) { | 385 ///version (DMDV2) { |
386 if (irs.sclosure) | 386 if (irs.sclosure) |
387 ethis = el_var(irs.sclosure); | 387 ethis = el_var(irs.sclosure); |
388 else | 388 else |
389 ///} | 389 ///} |
390 if (irs.sthis) | 390 if (irs.sthis) |
391 { | 391 { |
392 // We have a 'this' pointer for the current function | 392 // We have a 'this' pointer for the current function |
393 ethis = el_var(irs.sthis); | 393 ethis = el_var(irs.sthis); |
394 | 394 |
395 /* If no variables in the current function's frame are | 395 /* If no variables in the current function's frame are |
396 * referenced by nested functions, then we can 'skip' | 396 * referenced by nested functions, then we can 'skip' |
401 bool cond = (thisfd.closureVars.dim != 0); | 401 bool cond = (thisfd.closureVars.dim != 0); |
402 } else { | 402 } else { |
403 bool cond = thisfd.nestedFrameRef; | 403 bool cond = thisfd.nestedFrameRef; |
404 } | 404 } |
405 if (cond) | 405 if (cond) |
406 { | 406 { |
407 /* Local variables are referenced, can't skip. | 407 /* Local variables are referenced, can't skip. |
408 * Address of 'this' gives the 'this' for the nested | 408 * Address of 'this' gives the 'this' for the nested |
409 * function | 409 * function |
410 */ | 410 */ |
411 ethis = el_una(OPER.OPaddr, TYM.TYnptr, ethis); | 411 ethis = el_una(OPER.OPaddr, TYM.TYnptr, ethis); |
412 } | 412 } |
413 } | 413 } |
414 else | 414 else |
415 { | 415 { |
416 /* No 'this' pointer for current function, | 416 /* No 'this' pointer for current function, |
417 * use null if no references to the current function's frame | 417 * use null if no references to the current function's frame |
418 */ | 418 */ |
419 ethis = el_long(TYM.TYnptr, 0); | 419 ethis = el_long(TYM.TYnptr, 0); |
420 version (DMDV2) { | 420 version (DMDV2) { |
421 bool cond = (thisfd.closureVars.dim != 0); | 421 bool cond = (thisfd.closureVars.dim != 0); |
422 } else { | 422 } else { |
423 bool cond = thisfd.nestedFrameRef; | 423 bool cond = thisfd.nestedFrameRef; |
424 } | 424 } |
425 if (cond) | 425 if (cond) |
426 { | 426 { |
427 /* OPframeptr is an operator that gets the frame pointer | 427 /* OPframeptr is an operator that gets the frame pointer |
428 * for the current function, i.e. for the x86 it gets | 428 * for the current function, i.e. for the x86 it gets |
429 * the value of EBP | 429 * the value of EBP |
430 */ | 430 */ |
431 ethis.Eoper = OPER.OPframeptr; | 431 ethis.Eoper = OPER.OPframeptr; |
432 } | 432 } |
433 } | 433 } |
434 | 434 |
435 //if (fdparent != thisfd) ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, 0x18)); | 435 //if (fdparent != thisfd) ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, 0x18)); |
436 } | 436 } |
437 else | 437 else |
438 { | 438 { |
439 if (!irs.sthis) // if no frame pointer for this function | 439 if (!irs.sthis) // if no frame pointer for this function |
444 else | 444 else |
445 { | 445 { |
446 ethis = el_var(irs.sthis); | 446 ethis = el_var(irs.sthis); |
447 Dsymbol s = thisfd; | 447 Dsymbol s = thisfd; |
448 while (fd != s) | 448 while (fd != s) |
449 { | 449 { |
450 /* Go up a nesting level, i.e. we need to find the 'this' | 450 /* Go up a nesting level, i.e. we need to find the 'this' |
451 * of an enclosing function. | 451 * of an enclosing function. |
452 * Our 'enclosing function' may also be an inner class. | 452 * Our 'enclosing function' may also be an inner class. |
453 */ | 453 */ |
454 | 454 |
455 //printf("\ts = '%s'\n", s.toChars()); | 455 //printf("\ts = '%s'\n", s.toChars()); |
456 thisfd = s.isFuncDeclaration(); | 456 thisfd = s.isFuncDeclaration(); |
457 if (thisfd) | 457 if (thisfd) |
458 { | 458 { |
459 /* Enclosing function is a function. | 459 /* Enclosing function is a function. |
460 */ | 460 */ |
461 if (fdparent == s.toParent2()) | 461 if (fdparent == s.toParent2()) |
462 break; | 462 break; |
463 | 463 |
482 // Error should have been caught by front end | 482 // Error should have been caught by front end |
483 assert(0); | 483 assert(0); |
484 } | 484 } |
485 } | 485 } |
486 else | 486 else |
487 { | 487 { |
488 /* Enclosed by an aggregate. That means the current | 488 /* Enclosed by an aggregate. That means the current |
489 * function must be a member function of that aggregate. | 489 * function must be a member function of that aggregate. |
490 */ | 490 */ |
491 ClassDeclaration cd; | 491 ClassDeclaration cd; |
492 StructDeclaration sd; | 492 StructDeclaration sd; |
525 * of frames. | 525 * of frames. |
526 */ | 526 */ |
527 version (DMDV2) { | 527 version (DMDV2) { |
528 bool cond = (fdd.closureVars.dim != 0); | 528 bool cond = (fdd.closureVars.dim != 0); |
529 } else { | 529 } else { |
530 bool cond = fdd.nestedFrameRef; | 530 bool cond = fdd.nestedFrameRef; |
531 } | 531 } |
532 if (cond) { | 532 if (cond) { |
533 ethis = el_una(OPER.OPind, TYM.TYnptr, ethis); | 533 ethis = el_una(OPER.OPind, TYM.TYnptr, ethis); |
534 } | 534 } |
535 break; | 535 break; |
656 //extern (C++) extern int intrinsic_op(char* name); | 656 //extern (C++) extern int intrinsic_op(char* name); |
657 | 657 |
658 OPER intrinsic_oper(const(char)* name) | 658 OPER intrinsic_oper(const(char)* name) |
659 { | 659 { |
660 version(DMDV1) | 660 version(DMDV1) |
661 static const(char) *namearray[] = | 661 enum const(char) *namearray[] = |
662 [ | 662 [ |
663 "4math3cosFeZe", | 663 "4math3cosFeZe", |
664 "4math3sinFeZe", | 664 "4math3sinFeZe", |
665 "4math4fabsFeZe", | 665 "4math4fabsFeZe", |
666 "4math4rintFeZe", | 666 "4math4rintFeZe", |
685 "9intrinsic5bswapFkZk", | 685 "9intrinsic5bswapFkZk", |
686 "9intrinsic5outplFkkZk", | 686 "9intrinsic5outplFkkZk", |
687 "9intrinsic5outpwFktZt", | 687 "9intrinsic5outpwFktZt", |
688 ]; | 688 ]; |
689 else | 689 else |
690 static const(char) *namearray[] = | 690 enum const(char) *namearray[] = |
691 [ | 691 [ |
692 /* The names are mangled differently because of the pure and | 692 /* The names are mangled differently because of the pure and |
693 * nothrow attributes. | 693 * nothrow attributes. |
694 */ | 694 */ |
695 "4math3cosFNaNbNfeZe", | 695 "4math3cosFNaNbNfeZe", |
717 "9intrinsic5bswapFNaNbkZk", | 717 "9intrinsic5bswapFNaNbkZk", |
718 "9intrinsic5outplFNbkkZk", | 718 "9intrinsic5outplFNbkkZk", |
719 "9intrinsic5outpwFNbktZt", | 719 "9intrinsic5outpwFNbktZt", |
720 ]; | 720 ]; |
721 | 721 |
722 static const OPER ioptab[] = | 722 enum OPER ioptab[] = |
723 [ | 723 [ |
724 OPcos, | 724 OPcos, |
725 OPsin, | 725 OPsin, |
726 OPabs, | 726 OPabs, |
727 OPrint, | 727 OPrint, |
746 OPbswap, | 746 OPbswap, |
747 OPoutp, | 747 OPoutp, |
748 OPoutp, | 748 OPoutp, |
749 ]; | 749 ]; |
750 | 750 |
751 debug | 751 debug |
752 { | 752 { |
753 assert(namearray.length == ioptab.length); | 753 assert(namearray.length == ioptab.length); |
754 // assume sorted namearray | 754 // assume sorted namearray |
755 for (int i = 0; i < namearray.length - 1; i++) | 755 for (int i = 0; i < namearray.length - 1; i++) |
756 { | 756 { |
843 } | 843 } |
844 } | 844 } |
845 else if ((td = s.isTupleDeclaration()) !is null) | 845 else if ((td = s.isTupleDeclaration()) !is null) |
846 { | 846 { |
847 for (size_t i = 0; i < td.objects.dim; i++) | 847 for (size_t i = 0; i < td.objects.dim; i++) |
848 { | 848 { |
849 auto o = td.objects[i]; | 849 auto o = td.objects[i]; |
850 ///if (o.dyncast() == DYNCAST_EXPRESSION) | 850 ///if (o.dyncast() == DYNCAST_EXPRESSION) |
851 if (auto eo = cast(Expression)o) | 851 if (auto eo = cast(Expression)o) |
852 { | 852 { |
853 if (eo.op == TOK.TOKdsymbol) | 853 if (eo.op == TOK.TOKdsymbol) |
854 { | 854 { |
855 auto se = cast(DsymbolExp)eo; | 855 auto se = cast(DsymbolExp)eo; |
856 e = el_combine(e, Dsymbol_toElem(se.s, irs)); | 856 e = el_combine(e, Dsymbol_toElem(se.s, irs)); |
857 } | 857 } |
858 } | 858 } |
859 } | 859 } |
883 { | 883 { |
884 //printf("resolveLengthVar()\n"); | 884 //printf("resolveLengthVar()\n"); |
885 elem* einit = null; | 885 elem* einit = null; |
886 | 886 |
887 if (lengthVar && !(lengthVar.storage_class & STC.STCconst)) | 887 if (lengthVar && !(lengthVar.storage_class & STC.STCconst)) |
888 { | 888 { |
889 elem* elength; | 889 elem* elength; |
890 Symbol* slength; | 890 Symbol* slength; |
891 | 891 |
892 if (t1.ty == TY.Tsarray) | 892 if (t1.ty == TY.Tsarray) |
893 { | 893 { |
894 TypeSArray tsa = cast(TypeSArray)t1; | 894 TypeSArray tsa = cast(TypeSArray)t1; |
895 long length = tsa.dim.toInteger(); | 895 long length = tsa.dim.toInteger(); |
896 | 896 |
897 elength = el_long(TYM.TYuint, length); | 897 elength = el_long(TYM.TYuint, length); |
898 goto L3; | 898 goto L3; |
921 * evalue value to write | 921 * evalue value to write |
922 * edim number of times to write evalue to eptr[] | 922 * edim number of times to write evalue to eptr[] |
923 * tb type of evalue | 923 * tb type of evalue |
924 */ | 924 */ |
925 elem* setArray(elem* eptr, elem* edim, Type tb, elem* evalue, IRState* irs, int op) | 925 elem* setArray(elem* eptr, elem* edim, Type tb, elem* evalue, IRState* irs, int op) |
926 { | 926 { |
927 int r; | 927 int r; |
928 elem* e; | 928 elem* e; |
929 int sz = cast(int)tb.size(); | 929 int sz = cast(int)tb.size(); |
930 | 930 |
931 if (tb.ty == TY.Tfloat80 || tb.ty == TY.Timaginary80) | 931 if (tb.ty == TY.Tfloat80 || tb.ty == TY.Timaginary80) |
949 */ | 949 */ |
950 if (op != TOK.TOKblit) | 950 if (op != TOK.TOKblit) |
951 { | 951 { |
952 StructDeclaration sd = needsPostblit(tb); | 952 StructDeclaration sd = needsPostblit(tb); |
953 if (sd) | 953 if (sd) |
954 { | 954 { |
955 /* Need to do postblit. | 955 /* Need to do postblit. |
956 * void *_d_arraysetassign(void *p, void *value, int dim, TypeInfo ti); | 956 * void *_d_arraysetassign(void *p, void *value, int dim, TypeInfo ti); |
957 */ | 957 */ |
958 r = (op == TOK.TOKconstruct) ? RTLSYM.RTLSYM_ARRAYSETCTOR : RTLSYM.RTLSYM_ARRAYSETASSIGN; | 958 r = (op == TOK.TOKconstruct) ? RTLSYM.RTLSYM_ARRAYSETCTOR : RTLSYM.RTLSYM_ARRAYSETASSIGN; |
959 evalue = el_una(OPER.OPaddr, TYM.TYnptr, evalue); | 959 evalue = el_una(OPER.OPaddr, TYM.TYnptr, evalue); |
1017 Dsymbol cdp = ad.toParent2(); // class/func we're nested in | 1017 Dsymbol cdp = ad.toParent2(); // class/func we're nested in |
1018 | 1018 |
1019 //printf("setEthis(ad = %s, cdp = %s, thisfd = %s)\n", ad.toChars(), cdp.toChars(), thisfd.toChars()); | 1019 //printf("setEthis(ad = %s, cdp = %s, thisfd = %s)\n", ad.toChars(), cdp.toChars(), thisfd.toChars()); |
1020 | 1020 |
1021 if (cdp is thisfd) | 1021 if (cdp is thisfd) |
1022 { | 1022 { |
1023 /* Class we're new'ing is a local class in this function: | 1023 /* Class we're new'ing is a local class in this function: |
1024 * void thisfd() { class ad { } } | 1024 * void thisfd() { class ad { } } |
1025 */ | 1025 */ |
1026 if (irs.sclosure) | 1026 if (irs.sclosure) |
1027 ethis = el_var(irs.sclosure); | 1027 ethis = el_var(irs.sclosure); |
1055 cdp == thisfd.toParent2() || ( | 1055 cdp == thisfd.toParent2() || ( |
1056 cdp.isClassDeclaration() && cdp.isClassDeclaration().isBaseOf(thisfd.toParent2().isClassDeclaration(), &offset) | 1056 cdp.isClassDeclaration() && cdp.isClassDeclaration().isBaseOf(thisfd.toParent2().isClassDeclaration(), &offset) |
1057 ) | 1057 ) |
1058 ) | 1058 ) |
1059 ) | 1059 ) |
1060 { | 1060 { |
1061 /* Class we're new'ing is at the same level as thisfd | 1061 /* Class we're new'ing is at the same level as thisfd |
1062 */ | 1062 */ |
1063 assert(offset == 0); // BUG: should handle this case | 1063 assert(offset == 0); // BUG: should handle this case |
1064 ethis = el_var(irs.sthis); | 1064 ethis = el_var(irs.sthis); |
1065 } | 1065 } |
1086 | 1086 |
1087 while (t.ty == TY.Tsarray) | 1087 while (t.ty == TY.Tsarray) |
1088 t = t.nextOf().toBasetype(); | 1088 t = t.nextOf().toBasetype(); |
1089 | 1089 |
1090 if (t.ty == TY.Tstruct) | 1090 if (t.ty == TY.Tstruct) |
1091 { | 1091 { |
1092 StructDeclaration sd = (cast(TypeStruct)t).sym; | 1092 StructDeclaration sd = (cast(TypeStruct)t).sym; |
1093 if (sd.postblit) | 1093 if (sd.postblit) |
1094 return sd; | 1094 return sd; |
1095 } | 1095 } |
1096 | 1096 |
1130 size_t len = tysize[tybasic(e.Ety)]; | 1130 size_t len = tysize[tybasic(e.Ety)]; |
1131 elem* es = el_calloc(); | 1131 elem* es = el_calloc(); |
1132 es.Eoper = OPER.OPstring; | 1132 es.Eoper = OPER.OPstring; |
1133 | 1133 |
1134 // Match MEM_PH_FREE for OPstring in ztc\el.c | 1134 // Match MEM_PH_FREE for OPstring in ztc\el.c |
1135 es.EV.ss.Vstring = cast(char*)malloc(len); /// ! | 1135 es.EV.ss.Vstring = cast(char*)GC.malloc(len); /// ! |
1136 memcpy(es.EV.ss.Vstring, &e.EV, len); | 1136 memcpy(es.EV.ss.Vstring, &e.EV, len); |
1137 | 1137 |
1138 es.EV.ss.Vstrlen = len; | 1138 es.EV.ss.Vstrlen = len; |
1139 es.Ety = TYM.TYnptr; | 1139 es.Ety = TYM.TYnptr; |
1140 e = es; | 1140 e = es; |
1274 return null; | 1274 return null; |
1275 } | 1275 } |
1276 | 1276 |
1277 s = label.statement; | 1277 s = label.statement; |
1278 if (!s.lblock) | 1278 if (!s.lblock) |
1279 { | 1279 { |
1280 s.lblock = block_calloc(blx); | 1280 s.lblock = block_calloc(blx); |
1281 if (s.isReturnLabel) | 1281 if (s.isReturnLabel) |
1282 s.lblock.Btry = null; | 1282 s.lblock.Btry = null; |
1283 } | 1283 } |
1284 return s.lblock; | 1284 return s.lblock; |
1291 * tries to use aligned int stores whereever possible. | 1291 * tries to use aligned int stores whereever possible. |
1292 * Update *poffset to end of initialized hole; *poffset will be >= offset2. | 1292 * Update *poffset to end of initialized hole; *poffset will be >= offset2. |
1293 */ | 1293 */ |
1294 | 1294 |
1295 elem* fillHole(Symbol* stmp, size_t* poffset, size_t offset2, size_t maxoff) | 1295 elem* fillHole(Symbol* stmp, size_t* poffset, size_t offset2, size_t maxoff) |
1296 { | 1296 { |
1297 elem* e = null; | 1297 elem* e = null; |
1298 int basealign = 1; | 1298 int basealign = 1; |
1299 | 1299 |
1300 while (*poffset < offset2) | 1300 while (*poffset < offset2) |
1301 { | 1301 { |
1302 tym_t ty; | 1302 tym_t ty; |
1303 elem* e1; | 1303 elem* e1; |
1304 | 1304 |
1305 if (tybasic(stmp.Stype.Tty) == TYnptr) | 1305 if (tybasic(stmp.Stype.Tty) == TYnptr) |
1306 e1 = el_var(stmp); | 1306 e1 = el_var(stmp); |
1307 else | 1307 else |
1308 e1 = el_ptr(stmp); | 1308 e1 = el_ptr(stmp); |
1309 | 1309 |
1310 if (basealign) | 1310 if (basealign) |
1311 *poffset &= ~3; | 1311 *poffset &= ~3; |
1312 | 1312 |
1313 basealign = 1; | 1313 basealign = 1; |
1314 size_t sz = maxoff - *poffset; | 1314 size_t sz = maxoff - *poffset; |
1315 switch (sz) | 1315 switch (sz) |
1316 { | 1316 { |
1317 case 1: ty = TYchar; break; | 1317 case 1: ty = TYchar; break; |
1318 case 2: ty = TYshort; break; | 1318 case 2: ty = TYshort; break; |
1319 case 3: | 1319 case 3: |
1320 ty = TYshort; | 1320 ty = TYshort; |
1321 basealign = 0; | 1321 basealign = 0; |