@@ -239,23 +239,105 @@ fn void Generator.emitStmt(Generator* gen, Stmt* s, u32 indent, bool newline) {
239239 break;
240240 case Assert:
241241 if (!gen.enable_asserts) break;
242+ gen.emitAssertStmt(cast<AssertStmt*>(s), indent);
243+ break;
244+ }
245+ }
242246
243- AssertStmt* a = cast<AssertStmt*>(s);
244- source_mgr.Location loc = gen.sm.locate(s.getLoc());
245- const char* funcname = gen.cur_function.asDecl().getFullName();
246-
247- out.add1('(');
248- Expr* inner = a.getInner();
249- gen.emitExpr(out, inner);
250- out.print(") || c2_assert(\"%s\", %d, \"%s\", \"", loc.filename, loc.line, funcname);
251- // encode expression as a string
252- string_buffer.Buf* str = string_buffer.create(128, false, 0);
253- inner.printLiteral(str);
254- out.encodeBytes(str.data(), str.size(), '"');
255- str.free();
256- out.add("\");\n");
247+ fn const char* get_type_format(Expr* e) {
248+ QualType qt = e.getType();
249+ QualType canon = qt.getCanonicalType();
250+ if (canon.isPointer() || canon.isFunction()) return "p";
251+ const Type* t = canon.getTypeOrNil();
252+ if (canon.isEnum()) {
253+ // output numeric value
254+ EnumType* et = (EnumType*)t;
255+ canon = et.getImplType();
256+ t = canon.getTypeOrNil();
257+ }
258+ const BuiltinType* bi = (BuiltinType*)t;
259+ switch (bi.getBaseKind()) {
260+ case Char:
261+ case Int8:
262+ case Int16:
263+ case Int32:
264+ return "d";
265+ case Int64:
266+ return "ld";
267+ case UInt8:
268+ case UInt16:
269+ case UInt32:
270+ return "u";
271+ case UInt64:
272+ return "lu";
273+ case Float32:
274+ case Float64:
275+ return "g";
276+ case Bool:
277+ return "d";
278+ case ISize: // not a base kind
279+ case USize: // not a base kind
280+ case Void:
257281 break;
258282 }
283+ return nil;
284+ }
285+
286+ // encode expression as a string
287+ fn void encode_expression(string_buffer.Buf* out, Expr* e) {
288+ char[128] tmp;
289+ string_buffer.Buf buf.init(tmp, elemsof(tmp), false, false, 0);
290+ e.printLiteral(&buf);
291+ const char* s = buf.data();
292+ for (const char* p = s;; p++) {
293+ if (!*p || *p == '%') {
294+ out.encodeBytes(s, (u32)(p - s), '"');
295+ if (!*p) break;
296+ if (*p == '%') out.add("%%");
297+ }
298+ }
299+ }
300+
301+ fn void Generator.emitAssertStmt(Generator* gen, AssertStmt* a, u32 indent) {
302+ string_buffer.Buf* out = gen.out;
303+ source_mgr.Location loc = gen.sm.locate(((Stmt*)a).getLoc());
304+ const char* funcname = gen.cur_function.asDecl().getFullName();
305+ Expr* inner = a.getInner();
306+ out.add1('(');
307+ gen.emitExpr(out, inner);
308+ out.print(") || c2_assert(\"%s\", %d, \"%s\", \"", loc.filename, loc.line, funcname);
309+ encode_expression(out, inner);
310+ if (inner.isComparison()) {
311+ BinaryOperator* b = (BinaryOperator*)inner;
312+ Expr* lhs = b.getLHS();
313+ Expr* rhs = b.getRHS();
314+ const char* fmt1 = lhs.isLiteral() ? nil : get_type_format(lhs);
315+ const char* fmt2 = rhs.isLiteral() ? nil : get_type_format(rhs);
316+ if (fmt1) {
317+ out.print(", ");
318+ encode_expression(out, lhs);
319+ out.print(": %%%s", fmt1);
320+ }
321+ if (fmt2) {
322+ out.print(", ");
323+ encode_expression(out, rhs);
324+ out.print(": %%%s", fmt2);
325+ }
326+ out.add1('"');
327+ if (fmt1) {
328+ out.add(", ");
329+ if (*fmt1 == 'p') out.add("(void*)");
330+ gen.emitExpr(out, lhs);
331+ }
332+ if (fmt2) {
333+ out.add(", ");
334+ if (*fmt2 == 'p') out.add("(void*)");
335+ gen.emitExpr(out, rhs);
336+ }
337+ } else {
338+ out.add1('"');
339+ }
340+ out.add(");\n");
259341}
260342
261343fn void emitAsmPart(string_buffer.Buf* out, bool multi_line, u32 indent) {
0 commit comments