// File: /workspace/github_cpp_makefile_star2_O2/RuiDGPires[P]CrimLang/src/generator.cpp
// Function: gc_Tracker::factor(crl::Node*, std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char>>&)
u32 _gc_Tracker::factor(crl::Node *node, std::stringstream &stream){
	u32 reg;

//	ASSERT(node->type == crl::Node::Type::FACTOR, "Factor needs to be factor " + std::to_string(node->type));

	if (node->get_child(0)->type == crl::Node::Type::LEAF){
		reg = this->reg_tracker.alloc();
		std::string reg_name = reg_tracker.reg_name(reg);

		crl::Token t = get_token(node->get_child(0));
		switch (t.type){
			case crl::Token::Type::IDENT:
				if (this->symb_tracker.has_local(t.str)){
					std::pair<u32, bool> p = symb_tracker.get_local(t.str);
					stream <<
						"LOAD " << reg_name << " m[RF][-" << p.first << "]\n";
					if (p.second)
						stream <<
							"LOAD " << reg_name << " m[" << reg_name << "]\n";

				}else{
					stream <<
						"MVI " << reg_name << " " << symb_tracker.get_global(t.str) << "\n" <<
						"LOAD " << reg_name << " m[" << reg_name << "]\n";
				}
				break;
			case crl::Token::Type::INT:
				stream <<
					"MVI " << reg_name << " " << t.str << "\n";
				break;
			case crl::Token::Type::CHAR:
				stream <<
					"MVI " << reg_name << " '" << t.str << "'\n'";
				break;
			default:
				ASSERT(false, "Factor not implemented");
				break;
		}
		
	}else if (node->get_child(0)->type == crl::Node::Type::VECTOR){
		reg = this->reg_tracker.alloc();
		std::string reg_name = reg_tracker.reg_name(reg);

		crl::Token t = get_token(node->get_child(0)->get_child(0));
		u32 offset = atoi(get_token(node->get_child(0)->get_child(1)).str.c_str());
		if (this->symb_tracker.has_local(t.str)){
			std::pair<u32, bool> p = symb_tracker.get_local(t.str);
			if (p.second)
				stream <<
					"LOAD " << reg_name << " m[RF][-" << p.first << "]\n" << 
					"LOAD " << reg_name << " m[" << reg_name << "][-" << offset << "]\n";
			else
				stream <<
					"LOAD " << reg_name << " m[RF][-" << p.first + offset << "]\n";
		}else
			stream <<
				"MVI " << reg_name << " " << symb_tracker.get_global(t.str) << "\n" <<
				"LOAD " << reg_name << " m[" << reg_name << "][-" << offset << "]\n";

	}else if (node->get_child(0)->type == crl::Node::Type::EXPRESSION)
		reg =  this->expression_reg(node->get_child(0), stream);
	else if (node->get_child(0)->type == crl::Node::Type::CAST)
		if (node->get_child(0)->get_child(0)->type == crl::Node::Type::EXPRESSION)
			reg = this->expression_reg(node->get_child(0)->get_child(0), stream);
		else
			reg = this->factor(node->get_child(0), stream);
	else if (node->get_child(0)->type == crl::Node::Type::CALL){
		this->func_call(node->get_child(0), stream);
		reg = this->reg_tracker.alloc();	
		stream << "POP " << reg_tracker.reg_name(reg) << "\n"; // TODO Size larger than 1
	}else if (node->get_child(0)->type == crl::Node::Type::INC || node->get_child(0)->type == crl::Node::Type::DEC){
		reg = unary_reg(node->get_child(0)); 
	}else ASSERT(false, "Not implemented");
	
	return reg;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x188, %rsp            # imm = 0x188
movq %rdx, %r14
movq %rsi, %r12
movq %rdi, %r15
movq (%r12), %rax
movq %r12, %rdi
xorl %esi, %esi
callq *0x18(%rax)
cmpl $0x10, 0x8(%rax)
je 0x505e
movq (%r12), %rax
movq %r12, %rdi
xorl %esi, %esi
callq *0x18(%rax)
cmpl $0x19, 0x8(%rax)
je 0x5103
movq (%r12), %rax
movq %r12, %rdi
xorl %esi, %esi
callq *0x18(%rax)
movl 0x8(%rax), %ebx
movq (%r12), %rax
movq %r12, %rdi
xorl %esi, %esi
callq *0x18(%rax)
cmpl $0xd, %ebx
je 0x503f
movl 0x8(%rax), %ebx
movq (%r12), %rax
movq %r12, %rdi
xorl %esi, %esi
callq *0x18(%rax)
cmpl $0x15, %ebx
jne 0x523c
movq (%rax), %rcx
movq %rax, %rdi
xorl %esi, %esi
callq *0x18(%rcx)
movl 0x8(%rax), %ebx
movq (%r12), %rax
movq %r12, %rdi
xorl %esi, %esi
callq *0x18(%rax)
movq %rax, %r12
cmpl $0xd, %ebx
jne 0x4fa9
movq (%r12), %rax
movq %r12, %rdi
xorl %esi, %esi
callq *0x18(%rax)
movq %r15, %rdi
movq %rax, %rsi
movq %r14, %rdx
addq $0x188, %rsp            # imm = 0x188
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x586e
leaq 0x500(%r15), %r13
movq %r13, %rdi
callq 0xaa6c
movl %eax, %ebx
leaq -0xa8(%rbp), %rdi
movq %r13, %rsi
movl %eax, %edx
callq 0xab34
movq (%r12), %rax
movq %r12, %rdi
xorl %esi, %esi
callq *0x18(%rax)
addq $0x58, %rax
leaq -0x58(%rbp), %rdi
movq %rax, %rsi
callq 0xb24a
movl -0x38(%rbp), %eax
cmpl $0x1, %eax
je 0x543b
cmpl $0x13, %eax
je 0x53da
cmpl $0x1b, %eax
jne 0x56de
addq $0x10, %r14
leaq 0x10184(%rip), %rsi     # 0x15249
movq %r14, %rdi
callq 0x3230
leaq -0xa8(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0x1016b(%rip), %rsi     # 0x1524e
movq %rax, %rdi
callq 0x3230
leaq -0x58(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0x10153(%rip), %rsi     # 0x15251
jmp 0x541e
leaq 0x500(%r15), %r13
movq %r13, %rdi
callq 0xaa6c
movl %eax, %ebx
leaq -0x78(%rbp), %rdi
movq %r13, %rsi
movl %eax, %edx
callq 0xab34
movq (%r12), %rax
movq %r12, %rdi
xorl %esi, %esi
callq *0x18(%rax)
movq (%rax), %rcx
movq %rax, %rdi
xorl %esi, %esi
callq *0x18(%rcx)
addq $0x58, %rax
leaq -0x58(%rbp), %rdi
movq %rax, %rsi
callq 0xb24a
movq (%r12), %rax
movq %r12, %rdi
xorl %esi, %esi
callq *0x18(%rax)
movq (%rax), %rcx
pushq $0x1
popq %rsi
movq %rax, %rdi
callq *0x18(%rcx)
addq $0x58, %rax
leaq -0xa8(%rbp), %rdi
movq %rax, %rsi
callq 0xb24a
leaq -0xa8(%rbp), %r13
movq (%r13), %rdi
callq 0x3350
movl %eax, %r12d
movq %r13, %rdi
callq 0x135f8
leaq -0x108(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x32f0
addq $0x530, %r15            # imm = 0x530
leaq -0x108(%rbp), %rsi
movq %r15, %rdi
callq 0xabb4
movl %eax, %r13d
leaq -0x108(%rbp), %rdi
callq 0x3110
testb %r13b, %r13b
je 0x52bd
leaq -0xe8(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x32f0
leaq -0xe8(%rbp), %rsi
movq %r15, %rdi
callq 0xabee
movq %rax, %r15
leaq -0xe8(%rbp), %rdi
callq 0x3110
addq $0x10, %r14
btq $0x20, %r15
jb 0x554d
leaq 0x1002f(%rip), %rsi     # 0x15240
movq %r14, %rdi
callq 0x3230
leaq -0x78(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0x103b4(%rip), %rsi     # 0x155e0
movq %rax, %rdi
callq 0x3230
addl %r15d, %r12d
jmp 0x55d6
movl 0x8(%rax), %ebx
movq (%r12), %rax
movq %r12, %rdi
xorl %esi, %esi
callq *0x18(%rax)
cmpl $0xc, %ebx
jne 0x5396
movq %r15, %rdi
movq %rax, %rsi
movq %r14, %rdx
callq 0x5a58
addq $0x500, %r15            # imm = 0x500
movq %r15, %rdi
callq 0xaa6c
movl %eax, %ebx
addq $0x10, %r14
leaq 0xffee(%rip), %rsi      # 0x1526c
movq %r14, %rdi
callq 0x3230
movq %rax, %r14
leaq -0x58(%rbp), %r12
movq %r12, %rdi
movq %r15, %rsi
movl %ebx, %edx
callq 0xab34
movq %r14, %rdi
movq %r12, %rsi
callq 0x3220
leaq 0x10237(%rip), %rsi     # 0x154e3
movq %rax, %rdi
callq 0x3230
leaq -0x58(%rbp), %rdi
jmp 0x55fd
addq $0x10, %r14
leaq 0xff81(%rip), %rsi      # 0x15249
movq %r14, %rdi
callq 0x3230
leaq -0x78(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0xfd22(%rip), %rsi      # 0x15005
movq %rax, %rdi
callq 0x3230
movq %rax, %r14
leaq -0xc8(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x32f0
leaq -0xc8(%rbp), %rsi
movq %r15, %rdi
callq 0xac04
movl %eax, %esi
movq %r14, %rdi
callq 0x3180
leaq 0x101c5(%rip), %rsi     # 0x154e3
movq %rax, %rdi
callq 0x3230
leaq 0xff13(%rip), %rsi      # 0x15240
movq %rax, %rdi
callq 0x3230
leaq -0x78(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0x1028c(%rip), %rsi     # 0x155d4
movq %rax, %rdi
callq 0x3230
leaq -0x78(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0x10282(%rip), %rsi     # 0x155e5
movq %rax, %rdi
callq 0x3230
movl %r12d, %esi
movq %rax, %rdi
callq 0x3180
leaq 0xfec9(%rip), %rsi      # 0x15246
movq %rax, %rdi
callq 0x3230
leaq -0xc8(%rbp), %rdi
callq 0x3110
jmp 0x55f0
cmpl $0x13, 0x8(%rax)
je 0x53b2
movq (%r12), %rax
movq %r12, %rdi
xorl %esi, %esi
callq *0x18(%rax)
cmpl $0x14, 0x8(%rax)
jne 0x5732
movq (%r12), %rax
movq %r12, %rdi
xorl %esi, %esi
callq *0x18(%rax)
movq %r15, %rdi
movq %rax, %rsi
addq $0x188, %rsp            # imm = 0x188
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x5e9c
addq $0x10, %r14
leaq 0xfe64(%rip), %rsi      # 0x15249
movq %r14, %rdi
callq 0x3230
leaq -0xa8(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0xfc02(%rip), %rsi      # 0x15005
movq %rax, %rdi
callq 0x3230
leaq -0x58(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0x100c5(%rip), %rsi     # 0x154e3
movq %rax, %rdi
callq 0x3230
leaq -0x58(%rbp), %rdi
callq 0x135f8
leaq -0xa8(%rbp), %rdi
jmp 0x55fd
leaq -0x168(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x32f0
addq $0x530, %r15            # imm = 0x530
leaq -0x168(%rbp), %rsi
movq %r15, %rdi
callq 0xabb4
movl %eax, %r12d
leaq -0x168(%rbp), %rdi
callq 0x3110
testb %r12b, %r12b
je 0x5616
leaq -0x148(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x32f0
leaq -0x148(%rbp), %rsi
movq %r15, %rdi
callq 0xabee
movq %rax, %r15
leaq -0x148(%rbp), %rdi
callq 0x3110
addq $0x10, %r14
leaq 0xfd8e(%rip), %rsi      # 0x15240
movq %r14, %rdi
callq 0x3230
leaq -0xa8(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0x10110(%rip), %rsi     # 0x155e0
movq %rax, %rdi
callq 0x3230
movl %r15d, %esi
movq %rax, %rdi
callq 0x3180
leaq 0xfd5c(%rip), %rsi      # 0x15246
movq %rax, %rdi
callq 0x3230
btq $0x20, %r15
jae 0x5426
leaq 0xfd3c(%rip), %rsi      # 0x15240
movq %r14, %rdi
callq 0x3230
leaq -0xa8(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0x100b2(%rip), %rsi     # 0x155d4
movq %rax, %rdi
callq 0x3230
leaq -0xa8(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0xfd06(%rip), %rsi      # 0x15246
movq %rax, %rdi
callq 0x3230
jmp 0x5426
leaq 0xfcec(%rip), %rsi      # 0x15240
movq %r14, %rdi
callq 0x3230
leaq -0x78(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0x10071(%rip), %rsi     # 0x155e0
movq %rax, %rdi
callq 0x3230
movl %r15d, %esi
movq %rax, %rdi
callq 0x3180
leaq 0xfcbd(%rip), %rsi      # 0x15246
movq %rax, %rdi
callq 0x3230
leaq 0xfca8(%rip), %rsi      # 0x15240
movq %rax, %rdi
callq 0x3230
leaq -0x78(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0x10021(%rip), %rsi     # 0x155d4
movq %rax, %rdi
callq 0x3230
leaq -0x78(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0x10017(%rip), %rsi     # 0x155e5
movq %rax, %rdi
callq 0x3230
movl %r12d, %esi
movq %rax, %rdi
callq 0x3180
leaq 0xfc5e(%rip), %rsi      # 0x15246
movq %rax, %rdi
callq 0x3230
leaq -0x58(%rbp), %rdi
callq 0x135f8
leaq -0x78(%rbp), %rdi
callq 0x3110
movl %ebx, %eax
addq $0x188, %rsp            # imm = 0x188
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
addq $0x10, %r14
leaq 0xfc28(%rip), %rsi      # 0x15249
movq %r14, %rdi
callq 0x3230
leaq -0xa8(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0xf9c6(%rip), %rsi      # 0x15005
movq %rax, %rdi
callq 0x3230
movq %rax, %r14
leaq -0x128(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x32f0
leaq -0x128(%rbp), %rsi
movq %r15, %rdi
callq 0xac04
movl %eax, %esi
movq %r14, %rdi
callq 0x3180
leaq 0xfe69(%rip), %rsi      # 0x154e3
movq %rax, %rdi
callq 0x3230
leaq 0xfbb7(%rip), %rsi      # 0x15240
movq %rax, %rdi
callq 0x3230
leaq -0xa8(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0xff2d(%rip), %rsi      # 0x155d4
movq %rax, %rdi
callq 0x3230
leaq -0xa8(%rbp), %rsi
movq %rax, %rdi
callq 0x3220
leaq 0xfb81(%rip), %rsi      # 0x15246
movq %rax, %rdi
callq 0x3230
leaq -0x128(%rbp), %rdi
callq 0x3110
jmp 0x5426
pushq $0x50
popq %rdi
callq 0x3140
movq %rax, %r14
leaq 0xfb65(%rip), %rsi      # 0x15255
leaq -0x1a8(%rbp), %rdi
leaq -0x78(%rbp), %rdx
callq 0x3be4
movb $0x1, %r15b
pushq $-0x1
popq %rdx
leaq -0x1a8(%rbp), %rcx
movq %r14, %rdi
movl %edx, %esi
callq 0x4e88
xorl %r15d, %r15d
leaq 0x1866f(%rip), %rsi     # 0x1dd90
leaq -0x7f0(%rip), %rdx      # 0x4f38
movq %r14, %rdi
callq 0x33f0
jmp 0x5784
pushq $0x50
popq %rdi
callq 0x3140
movq %rax, %r14
leaq 0xfb2d(%rip), %rsi      # 0x15271
leaq -0x188(%rbp), %rdi
leaq -0x58(%rbp), %rdx
callq 0x3be4
movb $0x1, %r15b
pushq $-0x1
popq %rdx
leaq -0x188(%rbp), %rcx
movq %r14, %rdi
movl %edx, %esi
callq 0x4e88
xorl %r15d, %r15d
leaq 0x1861b(%rip), %rsi     # 0x1dd90
leaq -0x844(%rip), %rdx      # 0x4f38
movq %r14, %rdi
callq 0x33f0
movq %rax, %rbx
leaq -0x188(%rbp), %rdi
callq 0x3110
testb %r15b, %r15b
jne 0x57a0
jmp 0x5865
movq %rax, %rbx
movq %r14, %rdi
callq 0x31b0
jmp 0x5865
movq %rax, %rbx
leaq -0x148(%rbp), %rdi
jmp 0x5813
movq %rax, %rbx
leaq -0x1a8(%rbp), %rdi
callq 0x3110
testb %r15b, %r15b
jne 0x57d2
jmp 0x582d
movq %rax, %rbx
movq %r14, %rdi
callq 0x31b0
jmp 0x582d
movq %rax, %rbx
leaq -0x168(%rbp), %rdi
jmp 0x5813
movq %rax, %rbx
leaq -0xe8(%rbp), %rdi
jmp 0x584e
movq %rax, %rbx
leaq -0x58(%rbp), %rdi
jmp 0x5860
movq %rax, %rbx
leaq -0x108(%rbp), %rdi
jmp 0x584e
movq %rax, %rbx
leaq -0x128(%rbp), %rdi
callq 0x3110
jmp 0x582d
jmp 0x582a
movq %rax, %rbx
jmp 0x5836
jmp 0x583f
jmp 0x583f
movq %rax, %rbx
jmp 0x585c
movq %rax, %rbx
leaq -0x58(%rbp), %rdi
callq 0x135f8
leaq -0xa8(%rbp), %rdi
jmp 0x5860
movq %rax, %rbx
jmp 0x5853
movq %rax, %rbx
leaq -0xc8(%rbp), %rdi
callq 0x3110
leaq -0x58(%rbp), %rdi
callq 0x135f8
leaq -0x78(%rbp), %rdi
callq 0x3110
movq %rbx, %rdi
callq 0x3410
nop