Mercurial > projects > ddmd
view dmd/AssertExp.d @ 77:ad4792a1cfd6
more D-ification container accessing
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Sun, 29 Aug 2010 14:36:55 +0100 |
parents | 2e2a5c3f943a |
children | e28b18c23469 |
line wrap: on
line source
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; } override Expression syntaxCopy() { AssertExp ae = new AssertExp(loc, e1.syntaxCopy(), msg ? msg.syntaxCopy() : null); return ae; } override 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; } override Expression interpret(InterState istate) { assert(false); } override bool checkSideEffect(int flag) { return true; } version (DMDV2) { override bool canThrow() { /* assert()s are non-recoverable errors, so functions that * use them can be considered "nothrow" */ return 0; //(global.params.useAssert != 0); } } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { assert(false); } override int inlineCost(InlineCostState* ics) { return 1 + e1.inlineCost(ics) + (msg ? msg.inlineCost(ics) : 0); } override Expression doInline(InlineDoState ids) { AssertExp ae = cast(AssertExp)copy(); ae.e1 = e1.doInline(ids); if (msg) ae.msg = msg.doInline(ids); return ae; } override 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; } override 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 (POSIX) {///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 = Segment.CDATA; } version (MACHOBJ) { assertexp_sfilename.Sseg = Segment.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; } }