// File: /workspace/github_c_makefile_star2_O3/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 0x8ebd(%rip), %r12      # 0x13158
callq 0xa5b8
movq %rax, %r14
leaq 0x4f9e(%rip), %rdi      # 0xf248
callq 0xa09f
testq %rax, %rax
je 0xa2d3
leaq 0x4f8d(%rip), %r15      # 0xf248
movq %r14, %rdi
callq 0x9cf6
movq %rax, %r14
movq %r15, %rdi
callq 0xa09f
testq %rax, %rax
jne 0xa2bb
movq 0x8e7e(%rip), %rax      # 0x13158
cmpl $0x2, 0x8(%rax)
jne 0xa416
movq 0x10(%rax), %r13
movq (%rax), %rax
movq %rax, 0x8e66(%rip)      # 0x13158
leaq 0x5535(%rip), %rdi      # 0xf82e
callq 0xa09f
testq %rax, %rax
je 0xa43e
xorl %eax, %eax
callq 0x307c
movq %rax, %r15
movq 0x8e68(%rip), %rbp      # 0x13180
movq $0x0, 0x8e6d(%rip) # 0x13190
movq 0x8e2e(%rip), %rdi      # 0x13158
leaq 0x4ea5(%rip), %rsi      # 0xf1d6
callq 0xdab0
testb %al, %al
movl %ebx, 0x4(%rsp)
je 0xa37e
movq 0x8e13(%rip), %rax      # 0x13158
movq (%rax), %rdi
leaq 0x4f7d(%rip), %rsi      # 0xf2cc
callq 0xdab0
testb %al, %al
je 0xa37e
movq %r13, %rbx
movq %rbp, %r13
movq 0x8df3(%rip), %rax      # 0x13158
movq (%rax), %rax
movq %rax, 0x8de9(%rip)      # 0x13158
movq (%rax), %rax
movq %rax, 0x8ddf(%rip)      # 0x13158
jmp 0xa4ad
movq 0x8dd3(%rip), %rdi      # 0x13158
callq 0xaff5
testl %eax, %eax
je 0xa451
callq 0xa5b8
movq %rax, %rdi
callq 0xa931
movq %rax, %r12
movq 0x10(%rax), %rsi
movq 0x40(%rax), %rdi
callq 0xb8ca
movq 0x8(%r12), %rdi
movq 0x40(%r12), %rsi
callq 0xb784
movq %r15, %rdi
movq %rax, %rsi
callq 0x30ae
leaq 0x4efc(%rip), %rdi      # 0xf2cc
callq 0xa09f
testq %rax, %rax
jne 0xa4a7
leaq 0x3c69(%rip), %rdi      # 0xe04e
callq 0xa09f
testq %rax, %rax
jne 0xa37e
movq 0x8d62(%rip), %rbx      # 0x13158
leaq 0x3c53(%rip), %rdi      # 0xe050
leaq 0x4ec3(%rip), %rsi      # 0xf2c7
xorl %eax, %eax
callq 0xd86a
movq %rbx, %rdi
movq %rax, %rsi
callq 0xcd01
leaq 0x4f06(%rip), %rdi      # 0xf323
callq 0xa09f
testq %rax, %rax
jne 0xa44a
movq 0x8d2a(%rip), %rbx      # 0x13158
leaq 0x3c1b(%rip), %rdi      # 0xe050
leaq 0x4e78(%rip), %rsi      # 0xf2b4
jmp 0xa404
movq %r12, 0x8d13(%rip)      # 0x13158
callq 0xa0d4
xorl %eax, %eax
jmp 0xa522
movq %r13, %rbx
movq %rbp, %r13
leaq 0x4e70(%rip), %rdi      # 0xf2ce
callq 0xa09f
testq %rax, %rax
je 0xa47c
leaq 0x4e5d(%rip), %rdi      # 0xf2cc
callq 0xa09f
movb $0x1, %bpl
testq %rax, %rax
jne 0xa4af
leaq 0x4e49(%rip), %rdi      # 0xf2cc
callq 0xa09f
testq %rax, %rax
jne 0xa4ad
movq 0x8cc4(%rip), %rbx      # 0x13158
leaq 0x3bb5(%rip), %rdi      # 0xe050
leaq 0x4e2a(%rip), %rsi      # 0xf2cc
jmp 0xa404
movq %r13, %rbx
movq %rbp, %r13
xorl %ebp, %ebp
leaq 0x4e6d(%rip), %rdi      # 0xf323
callq 0xa09f
testq %rax, %rax
je 0xa4df
movq %r13, 0x8cb9(%rip)      # 0x13180
movl $0x1, %edi
movl $0x30, %esi
callq 0x20f0
movq %rbx, (%rax)
movq %r14, 0x8(%rax)
jmp 0xa508
callq 0xb920
movq %rax, %r12
movq %r13, 0x8c92(%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 0x8c7d(%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