// File: /workspace/github_c_makefile_star2_O0/Encryptr[P]O-plus-plus/opp/analysis/analysis.c
// Function: opp_analize_bin
static Opp_Obj opp_analize_bin(struct Opp_Analize* ctx, struct Opp_Node* node)
{
	opp_analize_time_eval(ctx, node);

	if (node->type == EUNARY)
		return opp_analize_unary(ctx, node);

	/* ### Swap sides optimization for compiler ### */
	/* Rules
	Dont do on div / mod
	1: 2 + a / 2.3 + a
		Swap immidiates to left
	2: m + test()
		Swap function calls to right

	3: a + b
		No swap
	4: test() + test()
		No swap
	*/
	if (node->bin_expr.tok != TDIV && node->bin_expr.tok != TMOD) {
		struct Opp_Node* temp = NULL;
		if ((node->bin_expr.left->type == EUNARY) &&
			(node->bin_expr.left->unary_expr.type == TINTEGER 
			|| node->bin_expr.left->unary_expr.type == TFLOAT)) 
		{
			// Swap imm to left side
			temp = node->bin_expr.left;
			node->bin_expr.left = node->bin_expr.right;
			node->bin_expr.right = temp;
		}
		else if (node->bin_expr.right->type == ECALL) {
			// Swap func call to left side
			temp = node->bin_expr.left;
			node->bin_expr.left = node->bin_expr.right;
			node->bin_expr.right = temp;
		}
	}

	const char *l_name, *r_name;
	Opp_Obj lhs = opp_analize_expr(ctx, node->bin_expr.left);
	l_name = ctx->debug.res_name;
	Opp_Obj rhs = opp_analize_expr(ctx, node->bin_expr.right);
	r_name = ctx->debug.res_name;

	// Cannot add struct obj of non ptr type
	if ((rhs.decl->t_type == TYPE_STRUCT && rhs.depth == 0) 
		|| 
	   (lhs.decl->t_type == TYPE_STRUCT && lhs.depth == 0))
		opp_semantics_error(ctx, node, "Not allowed to preform arith on struct type");

	// Warn adding two pointer types
	if (rhs.depth > 0 && lhs.depth > 0)
		opp_warning(ctx, node, "Adding two pointers '%s' '%s'", l_name, r_name);

	// Warn array type in arith
	if (rhs.size > 0 || lhs.size > 0)
		opp_warning(ctx, node, "Adding two arrays causes undefined behavior");

	// Error adding to pointer a floating point
	if ((rhs.depth > 0 || lhs.depth > 0) 
		&& 
		((rhs.decl->t_type == TYPE_FLOAT || rhs.decl->t_type == TYPE_DOUBLE)
			|| (lhs.decl->t_type == TYPE_FLOAT || lhs.decl->t_type == TYPE_DOUBLE)))
		opp_semantics_error(ctx, node, "Adding a floating point type to pointer");

	/* ### Pointer size optimization ### */
	/* Rules
	Only applies to add and sub
	double* a;
	1: a + 2
		Make 2 actually 2 * sizeof(double)
	
	int** b;
	2: b + 3
		Make 3 actually 3 * sizeof(int**)
	*/
	if (node->bin_expr.tok == TADD || node->bin_expr.tok == TMIN) {
		if (lhs.depth > 0 && (node->bin_expr.right->type == EUNARY 
			&& node->bin_expr.right->unary_expr.type == TINTEGER))
		{
			lhs.depth--;
			unsigned int size = get_type_size(&lhs);
			node->bin_expr.right->unary_expr.val.i64val *= size;
			lhs.depth++;
		}
	}

	return lhs;
}

