// File: /workspace/github_c_makefile_star2_O0/pocari[P]compilerbook-9cc/codegen.c
// Function: codegen_func
static void codegen_func(Function *func) {
  funcname = func->name;
  if (!func->is_staitc) {
    printfln(".global %s", func->name);
  }
  printfln("%s:", func->name);
  // プロローグ
  // rbp初期化とローカル変数確保
  printfln("  push rbp"); // 前の関数呼び出しでのrbpをスタックに対比
  printfln("  mov rbp, rsp"); // この関数呼び出しでのベースポインタ設定
  // 使用されているローカル変数の数分、領域確保(ここに引数の値を保存する領域も確保される)
  printfln("  sub rsp, %d", func->stack_size);

  // paramsが引数を逆順に保持しているので、ロードするレジスタも逆順にする。そのため一度引数の数を数える
  int param_len = 0;
  for (VarList *v = func->params; v; v = v->next) {
    param_len++;
  }

  // レジスタから引数の情報をスタックに確保
  if (func->has_vararg) {
    printfln("  mov dword ptr [rbp-8], %d", param_len * 8);
    printfln("  mov [rbp-16], r9");
    printfln("  mov [rbp-24], r8");
    printfln("  mov [rbp-32], rcx");
    printfln("  mov [rbp-40], rdx");
    printfln("  mov [rbp-48], rsi");
    printfln("  mov [rbp-56], rdi");
  }

  int i = param_len - 1;
  for (VarList *v = func->params; v; v = v->next) {
    if (i >= 6) {
      // 7個以上(indexベースでいうと6以上)の引数は、スタックから取得する

      // 7個目の引数は、この関数のスタックフレームの外(呼び出した側のスタック)にあるので、
      // リターンアドレス(=rbp + 8)の次(rbp + 16)からのオフセットで7個目以上の引数のアドレスを計算
      printfln("  mov rax, [rbp+%d]", 16 + (i - 6) * 8);
      printfln("  mov [rbp-%d], rax", v->var->offset);
    } else {
      int sz = v->var->type->size;
      if (sz == 1) {
        printfln("  mov [rbp-%d], %s", v->var->offset, ARGUMENT_REGISTERS_SIZE1[i]);
      } else if (sz == 2) {
        printfln("  mov [rbp-%d], %s", v->var->offset, ARGUMENT_REGISTERS_SIZE2[i]);
      } else if (sz == 4) {
        printfln("  mov [rbp-%d], %s", v->var->offset, ARGUMENT_REGISTERS_SIZE4[i]);
      } else if (sz == 8) {
        assert(sz == 8);
        printfln("  mov [rbp-%d], %s", v->var->offset, ARGUMENT_REGISTERS_SIZE8[i]);
      } else {
        assert(false);
      }
    }
    i--;
  }

  // fprintfln(stderr, "func: %s, stack_size: %d", node->name, node->stack_size);
  // 先頭の文からコード生成
  for (Node *n = func->body; n; n = n->next) {
    gen(n);
  }

  // エピローグ
  // rbpの復元と戻り値設定
  // 最後の演算結果が、rax(forの最後でpopしてるやつ)にロードされてるのでそれをmainの戻り値として返す
  printfln(".L.return.%s:", func->name);
  printfln("  mov rsp, rbp");
  printfln("  pop rbp");
  printfln("  ret");
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, 0x12f2d(%rip)     # 0x15568
movq -0x8(%rbp), %rax
testb $0x1, 0x34(%rax)
jne 0x265b
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rsi
leaq 0xcaaf(%rip), %rdi      # 0xf103
movb $0x0, %al
callq 0x2320
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rsi
leaq 0xcc28(%rip), %rdi      # 0xf292
movb $0x0, %al
callq 0x2320
leaq 0xcae5(%rip), %rdi      # 0xf15d
movb $0x0, %al
callq 0x2320
leaq 0xcae2(%rip), %rdi      # 0xf168
movb $0x0, %al
callq 0x2320
movq -0x8(%rbp), %rax
movl 0x30(%rax), %esi
leaq 0xcadc(%rip), %rdi      # 0xf177
movb $0x0, %al
callq 0x2320
movl $0x0, -0xc(%rbp)
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0x26d2
movl -0xc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x18(%rbp)
jmp 0x26b5
movq -0x8(%rbp), %rax
testb $0x1, 0x35(%rax)
je 0x2744
movl -0xc(%rbp), %esi
shll $0x3, %esi
leaq 0xca9c(%rip), %rdi      # 0xf185
movb $0x0, %al
callq 0x2320
leaq 0xcaaa(%rip), %rdi      # 0xf1a1
movb $0x0, %al
callq 0x2320
leaq 0xcaaf(%rip), %rdi      # 0xf1b4
movb $0x0, %al
callq 0x2320
leaq 0xcab4(%rip), %rdi      # 0xf1c7
movb $0x0, %al
callq 0x2320
leaq 0xcaba(%rip), %rdi      # 0xf1db
movb $0x0, %al
callq 0x2320
leaq 0xcac0(%rip), %rdi      # 0xf1ef
movb $0x0, %al
callq 0x2320
leaq 0xcac6(%rip), %rdi      # 0xf203
movb $0x0, %al
callq 0x2320
movl -0xc(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x1c(%rbp)
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
je 0x28e0
cmpl $0x6, -0x1c(%rbp)
jl 0x27a2
movl -0x1c(%rbp), %esi
subl $0x6, %esi
shll $0x3, %esi
addl $0x10, %esi
leaq 0xca9a(%rip), %rdi      # 0xf217
movb $0x0, %al
callq 0x2320
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movl 0x10(%rax), %esi
leaq 0xca95(%rip), %rdi      # 0xf22b
movb $0x0, %al
callq 0x2320
jmp 0x28c7
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq (%rax), %rax
movl 0x4(%rax), %eax
movl %eax, -0x2c(%rbp)
cmpl $0x1, -0x2c(%rbp)
jne 0x27e6
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movl 0x10(%rax), %esi
movslq -0x1c(%rbp), %rcx
leaq 0x12931(%rip), %rax     # 0x15100
movq (%rax,%rcx,8), %rdx
leaq 0xca65(%rip), %rdi      # 0xf23f
movb $0x0, %al
callq 0x2320
jmp 0x28c5
cmpl $0x2, -0x2c(%rbp)
jne 0x2819
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movl 0x10(%rax), %esi
movslq -0x1c(%rbp), %rcx
leaq 0x1292e(%rip), %rax     # 0x15130
movq (%rax,%rcx,8), %rdx
leaq 0xca32(%rip), %rdi      # 0xf23f
movb $0x0, %al
callq 0x2320
jmp 0x28c3
cmpl $0x4, -0x2c(%rbp)
jne 0x2849
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movl 0x10(%rax), %esi
movslq -0x1c(%rbp), %rcx
leaq 0x1292b(%rip), %rax     # 0x15160
movq (%rax,%rcx,8), %rdx
leaq 0xc9ff(%rip), %rdi      # 0xf23f
movb $0x0, %al
callq 0x2320
jmp 0x28c1
cmpl $0x8, -0x2c(%rbp)
jne 0x28a0
cmpl $0x8, -0x2c(%rbp)
jne 0x2857
jmp 0x2876
leaq 0xc9f4(%rip), %rdi      # 0xf252
leaq 0xc9f5(%rip), %rsi      # 0xf25a
movl $0x35b, %edx            # imm = 0x35B
leaq 0xc9f3(%rip), %rcx      # 0xf264
callq 0x20b0
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movl 0x10(%rax), %esi
movslq -0x1c(%rbp), %rcx
leaq 0x12904(%rip), %rax     # 0x15190
movq (%rax,%rcx,8), %rdx
leaq 0xc9a8(%rip), %rdi      # 0xf23f
movb $0x0, %al
callq 0x2320
jmp 0x28bf
leaq 0xc9db(%rip), %rdi      # 0xf282
leaq 0xc9ac(%rip), %rsi      # 0xf25a
movl $0x35e, %edx            # imm = 0x35E
leaq 0xc9aa(%rip), %rcx      # 0xf264
callq 0x20b0
jmp 0x28c1
jmp 0x28c3
jmp 0x28c5
jmp 0x28c7
movl -0x1c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x1c(%rbp)
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0x2759
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0x290a
movq -0x38(%rbp), %rdi
callq 0x2950
movq -0x38(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x38(%rbp)
jmp 0x28ec
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rsi
leaq 0xc96f(%rip), %rdi      # 0xf288
movb $0x0, %al
callq 0x2320
leaq 0xc96f(%rip), %rdi      # 0xf296
movb $0x0, %al
callq 0x2320
leaq 0xc970(%rip), %rdi      # 0xf2a5
movb $0x0, %al
callq 0x2320
leaq 0xc96c(%rip), %rdi      # 0xf2af
movb $0x0, %al
callq 0x2320
addq $0x40, %rsp
popq %rbp
retq