// File: /workspace/github_c_makefile_star2_O1/takoeight0821[P]hoc_nyan/src/parse.c
// Function: funcdef
static Function *funcdef(bool is_static) {
  Token *back = peek(0);
  Type *ret_type = type_specifier();

  while (match("*")) {
    ret_type = ptr_to(ret_type);
  }

  char *name = peek(0)->ident;

  if (peek_tag(0) != TIDENT) {
    if (match(";")) {
      // type definition
      return NULL;
    }
    parse_error("function name or ;", peek(0));
  } else {
    consume(); // TIDENT
  }

  if (!match("(")) {
    tokens = back;
    global_var();
    return NULL;
  }

  Vector *params = new_vec();
  LVar *tmp = local_env; // start scope
  bool has_va_arg = false;
  local_size = 0;

  if (eq_reserved(peek(0), "void") && eq_reserved(peek(1), ")")) {
    consume();
    consume();
  } else {
    for (;;) {
      if (is_typename(peek(0))) {
        Node *param_decl = declarator(type_specifier()); // NDEFVAR
        add_lvar(param_decl->token, param_decl->name, param_decl->type);
        Node *param = find_var(param_decl->token, param_decl->name);

        vec_push(params, param);
        if (match(")"))
          break;
        if (!match(",")) {
          parse_error(", or )", peek(0));
        }
      } else if (match("...") && match(")")) {
        has_va_arg = true;
        break;
      } else if (match(")")) {
        break;
      } else {
        parse_error(")", peek(0));
      }
    }
  }

  if (match(";")) {
    local_env = tmp; // end scope

    Function *func = calloc(1, sizeof(Function));
    func->name = name;
    func->ret_type = ret_type;
    func->body = NULL;
    func->params = params;
    func->local_size = local_size;
    func->is_static = is_static;
    func->has_va_arg = has_va_arg;
    return func;
  }

  Node *body = statement();

  local_env = tmp; // end scope

  Function *func = calloc(1, sizeof(Function));
  func->name = name;
  func->ret_type = ret_type;
  func->body = body;
  func->params = params;
  func->local_size = local_size;
  func->is_static = is_static;
  func->has_va_arg = has_va_arg;

  return func;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movl %edi, %ebx
movq 0x8dc1(%rip), %r12      # 0x13158
callq 0xa6d2
movq %rax, %r14
leaq 0x5129(%rip), %rdi      # 0xf4cf
callq 0xa184
testq %rax, %rax
je 0xa3cf
leaq 0x5118(%rip), %r15      # 0xf4cf
movq %r14, %rdi
callq 0x9d9e
movq %rax, %r14
movq %r15, %rdi
callq 0xa184
testq %rax, %rax
jne 0xa3b7
movq 0x8d82(%rip), %rax      # 0x13158
cmpl $0x2, 0x8(%rax)
jne 0xa503
movq 0x10(%rax), %r13
movq (%rax), %rax
movq %rax, 0x8d6a(%rip)      # 0x13158
leaq 0x545d(%rip), %rdi      # 0xf852
callq 0xa184
testq %rax, %rax
je 0xa52e
xorl %eax, %eax
callq 0x307c
movq %rax, %r15
movq 0x8d6c(%rip), %rbp      # 0x13180
movq $0x0, 0x8d71(%rip) # 0x13190
movq 0x8d32(%rip), %rdi      # 0x13158
leaq 0x4dd1(%rip), %rsi      # 0xf1fe
callq 0xda40
testb %al, %al
movl %ebx, 0x4(%rsp)
je 0xa482
leaq 0x8d17(%rip), %rdi      # 0x13158
xorl %eax, %eax
movq (%rdi), %rdi
testb $0x1, %al
movb $0x1, %al
je 0xa443
leaq 0x4e9f(%rip), %rsi      # 0xf2f2
callq 0xda40
testb %al, %al
je 0xa482
movq %r13, %rbx
movq %rbp, %r13
movq 0x8cef(%rip), %rax      # 0x13158
movq (%rax), %rax
movq %rax, 0x8ce5(%rip)      # 0x13158
movq (%rax), %rax
movq %rax, 0x8cdb(%rip)      # 0x13158
jmp 0xa581
movq 0x8ccf(%rip), %rdi      # 0x13158
callq 0xb115
testl %eax, %eax
je 0xa541
callq 0xa6d2
movq %rax, %rdi
callq 0xaa49
movq %rax, %r12
movq 0x10(%rax), %rsi
movq 0x40(%rax), %rdi
callq 0xba46
movq 0x8(%r12), %rdi
movq 0x40(%r12), %rsi
callq 0xb8cb
movq %r15, %rdi
movq %rax, %rsi
callq 0x30b6
leaq 0x4e1e(%rip), %rdi      # 0xf2f2
callq 0xa184
testq %rax, %rax
jne 0xa4fb
movq %rax, %r12
leaq 0x3b66(%rip), %rdi      # 0xe04e
callq 0xa184
testq %rax, %rax
je 0xa60d
testq %r12, %r12
je 0xa482
movq %r13, %rbx
movq %rbp, %r13
jmp 0xa581
leaq 0x4e3f(%rip), %rdi      # 0xf349
callq 0xa184
testq %rax, %rax
jne 0xa53a
movq 0x8c3d(%rip), %rbx      # 0x13158
leaq 0x3b2e(%rip), %rdi      # 0xe050
leaq 0x4db1(%rip), %rsi      # 0xf2da
jmp 0xa622
movq %r12, 0x8c23(%rip)      # 0x13158
callq 0xa1b9
xorl %eax, %eax
jmp 0xa5fe
movq %r13, %rbx
movq %rbp, %r13
leaq 0x4da6(%rip), %rdi      # 0xf2f4
callq 0xa184
testq %rax, %rax
je 0xa56c
leaq 0x4d93(%rip), %rdi      # 0xf2f2
callq 0xa184
movb $0x1, %bpl
testq %rax, %rax
jne 0xa583
leaq 0x4d7f(%rip), %rdi      # 0xf2f2
callq 0xa184
testq %rax, %rax
je 0xa634
xorl %ebp, %ebp
leaq 0x4dbf(%rip), %rdi      # 0xf349
callq 0xa184
testq %rax, %rax
je 0xa5bb
movq %r13, 0x8be5(%rip)      # 0x13180
movl $0x1, %edi
movl $0x30, %esi
callq 0x20f0
movq %rbx, (%rax)
movq %r14, 0x8(%rax)
movq $0x0, 0x10(%rax)
jmp 0xa5e4
callq 0xba9c
movq %rax, %r12
movq %r13, 0x8bb6(%rip)      # 0x13180
movl $0x1, %edi
movl $0x30, %esi
callq 0x20f0
movq %rbx, (%rax)
movq %r14, 0x8(%rax)
movq %r12, 0x10(%rax)
movq %r15, 0x18(%rax)
movq 0x8ba1(%rip), %rcx      # 0x13190
movq %rcx, 0x20(%rax)
movl 0x4(%rsp), %ecx
movb %cl, 0x28(%rax)
movb %bpl, 0x29(%rax)
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8b44(%rip), %rbx      # 0x13158
leaq 0x3a35(%rip), %rdi      # 0xe050
leaq 0x4ccb(%rip), %rsi      # 0xf2ed
xorl %eax, %eax
callq 0xd7f2
movq %rbx, %rdi
movq %rax, %rsi
callq 0xce4d
movq 0x8b1d(%rip), %rbx      # 0x13158
leaq 0x3a0e(%rip), %rdi      # 0xe050
leaq 0x4ca9(%rip), %rsi      # 0xf2f2
jmp 0xa622