@@ -239,23 +239,94 @@ 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+ out.add1('"');
292+ out.encodeBytes(buf.data(), buf.size(), '"');
293+ out.add1('"');
294+ }
295+
296+ fn void Generator.emitAssertStmt(Generator* gen, AssertStmt* a, u32 indent) {
297+ string_buffer.Buf* out = gen.out;
298+ source_mgr.Location loc = gen.sm.locate(((Stmt*)a).getLoc());
299+ const char* funcname = gen.cur_function.asDecl().getFullName();
300+ Expr* inner = a.getInner();
301+ out.add1('(');
302+ gen.emitExpr(out, inner);
303+ out.print(") || c2_assert(\"%s\", %d, \"%s\", ", loc.filename, loc.line, funcname);
304+ encode_expression(out, inner);
305+ out.print(", \"\"");
306+ if (inner.isComparison()) {
307+ BinaryOperator* b = (BinaryOperator*)inner;
308+ Expr* lhs = b.getLHS();
309+ Expr* rhs = b.getRHS();
310+ const char* fmt1 = lhs.isLiteral() ? nil : get_type_format(lhs);
311+ const char* fmt2 = rhs.isLiteral() ? nil : get_type_format(rhs);
312+ if (fmt1) out.print("\", %%s: %%%s\"", fmt1);
313+ if (fmt2) out.print("\", %%s: %%%s\"", fmt2);
314+ if (!lhs.isLiteral()) {
315+ out.add(", ");
316+ encode_expression(out, lhs);
317+ out.add(", ");
318+ if (*fmt1 == 'p') out.add("(void*)");
319+ gen.emitExpr(out, lhs);
320+ }
321+ if (!rhs.isLiteral()) {
322+ out.add(", ");
323+ encode_expression(out, rhs);
324+ out.add(", ");
325+ if (*fmt2 == 'p') out.add("(void*)");
326+ gen.emitExpr(out, rhs);
327+ }
328+ }
329+ out.add(");\n");
259330}
260331
261332fn void emitAsmPart(string_buffer.Buf* out, bool multi_line, u32 indent) {
0 commit comments