view dmd/GotoCaseStatement.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 9e39c7de8438
children b0d41ff5e0df
line wrap: on
line source

module dmd.GotoCaseStatement;

import dmd.common;
import dmd.Statement;
import dmd.Expression;
import dmd.CaseStatement;
import dmd.IRState;
import dmd.Scope;
import dmd.Loc;
import dmd.InterState;
import dmd.OutBuffer;
import dmd.HdrGenState;
import dmd.BE;
import dmd.WANT;

import dmd.backend.Util;
import dmd.backend.block;
import dmd.backend.BC;
import dmd.backend.Blockx;

class GotoCaseStatement : Statement
{
    Expression exp;		// NULL, or which case to goto
    CaseStatement cs;		// case statement it resolves to

    this(Loc loc, Expression exp)
	{
		register();
		super(loc);
		cs = null;
		this.exp = exp;
	}
	
    override Statement syntaxCopy()
	{
		Expression e = exp ? exp.syntaxCopy() : null;
		GotoCaseStatement s = new GotoCaseStatement(loc, e);
		return s;
	}
	
    override Statement semantic(Scope sc)
	{
		if (exp)
			exp = exp.semantic(sc);

		if (!sc.sw)
			error("goto case not in switch statement");
		else
		{
			sc.sw.gotoCases.push(cast(void*)this);
			if (exp)
			{
				exp = exp.implicitCastTo(sc, sc.sw.condition.type);
				exp = exp.optimize(WANTvalue);
			}
		}
		return this;
	}
	
    override Expression interpret(InterState istate)
	{
		assert(false);
	}
	
    override BE blockExit()
	{
		return BEgoto;
	}
	
    override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
	{
		buf.writestring("goto case");
		if (exp)
		{   
			buf.writebyte(' ');
			exp.toCBuffer(buf, hgs);
		}
		buf.writebyte(';');
		buf.writenl();
	}

    override void toIR(IRState* irs)
	{
		block* b;
		Blockx* blx = irs.blx;
		block* bdest = cs.cblock;

		if (!bdest)
		{
			bdest = block_calloc(blx);
			cs.cblock = bdest;
		}

		b = blx.curblock;

		// The rest is equivalent to GotoStatement

		// Adjust exception handler scope index if in different try blocks
		if (b.Btry != bdest.Btry)
		{
			// Check that bdest is in an enclosing try block
			for (block* bt = b.Btry; bt != bdest.Btry; bt = bt.Btry)
			{
				if (!bt)
				{
					//printf("b.Btry = %p, bdest.Btry = %p\n", b.Btry, bdest.Btry);
					error("cannot goto into try block");
					break;
				}
			}

			//setScopeIndex(blx, b, bdest.Btry ? bdest.Btry.Bscope_index : -1);
		}

		list_append(&b.Bsucc,bdest);
		incUsage(irs, loc);
		block_next(blx, BC.BCgoto, null);
	}
}