// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x50, %rsp
movl %r8d, -0x44(%rbp)
movq %rcx, %rax
movl -0x44(%rbp), %ecx
movq %rax, -0x40(%rbp)
movq %rdx, %rax
movq -0x40(%rbp), %rdx
movq %rax, -0x38(%rbp)
movq %rsi, %rax
movq -0x38(%rbp), %rsi
movq %rax, -0x30(%rbp)
movq %rdi, %r8
movq -0x30(%rbp), %rdi
movb %r9b, %al
movq %r8, -0x8(%rbp)
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
andb $0x1, %cl
movb %cl, -0x21(%rbp)
andb $0x1, %al
movb %al, -0x22(%rbp)
testb $0x1, -0x21(%rbp)
jne 0xd27f
testb $0x1, -0x22(%rbp)
jne 0xd27f
movq -0x10(%rbp), %rax
cmpl $0xb, (%rax)
jne 0xd248
movq -0x18(%rbp), %rax
movq (%rax), %rax
movl (%rax), %edi
callq 0xf4a0
testb $0x1, %al
jne 0xd265
movq -0x10(%rbp), %rax
movl (%rax), %edi
callq 0xf4a0
testb $0x1, %al
jne 0xd259
jmp 0xd27f
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpl $0xb, (%rax)
jne 0xd27f
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0xd930
jmp 0xd6d8
movq -0x10(%rbp), %rdi
callq 0xcf80
testb $0x1, %al
jne 0xd28e
jmp 0xd2c3
movq -0x18(%rbp), %rax
movq (%rax), %rdi
callq 0xf4e0
testb $0x1, %al
jne 0xd2a0
jmp 0xd2c3
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
movb -0x21(%rbp), %al
andb $0x1, %al
movzbl %al, %r8d
callq 0xf520
jmp 0xd6d6
movq -0x10(%rbp), %rax
cmpl $0x14, (%rax)
jne 0xd2fb
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpl $0xd, (%rax)
jne 0xd2fb
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
movb -0x21(%rbp), %al
andb $0x1, %al
movzbl %al, %r8d
callq 0xf5c0
jmp 0xd6d4
movq -0x10(%rbp), %rax
cmpl $0x14, (%rax)
jne 0xd343
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpl $0x13, (%rax)
jne 0xd343
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rax
cmpl $0xd, (%rax)
jne 0xd343
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
movb -0x21(%rbp), %al
andb $0x1, %al
movzbl %al, %r8d
callq 0xdb70
jmp 0xd6d2
testb $0x1, -0x21(%rbp)
jne 0xd38b
testb $0x1, -0x22(%rbp)
jne 0xd38b
movq -0x10(%rbp), %rax
cmpl $0x13, (%rax)
jne 0xd38b
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
cmpl $0xd, (%rax)
jne 0xd38b
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpl $0x14, (%rax)
jne 0xd38b
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0xdc20
jmp 0xd6d0
movq -0x10(%rbp), %rax
cmpl $0x12, (%rax)
jne 0xd3e1
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpl $0x13, (%rax)
jne 0xd3e1
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rsi
callq 0x22250
testb $0x1, %al
jne 0xd3be
jmp 0xd3e1
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
movb -0x21(%rbp), %al
andb $0x1, %al
movzbl %al, %r8d
callq 0xf6c0
jmp 0xd6ce
testb $0x1, -0x21(%rbp)
jne 0xd43a
testb $0x1, -0x22(%rbp)
jne 0xd43a
movq -0x10(%rbp), %rax
cmpl $0x13, (%rax)
jne 0xd43a
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpl $0x12, (%rax)
jne 0xd43a
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rsi
callq 0x22250
testb $0x1, %al
jne 0xd420
jmp 0xd43a
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0xf7b0
jmp 0xd6cc
movq -0x10(%rbp), %rax
cmpl $0x17, (%rax)
jne 0xd4fc
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpl $0x17, (%rax)
jne 0xd47e
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rsi
callq 0x22250
testb $0x1, %al
jne 0xd47c
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0xf8c0
jmp 0xd4f7
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpl $0x10, (%rax)
jne 0xd4d2
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rax
cmpl $0x10, (%rax)
jne 0xd4bb
movq -0x8(%rbp), %rax
movq 0x50f8(%rax), %rcx
movq -0x8(%rbp), %rax
movq 0x5118(%rax), %rdi
leaq 0x1cb490(%rip), %rsi    # 0x1d8947
movb $0x0, %al
callq *%rcx
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0xfc40
jmp 0xd4f5
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpl $0x2, (%rax)
je 0xd4f3
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0x10050
jmp 0xd4f5
jmp 0xd4f7
jmp 0xd6ca
movq -0x10(%rbp), %rax
cmpl $0x10, (%rax)
jne 0xd53f
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpl $0x10, (%rax)
jne 0xd53f
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rsi
callq 0x100f0
testb $0x1, %al
jne 0xd52f
jmp 0xd53f
movq -0x10(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
jmp 0xd6c8
testb $0x1, -0x21(%rbp)
jne 0xd5a6
testb $0x1, -0x22(%rbp)
jne 0xd5a6
movq -0x10(%rbp), %rax
cmpl $0x11, (%rax)
jne 0xd5a6
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpl $0x10, (%rax)
jne 0xd5a6
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rsi
callq 0x22250
testb $0x1, %al
jne 0xd58c
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rax
cmpl $0x3, (%rax)
jne 0xd5a6
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0x10120
jmp 0xd6c6
movq -0x10(%rbp), %rax
cmpl $0x10, (%rax)
jne 0xd607
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpl $0x11, (%rax)
jne 0xd607
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rsi
callq 0x22250
testb $0x1, %al
jne 0xd5e4
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
cmpl $0x3, (%rax)
jne 0xd607
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
movb -0x21(%rbp), %al
andb $0x1, %al
movzbl %al, %r8d
callq 0x10190
jmp 0xd6c4
movq -0x10(%rbp), %rax
cmpl $0x18, (%rax)
jne 0xd657
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpl $0x1a, (%rax)
jne 0xd657
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq (%rax), %rax
movq 0x108(%rax), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rsi
callq 0x22250
testb $0x1, %al
jne 0xd640
jmp 0xd657
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0x10230
jmp 0xd6c2
testb $0x1, -0x21(%rbp)
jne 0xd6c0
testb $0x1, -0x22(%rbp)
jne 0xd6c0
movq -0x10(%rbp), %rdi
callq 0xf380
testb $0x1, %al
jne 0xd672
jmp 0xd6c0
movq -0x18(%rbp), %rax
movq (%rax), %rdi
callq 0xf380
testb $0x1, %al
jne 0xd684
jmp 0xd6c0
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rsi
callq 0x22250
testb $0x1, %al
jne 0xd6c0
movq -0x10(%rbp), %rax
movl 0x10(%rax), %eax
movq -0x18(%rbp), %rcx
movq (%rcx), %rcx
cmpl 0x10(%rcx), %eax
jne 0xd6c0
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0x10340
jmp 0xd6c2
jmp 0xd6c4
jmp 0xd6c6
jmp 0xd6c8
jmp 0xd6ca
jmp 0xd6cc
jmp 0xd6ce
jmp 0xd6d0
jmp 0xd6d2
jmp 0xd6d4
jmp 0xd6d6
jmp 0xd6d8
addq $0x50, %rsp
popq %rbp
retq
nop