// File: /workspace/github_cpp_makefile_star2_O2/luooofan[P]hblzbd_compiler/src/construct_ir_module.cpp
// Function: ConstructModule(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::vector<ir::IR*, std::allocator<ir::IR*>>&)
IRModule* ConstructModule(const std::string& module_name, std::vector<ir::IR*>& gIRList) {
  // Construct BasicBlocks Functions and Module from gIRList

  // 基本块的首指令
  //  由于IR中使用了label 所有跳转语句都跳到某个label
  //  并且每个出现在四元式中的label都有跳转到该label的指令(不一定)
  //  所以首指令为每个label和每个跳转语句(call,ret,goto,jxx)的下一句
  //  (即便不一定为真正的首指令也可以接受)

  // 先遍历一遍IR 把所有func和有label的BB创建完成 创建两个map
  std::unordered_map<std::string, IRBasicBlock*> label2bb;
  std::unordered_map<std::string, IRFunction*> label2func;

  // add library function to label2func
  // not add them to module
  label2func.insert({"getint", new IRFunction("getint", 0)});
  label2func.insert({"getch", new IRFunction("getch", 0)});
  label2func.insert({"getarray", new IRFunction("getarray", 0)});
  label2func.insert({"putint", new IRFunction("putint", 1)});
  label2func.insert({"putch", new IRFunction("putch", 1)});
  label2func.insert({"putarray", new IRFunction("putarray", 1)});
  label2func.insert({"_sysy_starttime", new IRFunction("_sysy_starttime", 1)});
  label2func.insert({"_sysy_stoptime", new IRFunction("_sysy_stoptime", 1)});
  label2func.insert({"memset", new IRFunction("memset", 3)});

  IRModule* module = new IRModule(module_name, gScopes[0]);

  // fill label2bb label2func. every bb has its first ir. every func has it first bb. module has all funs.
  for (int i = 0; i < gIRList.size(); ++i) {
    auto& ir = *gIRList[i];
    if (ir.op_ == IR::OpKind::LABEL) {
      auto& label_name = ir.opn1_.name_;
      IRBasicBlock* bb = new IRBasicBlock();
      bb->ir_list_.push_back(&ir);
      label2bb.insert({label_name, bb});
      if (ir.opn1_.type_ == Opn::Type::Func) {  // is a function begin
        auto& func_item = (*ir::gFuncTable.find(label_name)).second;
        IRFunction* func = new IRFunction(label_name, func_item.shape_list_.size());
        func->bb_list_.push_back(bb);
        bb->func_ = func;
        label2func.insert({label_name, func});
        module->func_list_.push_back(func);
      }
    }
  }

  bool is_leader = false;
  bool is_succ = true;
  IRFunction* curr_func = nullptr;
  IRBasicBlock* pre_bb = nullptr;
  IRBasicBlock* curr_bb = nullptr;
  // for every ir
  for (int i = 0; i < gIRList.size(); ++i) {
    auto& ir = *gIRList[i];
    if (ir.op_ == IR::OpKind::LABEL) {
      is_leader = true;  // 表示这条一定是首指令
    }
    if (is_leader) {  // 一定已经或者将要把该ir放入到基本块中
      pre_bb = curr_bb;
      // 更新curr_bb curr_func
      if (ir.op_ == IR::OpKind::LABEL) {
        curr_bb = label2bb[ir.opn1_.name_];
        if (ir.opn1_.type_ == Opn::Type::Func) {
          curr_func = label2func[ir.opn1_.name_];
          is_leader = false;  // 下一条语句非首指令
          continue;
        }
      } else {
        // new BB
        curr_bb = new IRBasicBlock();
        curr_bb->ir_list_.push_back(&ir);
      }
      curr_func->bb_list_.push_back(curr_bb);
      curr_bb->func_ = curr_func;
      // 维护两个基本块之间的关系
      if (nullptr != pre_bb && is_succ) {
        pre_bb->succ_.push_back(curr_bb);
        curr_bb->pred_.push_back(pre_bb);
      }
    } else {
      curr_bb->ir_list_.push_back(&ir);
    }
    is_succ = true;
    // 维护当前基本块和跳转目标基本块之间的关系 维护is_leader 之后is_leader表示下一条ir是否为首指令
    switch (ir.op_) {
      case IR::OpKind::RET:
        is_leader = true;
        is_succ = false;
        break;
      case IR::OpKind::CALL:  // NOTE: 此时不维护调用双方两个基本块之间的关系 TODO: call语句的下一条语句是首指令吗
        curr_func->call_func_list_.push_back(label2func[ir.opn1_.name_]);
        is_leader = false;
        break;
      case IR::OpKind::GOTO: {
        auto succ_bb = label2bb[ir.opn1_.name_];
        curr_bb->succ_.push_back(succ_bb);
        succ_bb->pred_.push_back(curr_bb);
        is_leader = true;
        is_succ = false;
        break;
      }
      case IR::OpKind::JEQ:
      case IR::OpKind::JNE:
      case IR::OpKind::JLT:
      case IR::OpKind::JLE:
      case IR::OpKind::JGT:
      case IR::OpKind::JGE: {
        auto succ_bb = label2bb[ir.res_.name_];
        curr_bb->succ_.push_back(succ_bb);
        succ_bb->pred_.push_back(curr_bb);
        is_leader = true;
        break;
      }
      default:
        is_leader = false;
        break;
    }
  }

  return module;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xd8, %rsp
movq %rsi, %rbx
movq %rdi, %r14
leaq 0xd0(%rsp), %rax
movq %rax, -0x30(%rax)
pushq $0x1
popq %rcx
movq %rcx, -0x28(%rax)
xorps %xmm0, %xmm0
movups %xmm0, -0x20(%rax)
movl $0x3f800000, %edx       # imm = 0x3F800000
movl %edx, -0x10(%rax)
movups %xmm0, -0x8(%rax)
leaq 0x88(%rsp), %rax
movq %rax, -0x30(%rax)
movq %rcx, -0x28(%rax)
movups %xmm0, -0x20(%rax)
movl %edx, -0x10(%rax)
movups %xmm0, -0x8(%rax)
movl $0x98, %edi
callq 0x8250
movq %rax, %r15
leaq 0x49724(%rip), %rsi     # 0x568b8
leaq 0x10(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0xa292
movb $0x1, %bpl
leaq 0x10(%rsp), %rsi
movq %r15, %rdi
xorl %edx, %edx
callq 0xda28
leaq 0x8(%rsp), %rdx
movq %r15, (%rdx)
xorl %ebp, %ebp
leaq 0x496f2(%rip), %rsi     # 0x568b8
leaq 0x30(%rsp), %rdi
callq 0xda92
leaq 0x58(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0xdf16
leaq 0x30(%rsp), %rdi
callq 0x8578
leaq 0x10(%rsp), %rdi
callq 0x8578
movl $0x98, %edi
callq 0x8250
movq %rax, %r15
leaq 0x496b8(%rip), %rsi     # 0x568bf
leaq 0x10(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0xa292
movb $0x1, %bpl
leaq 0x10(%rsp), %rsi
movq %r15, %rdi
xorl %edx, %edx
callq 0xda28
leaq 0x8(%rsp), %rdx
movq %r15, (%rdx)
xorl %ebp, %ebp
leaq 0x49686(%rip), %rsi     # 0x568bf
leaq 0x30(%rsp), %rdi
callq 0xdab6
leaq 0x58(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0xdf16
leaq 0x30(%rsp), %rdi
callq 0x8578
leaq 0x10(%rsp), %rdi
callq 0x8578
movl $0x98, %edi
callq 0x8250
movq %rax, %r15
leaq 0x4964b(%rip), %rsi     # 0x568c5
leaq 0x10(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0xa292
movb $0x1, %bpl
leaq 0x10(%rsp), %rsi
movq %r15, %rdi
xorl %edx, %edx
callq 0xda28
leaq 0x8(%rsp), %rdx
movq %r15, (%rdx)
xorl %ebp, %ebp
leaq 0x49619(%rip), %rsi     # 0x568c5
leaq 0x30(%rsp), %rdi
callq 0xdada
leaq 0x58(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0xdf16
leaq 0x30(%rsp), %rdi
callq 0x8578
leaq 0x10(%rsp), %rdi
callq 0x8578
movl $0x98, %edi
callq 0x8250
movq %rax, %r15
leaq 0x495e1(%rip), %rsi     # 0x568ce
leaq 0x10(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0xa292
movb $0x1, %bpl
leaq 0x10(%rsp), %rsi
pushq $0x1
popq %rdx
movq %r15, %rdi
callq 0xda28
leaq 0x8(%rsp), %rdx
movq %r15, (%rdx)
xorl %ebp, %ebp
leaq 0x495ae(%rip), %rsi     # 0x568ce
leaq 0x30(%rsp), %rdi
callq 0xda92
leaq 0x58(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0xdf16
leaq 0x30(%rsp), %rdi
callq 0x8578
leaq 0x10(%rsp), %rdi
callq 0x8578
movl $0x98, %edi
callq 0x8250
movq %rax, %r15
leaq 0x49574(%rip), %rsi     # 0x568d5
leaq 0x10(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0xa292
movb $0x1, %bpl
leaq 0x10(%rsp), %rsi
pushq $0x1
popq %rdx
movq %r15, %rdi
callq 0xda28
leaq 0x8(%rsp), %rdx
movq %r15, (%rdx)
xorl %ebp, %ebp
leaq 0x49541(%rip), %rsi     # 0x568d5
leaq 0x30(%rsp), %rdi
callq 0xdab6
leaq 0x58(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0xdf16
leaq 0x30(%rsp), %rdi
callq 0x8578
leaq 0x10(%rsp), %rdi
callq 0x8578
movl $0x98, %edi
callq 0x8250
movq %rax, %r15
leaq 0x49506(%rip), %rsi     # 0x568db
leaq 0x10(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0xa292
movb $0x1, %bpl
leaq 0x10(%rsp), %rsi
pushq $0x1
popq %rdx
movq %r15, %rdi
callq 0xda28
leaq 0x8(%rsp), %rdx
movq %r15, (%rdx)
xorl %ebp, %ebp
leaq 0x494d3(%rip), %rsi     # 0x568db
leaq 0x30(%rsp), %rdi
callq 0xdada
leaq 0x58(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0xdf16
leaq 0x30(%rsp), %rdi
callq 0x8578
leaq 0x10(%rsp), %rdi
callq 0x8578
movl $0x98, %edi
callq 0x8250
movq %rax, %r15
leaq 0x4949b(%rip), %rsi     # 0x568e4
leaq 0x10(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0xa292
movb $0x1, %bpl
leaq 0x10(%rsp), %rsi
pushq $0x1
popq %rdx
movq %r15, %rdi
callq 0xda28
leaq 0x8(%rsp), %rdx
movq %r15, (%rdx)
xorl %ebp, %ebp
leaq 0x49468(%rip), %rsi     # 0x568e4
leaq 0x30(%rsp), %rdi
callq 0xdafe
leaq 0x58(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0xdf16
leaq 0x30(%rsp), %rdi
callq 0x8578
leaq 0x10(%rsp), %rdi
callq 0x8578
movl $0x98, %edi
callq 0x8250
movq %rax, %r15
leaq 0x49437(%rip), %rsi     # 0x568f4
leaq 0x10(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0xa292
movb $0x1, %bpl
leaq 0x10(%rsp), %rsi
pushq $0x1
popq %rdx
movq %r15, %rdi
callq 0xda28
leaq 0x8(%rsp), %rdx
movq %r15, (%rdx)
xorl %ebp, %ebp
leaq 0x49404(%rip), %rsi     # 0x568f4
leaq 0x30(%rsp), %rdi
callq 0xdb22
leaq 0x58(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0xdf16
leaq 0x30(%rsp), %rdi
callq 0x8578
leaq 0x10(%rsp), %rdi
callq 0x8578
movl $0x98, %edi
callq 0x8250
movq %rax, %r15
leaq 0x493d2(%rip), %rsi     # 0x56903
leaq 0x10(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0xa292
movb $0x1, %bpl
leaq 0x10(%rsp), %rsi
pushq $0x3
popq %rdx
movq %r15, %rdi
callq 0xda28
leaq 0x8(%rsp), %rdx
movq %r15, (%rdx)
xorl %ebp, %ebp
leaq 0x4939f(%rip), %rsi     # 0x56903
leaq 0x30(%rsp), %rdi
callq 0xda92
leaq 0x58(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0xdf16
leaq 0x30(%rsp), %rdi
callq 0x8578
leaq 0x10(%rsp), %rdi
callq 0x8578
pushq $0x48
popq %rdi
callq 0x8250
movq %rax, %r15
leaq 0x73fa5(%rip), %rax     # 0x81548
movq (%rax), %rdx
movq %r15, %rdi
movq %r14, %rsi
callq 0xdb46
movq %r15, 0x90(%rsp)
addq $0x28, %r15
movq %r15, 0x98(%rsp)
xorl %r14d, %r14d
leaq 0x30(%rsp), %r15
movq (%rbx), %rax
movq 0x8(%rbx), %rcx
movq %rcx, %rdx
subq %rax, %rdx
sarq $0x3, %rdx
cmpq %r14, %rdx
jbe 0xd704
movq (%rax,%r14,8), %rbp
cmpl $0x7, (%rbp)
jne 0xd6fc
movl $0x2a8, %edi            # imm = 0x2A8
callq 0x8250
movq %rax, %r12
movq %rax, %rdi
callq 0xdb7c
movq %r12, 0x10(%rsp)
addq $0x8, %r12
movq %rbp, 0x30(%rsp)
movq %r12, %rdi
movq %r15, %rsi
callq 0xe358
leaq 0x10(%rbp), %r13
movq %r15, %rdi
movq %r13, %rsi
callq 0x8390
movq 0x10(%rsp), %rax
movq %rax, 0x50(%rsp)
leaq 0xa0(%rsp), %rdi
movq %r15, %rsi
callq 0xe4ea
movq %r15, %rdi
callq 0x8578
cmpl $0x3, 0x8(%rbp)
jne 0xd6fc
leaq 0x73efb(%rip), %rdi     # 0x81560
movq %r13, %rsi
callq 0xe8da
movq %rax, %r12
movl $0x98, %edi
callq 0x8250
movq %rax, %rbp
movq 0x38(%r12), %rax
subq 0x30(%r12), %rax
cqto
pushq $0x18
popq %rcx
idivq %rcx
movq %rbp, %rdi
movq %r13, %rsi
movl %eax, %edx
callq 0xda28
movq %rbp, 0x8(%rsp)
addq $0x30, %rbp
movq %rbp, %rdi
leaq 0x10(%rsp), %rsi
callq 0xdd4a
movq 0x8(%rsp), %rax
movq 0x10(%rsp), %rcx
movq %rax, 0x20(%rcx)
movq %r15, %rdi
movq %r13, %rsi
callq 0x8390
movq 0x8(%rsp), %rax
movq %rax, 0x50(%rsp)
leaq 0x58(%rsp), %rdi
movq %r15, %rsi
callq 0xdf16
movq %r15, %rdi
callq 0x8578
movq 0x98(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0xdd68
incq %r14
jmp 0xd5cd
leaq 0x30(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x10(%rsp), %rdx
andq $0x0, (%rdx)
movb $0x1, %r12b
xorl %r13d, %r13d
xorl %r14d, %r14d
xorl %r15d, %r15d
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %r13, %rcx
jbe 0xd904
movq (%rax,%r13,8), %rbp
movl (%rbp), %eax
cmpl $0x7, %eax
setne %cl
notb %r14b
movq 0x10(%rsp), %rdi
testb %cl, %r14b
jne 0xd78d
movq %rdi, 0x30(%rsp)
cmpl $0x7, %eax
jne 0xd7a2
leaq 0x10(%rbp), %r14
leaq 0xa0(%rsp), %rdi
movq %r14, %rsi
callq 0xec5e
movq (%rax), %rax
movq %rax, 0x10(%rsp)
cmpl $0x3, 0x8(%rbp)
jne 0xd7d2
leaq 0x58(%rsp), %rdi
movq %r14, %rsi
callq 0xed98
movq (%rax), %r15
jmp 0xd8f2
addq $0x8, %rdi
movq %rbp, 0x8(%rsp)
leaq 0x8(%rsp), %rsi
callq 0xe358
jmp 0xd81c
movl $0x2a8, %edi            # imm = 0x2A8
callq 0x8250
movq %rax, %r14
movq %rax, %rdi
callq 0xdb7c
movq %r14, 0x10(%rsp)
addq $0x8, %r14
movq %rbp, 0x8(%rsp)
movq %r14, %rdi
leaq 0x8(%rsp), %rsi
callq 0xe358
leaq 0x30(%r15), %rdi
leaq 0x10(%rsp), %rsi
callq 0xdd4a
movq 0x10(%rsp), %rax
movq %r15, 0x20(%rax)
movq 0x30(%rsp), %rdi
testq %rdi, %rdi
setne %al
andb %r12b, %al
cmpb $0x1, %al
jne 0xd81c
addq $0x40, %rdi
leaq 0x10(%rsp), %rsi
callq 0xdd4a
movq 0x10(%rsp), %rdi
addq $0x28, %rdi
leaq 0x30(%rsp), %rsi
callq 0xdd4a
movl (%rbp), %eax
addl $-0x9, %eax
cmpl $0x9, %eax
ja 0xd8ef
movb $0x1, %r14b
leaq 0x4905b(%rip), %rcx     # 0x56890
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
addq $0x90, %rbp
leaq 0xa0(%rsp), %rdi
movq %rbp, %rsi
callq 0xec5e
movq (%rax), %rax
movq %rax, 0x8(%rsp)
movq 0x10(%rsp), %rdi
addq $0x40, %rdi
leaq 0x8(%rsp), %rsi
callq 0xdd4a
movq 0x8(%rsp), %rdi
addq $0x28, %rdi
leaq 0x10(%rsp), %rsi
callq 0xdd4a
movb $0x1, %r14b
movb $0x1, %r12b
jmp 0xd8f5
addq $0x10, %rbp
leaq 0xa0(%rsp), %rdi
movq %rbp, %rsi
callq 0xec5e
movq (%rax), %rax
movq %rax, 0x8(%rsp)
movq 0x10(%rsp), %rdi
addq $0x40, %rdi
leaq 0x8(%rsp), %rsi
callq 0xdd4a
movq 0x8(%rsp), %rdi
addq $0x28, %rdi
leaq 0x10(%rsp), %rsi
callq 0xdd4a
xorl %r12d, %r12d
jmp 0xd8f5
addq $0x10, %rbp
leaq 0x58(%rsp), %rdi
movq %rbp, %rsi
callq 0xed98
leaq 0x48(%r15), %rdi
movq %rax, %rsi
callq 0xdd68
movb $0x1, %r12b
xorl %r14d, %r14d
incq %r13
movq (%rbx), %rax
movq 0x8(%rbx), %rcx
jmp 0xd722
leaq 0x58(%rsp), %rdi
callq 0xdd9a
leaq 0xa0(%rsp), %rdi
callq 0xde58
movq 0x90(%rsp), %rax
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
pushq $0x48
popq %rsi
jmp 0xd9c9
jmp 0xda05
jmp 0xd98a
jmp 0xd99b
jmp 0xda05
jmp 0xd98a
jmp 0xd99b
jmp 0xda05
jmp 0xd98a
jmp 0xd99b
jmp 0xda05
jmp 0xd98a
jmp 0xd99b
jmp 0xda05
jmp 0xd98a
jmp 0xd99b
jmp 0xda05
jmp 0xd98a
jmp 0xd99b
jmp 0xda05
jmp 0xd98a
jmp 0xd99b
jmp 0xda05
jmp 0xd98a
jmp 0xd99b
jmp 0xda05
movq %rax, %rbx
leaq 0x30(%rsp), %rdi
callq 0x8578
xorl %ebp, %ebp
jmp 0xd9b5
movq %rax, %rbx
jmp 0xd9c4
jmp 0xda05
jmp 0xd9b2
jmp 0xd9b2
jmp 0xd9b2
jmp 0xd9b2
jmp 0xd9b2
jmp 0xd9b2
jmp 0xd9b2
jmp 0xd9b2
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x8578
testb %bpl, %bpl
je 0xda08
movl $0x98, %esi
movq %r15, %rdi
jmp 0xd9dd
jmp 0xda05
jmp 0xda05
movq %rax, %rbx
movl $0x98, %esi
movq %rbp, %rdi
callq 0x8260
jmp 0xda08
jmp 0xd9ee
jmp 0xda05
jmp 0xda05
jmp 0xda05
jmp 0xda05
movq %rax, %rbx
leaq 0x30(%rsp), %rdi
callq 0x8578
jmp 0xda08
jmp 0xda05
jmp 0xda05
jmp 0xda05
jmp 0xda05
movq %rax, %rbx
leaq 0x58(%rsp), %rdi
callq 0xdd9a
leaq 0xa0(%rsp), %rdi
callq 0xde58
movq %rbx, %rdi
callq 0x84d0
nop