// File: /workspace/github_c_makefile_star2_O3/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
movl (%rsi), %eax
je 0xcb32
movl %eax, %ecx
andl $-0x2, %ecx
cmpl $0xe, %ecx
jne 0xcb49
movq (%rbx), %rdx
movl (%rdx), %ecx
leal -0x4(%rcx), %esi
cmpl $0x7, %esi
ja 0xce2a
cmpb $0x0, 0x16(%rdx)
jne 0xce2a
movzbl %bpl, %r8d
orl $0x6, %r8d
testq %r12, %r12
je 0xcd10
addq $0x4e68, %r15           # imm = 0x4E68
movq %r15, %rdi
movq %r12, %rsi
xorl %edx, %edx
callq 0xa608
jmp 0xd161
cmpl $0xb, %eax
jne 0xcba0
movq (%rbx), %rax
movl (%rax), %eax
andl $-0x4, %eax
cmpl $0x4, %eax
je 0xcbba
jmp 0xd164
cmpl $0x14, %eax
jne 0xcbd9
movq (%rbx), %rsi
movl (%rsi), %eax
cmpl $0x13, %eax
je 0xcce0
cmpl $0xd, %eax
jne 0xd0f5
testq %r12, %r12
je 0xcd29
addq $0xf0, %r15
cmpq $0x0, (%r12)
je 0xcda0
movl $0x1, %esi
movq %r15, %rdi
callq 0x7b1c
movb (%r12), %cl
movb %cl, (%rax)
movb $0x0, 0x1(%rax)
jmp 0xcdaa
movl %eax, %ecx
andl $-0x4, %ecx
cmpl $0x4, %ecx
jne 0xcae3
movq (%rbx), %rcx
cmpl $0xb, (%rcx)
jne 0xcae3
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 0xd6ed
cmpl $0x13, %eax
setne %cl
orb %r13b, %cl
je 0xcca6
cmpl $0x12, %eax
jne 0xcdb6
movq (%rbx), %rax
cmpl $0x13, (%rax)
jne 0xd0f5
movq 0x8(%r14), %rdi
movq 0x8(%rax), %rsi
callq 0x19f7d
testb %al, %al
je 0xcdb3
testq %r12, %r12
je 0xcc2e
movq 0x5118(%r15), %rdi
leaq 0x69c60(%rip), %rsi     # 0x76885
xorl %eax, %eax
callq *0x50f8(%r15)
testb %bpl, %bpl
je 0xcc3f
leaq 0x4e70(%r15), %rdi
callq 0x1327f
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 0x15267
leaq 0x4e70(%r15), %r12
movq %r12, %rdi
movl %eax, %esi
callq 0x12f97
movq %r12, %rdi
movq %r14, %rsi
movl $0x19, %edx
callq 0x13e7c
addq $0x100, %r15            # imm = 0x100
movq %r13, %rdi
movq 0x8(%rsp), %rsi
movq %r15, %rdx
movq 0x10(%rsp), %rcx
jmp 0xcd70
movq 0x8(%r14), %rax
cmpl $0xd, (%rax)
movq (%rbx), %rax
jne 0xcdc4
movl (%rax), %ecx
cmpl $0x14, %ecx
jne 0xcdc6
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 0xd8e0
movq 0x8(%rsi), %rax
cmpl $0xd, (%rax)
jne 0xd0f5
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 0xd831
addq $0x4e70, %r15           # imm = 0x4E70
movq %r15, %rdi
movl %ecx, %esi
movl %r8d, %edx
callq 0x13c9c
jmp 0xd161
testb %bpl, %bpl
je 0xcd3d
leaq 0x4e70(%r15), %rdi
callq 0x1327f
movq (%rbx), %rsi
leaq 0x4e70(%r15), %r12
movq %r12, %rdi
movl $0x1a, %edx
callq 0x13e7c
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 0x153ba
movl 0x120(%rax), %edx
movq %r12, %rdi
movq %r14, %rsi
callq 0x14698
testb %bpl, %bpl
je 0xd161
movq %r12, %rdi
jmp 0xd0ee
movq %r15, %rdi
xorl %esi, %esi
callq 0x7b1c
movq %rax, (%r12)
jmp 0xd161
movl (%r14), %eax
cmpl $0x13, %eax
setne %cl
orb %r13b, %cl
jne 0xce2a
movq (%rbx), %rax
movl (%rax), %ecx
cmpl $0x12, %ecx
jne 0xd0f5
movq 0x8(%r14), %rdi
movq 0x8(%rax), %rsi
callq 0x19f7d
testb %al, %al
je 0xce27
testq %r12, %r12
je 0xcfeb
addq $0xf0, %r15
movq (%rbx), %rax
movslq 0x10(%rax), %rdx
movq %r15, %rdi
movq %r14, %rsi
callq 0x7b48
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 0xd161
movl (%r14), %eax
cmpl $0x10, %eax
je 0xce86
cmpl $0x17, %eax
jne 0xceb3
movq (%rbx), %rdx
movl (%rdx), %eax
cmpl $0x2, %eax
je 0xd164
cmpl $0x10, %eax
je 0xcf6a
cmpl $0x17, %eax
jne 0xcf8c
movq %r14, %rdi
movq %rdx, %rsi
callq 0x19f7d
testb %al, %al
jne 0xd164
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 0x11968
movq (%rbx), %rcx
movl (%rcx), %eax
cmpl $0x10, %eax
jne 0xd090
movq 0x8(%r14), %rax
cmpl $0x2, (%rax)
je 0xd161
movq 0x8(%rcx), %rax
cmpl $0x3, (%rax)
je 0xd161
jmp 0xd0f5
cmpl $0x11, %eax
setne %cl
orb %r13b, %cl
je 0xcf0d
cmpl $0x18, %eax
jne 0xd0f5
movq (%rbx), %rsi
cmpl $0x1a, (%rsi)
jne 0xd0f5
movq 0x28(%r14), %rax
movq (%rax), %rax
movq 0x108(%rax), %rdi
callq 0x19f7d
testb %al, %al
je 0xd0f5
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 0x11ed4
movq (%rbx), %rax
cmpl $0x10, (%rax)
jne 0xd0f5
movq 0x8(%r14), %rdi
movq 0x8(%rax), %rsi
callq 0x19f7d
testb %al, %al
jne 0xcf3a
movq (%rbx), %rcx
movq 0x8(%rcx), %rax
cmpl $0x3, (%rax)
jne 0xd082
testq %r12, %r12
je 0xcf56
movq 0x5118(%r15), %rdi
leaq 0x69a26(%rip), %rsi     # 0x76973
xorl %eax, %eax
callq *0x50f8(%r15)
addq $0x4e70, %r15           # imm = 0x4E70
movq %r15, %rdi
callq 0x13af2
jmp 0xd161
movq 0x8(%rdx), %rax
cmpl $0x10, (%rax)
jne 0xcfcc
movq 0x5118(%r15), %rdi
leaq 0x698de(%rip), %rsi     # 0x7685f
xorl %eax, %eax
callq *0x50f8(%r15)
jmp 0xcfcc
testq %r12, %r12
je 0xcfab
movq 0x5118(%r15), %rdi
leaq 0x69921(%rip), %rsi     # 0x768c0
xorl %eax, %eax
callq *0x50f8(%r15)
movq (%rbx), %rdx
leaq 0x4e18(%r15), %rdi
leaq 0x4220(%r15), %rsi
callq 0x19e01
movq %rax, (%rbx)
movq %r15, %rdi
movq %rax, %rsi
callq 0x12128
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 0x11bef
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 0x15267
movl %eax, %ebp
leaq 0x4e70(%r15), %r12
movq (%rbx), %rax
movslq 0x10(%rax), %rsi
movq %r12, %rdi
callq 0x12ef1
movq %r12, %rdi
movl %ebp, %esi
callq 0x12f97
movq %r12, %rdi
movq %r14, %rsi
movl $0x17, %edx
callq 0x13e7c
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 0x153ba
movl 0x120(%rax), %edx
movq %r12, %rdi
movq %r14, %rsi
callq 0x14698
jmp 0xd161
movl (%r14), %eax
cmpl $0x10, %eax
jne 0xcebe
movl (%rcx), %eax
cmpl $0x11, %eax
jne 0xd0f5
movq 0x8(%r14), %rdi
movq 0x8(%rcx), %rsi
callq 0x19f7d
testb %al, %al
jne 0xd0b3
movq 0x8(%r14), %rax
cmpl $0x3, (%rax)
jne 0xd173
testq %r12, %r12
je 0xd0cf
movq 0x5118(%r15), %rdi
leaq 0x698ef(%rip), %rsi     # 0x769b5
xorl %eax, %eax
callq *0x50f8(%r15)
addq $0x4e70, %r15           # imm = 0x4E70
testb %bpl, %bpl
je 0xd159
movq %r15, %rdi
callq 0x1327f
movq %r15, %rdi
callq 0x13afe
movq %r15, %rdi
callq 0x1327f
jmp 0xd161
testb %r13b, %r13b
jne 0xd164
cmpl $0x16, (%r14)
jne 0xd164
cmpb $0x1, 0x14(%r14)
jne 0xd164
cmpl $0x0, 0x10(%r14)
jle 0xd164
movq (%rbx), %rsi
cmpl $0x16, (%rsi)
jne 0xd164
cmpb $0x1, 0x14(%rsi)
jne 0xd164
cmpl $0x0, 0x10(%rsi)
jle 0xd164
movq %r14, %rdi
callq 0x19f7d
testb %al, %al
jne 0xd164
movl 0x10(%r14), %eax
movq (%rbx), %rcx
cmpl 0x10(%rcx), %eax
jne 0xd164
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 0x11f85
movq %r15, %rdi
callq 0x13afe
movq %r14, (%rbx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl (%r14), %eax
jmp 0xcebe