// File: /workspace/github_c_makefile_star2_O3/Yamsman[P]scc/src/gen.c
// Function: gen_stmt_loop
void gen_stmt_loop(asm_f *f, ast_n *n) {
	char *lbl_beg = gen_numlabel(f);
	char *lbl_end = NULL;
	asmf_add_inst(f, mk_label(lbl_beg));

	//Condition for while and for loops
	if (n->dat.stmt.kind == STMT_WHILE) {
		lbl_end = gen_numlabel(f);
		
		//Does not apply for converted for loops with no condition
		if (n->dat.stmt.expr != NULL) {
			gen_expr(f, n->dat.stmt.expr);
			asmf_add_inst(f, mk_inst(INST_TEST, 2,
				mk_oprd(OPRD_REG, RAX),
				mk_oprd(OPRD_REG, RAX)
			));
			asmf_add_inst(f, mk_inst(INST_JZ, 1,
				mk_oprd_label(lbl_end)
			));
		}
	}
	
	//Generate loop body by hand to account for break/continue
	ast_n *n_cur = n->dat.stmt.body;
	if (n_cur->dat.stmt.kind == STMT_CMPD)
		n_cur = n_cur->next;
	while (n_cur != NULL) {
		f->cont_tgt = lbl_beg;
		f->break_tgt = lbl_end;
		switch (n_cur->kind) {
			case DECL: gen_decl(f, n_cur); break;
			case STMT: gen_stmt(f, n_cur); break;
		}
		n_cur = n_cur->next;
	}
	f->cont_tgt = NULL;
	f->break_tgt = NULL;

	//Condition for do-while loop
	if (n->dat.stmt.kind == STMT_DO_WHILE) {
		gen_expr(f, n->dat.stmt.expr);
		asmf_add_inst(f, mk_inst(INST_TEST, 2,
			mk_oprd(OPRD_REG, RAX),
			mk_oprd(OPRD_REG, RAX)
		));
		asmf_add_inst(f, mk_inst(INST_JNZ, 1,
			mk_oprd_label(lbl_beg)
		));
	} else {
		//Jump to beginning for while/for loops
		asmf_add_inst(f, mk_inst(INST_JMP, 1,
			mk_oprd_label(lbl_beg)
		));
	}

	//End label
	if (lbl_end != NULL)
		asmf_add_inst(f, mk_label(lbl_end));
	return;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x128, %rsp            # imm = 0x128
movq %rsi, %r12
movq %rdi, %rbx
callq 0x3e80
movq %rax, %r15
movq %rax, %rdi
callq 0x53b4
movq %rbx, %rdi
movq %rax, %rsi
callq 0x55c6
cmpl $0x4, 0x8(%r12)
jne 0x4d41
movq %rbx, %rdi
callq 0x3e80
movq %rax, %r14
movq 0x18(%r12), %rsi
testq %rsi, %rsi
je 0x4d44
movq %rbx, %rdi
callq 0x41eb
leaq 0x108(%rsp), %r13
movq %r13, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x52a0
leaq 0xe8(%rsp), %rbp
movq %rbp, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x52a0
movups (%rbp), %xmm0
movups 0x10(%rbp), %xmm1
movups %xmm1, 0x30(%rsp)
movups %xmm0, 0x20(%rsp)
movups (%r13), %xmm0
movups 0x10(%r13), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movl $0x3d, %edi
movl $0x2, %esi
xorl %eax, %eax
callq 0x52d5
movq %rbx, %rdi
movq %rax, %rsi
callq 0x55c6
leaq 0xc8(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
callq 0x52c0
movups (%r13), %xmm0
movups 0x10(%r13), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movl $0x39, %edi
movl $0x1, %esi
xorl %eax, %eax
callq 0x52d5
movq %rbx, %rdi
movq %rax, %rsi
callq 0x55c6
jmp 0x4d44
xorl %r14d, %r14d
movq 0x20(%r12), %r13
cmpl $0x1, 0x8(%r13)
jne 0x4d59
movq 0x60(%r13), %r13
testq %r13, %r13
je 0x4d75
movq %r15, 0x10(%rbx)
movq %r14, 0x18(%rbx)
cmpl $0x2, (%r13)
jne 0x4d50
movq %rbx, %rdi
movq %r13, %rsi
callq 0x497b
jmp 0x4d50
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rbx)
cmpl $0x6, 0x8(%r12)
jne 0x4e2c
movq 0x18(%r12), %rsi
movq %rbx, %rdi
callq 0x41eb
leaq 0xa8(%rsp), %r12
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x52a0
leaq 0x88(%rsp), %r13
movq %r13, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x52a0
movups (%r13), %xmm0
movups 0x10(%r13), %xmm1
movups %xmm1, 0x30(%rsp)
movups %xmm0, 0x20(%rsp)
movups (%r12), %xmm0
movups 0x10(%r12), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movl $0x3d, %edi
movl $0x2, %esi
xorl %eax, %eax
callq 0x52d5
movq %rbx, %rdi
movq %rax, %rsi
callq 0x55c6
leaq 0x68(%rsp), %r12
movq %r12, %rdi
movq %r15, %rsi
callq 0x52c0
movups (%r12), %xmm0
movups 0x10(%r12), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movl $0x3b, %edi
jmp 0x4e55
leaq 0x48(%rsp), %r12
movq %r12, %rdi
movq %r15, %rsi
callq 0x52c0
movups (%r12), %xmm0
movups 0x10(%r12), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movl $0x45, %edi
movl $0x1, %esi
xorl %eax, %eax
callq 0x52d5
movq %rbx, %rdi
movq %rax, %rsi
callq 0x55c6
testq %r14, %r14
je 0x4e84
movq %r14, %rdi
callq 0x53b4
movq %rbx, %rdi
movq %rax, %rsi
callq 0x55c6
addq $0x128, %rsp            # imm = 0x128
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq