Mercurial > projects > ddmd
annotate dmd/AssertExp.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | af724d3510d7 |
children | cd48cb899aee |
rev | line source |
---|---|
72 | 1 module dmd.AssertExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.backend.elem; | |
6 import dmd.UnaExp; | |
7 import dmd.InterState; | |
8 import dmd.OutBuffer; | |
9 import dmd.Loc; | |
10 import dmd.Scope; | |
11 import dmd.InlineCostState; | |
12 import dmd.InlineDoState; | |
13 import dmd.IRState; | |
14 import dmd.HdrGenState; | |
0 | 15 import dmd.InlineScanState; |
16 import dmd.Type; | |
17 import dmd.Global; | |
72 | 18 import dmd.InvariantDeclaration; |
0 | 19 import dmd.TOK; |
174 | 20 import dmd.PREC; |
0 | 21 import dmd.TY; |
22 import dmd.TypeClass; | |
23 import dmd.Module; | |
24 import dmd.WANT; | |
25 import dmd.FuncDeclaration; | |
26 import dmd.HaltExp; | |
27 import dmd.TypeStruct; | |
28 import dmd.backend.Util; | |
29 import dmd.codegen.Util; | |
30 import dmd.backend.OPER; | |
31 import dmd.backend.TYM; | |
32 import dmd.backend.RTLSYM; | |
33 import dmd.backend.Symbol; | |
34 import dmd.backend.dt_t; | |
35 import dmd.backend.SC; | |
72 | 36 import dmd.backend.FL; |
0 | 37 |
174 | 38 import dmd.expression.Util; |
39 | |
0 | 40 import core.stdc.string; |
41 import std.string : toStringz; | |
42 | |
165
25ede4f66bda
Temporarily disabled GC (again) because phobos fails to compile with it (looks like some ObjSymbols are being falsely collected, see Library.d:666)
korDen
parents:
114
diff
changeset
|
43 //static __gshared Symbol* assertexp_sfilename = null; |
25ede4f66bda
Temporarily disabled GC (again) because phobos fails to compile with it (looks like some ObjSymbols are being falsely collected, see Library.d:666)
korDen
parents:
114
diff
changeset
|
44 //static __gshared string assertexp_name = null; |
25ede4f66bda
Temporarily disabled GC (again) because phobos fails to compile with it (looks like some ObjSymbols are being falsely collected, see Library.d:666)
korDen
parents:
114
diff
changeset
|
45 //static __gshared Module assertexp_mn = null; |
72 | 46 |
0 | 47 class AssertExp : UnaExp |
48 { | |
49 Expression msg; | |
50 | |
51 this(Loc loc, Expression e, Expression msg = null) | |
52 { | |
178 | 53 register(); |
54 | |
0 | 55 super(loc, TOK.TOKassert, AssertExp.sizeof, e); |
56 this.msg = msg; | |
57 } | |
58 | |
72 | 59 override Expression syntaxCopy() |
0 | 60 { |
72 | 61 AssertExp ae = new AssertExp(loc, e1.syntaxCopy(), |
62 msg ? msg.syntaxCopy() : null); | |
53 | 63 return ae; |
0 | 64 } |
65 | |
72 | 66 override Expression semantic(Scope sc) |
0 | 67 { |
68 version (LOGSEMANTIC) { | |
69 printf("AssertExp.semantic('%s')\n", toChars()); | |
70 } | |
71 UnaExp.semantic(sc); | |
72 e1 = resolveProperties(sc, e1); | |
73 // BUG: see if we can do compile time elimination of the Assert | |
74 e1 = e1.optimize(WANTvalue); | |
75 e1 = e1.checkToBoolean(); | |
76 if (msg) | |
77 { | |
78 msg = msg.semantic(sc); | |
79 msg = resolveProperties(sc, msg); | |
80 msg = msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf()); | |
81 msg = msg.optimize(WANTvalue); | |
82 } | |
83 if (e1.isBool(false)) | |
84 { | |
85 FuncDeclaration fd = sc.parent.isFuncDeclaration(); | |
86 fd.hasReturnExp |= 4; | |
87 | |
88 if (!global.params.useAssert) | |
174 | 89 { |
0 | 90 Expression e = new HaltExp(loc); |
91 e = e.semantic(sc); | |
92 return e; | |
93 } | |
94 } | |
95 type = Type.tvoid; | |
96 return this; | |
97 } | |
98 | |
72 | 99 override Expression interpret(InterState istate) |
0 | 100 { |
101 assert(false); | |
102 } | |
103 | |
72 | 104 override bool checkSideEffect(int flag) |
0 | 105 { |
106 return true; | |
107 } | |
108 | |
109 version (DMDV2) { | |
72 | 110 override bool canThrow() |
0 | 111 { |
112 /* assert()s are non-recoverable errors, so functions that | |
113 * use them can be considered "nothrow" | |
114 */ | |
165
25ede4f66bda
Temporarily disabled GC (again) because phobos fails to compile with it (looks like some ObjSymbols are being falsely collected, see Library.d:666)
korDen
parents:
114
diff
changeset
|
115 return false; //(global.params.useAssert != 0); |
0 | 116 } |
117 } | |
72 | 118 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 119 { |
174 | 120 buf.writestring("assert("); |
121 expToCBuffer(buf, hgs, e1, PREC.PREC_assign); | |
122 if (msg) | |
123 { | |
124 buf.writeByte(','); | |
125 expToCBuffer(buf, hgs, msg, PREC_assign); | |
126 } | |
127 buf.writeByte(')'); | |
0 | 128 } |
129 | |
72 | 130 override int inlineCost(InlineCostState* ics) |
0 | 131 { |
132 return 1 + e1.inlineCost(ics) + (msg ? msg.inlineCost(ics) : 0); | |
133 } | |
134 | |
72 | 135 override Expression doInline(InlineDoState ids) |
0 | 136 { |
137 AssertExp ae = cast(AssertExp)copy(); | |
138 | |
139 ae.e1 = e1.doInline(ids); | |
140 if (msg) | |
141 ae.msg = msg.doInline(ids); | |
142 return ae; | |
143 } | |
144 | |
72 | 145 override Expression inlineScan(InlineScanState* iss) |
0 | 146 { |
147 e1 = e1.inlineScan(iss); | |
148 if (msg) | |
149 msg = msg.inlineScan(iss); | |
150 return this; | |
151 } | |
174 | 152 |
0 | 153 static private void* castToVoid(int i) |
154 { | |
155 return cast(void*)i; | |
156 } | |
157 | |
72 | 158 override elem* toElem(IRState* irs) |
0 | 159 { |
160 elem* e; | |
161 elem* ea; | |
162 Type t1 = e1.type.toBasetype(); | |
163 | |
164 //printf("AssertExp.toElem() %s\n", toChars()); | |
165 if (global.params.useAssert) | |
166 { | |
167 e = e1.toElem(irs); | |
168 | |
169 InvariantDeclaration inv = cast(InvariantDeclaration)castToVoid(1); | |
170 | |
171 // If e1 is a class object, call the class invariant on it | |
172 if (global.params.useInvariants && t1.ty == Tclass && | |
173 !(cast(TypeClass)t1).sym.isInterfaceDeclaration()) | |
174 { | |
22
fd4acc376c45
Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
175 version (POSIX) {///TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS |
0 | 176 e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM__DINVARIANT]), e); |
177 } else { | |
178 e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DINVARIANT]), e); | |
179 } | |
180 } | |
181 // If e1 is a struct object, call the struct invariant on it | |
182 else if (global.params.useInvariants && | |
183 t1.ty == Tpointer && | |
184 t1.nextOf().ty == Tstruct && | |
185 (inv = (cast(TypeStruct)t1.nextOf()).sym.inv) !is null) | |
186 { | |
187 e = callfunc(loc, irs, 1, inv.type.nextOf(), e, e1.type, inv, inv.type, null, null); | |
188 } | |
189 else | |
190 { | |
191 // Construct: (e1 || ModuleAssert(line)) | |
192 Symbol* sassert; | |
193 Module m = irs.blx.module_; | |
194 string mname = m.srcfile.toChars(); | |
195 | |
196 //printf("filename = '%s'\n", loc.filename); | |
197 //printf("module = '%s'\n", m.srcfile.toChars()); | |
198 | |
199 /* If the source file name has changed, probably due | |
200 * to a #line directive. | |
201 */ | |
202 if (loc.filename && (msg || loc.filename != mname)) | |
174 | 203 { |
0 | 204 elem* efilename; |
205 | |
206 /* Cache values. | |
207 */ | |
165
25ede4f66bda
Temporarily disabled GC (again) because phobos fails to compile with it (looks like some ObjSymbols are being falsely collected, see Library.d:666)
korDen
parents:
114
diff
changeset
|
208 Symbol* assertexp_sfilename = null; |
25ede4f66bda
Temporarily disabled GC (again) because phobos fails to compile with it (looks like some ObjSymbols are being falsely collected, see Library.d:666)
korDen
parents:
114
diff
changeset
|
209 string assertexp_name = null; |
25ede4f66bda
Temporarily disabled GC (again) because phobos fails to compile with it (looks like some ObjSymbols are being falsely collected, see Library.d:666)
korDen
parents:
114
diff
changeset
|
210 Module assertexp_mn = null; |
0 | 211 |
212 if (!assertexp_sfilename || loc.filename != assertexp_name || assertexp_mn != m) | |
213 { | |
214 dt_t* dt = null; | |
215 | |
216 string id = loc.filename; | |
217 int len = id.length; | |
218 dtdword(&dt, len); | |
219 dtabytes(&dt,TYnptr, 0, len + 1, toStringz(id)); | |
220 | |
221 assertexp_sfilename = symbol_generate(SCstatic,type_fake(TYdarray)); | |
222 assertexp_sfilename.Sdt = dt; | |
223 assertexp_sfilename.Sfl = FLdata; | |
224 version (ELFOBJ) { | |
22
fd4acc376c45
Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
225 assertexp_sfilename.Sseg = Segment.CDATA; |
0 | 226 } |
227 version (MACHOBJ) { | |
22
fd4acc376c45
Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
228 assertexp_sfilename.Sseg = Segment.DATA; |
0 | 229 } |
230 outdata(assertexp_sfilename); | |
231 | |
232 assertexp_mn = m; | |
233 assertexp_name = id; | |
234 } | |
235 | |
236 efilename = el_var(assertexp_sfilename); | |
237 | |
238 if (msg) | |
174 | 239 { |
0 | 240 elem* emsg = msg.toElem(irs); |
241 ea = el_var(rtlsym[RTLSYM_DASSERT_MSG]); | |
242 ea = el_bin(OPcall, TYvoid, ea, el_params(el_long(TYint, loc.linnum), efilename, emsg, null)); | |
243 } | |
244 else | |
245 { | |
246 ea = el_var(rtlsym[RTLSYM_DASSERT]); | |
247 ea = el_bin(OPcall, TYvoid, ea, el_param(el_long(TYint, loc.linnum), efilename)); | |
248 } | |
249 } | |
250 else | |
251 { | |
252 sassert = m.toModuleAssert(); | |
253 ea = el_bin(OPcall,TYvoid,el_var(sassert), | |
254 el_long(TYint, loc.linnum)); | |
255 } | |
256 e = el_bin(OPoror,TYvoid,e,ea); | |
257 } | |
258 } | |
259 else | |
174 | 260 { |
0 | 261 // BUG: should replace assert(0); with a HLT instruction |
262 e = el_long(TYint, 0); | |
263 } | |
264 el_setLoc(e,loc); | |
265 | |
266 return e; | |
267 } | |
268 } | |
269 |