#include"dump.h" #include"ast.h" #include"types.h" #include #include #include #include"utils.h" char *type_to_string(Type *t) { if(t->type == TYPE_TYPE_PRIMITIVE) { char ret[16] = {}; int i = 0; ret[i++] = t->primitive.isFloat ? 'f' : (t->primitive.isUnsigned ? 'u' : 'i'); snprintf(ret + i, sizeof(ret) - i, "%i", t->primitive.width); return strdup(ret); } else if(t->type == TYPE_TYPE_POINTER) { char *c = type_to_string(t->pointer.of); char *r = malp("%s*", c); free(c); return r; } else if(t->type == TYPE_TYPE_RECORD) { return malp("%s", t->record.name); } else if(t->type == TYPE_TYPE_GENERIC) { return malp("%s", t->generic.paramName); } else if(t->type == TYPE_TYPE_ARRAY) { char *of = type_to_string(t->array.of); char *len = NULL; if(t->array.lengthIsGeneric) { len = malp(""); } else { len = malp("%li", t->array.length); } char *r = malp("%s[%s]", of, len); free(of); free(len); return r; } return strdup("@unimp"); } static char *ast_dumpe(AST *tlc, AST *e) { if(!e) { return malp("(null)"); } if(e->nodeKind == AST_EXPR_PRIMITIVE) { return malp("%i", e->exprPrim.val); } else if(e->nodeKind == AST_EXPR_VAR) { ScopeItem *vte = e->exprVar.thing; if(vte->kind == SCOPEITEM_VAR) { return strdup(vte->data.var.name); } else if(vte->kind == SCOPEITEM_SYMBOL) { return strdup(vte->data.symbol.name); } else if(vte->kind == SCOPEITEM_CEXPR) { return ast_dumpe(tlc, vte->data.cexpr.concrete); } else abort(); } else if(e->nodeKind == AST_EXPR_UNARY_OP) { const char *op = NULL; switch(e->exprUnOp.operator) { case UNOP_REF: op = "&"; break; case UNOP_DEREF: op = "*"; break; case UNOP_BITWISE_NOT: op = "~"; break; case UNOP_NEGATE: op = "-"; break; case UNOP_NOT: op = "!"; break; default: abort(); } char *c = ast_dumpe(tlc, e->exprUnOp.operand); char *r = malp("%s%s", op, c); free(c); return r; } else if(e->nodeKind == AST_EXPR_BINARY_OP) { char *a = ast_dumpe(tlc, e->exprBinOp.operands[0]); char *b = ast_dumpe(tlc, e->exprBinOp.operands[1]); const char *op; switch(e->exprBinOp.operator) { case BINOP_ADD: op = "+"; break; case BINOP_SUB: op = "-"; break; case BINOP_MUL: op = "*"; break; case BINOP_DIV: op = "/"; break; case BINOP_BITWISE_AND: op = "&"; break; case BINOP_BITWISE_OR: op = "|"; break; case BINOP_BITWISE_XOR: op = "^"; break; case BINOP_EQUAL: op = "=="; break; case BINOP_NEQUAL: op = "!="; break; case BINOP_LESS: op = "<"; break; case BINOP_GREATER: op = ">"; break; case BINOP_LEQUAL: op = "<="; break; case BINOP_GEQUAL: op = ">="; break; case BINOP_MULHI: op = "*^"; break; case BINOP_LOGICAL_AND: op = "&&"; break; case BINOP_LOGICAL_OR: op = "||"; break; default: abort(); } char *r = malp("(%s %s %s)", a, op, b); free(a); free(b); return r; } else if(e->nodeKind == AST_EXPR_STACK_POINTER) { return malp("@stack"); } else if(e->nodeKind == AST_EXPR_FUNC) { char *out = NULL; if(type_is_generic(e->expression.type)) { out = malp("(generic)"); return out; } { char *rettype = type_to_string(e->expression.type->function.ret); out = malp("%s(", rettype); free(rettype); } for(int i = 0; i < e->expression.type->function.argCount; i++) { char *argtype = type_to_string(e->expression.type->function.args[i]); char *out2 = malp(i == e->expression.type->function.argCount - 1 ? "%s%s" : "%s%s, ", out, argtype); free(out); free(argtype); out = out2; } { char *choonk = ast_dumpc(tlc, e->exprFunc.chunk); char *out2 = malp("%s) {\n%s}", out, choonk); free(out); free(choonk); out = out2; } return out; } else if(e->nodeKind == AST_EXPR_CALL) { char *w = ast_dumpe(tlc, e->exprCall.what); char *out = malp("%s(", w); free(w); size_t argCount = e->exprCall.what->expression.type->pointer.of->function.argCount; for(size_t i = 0; i < argCount; i++) { char *a = ast_dumpe(tlc, e->exprCall.args[i]); char *out2 = malp(i == argCount - 1 ? "%s%s)" : "%s%s, ", out, a); free(a); free(out); out = out2; } return out; } else if(e->nodeKind == AST_EXPR_EXT_SALLOC) { char *w = type_to_string(e->exprExtSalloc.size); char *out = malp("@salloc(%s)", w); free(w); return out; } else if(e->nodeKind == AST_EXPR_CAST) { char *a = ast_dumpe(tlc, e->exprCast.what); char *b = type_to_string(e->exprCast.to); char *out = malp("(%s as %s)", a, b); free(a); free(b); return out; } else if(e->nodeKind == AST_EXPR_DOT) { char *a = ast_dumpe(tlc, e->exprDot.a); char *out = malp(e->nodeKind == AST_EXPR_BINARY_OP ? "(%s).%s" : "%s.%s", a, e->exprDot.b); free(a); return out; } return malp("@unimp:%s", AST_KIND_STR[e->nodeKind]); } static char *ast_dumps(AST *tlc, AST *s) { if(s->nodeKind == AST_STMT_ASSIGN) { if(s->stmtAssign.to) { char *a = ast_dumpe(tlc, s->stmtAssign.what); char *b = ast_dumpe(tlc, s->stmtAssign.to); char *r = malp("%s = %s;", a, b); free(a); free(b); return r; } else { char *a = ast_dumpe(tlc, s->stmtAssign.what); char *r = malp("%s = ; /* fake def */", a); free(a); return r; } } else if(s->nodeKind == AST_STMT_JUMP) { char *a = ast_dumpe(tlc, s->stmtJump.condition); char *r = malp("jump %s if %s;", s->stmtJump.label, a); free(a); return r; } else if(s->nodeKind == AST_STMT_LABEL) { return malp("@label %s;", s->stmtLabel.name); } else if(s->nodeKind == AST_STMT_LOOP) { char *inner = ast_dumpc(tlc, s->stmtLoop.body); char *c = malp("loop {\n%s}", inner); free(inner); return c; } else if(s->nodeKind == AST_STMT_IF) { char *cond = ast_dumpe(tlc, s->stmtIf.expression); char *inner = ast_dumpc(tlc, s->stmtIf.then); char *elss = s->stmtIf.elss ? ast_dumpc(tlc, s->stmtIf.elss) : NULL; char *c; if(elss) { c = malp("if(%s) {\n%s} else {\n%s}", cond, inner, elss); free(elss); } else { c = malp("if(%s) {\n%s}", cond, inner); } free(cond); free(inner); return c; } else if(s->nodeKind == AST_STMT_EXPR && s->stmtExpr.expr->nodeKind == AST_EXPR_VAR) { const char *name; if(s->stmtExpr.expr->exprVar.thing->kind == SCOPEITEM_VAR) { name = s->stmtExpr.expr->exprVar.thing->data.var.name; } else { name = s->stmtExpr.expr->exprVar.thing->data.symbol.name; } return malp("%s; /* loop guard */", name); } else if(s->nodeKind == AST_STMT_EXPR) { return ast_dumpe(tlc, s->stmtExpr.expr); } else if(s->nodeKind == AST_STMT_DECL) { ScopeItem *si = s->stmtDecl.thing; const char *name = si->kind == SCOPEITEM_VAR ? si->data.var.name : si->data.symbol.name; char *a = type_to_string(si->type); char *c; if(s->stmtDecl.expression) { char *b = ast_dumpe(tlc, s->stmtDecl.expression); c = malp("%s %s = %s;", a, name, b); free(b); } else { c = malp("%s %s;", a, name); } free(a); return c; } else if(s->nodeKind == AST_STMT_RETURN) { if(s->stmtReturn.val) { char *e = ast_dumpe(tlc, s->stmtReturn.val); char *c = malp("return %s;", e); free(e); return c; } else { return malp("return;"); } } return malp("@unimp:%s;", AST_KIND_STR[s->nodeKind]); } static char *stmt_live_range_dbgs(AST *tlc, AST *stmt) { char *ret = malp(""); for(size_t v = 0; v < tlc->chunk.varCount; v++) { ScopeItem *si = tlc->chunk.vars[v]; if(si->data.var.liveRangeStart == stmt) { char *ret2 = malp("%s (%s start)", ret, si->data.var.name); free(ret); ret = ret2; } if(si->data.var.liveRangeEnd == stmt) { char *ret2 = malp("%s (%s end)", ret, si->data.var.name); free(ret); ret = ret2; } } return ret; } char *ast_dumpc(AST *tlc, AST *chu) { AST *stmt = chu->chunk.statementFirst; char *ret = malp(""); while(stmt) { char *new = ast_dumps(tlc, stmt); char *users = stmt_live_range_dbgs(tlc, stmt); char *ret2 = malp("%s%s%s\n", ret, new, users); free(ret); free(new); free(users); ret = ret2; stmt = stmt->statement.next; } return ret; } char *ast_dump(AST *tlc) { return ast_dumpc(tlc, tlc); }