72
|
1 module dmd.SymbolExp;
|
|
2
|
|
3 import dmd.Expression;
|
|
4 import dmd.Declaration;
|
|
5 import dmd.Loc;
|
|
6 import dmd.IRState;
|
|
7 import dmd.TOK;
|
|
8 import dmd.TY;
|
|
9 import dmd.Type;
|
|
10 import dmd.SymOffExp;
|
|
11 import dmd.FuncDeclaration;
|
|
12 import dmd.VarDeclaration;
|
|
13 import dmd.backend.OPER;
|
|
14 import dmd.backend.TYM;
|
|
15 import dmd.backend.mTY;
|
|
16 import dmd.backend.SC;
|
|
17 import dmd.backend.elem;
|
|
18 import dmd.backend.Symbol;
|
|
19 import dmd.backend.Util;
|
|
20 import dmd.codegen.Util;
|
|
21
|
0
|
22 class SymbolExp : Expression
|
|
23 {
|
|
24 Declaration var;
|
|
25
|
|
26 int hasOverloads;
|
|
27
|
|
28 this(Loc loc, TOK op, int size, Declaration var, int hasOverloads)
|
|
29 {
|
72
|
30 super(loc, op, size);
|
|
31 assert(var);
|
|
32 this.var = var;
|
0
|
33 this.hasOverloads = hasOverloads;
|
|
34 }
|
|
35
|
72
|
36 override elem* toElem(IRState* irs)
|
0
|
37 {
|
72
|
38 Symbol* s;
|
|
39 elem* e;
|
|
40 tym_t tym;
|
|
41 Type tb = (op == TOK.TOKsymoff) ? var.type.toBasetype() : type.toBasetype();
|
|
42 int offset = (op == TOK.TOKsymoff) ? (cast(SymOffExp)this).offset : 0;
|
|
43 FuncDeclaration fd;
|
|
44 VarDeclaration v = var.isVarDeclaration();
|
|
45
|
|
46 //printf("SymbolExp::toElem('%s') %p\n", toChars(), this);
|
|
47 //printf("\tparent = '%s'\n", var.parent ? var.parent.toChars() : "null");
|
|
48 if (op == TOK.TOKvar && var.needThis())
|
|
49 {
|
|
50 error("need 'this' to access member %s", toChars());
|
|
51 return el_long(TYM.TYint, 0);
|
|
52 }
|
|
53 s = var.toSymbol();
|
|
54 fd = null;
|
|
55 if (var.toParent2())
|
|
56 fd = var.toParent2().isFuncDeclaration();
|
|
57
|
|
58 int nrvo = 0;
|
|
59 if (fd && fd.nrvo_can && fd.nrvo_var == var)
|
|
60 {
|
|
61 s = fd.shidden;
|
|
62 nrvo = 1;
|
|
63 }
|
|
64
|
|
65 if (s.Sclass == SC.SCauto || s.Sclass == SC.SCparameter)
|
|
66 {
|
|
67 if (fd && fd != irs.getFunc())
|
|
68 {
|
|
69 // 'var' is a variable in an enclosing function.
|
|
70 elem* ethis;
|
|
71 int soffset;
|
|
72
|
|
73 ethis = getEthis(loc, irs, fd);
|
|
74 ethis = el_una(OPER.OPaddr, TYM.TYnptr, ethis);
|
|
75
|
|
76 if (v && v.offset)
|
|
77 soffset = v.offset;
|
|
78 else
|
|
79 {
|
|
80 soffset = s.Soffset;
|
|
81 /* If fd is a non-static member function of a class or struct,
|
|
82 * then ethis isn't the frame pointer.
|
|
83 * ethis is the 'this' pointer to the class/struct instance.
|
|
84 * We must offset it.
|
|
85 */
|
|
86 if (fd.vthis)
|
|
87 {
|
|
88 soffset -= fd.vthis.toSymbol().Soffset;
|
|
89 }
|
|
90 //printf("\tSoffset = x%x, sthis.Soffset = x%x\n", s.Soffset, irs.sthis.Soffset);
|
|
91 }
|
|
92
|
|
93 if (!nrvo)
|
|
94 soffset += offset;
|
|
95
|
|
96 e = el_bin(OPER.OPadd, TYM.TYnptr, ethis, el_long(TYM.TYnptr, soffset));
|
|
97
|
|
98 if (op == TOK.TOKvar)
|
|
99 e = el_una(OPER.OPind, TYM.TYnptr, e);
|
|
100 if ((var.isParameter() && tb.ty == TY.Tsarray) || var.isOut() || var.isRef())
|
|
101 e = el_una(OPER.OPind, s.ty(), e);
|
|
102 else if (op == TOK.TOKsymoff && nrvo)
|
|
103 {
|
|
104 e = el_una(OPER.OPind, TYM.TYnptr, e);
|
|
105 e = el_bin(OPER.OPadd, e.Ety, e, el_long(TYM.TYint, offset));
|
|
106 }
|
|
107 goto L1;
|
|
108 }
|
|
109 }
|
|
110
|
|
111 /* If var is a member of a closure
|
|
112 */
|
|
113 if (v && v.offset)
|
|
114 {
|
|
115 assert(irs.sclosure);
|
|
116 e = el_var(irs.sclosure);
|
|
117 e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, v.offset));
|
|
118 if (op == TOK.TOKvar)
|
|
119 {
|
|
120 e = el_una(OPER.OPind, type.totym(), e);
|
|
121 if (tybasic(e.Ety) == TYM.TYstruct)
|
|
122 e.Enumbytes = cast(uint)type.size();
|
|
123 el_setLoc(e, loc);
|
|
124 }
|
|
125 if ((var.isParameter() && tb.ty == TY.Tsarray) || var.isOut() || var.isRef())
|
|
126 {
|
|
127 e.Ety = TYM.TYnptr;
|
|
128 e = el_una(OPER.OPind, s.ty(), e);
|
|
129 }
|
|
130 else if (op == TOK.TOKsymoff && nrvo)
|
|
131 { e = el_una(OPER.OPind, TYM.TYnptr, e);
|
|
132 e = el_bin(OPER.OPadd, e.Ety, e, el_long(TYM.TYint, offset));
|
|
133 }
|
|
134 else if (op == TOK.TOKsymoff)
|
|
135 {
|
|
136 e = el_bin(OPER.OPadd, e.Ety, e, el_long(TYM.TYint, offset));
|
|
137 }
|
|
138 goto L1;
|
|
139 }
|
|
140
|
|
141 if (s.Sclass == SC.SCauto && s.Ssymnum == -1)
|
|
142 {
|
|
143 //printf("\tadding symbol\n");
|
|
144 symbol_add(s);
|
|
145 }
|
|
146
|
|
147 if (var.isImportedSymbol())
|
|
148 {
|
|
149 assert(op == TOK.TOKvar);
|
|
150 e = el_var(var.toImport());
|
|
151 e = el_una(OPER.OPind,s.ty(),e);
|
|
152 }
|
|
153 else if ((var.isParameter() && tb.ty == TY.Tsarray) || var.isOut() || var.isRef())
|
|
154 {
|
|
155 // Static arrays are really passed as pointers to the array
|
|
156 // Out parameters are really references
|
|
157 e = el_var(s);
|
|
158 e.Ety = TYM.TYnptr;
|
|
159 if (op == TOK.TOKvar)
|
|
160 e = el_una(OPER.OPind, s.ty(), e);
|
|
161 else if (offset)
|
|
162 e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, offset));
|
|
163 }
|
|
164 else if (op == TOK.TOKvar)
|
|
165 e = el_var(s);
|
|
166 else
|
|
167 {
|
|
168 e = nrvo ? el_var(s) : el_ptr(s);
|
|
169 e = el_bin(OPER.OPadd, e.Ety, e, el_long(TYM.TYint, offset));
|
|
170 }
|
|
171 L1:
|
|
172 if (op == TOK.TOKvar)
|
|
173 {
|
|
174 if (nrvo)
|
|
175 {
|
|
176 e.Ety = TYM.TYnptr;
|
|
177 e = el_una(OPER.OPind, 0, e);
|
|
178 }
|
|
179 if (tb.ty == TY.Tfunction)
|
|
180 {
|
|
181 tym = s.Stype.Tty;
|
|
182 }
|
|
183 else
|
|
184 tym = type.totym();
|
|
185 e.Ejty = cast(ubyte)tym;
|
|
186 e.Ety = e.Ejty;
|
|
187 if (tybasic(tym) == TYM.TYstruct)
|
|
188 {
|
|
189 e.Enumbytes = cast(uint)type.size();
|
|
190 }
|
|
191 else if (tybasic(tym) == TYM.TYarray)
|
|
192 {
|
|
193 e.Ejty = TYM.TYstruct;
|
|
194 e.Ety = e.Ejty;
|
|
195 e.Enumbytes = cast(uint)type.size();
|
|
196 }
|
|
197 }
|
|
198 el_setLoc(e,loc);
|
0
|
199 return e;
|
|
200 }
|
|
201 }
|
|
202
|