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