// File: /workspace/github_c_makefile_star2_O0/yutopp[P]cc/asm_x86_64.c
// Function: built_from_ir_function
void built_from_ir_function(ASM_X86_64 *a, IRFunction* f) {
    {
        // .text
        ASM_X86_64_Inst* inst = (ASM_X86_64_Inst*)vector_append(a->insts);
        inst->kind = ASM_X86_64_INST_KIND_TEXT;
    }

    // TODO: fix
    {
        // .global
        ASM_X86_64_Inst* inst = (ASM_X86_64_Inst*)vector_append(a->insts);
        inst->kind = ASM_X86_64_INST_KIND_GLOBAL;
        inst->value.global.name = f->name;
    }

    {
        // .type
        ASM_X86_64_Inst* inst = (ASM_X86_64_Inst*)vector_append(a->insts);
        inst->kind = ASM_X86_64_INST_KIND_TYPE;
        inst->value.type.name = f->name;
        inst->value.type.type = "@function";
    }

    {
        // label
        ASM_X86_64_Inst* inst = (ASM_X86_64_Inst*)vector_append(a->insts);
        inst->kind = ASM_X86_64_INST_KIND_LABEL;
        inst->value.label.name = f->name;
        inst->value.label.generated = 0;
    }

    {
        // pushq rbp
        ASM_X86_64_Inst* inst = (ASM_X86_64_Inst*)vector_append(a->insts);
        inst->kind = ASM_X86_64_INST_KIND_OP;
        inst->value.op.op = ASM_X86_64_OP_PUSHQ;
        inst->value.op.args[0].kind = ASM_X86_64_VALUE_KIND_REG;
        inst->value.op.args[0].value.reg = ASM_X86_64_REG_RBP;
    }

    {
        // movq rbp, rsp
        ASM_X86_64_Inst* inst = (ASM_X86_64_Inst*)vector_append(a->insts);
        inst->kind = ASM_X86_64_INST_KIND_OP;
        inst->value.op.op = ASM_X86_64_OP_MOVQ;
        inst->value.op.args[0].kind = ASM_X86_64_VALUE_KIND_REG;
        inst->value.op.args[0].value.reg = ASM_X86_64_REG_RBP;
        inst->value.op.args[1].kind = ASM_X86_64_VALUE_KIND_REG;
        inst->value.op.args[1].value.reg = ASM_X86_64_REG_RSP;
    }

    size_t stack_size = 0;
    for(size_t i=0; i<vector_len(f->locals); ++i) {
        size_t* local = vector_at(f->locals, i);

        asm_x86_64_set_local(a, i, stack_size);
        assert(*local <= 16);
        stack_size += *local;
    }

    if (stack_size != 0) {
        // subq rsp, 'stack_size'
        ASM_X86_64_Inst* inst = (ASM_X86_64_Inst*)vector_append(a->insts);
        inst->kind = ASM_X86_64_INST_KIND_OP;
        inst->value.op.op = ASM_X86_64_OP_SUBQ;
        inst->value.op.args[0].kind = ASM_X86_64_VALUE_KIND_REG;
        inst->value.op.args[0].value.reg = ASM_X86_64_REG_RSP;
        inst->value.op.args[1].kind = ASM_X86_64_VALUE_KIND_IMM_INT;
        inst->value.op.args[1].value.imm_int = stack_size;
    }

    ir_bb_visit(f->entry, built_from_ir_function_bb_collect_labels_iter, a);
    ir_bb_visit(f->entry, built_from_ir_function_bb_built_iter, a);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rdi
callq 0x4480
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movl $0x2, (%rax)
movq -0x8(%rbp), %rax
movq (%rax), %rdi
callq 0x4480
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movl $0x3, (%rax)
movq -0x10(%rbp), %rax
movq (%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x8(%rbp), %rax
movq (%rax), %rdi
callq 0x4480
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movl $0x4, (%rax)
movq -0x10(%rbp), %rax
movq (%rax), %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x28(%rbp), %rax
leaq 0x3fb7(%rip), %rcx      # 0xbd9e
movq %rcx, 0x10(%rax)
movq -0x8(%rbp), %rax
movq (%rax), %rdi
callq 0x4480
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movl $0x5, (%rax)
movq -0x10(%rbp), %rax
movq (%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x30(%rbp), %rax
movl $0x0, 0x10(%rax)
movq -0x8(%rbp), %rax
movq (%rax), %rdi
callq 0x4480
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movl $0x6, (%rax)
movq -0x38(%rbp), %rax
movl $0x0, 0x8(%rax)
movq -0x38(%rbp), %rax
movl $0x3, 0x10(%rax)
movq -0x38(%rbp), %rax
movl $0x5, 0x18(%rax)
movq -0x8(%rbp), %rax
movq (%rax), %rdi
callq 0x4480
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movl $0x6, (%rax)
movq -0x40(%rbp), %rax
movl $0x2, 0x8(%rax)
movq -0x40(%rbp), %rax
movl $0x3, 0x10(%rax)
movq -0x40(%rbp), %rax
movl $0x5, 0x18(%rax)
movq -0x40(%rbp), %rax
movl $0x3, 0x28(%rax)
movq -0x40(%rbp), %rax
movl $0x4, 0x30(%rax)
movq $0x0, -0x48(%rbp)
movq $0x0, -0x50(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x4580
movq %rax, %rcx
movq -0x68(%rbp), %rax
cmpq %rcx, %rax
jae 0x7f4d
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rdi
movq -0x50(%rbp), %rsi
callq 0x4530
movq %rax, -0x58(%rbp)
movq -0x8(%rbp), %rdi
movq -0x50(%rbp), %rsi
movq -0x48(%rbp), %rdx
callq 0x80f0
movq -0x58(%rbp), %rax
cmpq $0x10, (%rax)
ja 0x7f0e
jmp 0x7f2d
leaq 0x3e93(%rip), %rdi      # 0xbda8
leaq 0x3cc9(%rip), %rsi      # 0xbbe5
movl $0x20b, %edx            # imm = 0x20B
leaq 0x3e8d(%rip), %rcx      # 0xbdb5
callq 0x10b0
movq -0x58(%rbp), %rax
movq (%rax), %rax
addq -0x48(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x50(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x50(%rbp)
jmp 0x7ebb
cmpq $0x0, -0x48(%rbp)
je 0x7fa7
movq -0x8(%rbp), %rax
movq (%rax), %rdi
callq 0x4480
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
movl $0x6, (%rax)
movq -0x60(%rbp), %rax
movl $0x5, 0x8(%rax)
movq -0x60(%rbp), %rax
movl $0x3, 0x10(%rax)
movq -0x60(%rbp), %rax
movl $0x4, 0x18(%rax)
movq -0x60(%rbp), %rax
movl $0x1, 0x28(%rax)
movq -0x48(%rbp), %rax
movl %eax, %ecx
movq -0x60(%rbp), %rax
movl %ecx, 0x30(%rax)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x8(%rbp), %rdx
leaq 0x1e6(%rip), %rsi       # 0x81a0
callq 0x92b0
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x8(%rbp), %rdx
leaq 0x1fe(%rip), %rsi       # 0x81d0
callq 0x92b0
addq $0x70, %rsp
popq %rbp
retq
nopl (%rax)