// File: /workspace/github_c_makefile_star2_O1/vtereshkov[P]umka-lang/src/umka_expr.c
// Function: doImplicitTypeConvEx
static void doImplicitTypeConvEx(Compiler *comp, const Type *dest, const Type **src, Const *constant, bool lhs, bool rhs)
{
    // lhs/rhs can only be set to true for operands of binary operators

    // Signed to 64-bit unsigned integer or vice versa (64-bit overflow check only, not applied to operands of binary operators)
    if (!lhs && !rhs && ((dest->kind == TYPE_UINT && typeKindSigned((*src)->kind)) || (typeKindSigned(dest->kind) && (*src)->kind == TYPE_UINT)))
    {
        doOrdinalToOrdinalOrRealToRealConv(comp, dest, src, constant);
    }

    // Integer to real
    else if (typeReal(dest) && typeInteger(*src))
    {
        doIntToRealConv(comp, dest, src, constant, lhs);
    }

    // Character to string
    else if (dest->kind == TYPE_STR && (*src)->kind == TYPE_CHAR)
    {
        doCharToStrConv(comp, dest, src, constant, lhs);
    }

    // Dynamic array to string
    else if (dest->kind == TYPE_STR && (*src)->kind == TYPE_DYNARRAY && (*src)->base->kind == TYPE_CHAR)
    {
        doDynArrayToStrConv(comp, dest, src, constant, lhs);
    }

    // String to dynamic array (not applied to operands of binary operators)
    else if (!lhs && !rhs && dest->kind == TYPE_DYNARRAY && dest->base->kind == TYPE_CHAR && (*src)->kind == TYPE_STR)
    {
        doStrToDynArrayConv(comp, dest, src, constant);
    }

    // Dynamic array to array
    else if (dest->kind == TYPE_ARRAY && (*src)->kind == TYPE_DYNARRAY && typeEquivalent(dest->base, (*src)->base))
    {
        doDynArrayToArrayConv(comp, dest, src, constant, lhs);
    }

    // Array to dynamic array (not applied to operands of binary operators)
    else if (!lhs && !rhs && dest->kind == TYPE_DYNARRAY && (*src)->kind == TYPE_ARRAY && typeEquivalent(dest->base, (*src)->base))
    {
        doArrayToDynArrayConv(comp, dest, src, constant);
    }

    // Concrete to interface or interface to interface
    else if (dest->kind == TYPE_INTERFACE)
    {
        if ((*src)->kind == TYPE_INTERFACE)
        {
            // Interface to interface
            if (!typeEquivalent(dest, *src))
                doInterfaceToInterfaceConv(comp, dest, src, constant);
        }
        else if ((*src)->kind == TYPE_PTR)
        {
            // Pointer to interface
            if ((*src)->base->kind == TYPE_PTR)
                comp->error.handler(comp->error.context, "Pointer base type cannot be a pointer");

            doPtrToInterfaceConv(comp, dest, src, constant);
        }
        else if ((*src)->kind != TYPE_VOID)
        {
            // Value to interface
            doValueToInterfaceConv(comp, dest, src, constant);
        }
    }

    // Pointer to pointer
    else if (dest->kind == TYPE_PTR && (*src)->kind == TYPE_PTR && typeImplicitlyConvertibleBaseTypes(dest->base, (*src)->base))
    {
        *src = dest;
    }

    // Pointer to weak pointer (not applied to operands of binary operators)
    else if (!lhs && !rhs && dest->kind == TYPE_WEAKPTR && (*src)->kind == TYPE_PTR && (typeEquivalent(dest->base, (*src)->base) || (*src)->base->kind == TYPE_NULL))
    {
        doPtrToWeakPtrConv(comp, dest, src, constant);
    }

    // Weak pointer to pointer
    else if (dest->kind == TYPE_PTR && (*src)->kind == TYPE_WEAKPTR && (typeEquivalent(dest->base, (*src)->base) || dest->base->kind == TYPE_NULL))
    {
        doWeakPtrToPtrConv(comp, dest, src, constant, lhs);
    }

    // Function to closure
    else if (dest->kind == TYPE_CLOSURE && (*src)->kind == TYPE_FN && typeEquivalent(dest->field[0]->type, *src))
    {
        doFnToClosureConv(comp, dest, src, constant);
    }

    // Expression list to expression list (not applied to operands of binary operators)
    else if (!lhs && !rhs && typeExprListStruct(dest) && typeExprListStruct(*src) && !typeEquivalent(dest, *src) && dest->numItems == (*src)->numItems)
    {
        doExprListToExprListConv(comp, dest, src, constant);
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movl %r9d, %r13d
movl %r8d, %ebp
movq %rcx, %r12
movq %rdx, %rbx
movq %rsi, %r14
movq %rdi, %r15
orl %r8d, %r13d
jne 0x11c7e
movl (%r14), %eax
cmpl $0xb, %eax
jne 0x11c4f
movq (%rbx), %rcx
movl (%rcx), %ecx
andl $-0x4, %ecx
cmpl $0x4, %ecx
je 0x11c5f
andl $-0x4, %eax
cmpl $0x4, %eax
jne 0x11c7e
movq (%rbx), %rax
cmpl $0xb, (%rax)
jne 0x11c7e
movq %r15, %rdi
movq %r14, %rsi
movq %rbx, %rdx
movq %r12, %rcx
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x12802
movl (%r14), %eax
movl %eax, %ecx
andl $-0x2, %ecx
cmpl $0xe, %ecx
jne 0x11ca2
movq (%rbx), %rdx
movl (%rdx), %ecx
leal -0x4(%rcx), %esi
cmpl $0x7, %esi
ja 0x11ca2
cmpb $0x0, 0x16(%rdx)
je 0x1209c
cmpl $0x14, %eax
jne 0x11d19
movq (%rbx), %rcx
movl (%rcx), %edx
cmpl $0x13, %edx
je 0x11ced
cmpl $0xd, %edx
jne 0x11d19
testq %r12, %r12
je 0x120c6
addq $0xf0, %r15
cmpq $0x0, (%r12)
je 0x121dc
movl $0x1, %esi
movq %r15, %rdi
callq 0xcd54
movb (%r12), %cl
movb %cl, (%rax)
movb $0x0, 0x1(%rax)
jmp 0x121e6
movq 0x8(%rcx), %rcx
cmpl $0xd, (%rcx)
jne 0x11d19
movzbl %bpl, %r8d
movq %r15, %rdi
movq %r14, %rsi
movq %rbx, %rdx
movq %r12, %rcx
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x12919
cmpl $0x13, %eax
setne %cl
orb %r13b, %cl
jne 0x11d54
movq 0x8(%r14), %rcx
cmpl $0xd, (%rcx)
jne 0x11d54
movq (%rbx), %rcx
cmpl $0x14, (%rcx)
jne 0x11d54
movq %r15, %rdi
movq %r14, %rsi
movq %rbx, %rdx
movq %r12, %rcx
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x129c8
cmpl $0x12, %eax
jne 0x11e12
movq (%rbx), %rax
cmpl $0x13, (%rax)
jne 0x11e12
movq 0x8(%r14), %rdi
movq 0x8(%rax), %rsi
callq 0x1ef64
testb %al, %al
je 0x11e12
testq %r12, %r12
je 0x11d9a
movq 0x5118(%r15), %rdi
leaq 0x65af4(%rip), %rsi     # 0x77885
xorl %eax, %eax
callq *0x50f8(%r15)
testb %bpl, %bpl
je 0x11dab
leaq 0x4e70(%r15), %rdi
callq 0x1827d
leaq 0x4e38(%r15), %r13
leaq 0x4e18(%r15), %rsi
movq %rsi, 0x8(%rsp)
leaq 0x4220(%r15), %rdx
movq %rdx, 0x10(%rsp)
movq %r13, %rdi
movq %r14, %rcx
callq 0x1a2d1
leaq 0x4e70(%r15), %r12
movq %r12, %rdi
movl %eax, %esi
callq 0x17f78
movq %r12, %rdi
movq %r14, %rsi
movl $0x19, %edx
callq 0x18ec4
addq $0x100, %r15            # imm = 0x100
movq %r13, %rdi
movq 0x8(%rsp), %rsi
movq %r15, %rdx
movq 0x10(%rsp), %rcx
jmp 0x1210d
testb %r13b, %r13b
jne 0x11e7d
cmpl $0x13, (%r14)
jne 0x11e7d
movq (%rbx), %rax
cmpl $0x12, (%rax)
jne 0x11e7d
movq 0x8(%r14), %rdi
movq 0x8(%rax), %rsi
callq 0x1ef64
testb %al, %al
je 0x11e7d
testq %r12, %r12
je 0x121fc
addq $0xf0, %r15
movq (%rbx), %rax
movslq 0x10(%rax), %rdx
movq %r15, %rdi
movq %r14, %rsi
callq 0xcd80
movq %rax, %r15
movq 0x10(%rax), %rdi
movq (%r12), %rsi
movq (%rbx), %rax
movslq 0x10(%rax), %rdx
imulq 0x8(%r15), %rdx
callq 0x3260
movq %r15, (%r12)
jmp 0x121ea
movl (%r14), %eax
cmpl $0x10, %eax
je 0x11ed9
cmpl $0x17, %eax
jne 0x11efb
movq (%rbx), %rsi
movl (%rsi), %eax
cmpl $0x2, %eax
je 0x121ed
cmpl $0x10, %eax
je 0x1215b
cmpl $0x17, %eax
jne 0x1217d
movq %r14, %rdi
callq 0x1ef64
testb %al, %al
jne 0x121ed
movq %r15, %rdi
movq %r14, %rsi
movq %rbx, %rdx
movq %r12, %rcx
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x16931
movq (%rbx), %rcx
cmpl $0x10, (%rcx)
jne 0x11efb
movq 0x8(%r14), %rdx
cmpl $0x2, (%rdx)
je 0x121ea
movq 0x8(%rcx), %rcx
cmpl $0x3, (%rcx)
je 0x121ea
cmpl $0x11, %eax
setne %al
orb %r13b, %al
jne 0x11f5b
movq (%rbx), %rax
cmpl $0x10, (%rax)
jne 0x11f5b
movq 0x8(%r14), %rdi
movq 0x8(%rax), %rsi
callq 0x1ef64
testb %al, %al
jne 0x11f2b
movq (%rbx), %rax
movq 0x8(%rax), %rax
cmpl $0x3, (%rax)
jne 0x11f5b
testq %r12, %r12
je 0x11f47
movq 0x5118(%r15), %rdi
leaq 0x65a35(%rip), %rsi     # 0x77973
xorl %eax, %eax
callq *0x50f8(%r15)
addq $0x4e70, %r15           # imm = 0x4E70
movq %r15, %rdi
callq 0x18b23
jmp 0x121ea
cmpl $0x10, (%r14)
jne 0x11fd0
movq (%rbx), %rax
cmpl $0x11, (%rax)
jne 0x11fd0
movq 0x8(%r14), %rdi
movq 0x8(%rax), %rsi
callq 0x1ef64
testb %al, %al
jne 0x11f83
movq 0x8(%r14), %rax
cmpl $0x3, (%rax)
jne 0x11fd0
testq %r12, %r12
je 0x11f9f
movq 0x5118(%r15), %rdi
leaq 0x65a1f(%rip), %rsi     # 0x779b5
xorl %eax, %eax
callq *0x50f8(%r15)
testb %bpl, %bpl
je 0x11fb0
leaq 0x4e70(%r15), %rdi
callq 0x1827d
addq $0x4e70, %r15           # imm = 0x4E70
movq %r15, %rdi
callq 0x18b2f
testb %bpl, %bpl
je 0x121ea
movq %r15, %rdi
jmp 0x12138
cmpl $0x18, (%r14)
jne 0x12014
movq (%rbx), %rsi
cmpl $0x1a, (%rsi)
jne 0x12014
movq 0x28(%r14), %rax
movq (%rax), %rax
movq 0x108(%rax), %rdi
callq 0x1ef64
testb %al, %al
je 0x12014
movq %r15, %rdi
movq %r14, %rsi
movq %rbx, %rdx
movq %r12, %rcx
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x16e9d
testb %r13b, %r13b
jne 0x121ed
cmpl $0x16, (%r14)
jne 0x121ed
cmpb $0x1, 0x14(%r14)
jne 0x121ed
cmpl $0x0, 0x10(%r14)
jle 0x121ed
movq (%rbx), %rsi
cmpl $0x16, (%rsi)
jne 0x121ed
cmpb $0x1, 0x14(%rsi)
jne 0x121ed
cmpl $0x0, 0x10(%rsi)
jle 0x121ed
movq %r14, %rdi
callq 0x1ef64
testb %al, %al
jne 0x121ed
movl 0x10(%r14), %eax
movq (%rbx), %rcx
cmpl 0x10(%rcx), %eax
jne 0x121ed
movq %r15, %rdi
movq %r14, %rsi
movq %rbx, %rdx
movq %r12, %rcx
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x16f4e
movzbl %bpl, %r8d
orl $0x6, %r8d
testq %r12, %r12
je 0x12142
addq $0x4e68, %r15           # imm = 0x4E68
movq %r15, %rdi
movq %r12, %rsi
xorl %edx, %edx
callq 0xf7f6
jmp 0x121ea
testb %bpl, %bpl
je 0x120d7
leaq 0x4e70(%r15), %rdi
callq 0x1827d
leaq 0x4e70(%r15), %r12
movq (%rbx), %rsi
movq %r12, %rdi
movl $0x1a, %edx
callq 0x18ec4
leaq 0x4e38(%r15), %rdi
leaq 0x4e18(%r15), %rsi
leaq 0x100(%r15), %rdx
addq $0x4220, %r15           # imm = 0x4220
movq %r15, %rcx
movq %r14, %r8
movl $0x1, %r9d
callq 0x1a429
movl 0x120(%rax), %edx
movq %r12, %rdi
movq %r14, %rsi
callq 0x196d8
testb %bpl, %bpl
je 0x121ea
movq %r12, %rdi
callq 0x1827d
jmp 0x121ea
addq $0x4e70, %r15           # imm = 0x4E70
movq %r15, %rdi
movl %ecx, %esi
movl %r8d, %edx
callq 0x18cbb
jmp 0x121ea
movq 0x8(%rsi), %rax
cmpl $0x10, (%rax)
jne 0x121bd
movq 0x5118(%r15), %rdi
leaq 0x656ed(%rip), %rsi     # 0x7785f
xorl %eax, %eax
callq *0x50f8(%r15)
jmp 0x121bd
testq %r12, %r12
je 0x12199
movq 0x5118(%r15), %rdi
leaq 0x65730(%rip), %rsi     # 0x778c0
xorl %eax, %eax
callq *0x50f8(%r15)
leaq 0x4e18(%r15), %rdi
leaq 0x4220(%r15), %rsi
movq (%rbx), %rdx
callq 0x1edd3
movq %rax, (%rbx)
movq %r15, %rdi
movq %rax, %rsi
callq 0x170f1
movq %r15, %rdi
movq %r14, %rsi
movq %rbx, %rdx
movq %r12, %rcx
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x16bb8
movq %r15, %rdi
xorl %esi, %esi
callq 0xcd54
movq %rax, (%r12)
movq %r14, (%rbx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x4e38(%r15), %r13
leaq 0x4e18(%r15), %rsi
movq %rsi, 0x8(%rsp)
leaq 0x4220(%r15), %rdx
movq %rdx, 0x10(%rsp)
movq %r13, %rdi
movq %r14, %rcx
callq 0x1a2d1
movl %eax, %ebp
leaq 0x4e70(%r15), %r12
movq (%rbx), %rax
movslq 0x10(%rax), %rsi
movq %r12, %rdi
callq 0x17eca
movq %r12, %rdi
movl %ebp, %esi
callq 0x17f78
movq %r12, %rdi
movq %r14, %rsi
movl $0x17, %edx
callq 0x18ec4
addq $0x100, %r15            # imm = 0x100
movq %r13, %rdi
movq 0x8(%rsp), %rsi
movq %r15, %rdx
movq 0x10(%rsp), %rcx
movq %r14, %r8
movl $0x1, %r9d
callq 0x1a429
movl 0x120(%rax), %edx
movq %r12, %rdi
movq %r14, %rsi
callq 0x196d8
jmp 0x121ea