250 lines
10 KiB
C
250 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, "origin: ", t->origin);
|
|
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);
|
|
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);
|
|
}
|
|
}
|