// File: /workspace/github_cpp_makefile_star2_O2/rfotino[P]consolite-compiler/src/syntax.cpp
// Function: FunctionToken::output(Parser*)
void FunctionToken::output(Parser *parser) {
  // Check if this is a builtin function, in which case we should
  // do nothing.
  if (isBuiltin(_name)) {
    return;
  }
  // Create an end label for the function, so if we return we can jump
  // to it without having to unwind the stack each time.
  std::string endLabel = parser->getUnusedLabel(_name + "_end");
  // Create a label for the function so that we can CALL it.
  parser->writeln(_name + ":");
  // Assign registers or stack positions to parameters. Parameters can
  // be stored in registers "A" through "D", and if there are more than
  // 4 parameters they will be stored on the stack before the return
  // address. The return address is stored at FP, so the first
  // overflow parameter will be stored at -2, the next at -4, etc.
  std::string reg = "A";
  int offset = -ADDRESS_SIZE;
  int numOverflowParams = 0;
  for (auto param : _parameters) {
    if (reg[0] <= 'D') {
      param->setReg(reg);
      reg[0]++;
    } else {
      param->setOffset(offset);
      offset -= DATA_SIZE;
      numOverflowParams++;
    }
  }
  // Assign registers or stack positions to local variables. Local
  // variables can be stored in registers "E" through "K", and if there
  // are more local variables than can fit in registers we store them
  // as frame pointer offsets. The offset starts at 0 and increases from
  // there.
  reg = "E";
  offset = 0;
  int extraParamOffset = 0;
  for (auto local : _localVars) {
    if (reg[0] <= 'K' && local->canBeReg()) {
      local->setReg(reg);
      // This is a callee-saved register, push it onto the stack and
      // make a note that we need to pop it later.
      parser->writeInst("PUSH " + reg);
      _savedRegisters.push(reg);
      extraParamOffset -= DATA_SIZE;
      // Increment the register
      reg[0]++;
    } else {
      local->setOffset(offset);
      offset += DATA_SIZE;
    }
    // If this is an array, reserve space for the array's data.
    if (local->type().isArray()) {
      // The data offset is at the current stack offset + DATA_SIZE.
      // We must add DATA_SIZE because the stack pointer points at an
      // address that's in use, and we want the next unused address.
      local->setDataOffset(offset + DATA_SIZE);
      offset += local->type().arraySize() * DATA_SIZE;
    }
  }
  // Save the previous value of the frame pointer.
  parser->writeInst("PUSH FP");
  _savedRegisters.push("FP");
  extraParamOffset -= DATA_SIZE;
  // Set the frame pointer to the stack's current location.
  parser->writeInst("MOV FP SP");
  // Store parameters on the stack if they are currently stored in
  // registers but are flagged as needing their own address. Also fix
  // offset for parameters on the stack based on the number of saved
  // registers.
  for (auto param : _parameters) {
    if (param->isReg() && !param->canBeReg()) {
      parser->writeInst("PUSH " + param->getReg());
      param->setOffset(offset);
      offset += DATA_SIZE;
    } else if (!param->isReg()) {
      param->setOffset(param->getOffset() + extraParamOffset);
    }
  }
  // Reserve space for the local variable storage on the stack.
  if (0 < offset) {
    parser->writeInst("MOVI L " + toHexStr(offset));
    parser->writeInst("ADD SP L");
  }

  // Outputs initial values of local variables.
  for (auto local : _localVars) {
    local->output(parser);
  }

  // Assign assembly-level labels to all label declarations.
  for (auto label : _labels) {
    std::string asmLabel = parser->getUnusedLabel(_name + "_" + label->name());
    label->setAsmLabel(asmLabel);
  }

  // Output assembly code for the rest of the statement types.
  for (auto statement : _statements) {
    statement->output(parser, shared_from_this(), endLabel);
  }

  // Unwind the stack, popping the saved registers, then return.
  // We have a label here so that when we have return statements
  // they can jump here without having to unwind the stack in
  // multiple places.
  parser->writeln(endLabel + ":");
  parser->writeInst("MOV SP FP");
  while (!_savedRegisters.empty()) {
    parser->writeInst("POP " + _savedRegisters.top());
    _savedRegisters.pop();
  }
  // If there are overflow parameters, pop them off the stack in
  // addition to jumping to the return address.
  if (0 < numOverflowParams) {
    parser->writeInst("RET " + toHexStr(numOverflowParams * DATA_SIZE, 2));
  } else {
    parser->writeInst("RET");
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x138, %rsp            # imm = 0x138
movq %rsi, %r14
movq %rdi, %r15
leaq 0x58(%rdi), %r12
movq %r12, %rdi
callq 0x280fd
testb %al, %al
jne 0x149a5
leaq 0x15d51(%rip), %rdx     # 0x29edb
leaq 0x18(%rsp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x99f6
leaq 0x118(%rsp), %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0x901a
leaq 0x18(%rsp), %rdi
callq 0x75c8
leaq 0x17472(%rip), %rdx     # 0x2b630
leaq 0x18(%rsp), %rdi
movq %r12, %rsi
callq 0x99f6
leaq 0x18(%rsp), %rsi
movq %r14, %rdi
callq 0x93f2
movq %r12, 0xb0(%rsp)
movq %r14, 0x10(%rsp)
leaq 0x18(%rsp), %rdi
callq 0x75c8
leaq 0x15665(%rip), %rsi     # 0x2985b
leaq 0xd8(%rsp), %rdi
leaq 0x18(%rsp), %rdx
callq 0x9502
movq 0x78(%r15), %rbx
movq %r15, 0x60(%rsp)
movq 0x80(%r15), %r13
pushq $-0x2
popq %rbp
movl $0x0, 0x8c(%rsp)
leaq 0x20(%rsp), %r14
leaq 0x18(%rsp), %r15
leaq 0xd8(%rsp), %r12
cmpq %r13, %rbx
je 0x1428d
movq %r15, %rdi
movq %rbx, %rsi
callq 0x9d16
movq 0xd8(%rsp), %rax
cmpb $0x44, (%rax)
movq 0x18(%rsp), %rdi
jg 0x14272
addq $0x10, %rdi
movq %r12, %rsi
callq 0x71c0
movq 0xd8(%rsp), %rax
incb (%rax)
jmp 0x1427f
movl %ebp, 0x30(%rdi)
addl $-0x2, %ebp
incl 0x8c(%rsp)
movq %r14, %rdi
callq 0x7a34
addq $0x10, %rbx
jmp 0x14238
leaq 0x155cb(%rip), %rsi     # 0x2985f
leaq 0xd8(%rsp), %rdi
callq 0x7580
movq 0x60(%rsp), %rax
movq 0x90(%rax), %rbp
movq 0x98(%rax), %r14
addq $0xf0, %rax
movq %rax, 0xa8(%rsp)
movl $0x0, 0x50(%rsp)
leaq 0xd8(%rsp), %r12
leaq 0x18(%rsp), %r15
xorl %ebx, %ebx
cmpq %r14, %rbp
je 0x143c9
leaq 0x68(%rsp), %rdi
movq %rbp, %rsi
callq 0x18ee0
movq 0xd8(%rsp), %rax
cmpb $0x4b, (%rax)
movq 0x68(%rsp), %rsi
jg 0x14366
cmpb $0x1, 0x90(%rsi)
jne 0x14366
addq $0x10, %rsi
movq %rsi, %rdi
movq %r12, %rsi
callq 0x71c0
movq %r15, %rdi
leaq 0x14e1c(%rip), %rsi     # 0x2913f
movq %r12, %rdx
callq 0x9980
movq 0x10(%rsp), %rdi
movq %r15, %rsi
callq 0x914a
movq %r15, %rdi
callq 0x75c8
movq 0xa8(%rsp), %rdi
movq %r12, %rsi
callq 0x2554a
addl $-0x2, 0x50(%rsp)
movq 0xd8(%rsp), %rax
incb (%rax)
movq 0x68(%rsp), %rsi
jmp 0x1436c
movl %ebx, 0x30(%rsi)
addl $0x2, %ebx
addq $0x38, %rsi
movq %r15, %rdi
callq 0x9b54
movb 0x48(%rsp), %r13b
movq %r15, %rdi
callq 0x97a8
cmpb $0x1, %r13b
jne 0x143b6
movq 0x68(%rsp), %rsi
leal 0x2(%rbx), %eax
movw %ax, 0xb0(%rsi)
addq $0x38, %rsi
movq %r15, %rdi
callq 0x9b54
movzwl 0x4a(%rsp), %eax
leal (%rbx,%rax,2), %ebx
movq %r15, %rdi
callq 0x97a8
leaq 0x70(%rsp), %rdi
callq 0x7a34
addq $0x10, %rbp
jmp 0x142d9
leaq 0x159b2(%rip), %rsi     # 0x29d82
leaq 0x18(%rsp), %rdi
leaq 0x68(%rsp), %rdx
callq 0x9502
leaq 0x18(%rsp), %rsi
movq 0x10(%rsp), %r14
movq %r14, %rdi
callq 0x914a
movq 0x60(%rsp), %r15
movq 0xa8(%rsp), %r12
leaq 0x18(%rsp), %rdi
callq 0x75c8
leaq 0x15978(%rip), %rsi     # 0x29d87
leaq 0x18(%rsp), %rdi
leaq 0x68(%rsp), %rdx
callq 0x9502
leaq 0x18(%rsp), %rsi
movq %r12, %rdi
callq 0x24caa
leaq 0x18(%rsp), %rdi
callq 0x75c8
leaq 0x1594e(%rip), %rsi     # 0x29d8a
leaq 0x18(%rsp), %rdi
leaq 0x68(%rsp), %rdx
callq 0x9502
leaq 0x18(%rsp), %rsi
movq %r14, %rdi
callq 0x914a
addl $-0x2, 0x50(%rsp)
leaq 0x18(%rsp), %r14
movq %r14, %rdi
callq 0x75c8
movq 0x78(%r15), %r12
movq 0x80(%r15), %r15
leaq 0xb8(%rsp), %r13
leaq 0x68(%rsp), %rbp
cmpq %r15, %r12
je 0x14516
movq %r13, %rdi
movq %r12, %rsi
callq 0x9d16
movq 0xb8(%rsp), %rsi
cmpq $0x0, 0x18(%rsi)
je 0x144f9
cmpb $0x0, 0x90(%rsi)
jne 0x14500
addq $0x10, %rsi
movq %rbp, %rdi
callq 0x73e0
movq %r14, %rdi
leaq 0x14c7b(%rip), %rsi     # 0x2913f
movq %rbp, %rdx
callq 0x1832f
movq 0x10(%rsp), %rdi
movq %r14, %rsi
callq 0x914a
movq %r14, %rdi
callq 0x75c8
movq %rbp, %rdi
callq 0x75c8
movq 0xb8(%rsp), %rax
movl %ebx, 0x30(%rax)
addl $0x2, %ebx
jmp 0x14500
movl 0x50(%rsp), %eax
addl %eax, 0x30(%rsi)
leaq 0xc0(%rsp), %rdi
callq 0x7a34
addq $0x10, %r12
jmp 0x14482
testl %ebx, %ebx
movq 0x60(%rsp), %r14
jle 0x14598
movzwl %bx, %esi
leaq 0x68(%rsp), %rdi
pushq $0x4
popq %rdx
callq 0x27ea7
leaq 0x152e5(%rip), %rsi     # 0x2981b
leaq 0x18(%rsp), %rdi
leaq 0x68(%rsp), %rdx
callq 0x1832f
movq 0x10(%rsp), %rbx
leaq 0x18(%rsp), %rsi
movq %rbx, %rdi
callq 0x914a
leaq 0x18(%rsp), %rdi
callq 0x75c8
leaq 0x68(%rsp), %rdi
callq 0x75c8
leaq 0x15822(%rip), %rsi     # 0x29d94
leaq 0x18(%rsp), %rdi
leaq 0x68(%rsp), %rdx
callq 0x9502
leaq 0x18(%rsp), %rsi
movq %rbx, %rdi
callq 0x914a
leaq 0x18(%rsp), %rdi
callq 0x75c8
movq 0x90(%r14), %r13
movq 0x98(%r14), %rax
movq %rax, 0x50(%rsp)
leaq 0x15b1d(%rip), %rbp     # 0x2a0cf
leaq 0x18(%rsp), %r15
leaq 0x68(%rsp), %r14
leaq 0xb8(%rsp), %r12
cmpq 0x50(%rsp), %r13
je 0x1467c
leaq 0xf8(%rsp), %rdi
movq %r13, %rsi
callq 0x18ee0
movq 0xf8(%rsp), %rbx
xorps %xmm0, %xmm0
movaps %xmm0, 0x90(%rsp)
movq %r15, %rdi
movq %rbp, %rsi
leaq 0xf(%rsp), %rdx
callq 0x9502
movq %r14, %rdi
movq %rbp, %rsi
leaq 0x5f(%rsp), %rdx
callq 0x9502
movq %r12, %rdi
movq %rbp, %rsi
leaq 0x5e(%rsp), %rdx
callq 0x9502
movq (%rbx), %rax
movq %rbx, %rdi
movq 0x10(%rsp), %rsi
leaq 0x90(%rsp), %rdx
movq %r15, %rcx
movq %r14, %r8
movq %r12, %r9
callq *0x8(%rax)
movq %r12, %rdi
callq 0x75c8
movq %r14, %rdi
callq 0x75c8
movq %r15, %rdi
callq 0x75c8
leaq 0x98(%rsp), %rdi
callq 0x7a34
leaq 0x100(%rsp), %rdi
callq 0x7a34
addq $0x10, %r13
jmp 0x145c4
movq 0x60(%rsp), %rax
movq 0xa8(%rax), %r15
movq 0xb0(%rax), %rbx
leaq 0xb8(%rsp), %r13
leaq 0xf8(%rsp), %r14
leaq 0x68(%rsp), %r12
leaq 0x18(%rsp), %rbp
cmpq %rbx, %r15
je 0x14755
leaq 0x90(%rsp), %rdi
movq %r15, %rsi
callq 0x18ef4
movq %r13, %rdi
movq 0xb0(%rsp), %rsi
leaq 0x156c9(%rip), %rdx     # 0x29d9d
callq 0x99f6
movq 0x90(%rsp), %rsi
addq $0x10, %rsi
movq %r14, %rdi
callq 0x73e0
movq %r12, %rdi
movq %r13, %rsi
movq %r14, %rdx
callq 0x18714
movq %rbp, %rdi
movq 0x10(%rsp), %rsi
movq %r12, %rdx
callq 0x901a
movq %r12, %rdi
callq 0x75c8
movq %r14, %rdi
callq 0x75c8
movq %r13, %rdi
callq 0x75c8
movq 0x90(%rsp), %rdi
addq $0x30, %rdi
movq %rbp, %rsi
callq 0x71c0
movq %rbp, %rdi
callq 0x75c8
leaq 0x98(%rsp), %rdi
callq 0x7a34
addq $0x10, %r15
jmp 0x146a9
movq 0x60(%rsp), %rax
movq 0xd8(%rax), %r14
movq 0xe0(%rax), %rcx
movq %rcx, 0x50(%rsp)
addq $0x10, %rax
movq %rax, 0xb0(%rsp)
leaq 0xf8(%rsp), %rbx
leaq 0x15947(%rip), %r15     # 0x2a0cf
leaq 0x18(%rsp), %r12
leaq 0x68(%rsp), %rbp
cmpq 0x50(%rsp), %r14
je 0x1483b
leaq 0xb8(%rsp), %rdi
movq %r14, %rsi
callq 0x18f08
movq 0xb8(%rsp), %r13
movq %rbx, %rdi
movq 0xb0(%rsp), %rsi
callq 0x262aa
movq %r12, %rdi
movq %r15, %rsi
leaq 0x90(%rsp), %rdx
callq 0x9502
movq %rbp, %rdi
movq %r15, %rsi
leaq 0xf(%rsp), %rdx
callq 0x9502
movq (%r13), %rax
movq %r13, %rdi
movq 0x10(%rsp), %rsi
movq %rbx, %rdx
leaq 0x118(%rsp), %rcx
movq %r12, %r8
movq %rbp, %r9
callq *0x8(%rax)
movq %rbp, %rdi
callq 0x75c8
movq %r12, %rdi
callq 0x75c8
leaq 0x100(%rsp), %rdi
callq 0x7a34
leaq 0xc0(%rsp), %rdi
callq 0x7a34
addq $0x10, %r14
jmp 0x14792
leaq 0x16dee(%rip), %rdx     # 0x2b630
leaq 0x18(%rsp), %rdi
leaq 0x118(%rsp), %rsi
callq 0x99f6
leaq 0x18(%rsp), %rsi
movq 0x10(%rsp), %r12
movq %r12, %rdi
callq 0x93f2
movq 0x60(%rsp), %r13
movq 0xa8(%rsp), %rbp
leaq 0x18(%rsp), %rdi
callq 0x75c8
leaq 0x1551b(%rip), %rsi     # 0x29d9f
leaq 0x18(%rsp), %rdi
leaq 0x68(%rsp), %rdx
callq 0x9502
leaq 0x18(%rsp), %rsi
movq %r12, %rdi
callq 0x914a
leaq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x75c8
movl $0x200, %r15d           # imm = 0x200
leaq 0x1486a(%rip), %r14     # 0x29124
movq 0x120(%r13), %rdx
cmpq 0x100(%r13), %rdx
je 0x1490d
cmpq 0x128(%r13), %rdx
jne 0x148e1
movq 0x138(%r13), %rax
movq -0x8(%rax), %rdx
addq %r15, %rdx
addq $-0x20, %rdx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x9980
movq %r12, %rdi
movq %rbx, %rsi
callq 0x914a
movq %rbx, %rdi
callq 0x75c8
movq %rbp, %rdi
callq 0x25368
jmp 0x148ba
movl 0x8c(%rsp), %eax
testl %eax, %eax
jle 0x1495e
addl %eax, %eax
movzwl %ax, %esi
leaq 0x68(%rsp), %rdi
pushq $0x2
popq %rdx
callq 0x27ea7
leaq 0x15478(%rip), %rsi     # 0x29da9
leaq 0x18(%rsp), %rdi
leaq 0x68(%rsp), %rdx
callq 0x1832f
leaq 0x18(%rsp), %rsi
movq %r12, %rdi
callq 0x914a
leaq 0x18(%rsp), %rdi
callq 0x75c8
leaq 0x68(%rsp), %rdi
jmp 0x14986
leaq 0x15449(%rip), %rsi     # 0x29dae
leaq 0x18(%rsp), %rdi
leaq 0x68(%rsp), %rdx
callq 0x9502
leaq 0x18(%rsp), %rsi
movq %r12, %rdi
callq 0x914a
leaq 0x18(%rsp), %rdi
callq 0x75c8
leaq 0xd8(%rsp), %rdi
callq 0x75c8
leaq 0x118(%rsp), %rdi
callq 0x75c8
addq $0x138, %rsp            # imm = 0x138
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x14a95
jmp 0x14a8d
jmp 0x149d4
jmp 0x149e3
jmp 0x14a8d
jmp 0x14a95
jmp 0x14a8d
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x75c8
jmp 0x149e6
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
jmp 0x14a9d
jmp 0x14a8d
jmp 0x14a95
jmp 0x14a8d
jmp 0x14a95
jmp 0x14a8d
jmp 0x14a95
jmp 0x14a8d
jmp 0x14a95
jmp 0x14a8d
jmp 0x14a95
jmp 0x14a8d
jmp 0x14a8d
jmp 0x14a2c
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
jmp 0x14b90
movq %rax, %rbx
jmp 0x14b95
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
jmp 0x14b9d
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x75c8
jmp 0x14b7e
jmp 0x14b7b
jmp 0x14aa7
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x75c8
jmp 0x14a6c
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
callq 0x75c8
jmp 0x14ada
jmp 0x14b7b
jmp 0x14b7b
movq %rax, %rbx
movq %r14, %rdi
jmp 0x14b83
movq %rax, %rbx
jmp 0x14b88
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x75c8
jmp 0x14b88
movq %rax, %rbx
jmp 0x14ada
movq %rax, %rbx
jmp 0x14acd
movq %rax, %rbx
jmp 0x14ac3
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
callq 0x75c8
leaq 0x18(%rsp), %rdi
callq 0x75c8
leaq 0x100(%rsp), %rdi
callq 0x7a34
leaq 0xc0(%rsp), %rdi
jmp 0x14b83
movq %rax, %rbx
jmp 0x14b0b
movq %rax, %rbx
jmp 0x14afe
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
callq 0x75c8
leaq 0xf8(%rsp), %rdi
callq 0x75c8
leaq 0xb8(%rsp), %rdi
jmp 0x14b1d
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x75c8
jmp 0x14b27
movq %rax, %rbx
leaq 0x98(%rsp), %rdi
jmp 0x14b83
movq %rax, %rbx
jmp 0x14b64
movq %rax, %rbx
jmp 0x14b5a
movq %rax, %rbx
jmp 0x14b50
movq %rax, %rbx
leaq 0xb8(%rsp), %rdi
callq 0x75c8
leaq 0x68(%rsp), %rdi
callq 0x75c8
leaq 0x18(%rsp), %rdi
callq 0x75c8
leaq 0x98(%rsp), %rdi
callq 0x7a34
leaq 0x100(%rsp), %rdi
jmp 0x14b83
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x7a34
leaq 0xd8(%rsp), %rdi
callq 0x75c8
leaq 0x118(%rsp), %rdi
callq 0x75c8
movq %rbx, %rdi
callq 0x7510