// File: luooofan[P]hblzbd_compiler/src/arm_struct.cpp
// Function: ArmModule::EmitCode(std::ostream&)
void ArmModule::EmitCode(std::ostream& out) {
  out << ".arch armv7ve" << std::endl;
  out << ".arm" << std::endl;
  out << "@ module: " << this->name_ << std::endl;
  out << std::endl;
  out << R"(
.macro mov32, cond, reg, val
    movw\cond \reg, #:lower16:\val
    movt\cond \reg, #:upper16:\val
.endm
  )" << std::endl;
  out << std::endl;
  // .data
  auto& global_symtab = this->global_scope_.symbol_table_;
  if (!global_symtab.empty()) {
    // out << ".section .data" << std::endl;
    // out << ".align 4" << std::endl;
    // out << std::endl;
    // TODO: order?
    for (auto& symbol : global_symtab) {
      if (symbol.first == "_sysy_idx" || symbol.first == "_sysy_l1" || symbol.first == "_sysy_l2" ||
          symbol.first == "_sysy_h" || symbol.first == "_sysy_m" || symbol.first == "_sysy_s" ||
          symbol.first == "_sysy_us")
        continue;
      // NOTE: 数组常量不能删 可能会用到变量下标
      if (symbol.second.is_const_ && !symbol.second.is_array_) continue;
      bool in_bss = true;
      int last_not0 = 0;
      for (int i = 0; i < symbol.second.initval_.size(); ++i) {
        if (0 != symbol.second.initval_[i]) {
          in_bss = false;
          last_not0 = i;
        }
      }
      if (in_bss) {
        // .comm symbol length align
        out << ".comm " << symbol.first << ", " << (symbol.second.width_.empty() ? 4 : symbol.second.width_[0]) << ", 4"
            << std::endl;
      } else {
        out << "\t.global " << symbol.first << std::endl;
        out << "\t.data" << std::endl;
        out << "\t.align 4" << std::endl;
        out << "\t.type " << symbol.first << ", %object" << std::endl;
        out << symbol.first << ":" << std::endl;
        int cnt0 = 0;
        for (int i = 0; i < symbol.second.initval_.size(); ++i) {
          if (0 == symbol.second.initval_[i]) {
            ++cnt0;
          } else {
            if (0 != cnt0) {
              out << "\t.space " << cnt0 * 4 << std::endl;
              cnt0 = 0;
            }
            out << "\t.word " << symbol.second.initval_[i] << std::endl;
          }
          if (i == last_not0) break;
        }
        int space = (symbol.second.initval_.size() - last_not0 - 1) * 4;
        if (0 != space) {
          out << "\t.space " << space << std::endl;
        }
      }
      out << std::endl;
    }
  }

  // .text
  out << ".section .text" << std::endl;
  out << std::endl;
  // out << ".syntax unified" << std::endl << std::endl;
  for (auto func : this->func_list_) {
    func->EmitCode(out);
    out << std::endl;
  }
}

