Mercurial > projects > ddmd
diff dmd/SynchronizedStatement.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 2e2a5c3f943a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/SynchronizedStatement.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,193 @@ +module dmd.SynchronizedStatement; + +import dmd.Statement; +import dmd.IntegerExp; +import dmd.TypeSArray; +import dmd.CompoundStatement; +import dmd.Loc; +import dmd.Scope; +import dmd.Expression; +import dmd.ClassDeclaration; +import dmd.Id; +import dmd.TypeIdentifier; +import dmd.Type; +import dmd.OutBuffer; +import dmd.HdrGenState; +import dmd.InlineScanState; +import dmd.IRState; +import dmd.CastExp; +import dmd.TryFinallyStatement; +import dmd.ExpStatement; +import dmd.CallExp; +import dmd.DeclarationExp; +import dmd.VarExp; +import dmd.DeclarationStatement; +import dmd.ArrayTypes; +import dmd.Statement; +import dmd.VarDeclaration; +import dmd.ExpInitializer; +import dmd.Lexer; +import dmd.Identifier; +import dmd.FuncDeclaration; +import dmd.BE; +import dmd.STC; +import dmd.DotIdExp; + +import dmd.backend.elem; +import dmd.backend.Util; + +class SynchronizedStatement : Statement +{ + Expression exp; + Statement body_; + + this(Loc loc, Expression exp, Statement body_) + { + super(loc); + + this.exp = exp; + this.body_ = body_; + this.esync = null; + } + + Statement syntaxCopy() + { + assert(false); + } + + Statement semantic(Scope sc) + { + if (exp) + { + exp = exp.semantic(sc); + exp = resolveProperties(sc, exp); + ClassDeclaration cd = exp.type.isClassHandle(); + if (!cd) + error("can only synchronize on class objects, not '%s'", exp.type.toChars()); + else if (cd.isInterfaceDeclaration()) + { + /* Cast the interface to an object, as the object has the monitor, + * not the interface. + */ + Type t = new TypeIdentifier(Loc(0), Id.Object_); + + t = t.semantic(Loc(0), sc); + exp = new CastExp(loc, exp, t); + exp = exp.semantic(sc); + } + +static if (true) { + /* 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(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + + FuncDeclaration fdenter = FuncDeclaration.genCfunc(Type.tvoid, Id.monitorenter); + 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(cast(void*)new ExpStatement(loc, e)); + + FuncDeclaration fdexit = FuncDeclaration.genCfunc(Type.tvoid, Id.monitorexit); + 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(cast(void*)s); + + s = new CompoundStatement(loc, cs); + return s.semantic(sc); +} + } +/// static if (true) { + 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"); + Type t = new TypeSArray(Type.tint8, new IntegerExp(PTRSIZE + os_critsecsize())); + VarDeclaration tmp = new VarDeclaration(loc, t, id, null); + tmp.storage_class |= STCgshared | STCstatic; + + Statements cs = new Statements(); + cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + + FuncDeclaration fdenter = FuncDeclaration.genCfunc(Type.tvoid, Id.criticalenter); + 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(cast(void*)new ExpStatement(loc, e)); + + FuncDeclaration fdexit = FuncDeclaration.genCfunc(Type.tvoid, Id.criticalexit); + 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(cast(void*)s); + + s = new CompoundStatement(loc, cs); + return s.semantic(sc); + } +/// } + if (body_) + body_ = body_.semantic(sc); + + return this; + } + + bool hasBreak() + { + assert(false); + } + + bool hasContinue() + { + assert(false); + } + + bool usesEH() + { + assert(false); + } + + BE blockExit() + { + assert(false); + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + assert(false); + } + + Statement inlineScan(InlineScanState* iss) + { + assert(false); + } + +// Back end + elem* esync; + + this(Loc loc, elem *esync, Statement body_) + { + assert(false); + super(loc); + } + + void toIR(IRState* irs) + { + assert(false); + } +} \ No newline at end of file