diff dmd/AssertExp.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children fd4acc376c45
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AssertExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,254 @@
+module dmd.AssertExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.InlineDoState;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.Type;
+import dmd.Global;
+import dmd.InvariantDeclaration;
+import dmd.TOK;
+import dmd.TY;
+import dmd.TypeClass;
+import dmd.Module;
+import dmd.WANT;
+import dmd.FuncDeclaration;
+import dmd.HaltExp;
+import dmd.TypeStruct;
+import dmd.backend.Util;
+import dmd.codegen.Util;
+import dmd.backend.OPER;
+import dmd.backend.TYM;
+import dmd.backend.RTLSYM;
+import dmd.backend.Symbol;
+import dmd.backend.dt_t;
+import dmd.backend.SC;
+import dmd.backend.FL;
+
+import core.stdc.string;
+import std.string : toStringz;
+
+static __gshared Symbol* assertexp_sfilename = null;
+static __gshared string assertexp_name = null;
+static __gshared Module assertexp_mn = null;
+
+class AssertExp : UnaExp
+{
+	Expression msg;
+
+	this(Loc loc, Expression e, Expression msg = null)
+	{
+		super(loc, TOK.TOKassert, AssertExp.sizeof, e);
+		this.msg = msg;
+	}
+
+	Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+	version (LOGSEMANTIC) {
+		printf("AssertExp.semantic('%s')\n", toChars());
+	}
+		UnaExp.semantic(sc);
+		e1 = resolveProperties(sc, e1);
+		// BUG: see if we can do compile time elimination of the Assert
+		e1 = e1.optimize(WANTvalue);
+		e1 = e1.checkToBoolean();
+		if (msg)
+		{
+			msg = msg.semantic(sc);
+			msg = resolveProperties(sc, msg);
+			msg = msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf());
+			msg = msg.optimize(WANTvalue);
+		}
+		if (e1.isBool(false))
+		{
+			FuncDeclaration fd = sc.parent.isFuncDeclaration();
+			fd.hasReturnExp |= 4;
+
+			if (!global.params.useAssert)
+			{   
+				Expression e = new HaltExp(loc);
+				e = e.semantic(sc);
+				return e;
+			}
+		}
+		type = Type.tvoid;
+		return this;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		return true;
+	}
+
+version (DMDV2) {
+	bool canThrow()
+	{
+		/* assert()s are non-recoverable errors, so functions that
+		 * use them can be considered "nothrow"
+		 */
+		return 0; //(global.params.useAssert != 0);
+	}
+}
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		return 1 + e1.inlineCost(ics) + (msg ? msg.inlineCost(ics) : 0);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		AssertExp ae = cast(AssertExp)copy();
+
+		ae.e1 = e1.doInline(ids);
+		if (msg)
+			ae.msg = msg.doInline(ids);
+		return ae;
+	}
+
+	Expression inlineScan(InlineScanState* iss)
+	{
+		e1 = e1.inlineScan(iss);
+		if (msg)
+			msg = msg.inlineScan(iss);
+		return this;
+	}
+	
+	static private void* castToVoid(int i)
+	{
+		return cast(void*)i;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e;
+		elem* ea;
+		Type t1 = e1.type.toBasetype();
+
+		//printf("AssertExp.toElem() %s\n", toChars());
+		if (global.params.useAssert)
+		{
+			e = e1.toElem(irs);
+
+			InvariantDeclaration inv = cast(InvariantDeclaration)castToVoid(1);
+
+			// If e1 is a class object, call the class invariant on it
+			if (global.params.useInvariants && t1.ty == Tclass &&
+				!(cast(TypeClass)t1).sym.isInterfaceDeclaration())
+			{
+		version (XXX) {///TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS
+				e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM__DINVARIANT]), e);
+		} else {
+				e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DINVARIANT]), e);
+		}
+			}
+			// If e1 is a struct object, call the struct invariant on it
+			else if (global.params.useInvariants &&
+				t1.ty == Tpointer &&
+				t1.nextOf().ty == Tstruct &&
+				(inv = (cast(TypeStruct)t1.nextOf()).sym.inv) !is null)
+			{
+				e = callfunc(loc, irs, 1, inv.type.nextOf(), e, e1.type, inv, inv.type, null, null);
+			}
+			else
+			{
+				// Construct: (e1 || ModuleAssert(line))
+				Symbol* sassert;
+				Module m = irs.blx.module_;
+				string mname = m.srcfile.toChars();
+
+				//printf("filename = '%s'\n", loc.filename);
+				//printf("module = '%s'\n", m.srcfile.toChars());
+
+				/* If the source file name has changed, probably due
+				 * to a #line directive.
+				 */
+				if (loc.filename && (msg || loc.filename != mname))
+				{	
+					elem* efilename;
+
+					/* Cache values.
+					 */
+					//static Symbol *assertexp_sfilename = null;
+					//static char *assertexp_name = null;
+					//static Module *assertexp_mn = null;
+
+					if (!assertexp_sfilename || loc.filename != assertexp_name || assertexp_mn != m)
+					{
+						dt_t* dt = null;
+
+						string id = loc.filename;
+						int len = id.length;
+						dtdword(&dt, len);
+						dtabytes(&dt,TYnptr, 0, len + 1, toStringz(id));
+
+						assertexp_sfilename = symbol_generate(SCstatic,type_fake(TYdarray));
+						assertexp_sfilename.Sdt = dt;
+						assertexp_sfilename.Sfl = FLdata;
+			version (ELFOBJ) {
+						assertexp_sfilename.Sseg = CDATA;
+			}
+			version (MACHOBJ) {
+						assertexp_sfilename.Sseg = DATA;
+			}
+						outdata(assertexp_sfilename);
+
+						assertexp_mn = m;
+						assertexp_name = id;
+					}
+
+					efilename = el_var(assertexp_sfilename);
+
+					if (msg)
+					{   
+						elem* emsg = msg.toElem(irs);
+						ea = el_var(rtlsym[RTLSYM_DASSERT_MSG]);
+						ea = el_bin(OPcall, TYvoid, ea, el_params(el_long(TYint, loc.linnum), efilename, emsg, null));
+					}
+					else
+					{
+						ea = el_var(rtlsym[RTLSYM_DASSERT]);
+						ea = el_bin(OPcall, TYvoid, ea, el_param(el_long(TYint, loc.linnum), efilename));
+					}
+				}
+				else
+				{
+					sassert = m.toModuleAssert();
+					ea = el_bin(OPcall,TYvoid,el_var(sassert),
+						el_long(TYint, loc.linnum));
+				}
+				e = el_bin(OPoror,TYvoid,e,ea);
+			}
+		}
+		else
+		{	
+			// BUG: should replace assert(0); with a HLT instruction
+			e = el_long(TYint, 0);
+		}
+		el_setLoc(e,loc);
+
+		return e;
+	}
+}
+