LLM4Binary/decompile-bench-makefile huggingface dataset:
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/cg.c
// Function: cgcall
int cgcall(struct symtable *sym, int numargs) {
  int outr;

  // 调用函数
  fprintf(Outfile, "\tcall\t%s@PLT\n", sym->name);

  // 删除之前入栈的实参
  if (numargs > 6)
    fprintf(Outfile, "\taddq\t$%d, %%rsp\n", 8 * (numargs - 6));

  // 恢复之前入栈的寄存器
  cgunspillregs();

  // 获取一个新的寄存器,拷贝返回值给他
  outr = cgallocreg();
  fprintf(Outfile, "\tmovq\t%%rax, %s\n", reglist[outr]);
  return (outr);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x10, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
leaq 0xf002(%rip), %rax      # 0x12518
movq (%rax), %rdi
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdx
leaq 0x8faf(%rip), %rsi      # 0xc4d7
movb $0x0, %al
callq 0x20e0
cmpl $0x6, -0xc(%rbp)
jle 0x3556
leaq 0xefdc(%rip), %rax      # 0x12518
movq (%rax), %rdi
movl -0xc(%rbp), %edx
subl $0x6, %edx
shll $0x3, %edx
leaq 0x8f96(%rip), %rsi      # 0xc4e5
movb $0x0, %al
callq 0x20e0
callq 0x35a0
callq 0x23f0
movl %eax, -0x10(%rbp)
leaq 0xefae(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x10(%rbp), %rcx
leaq 0xeb58(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rdx
leaq 0x8f74(%rip), %rsi      # 0xc4f7
movb $0x0, %al
callq 0x20e0
movl -0x10(%rbp), %eax
addq $0x10, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/cg.c
// Function: cgcopyarg
void cgcopyarg(int r, int argposn) {

  // 如果实参数量大于6个,那就把大于的都压入栈中
  if (argposn > 6) {
    fprintf(Outfile, "\tpushq\t%s\n", reglist[r]);
  } else {
    // 否则把实参值拷贝到指定的寄存器
    fprintf(Outfile, "\tmovq\t%s, %s\n", reglist[r],
	    reglist[FIRSTPARAMREG - argposn + 1]);
  }
  cgfreereg(r);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x10, %rsp
movl %edi, -0x4(%rbp)
movl %esi, -0x8(%rbp)
cmpl $0x6, -0x8(%rbp)
jle 0x360d
leaq 0xef2d(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xead7(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rdx
leaq 0x8f04(%rip), %rsi      # 0xc508
movb $0x0, %al
callq 0x20e0
jmp 0x364d
leaq 0xef04(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xeaae(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rdx
movl $0x9, %eax
subl -0x8(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rcx
leaq 0xea95(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rcx
leaq 0x8ecd(%rip), %rsi      # 0xc513
movb $0x0, %al
callq 0x20e0
movl -0x4(%rbp), %edi
callq 0x24c0
addq $0x10, %rsp
popq %rbp
retq
nopl (%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/cg.c
// Function: cgstorglob
int cgstorglob(int r, struct symtable *sym) {

  if (cgprimsize(sym->type) == 8) {
    fprintf(Outfile, "\tmovq\t%s, %s(%%rip)\n", reglist[r], sym->name);
  } else
    switch (sym->type) {
    case P_CHAR:
      fprintf(Outfile, "\tmovb\t%s, %s(%%rip)\n", breglist[r], sym->name);
      break;
    case P_INT:
      fprintf(Outfile, "\tmovl\t%s, %s(%%rip)\n", dreglist[r], sym->name);
      break;
    default:
      fatald("Bad type in cgstorglob:", sym->type);
    }
  return (r);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movl %edi, -0x4(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movl 0x10(%rax), %edi
callq 0x22e0
cmpl $0x8, %eax
jne 0x3704
leaq 0xee41(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xe9eb(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rdx
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rcx
leaq 0x8e38(%rip), %rsi      # 0xc530
movb $0x0, %al
callq 0x20e0
jmp 0x3796
movq -0x10(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x14(%rbp)
subl $0x20, %eax
je 0x371f
jmp 0x3715
movl -0x14(%rbp), %eax
subl $0x30, %eax
je 0x3750
jmp 0x3781
leaq 0xedf2(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xe9ec(%rip), %rax      # 0x12120
movq (%rax,%rcx,8), %rdx
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rcx
leaq 0x8dfe(%rip), %rsi      # 0xc545
movb $0x0, %al
callq 0x20e0
jmp 0x3794
leaq 0xedc1(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xea0b(%rip), %rax      # 0x12170
movq (%rax,%rcx,8), %rdx
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rcx
leaq 0x8de2(%rip), %rsi      # 0xc55a
movb $0x0, %al
callq 0x20e0
jmp 0x3794
movq -0x10(%rbp), %rax
movl 0x10(%rax), %esi
leaq 0x8de0(%rip), %rdi      # 0xc56f
callq 0x8180
jmp 0x3796
movl -0x4(%rbp), %eax
addq $0x20, %rsp
popq %rbp
retq
nop
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/cg.c
// Function: cgglobstr
void cgglobstr(int l, char *strvalue, int append) {
  char *cptr;
  if (!append)
    cglabel(l);
  for (cptr = strvalue; *cptr; cptr++) {
    fprintf(Outfile, "\t.byte\t%d\n", *cptr);
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movl %edi, -0x4(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
cmpl $0x0, -0x14(%rbp)
jne 0x39d0
movl -0x4(%rbp), %edi
callq 0x2960
movq -0x10(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
cmpb $0x0, (%rax)
je 0x3a0e
leaq 0xeb30(%rip), %rax      # 0x12518
movq (%rax), %rdi
movq -0x20(%rbp), %rax
movsbl (%rax), %edx
leaq 0x8bf7(%rip), %rsi      # 0xc5f0
movb $0x0, %al
callq 0x20e0
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x39d8
addq $0x20, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/cg.c
// Function: cgcompare_and_set
int cgcompare_and_set(int ASTop, int r1, int r2, int type) {
  int size = cgprimsize(type);


  // 检查语法树操作的范围
  if (ASTop < A_EQ || ASTop > A_GE)
    fatal("Bad ASTop in cgcompare_and_set()");

  switch (size) {
  case 1:
    fprintf(Outfile, "\tcmpb\t%s, %s\n", breglist[r2], breglist[r1]);
    break;
  case 4:
    fprintf(Outfile, "\tcmpl\t%s, %s\n", dreglist[r2], dreglist[r1]);
    break;
  default:
    fprintf(Outfile, "\tcmpq\t%s, %s\n", reglist[r2], reglist[r1]);
  }

  fprintf(Outfile, "\t%s\t%s\n", cmplist[ASTop - A_EQ], breglist[r2]);
  fprintf(Outfile, "\tmovzbq\t%s, %s\n", breglist[r2], reglist[r2]);
  cgfreereg(r1);
  return (r2);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movl %edi, -0x4(%rbp)
movl %esi, -0x8(%rbp)
movl %edx, -0xc(%rbp)
movl %ecx, -0x10(%rbp)
movl -0x10(%rbp), %edi
callq 0x22e0
movl %eax, -0x14(%rbp)
cmpl $0xd, -0x4(%rbp)
jl 0x3a6b
cmpl $0x12, -0x4(%rbp)
jle 0x3a77
leaq 0x8bb5(%rip), %rdi      # 0xc627
callq 0x8110
movl -0x14(%rbp), %eax
movl %eax, -0x18(%rbp)
subl $0x1, %eax
je 0x3a8e
jmp 0x3a84
movl -0x18(%rbp), %eax
subl $0x4, %eax
je 0x3ac6
jmp 0x3afe
leaq 0xea83(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0xc(%rbp), %rcx
leaq 0xe67d(%rip), %rax      # 0x12120
movq (%rax,%rcx,8), %rdx
movslq -0x8(%rbp), %rcx
leaq 0xe66e(%rip), %rax      # 0x12120
movq (%rax,%rcx,8), %rcx
leaq 0x8b8b(%rip), %rsi      # 0xc648
movb $0x0, %al
callq 0x20e0
jmp 0x3b34
leaq 0xea4b(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0xc(%rbp), %rcx
leaq 0xe695(%rip), %rax      # 0x12170
movq (%rax,%rcx,8), %rdx
movslq -0x8(%rbp), %rcx
leaq 0xe686(%rip), %rax      # 0x12170
movq (%rax,%rcx,8), %rcx
leaq 0x8b61(%rip), %rsi      # 0xc656
movb $0x0, %al
callq 0x20e0
jmp 0x3b34
leaq 0xea13(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0xc(%rbp), %rcx
leaq 0xe5bd(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rdx
movslq -0x8(%rbp), %rcx
leaq 0xe5ae(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rcx
leaq 0x8b37(%rip), %rsi      # 0xc664
movb $0x0, %al
callq 0x20e0
leaq 0xe9dd(%rip), %rax      # 0x12518
movq (%rax), %rdi
movl -0x4(%rbp), %eax
subl $0xd, %eax
movslq %eax, %rcx
leaq 0xe672(%rip), %rax      # 0x121c0
movq (%rax,%rcx,8), %rdx
movslq -0xc(%rbp), %rcx
leaq 0xe5c3(%rip), %rax      # 0x12120
movq (%rax,%rcx,8), %rcx
leaq 0x8b0a(%rip), %rsi      # 0xc672
movb $0x0, %al
callq 0x20e0
leaq 0xe9a2(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0xc(%rbp), %rcx
leaq 0xe59c(%rip), %rax      # 0x12120
movq (%rax,%rcx,8), %rdx
movslq -0xc(%rbp), %rcx
leaq 0xe53d(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rcx
leaq 0x890b(%rip), %rsi      # 0xc4a9
movb $0x0, %al
callq 0x20e0
movl -0x8(%rbp), %edi
callq 0x24c0
movl -0xc(%rbp), %eax
addq $0x20, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/cg.c
// Function: cgcompare_and_jump
int cgcompare_and_jump(int ASTop, int r1, int r2, int label, int type) {
  int size = cgprimsize(type);

  // 检查语法树操作范围
  if (ASTop < A_EQ || ASTop > A_GE)
    fatal("Bad ASTop in cgcompare_and_set()");

  switch (size) {
  case 1:
    fprintf(Outfile, "\tcmpb\t%s, %s\n", breglist[r2], breglist[r1]);
    break;
  case 4:
    fprintf(Outfile, "\tcmpl\t%s, %s\n", dreglist[r2], dreglist[r1]);
    break;
  default:
    fprintf(Outfile, "\tcmpq\t%s, %s\n", reglist[r2], reglist[r1]);
  }

  fprintf(Outfile, "\t%s\tL%d\n", invcmplist[ASTop - A_EQ], label);
  cgfreereg(r1);
  cgfreereg(r2);
  return (NOREG);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movl %edi, -0x4(%rbp)
movl %esi, -0x8(%rbp)
movl %edx, -0xc(%rbp)
movl %ecx, -0x10(%rbp)
movl %r8d, -0x14(%rbp)
movl -0x14(%rbp), %edi
callq 0x22e0
movl %eax, -0x18(%rbp)
cmpl $0xd, -0x4(%rbp)
jl 0x3c1f
cmpl $0x12, -0x4(%rbp)
jle 0x3c2b
leaq 0x8a01(%rip), %rdi      # 0xc627
callq 0x8110
movl -0x18(%rbp), %eax
movl %eax, -0x1c(%rbp)
subl $0x1, %eax
je 0x3c42
jmp 0x3c38
movl -0x1c(%rbp), %eax
subl $0x4, %eax
je 0x3c7a
jmp 0x3cb2
leaq 0xe8cf(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0xc(%rbp), %rcx
leaq 0xe4c9(%rip), %rax      # 0x12120
movq (%rax,%rcx,8), %rdx
movslq -0x8(%rbp), %rcx
leaq 0xe4ba(%rip), %rax      # 0x12120
movq (%rax,%rcx,8), %rcx
leaq 0x89d7(%rip), %rsi      # 0xc648
movb $0x0, %al
callq 0x20e0
jmp 0x3ce8
leaq 0xe897(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0xc(%rbp), %rcx
leaq 0xe4e1(%rip), %rax      # 0x12170
movq (%rax,%rcx,8), %rdx
movslq -0x8(%rbp), %rcx
leaq 0xe4d2(%rip), %rax      # 0x12170
movq (%rax,%rcx,8), %rcx
leaq 0x89ad(%rip), %rsi      # 0xc656
movb $0x0, %al
callq 0x20e0
jmp 0x3ce8
leaq 0xe85f(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0xc(%rbp), %rcx
leaq 0xe409(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rdx
movslq -0x8(%rbp), %rcx
leaq 0xe3fa(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rcx
leaq 0x8983(%rip), %rsi      # 0xc664
movb $0x0, %al
callq 0x20e0
leaq 0xe829(%rip), %rax      # 0x12518
movq (%rax), %rdi
movl -0x4(%rbp), %eax
subl $0xd, %eax
movslq %eax, %rcx
leaq 0xe4ee(%rip), %rax      # 0x121f0
movq (%rax,%rcx,8), %rdx
movl -0x10(%rbp), %ecx
leaq 0x897a(%rip), %rsi      # 0xc68a
movb $0x0, %al
callq 0x20e0
movl -0x8(%rbp), %edi
callq 0x24c0
movl -0xc(%rbp), %edi
callq 0x24c0
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x20, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/cg.c
// Function: cgreturn
void cgreturn(int reg, struct symtable *sym) {

  // 处理有返回值的
  if (reg != NOREG) {
    // 处理指针，不能把它放在下面的switch语句里面一起处理
    if (ptrtype(sym->type))
      fprintf(Outfile, "\tmovq\t%s, %%rax\n", reglist[reg]);
    else {
      // 根据函数类型生成相应汇编代码
      switch (sym->type) {
      case P_CHAR:
        fprintf(Outfile, "\tmovzbl\t%s, %%eax\n", breglist[reg]);
        break;
      case P_INT:
        fprintf(Outfile, "\tmovl\t%s, %%eax\n", dreglist[reg]);
        break;
      case P_LONG:
        fprintf(Outfile, "\tmovq\t%s, %%rax\n", reglist[reg]);
        break;
      default:
	      fatald("Bad function type in cgreturn:", sym->type);
      }
    }
  }

  cgjump(sym->stu.st_endlabel);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movl %edi, -0x4(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $-0x1, -0x4(%rbp)
je 0x3e6d
movq -0x10(%rbp), %rax
movl 0x10(%rax), %edi
callq 0xb720
cmpl $0x0, %eax
je 0x3db6
leaq 0xe787(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xe331(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rdx
leaq 0x88e9(%rip), %rsi      # 0xc693
movb $0x0, %al
callq 0x20e0
jmp 0x3e6b
movq -0x10(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x14(%rbp)
subl $0x20, %eax
je 0x3ddb
jmp 0x3dc7
movl -0x14(%rbp), %eax
subl $0x30, %eax
je 0x3e04
jmp 0x3dd1
movl -0x14(%rbp), %eax
subl $0x40, %eax
je 0x3e2d
jmp 0x3e56
leaq 0xe736(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xe330(%rip), %rax      # 0x12120
movq (%rax,%rcx,8), %rdx
leaq 0x88a9(%rip), %rsi      # 0xc6a4
movb $0x0, %al
callq 0x20e0
jmp 0x3e69
leaq 0xe70d(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xe357(%rip), %rax      # 0x12170
movq (%rax,%rcx,8), %rdx
leaq 0x8893(%rip), %rsi      # 0xc6b7
movb $0x0, %al
callq 0x20e0
jmp 0x3e69
leaq 0xe6e4(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xe28e(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rdx
leaq 0x8846(%rip), %rsi      # 0xc693
movb $0x0, %al
callq 0x20e0
jmp 0x3e69
movq -0x10(%rbp), %rax
movl 0x10(%rax), %esi
leaq 0x8864(%rip), %rdi      # 0xc6c8
callq 0x8180
jmp 0x3e6b
jmp 0x3e6d
movq -0x10(%rbp), %rax
movl (%rax), %edi
callq 0x3bc0
addq $0x20, %rsp
popq %rbp
retq
nop
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/cg.c
// Function: cgaddress
int cgaddress(struct symtable *sym) {
  int r = cgallocreg();

  if (sym->class == C_GLOBAL ||
      sym->class == C_EXTERN || sym->class == C_STATIC)
    fprintf(Outfile, "\tleaq\t%s(%%rip), %s\n", sym->name, reglist[r]);
  else
    fprintf(Outfile, "\tleaq\t%d(%%rbp), %s\n", sym->stu.st_posn, reglist[r]);
  return (r);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x10, %rsp
movq %rdi, -0x8(%rbp)
callq 0x23f0
movl %eax, -0xc(%rbp)
movq -0x8(%rbp), %rax
cmpl $0x1, 0x24(%rax)
je 0x3eb2
movq -0x8(%rbp), %rax
cmpl $0x4, 0x24(%rax)
je 0x3eb2
movq -0x8(%rbp), %rax
cmpl $0x5, 0x24(%rax)
jne 0x3ee3
leaq 0xe65f(%rip), %rax      # 0x12518
movq (%rax), %rdi
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdx
movslq -0xc(%rbp), %rcx
leaq 0xe201(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rcx
leaq 0x83fd(%rip), %rsi      # 0xc2d7
movb $0x0, %al
callq 0x20e0
jmp 0x3f10
leaq 0xe62e(%rip), %rax      # 0x12518
movq (%rax), %rdi
movq -0x8(%rbp), %rax
movl (%rax), %edx
movslq -0xc(%rbp), %rcx
leaq 0xe1d2(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rcx
leaq 0x83b9(%rip), %rsi      # 0xc2c2
movb $0x0, %al
callq 0x20e0
movl -0xc(%rbp), %eax
addq $0x10, %rsp
popq %rbp
retq
nopl (%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/cg.c
// Function: cgderef
int cgderef(int r, int type) {
  // 获得指针指向的类型
  int newtype = value_at(type);
  // 获得类型大小
  int size = cgprimsize(newtype);

  switch (size) {
  case 1:
    fprintf(Outfile, "\tmovzbq\t(%s), %s\n", reglist[r], reglist[r]);
    break;
  case 4:
    fprintf(Outfile, "\tmovslq\t(%s), %s\n", reglist[r], reglist[r]);
    break;
  case 8:
    fprintf(Outfile, "\tmovq\t(%s), %s\n", reglist[r], reglist[r]);
    break;
  default:
    fatald("Can't cgderef on type:", type);
  }
  return (r);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movl %edi, -0x4(%rbp)
movl %esi, -0x8(%rbp)
movl -0x8(%rbp), %edi
callq 0xb780
movl %eax, -0xc(%rbp)
movl -0xc(%rbp), %edi
callq 0x22e0
movl %eax, -0x10(%rbp)
movl -0x10(%rbp), %eax
movl %eax, -0x14(%rbp)
subl $0x1, %eax
je 0x3f68
jmp 0x3f51
movl -0x14(%rbp), %eax
subl $0x4, %eax
je 0x3fa0
jmp 0x3f5b
movl -0x14(%rbp), %eax
subl $0x8, %eax
je 0x3fd8
jmp 0x4010
leaq 0xe5a9(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xe153(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rdx
movslq -0x4(%rbp), %rcx
leaq 0xe144(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rcx
leaq 0x8750(%rip), %rsi      # 0xc6e7
movb $0x0, %al
callq 0x20e0
jmp 0x401f
leaq 0xe571(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xe11b(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rdx
movslq -0x4(%rbp), %rcx
leaq 0xe10c(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rcx
leaq 0x872a(%rip), %rsi      # 0xc6f9
movb $0x0, %al
callq 0x20e0
jmp 0x401f
leaq 0xe539(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xe0e3(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rdx
movslq -0x4(%rbp), %rcx
leaq 0xe0d4(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rcx
leaq 0x8704(%rip), %rsi      # 0xc70b
movb $0x0, %al
callq 0x20e0
jmp 0x401f
movl -0x8(%rbp), %esi
leaq 0x8701(%rip), %rdi      # 0xc71b
callq 0x8180
movl -0x4(%rbp), %eax
addq $0x20, %rsp
popq %rbp
retq
nopl (%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/cg.c
// Function: cgstorderef
int cgstorderef(int r1, int r2, int type) {
  // 获得类型大小
  int size = cgprimsize(type);

  switch (size) {
  case 1:
    fprintf(Outfile, "\tmovb\t%s, (%s)\n", breglist[r1], reglist[r2]);
    break;
  case 4:
    fprintf(Outfile, "\tmovl\t%s, (%s)\n", dreglist[r1], reglist[r2]);
    break;
  case 8:
    fprintf(Outfile, "\tmovq\t%s, (%s)\n", reglist[r1], reglist[r2]);
    break;
  default:
    fatald("Can't cgstoderef on type:", type);
  }
  return (r1);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movl %edi, -0x4(%rbp)
movl %esi, -0x8(%rbp)
movl %edx, -0xc(%rbp)
movl -0xc(%rbp), %edi
callq 0x22e0
movl %eax, -0x10(%rbp)
movl -0x10(%rbp), %eax
movl %eax, -0x14(%rbp)
subl $0x1, %eax
je 0x4070
jmp 0x4059
movl -0x14(%rbp), %eax
subl $0x4, %eax
je 0x40a8
jmp 0x4063
movl -0x14(%rbp), %eax
subl $0x8, %eax
je 0x40e0
jmp 0x4118
leaq 0xe4a1(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xe09b(%rip), %rax      # 0x12120
movq (%rax,%rcx,8), %rdx
movslq -0x8(%rbp), %rcx
leaq 0xe03c(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rcx
leaq 0x8693(%rip), %rsi      # 0xc732
movb $0x0, %al
callq 0x20e0
jmp 0x4127
leaq 0xe469(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xe0b3(%rip), %rax      # 0x12170
movq (%rax,%rcx,8), %rdx
movslq -0x8(%rbp), %rcx
leaq 0xe004(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rcx
leaq 0x866b(%rip), %rsi      # 0xc742
movb $0x0, %al
callq 0x20e0
jmp 0x4127
leaq 0xe431(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xdfdb(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rdx
movslq -0x8(%rbp), %rcx
leaq 0xdfcc(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rcx
leaq 0x8643(%rip), %rsi      # 0xc752
movb $0x0, %al
callq 0x20e0
jmp 0x4127
movl -0xc(%rbp), %esi
leaq 0x8640(%rip), %rdi      # 0xc762
callq 0x8180
movl -0x4(%rbp), %eax
addq $0x20, %rsp
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/cg.c
// Function: cgswitch
void cgswitch(int reg, int casecount, int toplabel,
	      int *caselabel, int *caseval, int defaultlabel) {
  int i, label;

  // 为switch表，获得和生成一个标签
  label = genlabel();
  cglabel(label);

  // 如果没有case，就创建一个case指向默认case
  if (casecount == 0) {
    caseval[0] = 0;
    caselabel[0] = defaultlabel;
    casecount = 1;
  }
  // 生成switch跳表
  fprintf(Outfile, "\t.quad\t%d\n", casecount);
  for (i = 0; i < casecount; i++)
    fprintf(Outfile, "\t.quad\t%d, L%d\n", caseval[i], caselabel[i]);
  fprintf(Outfile, "\t.quad\tL%d\n", defaultlabel);

  // 加载指定寄存器
  cglabel(toplabel);
  fprintf(Outfile, "\tmovq\t%s, %%rax\n", reglist[reg]);
  fprintf(Outfile, "\tleaq\tL%d(%%rip), %%rdx\n", label);
  fprintf(Outfile, "\tjmp\t__switch\n");
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movl %edi, -0x4(%rbp)
movl %esi, -0x8(%rbp)
movl %edx, -0xc(%rbp)
movq %rcx, -0x18(%rbp)
movq %r8, -0x20(%rbp)
movl %r9d, -0x24(%rbp)
callq 0x6830
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %edi
callq 0x2960
cmpl $0x0, -0x8(%rbp)
jne 0x417d
movq -0x20(%rbp), %rax
movl $0x0, (%rax)
movl -0x24(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, (%rax)
movl $0x1, -0x8(%rbp)
leaq 0xe394(%rip), %rax      # 0x12518
movq (%rax), %rdi
movl -0x8(%rbp), %edx
leaq 0x8481(%rip), %rsi      # 0xc612
movb $0x0, %al
callq 0x20e0
movl $0x0, -0x28(%rbp)
movl -0x28(%rbp), %eax
cmpl -0x8(%rbp), %eax
jge 0x41e0
leaq 0xe36a(%rip), %rax      # 0x12518
movq (%rax), %rdi
movq -0x20(%rbp), %rax
movslq -0x28(%rbp), %rcx
movl (%rax,%rcx,4), %edx
movq -0x18(%rbp), %rax
movslq -0x28(%rbp), %rcx
movl (%rax,%rcx,4), %ecx
leaq 0x85ae(%rip), %rsi      # 0xc77c
movb $0x0, %al
callq 0x20e0
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x28(%rbp)
jmp 0x419f
leaq 0xe331(%rip), %rax      # 0x12518
movq (%rax), %rdi
movl -0x24(%rbp), %edx
leaq 0x8412(%rip), %rsi      # 0xc606
movb $0x0, %al
callq 0x20e0
movl -0xc(%rbp), %edi
callq 0x2960
leaq 0xe30e(%rip), %rax      # 0x12518
movq (%rax), %rdi
movslq -0x4(%rbp), %rcx
leaq 0xdeb8(%rip), %rax      # 0x120d0
movq (%rax,%rcx,8), %rdx
leaq 0x8470(%rip), %rsi      # 0xc693
movb $0x0, %al
callq 0x20e0
leaq 0xe2e7(%rip), %rax      # 0x12518
movq (%rax), %rdi
movl -0x2c(%rbp), %edx
leaq 0x854e(%rip), %rsi      # 0xc78c
movb $0x0, %al
callq 0x20e0
leaq 0xe2cc(%rip), %rax      # 0x12518
movq (%rax), %rdi
leaq 0x854f(%rip), %rsi      # 0xc7a5
movb $0x0, %al
callq 0x20e0
addq $0x30, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/decl.c
// Function: typedef_declaration
static int typedef_declaration(struct symtable **ctype) {
  int type, class = 0;

  // 跳过typedef关键字.
  scan(&Token);

  // 获得接下来实际的类型
  type = parse_type(ctype, &class);
  if (class != 0)
    fatal("Can't have static/extern in a typedef declaration");

  // 检查看看是否已经存在
  if (findtypedef(Text) != NULL)
    fatals("redefinition of typedef", Text);

  // 解析指针类型
  // TODO：这里有问题
  type = parse_stars(type);

  // 不存在就把它加入到typedef列表
  addtypedef(Text, type, *ctype);
  scan(&Token);
  return (type);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x10, %rsp
movq %rdi, -0x8(%rbp)
movl $0x0, -0x10(%rbp)
leaq 0xdbd6(%rip), %rdi      # 0x12530
callq 0x84c0
movq -0x8(%rbp), %rdi
leaq -0x10(%rbp), %rsi
callq 0x42d0
movl %eax, -0xc(%rbp)
cmpl $0x0, -0x10(%rbp)
je 0x4981
leaq 0x8187(%rip), %rdi      # 0xcb03
callq 0x8110
leaq 0xdbd8(%rip), %rdi      # 0x12560
callq 0xa5a0
cmpq $0x0, %rax
je 0x49a6
leaq 0x819b(%rip), %rdi      # 0xcb35
leaq 0xdbbf(%rip), %rsi      # 0x12560
callq 0x7fc0
movl -0xc(%rbp), %edi
callq 0x4a40
movl %eax, -0xc(%rbp)
movl -0xc(%rbp), %esi
movq -0x8(%rbp), %rax
movq (%rax), %rdx
leaq 0xdb9e(%rip), %rdi      # 0x12560
callq 0xa290
leaq 0xdb62(%rip), %rdi      # 0x12530
callq 0x84c0
movl -0xc(%rbp), %eax
addq $0x10, %rsp
popq %rbp
retq
nopl (%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/decl.c
// Function: type_of_typedef
static int type_of_typedef(char *name, struct symtable **ctype) {
  struct symtable *t;

  // 查找typedef列表
  t = findtypedef(name);
  if (t == NULL)
    fatals("unknown type", name);
  scan(&Token);
  *ctype = t->ctype;
  return (t->type);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rdi
callq 0xa5a0
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x18(%rbp)
jne 0x4a14
movq -0x8(%rbp), %rsi
leaq 0x813e(%rip), %rdi      # 0xcb4d
callq 0x7fc0
leaq 0xdb15(%rip), %rdi      # 0x12530
callq 0x84c0
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
movq -0x18(%rbp), %rax
movl 0x10(%rax), %eax
addq $0x20, %rsp
popq %rbp
retq
nopl (%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/decl.c
// Function: parse_stars
int parse_stars(int type) {

  while (1) {
    if (Token.token != T_STAR)
      break;
    type = pointer_to(type);
    scan(&Token);
  }
  return (type);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x10, %rsp
movl %edi, -0x4(%rbp)
leaq 0xdade(%rip), %rax      # 0x12530
cmpl $0x17, (%rax)
je 0x4a59
jmp 0x4a72
movl -0x4(%rbp), %edi
callq 0xb740
movl %eax, -0x4(%rbp)
leaq 0xdac5(%rip), %rdi      # 0x12530
callq 0x84c0
jmp 0x4a4b
movl -0x4(%rbp), %eax
addq $0x10, %rsp
popq %rbp
retq
nopl (%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/decl.c
// Function: parse_cast
int parse_cast(struct symtable **ctype) {
  int type, class = 0;

  // 从括号里面获取类型
  type = parse_stars(parse_type(ctype, &class));

  // 错误检查，目前不支持，强转到复合类型
  if (type == P_STRUCT || type == P_UNION || type == P_VOID)
    fatal("Cannot cast to a struct, union or void type");
  return (type);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x10, %rsp
movq %rdi, -0x8(%rbp)
movl $0x0, -0x10(%rbp)
movq -0x8(%rbp), %rdi
leaq -0x10(%rbp), %rsi
callq 0x42d0
movl %eax, %edi
callq 0x4a40
movl %eax, -0xc(%rbp)
cmpl $0x50, -0xc(%rbp)
je 0x4abc
cmpl $0x60, -0xc(%rbp)
je 0x4abc
cmpl $0x10, -0xc(%rbp)
jne 0x4ac8
leaq 0x7ecb(%rip), %rdi      # 0xc98e
callq 0x8110
movl -0xc(%rbp), %eax
addq $0x10, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/decl.c
// Function: parse_literal
int parse_literal(int type) {
  struct ASTnode *tree;

  // 解析表达式，并优化解析出来的语法树tree
  tree = optimise(binexpr(0));

  // 如果这里有个cast，获取子树应用到tree上
  if (tree->op == A_CAST) {
    tree->left->type = tree->type;
    tree = tree->left;
  }

  // 这颗tree现在必须是个整型或者字符串字面量
  if (tree->op != A_INTLIT && tree->op != A_STRLIT)
    fatal("Cannot initialise globals with a general expression");

  // 如果type是char*
  if (type == pointer_to(P_CHAR)) {
    // tree是字符字面量，返回标签号
    if (tree->op == A_STRLIT)
      return (tree->atu.a_intvalue);
    // tree是整型零值，所以是个NULL，所以返回0
    if (tree->op == A_INTLIT && tree->atu.a_intvalue == 0)
      return (0);
  }

  // 代码走到这里就是处理整型字面量量
  // 输入的type必须是个整型，同时足够宽来容纳这个字面值
  if (inttype(type) && typesize(type, NULL) >= typesize(tree->type, NULL))
    return (tree->atu.a_intvalue);

  fatal("Type mismatch: literal vs. variable");
  return (0);		
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movl %edi, -0x8(%rbp)
xorl %edi, %edi
callq 0x58c0
movq %rax, %rdi
callq 0x8260
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x34, 0x4(%rax)
jne 0x4b26
movq -0x10(%rbp), %rax
movl 0x8(%rax), %ecx
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movl %ecx, 0x8(%rax)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x1a, 0x4(%rax)
je 0x4b46
movq -0x10(%rbp), %rax
cmpl $0x1b, 0x4(%rax)
je 0x4b46
leaq 0x7e79(%rip), %rdi      # 0xc9ba
callq 0x8110
movl -0x8(%rbp), %eax
movl %eax, -0x14(%rbp)
movl $0x20, %edi
callq 0xb740
movl %eax, %ecx
movl -0x14(%rbp), %eax
cmpl %ecx, %eax
jne 0x4b92
movq -0x10(%rbp), %rax
cmpl $0x1b, 0x4(%rax)
jne 0x4b74
movq -0x10(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x4(%rbp)
jmp 0x4be5
movq -0x10(%rbp), %rax
cmpl $0x1a, 0x4(%rax)
jne 0x4b90
movq -0x10(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x4b90
movl $0x0, -0x4(%rbp)
jmp 0x4be5
jmp 0x4b92
movl -0x8(%rbp), %edi
callq 0xb6e0
cmpl $0x0, %eax
je 0x4bd2
movl -0x8(%rbp), %edi
xorl %eax, %eax
movl %eax, %esi
callq 0xb7c0
movl %eax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %edi
xorl %eax, %eax
movl %eax, %esi
callq 0xb7c0
movl %eax, %ecx
movl -0x18(%rbp), %eax
cmpl %ecx, %eax
jl 0x4bd2
movq -0x10(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x4(%rbp)
jmp 0x4be5
leaq 0x7e15(%rip), %rdi      # 0xc9ee
callq 0x8110
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x20, %rsp
popq %rbp
retq
nop
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/decl.c
// Function: declaration_list
int declaration_list(struct symtable **ctype, int class, int et1, int et2,
		     struct ASTnode **gluetree) {
  int inittype, type;
  struct symtable *sym;
  struct ASTnode *tree;
  *gluetree = NULL; // TODO：有问题？

  // 获取初始的类型， 如果是-1，代表是个复合类型声明，直接返回
  if ((inittype = parse_type(ctype, &class)) == -1)
    return (inittype);

  // 现在解析一列表符号
  while (1) {
    // 看看这个符号是否是个指针
    type = parse_stars(inittype);

    // 解析符号
    sym = symbol_declaration(type, *ctype, class, &tree);

    // 解析到函数，直接返回
    if (sym->stype == S_FUNCTION) {
      if (class != C_GLOBAL && class != C_STATIC)
	      fatal("Function definition not at global level");
      return (type);
    }

    // 把tree粘起来（Glue）
    // 这只在本地变量声明并有赋值操作的时候，
    // 这样就能把一系列赋值操作连起来
    if (*gluetree == NULL)
      *gluetree = tree;
    else
      *gluetree =
	      mkastnode(A_GLUE, P_NONE, NULL, *gluetree, NULL, tree, NULL, 0);

    // 遇到结束token，返回
    if (Token.token == et1 || Token.token == et2)
      return (type);

    // 否则，匹配逗号，继续
    comma();
  }

  return(0);	
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movl %edx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movq %r8, -0x28(%rbp)
movq -0x28(%rbp), %rax
movq $0x0, (%rax)
movq -0x10(%rbp), %rdi
leaq -0x14(%rbp), %rsi
callq 0x42d0
movl %eax, -0x2c(%rbp)
cmpl $-0x1, %eax
jne 0x4c34
movl -0x2c(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x4d03
jmp 0x4c36
movl -0x2c(%rbp), %edi
callq 0x4a40
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %edi
movq -0x10(%rbp), %rax
movq (%rax), %rsi
movl -0x14(%rbp), %edx
leaq -0x40(%rbp), %rcx
callq 0x4d10
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
cmpl $0x1, 0x20(%rax)
jne 0x4c85
cmpl $0x1, -0x14(%rbp)
je 0x4c7d
cmpl $0x5, -0x14(%rbp)
je 0x4c7d
leaq 0x7d9a(%rip), %rdi      # 0xca12
callq 0x8110
movl -0x30(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x4d03
movq -0x28(%rbp), %rax
cmpq $0x0, (%rax)
jne 0x4c9c
movq -0x40(%rbp), %rcx
movq -0x28(%rbp), %rax
movq %rcx, (%rax)
jmp 0x4cd5
movq -0x28(%rbp), %rax
movq (%rax), %rcx
movq -0x40(%rbp), %r9
movl $0x1d, %edi
xorl %esi, %esi
xorl %eax, %eax
movl %eax, %r8d
movq %r8, %rdx
movq $0x0, (%rsp)
movl $0x0, 0x8(%rsp)
callq 0xac90
movq %rax, %rcx
movq -0x28(%rbp), %rax
movq %rcx, (%rax)
leaq 0xd854(%rip), %rax      # 0x12530
movl (%rax), %eax
cmpl -0x18(%rbp), %eax
je 0x4cf1
leaq 0xd846(%rip), %rax      # 0x12530
movl (%rax), %eax
cmpl -0x1c(%rbp), %eax
jne 0x4cf9
movl -0x30(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x4d03
callq 0x80f0
jmp 0x4c36
movl -0x4(%rbp), %eax
addq $0x50, %rsp
popq %rbp
retq
nopl (%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/decl.c
// Function: symbol_declaration
static struct symtable *symbol_declaration(int type, struct symtable *ctype,
					   int class, struct ASTnode **tree) {
  struct symtable *sym = NULL;
  char *varname = strdup(Text); // 拷贝出来以防后面Text被覆盖

  // 保证我们有个标识符
  ident();

  // 处理函数声明
  if (Token.token == T_LPAREN) {
    return (function_declaration(varname, type, ctype, class));
  }

  // 检查变量是否已经声明过了
  switch (class) {
    case C_EXTERN:
    case C_STATIC:
    case C_GLOBAL:
    case C_LOCAL:
    case C_PARAM:
      if (findlocl(varname) != NULL)
	      fatals("Duplicate local variable declaration", varname);
    case C_MEMBER:
      if (findmember(varname) != NULL)
	      fatals("Duplicate struct/union member declaration", varname);
  }

  // 把数组或标量变量加入到符号表
  if (Token.token == T_LBRACKET) {
    sym = array_declaration(varname, type, ctype, class);
    *tree= NULL;	// 本地数组不支持初始化
  } else
    sym = scalar_declaration(varname, type, ctype, class, tree);
  return (sym);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movl %edi, -0xc(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movq %rcx, -0x28(%rbp)
movq $0x0, -0x30(%rbp)
leaq 0xd82b(%rip), %rdi      # 0x12560
callq 0x2150
movq %rax, -0x38(%rbp)
callq 0x80d0
leaq 0xd7e6(%rip), %rax      # 0x12530
cmpl $0x39, (%rax)
jne 0x4d6b
movq -0x38(%rbp), %rdi
movl -0xc(%rbp), %esi
movq -0x18(%rbp), %rdx
movl -0x1c(%rbp), %ecx
callq 0x4e90
movq %rax, -0x8(%rbp)
jmp 0x4e19
movl -0x1c(%rbp), %eax
movl %eax, -0x3c(%rbp)
decl %eax
subl $0x5, %eax
jb 0x4d84
jmp 0x4d7a
movl -0x3c(%rbp), %eax
subl $0x8, %eax
je 0x4da5
jmp 0x4dc6
movq -0x38(%rbp), %rdi
callq 0xa3a0
cmpq $0x0, %rax
je 0x4da3
movq -0x38(%rbp), %rsi
leaq 0x7dbc(%rip), %rdi      # 0xcb5a
callq 0x7fc0
jmp 0x4da5
movq -0x38(%rbp), %rdi
callq 0xa4b0
cmpq $0x0, %rax
je 0x4dc4
movq -0x38(%rbp), %rsi
leaq 0x7dc0(%rip), %rdi      # 0xcb7f
callq 0x7fc0
jmp 0x4dc6
leaq 0xd763(%rip), %rax      # 0x12530
cmpl $0x3b, (%rax)
jne 0x4df6
movq -0x38(%rbp), %rdi
movl -0xc(%rbp), %esi
movq -0x18(%rbp), %rdx
movl -0x1c(%rbp), %ecx
callq 0x50d0
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rax
movq $0x0, (%rax)
jmp 0x4e11
movq -0x38(%rbp), %rdi
movl -0xc(%rbp), %esi
movq -0x18(%rbp), %rdx
movl -0x1c(%rbp), %ecx
movq -0x28(%rbp), %r8
callq 0x53d0
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/decl.c
// Function: global_declarations
void global_declarations(void) {
  struct symtable *ctype= NULL;
  struct ASTnode *unused;

  // 循环解析直到文件结束
  while (Token.token != T_EOF) {
    declaration_list(&ctype, C_GLOBAL, T_SEMI, T_EOF, &unused);

    // 跳过分号
    if (Token.token == T_SEMI)
      scan(&Token);
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x10, %rsp
movq $0x0, -0x8(%rbp)
leaq 0xd6e9(%rip), %rax      # 0x12530
cmpl $0x0, (%rax)
je 0x4e7f
leaq -0x8(%rbp), %rdi
movl $0x1, %esi
movl $0x35, %edx
xorl %ecx, %ecx
leaq -0x10(%rbp), %r8
callq 0x4bf0
leaq 0xd6c4(%rip), %rax      # 0x12530
cmpl $0x35, (%rax)
jne 0x4e7d
leaq 0xd6b8(%rip), %rdi      # 0x12530
callq 0x84c0
jmp 0x4e40
addq $0x10, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/decl.c
// Function: param_declaration_list
static int param_declaration_list(struct symtable *oldfuncsym,
				  struct symtable *newfuncsym) {
  int type, paramcnt = 0;
  struct symtable *ctype;
  struct symtable *protoptr = NULL;
  struct ASTnode *unused;

  // 获取旧函数的成员
  if (oldfuncsym != NULL)
    protoptr = oldfuncsym->member;

  // 循环获取参数
  while (Token.token != T_RPAREN) {

    // 如果第一个token是'void'
    if (Token.token == T_VOID) {
      // 偷看下个token，如果是')', 表示函数没有参数，离开循环  
      scan(&Peektoken);
      if (Peektoken.token == T_RPAREN) {
        // 把Peektoken放回到Token
        paramcnt = 0;
        scan(&Token);
        break;
      }
    }

    // 获得下一个参数的类型
    type = declaration_list(&ctype, C_PARAM, T_COMMA, T_RPAREN, &unused);
    if (type == -1)
      fatal("Bad type in parameter list");

    // 保证这个参数的类型跟旧的匹配
    if (protoptr != NULL) {
      if (type != protoptr->type)
	      fatald("Type doesn't match prototype for parameter", paramcnt + 1);
      protoptr = protoptr->next;
    }
    paramcnt++;

    // 遇到右括号，退出循环
    if (Token.token == T_RPAREN)
      break;
    // 否则看看是否是个逗号
    comma();
  }

  if (oldfuncsym != NULL && paramcnt != oldfuncsym->nelems)
    fatals("Parameter count mismatch for function", oldfuncsym->name);

  // 返回函数参数
  return (paramcnt);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x0, -0x18(%rbp)
movq $0x0, -0x28(%rbp)
cmpq $0x0, -0x8(%rbp)
je 0x5642
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0x5644
leaq 0xcee5(%rip), %rax      # 0x12530
cmpl $0x3a, (%rax)
je 0x5715
leaq 0xced5(%rip), %rax      # 0x12530
cmpl $0x1e, (%rax)
jne 0x5692
leaq 0xcee1(%rip), %rdi      # 0x12548
callq 0x84c0
leaq 0xced5(%rip), %rax      # 0x12548
cmpl $0x3a, (%rax)
jne 0x5690
movl $0x0, -0x18(%rbp)
leaq 0xceaa(%rip), %rdi      # 0x12530
callq 0x84c0
jmp 0x5715
jmp 0x5692
leaq -0x20(%rbp), %rdi
movl $0x3, %esi
movl $0x3d, %edx
movl $0x3a, %ecx
leaq -0x30(%rbp), %r8
callq 0x4bf0
movl %eax, -0x14(%rbp)
cmpl $-0x1, -0x14(%rbp)
jne 0x56c3
leaq 0x7542(%rip), %rdi      # 0xcc00
callq 0x8110
cmpq $0x0, -0x28(%rbp)
je 0x56f4
movl -0x14(%rbp), %eax
movq -0x28(%rbp), %rcx
cmpl 0x10(%rcx), %eax
je 0x56e8
movl -0x18(%rbp), %esi
addl $0x1, %esi
leaq 0x7538(%rip), %rdi      # 0xcc1b
callq 0x8180
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x28(%rbp)
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
leaq 0xce2c(%rip), %rax      # 0x12530
cmpl $0x3a, (%rax)
jne 0x570b
jmp 0x5715
callq 0x80f0
jmp 0x5644
cmpq $0x0, -0x8(%rbp)
je 0x573c
movl -0x18(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl 0x2c(%rcx), %eax
je 0x573c
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rsi
leaq 0x750f(%rip), %rdi      # 0xcc46
callq 0x7fc0
movl -0x18(%rbp), %eax
addq $0x30, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/decl.c
// Function: is_new_symbol
static int is_new_symbol(struct symtable *sym, int class, 
		  int type, struct symtable *ctype) {

  // 不存在，代表是新的
  if (sym==NULL) return(1);

  // 如果类型匹配，就转换为global（全局）
  if ((sym->class== C_GLOBAL && class== C_EXTERN)
      || (sym->class== C_EXTERN && class== C_GLOBAL)) {

      // 类型不匹配
      if (type != sym->type)
        fatals("Type mismatch between global/extern", sym->name);

      // Struct/unions, 比较ctype
      if (type >= P_STRUCT && ctype != sym->ctype)
        fatals("Type mismatch between global/extern", sym->name);

      // 到这里，代表类型匹配来，转换为global（全局）
      sym->class= C_GLOBAL;
      // 返回0，表示符号不是新的
      return(0);
  }

  // 如果到了这里，代表重复定义
  fatals("Duplicate global variable declaration", sym->name);
  return(-1);	
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movl %edx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
cmpq $0x0, -0x10(%rbp)
jne 0x5779
movl $0x1, -0x4(%rbp)
jmp 0x5810
movq -0x10(%rbp), %rax
cmpl $0x1, 0x24(%rax)
jne 0x5789
cmpl $0x4, -0x14(%rbp)
je 0x5799
movq -0x10(%rbp), %rax
cmpl $0x4, 0x24(%rax)
jne 0x57f5
cmpl $0x1, -0x14(%rbp)
jne 0x57f5
movl -0x18(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0x10(%rcx), %eax
je 0x57b9
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
leaq 0x756c(%rip), %rdi      # 0xcd20
callq 0x7fc0
cmpl $0x50, -0x18(%rbp)
jl 0x57e1
movq -0x20(%rbp), %rax
movq -0x10(%rbp), %rcx
cmpq 0x18(%rcx), %rax
je 0x57e1
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
leaq 0x7544(%rip), %rdi      # 0xcd20
callq 0x7fc0
movq -0x10(%rbp), %rax
movl $0x1, 0x24(%rax)
movl $0x0, -0x4(%rbp)
jmp 0x5810
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
leaq 0x7540(%rip), %rdi      # 0xcd44
callq 0x7fc0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl -0x4(%rbp), %eax
addq $0x20, %rsp
popq %rbp
retq
nopl (%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/expr.c
// Function: expression_list
struct ASTnode *expression_list(int endtoken) {
  struct ASTnode *tree = NULL;
  struct ASTnode *child = NULL;
  int exprcount = 0;

  // 循环直到遇到结束的token
  while (Token.token != endtoken) {

    // 解析下个表达式，同时增加表达式数量
    child = binexpr(0);
    exprcount++;

    // 创建一个A_GLUE节点，左树是之前的tree，右树是新的表达式child，同时保存表达式数量
    tree =
      mkastnode(A_GLUE, P_NONE, NULL, tree, NULL, child, NULL, exprcount);

    // 遇到结束token
    if (Token.token == endtoken)
      break;

    // 必须有逗号
    match(T_COMMA, ",");
  }

  // 返回所有表达式的树
  return (tree);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movl %edi, -0x4(%rbp)
movq $0x0, -0x10(%rbp)
movq $0x0, -0x18(%rbp)
movl $0x0, -0x1c(%rbp)
leaq 0xcce7(%rip), %rax      # 0x12530
movl (%rax), %eax
cmpl -0x4(%rbp), %eax
je 0x58b6
xorl %edi, %edi
callq 0x58c0
movq %rax, -0x18(%rbp)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
movq -0x10(%rbp), %rcx
movq -0x18(%rbp), %r9
movl -0x1c(%rbp), %eax
movl $0x1d, %edi
xorl %esi, %esi
xorl %edx, %edx
movl %edx, %r8d
movq %r8, %rdx
movq $0x0, (%rsp)
movl %eax, 0x8(%rsp)
callq 0xac90
movq %rax, -0x10(%rbp)
leaq 0xcc96(%rip), %rax      # 0x12530
movl (%rax), %eax
cmpl -0x4(%rbp), %eax
jne 0x58a3
jmp 0x58b6
movl $0x3d, %edi
leaq 0x75fd(%rip), %rsi      # 0xceac
callq 0x7f70
jmp 0x5842
movq -0x10(%rbp), %rax
addq $0x30, %rsp
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/expr.c
// Function: op_precedence
static int op_precedence(int tokentype) {
  int prec;
  if (tokentype > T_MOD)
    fatals("Token with no precedence in op_precedence:", Tstring[tokentype]);
  prec = OpPrec[tokentype];
  if (prec == 0)
    fatals("Syntax error, token", Tstring[tokentype]);
  return (prec);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x10, %rsp
movl %edi, -0x4(%rbp)
cmpl $0x19, -0x4(%rbp)
jle 0x5eec
movslq -0x4(%rbp), %rcx
leaq 0xc3b4(%rip), %rax      # 0x12290
movq (%rax,%rcx,8), %rsi
leaq 0x72e7(%rip), %rdi      # 0xd1ce
callq 0x7fc0
movslq -0x4(%rbp), %rcx
leaq 0xc329(%rip), %rax      # 0x12220
movl (%rax,%rcx,4), %eax
movl %eax, -0x8(%rbp)
cmpl $0x0, -0x8(%rbp)
jne 0x5f1e
movslq -0x4(%rbp), %rcx
leaq 0xc382(%rip), %rax      # 0x12290
movq (%rax,%rcx,8), %rsi
leaq 0x72e0(%rip), %rdi      # 0xd1f9
callq 0x7fc0
movl -0x8(%rbp), %eax
addq $0x10, %rsp
popq %rbp
retq
nopw (%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/expr.c
// Function: binastop
static int binastop(int tokentype) {
  if (tokentype > T_EOF && tokentype <= T_MOD)
    return (tokentype);
  fatals("Syntax error, token", Tstring[tokentype]);
  return (0);		
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x10, %rsp
movl %edi, -0x8(%rbp)
cmpl $0x0, -0x8(%rbp)
jle 0x5f7f
cmpl $0x19, -0x8(%rbp)
jg 0x5f7f
movl -0x8(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x5fa1
movslq -0x8(%rbp), %rcx
leaq 0xc306(%rip), %rax      # 0x12290
movq (%rax,%rcx,8), %rsi
leaq 0x7264(%rip), %rdi      # 0xd1f9
callq 0x7fc0
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x10, %rsp
popq %rbp
retq
nopw (%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/expr.c
// Function: postfix
static struct ASTnode *postfix(int ptp) {
  struct ASTnode *n;

  // 获取主语表达式
  n = primary(ptp);

  // 循环直到没有后缀操作符
  while (1) {
    switch (Token.token) {
    case T_LBRACKET:
      // 访问数组
      n = array_access(n);
      break;

    case T_DOT:
      // 访问struct/union
      n = member_access(n, 0);
      break;

    case T_ARROW:
      // 指针访问struct/union
      n = member_access(n, 1);
      break;

    case T_INC:
      // 后缀加加
      if (n->rvalue == 1)
	      fatal("Cannot ++ on rvalue");
      scan(&Token); // 跳过token

      // 不能做两次
      if (n->op == A_POSTINC || n->op == A_POSTDEC)
	      fatal("Cannot ++ and/or -- more than once");

      // 改变节点类型
      n->op = A_POSTINC;
      break;

    case T_DEC:
      // 后缀减减
      if (n->rvalue == 1)
	      fatal("Cannot -- on rvalue");
      scan(&Token); // 跳过token

      // 不能做两次
      if (n->op == A_POSTINC || n->op == A_POSTDEC)
	      fatal("Cannot ++ and/or -- more than once");

      // 改变节点类型
      n->op = A_POSTDEC;
      break;

    default:
      return (n);
    }
  }

  return (NULL);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movl %edi, -0x4(%rbp)
movl -0x4(%rbp), %edi
callq 0x60e0
movq %rax, -0x10(%rbp)
leaq 0xc562(%rip), %rax      # 0x12530
movl (%rax), %eax
addl $-0x1a, %eax
movl %eax, %ecx
movq %rcx, -0x18(%rbp)
subl $0x25, %eax
ja 0x60d1
movq -0x18(%rbp), %rax
leaq 0x6deb(%rip), %rcx      # 0xcdd8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x10(%rbp), %rdi
callq 0x6410
movq %rax, -0x10(%rbp)
jmp 0x60db
movq -0x10(%rbp), %rdi
xorl %esi, %esi
callq 0x6520
movq %rax, -0x10(%rbp)
jmp 0x60db
movq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0x6520
movq %rax, -0x10(%rbp)
jmp 0x60db
movq -0x10(%rbp), %rax
cmpl $0x1, 0x18(%rax)
jne 0x6049
leaq 0x6f83(%rip), %rdi      # 0xcfc7
callq 0x8110
leaq 0xc4e0(%rip), %rdi      # 0x12530
callq 0x84c0
movq -0x10(%rbp), %rax
cmpl $0x29, 0x4(%rax)
je 0x6069
movq -0x10(%rbp), %rax
cmpl $0x2a, 0x4(%rax)
jne 0x6075
leaq 0x6f6b(%rip), %rdi      # 0xcfdb
callq 0x8110
movq -0x10(%rbp), %rax
movl $0x29, 0x4(%rax)
jmp 0x60db
movq -0x10(%rbp), %rax
cmpl $0x1, 0x18(%rax)
jne 0x6098
leaq 0x6f6b(%rip), %rdi      # 0xcffe
callq 0x8110
leaq 0xc491(%rip), %rdi      # 0x12530
callq 0x84c0
movq -0x10(%rbp), %rax
cmpl $0x29, 0x4(%rax)
je 0x60b8
movq -0x10(%rbp), %rax
cmpl $0x2a, 0x4(%rax)
jne 0x60c4
leaq 0x6f1c(%rip), %rdi      # 0xcfdb
callq 0x8110
movq -0x10(%rbp), %rax
movl $0x2a, 0x4(%rax)
jmp 0x60db
movq -0x10(%rbp), %rax
addq $0x20, %rsp
popq %rbp
retq
jmp 0x5fc7
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/expr.c
// Function: array_access
static struct ASTnode *array_access(struct ASTnode *left) {
  struct ASTnode *right;

  // 确认子树是否为指针
  if (!ptrtype(left->type))
    fatal("Not an array or pointer");

  // 获得'['
  scan(&Token);

  // 解析接下来的表达式
  right = binexpr(0);

  // 匹配']'
  match(T_RBRACKET, "]");

  // 保证是整型
  if (!inttype(right->type))
    fatal("Array index is not of integer type");

  // 让左树为右值
  left->rvalue = 1;

  // 使索引按元素类型大小来增大
  right = modify_type(right, left->type, left->ctype, A_ADD);

  // 返回一个语法树节点，该节点是给这个数组的基地址加上位移
  // 然后再在这个节点基础上，再加个节点来解引用。现在这些节点还是左值
  left =
    mkastnode(A_ADD, left->type, left->ctype, left, NULL, right, NULL, 0);
  left =
    mkastunary(A_DEREF, value_at(left->type), left->ctype, left, NULL, 0);
  return (left);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movl 0x8(%rax), %edi
callq 0xb720
cmpl $0x0, %eax
jne 0x6439
leaq 0x6cee(%rip), %rdi      # 0xd122
callq 0x8110
leaq 0xc0f0(%rip), %rdi      # 0x12530
callq 0x84c0
xorl %edi, %edi
callq 0x58c0
movq %rax, -0x10(%rbp)
movl $0x3c, %edi
leaq 0x7b58(%rip), %rsi      # 0xdfb4
callq 0x7f70
movq -0x10(%rbp), %rax
movl 0x8(%rax), %edi
callq 0xb6e0
cmpl $0x0, %eax
jne 0x647e
leaq 0x6cc1(%rip), %rdi      # 0xd13a
callq 0x8110
movq -0x8(%rbp), %rax
movl $0x1, 0x18(%rax)
movq -0x10(%rbp), %rdi
movq -0x8(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rdx
movl $0x15, %ecx
callq 0xb800
movq %rax, -0x10(%rbp)
movq -0x8(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rdx
movq -0x8(%rbp), %rcx
movq -0x10(%rbp), %r9
movl $0x15, %edi
xorl %eax, %eax
movl %eax, %r8d
xorl %eax, %eax
movq $0x0, (%rsp)
movl $0x0, 0x8(%rsp)
callq 0xac90
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
movl 0x8(%rax), %edi
callq 0xb780
movl %eax, %esi
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rdx
movq -0x8(%rbp), %rcx
movl $0x24, %edi
xorl %eax, %eax
movl %eax, %r8d
xorl %r9d, %r9d
callq 0xada0
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x20, %rsp
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/expr.c
// Function: funccall
static struct ASTnode *funccall(void) {
  struct ASTnode *tree;
  struct symtable *funcptr;

  // 判断函数是否已经定义了
  if ((funcptr = findsymbol(Text)) == NULL || funcptr->stype != S_FUNCTION) {
    fatals("Undeclared function", Text);
  }

  // 是否匹配'('
  lparen();

  // 解析参数的表达式列表
  tree = expression_list(T_RPAREN);

  // TODO: 要检查每个参数类型是否匹配函数原型

  // 创建函数调用语法树节点，保存函数返回类型作为节点类型
  // 同时记录函数符号号
  tree =
    mkastunary(A_FUNCCALL, funcptr->type, funcptr->ctype, tree, funcptr, 0);

  // 是否匹配')'
  rparen();
  return (tree);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x10, %rsp
leaq 0xbe81(%rip), %rdi      # 0x12560
callq 0xa410
movq %rax, -0x10(%rbp)
cmpq $0x0, %rax
je 0x66f8
movq -0x10(%rbp), %rax
cmpl $0x1, 0x20(%rax)
je 0x670b
leaq 0x6a0f(%rip), %rdi      # 0xd10e
leaq 0xbe5a(%rip), %rsi      # 0x12560
callq 0x7fc0
callq 0x8090
movl $0x3a, %edi
callq 0x5820
movq %rax, -0x8(%rbp)
movq -0x10(%rbp), %rax
movl 0x10(%rax), %esi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdx
movq -0x8(%rbp), %rcx
movq -0x10(%rbp), %r8
movl $0x23, %edi
xorl %r9d, %r9d
callq 0xada0
movq %rax, -0x8(%rbp)
callq 0x80b0
movq -0x8(%rbp), %rax
addq $0x10, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/expr.c
// Function: paren_expression
static struct ASTnode *paren_expression(int ptp) {
  struct ASTnode *n;
  int type = 0;
  struct symtable *ctype = NULL;

  // 跳过'('
  scan(&Token);

  // 如果后面跟的是一个类型标识符，有可能是一个cast表达式
  switch (Token.token) {
  case T_IDENT:
    // 如果一个标识符匹配一个typedef
    // 如果不是，那就是普通表达式
    if (findtypedef(Text) == NULL) {
      n = binexpr(0);	// ptp是0，当表达式在( )里
      break;
    }
  case T_VOID:
  case T_CHAR:
  case T_INT:
  case T_LONG:
  case T_STRUCT:
  case T_UNION:
  case T_ENUM:
    // 在括号里面获取类型
    type = parse_cast(&ctype);

    // 跳过')'，然后解析接下来的表达式
    rparen();

  default:
    n = binexpr(ptp);		// 扫描表达式，我们传入ptp，是因为cast不会改变表达式优先级

  }

  // n现在至少有一个表达式，
  // type如果是非0，那就代表有cast
  // type如果是0，代表没有cast，那就跳过')'
  if (type == 0)
    rparen();
  else
    // 否则，为cast创建一个单语法树节点
    n = mkastunary(A_CAST, type, ctype, n, NULL, 0);
  return (n);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movl %edi, -0x4(%rbp)
movl $0x0, -0x14(%rbp)
movq $0x0, -0x20(%rbp)
leaq 0xbdaf(%rip), %rdi      # 0x12530
movq %rdi, -0x30(%rbp)
callq 0x84c0
movq -0x30(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x24(%rbp)
addl $-0x1e, %eax
subl $0x4, %eax
jb 0x67d5
jmp 0x679d
movl -0x24(%rbp), %eax
addl $-0x27, %eax
subl $0x3, %eax
jb 0x67d5
jmp 0x67aa
movl -0x24(%rbp), %eax
subl $0x36, %eax
jne 0x67e6
jmp 0x67b4
leaq 0xbda5(%rip), %rdi      # 0x12560
callq 0xa5a0
cmpq $0x0, %rax
jne 0x67d3
xorl %edi, %edi
callq 0x58c0
movq %rax, -0x10(%rbp)
jmp 0x67f2
jmp 0x67d5
leaq -0x20(%rbp), %rdi
callq 0x4a80
movl %eax, -0x14(%rbp)
callq 0x80b0
movl -0x4(%rbp), %edi
callq 0x58c0
movq %rax, -0x10(%rbp)
cmpl $0x0, -0x14(%rbp)
jne 0x67ff
callq 0x80b0
jmp 0x6820
movl -0x14(%rbp), %esi
movq -0x20(%rbp), %rdx
movq -0x10(%rbp), %rcx
movl $0x34, %edi
xorl %eax, %eax
movl %eax, %r8d
xorl %r9d, %r9d
callq 0xada0
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
addq $0x30, %rsp
popq %rbp
retq
nopw (%rax,%rax)