// File: /workspace/github_c_makefile_star2_O3/hikalium[P]compilium/ast.c
// Function: PrintASTNodeSub
static void PrintASTNodeSub(struct Node *n, int depth) {
  if (!n) {
    fprintf(stderr, "(null)");
    return;
  }
  if (IsToken(n)) {
    PrintTokenBrief(n);
    return;
  }
  if (n->type == kASTList) {
    fprintf(stderr, "[");
    if (GetSizeOfList(n) == 0) {
      fprintf(stderr, "]");
      return;
    }
    for (int i = 0; i < GetSizeOfList(n); i++) {
      fprintf(stderr, "%s\n", i ? "," : "");
      PrintPadding(depth + 1);
      PrintASTNodeSub(GetNodeAt(n, i), depth + 1);
    }
    fprintf(stderr, "\n");
    PrintPadding(depth);
    fprintf(stderr, "]");
    return;
  } else if (n->type == kASTStructSpec) {
    fprintf(stderr, "StructSpec: ");
    PrintASTNodeSub(n->struct_member_dict, depth);
    return;
  } else if (n->type == kASTKeyValue) {
    fprintf(stderr, "%s: ", n->key);
    PrintASTNodeSub(n->value, depth);
    return;
  } else if (n->type == kNodeStructMember) {
    fprintf(stderr, "Member +%d: ", n->struct_member_ent_ofs);
    PrintASTNodeSub(n->struct_member_ent_type, depth);
    return;
  } else if (n->type == kNodeMacroReplacement) {
    fprintf(stderr, "MacroReplacement<args: ");
    PrintASTNodeSub(n->arg_expr_list, depth);
    fprintf(stderr, ", rep: ");
    PrintTokenSequence(n->value);
    fprintf(stderr, ">");
    return;
  } else if (n->type == kTypeBase) {
    PrintTokenStrToFile(n->op, stderr);
    return;
  } else if (n->type == kTypeLValue) {
    fprintf(stderr, "lvalue<");
    PrintASTNodeSub(n->right, depth);
    fprintf(stderr, ">");
    return;
  } else if (n->type == kTypePointer) {
    fprintf(stderr, "pointer_of<");
    PrintASTNodeSub(n->right, depth);
    fprintf(stderr, ">");
    return;
  } else if (n->type == kTypeFunction) {
    fprintf(stderr, "function<returns: ");
    PrintASTNodeSub(n->left, depth);
    fprintf(stderr, ", args: ");
    PrintASTNodeSub(n->right, depth);
    fprintf(stderr, ">");
    return;
  } else if (n->type == kTypeStruct) {
    fprintf(stderr, "struct<tag: ");
    PrintASTNodeSub(n->tag, depth);
    if (!n->type_struct_spec) {
      fprintf(stderr, ", incomplete");
    }
    fprintf(stderr, ">");
    return;
  } else if (n->type == kTypeArray) {
    fprintf(stderr, "array_of<");
    PrintASTNodeSub(n->type_array_type_of, depth);
    fprintf(stderr, ">[");
    PrintASTNodeSub(n->type_array_index_decl, depth);
    fprintf(stderr, "]");
    return;
  } else if (n->type == kTypeAttrIdent) {
    fputc('`', stderr);
    PrintTokenStrToFile(n->left, stderr);
    fputc('`', stderr);
    fprintf(stderr, " has a type: ");
    PrintASTNodeSub(n->right, depth);
    return;
  } else if (n->type == kASTFuncDef) {
    fprintf(stderr, "FuncDef ");
    PrintASTNodeSub(n->func_name_token, depth);
    fprintf(stderr, " : ");
    PrintASTNodeSub(n->func_type, depth);
    fprintf(stderr, "{\n");
    PrintPadding(depth + 1);
    PrintASTNodeSub(n->func_body, depth + 1);
    fprintf(stderr, "\n");
    PrintPadding(depth);
    fprintf(stderr, "}");
    return;
  } else if (n->type == kASTExprStmt) {
    PrintASTNodeSub(n->left, depth);
    fprintf(stderr, ";");
    return;
  } else if (n->type == kASTExprFuncCall) {
    fprintf(stderr, "FuncCall<");
    PrintASTNodeSub(n->func_expr, depth);
    fprintf(stderr, ">(");
    PrintASTNodeSub(n->arg_expr_list, depth);
    fprintf(stderr, ")");
    return;
  }
  fprintf(stderr, "(op=");
  if (n->op) PrintTokenBrief(n->op);
  if (n->expr_type) {
    fprintf(stderr, ":");
    PrintASTNodeSub(n->expr_type, depth + 1);
  }
  if (n->reg) fprintf(stderr, " reg: %d", n->reg);
  if (n->cond) {
    fprintf(stderr, " cond=");
    PrintASTNodeSub(n->cond, depth + 1);
  }
  if (n->left) {
    fprintf(stderr, " L=");
    PrintASTNodeSub(n->left, depth + 1);
  }
  if (n->right) {
    fprintf(stderr, " R=");
    PrintASTNodeSub(n->right, depth + 1);
  }
  fprintf(stderr, ")");
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
testq %rdi, %rdi
je 0x44b5
movl %esi, %ebx
movq %rdi, %r14
leaq 0x6ea7(%rip), %r15      # 0xb2f4
movq %r14, %rdi
callq 0x90c4
testb %al, %al
jne 0x4558
movl (%r14), %eax
addl $-0x2, %eax
cmpl $0x18, %eax
ja 0x45ce
movslq (%r15,%rax,4), %rax
addq %r15, %rax
jmpq *%rax
movq %r14, %rdi
callq 0x267e
movl $0x70, %eax
jmp 0x44ac
movq %r14, %rdi
callq 0x23f0
movl $0x20, %eax
jmp 0x44ac
movq %r14, %rdi
callq 0x269f
movl $0xa0, %eax
jmp 0x44ac
callq 0x26c1
movl $0x68, %eax
movq (%r14,%rax), %r14
testq %r14, %r14
jne 0x444d
callq 0x2873
popq %rbx
popq %r14
popq %r15
retq
movq 0x18(%r14), %rdi
movl %ebx, %esi
callq 0x4437
movq 0xcb26(%rip), %rax      # 0x10ff8
movq (%rax), %rsi
movl $0x3b, %edi
jmp 0x4536
movq 0xcb15(%rip), %r15      # 0x10ff8
movq (%r15), %rsi
movl $0x5b, %edi
callq 0x20d0
movq %r14, %rdi
callq 0x48ee
testl %eax, %eax
je 0x452e
movq %r14, %rdi
callq 0x48ee
testl %eax, %eax
jg 0x45ec
movq (%r15), %rsi
movl $0xa, %edi
callq 0x20d0
testl %ebx, %ebx
jle 0x452e
movq (%r15), %rsi
movl $0x20, %edi
callq 0x20d0
decl %ebx
jne 0x451d
movq (%r15), %rsi
movl $0x5d, %edi
popq %rbx
popq %r14
popq %r15
jmp 0x20d0
movq 0x10(%r14), %rdi
movq 0xcaad(%rip), %rax      # 0x10ff8
movq (%rax), %rsi
popq %rbx
popq %r14
popq %r15
jmp 0x9335
movq %r14, %rdi
popq %rbx
popq %r14
popq %r15
jmp 0x9310
movq %r14, %rdi
movl %ebx, %esi
callq 0x25c8
jmp 0x44ba
movq %r14, %rdi
movl %ebx, %esi
callq 0x230e
jmp 0x44ba
movq %r14, %rdi
movl %ebx, %esi
callq 0x243a
jmp 0x44ba
movq %r14, %rdi
movl %ebx, %esi
callq 0x2609
jmp 0x44ba
movq %r14, %rdi
movl %ebx, %esi
callq 0x2297
jmp 0x44ba
movq %r14, %rdi
movl %ebx, %esi
callq 0x2516
jmp 0x44ba
movq %r14, %rdi
movl %ebx, %esi
callq 0x2587
jmp 0x44ba
movq %r14, %rdi
movl %ebx, %esi
callq 0x2774
jmp 0x44ba
movq %r14, %rdi
movl %ebx, %esi
callq 0x24b1
jmp 0x44ba
movl %ebx, %edi
movq %r14, %rsi
callq 0x26dd
jmp 0x450c
nop