diff dmd/SymOffExp.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 4290d870944a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/SymOffExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,230 @@
+module dmd.SymOffExp;
+
+import dmd.Expression;
+import dmd.Declaration;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineDoState;
+import dmd.HdrGenState;
+import dmd.backend.dt_t;
+import dmd.SymbolExp;
+import dmd.VarDeclaration;
+import dmd.DelegateExp;
+import dmd.ThisExp;
+import dmd.FuncDeclaration;
+import dmd.IntegerExp;
+import dmd.ErrorExp;
+import dmd.TY;
+import dmd.TOK;
+
+import dmd.backend.Symbol;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+
+class SymOffExp : SymbolExp
+{
+	uint offset;
+
+	this(Loc loc, Declaration var, uint offset, int hasOverloads = 0)
+	{
+		super(loc, TOK.TOKsymoff, SymOffExp.sizeof, var, hasOverloads);
+		
+		this.offset = offset;
+		VarDeclaration v = var.isVarDeclaration();
+		if (v && v.needThis())
+			error("need 'this' for address of %s", v.toChars());
+	}
+
+	Expression semantic(Scope sc)
+	{
+	version(LOGSEMANTIC) {
+		printf("SymOffExp::semantic('%s')\n", toChars());
+	}
+		//var.semantic(sc);
+		if (!type)
+			type = var.type.pointerTo();
+		VarDeclaration v = var.isVarDeclaration();
+		if (v)
+			v.checkNestedReference(sc, loc);
+		return this;
+	}
+
+	void checkEscape()
+	{
+		VarDeclaration v = var.isVarDeclaration();
+		if (v)
+		{
+			if (!v.isDataseg())
+				error("escaping reference to local variable %s", v.toChars());
+		}
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	int isConst()
+	{
+		return 2;
+	}
+
+	bool isBool(bool result)
+	{
+		assert(false);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		int i;
+
+		//printf("SymOffExp.doInline(%s)\n", toChars());
+		for (i = 0; i < ids.from.dim; i++)
+		{
+			if (var is cast(Declaration)ids.from.data[i])
+			{
+				SymOffExp se = cast(SymOffExp)copy();
+
+				se.var = cast(Declaration)ids.to.data[i];
+				return se;
+			}
+		}
+		return this;
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+	static if (false) {
+		printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars());
+	}
+		MATCH result = type.implicitConvTo(t);
+		//printf("\tresult = %d\n", result);
+
+		if (result == MATCHnomatch)
+		{
+			// Look for pointers to functions where the functions are overloaded.
+			FuncDeclaration f;
+
+			t = t.toBasetype();
+			if (type.ty == Tpointer && type.nextOf().ty == Tfunction &&
+				(t.ty == Tpointer || t.ty == Tdelegate) && t.nextOf().ty == Tfunction)
+			{
+				f = var.isFuncDeclaration();
+				if (f)
+				{	
+					f = f.overloadExactMatch(t.nextOf());
+					if (f)
+					{   
+						if ((t.ty == Tdelegate && (f.needThis() || f.isNested())) ||
+							(t.ty == Tpointer && !(f.needThis() || f.isNested())))
+						{
+							result = MATCHexact;
+						}
+					}
+				}
+			}
+		}
+		//printf("\tresult = %d\n", result);
+		return result;
+	}
+
+	Expression castTo(Scope sc, Type t)
+	{
+	static if (false) {
+		printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars());
+	}
+		if (type == t && hasOverloads == 0)
+			return this;
+
+		Expression e;
+		Type tb = t.toBasetype();
+		Type typeb = type.toBasetype();
+
+		if (tb != typeb)
+		{
+			// Look for pointers to functions where the functions are overloaded.
+			FuncDeclaration f;
+
+			if (hasOverloads &&
+				typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
+				(tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
+			{
+				f = var.isFuncDeclaration();
+				if (f)
+				{
+					f = f.overloadExactMatch(tb.nextOf());
+					if (f)
+					{
+						if (tb.ty == Tdelegate)
+						{
+							if (f.needThis() && hasThis(sc))
+							{
+								e = new DelegateExp(loc, new ThisExp(loc), f);
+								e = e.semantic(sc);
+							}
+							else if (f.isNested())
+							{
+								e = new DelegateExp(loc, new IntegerExp(0), f);
+								e = e.semantic(sc);
+							}
+							else if (f.needThis())
+							{   
+								error("no 'this' to create delegate for %s", f.toChars());
+								e = new ErrorExp();
+							}
+							else
+							{   
+								error("cannot cast from function pointer to delegate");
+								e = new ErrorExp();
+							}
+						}
+						else
+						{
+							e = new SymOffExp(loc, f, 0);
+							e.type = t;
+						}
+			version (DMDV2) {
+						f.tookAddressOf++;
+			}
+						return e;
+					}
+				}
+			}
+			e = Expression.castTo(sc, t);
+		}
+		else
+		{	
+			e = copy();
+			e.type = t;
+			(cast(SymOffExp)e).hasOverloads = 0;
+		}
+		return e;
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	dt_t** toDt(dt_t** pdt)
+	{
+		//printf("SymOffExp.toDt('%s')\n", var.toChars());
+		assert(var);
+		if (!(var.isDataseg() || var.isCodeseg()) ||
+			var.needThis() ||
+			var.isThreadlocal()
+		)
+		{
+			debug writef("SymOffExp.toDt()\n");
+			error("non-constant expression %s", toChars());
+			return pdt;
+		}
+
+		Symbol* s = var.toSymbol();
+		return dtxoff(pdt, s, offset, TYnptr);
+	}
+}
+