// Assembly:
subq $0xa8, %rsp
movq %rdi, 0xa0(%rsp)
movq %rsi, 0x98(%rsp)
movq 0xa0(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x98(%rsp), %rdi
leaq 0xea3b9(%rip), %rsi     # 0xfa2cc
callq 0x8330
movq %rax, %rdi
movq 0x13c05e(%rip), %rsi    # 0x14bf80
callq 0x8380
movq 0x98(%rsp), %rdi
leaq 0xea3a4(%rip), %rsi     # 0xfa2da
callq 0x8330
movq %rax, %rdi
movq 0x13c03b(%rip), %rsi    # 0x14bf80
callq 0x8380
movq 0x98(%rsp), %rdi
leaq 0xea386(%rip), %rsi     # 0xfa2df
callq 0x8330
movq 0x30(%rsp), %rsi
movq %rax, %rdi
addq $0x8, %rsi
callq 0x8310
movq %rax, %rdi
movq 0x13c007(%rip), %rsi    # 0x14bf80
callq 0x8380
movq 0x98(%rsp), %rdi
movq 0x13bff3(%rip), %rsi    # 0x14bf80
callq 0x8380
movq 0x98(%rsp), %rdi
leaq 0xea349(%rip), %rsi     # 0xfa2ea
callq 0x8330
movq %rax, %rdi
movq 0x13bfd0(%rip), %rsi    # 0x14bf80
callq 0x8380
movq 0x98(%rsp), %rdi
movq 0x13bfbc(%rip), %rsi    # 0x14bf80
callq 0x8380
movq 0x30(%rsp), %rax
movq 0x40(%rax), %rax
movq %rax, 0x90(%rsp)
movq 0x90(%rsp), %rdi
callq 0x10980
testb $0x1, %al
jne 0x104ba
movq 0x90(%rsp), %rax
movq %rax, 0x88(%rsp)
movq 0x88(%rsp), %rdi
callq 0x109a0
movq %rax, 0x80(%rsp)
movq 0x88(%rsp), %rdi
callq 0x109d0
movq %rax, 0x78(%rsp)
leaq 0x80(%rsp), %rdi
leaq 0x78(%rsp), %rsi
callq 0x10a00
testb $0x1, %al
jne 0x10041
jmp 0x104b8
leaq 0x80(%rsp), %rdi
callq 0x10a20
movq %rax, 0x70(%rsp)
movq 0x70(%rsp), %rdi
leaq 0xea2f8(%rip), %rsi     # 0xfa357
callq 0xcc60
testb $0x1, %al
jne 0x100ec
movq 0x70(%rsp), %rdi
leaq 0xea2e9(%rip), %rsi     # 0xfa361
callq 0xcc60
testb $0x1, %al
jne 0x100ec
movq 0x70(%rsp), %rdi
leaq 0xea2dd(%rip), %rsi     # 0xfa36a
callq 0xcc60
testb $0x1, %al
jne 0x100ec
movq 0x70(%rsp), %rdi
leaq 0xea2d1(%rip), %rsi     # 0xfa373
callq 0xcc60
testb $0x1, %al
jne 0x100ec
movq 0x70(%rsp), %rdi
leaq 0xea2c4(%rip), %rsi     # 0xfa37b
callq 0xcc60
testb $0x1, %al
jne 0x100ec
movq 0x70(%rsp), %rdi
leaq 0xea2b7(%rip), %rsi     # 0xfa383
callq 0xcc60
testb $0x1, %al
jne 0x100ec
movq 0x70(%rsp), %rdi
leaq 0xea2aa(%rip), %rsi     # 0xfa38b
callq 0xcc60
testb $0x1, %al
jne 0x100ec
jmp 0x100f1
jmp 0x104a6
movq 0x70(%rsp), %rax
testb $0x1, 0x21(%rax)
je 0x1010c
movq 0x70(%rsp), %rax
testb $0x1, 0x20(%rax)
jne 0x1010c
jmp 0x104a6
movb $0x1, 0x6f(%rsp)
movl $0x0, 0x68(%rsp)
movl $0x0, 0x64(%rsp)
movslq 0x64(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x70(%rsp), %rdi
addq $0x20, %rdi
addq $0x38, %rdi
callq 0x10a40
movq %rax, %rcx
movq 0x28(%rsp), %rax
cmpq %rcx, %rax
jae 0x10186
movq 0x70(%rsp), %rdi
addq $0x20, %rdi
addq $0x38, %rdi
movslq 0x64(%rsp), %rsi
callq 0x10a60
movq %rax, %rcx
xorl %eax, %eax
cmpl (%rcx), %eax
je 0x10177
movb $0x0, 0x6f(%rsp)
movl 0x64(%rsp), %eax
movl %eax, 0x68(%rsp)
jmp 0x10179
movl 0x64(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x64(%rsp)
jmp 0x10121
testb $0x1, 0x6f(%rsp)
je 0x10236
movq 0x98(%rsp), %rdi
leaq 0xea1f4(%rip), %rsi     # 0xfa394
callq 0x8330
movq %rax, %rdi
movq 0x70(%rsp), %rsi
callq 0x8310
movq %rax, %rdi
leaq 0xe9fb3(%rip), %rsi     # 0xfa16f
callq 0x8330
movq %rax, 0x20(%rsp)
movq 0x70(%rsp), %rdi
addq $0x20, %rdi
addq $0x20, %rdi
callq 0x10a80
testb $0x1, %al
jne 0x101de
jmp 0x101e9
movl $0x4, %eax
movl %eax, 0x1c(%rsp)
jmp 0x10205
movq 0x70(%rsp), %rdi
addq $0x20, %rdi
addq $0x20, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x10a60
movl (%rax), %eax
movl %eax, 0x1c(%rsp)
movq 0x20(%rsp), %rdi
movl 0x1c(%rsp), %esi
callq 0x8650
movq %rax, %rdi
leaq 0xea17e(%rip), %rsi     # 0xfa39b
callq 0x8330
movq %rax, %rdi
movq 0x13bd54(%rip), %rsi    # 0x14bf80
callq 0x8380
jmp 0x10492
movq 0x98(%rsp), %rdi
leaq 0xea15a(%rip), %rsi     # 0xfa39f
callq 0x8330
movq %rax, %rdi
movq 0x70(%rsp), %rsi
callq 0x8310
movq %rax, %rdi
movq 0x13bd1f(%rip), %rsi    # 0x14bf80
callq 0x8380
movq 0x98(%rsp), %rdi
leaq 0xea134(%rip), %rsi     # 0xfa3a9
callq 0x8330
movq %rax, %rdi
movq 0x13bcfc(%rip), %rsi    # 0x14bf80
callq 0x8380
movq 0x98(%rsp), %rdi
leaq 0xea118(%rip), %rsi     # 0xfa3b0
callq 0x8330
movq %rax, %rdi
movq 0x13bcd9(%rip), %rsi    # 0x14bf80
callq 0x8380
movq 0x98(%rsp), %rdi
leaq 0xea0ff(%rip), %rsi     # 0xfa3ba
callq 0x8330
movq %rax, %rdi
movq 0x70(%rsp), %rsi
callq 0x8310
movq %rax, %rdi
leaq 0xea0eb(%rip), %rsi     # 0xfa3c2
callq 0x8330
movq %rax, %rdi
movq 0x13bc9a(%rip), %rsi    # 0x14bf80
callq 0x8380
movq 0x98(%rsp), %rdi
movq 0x70(%rsp), %rsi
callq 0x8310
movq %rax, %rdi
leaq 0xeb0e3(%rip), %rsi     # 0xfb3ea
callq 0x8330
movq %rax, %rdi
movq 0x13bc6a(%rip), %rsi    # 0x14bf80
callq 0x8380
movl $0x0, 0x60(%rsp)
movl $0x0, 0x5c(%rsp)
movslq 0x5c(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x70(%rsp), %rdi
addq $0x20, %rdi
addq $0x38, %rdi
callq 0x10a40
movq %rax, %rcx
movq 0x10(%rsp), %rax
cmpq %rcx, %rax
jae 0x10433
movq 0x70(%rsp), %rdi
addq $0x20, %rdi
addq $0x38, %rdi
movslq 0x5c(%rsp), %rsi
callq 0x10a60
movq %rax, %rcx
xorl %eax, %eax
cmpl (%rcx), %eax
jne 0x10388
movl 0x60(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x60(%rsp)
jmp 0x10415
xorl %eax, %eax
cmpl 0x60(%rsp), %eax
je 0x103ca
movq 0x98(%rsp), %rdi
leaq 0xea02d(%rip), %rsi     # 0xfa3cc
callq 0x8330
movq %rax, %rdi
movl 0x60(%rsp), %esi
shll $0x2, %esi
callq 0x8650
movq %rax, %rdi
movq 0x13bbc3(%rip), %rsi    # 0x14bf80
callq 0x8380
movl $0x0, 0x60(%rsp)
movq 0x98(%rsp), %rdi
leaq 0xe9ffc(%rip), %rsi     # 0xfa3d5
callq 0x8330
movq %rax, 0x8(%rsp)
movq 0x70(%rsp), %rdi
addq $0x20, %rdi
addq $0x38, %rdi
movslq 0x5c(%rsp), %rsi
callq 0x10a60
movq 0x8(%rsp), %rdi
movl (%rax), %esi
callq 0x8650
movq %rax, %rdi
movq 0x13bb70(%rip), %rsi    # 0x14bf80
callq 0x8380
movl 0x5c(%rsp), %eax
cmpl 0x68(%rsp), %eax
jne 0x10421
jmp 0x10433
jmp 0x10423
movl 0x5c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x5c(%rsp)
jmp 0x1032b
movq 0x70(%rsp), %rdi
addq $0x20, %rdi
addq $0x38, %rdi
callq 0x10a40
movslq 0x68(%rsp), %rcx
subq %rcx, %rax
subq $0x1, %rax
shlq $0x2, %rax
movl %eax, 0x58(%rsp)
xorl %eax, %eax
cmpl 0x58(%rsp), %eax
je 0x10490
movq 0x98(%rsp), %rdi
leaq 0xe9f5c(%rip), %rsi     # 0xfa3cc
callq 0x8330
movq %rax, %rdi
movl 0x58(%rsp), %esi
callq 0x8650
movq %rax, %rdi
movq 0x13baf5(%rip), %rsi    # 0x14bf80
callq 0x8380
jmp 0x10492
movq 0x98(%rsp), %rdi
movq 0x13badf(%rip), %rsi    # 0x14bf80
callq 0x8380
leaq 0x80(%rsp), %rdi
callq 0x10ad0
jmp 0x10026
jmp 0x104ba
movq 0x98(%rsp), %rdi
leaq 0xe9f14(%rip), %rsi     # 0xfa3dd
callq 0x8330
movq %rax, %rdi
movq 0x13baa8(%rip), %rsi    # 0x14bf80
callq 0x8380
movq 0x98(%rsp), %rdi
movq 0x13ba94(%rip), %rsi    # 0x14bf80
callq 0x8380
movq 0x30(%rsp), %rax
addq $0x28, %rax
movq %rax, 0x50(%rsp)
movq 0x50(%rsp), %rdi
callq 0x10b00
movq %rax, 0x48(%rsp)
movq 0x50(%rsp), %rdi
callq 0x10b30
movq %rax, 0x40(%rsp)
leaq 0x48(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x10b60
testb $0x1, %al
jne 0x10532
jmp 0x10576
leaq 0x48(%rsp), %rdi
callq 0x10ba0
movq (%rax), %rax
movq %rax, 0x38(%rsp)
movq 0x38(%rsp), %rdi
movq 0x98(%rsp), %rsi
callq 0x10580
movq 0x98(%rsp), %rdi
movq 0x13ba1b(%rip), %rsi    # 0x14bf80
callq 0x8380
leaq 0x48(%rsp), %rdi
callq 0x10bb0
jmp 0x1051d
addq $0xa8, %rsp
retq
nop