comparison dmd2/statement.c @ 1577:e4f7b5d9c68a

DMD 2.032 Merge.
author Robert Clipsham <robert@octarineparrot.com>
date Tue, 08 Sep 2009 10:07:56 +0100
parents 54b3c1394d62
children 1dee66f6ec0b
comparison
equal deleted inserted replaced
1576:4551475bc6b6 1577:e4f7b5d9c68a
27 #include "hdrgen.h" 27 #include "hdrgen.h"
28 #include "parse.h" 28 #include "parse.h"
29 #include "template.h" 29 #include "template.h"
30 #include "attrib.h" 30 #include "attrib.h"
31 31
32 #if IN_LLVM
33 #include "gen/tollvm.h"
34 #elif IN_DMD
35 extern int os_critsecsize();
36 #endif
37
32 /******************************** Statement ***************************/ 38 /******************************** Statement ***************************/
33 39
34 Statement::Statement(Loc loc) 40 Statement::Statement(Loc loc)
35 : loc(loc) 41 : loc(loc)
36 { 42 {
180 { 186 {
181 return NULL; 187 return NULL;
182 } 188 }
183 189
184 190
191 /******************************** PeelStatement ***************************/
192
193 PeelStatement::PeelStatement(Statement *s)
194 : Statement(s->loc)
195 {
196 this->s = s;
197 }
198
199 Statement *PeelStatement::semantic(Scope *sc)
200 {
201 /* "peel" off this wrapper, and don't run semantic()
202 * on the result.
203 */
204 return s;
205 }
206
185 /******************************** ExpStatement ***************************/ 207 /******************************** ExpStatement ***************************/
186 208
187 ExpStatement::ExpStatement(Loc loc, Expression *exp) 209 ExpStatement::ExpStatement(Loc loc, Expression *exp)
188 : Statement(loc) 210 : Statement(loc)
189 { 211 {
342 364
343 e = v->callAutoDtor(sc); 365 e = v->callAutoDtor(sc);
344 if (e) 366 if (e)
345 { 367 {
346 //printf("dtor is: "); e->print(); 368 //printf("dtor is: "); e->print();
369 #if 0
370 if (v->type->toBasetype()->ty == Tstruct)
371 { /* Need a 'gate' to turn on/off destruction,
372 * in case v gets moved elsewhere.
373 */
374 Identifier *id = Lexer::uniqueId("__runDtor");
375 ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(1));
376 VarDeclaration *rd = new VarDeclaration(loc, Type::tint32, id, ie);
377 *sentry = new DeclarationStatement(loc, rd);
378 v->rundtor = rd;
379
380 /* Rewrite e as:
381 * rundtor && e
382 */
383 Expression *ve = new VarExp(loc, v->rundtor);
384 e = new AndAndExp(loc, ve, e);
385 e->type = Type::tbool;
386 }
387 #endif
347 *sfinally = new ExpStatement(loc, e); 388 *sfinally = new ExpStatement(loc, e);
348 } 389 }
349 } 390 }
350 } 391 }
351 } 392 }
416 457
417 s->scopeCode(sc, &sentry, &sexception, &sfinally); 458 s->scopeCode(sc, &sentry, &sexception, &sfinally);
418 if (sentry) 459 if (sentry)
419 { 460 {
420 sentry = sentry->semantic(sc); 461 sentry = sentry->semantic(sc);
421 statements->data[i] = sentry; 462 if (s->isDeclarationStatement())
463 { statements->insert(i, sentry);
464 i++;
465 }
466 else
467 statements->data[i] = sentry;
422 } 468 }
423 if (sexception) 469 if (sexception)
424 { 470 {
425 if (i + 1 == statements->dim && !sfinally) 471 if (i + 1 == statements->dim && !sfinally)
426 { 472 {
560 { 606 {
561 //printf("result = x%x\n", result); 607 //printf("result = x%x\n", result);
562 //printf("%s\n", s->toChars()); 608 //printf("%s\n", s->toChars());
563 if (!(result & BEfallthru) && !s->comeFrom()) 609 if (!(result & BEfallthru) && !s->comeFrom())
564 { 610 {
565 s->warning("statement is not reachable"); 611 if (s->blockExit() != BEhalt)
612 s->warning("statement is not reachable");
566 } 613 }
567 614
568 result &= ~BEfallthru; 615 result &= ~BEfallthru;
569 result |= s->blockExit(); 616 result |= s->blockExit();
570 } 617 }
907 } 954 }
908 955
909 956
910 Statement *WhileStatement::semantic(Scope *sc) 957 Statement *WhileStatement::semantic(Scope *sc)
911 { 958 {
912 #if 0 959 /* Rewrite as a for(;condition;) loop
913 if (condition->op == TOKmatch) 960 */
914 { 961
915 /* Rewrite while (condition) body as: 962 Statement *s = new ForStatement(loc, NULL, condition, NULL, body);
916 * if (condition) 963 s = s->semantic(sc);
917 * do 964 return s;
918 * body
919 * while ((_match = _match.opNext), _match);
920 */
921
922 Expression *ew = new IdentifierExp(0, Id::_match);
923 ew = new DotIdExp(0, ew, Id::next);
924 ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew);
925 ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0));
926 Expression *ev = new IdentifierExp(0, Id::_match);
927 //ev = new CastExp(0, ev, Type::tvoidptr);
928 ew = new CommaExp(0, ew, ev);
929 Statement *sw = new DoStatement(loc, body, ew);
930 Statement *si = new IfStatement(loc, condition, sw, NULL);
931 return si->semantic(sc);
932 }
933 #endif
934
935 condition = condition->semantic(sc);
936 condition = resolveProperties(sc, condition);
937 condition = condition->optimize(WANTvalue);
938 condition = condition->checkToBoolean();
939
940 sc->noctor++;
941
942 Scope *scd = sc->push();
943 scd->sbreak = this;
944 scd->scontinue = this;
945 if (body)
946 body = body->semantic(scd);
947 scd->pop();
948
949 sc->noctor--;
950
951 return this;
952 } 965 }
953 966
954 int WhileStatement::hasBreak() 967 int WhileStatement::hasBreak()
955 { 968 {
956 return TRUE; 969 return TRUE;
961 return TRUE; 974 return TRUE;
962 } 975 }
963 976
964 int WhileStatement::usesEH() 977 int WhileStatement::usesEH()
965 { 978 {
979 assert(0);
966 return body ? body->usesEH() : 0; 980 return body ? body->usesEH() : 0;
967 } 981 }
968 982
969 int WhileStatement::blockExit() 983 int WhileStatement::blockExit()
970 { 984 {
985 assert(0);
971 //printf("WhileStatement::blockExit(%p)\n", this); 986 //printf("WhileStatement::blockExit(%p)\n", this);
972 987
973 int result = BEnone; 988 int result = BEnone;
974 if (condition->canThrow()) 989 if (condition->canThrow())
975 result |= BEthrow; 990 result |= BEthrow;
996 } 1011 }
997 1012
998 1013
999 int WhileStatement::comeFrom() 1014 int WhileStatement::comeFrom()
1000 { 1015 {
1016 assert(0);
1001 if (body) 1017 if (body)
1002 return body->comeFrom(); 1018 return body->comeFrom();
1003 return FALSE; 1019 return FALSE;
1004 } 1020 }
1005 1021
1191 return result; 1207 return result;
1192 } 1208 }
1193 if (condition) 1209 if (condition)
1194 { if (condition->canThrow()) 1210 { if (condition->canThrow())
1195 result |= BEthrow; 1211 result |= BEthrow;
1212 if (condition->isBool(TRUE))
1213 result &= ~BEfallthru;
1214 else if (condition->isBool(FALSE))
1215 return result;
1196 } 1216 }
1197 else 1217 else
1198 result &= ~BEfallthru; // the body must do the exiting 1218 result &= ~BEfallthru; // the body must do the exiting
1199 if (body) 1219 if (body)
1200 { int r = body->blockExit(); 1220 { int r = body->blockExit();
1450 } 1470 }
1451 1471
1452 for (size_t i = 0; i < dim; i++) 1472 for (size_t i = 0; i < dim; i++)
1453 { // Declare args 1473 { // Declare args
1454 Argument *arg = (Argument *)arguments->data[i]; 1474 Argument *arg = (Argument *)arguments->data[i];
1475 Type *argtype = arg->type->semantic(loc, sc);
1455 VarDeclaration *var; 1476 VarDeclaration *var;
1456 1477
1457 var = new VarDeclaration(loc, arg->type, arg->ident, NULL); 1478 var = new VarDeclaration(loc, argtype, arg->ident, NULL);
1458 var->storage_class |= STCforeach; 1479 var->storage_class |= STCforeach;
1459 var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); 1480 var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR);
1481 if (var->storage_class & (STCref | STCout))
1482 var->storage_class |= STCnodtor;
1460 if (dim == 2 && i == 0) 1483 if (dim == 2 && i == 0)
1461 { key = var; 1484 { key = var;
1462 //var->storage_class |= STCfinal; 1485 //var->storage_class |= STCfinal;
1463 } 1486 }
1464 else 1487 else
1469 if (var->storage_class & STCref && !tn->isMutable()) 1492 if (var->storage_class & STCref && !tn->isMutable())
1470 { 1493 {
1471 var->storage_class |= STCconst; 1494 var->storage_class |= STCconst;
1472 } 1495 }
1473 } 1496 }
1474 #if 1 1497 #if 0
1475 DeclarationExp *de = new DeclarationExp(loc, var); 1498 DeclarationExp *de = new DeclarationExp(loc, var);
1476 de->semantic(sc); 1499 de->semantic(sc);
1477 #else
1478 var->semantic(sc);
1479 if (!sc->insert(var))
1480 error("%s already defined", var->ident->toChars());
1481 #endif 1500 #endif
1482 } 1501 }
1483 1502
1484 sc->sbreak = this; 1503 #if 1
1485 sc->scontinue = this; 1504 {
1486 body = body->semantic(sc); 1505 /* Convert to a ForStatement
1487 1506 * foreach (key, value; a) body =>
1507 * for (T[] tmp = a[], size_t key; key < tmp.length; ++key)
1508 * { T value = tmp[k]; body }
1509 *
1510 * foreach_reverse (key, value; a) body =>
1511 * for (T[] tmp = a[], size_t key = tmp.length; key--; )
1512 * { T value = tmp[k]; body }
1513 */
1514 Identifier *id = Lexer::uniqueId("__aggr");
1515 ExpInitializer *ie = new ExpInitializer(loc, new SliceExp(loc, aggr, NULL, NULL));
1516 VarDeclaration *tmp = new VarDeclaration(loc, aggr->type->nextOf()->arrayOf(), id, ie);
1517
1518 Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length);
1519
1520 if (!key)
1521 {
1522 Identifier *id = Lexer::uniqueId("__key");
1523 key = new VarDeclaration(loc, Type::tsize_t, id, NULL);
1524 }
1525 if (op == TOKforeach_reverse)
1526 key->init = new ExpInitializer(loc, tmp_length);
1527 else
1528 key->init = new ExpInitializer(loc, new IntegerExp(0));
1529
1530 Statements *cs = new Statements();
1531 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
1532 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
1533 Statement *forinit = new CompoundDeclarationStatement(loc, cs);
1534
1535 Expression *cond;
1536 if (op == TOKforeach_reverse)
1537 // key--
1538 cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key));
1539 else
1540 // key < tmp.length
1541 cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), tmp_length);
1542
1543 Expression *increment = NULL;
1544 if (op == TOKforeach)
1545 // key += 1
1546 increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
1547
1548 // T value = tmp[key];
1549 value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key)));
1550 Statement *ds = new DeclarationStatement(loc, new DeclarationExp(loc, value));
1551
1552 body = new CompoundStatement(loc, ds, body);
1553
1554 ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body);
1555 s = fs->semantic(sc);
1556 break;
1557 }
1558 #else
1488 if (tab->nextOf()->implicitConvTo(value->type) < MATCHconst) 1559 if (tab->nextOf()->implicitConvTo(value->type) < MATCHconst)
1489 { 1560 {
1490 if (aggr->op == TOKstring) 1561 if (aggr->op == TOKstring)
1491 aggr = aggr->implicitCastTo(sc, value->type->arrayOf()); 1562 aggr = aggr->implicitCastTo(sc, value->type->arrayOf());
1492 else 1563 else
1493 error("foreach: %s is not an array of %s", 1564 error("foreach: %s is not an array of %s",
1494 tab->toChars(), value->type->toChars()); 1565 tab->toChars(), value->type->toChars());
1495 } 1566 }
1496 1567
1497 if (key && key->type->ty != Tint32 && key->type->ty != Tuns32) 1568 if (key)
1498 { 1569 {
1499 if (global.params.is64bit) 1570 if (global.params.is64bit)
1500 { 1571 {
1501 if (key->type->ty != Tint64 && key->type->ty != Tuns64) 1572 if (key->type->ty != Tint64 && key->type->ty != Tuns64)
1502 error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars()); 1573 error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars());
1503 } 1574 }
1504 else 1575
1505 error("foreach: key type must be int or uint, not %s", key->type->toChars()); 1576 if (key->storage_class & (STCout | STCref))
1577 error("foreach: key cannot be out or ref");
1506 } 1578 }
1507 1579
1508 if (key && key->storage_class & (STCout | STCref)) 1580 sc->sbreak = this;
1509 error("foreach: key cannot be out or ref"); 1581 sc->scontinue = this;
1582 body = body->semantic(sc);
1510 break; 1583 break;
1584 #endif
1511 1585
1512 case Taarray: 1586 case Taarray:
1513 if (!checkForArgTypes()) 1587 if (!checkForArgTypes())
1514 return this; 1588 return this;
1515 1589
1743 exps->push(aggr); 1817 exps->push(aggr);
1744 size_t keysize = taa->index->size(); 1818 size_t keysize = taa->index->size();
1745 keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1); 1819 keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1);
1746 exps->push(new IntegerExp(0, keysize, Type::tsize_t)); 1820 exps->push(new IntegerExp(0, keysize, Type::tsize_t));
1747 1821
1822 #if IN_LLVM
1748 // LDC paint delegate argument to the type runtime expects 1823 // LDC paint delegate argument to the type runtime expects
1749 if (!fldeTy->equals(flde->type)) 1824 if (!fldeTy->equals(flde->type))
1750 { 1825 {
1751 flde = new CastExp(loc, flde, flde->type); 1826 flde = new CastExp(loc, flde, flde->type);
1752 flde->type = fldeTy; 1827 flde->type = fldeTy;
1753 } 1828 }
1829 #endif
1754 exps->push(flde); 1830 exps->push(flde);
1755 e = new CallExp(loc, ec, exps); 1831 e = new CallExp(loc, ec, exps);
1756 e->type = Type::tindex; // don't run semantic() on e 1832 e->type = Type::tindex; // don't run semantic() on e
1757 } 1833 }
1758 else if (tab->ty == Tarray || tab->ty == Tsarray) 1834 else if (tab->ty == Tarray || tab->ty == Tsarray)
2053 ea.typeCombine(sc); 2129 ea.typeCombine(sc);
2054 arg->type = ea.type->mutableOf(); 2130 arg->type = ea.type->mutableOf();
2055 lwr = ea.e1; 2131 lwr = ea.e1;
2056 upr = ea.e2; 2132 upr = ea.e2;
2057 } 2133 }
2134 #if 1
2135 /* Convert to a for loop:
2136 * foreach (key; lwr .. upr) =>
2137 * for (auto key = lwr, auto tmp = upr; key < tmp; ++key)
2138 *
2139 * foreach_reverse (key; lwr .. upr) =>
2140 * for (auto tmp = lwr, auto key = upr; key-- > tmp;)
2141 */
2142
2143 ExpInitializer *ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr);
2144 key = new VarDeclaration(loc, arg->type, arg->ident, ie);
2145
2146 Identifier *id = Lexer::uniqueId("__limit");
2147 ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr);
2148 VarDeclaration *tmp = new VarDeclaration(loc, arg->type, id, ie);
2149
2150 Statements *cs = new Statements();
2151 // Keep order of evaluation as lwr, then upr
2152 if (op == TOKforeach)
2153 {
2154 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
2155 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
2156 }
2157 else
2158 {
2159 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
2160 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
2161 }
2162 Statement *forinit = new CompoundDeclarationStatement(loc, cs);
2163
2164 Expression *cond;
2165 if (op == TOKforeach_reverse)
2166 { // key-- > tmp
2167 cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key));
2168 cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp));
2169 }
2170 else
2171 // key < tmp
2172 cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), new VarExp(loc, tmp));
2173
2174 Expression *increment = NULL;
2175 if (op == TOKforeach)
2176 // key += 1
2177 increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
2178
2179 ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body);
2180 s = fs->semantic(sc);
2181 return s;
2182 #else
2058 if (!arg->type->isscalar()) 2183 if (!arg->type->isscalar())
2059 error("%s is not a scalar type", arg->type->toChars()); 2184 error("%s is not a scalar type", arg->type->toChars());
2060 2185
2061 sym = new ScopeDsymbol(); 2186 sym = new ScopeDsymbol();
2062 sym->parent = sc->scopesym; 2187 sym->parent = sc->scopesym;
2076 body = body->semantic(sc); 2201 body = body->semantic(sc);
2077 2202
2078 sc->noctor--; 2203 sc->noctor--;
2079 sc->pop(); 2204 sc->pop();
2080 return s; 2205 return s;
2206 #endif
2081 } 2207 }
2082 2208
2083 int ForeachRangeStatement::hasBreak() 2209 int ForeachRangeStatement::hasBreak()
2084 { 2210 {
2085 return TRUE; 2211 return TRUE;
2090 return TRUE; 2216 return TRUE;
2091 } 2217 }
2092 2218
2093 int ForeachRangeStatement::usesEH() 2219 int ForeachRangeStatement::usesEH()
2094 { 2220 {
2221 assert(0);
2095 return body->usesEH(); 2222 return body->usesEH();
2096 } 2223 }
2097 2224
2098 int ForeachRangeStatement::blockExit() 2225 int ForeachRangeStatement::blockExit()
2099 { int result = BEfallthru; 2226 {
2227 assert(0);
2228 int result = BEfallthru;
2100 2229
2101 if (lwr && lwr->canThrow()) 2230 if (lwr && lwr->canThrow())
2102 result |= BEthrow; 2231 result |= BEthrow;
2103 else if (upr && upr->canThrow()) 2232 else if (upr && upr->canThrow())
2104 result |= BEthrow; 2233 result |= BEthrow;
2111 } 2240 }
2112 2241
2113 2242
2114 int ForeachRangeStatement::comeFrom() 2243 int ForeachRangeStatement::comeFrom()
2115 { 2244 {
2245 assert(0);
2116 if (body) 2246 if (body)
2117 return body->comeFrom(); 2247 return body->comeFrom();
2118 return FALSE; 2248 return FALSE;
2119 } 2249 }
2120 2250
2460 // LDC 2590 // LDC
2461 else if (ident == Id::allow_inline) 2591 else if (ident == Id::allow_inline)
2462 { 2592 {
2463 sc->func->allowInlining = true; 2593 sc->func->allowInlining = true;
2464 } 2594 }
2465 2595 #if DMDV2
2466 else if (ident == Id::startaddress) 2596 else if (ident == Id::startaddress)
2467 { 2597 {
2468 if (!args || args->dim != 1) 2598 if (!args || args->dim != 1)
2469 error("function name expected for start address"); 2599 error("function name expected for start address");
2470 else 2600 else
2481 body = body->semantic(sc); 2611 body = body->semantic(sc);
2482 } 2612 }
2483 return this; 2613 return this;
2484 } 2614 }
2485 } 2615 }
2616 #endif
2486 else 2617 else
2487 error("unrecognized pragma(%s)", ident->toChars()); 2618 error("unrecognized pragma(%s)", ident->toChars());
2488 2619
2489 if (body) 2620 if (body)
2490 { 2621 {
2655 2786
2656 Lfoundcase: 2787 Lfoundcase:
2657 ; 2788 ;
2658 } 2789 }
2659 2790
2660 if (!sc->sw->sdefault) 2791 if (!sc->sw->sdefault && !isFinal)
2661 { hasNoDefault = 1; 2792 { hasNoDefault = 1;
2662 2793
2663 warning("switch statement has no default"); 2794 warning("switch statement has no default");
2664 2795
2665 // Generate runtime error if the default is hit 2796 // Generate runtime error if the default is hit
3691 } 3822 }
3692 3823
3693 Statement *SynchronizedStatement::semantic(Scope *sc) 3824 Statement *SynchronizedStatement::semantic(Scope *sc)
3694 { 3825 {
3695 if (exp) 3826 if (exp)
3696 { ClassDeclaration *cd; 3827 {
3697
3698 exp = exp->semantic(sc); 3828 exp = exp->semantic(sc);
3699 exp = resolveProperties(sc, exp); 3829 exp = resolveProperties(sc, exp);
3700 cd = exp->type->isClassHandle(); 3830 ClassDeclaration *cd = exp->type->isClassHandle();
3701 if (!cd) 3831 if (!cd)
3702 error("can only synchronize on class objects, not '%s'", exp->type->toChars()); 3832 error("can only synchronize on class objects, not '%s'", exp->type->toChars());
3703 else if (cd->isInterfaceDeclaration()) 3833 else if (cd->isInterfaceDeclaration())
3704 { Type *t = new TypeIdentifier(0, Id::Object); 3834 { /* Cast the interface to an object, as the object has the monitor,
3835 * not the interface.
3836 */
3837 Type *t = new TypeIdentifier(0, Id::Object);
3705 3838
3706 t = t->semantic(0, sc); 3839 t = t->semantic(0, sc);
3707 exp = new CastExp(loc, exp, t); 3840 exp = new CastExp(loc, exp, t);
3708 exp = exp->semantic(sc); 3841 exp = exp->semantic(sc);
3709 } 3842 }
3710 } 3843
3844 #if 1
3845 /* Rewrite as:
3846 * auto tmp = exp;
3847 * _d_monitorenter(tmp);
3848 * try { body } finally { _d_monitorexit(tmp); }
3849 */
3850 Identifier *id = Lexer::uniqueId("__sync");
3851 ExpInitializer *ie = new ExpInitializer(loc, exp);
3852 VarDeclaration *tmp = new VarDeclaration(loc, exp->type, id, ie);
3853
3854 Statements *cs = new Statements();
3855 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
3856
3857 #if IN_LLVM
3858 // LDC: Build args
3859 Arguments* args = new Arguments;
3860 args->push(new Argument(STCin, ClassDeclaration::object->type, NULL, NULL));
3861 FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorenter);
3862 #else
3863 FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorenter);
3864 #endif
3865 Expression *e = new CallExp(loc, new VarExp(loc, fdenter), new VarExp(loc, tmp));
3866 e->type = Type::tvoid; // do not run semantic on e
3867 cs->push(new ExpStatement(loc, e));
3868
3869 #if IN_LLVM
3870 FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorexit);
3871 #else
3872 FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorexit);
3873 #endif
3874 e = new CallExp(loc, new VarExp(loc, fdexit), new VarExp(loc, tmp));
3875 e->type = Type::tvoid; // do not run semantic on e
3876 Statement *s = new ExpStatement(loc, e);
3877 s = new TryFinallyStatement(loc, body, s);
3878 cs->push(s);
3879
3880 s = new CompoundStatement(loc, cs);
3881 return s->semantic(sc);
3882 #endif
3883 }
3884 #if 1
3885 else
3886 { /* Generate our own critical section, then rewrite as:
3887 * __gshared byte[CriticalSection.sizeof] critsec;
3888 * _d_criticalenter(critsec.ptr);
3889 * try { body } finally { _d_criticalexit(critsec.ptr); }
3890 */
3891 Identifier *id = Lexer::uniqueId("__critsec");
3892 #if IN_LLVM
3893 Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + getTypePaddedSize(DtoMutexType())));
3894 #elif IN_DMD
3895 Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + os_critsecsize()));
3896 #endif
3897 VarDeclaration *tmp = new VarDeclaration(loc, t, id, NULL);
3898 tmp->storage_class |= STCgshared | STCstatic;
3899
3900 Statements *cs = new Statements();
3901 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
3902
3903 #if IN_LLVM
3904 // LDC: Build args (based on the code from gen/tollvm.cpp:DtoMutexType()
3905 Arguments* args = new Arguments;
3906 StructDeclaration* dcs = new StructDeclaration(loc, id);
3907 if (global.params.os == OSWindows)
3908 {
3909 dcs->addField(dcs->scope, new VarDeclaration(loc, Type::tint32, id, NULL));
3910 }
3911 else if (global.params.os == OSFreeBSD)
3912 {
3913 dcs->addField(dcs->scope, new VarDeclaration(loc, Type::tsize_t, id, NULL));
3914 }
3915 else
3916 {
3917 // pthread_fastlock
3918 StructDeclaration* pfl = new StructDeclaration(loc, id);
3919 pfl->scope->linkage = LINKc;
3920 pfl->addField(pfl->scope, new VarDeclaration(loc, Type::tsize_t, id, NULL));
3921 pfl->addField(pfl->scope, new VarDeclaration(loc, Type::tint32, id, NULL));
3922
3923 // pthread_mutex
3924 StructDeclaration* pm = new StructDeclaration(loc, id);
3925 pm->scope->linkage = LINKc;
3926 pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL));
3927 pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL));
3928 pm->addField(pm->scope, new VarDeclaration(loc, Type::tvoidptr, id, NULL));
3929 pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL));
3930 pm->addField(pm->scope, new VarDeclaration(loc, pfl->type, id, NULL));
3931
3932 // D_CRITICAL_SECTION
3933 dcs->scope->linkage = LINKc;
3934 dcs->addField(dcs->scope, new VarDeclaration(loc, dcs->type->pointerTo(), id, NULL));
3935 dcs->addField(dcs->scope, new VarDeclaration(loc, pm->type, id, NULL));
3936 }
3937 args->push(new Argument(STCin, dcs->type->pointerTo(), NULL, NULL));
3938
3939 FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalenter);
3940 #else
3941 FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalenter);
3942 #endif
3943 Expression *e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr);
3944 e = e->semantic(sc);
3945 e = new CallExp(loc, new VarExp(loc, fdenter), e);
3946 e->type = Type::tvoid; // do not run semantic on e
3947 cs->push(new ExpStatement(loc, e));
3948
3949 #if IN_LLVM
3950 FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalexit);
3951 #else
3952 FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalexit);
3953 #endif
3954 e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr);
3955 e = e->semantic(sc);
3956 e = new CallExp(loc, new VarExp(loc, fdexit), e);
3957 e->type = Type::tvoid; // do not run semantic on e
3958 Statement *s = new ExpStatement(loc, e);
3959 s = new TryFinallyStatement(loc, body, s);
3960 cs->push(s);
3961
3962 s = new CompoundStatement(loc, cs);
3963 return s->semantic(sc);
3964 }
3965 #endif
3711 if (body) 3966 if (body)
3712 { 3967 {
3713 Statement* oldScopeExit = sc->enclosingScopeExit; 3968 Statement* oldScopeExit = sc->enclosingScopeExit;
3714 sc->enclosingScopeExit = this; 3969 sc->enclosingScopeExit = this;
3715 body = body->semantic(sc); 3970 body = body->semantic(sc);