// File: /workspace/github_cpp_makefile_star2_O2/luooofan[P]hblzbd_compiler/src/generate_ir.cpp
// Function: ast::FunctionDefine::GenerateIR(ir::ContextInfo&, std::vector<ir::IR*, std::allocator<ir::IR*>>&)
void FunctionDefine::GenerateIR(ir::ContextInfo &ctx, std::vector<ir::IR *> &gIRList) {
#ifdef GENIR_TIME_CONTROL
  clock_t begin, end;
  double cost;
  begin = clock();
#endif
  // NOTE: 函数无法嵌套定义
  if (ctx.scope_id_ != 0) {
    ir::SemanticError(this->line_no_, "function nest define.");
    return;
  }
  const auto &func_iter = ir::gFuncTable.find(this->name_.name_);
  if (func_iter == ir::gFuncTable.end()) {
    ctx.current_func_name_ = this->name_.name_;
    ctx.scope_id_ = ir::gScopes.size();
    gIRList.push_back(new ir::IR(IROpKind::LABEL, FUNC_OPN(this->name_.name_)));
    // 父作用域id一定为0 函数初始栈偏移为0
    ir::gScopes.push_back({ctx.scope_id_, 0});
    auto tmp = new ir::FuncTableItem(return_type_, ctx.scope_id_);
    ctx.has_aug_scope = true;
    for (int i = 0; i < args_.arg_list_.size(); ++i) {
      // for (const auto &arg : args_.arg_list_) {
      const auto &arg = args_.arg_list_[i];
      auto &scope = ir::gScopes[ctx.scope_id_];
      auto &symbol_table = scope.symbol_table_;
      if (Identifier *ident = dynamic_cast<Identifier *>(&arg->name_)) {
        const auto &var_iter = symbol_table.find(ident->name_);
        if (var_iter == symbol_table.end()) {
          auto &&symbol_item = ir::SymbolTableItem(false, false);
          symbol_table.insert({ident->name_, symbol_item});
          // ADD DECLARE
          gIRList.push_back(new ir::IR{IROpKind::DECLARE, ir::Opn(OpnType::Var, ident->name_, ctx.scope_id_),
                                       ir::Opn(OpnType::Imm, i)});
        } else {
          ir::SemanticError(this->line_no_, ident->name_ + ": variable redefined");
        }
        tmp->shape_list_.push_back(std::vector<int>());
      } else if (ArrayIdentifier *arrident = dynamic_cast<ArrayIdentifier *>(&arg->name_)) {
        const auto &var_iter = symbol_table.find(arrident->name_.name_);
        if (var_iter == symbol_table.end()) {
          auto tmp1 = new ir::SymbolTableItem(true, false);
          // NOTE: 参数中的数组视为一个基址指针
          // ADD DECLARE
          gIRList.push_back(
              new ir::IR{IROpKind::DECLARE,
                         ir::Opn(OpnType::Array, arrident->name_.name_, ctx.scope_id_, new ir::Opn(OpnType::Imm, 0)),
                         ir::Opn(OpnType::Imm, i)});

          // 计算shape和width shape:-1 2 3  width:? 24 12 4
          tmp1->shape_.push_back(-1);  //第一维因为文法规定必须留空，这里记-1
          for (const auto &shape : arrident->shape_list_) {
            shape->Evaluate(ctx, gIRList);
            tmp1->shape_.push_back(ctx.opn_.imm_num_);
          }
          tmp1->width_.resize(tmp1->shape_.size() + 1);
          tmp1->width_[tmp1->width_.size() - 1] = ir::kIntWidth;
          for (int i = tmp1->width_.size() - 2; i > 0; i--) tmp1->width_[i] = tmp1->width_[i + 1] * tmp1->shape_[i];
          tmp1->width_[0] = -1;  // useless
          symbol_table.insert({arrident->name_.name_, *tmp1});
          tmp->shape_list_.push_back(tmp1->shape_);
          delete tmp1;
        } else {
          ir::SemanticError(this->line_no_, arrident->name_.name_ + ": variable redefined");
        }
      }
      // std::cout<<"haha"<<ctx.shape_.size()<<'\n';
      // tmp->shape_list_.push_back(ctx.shape_);
    }
    ir::gFuncTable.insert({name_.name_, *tmp});
    delete tmp;

    ctx.has_return = false;
    this->body_.GenerateIR(ctx, gIRList);

    if (return_type_ == INT && ctx.has_return == false) {
      ir::SemanticError(this->line_no_,
                        this->name_.name_ + ": function's return type is INT,but does not return anything");
    }
    // 保证函数执行流最后会有一条ret语句 方便汇编生成
    if (return_type_ == VOID /*&& ctx.has_return == false*/) {
      gIRList.push_back(new ir::IR(IROpKind::RET));
    }

    // Set current_scope_id
    ctx.scope_id_ = 0;
  } else {
    ir::SemanticError(this->line_no_, this->name_.name_ + ": function redefined");
  }
#ifdef GENIR_TIME_CONTROL
  end = clock();
  cost = (double)(end - begin) / CLOCKS_PER_SEC;
  std::cout << "GenIrFunction cost: " << cost << "s" << std::endl;
  if (cost > 3) exit(233);
#endif
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2b8, %rsp            # imm = 0x2B8
movq %rdi, %r12
cmpl $0x0, (%rsi)
je 0x12f63
movl 0x8(%r12), %ebx
leaq 0x43c45(%rip), %rsi     # 0x56b88
leaq 0x40(%rsp), %rdi
leaq 0x1e8(%rsp), %rdx
callq 0xa292
leaq 0x40(%rsp), %rsi
movl %ebx, %edi
callq 0x1f699
jmp 0x12faf
movq %rdx, %r15
movq %rsi, %rbx
movq 0x10(%r12), %rax
movq 0x10(%rax), %rsi
leaq 0x6e5e7(%rip), %rdi     # 0x81560
callq 0xe8da
testq %rax, %rax
je 0x12fcb
movl 0x8(%r12), %ebx
movq 0x10(%r12), %rax
movq 0x10(%rax), %rsi
leaq 0x43c43(%rip), %rdx     # 0x56bdb
leaq 0x40(%rsp), %r14
movq %r14, %rdi
callq 0xa334
movl %ebx, %edi
movq %r14, %rsi
callq 0x1f699
leaq 0x40(%rsp), %rdi
callq 0x8578
addq $0x2b8, %rsp            # imm = 0x2B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x10(%r12), %rax
movq 0x10(%rax), %rsi
leaq 0x1e8(%rbx), %rdi
callq 0x81a0
leaq 0x6e561(%rip), %rax     # 0x81548
movq 0x8(%rax), %rcx
subq (%rax), %rcx
shrq $0x6, %rcx
movl %ecx, (%rbx)
movl $0xe0, %edi
callq 0x8250
movq %rax, %r14
movq 0x10(%r12), %rax
movq 0x10(%rax), %rsi
leaq 0xe8(%rsp), %rdi
callq 0x8390
movq %r12, (%rsp)
leaq 0x1a8(%rsp), %rdi
pushq $0x3
popq %rsi
leaq 0xe8(%rsp), %rdx
callq 0x1ac46
movb $0x1, %bpl
pushq $0x7
popq %rsi
leaq 0x1a8(%rsp), %rdx
movq %r14, %rdi
callq 0x1abbe
leaq 0x40(%rsp), %rsi
movq %r14, (%rsi)
xorl %ebp, %ebp
movq %r15, %rdi
callq 0xe358
movq %r15, 0x8(%rsp)
leaq 0x1b0(%rsp), %rdi
callq 0x8578
leaq 0xe8(%rsp), %rdi
callq 0x8578
movl (%rbx), %eax
leaq 0x70(%rsp), %rcx
movq %rcx, -0x30(%rcx)
movq $0x1, -0x28(%rcx)
xorps %xmm0, %xmm0
movups %xmm0, -0x20(%rcx)
movl $0x3f800000, -0x10(%rcx) # imm = 0x3F800000
movups %xmm0, -0x8(%rcx)
movl %eax, 0x8(%rcx)
andl $0x0, 0xc(%rcx)
leaq 0x6e49b(%rip), %rdi     # 0x81548
leaq 0x40(%rsp), %rsi
callq 0x1bc58
leaq 0x40(%rsp), %rdi
callq 0x1b358
pushq $0x20
popq %rdi
callq 0x8250
movq (%rsp), %rbp
movl 0xc(%rbp), %edx
movl (%rbx), %ecx
movl %edx, (%rax)
movl %ecx, 0x4(%rax)
leaq 0x8(%rax), %rcx
movq %rcx, 0x20(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rax)
movq %rax, 0xb8(%rsp)
andq $0x0, 0x18(%rax)
movb $0x1, 0x208(%rbx)
leaq 0xc(%rbx), %rax
movq %rax, 0xc0(%rsp)
leaq 0x44032(%rip), %rax     # 0x57140
movl (%rax), %eax
movl %eax, 0x34(%rsp)
xorl %r13d, %r13d
leaq 0x6cd4a(%rip), %r15     # 0x7fe68
movq 0x18(%rbp), %rcx
movq 0x10(%rcx), %rax
movq 0x18(%rcx), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %r13, %rcx
jbe 0x13586
movq (%rax,%r13,8), %rax
movq 0x10(%rax), %r14
testq %r14, %r14
je 0x1337b
movq %r13, 0x28(%rsp)
movq %rbx, %r13
movslq (%rbx), %r12
shlq $0x6, %r12
leaq 0x6e3e7(%rip), %rax     # 0x81548
addq (%rax), %r12
movq %r14, %rdi
movq %r15, %rsi
leaq 0x6c9f7(%rip), %rdx     # 0x7fb68
xorl %ecx, %ecx
callq 0x82c0
testq %rax, %rax
je 0x131da
movq %rax, %rbx
movq 0x10(%rax), %rsi
movq %r12, %rdi
callq 0xf75e
testq %rax, %rax
je 0x13255
movl 0x8(%rbp), %ebp
movq 0x10(%rbx), %rsi
leaq 0x40(%rsp), %r14
movq %r14, %rdi
leaq 0x439c8(%rip), %rdx     # 0x56b73
callq 0xa334
movl %ebp, %edi
movq %r14, %rsi
callq 0x1f699
movq %r14, %rdi
callq 0x8578
movq (%rsp), %rbp
leaq 0x6cc9b(%rip), %r15     # 0x7fe68
movq %r13, %rbx
movq 0x28(%rsp), %r13
jmp 0x13358
movq %r14, %rdi
movq %r15, %rsi
leaq 0x6c999(%rip), %rdx     # 0x7fb80
xorl %ecx, %ecx
callq 0x82c0
testq %rax, %rax
movq %r13, %rbx
movq 0x28(%rsp), %r13
je 0x1337b
movq %rax, %r14
movq 0x10(%rax), %rax
movq 0x10(%rax), %rsi
movq %r12, %rdi
callq 0xf75e
testq %rax, %rax
je 0x13383
movl 0x8(%rbp), %ebp
movq 0x10(%r14), %rax
movq 0x10(%rax), %rsi
leaq 0x40(%rsp), %r14
movq %r14, %rdi
leaq 0x4393e(%rip), %rdx     # 0x56b73
callq 0xa334
movl %ebp, %edi
movq %r14, %rsi
callq 0x1f699
movq %r14, %rdi
callq 0x8578
movq (%rsp), %rbp
jmp 0x1337b
leaq 0x1e8(%rsp), %r15
movq %r15, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x1a960
movq 0x10(%rbx), %rsi
leaq 0x40(%rsp), %r14
movq %r14, %rdi
movq %r15, %rdx
callq 0x1ac9a
movq %r12, %rdi
movq %r14, %rsi
callq 0x1c154
leaq 0x108(%rsp), %r15
leaq 0x278(%rsp), %r12
movq %r14, %rdi
callq 0x1aa18
movl $0xe0, %edi
callq 0x8250
movq %rax, %r14
movq 0x10(%rbx), %rsi
movq %r15, %rdi
callq 0x8390
movq %r13, %rbx
movl (%r13), %ecx
leaq 0x168(%rsp), %rdi
xorl %esi, %esi
movq %r15, %rdx
callq 0x1a8d4
leaq 0x6cb8f(%rip), %r15     # 0x7fe68
movq %r12, %rdi
pushq $0x1
popq %rsi
movq 0x28(%rsp), %r13
movl %r13d, %edx
callq 0xf6ba
movb $0x1, %bpl
movq %r14, %rdi
pushq $0x17
popq %rsi
leaq 0x168(%rsp), %rdx
movq %r12, %rcx
callq 0x1aa52
movq %r14, 0x40(%rsp)
xorl %ebp, %ebp
movq 0x8(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0xe358
leaq 0x280(%rsp), %rdi
callq 0x8578
leaq 0x170(%rsp), %rdi
callq 0x8578
leaq 0x108(%rsp), %rdi
callq 0x8578
leaq 0x1e8(%rsp), %rdi
callq 0x1aa2e
movq (%rsp), %rbp
leaq 0x40(%rsp), %r14
xorps %xmm0, %xmm0
movaps %xmm0, 0x40(%rsp)
andq $0x0, 0x50(%rsp)
movq 0x20(%rsp), %rdi
movq %r14, %rsi
callq 0x1ba18
movq %r14, %rdi
callq 0x1b2b6
incq %r13
jmp 0x1311e
movq %r14, 0x18(%rsp)
pushq $0x50
popq %rdi
callq 0x8250
movq %rax, %r14
movq %rax, %rdi
pushq $0x1
popq %rsi
xorl %edx, %edx
callq 0x1a960
movq %r14, 0x10(%rsp)
movl $0xe0, %edi
callq 0x8250
movq %rax, 0x38(%rsp)
movq 0x18(%rsp), %rax
movq 0x10(%rax), %rax
movq 0x10(%rax), %rsi
leaq 0xc8(%rsp), %rdi
callq 0x8390
leaq 0x238(%rsp), %r14
movl (%rbx), %ebp
pushq $0x40
popq %rdi
callq 0x8250
movq %rax, %r15
movq %rax, %rdi
pushq $0x1
popq %rsi
xorl %edx, %edx
callq 0xf6ba
leaq 0x128(%rsp), %rdi
pushq $0x5
popq %rsi
leaq 0xc8(%rsp), %rdx
movl %ebp, %ecx
movq %r15, %r8
callq 0x1a934
movq %r14, %rdi
pushq $0x1
popq %rsi
movl %r13d, %edx
callq 0xf6ba
movb $0x1, %bpl
movq 0x38(%rsp), %r15
movq %r15, %rdi
pushq $0x17
popq %rsi
leaq 0x128(%rsp), %rdx
movq %r14, %rcx
callq 0x1aa52
leaq 0x40(%rsp), %r14
movq %r15, 0x40(%rsp)
xorl %ebp, %ebp
movq 0x8(%rsp), %rdi
movq %r14, %rsi
callq 0xe358
leaq 0x240(%rsp), %rdi
callq 0x8578
leaq 0x130(%rsp), %rdi
callq 0x8578
leaq 0xc8(%rsp), %rdi
callq 0x8578
movq 0x10(%rsp), %rax
leaq 0x8(%rax), %r15
orl $-0x1, 0x40(%rsp)
movq %r15, %rdi
movq %r14, %rsi
callq 0x1c9ca
movq 0x18(%rsp), %rax
movq 0x18(%rax), %rbp
movq 0x20(%rax), %r14
cmpq %r14, %rbp
je 0x134cc
movq (%rbp), %rdi
movq (%rdi), %rax
movq %rbx, %rsi
movq 0x8(%rsp), %rdx
callq *0x18(%rax)
movq %r15, %rdi
movq 0xc0(%rsp), %rsi
callq 0xf720
addq $0x10, %rbp
jmp 0x1349f
movq 0x10(%rsp), %r14
movq %r14, %rdi
addq $0x20, %rdi
movq 0x10(%r14), %rsi
subq 0x8(%r14), %rsi
sarq $0x2, %rsi
incq %rsi
callq 0x1acf6
movq 0x20(%r14), %rax
movq 0x28(%r14), %rcx
movl 0x34(%rsp), %edx
movl %edx, -0x4(%rcx)
subq %rax, %rcx
shrq $0x2, %rcx
addl $-0x2, %ecx
movq (%rsp), %rbp
movq 0x18(%rsp), %rsi
testl %ecx, %ecx
jle 0x13525
movq (%r15), %rdx
movl (%rdx,%rcx,4), %edx
imull 0x4(%rax,%rcx,4), %edx
movl %edx, (%rax,%rcx,4)
decq %rcx
jmp 0x1350e
orl $-0x1, (%rax)
movq 0x10(%rsi), %rax
movq 0x10(%rax), %rsi
leaq 0x40(%rsp), %rdi
movq 0x10(%rsp), %r14
movq %r14, %rdx
callq 0x1ac9a
movq %r12, %rdi
leaq 0x40(%rsp), %r12
movq %r12, %rsi
callq 0x1c154
movq %r12, %rdi
callq 0x1aa18
movq 0x20(%rsp), %rdi
movq %r15, %rsi
callq 0x1ad44
movq %r14, %rdi
callq 0x1aa2e
movq %r14, %rdi
pushq $0x50
popq %rsi
callq 0x8260
leaq 0x6c8e7(%rip), %r15     # 0x7fe68
jmp 0x1337b
movq 0x10(%rbp), %rax
movq 0x10(%rax), %rsi
leaq 0x40(%rsp), %r14
movq %r14, %rdi
movq 0xb8(%rsp), %r15
movq %r15, %rdx
callq 0x1ad70
leaq 0x6dfb3(%rip), %rdi     # 0x81560
movq %r14, %rsi
callq 0x1b65c
leaq 0x40(%rsp), %rdi
callq 0x1a656
movq 0x20(%rsp), %rdi
callq 0x1b336
pushq $0x20
popq %rsi
movq %r15, %rdi
callq 0x8260
movb $0x0, 0x48(%rbx)
movq 0x20(%rbp), %rdi
movq (%rdi), %rax
movq %rbx, %rsi
movq 0x8(%rsp), %r15
movq %r15, %rdx
callq *0x10(%rax)
movl 0xc(%rbp), %eax
cmpl $0x121, %eax            # imm = 0x121
jne 0x13639
cmpb $0x0, 0x48(%rbx)
jne 0x13639
movq %rbp, %r12
movl 0x8(%rbp), %ebp
movq 0x10(%r12), %rax
movq 0x10(%rax), %rsi
leaq 0x4358b(%rip), %rdx     # 0x56b9e
leaq 0x40(%rsp), %r14
movq %r14, %rdi
callq 0xa334
movl %ebp, %edi
movq %r14, %rsi
callq 0x1f699
leaq 0x40(%rsp), %rdi
callq 0x8578
movl 0xc(%r12), %eax
cmpl $0x122, %eax            # imm = 0x122
jne 0x13668
movl $0xe0, %edi
callq 0x8250
movq %rax, %r14
pushq $0xa
popq %rsi
movq %rax, %rdi
callq 0x1ada6
leaq 0x40(%rsp), %rsi
movq %r14, (%rsi)
movq %r15, %rdi
callq 0xe358
andl $0x0, (%rbx)
jmp 0x12fb9
jmp 0x136a3
jmp 0x137a0
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x1a656
jmp 0x13807
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x1b358
jmp 0x13807
movq %rax, %rbx
movb $0x1, %bpl
jmp 0x136f7
movq %rax, %rbx
jmp 0x1370d
jmp 0x137a0
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x1aa18
jmp 0x13807
movq %rax, %rbx
jmp 0x13757
movq %rax, %rbx
movb $0x1, %bpl
jmp 0x1372c
movq %rax, %rbx
pushq $0x40
popq %rsi
movq %r15, %rdi
callq 0x8260
jmp 0x1373e
movq %rax, %rbx
pushq $0x50
popq %rsi
jmp 0x13712
movq %rax, %rbx
leaq 0x1b0(%rsp), %rdi
callq 0x8578
leaq 0xe8(%rsp), %rdi
callq 0x8578
testb %bpl, %bpl
je 0x13807
movl $0xe0, %esi
movq %r14, %rdi
jmp 0x13761
jmp 0x137a0
movq %rax, %rbx
leaq 0x240(%rsp), %rdi
callq 0x8578
leaq 0x130(%rsp), %rdi
callq 0x8578
jmp 0x13741
movq %rax, %rbx
movb $0x1, %bpl
leaq 0xc8(%rsp), %rdi
callq 0x8578
testb %bpl, %bpl
je 0x13807
movl $0xe0, %esi
movq 0x38(%rsp), %rdi
callq 0x8260
jmp 0x13807
jmp 0x137a0
movq %rax, %rbx
jmp 0x13807
movq %rax, %rbx
movb $0x1, %bpl
jmp 0x137cc
movq %rax, %rbx
jmp 0x137de
movq %rax, %rbx
movb $0x1, %bpl
jmp 0x137bf
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x1aa18
jmp 0x137eb
jmp 0x1379b
movq %rax, %rbx
jmp 0x137eb
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x8578
jmp 0x13807
movq %rax, %rbx
leaq 0x280(%rsp), %rdi
callq 0x8578
leaq 0x170(%rsp), %rdi
callq 0x8578
leaq 0x108(%rsp), %rdi
callq 0x8578
testb %bpl, %bpl
je 0x137eb
movl $0xe0, %esi
movq %r14, %rdi
callq 0x8260
leaq 0x1e8(%rsp), %rdi
callq 0x1aa2e
jmp 0x13807
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x1b2b6
movq %rbx, %rdi
callq 0x84d0
nop