@@ -237,26 +237,114 @@ 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
287+ case Void:
258288 break;
259289 }
290+ return nil;
291+ }
292+
293+ // encode expression as a string
294+ fn void encode_expression(string_buffer.Buf* out, Expr* e) {
295+ char[128] tmp;
296+ string_buffer.Buf buf.init(tmp, elemsof(tmp), false, false, 0);
297+ e.printLiteral(&buf);
298+ const char* s = buf.data();
299+ for (const char* p = s;; p++) {
300+ if (!*p || *p == '%') {
301+ out.encodeBytes(s, (u32)(p - s), '"');
302+ if (!*p) break;
303+ if (*p == '%') out.add("%%");
304+ }
305+ }
306+ }
307+
308+ fn void Generator.emitAssertStmt(Generator* gen, AssertStmt* a, u32 indent) {
309+ string_buffer.Buf* out = gen.out;
310+ source_mgr.Location loc = gen.sm.locate(((Stmt*)a).getLoc());
311+ const char* funcname = gen.cur_function.asDecl().getFullName();
312+ Expr* inner = a.getInner();
313+ out.add1('(');
314+ gen.emitExpr(out, inner);
315+ out.print(") || c2_assert(\"%s\", %d, \"%s\", \"", loc.filename, loc.line, funcname);
316+ encode_expression(out, inner);
317+ if (inner.isComparison()) {
318+ BinaryOperator* b = (BinaryOperator*)inner;
319+ Expr* lhs = b.getLHS();
320+ Expr* rhs = b.getRHS();
321+ const char* fmt1 = lhs.isLiteral() ? nil : get_type_format(lhs);
322+ const char* fmt2 = rhs.isLiteral() ? nil : get_type_format(rhs);
323+ if (fmt1) {
324+ out.print(", ");
325+ encode_expression(out, lhs);
326+ out.print(": %%%s", fmt1);
327+ }
328+ if (fmt2) {
329+ out.print(", ");
330+ encode_expression(out, rhs);
331+ out.print(": %%%s", fmt2);
332+ }
333+ out.add1('"');
334+ if (fmt1) {
335+ out.add(", ");
336+ if (*fmt1 == 'p') out.add("(void*)");
337+ gen.emitExpr(out, lhs);
338+ }
339+ if (fmt2) {
340+ out.add(", ");
341+ if (*fmt2 == 'p') out.add("(void*)");
342+ gen.emitExpr(out, rhs);
343+ }
344+ } else {
345+ out.add1('"');
346+ }
347+ out.add(");\n");
260348}
261349
262350fn void emitAsmPart(string_buffer.Buf* out, bool multi_line, u32 indent) {
0 commit comments