// Assembly:
subq $0x58, %rsp
movq %rdi, 0x40(%rsp)
movq %rsi, 0x38(%rsp)
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rsi
callq 0x3910
movq 0x38(%rsp), %rax
cmpl $0x5, (%rax)
jne 0x48b5
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rsi
callq 0x4b60
movq %rax, 0x48(%rsp)
movq %rdx, 0x50(%rsp)
jmp 0x4b4d
movq 0x38(%rsp), %rax
cmpl $0x15, 0x10(%rax)
je 0x4978
movq 0x38(%rsp), %rax
cmpl $0x17, 0x10(%rax)
je 0x4978
movq $0x0, 0x30(%rsp)
movq 0x38(%rsp), %rax
movq 0x20(%rax), %rax
cmpl $0x5, (%rax)
jne 0x4938
movq 0x38(%rsp), %rax
movq 0x20(%rax), %rax
cmpl $0x2, 0x10(%rax)
je 0x4908
movq 0x38(%rsp), %rax
movq 0x20(%rax), %rax
cmpl $0x3, 0x10(%rax)
jne 0x4938
movq 0x38(%rsp), %rax
movq 0x20(%rax), %rax
movq %rax, 0x30(%rsp)
movq 0x38(%rsp), %rax
movq 0x18(%rax), %rcx
movq 0x38(%rsp), %rax
movq %rcx, 0x20(%rax)
movq 0x30(%rsp), %rcx
movq 0x38(%rsp), %rax
movq %rcx, 0x18(%rax)
jmp 0x4976
movq 0x38(%rsp), %rax
movq 0x18(%rax), %rax
cmpl $0x3, (%rax)
jne 0x4974
movq 0x38(%rsp), %rax
movq 0x20(%rax), %rax
movq %rax, 0x30(%rsp)
movq 0x38(%rsp), %rax
movq 0x18(%rax), %rcx
movq 0x38(%rsp), %rax
movq %rcx, 0x20(%rax)
movq 0x30(%rsp), %rcx
movq 0x38(%rsp), %rax
movq %rcx, 0x18(%rax)
jmp 0x4976
jmp 0x4978
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rax
movq 0x20(%rax), %rsi
callq 0x3770
movq %rax, 0x48(%rsp)
movq %rdx, 0x50(%rsp)
movq 0x40(%rsp), %rax
movq 0x40(%rax), %rax
movq %rax, 0x28(%rsp)
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rax
movq 0x18(%rax), %rsi
callq 0x3770
movq %rax, 0x10(%rsp)
movq %rdx, 0x18(%rsp)
movq 0x40(%rsp), %rax
movq 0x40(%rax), %rax
movq %rax, 0x20(%rsp)
movq 0x10(%rsp), %rax
cmpl $0x8, 0x8(%rax)
jne 0x49e3
movzwl 0x18(%rsp), %eax
cmpl $0x0, %eax
je 0x49f8
movq 0x48(%rsp), %rax
cmpl $0x8, 0x8(%rax)
jne 0x4a10
movzwl 0x50(%rsp), %eax
cmpl $0x0, %eax
jne 0x4a10
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rsi
leaq 0xf0c6(%rip), %rdx      # 0x13acf
movb $0x0, %al
callq 0x2b10
movzwl 0x18(%rsp), %eax
cmpl $0x0, %eax
jle 0x4a46
movzwl 0x50(%rsp), %eax
cmpl $0x0, %eax
jle 0x4a46
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rsi
movq 0x28(%rsp), %rcx
movq 0x20(%rsp), %r8
leaq 0xf0bc(%rip), %rdx      # 0x13afb
movb $0x0, %al
callq 0x2e80
movzwl 0x1a(%rsp), %eax
cmpl $0x0, %eax
jg 0x4a5a
movzwl 0x52(%rsp), %eax
cmpl $0x0, %eax
jle 0x4a72
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rsi
leaq 0xf0ae(%rip), %rdx      # 0x13b19
movb $0x0, %al
callq 0x2e80
movzwl 0x18(%rsp), %eax
cmpl $0x0, %eax
jg 0x4a86
movzwl 0x50(%rsp), %eax
cmpl $0x0, %eax
jle 0x4aca
movq 0x10(%rsp), %rax
cmpl $0x5, 0x8(%rax)
je 0x4ab2
movq 0x10(%rsp), %rax
cmpl $0x6, 0x8(%rax)
je 0x4ab2
movq 0x48(%rsp), %rax
cmpl $0x5, 0x8(%rax)
je 0x4ab2
movq 0x48(%rsp), %rax
cmpl $0x6, 0x8(%rax)
jne 0x4aca
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rsi
leaq 0xf082(%rip), %rdx      # 0x13b45
movb $0x0, %al
callq 0x2b10
movq 0x38(%rsp), %rax
cmpl $0x13, 0x10(%rax)
je 0x4ae0
movq 0x38(%rsp), %rax
cmpl $0x14, 0x10(%rax)
jne 0x4b4b
movzwl 0x50(%rsp), %eax
cmpl $0x0, %eax
jle 0x4b49
movq 0x38(%rsp), %rax
movq 0x18(%rax), %rax
cmpl $0x5, (%rax)
jne 0x4b49
movq 0x38(%rsp), %rax
movq 0x18(%rax), %rax
cmpl $0x2, 0x10(%rax)
jne 0x4b49
movw 0x50(%rsp), %ax
addw $-0x1, %ax
movw %ax, 0x50(%rsp)
leaq 0x48(%rsp), %rdi
callq 0x52e0
movl %eax, 0xc(%rsp)
movl 0xc(%rsp), %eax
movl %eax, %ecx
movq 0x38(%rsp), %rax
movq 0x18(%rax), %rax
imulq 0x18(%rax), %rcx
movq %rcx, 0x18(%rax)
movw 0x50(%rsp), %ax
addw $0x1, %ax
movw %ax, 0x50(%rsp)
jmp 0x4b4b
jmp 0x4b4d
movq 0x48(%rsp), %rax
movq 0x50(%rsp), %rdx
addq $0x58, %rsp
retq
nopl (%rax)