Mercurial > projects > ddmd
diff dmd/SymbolExp.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/SymbolExp.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,202 @@ +module dmd.SymbolExp; + +import dmd.Expression; +import dmd.Declaration; +import dmd.Loc; +import dmd.IRState; +import dmd.TOK; +import dmd.TY; +import dmd.Type; +import dmd.SymOffExp; +import dmd.FuncDeclaration; +import dmd.VarDeclaration; +import dmd.backend.OPER; +import dmd.backend.TYM; +import dmd.backend.mTY; +import dmd.backend.SC; +import dmd.backend.elem; +import dmd.backend.Symbol; +import dmd.backend.Util; +import dmd.codegen.Util; + +class SymbolExp : Expression +{ + Declaration var; + + int hasOverloads; + + this(Loc loc, TOK op, int size, Declaration var, int hasOverloads) + { + super(loc, op, size); + assert(var); + this.var = var; + this.hasOverloads = hasOverloads; + } + + elem* toElem(IRState* irs) + { + Symbol* s; + elem* e; + tym_t tym; + Type tb = (op == TOK.TOKsymoff) ? var.type.toBasetype() : type.toBasetype(); + int offset = (op == TOK.TOKsymoff) ? (cast(SymOffExp)this).offset : 0; + FuncDeclaration fd; + VarDeclaration v = var.isVarDeclaration(); + + //printf("SymbolExp::toElem('%s') %p\n", toChars(), this); + //printf("\tparent = '%s'\n", var.parent ? var.parent.toChars() : "null"); + if (op == TOK.TOKvar && var.needThis()) + { + error("need 'this' to access member %s", toChars()); + return el_long(TYM.TYint, 0); + } + s = var.toSymbol(); + fd = null; + if (var.toParent2()) + fd = var.toParent2().isFuncDeclaration(); + + int nrvo = 0; + if (fd && fd.nrvo_can && fd.nrvo_var == var) + { + s = fd.shidden; + nrvo = 1; + } + + if (s.Sclass == SC.SCauto || s.Sclass == SC.SCparameter) + { + if (fd && fd != irs.getFunc()) + { + // 'var' is a variable in an enclosing function. + elem* ethis; + int soffset; + + ethis = getEthis(loc, irs, fd); + ethis = el_una(OPER.OPaddr, TYM.TYnptr, ethis); + + if (v && v.offset) + soffset = v.offset; + else + { + soffset = s.Soffset; + /* If fd is a non-static member function of a class or struct, + * then ethis isn't the frame pointer. + * ethis is the 'this' pointer to the class/struct instance. + * We must offset it. + */ + if (fd.vthis) + { + soffset -= fd.vthis.toSymbol().Soffset; + } + //printf("\tSoffset = x%x, sthis.Soffset = x%x\n", s.Soffset, irs.sthis.Soffset); + } + + if (!nrvo) + soffset += offset; + + e = el_bin(OPER.OPadd, TYM.TYnptr, ethis, el_long(TYM.TYnptr, soffset)); + + if (op == TOK.TOKvar) + e = el_una(OPER.OPind, TYM.TYnptr, e); + if ((var.isParameter() && tb.ty == TY.Tsarray) || var.isOut() || var.isRef()) + e = el_una(OPER.OPind, s.ty(), e); + else if (op == TOK.TOKsymoff && nrvo) + { + e = el_una(OPER.OPind, TYM.TYnptr, e); + e = el_bin(OPER.OPadd, e.Ety, e, el_long(TYM.TYint, offset)); + } + goto L1; + } + } + + /* If var is a member of a closure + */ + if (v && v.offset) + { + assert(irs.sclosure); + e = el_var(irs.sclosure); + e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, v.offset)); + if (op == TOK.TOKvar) + { + e = el_una(OPER.OPind, type.totym(), e); + if (tybasic(e.Ety) == TYM.TYstruct) + e.Enumbytes = cast(uint)type.size(); + el_setLoc(e, loc); + } + if ((var.isParameter() && tb.ty == TY.Tsarray) || var.isOut() || var.isRef()) + { + e.Ety = TYM.TYnptr; + e = el_una(OPER.OPind, s.ty(), e); + } + else if (op == TOK.TOKsymoff && nrvo) + { e = el_una(OPER.OPind, TYM.TYnptr, e); + e = el_bin(OPER.OPadd, e.Ety, e, el_long(TYM.TYint, offset)); + } + else if (op == TOK.TOKsymoff) + { + e = el_bin(OPER.OPadd, e.Ety, e, el_long(TYM.TYint, offset)); + } + goto L1; + } + + if (s.Sclass == SC.SCauto && s.Ssymnum == -1) + { + //printf("\tadding symbol\n"); + symbol_add(s); + } + + if (var.isImportedSymbol()) + { + assert(op == TOK.TOKvar); + e = el_var(var.toImport()); + e = el_una(OPER.OPind,s.ty(),e); + } + else if ((var.isParameter() && tb.ty == TY.Tsarray) || var.isOut() || var.isRef()) + { + // Static arrays are really passed as pointers to the array + // Out parameters are really references + e = el_var(s); + e.Ety = TYM.TYnptr; + if (op == TOK.TOKvar) + e = el_una(OPER.OPind, s.ty(), e); + else if (offset) + e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, offset)); + } + else if (op == TOK.TOKvar) + e = el_var(s); + else + { + e = nrvo ? el_var(s) : el_ptr(s); + e = el_bin(OPER.OPadd, e.Ety, e, el_long(TYM.TYint, offset)); + } + L1: + if (op == TOK.TOKvar) + { + if (nrvo) + { + e.Ety = TYM.TYnptr; + e = el_una(OPER.OPind, 0, e); + } + if (tb.ty == TY.Tfunction) + { + tym = s.Stype.Tty; + } + else + tym = type.totym(); + e.Ejty = cast(ubyte)tym; + e.Ety = e.Ejty; + if (tybasic(tym) == TYM.TYstruct) + { + e.Enumbytes = cast(uint)type.size(); + } + else if (tybasic(tym) == TYM.TYarray) + { + e.Ejty = TYM.TYstruct; + e.Ety = e.Ejty; + e.Enumbytes = cast(uint)type.size(); + } + } + el_setLoc(e,loc); + return e; + } +} +