// File: /workspace/github_cpp_makefile_star2_O2/JameyWoo[P]csmile/assembly.cpp
// Function: genFunc(TreeNode*)
void genFunc(TreeNode* func) {
    // ! 函数需要分析参数的栈情况, 写入符号表. 因此这个符号表非常重要.
    string func_name = func->child[1]->name;
    // debug("func name: " + func_name);
    // debug(func->child[2]->nodekind);  // 函数的参数
    // debug(func->child[3]->nodekind);  // 函数的内容

    assout << "\t.global\t" << func->child[1]->name << endl
           << "\t.type\t" << func->child[1]->name << ", @function" << endl
           << func->child[1]->name << ":" << endl
           << ".LFB" + to_string(LFB_id) << ":" << endl
           << "\t"
           << "pushl"
           << "\t"
           << "%ebp\n"
           << "\tmovl\t%esp, %ebp" << endl;

    int stack_size = 16;

    // 对参数生成对应的符号表
    getParams(func->child[2], func->child[1]->name);
    TreeNode* statement = NULL;

    // debug(func->child[3]->child[0]->nodekind);
    // 在 func->child[3] 中, 如果有临时变量声明, 那么是它的child[0], 否则child[0]是正式的内容, 所以要判断
    if (func->child[3]->child[0]->nodekind == "LocVarDecl") {
        // ! 局部变量声明, 更新符号表. 这个时候要保存每个变量在栈中的位置
        int ext = genLocVarDecl(func->child[3]->child[0], func->child[1]->name);
        stack_size += ext;
        statement = func->child[3]->child[1];

        // genStmt(func->child[3]->child[1], var2stack);          // 生成statement
    } else if (func->child[3]->child[0] != NULL) {  // 如果没有变量声明
        // // debug("before statement");
        statement = func->child[3]->child[0];
    }
    assout << "\t"
           << "subl"
           << "\t$" << stack_size << ", %esp" << endl;
    map<string, string> var2stack;
    for (auto x : fun2param[func_name]) {
        var2stack[x.first] = x.second;
    }
    for (auto x : fun2var[func_name]) {
        if (var2stack.count(x.first)) {
            cout << "error ! param & loc_var repeat!" << endl;
        } else {
            var2stack[x.first] = x.second;
        }
    }

    // ! 这个是最麻烦的
    genStmt(statement, var2stack);

    // // debug(func->child[3]->child[0]->nodekind);
    // // debug(func->child[3]->child[1]->nodekind);

    assout << "\t"
           << "leave" << endl
           << "\t"
           << "ret" << endl;

    assout << ".LFE" + to_string(LFE_id) + ":" << endl
           << "\t.size\t" + func->child[1]->name << ", .-" << func->child[1]->name
           << endl;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x178, %rsp            # imm = 0x178
movq %rdi, %rbp
movl $0xc0, %ebx
movq 0x8(%rdi), %rsi
addq %rbx, %rsi
leaq 0x88(%rsp), %rdi
callq 0x2250
leaq 0xa4c7(%rip), %rdi      # 0x16be0
leaq 0x3161(%rip), %rsi      # 0xf881
callq 0x21b0
addq 0x8(%rbp), %rbx
movq %rax, %rdi
movq %rbx, %rsi
callq 0x21a0
movq %rax, %rdi
callq 0x20f0
leaq 0x3148(%rip), %rsi      # 0xf88b
movq %rax, %rdi
callq 0x21b0
movl $0xc0, %esi
addq 0x8(%rbp), %rsi
movq %rax, %rdi
callq 0x21a0
leaq 0x3130(%rip), %rsi      # 0xf893
movq %rax, %rdi
callq 0x21b0
movq %rax, %rdi
callq 0x20f0
movl $0xc0, %esi
addq 0x8(%rbp), %rsi
movq %rax, %rdi
callq 0x21a0
leaq 0x318d(%rip), %rsi      # 0xf918
movq %rax, %rdi
callq 0x21b0
movq %rax, %rdi
callq 0x20f0
movq %rax, %rbx
movl 0xa69c(%rip), %esi      # 0x16e40
leaq 0x58(%rsp), %rdi
callq 0x7cbf
leaq 0x30ea(%rip), %rsi      # 0xf89f
leaq 0x18(%rsp), %rdi
leaq 0x58(%rsp), %rdx
callq 0x7c9b
leaq 0x18(%rsp), %rsi
movq %rbx, %rdi
callq 0x21a0
leaq 0x3140(%rip), %rsi      # 0xf918
movq %rax, %rdi
callq 0x21b0
movq %rax, %rdi
callq 0x20f0
leaq 0x2f25(%rip), %rsi      # 0xf714
movq %rax, %rdi
callq 0x21b0
leaq 0x30a6(%rip), %rsi      # 0xf8a4
movq %rax, %rdi
callq 0x21b0
leaq 0x2f07(%rip), %rsi      # 0xf714
movq %rax, %rdi
callq 0x21b0
leaq 0x308e(%rip), %rsi      # 0xf8aa
movq %rax, %rdi
callq 0x21b0
leaq 0x3085(%rip), %rsi      # 0xf8b0
movq %rax, %rdi
callq 0x21b0
movq %rax, %rdi
callq 0x20f0
leaq 0x18(%rsp), %rdi
callq 0x2358
leaq 0x58(%rsp), %rdi
callq 0x2358
movq 0x10(%rbp), %rbx
movl $0xc0, %esi
addq 0x8(%rbp), %rsi
leaq 0x128(%rsp), %rdi
callq 0x2250
leaq 0x128(%rsp), %rsi
movq %rbx, %rdi
callq 0xa56d
leaq 0x128(%rsp), %rdi
callq 0x2358
movq 0x18(%rbp), %rax
movq (%rax), %rdi
addq $0x30, %rdi
leaq 0x299a(%rip), %rsi      # 0xf232
callq 0x368e
movq 0x18(%rbp), %rcx
testb %al, %al
je 0xc8ea
movq (%rcx), %rbx
movl $0xc0, %esi
addq 0x8(%rbp), %rsi
leaq 0x108(%rsp), %rdi
callq 0x2250
leaq 0x108(%rsp), %rsi
movq %rbx, %rdi
callq 0xa6f0
movl %eax, %ebx
leaq 0x108(%rsp), %rdi
callq 0x2358
addl $0x10, %ebx
movq 0x18(%rbp), %rcx
addq $0x8, %rcx
jmp 0xc8ed
pushq $0x10
popq %rbx
movq (%rcx), %r14
leaq 0xa2e9(%rip), %rdi      # 0x16be0
leaq 0x2e16(%rip), %rsi      # 0xf714
callq 0x21b0
leaq 0x2fb7(%rip), %rsi      # 0xf8c1
movq %rax, %rdi
callq 0x21b0
leaq 0x2ebd(%rip), %rsi      # 0xf7d6
movq %rax, %rdi
callq 0x21b0
movq %rax, %rdi
movl %ebx, %esi
callq 0x22f0
leaq 0x2ea7(%rip), %rsi      # 0xf7d9
movq %rax, %rdi
callq 0x21b0
movq %rax, %rdi
callq 0x20f0
movq %r14, 0x10(%rsp)
leaq 0x60(%rsp), %rax
andl $0x0, (%rax)
andq $0x0, 0x8(%rax)
movq %rax, 0x10(%rax)
movq %rax, 0x18(%rax)
andq $0x0, 0x20(%rax)
leaq 0xa478(%rip), %rdi      # 0x16de0
leaq 0x88(%rsp), %rsi
callq 0xce3e
movq %rax, %rbx
movq 0x18(%rax), %r15
addq $0x8, %rbx
leaq 0x38(%rsp), %r14
leaq 0x18(%rsp), %r12
leaq 0x58(%rsp), %r13
cmpq %rbx, %r15
je 0xc9cb
leaq 0x20(%r15), %rsi
movq %r12, %rdi
callq 0xcedc
movq %r13, %rdi
movq %r12, %rsi
callq 0x7c16
movq %rax, %rdi
movq %r14, %rsi
callq 0x2110
movq %r12, %rdi
callq 0x7c00
movq %r15, %rdi
callq 0x2130
movq %rax, %r15
jmp 0xc98f
movq %rbp, 0x8(%rsp)
leaq 0xa439(%rip), %rdi      # 0x16e10
leaq 0x88(%rsp), %rsi
callq 0xce3e
movq %rax, %r15
movq 0x18(%rax), %r13
addq $0x8, %r15
leaq 0x18(%rsp), %rbp
leaq 0x58(%rsp), %r14
movq 0x95c8(%rip), %rbx      # 0x15fc8
leaq 0x2ebf(%rip), %r12      # 0xf8c6
cmpq %r15, %r13
je 0xca6a
leaq 0x20(%r13), %rsi
movq %rbp, %rdi
callq 0xcedc
movq %r14, %rdi
movq %rbp, %rsi
callq 0xcf16
testq %rax, %rax
je 0xca3d
movq %rbx, %rdi
movq %r12, %rsi
callq 0x21b0
movq %rax, %rdi
callq 0x20f0
jmp 0xca55
movq %r14, %rdi
movq %rbp, %rsi
callq 0x7c16
movq %rax, %rdi
leaq 0x38(%rsp), %rsi
callq 0x2110
movq %rbp, %rdi
callq 0x7c00
movq %r13, %rdi
callq 0x2130
movq %rax, %r13
jmp 0xca07
leaq 0x148(%rsp), %rdi
leaq 0x58(%rsp), %rsi
callq 0xd3ce
movq 0x8(%rsp), %r14
leaq 0x148(%rsp), %rsi
movq 0x10(%rsp), %rdi
callq 0xb021
leaq 0x148(%rsp), %rdi
callq 0x7b9c
leaq 0xa139(%rip), %rdi      # 0x16be0
leaq 0x2c66(%rip), %rsi      # 0xf714
callq 0x21b0
leaq 0x2e2c(%rip), %rsi      # 0xf8e6
movq %rax, %rdi
callq 0x21b0
movq %rax, %rdi
callq 0x20f0
leaq 0x2c43(%rip), %rsi      # 0xf714
movq %rax, %rdi
callq 0x21b0
leaq 0x2e0c(%rip), %rsi      # 0xf8ec
movq %rax, %rdi
callq 0x21b0
movq %rax, %rdi
callq 0x20f0
movl 0xa34e(%rip), %esi      # 0x16e44
leaq 0xc8(%rsp), %rdi
callq 0x7cbf
leaq 0x2de6(%rip), %rsi      # 0xf8f0
leaq 0xe8(%rsp), %rdi
leaq 0xc8(%rsp), %rdx
callq 0x7c9b
leaq 0x2df2(%rip), %rdx      # 0xf918
leaq 0x18(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x7c7c
leaq 0xa0a1(%rip), %rdi      # 0x16be0
leaq 0x18(%rsp), %rsi
callq 0x21a0
movq %rax, %rdi
callq 0x20f0
movq %rax, %rbx
movl $0xc0, %edx
addq 0x8(%r14), %rdx
leaq 0x2d91(%rip), %rsi      # 0xf8f5
leaq 0xa8(%rsp), %rdi
callq 0x8177
leaq 0xa8(%rsp), %rsi
movq %rbx, %rdi
callq 0x21a0
leaq 0x2d75(%rip), %rsi      # 0xf8fd
movq %rax, %rdi
callq 0x21b0
movl $0xc0, %esi
addq 0x8(%r14), %rsi
movq %rax, %rdi
callq 0x21a0
movq %rax, %rdi
callq 0x20f0
leaq 0xa8(%rsp), %rdi
callq 0x2358
leaq 0x18(%rsp), %rdi
callq 0x2358
leaq 0xe8(%rsp), %rdi
callq 0x2358
leaq 0xc8(%rsp), %rdi
callq 0x2358
leaq 0x58(%rsp), %rdi
callq 0x7b9c
leaq 0x88(%rsp), %rdi
callq 0x2358
addq $0x178, %rsp            # imm = 0x178
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0x108(%rsp), %rdi
jmp 0xcca9
jmp 0xccb0
jmp 0xcc58
movq %rax, %rbx
jmp 0xcc77
movq %rax, %rbx
jmp 0xcc84
jmp 0xccb7
movq %rax, %rbx
leaq 0x148(%rsp), %rdi
callq 0x7b9c
jmp 0xcccb
jmp 0xccb7
jmp 0xccb7
movq %rax, %rbx
leaq 0x128(%rsp), %rdi
jmp 0xcca9
jmp 0xccb0
movq %rax, %rbx
jmp 0xcca4
jmp 0xccb0
movq %rax, %rbx
jmp 0xcc6d
movq %rax, %rbx
leaq 0xa8(%rsp), %rdi
callq 0x2358
leaq 0x18(%rsp), %rdi
callq 0x2358
leaq 0xe8(%rsp), %rdi
callq 0x2358
leaq 0xc8(%rsp), %rdi
callq 0x2358
jmp 0xcccb
jmp 0xccb0
jmp 0xccb7
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x2358
leaq 0x58(%rsp), %rdi
callq 0x2358
jmp 0xccd5
movq %rax, %rbx
jmp 0xccd5
jmp 0xccb7
movq %rax, %rbx
jmp 0xcccb
jmp 0xccbe
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x7c00
leaq 0x58(%rsp), %rdi
callq 0x7b9c
leaq 0x88(%rsp), %rdi
callq 0x2358
movq %rbx, %rdi
callq 0x2300