Mercurial > projects > ldc
diff 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 |
line wrap: on
line diff
--- a/dmd2/statement.c Tue Aug 25 21:35:43 2009 +0200 +++ b/dmd2/statement.c Tue Sep 08 10:07:56 2009 +0100 @@ -29,6 +29,12 @@ #include "template.h" #include "attrib.h" +#if IN_LLVM +#include "gen/tollvm.h" +#elif IN_DMD +extern int os_critsecsize(); +#endif + /******************************** Statement ***************************/ Statement::Statement(Loc loc) @@ -182,6 +188,22 @@ } +/******************************** PeelStatement ***************************/ + +PeelStatement::PeelStatement(Statement *s) + : Statement(s->loc) +{ + this->s = s; +} + +Statement *PeelStatement::semantic(Scope *sc) +{ + /* "peel" off this wrapper, and don't run semantic() + * on the result. + */ + return s; +} + /******************************** ExpStatement ***************************/ ExpStatement::ExpStatement(Loc loc, Expression *exp) @@ -344,6 +366,25 @@ if (e) { //printf("dtor is: "); e->print(); +#if 0 + if (v->type->toBasetype()->ty == Tstruct) + { /* Need a 'gate' to turn on/off destruction, + * in case v gets moved elsewhere. + */ + Identifier *id = Lexer::uniqueId("__runDtor"); + ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(1)); + VarDeclaration *rd = new VarDeclaration(loc, Type::tint32, id, ie); + *sentry = new DeclarationStatement(loc, rd); + v->rundtor = rd; + + /* Rewrite e as: + * rundtor && e + */ + Expression *ve = new VarExp(loc, v->rundtor); + e = new AndAndExp(loc, ve, e); + e->type = Type::tbool; + } +#endif *sfinally = new ExpStatement(loc, e); } } @@ -418,7 +459,12 @@ if (sentry) { sentry = sentry->semantic(sc); - statements->data[i] = sentry; + if (s->isDeclarationStatement()) + { statements->insert(i, sentry); + i++; + } + else + statements->data[i] = sentry; } if (sexception) { @@ -562,7 +608,8 @@ //printf("%s\n", s->toChars()); if (!(result & BEfallthru) && !s->comeFrom()) { - s->warning("statement is not reachable"); + if (s->blockExit() != BEhalt) + s->warning("statement is not reachable"); } result &= ~BEfallthru; @@ -909,46 +956,12 @@ Statement *WhileStatement::semantic(Scope *sc) { -#if 0 - if (condition->op == TOKmatch) - { - /* Rewrite while (condition) body as: - * if (condition) - * do - * body - * while ((_match = _match.opNext), _match); - */ - - Expression *ew = new IdentifierExp(0, Id::_match); - ew = new DotIdExp(0, ew, Id::next); - ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew); - ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0)); - Expression *ev = new IdentifierExp(0, Id::_match); - //ev = new CastExp(0, ev, Type::tvoidptr); - ew = new CommaExp(0, ew, ev); - Statement *sw = new DoStatement(loc, body, ew); - Statement *si = new IfStatement(loc, condition, sw, NULL); - return si->semantic(sc); - } -#endif - - condition = condition->semantic(sc); - condition = resolveProperties(sc, condition); - condition = condition->optimize(WANTvalue); - condition = condition->checkToBoolean(); - - sc->noctor++; - - Scope *scd = sc->push(); - scd->sbreak = this; - scd->scontinue = this; - if (body) - body = body->semantic(scd); - scd->pop(); - - sc->noctor--; - - return this; + /* Rewrite as a for(;condition;) loop + */ + + Statement *s = new ForStatement(loc, NULL, condition, NULL, body); + s = s->semantic(sc); + return s; } int WhileStatement::hasBreak() @@ -963,11 +976,13 @@ int WhileStatement::usesEH() { + assert(0); return body ? body->usesEH() : 0; } int WhileStatement::blockExit() { + assert(0); //printf("WhileStatement::blockExit(%p)\n", this); int result = BEnone; @@ -998,6 +1013,7 @@ int WhileStatement::comeFrom() { + assert(0); if (body) return body->comeFrom(); return FALSE; @@ -1193,6 +1209,10 @@ if (condition) { if (condition->canThrow()) result |= BEthrow; + if (condition->isBool(TRUE)) + result &= ~BEfallthru; + else if (condition->isBool(FALSE)) + return result; } else result &= ~BEfallthru; // the body must do the exiting @@ -1452,11 +1472,14 @@ for (size_t i = 0; i < dim; i++) { // Declare args Argument *arg = (Argument *)arguments->data[i]; + Type *argtype = arg->type->semantic(loc, sc); VarDeclaration *var; - var = new VarDeclaration(loc, arg->type, arg->ident, NULL); + var = new VarDeclaration(loc, argtype, arg->ident, NULL); var->storage_class |= STCforeach; var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); + if (var->storage_class & (STCref | STCout)) + var->storage_class |= STCnodtor; if (dim == 2 && i == 0) { key = var; //var->storage_class |= STCfinal; @@ -1471,20 +1494,68 @@ var->storage_class |= STCconst; } } -#if 1 +#if 0 DeclarationExp *de = new DeclarationExp(loc, var); de->semantic(sc); -#else - var->semantic(sc); - if (!sc->insert(var)) - error("%s already defined", var->ident->toChars()); #endif } - sc->sbreak = this; - sc->scontinue = this; - body = body->semantic(sc); - +#if 1 + { + /* Convert to a ForStatement + * foreach (key, value; a) body => + * for (T[] tmp = a[], size_t key; key < tmp.length; ++key) + * { T value = tmp[k]; body } + * + * foreach_reverse (key, value; a) body => + * for (T[] tmp = a[], size_t key = tmp.length; key--; ) + * { T value = tmp[k]; body } + */ + Identifier *id = Lexer::uniqueId("__aggr"); + ExpInitializer *ie = new ExpInitializer(loc, new SliceExp(loc, aggr, NULL, NULL)); + VarDeclaration *tmp = new VarDeclaration(loc, aggr->type->nextOf()->arrayOf(), id, ie); + + Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length); + + if (!key) + { + Identifier *id = Lexer::uniqueId("__key"); + key = new VarDeclaration(loc, Type::tsize_t, id, NULL); + } + if (op == TOKforeach_reverse) + key->init = new ExpInitializer(loc, tmp_length); + else + key->init = new ExpInitializer(loc, new IntegerExp(0)); + + Statements *cs = new Statements(); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); + Statement *forinit = new CompoundDeclarationStatement(loc, cs); + + Expression *cond; + if (op == TOKforeach_reverse) + // key-- + cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key)); + else + // key < tmp.length + cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), tmp_length); + + Expression *increment = NULL; + if (op == TOKforeach) + // key += 1 + increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); + + // T value = tmp[key]; + value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key))); + Statement *ds = new DeclarationStatement(loc, new DeclarationExp(loc, value)); + + body = new CompoundStatement(loc, ds, body); + + ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body); + s = fs->semantic(sc); + break; + } +#else if (tab->nextOf()->implicitConvTo(value->type) < MATCHconst) { if (aggr->op == TOKstring) @@ -1494,20 +1565,23 @@ tab->toChars(), value->type->toChars()); } - if (key && key->type->ty != Tint32 && key->type->ty != Tuns32) + if (key) { if (global.params.is64bit) { if (key->type->ty != Tint64 && key->type->ty != Tuns64) error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars()); } - else - error("foreach: key type must be int or uint, not %s", key->type->toChars()); + + if (key->storage_class & (STCout | STCref)) + error("foreach: key cannot be out or ref"); } - if (key && key->storage_class & (STCout | STCref)) - error("foreach: key cannot be out or ref"); + sc->sbreak = this; + sc->scontinue = this; + body = body->semantic(sc); break; +#endif case Taarray: if (!checkForArgTypes()) @@ -1745,12 +1819,14 @@ keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1); exps->push(new IntegerExp(0, keysize, Type::tsize_t)); +#if IN_LLVM // LDC paint delegate argument to the type runtime expects if (!fldeTy->equals(flde->type)) { flde = new CastExp(loc, flde, flde->type); flde->type = fldeTy; } +#endif exps->push(flde); e = new CallExp(loc, ec, exps); e->type = Type::tindex; // don't run semantic() on e @@ -2055,6 +2131,55 @@ lwr = ea.e1; upr = ea.e2; } +#if 1 + /* Convert to a for loop: + * foreach (key; lwr .. upr) => + * for (auto key = lwr, auto tmp = upr; key < tmp; ++key) + * + * foreach_reverse (key; lwr .. upr) => + * for (auto tmp = lwr, auto key = upr; key-- > tmp;) + */ + + ExpInitializer *ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr); + key = new VarDeclaration(loc, arg->type, arg->ident, ie); + + Identifier *id = Lexer::uniqueId("__limit"); + ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr); + VarDeclaration *tmp = new VarDeclaration(loc, arg->type, id, ie); + + Statements *cs = new Statements(); + // Keep order of evaluation as lwr, then upr + if (op == TOKforeach) + { + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + } + else + { + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); + } + Statement *forinit = new CompoundDeclarationStatement(loc, cs); + + Expression *cond; + if (op == TOKforeach_reverse) + { // key-- > tmp + cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key)); + cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp)); + } + else + // key < tmp + cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), new VarExp(loc, tmp)); + + Expression *increment = NULL; + if (op == TOKforeach) + // key += 1 + increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); + + ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body); + s = fs->semantic(sc); + return s; +#else if (!arg->type->isscalar()) error("%s is not a scalar type", arg->type->toChars()); @@ -2078,6 +2203,7 @@ sc->noctor--; sc->pop(); return s; +#endif } int ForeachRangeStatement::hasBreak() @@ -2092,11 +2218,14 @@ int ForeachRangeStatement::usesEH() { + assert(0); return body->usesEH(); } int ForeachRangeStatement::blockExit() -{ int result = BEfallthru; +{ + assert(0); + int result = BEfallthru; if (lwr && lwr->canThrow()) result |= BEthrow; @@ -2113,6 +2242,7 @@ int ForeachRangeStatement::comeFrom() { + assert(0); if (body) return body->comeFrom(); return FALSE; @@ -2462,7 +2592,7 @@ { sc->func->allowInlining = true; } - +#if DMDV2 else if (ident == Id::startaddress) { if (!args || args->dim != 1) @@ -2483,6 +2613,7 @@ return this; } } +#endif else error("unrecognized pragma(%s)", ident->toChars()); @@ -2657,7 +2788,7 @@ ; } - if (!sc->sw->sdefault) + if (!sc->sw->sdefault && !isFinal) { hasNoDefault = 1; warning("switch statement has no default"); @@ -3693,21 +3824,145 @@ Statement *SynchronizedStatement::semantic(Scope *sc) { if (exp) - { ClassDeclaration *cd; - + { exp = exp->semantic(sc); exp = resolveProperties(sc, exp); - cd = exp->type->isClassHandle(); + ClassDeclaration *cd = exp->type->isClassHandle(); if (!cd) error("can only synchronize on class objects, not '%s'", exp->type->toChars()); else if (cd->isInterfaceDeclaration()) - { Type *t = new TypeIdentifier(0, Id::Object); + { /* Cast the interface to an object, as the object has the monitor, + * not the interface. + */ + Type *t = new TypeIdentifier(0, Id::Object); t = t->semantic(0, sc); exp = new CastExp(loc, exp, t); exp = exp->semantic(sc); } + +#if 1 + /* Rewrite as: + * auto tmp = exp; + * _d_monitorenter(tmp); + * try { body } finally { _d_monitorexit(tmp); } + */ + Identifier *id = Lexer::uniqueId("__sync"); + ExpInitializer *ie = new ExpInitializer(loc, exp); + VarDeclaration *tmp = new VarDeclaration(loc, exp->type, id, ie); + + Statements *cs = new Statements(); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + +#if IN_LLVM + // LDC: Build args + Arguments* args = new Arguments; + args->push(new Argument(STCin, ClassDeclaration::object->type, NULL, NULL)); + FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorenter); +#else + FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorenter); +#endif + Expression *e = new CallExp(loc, new VarExp(loc, fdenter), new VarExp(loc, tmp)); + e->type = Type::tvoid; // do not run semantic on e + cs->push(new ExpStatement(loc, e)); + +#if IN_LLVM + FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorexit); +#else + FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorexit); +#endif + e = new CallExp(loc, new VarExp(loc, fdexit), new VarExp(loc, tmp)); + e->type = Type::tvoid; // do not run semantic on e + Statement *s = new ExpStatement(loc, e); + s = new TryFinallyStatement(loc, body, s); + cs->push(s); + + s = new CompoundStatement(loc, cs); + return s->semantic(sc); +#endif } +#if 1 + else + { /* Generate our own critical section, then rewrite as: + * __gshared byte[CriticalSection.sizeof] critsec; + * _d_criticalenter(critsec.ptr); + * try { body } finally { _d_criticalexit(critsec.ptr); } + */ + Identifier *id = Lexer::uniqueId("__critsec"); +#if IN_LLVM + Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + getTypePaddedSize(DtoMutexType()))); +#elif IN_DMD + Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + os_critsecsize())); +#endif + VarDeclaration *tmp = new VarDeclaration(loc, t, id, NULL); + tmp->storage_class |= STCgshared | STCstatic; + + Statements *cs = new Statements(); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + +#if IN_LLVM + // LDC: Build args (based on the code from gen/tollvm.cpp:DtoMutexType() + Arguments* args = new Arguments; + StructDeclaration* dcs = new StructDeclaration(loc, id); + if (global.params.os == OSWindows) + { + dcs->addField(dcs->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); + } + else if (global.params.os == OSFreeBSD) + { + dcs->addField(dcs->scope, new VarDeclaration(loc, Type::tsize_t, id, NULL)); + } + else + { + // pthread_fastlock + StructDeclaration* pfl = new StructDeclaration(loc, id); + pfl->scope->linkage = LINKc; + pfl->addField(pfl->scope, new VarDeclaration(loc, Type::tsize_t, id, NULL)); + pfl->addField(pfl->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); + + // pthread_mutex + StructDeclaration* pm = new StructDeclaration(loc, id); + pm->scope->linkage = LINKc; + pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); + pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); + pm->addField(pm->scope, new VarDeclaration(loc, Type::tvoidptr, id, NULL)); + pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); + pm->addField(pm->scope, new VarDeclaration(loc, pfl->type, id, NULL)); + + // D_CRITICAL_SECTION + dcs->scope->linkage = LINKc; + dcs->addField(dcs->scope, new VarDeclaration(loc, dcs->type->pointerTo(), id, NULL)); + dcs->addField(dcs->scope, new VarDeclaration(loc, pm->type, id, NULL)); + } + args->push(new Argument(STCin, dcs->type->pointerTo(), NULL, NULL)); + + FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalenter); +#else + FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalenter); +#endif + Expression *e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr); + e = e->semantic(sc); + e = new CallExp(loc, new VarExp(loc, fdenter), e); + e->type = Type::tvoid; // do not run semantic on e + cs->push(new ExpStatement(loc, e)); + +#if IN_LLVM + FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalexit); +#else + FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalexit); +#endif + e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr); + e = e->semantic(sc); + e = new CallExp(loc, new VarExp(loc, fdexit), e); + e->type = Type::tvoid; // do not run semantic on e + Statement *s = new ExpStatement(loc, e); + s = new TryFinallyStatement(loc, body, s); + cs->push(s); + + s = new CompoundStatement(loc, cs); + return s->semantic(sc); + } +#endif if (body) { Statement* oldScopeExit = sc->enclosingScopeExit;