// File: /workspace/github_cpp_makefile_star2_O2/taurheim[P]AgNES/irGenerator.cpp
// Function: IRGenerator::genTACStatement(ASTNode*)
void IRGenerator::genTACStatement(ASTNode * node) {
    StatementNode * statementNode = (StatementNode *)node;
    switch(statementNode->type) {
        case STMT_NES_WAITFORFRAME: {
            intermediateCode.push_back({ IR_NES_WAITFORFRAME });
            break;
        }
        case STMT_NES_SETSPRITEX: {
            IdentifierNode * globalIdentifier = (IdentifierNode*) node->children[0];
            std::string varName = globalIdentifier->name;

            intermediateCode.push_back({ IR_NES_SETSPRITEX, varName });
            break;
        }
        case STMT_NES_SETSPRITEY: {
            IdentifierNode * globalIdentifier = (IdentifierNode*) node->children[0];
            std::string varName = globalIdentifier->name;

            intermediateCode.push_back({ IR_NES_SETSPRITEY, varName });
            break;
        }
        case STMT_RETURN: {
            std::string returnValueRegister = genTACExpression(node->children[0]);
            intermediateCode.push_back({ IR_RETURN, returnValueRegister });
            break;
        }
        case STMT_FUNCTIONCALL: {
            IdentifierNode * functionIdentifier = (IdentifierNode*) node->children[0];
            std::string functionName = functionIdentifier->name;

            // Push params to the stack
            int parameterCount = 0;
            auto i = node->children.begin() + 1;
            while (i != node->children.end()) {
                ASTNode * argument = *i;
                std::string paramReg = genTACExpression(argument);
                intermediateCode.push_back({ IR_PUSHPARAM, paramReg });
                parameterCount++;
                i++;
            }

            // Call the function
            intermediateCode.push_back({ IR_CALL, functionName});

            // Pop the params off the stack
            intermediateCode.push_back({ IR_POPPARAMS, std::to_string(parameterCount)});
            break;
        }
        case (STMT_WHILE): {
            std::string labelBefore = genLabel();
            std::string labelAfter = genLabel();
            intermediateCode.push_back({ IR_NEWLABEL, labelBefore});
            std::string condition = genTACExpression(node->children[0]);
            intermediateCode.push_back({ IR_IFFALSEGOTO, condition, labelAfter });
            genTACStatement(node->children[1]);
            intermediateCode.push_back({ IR_GOTO, labelBefore });
            intermediateCode.push_back({ IR_NEWLABEL, labelAfter });
            break;
        }
        case (STMT_BLOCK): {
            for (auto & child : statementNode->children) {
                genTACStatement(child);
            }
            break;
        }
        case (STMT_ASSIGN): {
            ASTNode * assignmentNode = node->children[0];
            IdentifierNode * assignTo = (IdentifierNode*) assignmentNode->children[0];
            std::string tempRegister = genTACExpression(assignmentNode->children[1]);
            // TODO scope
            intermediateCode.push_back({ IR_ASSIGN, assignTo->name, tempRegister});
            break;
        }
        case (STMT_IF): {
            ASTNode * condition = node->children[0];
            ASTNode * ifBlock = node->children[1];
            ASTNode * elseBlock = nullptr;
            if (node->children.size() > 2) {
                // Future: handle more than just the else block
                elseBlock = node->children[2];
            }
            std::string falseLabel = genLabel();
            std::string outLabel = genLabel();
            std::string conditionRegister = genTACExpression(condition);
            intermediateCode.push_back({ IR_IFFALSEGOTO, conditionRegister, falseLabel });
            genTACStatement(ifBlock);
            intermediateCode.push_back({ IR_GOTO, outLabel });
            intermediateCode.push_back({ IR_NEWLABEL, falseLabel });
            if (elseBlock != nullptr) {
                genTACStatement(elseBlock);
            }
            intermediateCode.push_back({ IR_NEWLABEL, outLabel });
            break;
        }
        default: {
            return;
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xe8, %rsp
movq %rsi, -0x30(%rbp)
movl 0x20(%rsi), %eax
cmpq $0xa, %rax
ja 0xc83d
movq %rdi, %r13
leaq 0x466d(%rip), %rcx      # 0x10734
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq -0xb8(%rbp), %rdi
movq %r13, %rsi
callq 0xcbf6
leaq -0xe0(%rbp), %rdi
movq %r13, %rsi
callq 0xcbf6
leaq -0x90(%rbp), %rdi
movl $0x3, -0x8(%rdi)
leaq -0xb8(%rbp), %rsi
callq 0x32e0
leaq 0x10(%r13), %r15
leaq -0x60(%rbp), %rcx
movq %rcx, -0x10(%rcx)
andq $0x0, -0x8(%rcx)
xorl %eax, %eax
movb %al, (%rcx)
movq %r13, %r14
leaq -0x40(%rbp), %r13
movq %r13, -0x10(%r13)
andq $0x0, -0x8(%r13)
movb %al, (%r13)
leaq -0x98(%rbp), %rsi
movq %r15, %rdi
callq 0xccb6
leaq -0x98(%rbp), %rdi
callq 0x6104
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movq (%rax), %rdx
leaq -0x108(%rbp), %rdi
movq %r14, %rbx
movq %r14, %rsi
callq 0xbe52
leaq -0x90(%rbp), %r12
movl $0x6, -0x8(%r12)
leaq -0x108(%rbp), %rsi
movq %r12, %rdi
callq 0x32e0
leaq -0x70(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x32e0
leaq -0x98(%rbp), %rsi
movq %r13, 0x48(%rsi)
andq $0x0, 0x50(%rsi)
movb $0x0, 0x58(%rsi)
movq %r15, %rdi
callq 0xccb6
leaq -0x98(%rbp), %rdi
callq 0x6104
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rsi
movq %rbx, %rdi
callq 0xc098
leaq -0x60(%rbp), %r14
leaq -0x90(%rbp), %rdi
movl $0x4, -0x8(%rdi)
leaq -0xb8(%rbp), %rsi
callq 0x32e0
leaq -0x98(%rbp), %rsi
movq %r14, 0x28(%rsi)
andq $0x0, 0x30(%rsi)
xorl %eax, %eax
movb %al, 0x38(%rsi)
movq %r13, 0x48(%rsi)
andq $0x0, 0x50(%rsi)
movb %al, 0x58(%rsi)
movq %r15, %rdi
callq 0xccb6
leaq -0x98(%rbp), %rbx
movq %rbx, %rdi
callq 0x6104
movl $0x3, (%rbx)
leaq -0x90(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x32e0
leaq -0x98(%rbp), %rsi
movq %r14, 0x28(%rsi)
andq $0x0, 0x30(%rsi)
xorl %eax, %eax
movb %al, 0x38(%rsi)
movq %r13, 0x48(%rsi)
andq $0x0, 0x50(%rsi)
movb %al, 0x58(%rsi)
movq %r15, %rdi
callq 0xccb6
jmp 0xc80d
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movq (%rax), %rdx
leaq -0xb8(%rbp), %rbx
movq %rbx, %rdi
movq %r13, %rsi
callq 0xbe52
leaq -0x90(%rbp), %rdi
movl $0xd, -0x8(%rdi)
movq %rbx, %rsi
callq 0x32e0
addq $0x10, %r13
leaq -0x60(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
xorl %ecx, %ecx
movb %cl, (%rax)
leaq -0x40(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb %cl, (%rax)
leaq -0x98(%rbp), %rsi
movq %r13, %rdi
callq 0xccb6
jmp 0xc64c
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rbx
movq 0x10(%rax), %r14
cmpq %r14, %rbx
je 0xc83d
movq (%rbx), %rsi
movq %r13, %rdi
callq 0xc098
addq $0x8, %rbx
jmp 0xc2e8
movq -0x30(%rbp), %rcx
movq 0x8(%rcx), %rax
movq 0x10(%rcx), %rcx
subq %rax, %rcx
cmpq $0x11, %rcx
jb 0xc65d
movq 0x10(%rax), %rcx
movq %rcx, -0x30(%rbp)
jmp 0xc665
leaq -0x80(%rbp), %rax
movl $0xe, -0x18(%rax)
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
xorl %ecx, %ecx
movb %cl, (%rax)
leaq -0x60(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
addq $0x10, %r13
movb %cl, (%rax)
leaq -0x40(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb %cl, (%rax)
leaq -0x98(%rbp), %rsi
movq %r13, %rdi
callq 0xccb6
leaq -0x98(%rbp), %rdi
callq 0x6104
jmp 0xc83d
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movq (%rax), %rsi
addq $0x20, %rsi
leaq -0xb8(%rbp), %rbx
movq %rbx, %rdi
callq 0x32e0
leaq -0x90(%rbp), %rdi
movl $0xf, -0x8(%rdi)
movq %rbx, %rsi
callq 0x32e0
addq $0x10, %r13
leaq -0x60(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
xorl %ecx, %ecx
movb %cl, (%rax)
leaq -0x40(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb %cl, (%rax)
leaq -0x98(%rbp), %rsi
movq %r13, %rdi
callq 0xccb6
jmp 0xc64c
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movq (%rax), %rax
movq 0x8(%rax), %rax
movq (%rax), %rbx
movq 0x8(%rax), %rdx
leaq -0xb8(%rbp), %rdi
movq %r13, %rsi
callq 0xbe52
leaq -0x90(%rbp), %r14
movl $0x2, -0x8(%r14)
addq $0x20, %rbx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x32e0
leaq -0x70(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0x32e0
addq $0x10, %r13
leaq -0x40(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq -0x98(%rbp), %rsi
movq %r13, %rdi
callq 0xccb6
jmp 0xc64c
movq -0x30(%rbp), %rbx
movq 0x8(%rbx), %rax
movq (%rax), %rsi
addq $0x20, %rsi
leaq -0xb8(%rbp), %rdi
callq 0x32e0
movq 0x8(%rbx), %r15
movq %r13, -0xe8(%rbp)
leaq 0x10(%r13), %rax
movq %rax, -0xc0(%rbp)
addq $0x8, %r15
xorl %r14d, %r14d
leaq -0xe0(%rbp), %rbx
leaq -0x98(%rbp), %r13
xorl %r12d, %r12d
movq -0x30(%rbp), %rax
cmpq 0x10(%rax), %r15
je 0xc5a4
movq (%r15), %rdx
movq %rbx, %rdi
movq -0xe8(%rbp), %rsi
callq 0xbe52
movl $0xa, -0x98(%rbp)
leaq -0x90(%rbp), %rdi
movq %rbx, %rsi
callq 0x32e0
leaq -0x60(%rbp), %rax
movq %rax, -0x70(%rbp)
andq $0x0, -0x68(%rbp)
movb %r14b, -0x60(%rbp)
leaq -0x40(%rbp), %rax
movq %rax, -0x50(%rbp)
andq $0x0, -0x48(%rbp)
movb %r14b, -0x40(%rbp)
movq -0xc0(%rbp), %rdi
movq %r13, %rsi
callq 0xccb6
movq %r13, %rdi
callq 0x6104
incl %r12d
movq %rbx, %rdi
callq 0x3140
addq $0x8, %r15
jmp 0xc4b2
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movq (%rax), %rsi
addq $0x20, %rsi
leaq -0xb8(%rbp), %rbx
movq %rbx, %rdi
callq 0x32e0
leaq -0x90(%rbp), %rdi
movl $0x10, -0x8(%rdi)
movq %rbx, %rsi
callq 0x32e0
addq $0x10, %r13
leaq -0x60(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
xorl %ecx, %ecx
movb %cl, (%rax)
leaq -0x40(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb %cl, (%rax)
leaq -0x98(%rbp), %rsi
movq %r13, %rdi
callq 0xccb6
jmp 0xc64c
leaq -0x90(%rbp), %rdi
movl $0x9, -0x8(%rdi)
leaq -0xb8(%rbp), %rsi
callq 0x32e0
leaq -0x98(%rbp), %rsi
leaq -0x60(%rbp), %rax
movq %rax, 0x28(%rsi)
andq $0x0, 0x30(%rsi)
xorl %eax, %eax
movb %al, 0x38(%rsi)
leaq -0x40(%rbp), %rcx
movq %rcx, 0x48(%rsi)
andq $0x0, 0x50(%rsi)
movb %al, 0x58(%rsi)
movq -0xc0(%rbp), %rdi
callq 0xccb6
leaq -0x98(%rbp), %rbx
movq %rbx, %rdi
callq 0x6104
movl $0xb, (%rbx)
leaq -0x90(%rbp), %rdi
movl %r12d, %esi
callq 0x9afb
leaq -0x98(%rbp), %rsi
leaq -0x60(%rbp), %rax
movq %rax, 0x28(%rsi)
andq $0x0, 0x30(%rsi)
xorl %eax, %eax
movb %al, 0x38(%rsi)
leaq -0x40(%rbp), %rcx
movq %rcx, 0x48(%rsi)
andq $0x0, 0x50(%rsi)
movb %al, 0x58(%rsi)
movq -0xc0(%rbp), %rdi
callq 0xccb6
leaq -0x98(%rbp), %rdi
callq 0x6104
jmp 0xc831
movq $0x0, -0x30(%rbp)
movq (%rax), %rbx
movq 0x8(%rax), %r12
leaq -0xb8(%rbp), %rdi
movq %r13, %rsi
callq 0xcbf6
leaq -0xe0(%rbp), %rdi
movq %r13, %rsi
callq 0xcbf6
leaq -0x108(%rbp), %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0xbe52
leaq -0x90(%rbp), %r15
movl $0x6, -0x8(%r15)
leaq -0x108(%rbp), %rsi
movq %r15, %rdi
callq 0x32e0
leaq -0x70(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0x32e0
leaq 0x10(%r13), %r15
movq %r13, %rbx
leaq -0x40(%rbp), %r13
movq %r13, -0x10(%r13)
andq $0x0, -0x8(%r13)
movb $0x0, (%r13)
leaq -0x98(%rbp), %rsi
movq %r15, %rdi
callq 0xccb6
leaq -0x98(%rbp), %rdi
callq 0x6104
movq %rbx, %r14
movq %rbx, %rdi
movq %r12, %rsi
callq 0xc098
leaq -0x90(%rbp), %rdi
movl $0x4, -0x8(%rdi)
leaq -0xe0(%rbp), %rsi
callq 0x32e0
leaq -0x60(%rbp), %r12
movq %r12, -0x10(%r12)
andq $0x0, -0x8(%r12)
xorl %eax, %eax
movb %al, (%r12)
movq %r13, 0x10(%r12)
andq $0x0, 0x18(%r12)
movb %al, 0x20(%r12)
leaq -0x98(%rbp), %rsi
movq %r15, %rdi
callq 0xccb6
leaq -0x98(%rbp), %rbx
movq %rbx, %rdi
callq 0x6104
movl $0x3, (%rbx)
leaq -0x90(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0x32e0
leaq -0x98(%rbp), %rsi
movq %r12, 0x28(%rsi)
andq $0x0, 0x30(%rsi)
xorl %eax, %eax
movb %al, 0x38(%rsi)
movq %r13, 0x48(%rsi)
andq $0x0, 0x50(%rsi)
movb %al, 0x58(%rsi)
movq %r15, %rdi
callq 0xccb6
leaq -0x98(%rbp), %rdi
callq 0x6104
cmpq $0x0, -0x30(%rbp)
je 0xc7ca
movq %r14, %rdi
movq -0x30(%rbp), %rsi
callq 0xc098
leaq -0x90(%rbp), %rdi
movl $0x3, -0x8(%rdi)
leaq -0xe0(%rbp), %rsi
callq 0x32e0
leaq -0x98(%rbp), %rsi
movq %r12, 0x28(%rsi)
andq $0x0, 0x30(%rsi)
xorl %eax, %eax
movb %al, 0x38(%rsi)
movq %r13, 0x48(%rsi)
andq $0x0, 0x50(%rsi)
movb %al, 0x58(%rsi)
movq %r15, %rdi
callq 0xccb6
leaq -0x98(%rbp), %rdi
callq 0x6104
leaq -0x108(%rbp), %rdi
callq 0x3140
leaq -0xe0(%rbp), %rdi
callq 0x3140
leaq -0xb8(%rbp), %rdi
callq 0x3140
addq $0xe8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0xc8b8
jmp 0xc8f7
jmp 0xc8b8
jmp 0xc8f7
jmp 0xc880
jmp 0xc880
jmp 0xc8e6
jmp 0xc8e6
jmp 0xc880
jmp 0xc880
jmp 0xc8e6
jmp 0xc8e6
jmp 0xc880
jmp 0xc8e6
jmp 0xc8e6
jmp 0xc880
movq %rax, %rbx
movq %r12, %rdi
jmp 0xc899
movq %rax, %rbx
leaq -0x98(%rbp), %rdi
callq 0x6104
jmp 0xc8e9
jmp 0xc8e6
movq %rax, %rbx
movq %r15, %rdi
callq 0x3140
jmp 0xc8e9
jmp 0xc8fc
jmp 0xc8e6
jmp 0xc8b8
jmp 0xc901
jmp 0xc8b8
jmp 0xc8fc
movq %rax, %rbx
movq %r14, %rdi
jmp 0xc917
jmp 0xc8b8
jmp 0xc8fc
movq %rax, %rbx
leaq -0x98(%rbp), %rdi
callq 0x6104
jmp 0xc91c
jmp 0xc8f7
jmp 0xc8f7
jmp 0xc8f7
jmp 0xc8f7
movq %rax, %rbx
leaq -0x98(%rbp), %rdi
callq 0x6104
jmp 0xc928
jmp 0xc8f7
jmp 0xc8f7
movq %rax, %rbx
leaq -0x108(%rbp), %rdi
callq 0x3140
jmp 0xc910
movq %rax, %rbx
jmp 0xc91c
movq %rax, %rbx
jmp 0xc910
movq %rax, %rbx
leaq -0x98(%rbp), %rdi
callq 0x6104
leaq -0xe0(%rbp), %rdi
callq 0x3140
leaq -0xb8(%rbp), %rdi
callq 0x3140
movq %rbx, %rdi
callq 0x33e0