cosmopolitan/third_party/chibicc/printast.c

256 lines
10 KiB
C

/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2020 Justine Alexandra Roberts Tunney │
│ │
│ Permission to use, copy, modify, and/or distribute this software for │
│ any purpose with or without fee is hereby granted, provided that the │
│ above copyright notice and this permission notice appear in all copies. │
│ │
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/alg/arraylist2.internal.h"
#include "third_party/chibicc/chibicc.h"
static const char kBoolStr[2][6] = {"false", "true"};
static const char kTypeKindStr[17][8] = {
"VOID", "BOOL", "CHAR", "SHORT", "INT", "LONG",
"INT128", "FLOAT", "DOUBLE", "LDOUBLE", "ENUM", "PTR",
"FUNC", "ARRAY", "VLA", "STRUCT", "UNION",
};
static const char kNodeKindStr[50][11] = {
"NULL_EXPR", "ADD", "SUB", "MUL", "DIV", "NEG",
"REM", "BINAND", "BINOR", "BINXOR", "SHL", "SHR",
"EQ", "NE", "LT", "LE", "ASSIGN", "COND",
"COMMA", "MEMBER", "ADDR", "DEREF", "NOT", "BITNOT",
"LOGAND", "LOGOR", "RETURN", "IF", "FOR", "DO",
"SWITCH", "CASE", "BLOCK", "GOTO", "GOTO_EXPR", "LABEL",
"LABEL_VAL", "FUNCALL", "EXPR_STMT", "STMT_EXPR", "VAR", "VLA_PTR",
"NUM", "CAST", "MEMZERO", "ASM", "CAS", "EXCH",
"FPCLASSIFY",
};
static struct Visited {
size_t i, n;
intptr_t *p;
} g_visited;
static void PrintObj(FILE *, int, const char *, Obj *);
static void PrintNode(FILE *, int, const char *, Node *);
static void PrintType(FILE *, int, const char *, Type *);
static bool Visit(void *ptr) {
size_t i;
intptr_t addr = (intptr_t)ptr;
for (i = 0; i < g_visited.i; ++i) {
if (addr == g_visited.p[i]) {
return false;
}
}
APPEND(&g_visited.p, &g_visited.i, &g_visited.n, &addr);
return true;
}
static void PrintLine(FILE *f, int l, char *fmt, ...) {
int i;
va_list ap;
for (i = 0; i < l; ++i) fputc(' ', f);
va_start(ap, fmt);
vfprintf(f, fmt, ap);
va_end(ap);
fputc('\n', f);
}
static void PrintBool(FILE *f, int l, const char *s, bool b) {
if (!b) return;
PrintLine(f, l, "%s%s", s, kBoolStr[b]);
}
static void PrintInt(FILE *f, int l, const char *s, long x) {
if (!x) return;
PrintLine(f, l, "%s%ld", s, x);
}
static void PrintStr(FILE *f, int l, const char *s, const char *t) {
if (!t || !*t) return;
PrintLine(f, l, "%s%`'s", s, t);
}
static void PrintTokStr(FILE *f, int l, const char *s, Token *t) {
if (!t) return;
PrintLine(f, l, "%s%`'.*s", s, t->len, t->loc);
}
static void PrintMember(FILE *f, int l, const char *s, Member *m) {
if (!m) return;
PrintLine(f, l, "%sMember { # %p", s, m);
PrintTokStr(f, l + 2, "name: ", m->name);
PrintInt(f, l + 2, "idx: ", m->idx);
PrintInt(f, l + 2, "align: ", m->align);
PrintInt(f, l + 2, "offset: ", m->offset);
PrintBool(f, l + 2, "is_bitfield: ", m->is_bitfield);
PrintInt(f, l + 2, "bit_offset: ", m->bit_offset);
PrintInt(f, l + 2, "bit_width: ", m->bit_width);
PrintType(f, l + 2, "ty: ", m->ty);
PrintLine(f, l, "}");
}
static void PrintMembers(FILE *f, int l, const char *s, Member *m) {
for (; m; m = m->next) {
PrintMember(f, l, s, m);
}
}
static void PrintType(FILE *f, int l, const char *s, Type *t) {
for (; t; t = t->next) {
if (Visit(t)) {
PrintLine(f, l, "%sType { # %p", s, t);
PrintLine(f, l + 2, "kind: TY_%s", kTypeKindStr[t->kind]);
PrintInt(f, l + 2, "size: ", t->size);
PrintInt(f, l + 2, "align: ", t->align);
PrintBool(f, l + 2, "is_unsigned: ", t->is_unsigned);
PrintBool(f, l + 2, "is_atomic: ", t->is_atomic);
PrintType(f, l + 2, "base: ", t->base);
PrintTokStr(f, l + 2, "name: ", t->name);
PrintTokStr(f, l + 2, "name_pos: ", t->name_pos);
PrintInt(f, l + 2, "array_len: ", t->array_len);
PrintInt(f, l + 2, "vector_size: ", t->vector_size);
PrintNode(f, l + 2, "vla_len: ", t->vla_len);
PrintObj(f, l + 2, "vla_size: ", t->vla_size);
PrintMembers(f, l + 2, "members: ", t->members);
PrintBool(f, l + 2, "is_flexible: ", t->is_flexible);
PrintBool(f, l + 2, "is_packed: ", t->is_packed);
PrintBool(f, l + 2, "is_aligned: ", t->is_aligned);
PrintType(f, l + 2, "return_ty: ", t->return_ty);
PrintType(f, l + 2, "params: ", t->params);
PrintBool(f, l + 2, "is_variadic: ", t->is_variadic);
PrintLine(f, l, "}");
} else if (t->name) {
PrintLine(f, l, "%sTY_%s %.*s # %p", s, kTypeKindStr[t->kind],
t->name->len, t->name->loc, t);
} else {
PrintLine(f, l, "%sTY_%s # %p", s, kTypeKindStr[t->kind], t);
}
}
}
static void PrintAsm(FILE *f, int l, const char *s, Asm *a) {
int i;
if (!a) return;
PrintLine(f, l, "%sAsm { # %p", s, a);
PrintStr(f, l + 2, "str: ", a->str);
for (i = 0; i < a->n; ++i) {
PrintLine(f, l + 2, "ops: AsmOperand {");
PrintStr(f, l + 4, "str: ", a->ops[i].str);
PrintNode(f, l + 4, "node: ", a->ops[i].node);
PrintLine(f, l + 2, "}");
}
PrintLine(f, l, "}");
}
static void PrintNode(FILE *f, int l, const char *s, Node *n) {
for (; n; n = n->next) {
PrintLine(f, l, "%sNode { # %p", s, n);
PrintLine(f, l + 2, "kind: ND_%s", kNodeKindStr[n->kind]);
PrintType(f, l + 2, "ty: ", n->ty);
PrintNode(f, l + 2, "lhs: ", n->lhs);
PrintNode(f, l + 2, "rhs: ", n->rhs);
PrintNode(f, l + 2, "cond: ", n->cond);
PrintNode(f, l + 2, "then: ", n->then);
PrintNode(f, l + 2, "els: ", n->els);
PrintNode(f, l + 2, "init: ", n->init);
PrintNode(f, l + 2, "inc: ", n->inc);
PrintNode(f, l + 2, "body: ", n->body);
PrintType(f, l + 2, "func_ty: ", n->func_ty);
PrintNode(f, l + 2, "args: ", n->args);
PrintObj(f, l + 2, "ret_buffer: ", n->ret_buffer);
PrintBool(f, l + 2, "pass_by_stack: ", n->pass_by_stack);
PrintBool(f, l + 2, "realign_stack: ", n->realign_stack);
PrintNode(f, l + 2, "case_next: ", n->case_next);
PrintNode(f, l + 2, "default_case: ", n->default_case);
PrintStr(f, l + 2, "label: ", n->label);
PrintStr(f, l + 2, "unique_label: ", n->unique_label);
PrintNode(f, l + 2, "goto_next: ", n->goto_next);
PrintStr(f, l + 2, "brk_label: ", n->brk_label);
PrintStr(f, l + 2, "cont_label: ", n->cont_label);
PrintInt(f, l + 2, "begin: ", n->begin);
PrintAsm(f, l + 2, "azm: ", n->azm);
PrintInt(f, l + 2, "end: ", n->end);
PrintMember(f, l + 2, "member: ", n->member);
PrintObj(f, l + 2, "var: ", n->var);
PrintNode(f, l + 2, "overflow: ", n->overflow);
PrintInt(f, l + 2, "val: ", n->val);
if (n->fval) PrintLine(f, l + 2, "fval: %Lf", n->fval);
PrintLine(f, l, "}");
}
}
static void PrintRelo(FILE *f, int l, const char *s, Relocation *r) {
for (; r; r = r->next) {
PrintLine(f, l, "%sRelocation { # %p", s, r);
PrintInt(f, l + 2, "offset: ", r->offset);
if (r->label) PrintStr(f, l + 2, "label: ", *r->label);
PrintInt(f, l + 2, "addend: ", r->addend);
PrintLine(f, l, "}");
}
}
static void PrintObj(FILE *f, int l, const char *s, Obj *o) {
if (!o) return;
PrintLine(f, l, "%sObj { # %p", s, o);
PrintStr(f, l + 2, "name: ", o->name);
PrintType(f, l + 2, "ty: ", o->ty);
PrintBool(f, l + 2, "is_local: ", o->is_local);
PrintInt(f, l + 2, "align: ", o->align);
PrintInt(f, l + 2, "offset: ", o->offset);
PrintBool(f, l + 2, "is_function: ", o->is_function);
PrintBool(f, l + 2, "is_definition: ", o->is_definition);
PrintBool(f, l + 2, "is_static: ", o->is_static);
PrintBool(f, l + 2, "is_weak: ", o->is_weak);
PrintBool(f, l + 2, "is_externally_visible: ", o->is_externally_visible);
PrintStr(f, l + 2, "asmname: ", o->asmname);
PrintStr(f, l + 2, "section: ", o->section);
PrintStr(f, l + 2, "visibility: ", o->visibility);
PrintBool(f, l + 2, "is_tentative: ", o->is_tentative);
PrintBool(f, l + 2, "is_string_literal: ", o->is_string_literal);
PrintBool(f, l + 2, "is_tls: ", o->is_tls);
PrintStr(f, l + 2, "init_data: ", o->init_data);
PrintRelo(f, l + 2, "rel: ", o->rel);
PrintBool(f, l + 2, "is_inline: ", o->is_inline);
PrintBool(f, l + 2, "is_aligned: ", o->is_aligned);
PrintBool(f, l + 2, "is_noreturn: ", o->is_noreturn);
PrintBool(f, l + 2, "is_destructor: ", o->is_destructor);
PrintBool(f, l + 2, "is_constructor: ", o->is_constructor);
PrintBool(f, l + 2, "is_externally_visible: ", o->is_externally_visible);
PrintBool(f, l + 2,
"is_no_instrument_function: ", o->is_no_instrument_function);
PrintBool(f, l + 2,
"is_force_align_arg_pointer: ", o->is_force_align_arg_pointer);
PrintBool(f, l + 2,
"is_no_caller_saved_registers: ", o->is_no_caller_saved_registers);
PrintInt(f, l + 2, "stack_size: ", o->stack_size);
PrintObj(f, l + 2, "params: ", o->params);
PrintNode(f, l + 2, "body: ", o->body);
PrintObj(f, l + 2, "locals: ", o->locals);
PrintObj(f, l + 2, "va_area: ", o->va_area);
PrintObj(f, l + 2, "alloca_bottom: ", o->alloca_bottom);
PrintBool(f, l + 2, "is_live: ", o->is_live);
PrintBool(f, l + 2, "is_root: ", o->is_root);
PrintLine(f, l, "}");
}
void print_ast(FILE *f, Obj *o) {
for (; o; o = o->next) {
PrintObj(f, 0, "", o);
}
}