diff dmd/AddrExp.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/AddrExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,355 @@
+module dmd.AddrExp;
+
+import dmd.Expression;
+import dmd.UnaExp;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.ErrorExp;
+import dmd.DotVarExp;
+import dmd.FuncDeclaration;
+import dmd.DelegateExp;
+import dmd.VarExp;
+import dmd.VarDeclaration;
+import dmd.ThisExp;
+import dmd.TOK;
+import dmd.WANT;
+import dmd.CommaExp;
+import dmd.STC;
+import dmd.PtrExp;
+import dmd.SymOffExp;
+import dmd.IndexExp;
+import dmd.OverExp;
+import dmd.Dsymbol;
+import dmd.ScopeDsymbol;
+import dmd.TY;
+import dmd.TypeSArray;
+
+import dmd.backend.elem;
+import dmd.backend.Util;
+import dmd.codegen.Util;
+
+class AddrExp : UnaExp
+{
+	this(Loc loc, Expression e)
+	{
+		super(loc, TOK.TOKaddress, AddrExp.sizeof, e);
+	}
+
+	Expression semantic(Scope sc)
+	{
+	version (LOGSEMANTIC) {
+		printf("AddrExp.semantic('%s')\n", toChars());
+	}
+		if (!type)
+		{
+			UnaExp.semantic(sc);
+			e1 = e1.toLvalue(sc, null);
+			if (!e1.type)
+			{
+				error("cannot take address of %s", e1.toChars());
+				return new ErrorExp();
+			}
+			if (!e1.type.deco)
+			{
+				/* No deco means semantic() was not run on the type.
+				 * We have to run semantic() on the symbol to get the right type:
+				 *	auto x = &bar;
+				 *	pure: int bar() { return 1;}
+				 * otherwise the 'pure' is missing from the type assigned to x.
+				 */
+
+				error("forward reference to %s", e1.toChars());
+				return new ErrorExp();
+			}
+
+		//printf("test3 deco = %p\n", e1.type.deco);
+			type = e1.type.pointerTo();
+
+			// See if this should really be a delegate
+			if (e1.op == TOKdotvar)
+			{
+				DotVarExp dve = cast(DotVarExp)e1;
+				FuncDeclaration f = dve.var.isFuncDeclaration();
+
+				if (f)
+				{
+					if (!dve.hasOverloads)
+						f.tookAddressOf++;
+					Expression e = new DelegateExp(loc, dve.e1, f, dve.hasOverloads);
+					e = e.semantic(sc);
+					return e;
+				}
+			}
+			else if (e1.op == TOKvar)
+			{
+				VarExp ve = cast(VarExp)e1;
+
+				VarDeclaration v = ve.var.isVarDeclaration();
+				if (v && !v.canTakeAddressOf())
+					error("cannot take address of %s", e1.toChars());
+
+				FuncDeclaration f = ve.var.isFuncDeclaration();
+
+				if (f)
+				{
+					if (!ve.hasOverloads ||
+						/* Because nested functions cannot be overloaded,
+						 * mark here that we took its address because castTo()
+						 * may not be called with an exact match.
+						 */
+						f.toParent2().isFuncDeclaration())
+						f.tookAddressOf++;
+
+					if (f.isNested())
+					{
+						Expression e = new DelegateExp(loc, e1, f, ve.hasOverloads);
+						e = e.semantic(sc);
+						return e;
+					}
+					if (f.needThis() && hasThis(sc))
+					{
+						/* Should probably supply 'this' after overload resolution,
+						 * not before.
+						 */
+						Expression ethis = new ThisExp(loc);
+						Expression e = new DelegateExp(loc, ethis, f, ve.hasOverloads);
+						e = e.semantic(sc);
+						return e;
+					}
+				}
+			}
+			return optimize(WANTvalue);
+		}
+		return this;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e;
+
+		//printf("AddrExp.toElem('%s')\n", toChars());
+
+		e = e1.toElem(irs);
+		e = addressElem(e, e1.type);
+	L2:
+		e.Ety = type.totym();
+		el_setLoc(e,loc);
+		return e;
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+	static if (false) {
+		printf("AddrExp.implicitConvTo(this=%s, type=%s, t=%s)\n",
+		toChars(), type.toChars(), t.toChars());
+	}
+		MATCH result;
+
+		result = type.implicitConvTo(t);
+		//printf("\tresult = %d\n", result);
+
+		if (result == MATCHnomatch)
+		{
+			// Look for pointers to functions where the functions are overloaded.
+
+			t = t.toBasetype();
+
+			if (e1.op == TOKoverloadset &&
+				(t.ty == Tpointer || t.ty == Tdelegate) && t.nextOf().ty == Tfunction)
+			{   
+				OverExp eo = cast(OverExp)e1;
+				FuncDeclaration f = null;
+				for (int i = 0; i < eo.vars.a.dim; i++)
+				{   
+					Dsymbol s = cast(Dsymbol)eo.vars.a.data[i];
+					FuncDeclaration f2 = s.isFuncDeclaration();
+					assert(f2);
+					if (f2.overloadExactMatch(t.nextOf()))
+					{   
+						if (f)
+							/* Error if match in more than one overload set,
+							 * even if one is a 'better' match than the other.
+							 */
+							ScopeDsymbol.multiplyDefined(loc, f, f2);
+						else
+							f = f2;
+						result = MATCHexact;
+					}
+				}
+			}
+
+			if (type.ty == Tpointer && type.nextOf().ty == Tfunction &&
+				t.ty == Tpointer && t.nextOf().ty == Tfunction &&
+				e1.op == TOKvar)
+			{
+				/* I don't think this can ever happen -
+				 * it should have been
+				 * converted to a SymOffExp.
+				 */
+				assert(0);
+				VarExp ve = cast(VarExp)e1;
+				FuncDeclaration f = ve.var.isFuncDeclaration();
+				if (f && f.overloadExactMatch(t.nextOf()))
+					result = MATCHexact;
+			}
+		}
+
+		//printf("\tresult = %d\n", result);
+		return result;
+	}
+
+	Expression castTo(Scope sc, Type t)
+	{
+	    Type tb;
+
+	static if (false) {
+		printf("AddrExp.castTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars());
+	}
+		Expression e = this;
+
+		tb = t.toBasetype();
+		type = type.toBasetype();
+		if (tb != type)
+		{
+			// Look for pointers to functions where the functions are overloaded.
+
+			if (e1.op == TOKoverloadset &&
+				(t.ty == Tpointer || t.ty == Tdelegate) && t.nextOf().ty == Tfunction)
+			{   
+				OverExp eo = cast(OverExp)e1;
+				FuncDeclaration f = null;
+				for (int i = 0; i < eo.vars.a.dim; i++)
+				{   
+					Dsymbol s = cast(Dsymbol)eo.vars.a.data[i];
+					FuncDeclaration f2 = s.isFuncDeclaration();
+					assert(f2);
+					if (f2.overloadExactMatch(t.nextOf()))
+					{   
+						if (f)
+							/* Error if match in more than one overload set,
+							 * even if one is a 'better' match than the other.
+							 */
+							ScopeDsymbol.multiplyDefined(loc, f, f2);
+						else
+							f = f2;
+					}
+				}
+				if (f)
+				{	
+					f.tookAddressOf++;
+					SymOffExp se = new SymOffExp(loc, f, 0, 0);
+					se.semantic(sc);
+					// Let SymOffExp.castTo() do the heavy lifting
+					return se.castTo(sc, t);
+				}
+			}
+
+
+			if (type.ty == Tpointer && type.nextOf().ty == Tfunction &&
+				tb.ty == Tpointer && tb.nextOf().ty == Tfunction &&
+				e1.op == TOKvar)
+			{
+				VarExp ve = cast(VarExp)e1;
+				FuncDeclaration f = ve.var.isFuncDeclaration();
+				if (f)
+				{
+					assert(0);	// should be SymOffExp instead
+					f = f.overloadExactMatch(tb.nextOf());
+					if (f)
+					{
+						e = new VarExp(loc, f);
+						e.type = f.type;
+						e = new AddrExp(loc, e);
+						e.type = t;
+						return e;
+					}
+				}
+			}
+			e = Expression.castTo(sc, t);
+		}
+		e.type = t;
+		return e;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		//printf("AddrExp.optimize(result = %d) %s\n", result, toChars());
+
+		/* Rewrite &(a,b) as (a,&b)
+		 */
+		if (e1.op == TOKcomma)
+		{	
+			CommaExp ce = cast(CommaExp)e1;
+			AddrExp ae = new AddrExp(loc, ce.e2);
+			ae.type = type;
+			e = new CommaExp(ce.loc, ce.e1, ae);
+			e.type = type;
+			return e.optimize(result);
+		}
+
+		if (e1.op == TOKvar)
+		{	
+			VarExp ve = cast(VarExp)e1;
+			if (ve.var.storage_class & STCmanifest)
+				e1 = e1.optimize(result);
+		}
+		else
+			e1 = e1.optimize(result);
+
+		// Convert &*ex to ex
+		if (e1.op == TOKstar)
+		{	
+			Expression ex;
+
+			ex = (cast(PtrExp)e1).e1;
+			if (type.equals(ex.type))
+				e = ex;
+			else
+			{
+				e = ex.copy();
+				e.type = type;
+			}
+			return e;
+		}
+		if (e1.op == TOKvar)
+		{	
+			VarExp ve = cast(VarExp)e1;
+			if (!ve.var.isOut() && !ve.var.isRef() &&
+				!ve.var.isImportedSymbol())
+			{
+				SymOffExp se = new SymOffExp(loc, ve.var, 0, ve.hasOverloads);
+				se.type = type;
+				return se;
+			}
+		}
+		if (e1.op == TOKindex)
+		{	
+			// Convert &array[n] to &array+n
+			IndexExp ae = cast(IndexExp)e1;
+
+			if (ae.e2.op == TOKint64 && ae.e1.op == TOKvar)
+			{
+				long index = ae.e2.toInteger();
+				VarExp ve = cast(VarExp)ae.e1;
+				if (ve.type.ty == Tsarray
+					&& !ve.var.isImportedSymbol())
+				{
+					TypeSArray ts = cast(TypeSArray)ve.type;
+					long dim = ts.dim.toInteger();
+					if (index < 0 || index >= dim)
+						error("array index %jd is out of bounds [0..%jd]", index, dim);
+					e = new SymOffExp(loc, ve.var, cast(uint)(index * ts.nextOf().size()));
+					e.type = type;
+					return e;
+				}
+			}
+		}
+		return this;
+	}
+}
+