view dmd/SynchronizedStatement.d @ 178:e3afd1303184

Many small bugs fixed Made all classes derive from TObject to detect memory leaks (functionality is disabled for now) Began work on overriding backend memory allocations (to avoid memory leaks)
author korDen
date Sun, 17 Oct 2010 07:42:00 +0400
parents c77e9f4f1793
children b0d41ff5e0df
line wrap: on
line source

module dmd.SynchronizedStatement;

import dmd.common;
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_)
	{
		register();
		super(loc);
		
		this.exp = exp;
		this.body_ = body_;
		this.esync = null;
	}
	
    override Statement syntaxCopy()
	{
		assert(false);
	}
	
    override 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(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(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(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(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(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(s);

			s = new CompoundStatement(loc, cs);
			return s.semantic(sc);
		}
///	}
		if (body_)
			body_ = body_.semantic(sc);

		return this;
	}
	
    override bool hasBreak()
	{
		assert(false);
	}
	
    override bool hasContinue()
	{
		assert(false);
	}
	
    override bool usesEH()
	{
		assert(false);
	}
	
    override BE blockExit()
	{
		assert(false);
	}
	
    override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
	{
		assert(false);
	}

    override Statement inlineScan(InlineScanState* iss)
	{
		assert(false);
	}

// Back end
    elem* esync;

	this(Loc loc, elem *esync, Statement body_)
	{
		register();
		assert(false);
		super(loc);
	}
	
    override void toIR(IRState* irs)
	{
		assert(false);
	}
}