// File: /workspace/github_c_makefile_star2_O0/vtereshkov[P]umka-lang/src/umka_ident.c
// Function: identAdd
static Ident *identAdd(Idents *idents, const Modules *modules, const Blocks *blocks, IdentKind kind, const char *name, const Type *type, bool exported)
{
    const Type *rcvType = NULL;
    if (type->kind == TYPE_FN && type->sig.isMethod)
        rcvType = type->sig.param[0]->type;

    const Ident *existingIdent = identFindEx(idents, modules, blocks, blocks->module, name, rcvType, false, kind == IDENT_MODULE);

    if (existingIdent)
    {
        if (existingIdent->block == blocks->item[blocks->top].block)
        {
            // Forward type declaration resolution
            if (existingIdent->kind == IDENT_TYPE && existingIdent->type->kind == TYPE_FORWARD &&
                kind == IDENT_TYPE && type->kind != TYPE_FORWARD &&
                strcmp(existingIdent->type->typeIdent->name, name) == 0)
            {
                Ident *modifiableIdent = (Ident *)existingIdent;
                Type *modifiableType = (Type *)type;
                Type *modifiableIdentType = (Type *)existingIdent->type;

                modifiableType->typeIdent = existingIdent;
                typeDeepCopy(idents->storage, modifiableIdentType, type);
                modifiableIdent->exported = exported;

                return modifiableIdent;
            }

            // Function prototype resolution
            if (existingIdent->kind == IDENT_CONST && existingIdent->type->kind == TYPE_FN &&
                kind == IDENT_CONST && type->kind == TYPE_FN &&
                existingIdent->exported == exported &&
                strcmp(existingIdent->name, name) == 0 &&
                typeCompatible(existingIdent->type, type) &&
                existingIdent->prototypeOffset >= 0)
            {
                Ident *modifiableIdent = (Ident *)existingIdent;
                Type *modifiableIdentType = (Type *)existingIdent->type;

                typeDeepCopy(idents->storage, modifiableIdentType, type);

                return modifiableIdent;
            }

            idents->error->handler(idents->error->context, "Duplicate identifier %s", name);
        }
        else if (!identIsHidden(name) && !identIsPlaceholder(name) && existingIdent->block != 0 && !identIsOuterLocalVar(blocks, existingIdent))
        {
            idents->error->warningHandler(idents->error->context, idents->debug, "Shadowed identifier %s", name);
        }
    }

    if (exported && blocks->top != 0)
        idents->error->handler(idents->error->context, "Local identifier %s cannot be exported", name);

    if (kind == IDENT_CONST || kind == IDENT_VAR)
    {
        if (type->kind == TYPE_FORWARD)
            idents->error->handler(idents->error->context, "Unresolved forward type declaration for %s", name);

        if (type->kind == TYPE_VOID)
            idents->error->handler(idents->error->context, "Void variable or constant %s is not allowed", name);
    }

    Ident *ident = storageAdd(idents->storage, sizeof(Ident));
    ident->kind = kind;

    strncpy(ident->name, name, MAX_IDENT_LEN);
    ident->name[MAX_IDENT_LEN] = 0;

    ident->hash = hash(name);

    ident->type              = type;
    ident->module            = blocks->module;
    ident->block             = blocks->item[blocks->top].block;
    ident->exported          = exported;
    ident->globallyAllocated = false;
    ident->temporary         = false;
    ident->used              = exported || ident->module == 0 || identIsHidden(ident->name) || identIsPlaceholder(ident->name) || identIsMain(ident);  // Exported, predefined, hidden, placeholder identifiers and main() are always treated as used
    ident->prototypeOffset   = -1;
    ident->debug             = *(idents->debug);

    ident->next   = idents->first;
    idents->first = ident;

    return ident;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movb 0x10(%rbp), %al
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movl %ecx, -0x24(%rbp)
movq %r8, -0x30(%rbp)
movq %r9, -0x38(%rbp)
andb $0x1, %al
movb %al, -0x39(%rbp)
movq $0x0, -0x48(%rbp)
movq -0x38(%rbp), %rax
cmpl $0x1a, (%rax)
jne 0x19b58
movq -0x38(%rbp), %rax
testb $0x1, 0x30(%rax)
je 0x19b58
movq -0x38(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x108(%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
movq -0x20(%rbp), %rax
movl 0x968(%rax), %ecx
movq -0x30(%rbp), %r8
movq -0x48(%rbp), %r9
cmpl $0x4, -0x24(%rbp)
sete %al
xorl %r10d, %r10d
movzbl %al, %r10d
andl $0x1, %r10d
movq %rsp, %rax
movl %r10d, 0x8(%rax)
movl $0x0, (%rax)
callq 0x195e0
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
je 0x19de1
movq -0x50(%rbp), %rax
movl 0x114(%rax), %eax
movq -0x20(%rbp), %rcx
movq -0x20(%rbp), %rdx
movslq 0x964(%rdx), %rdx
imulq $0x18, %rdx, %rdx
addq %rdx, %rcx
cmpl (%rcx), %eax
jne 0x19d75
movq -0x50(%rbp), %rax
cmpl $0x2, (%rax)
jne 0x19c83
movq -0x50(%rbp), %rax
movq 0x108(%rax), %rax
cmpl $0x1, (%rax)
jne 0x19c83
cmpl $0x2, -0x24(%rbp)
jne 0x19c83
movq -0x38(%rbp), %rax
cmpl $0x1, (%rax)
je 0x19c83
movq -0x50(%rbp), %rax
movq 0x108(%rax), %rax
movq 0x18(%rax), %rdi
addq $0x4, %rdi
movq -0x30(%rbp), %rsi
callq 0x3220
cmpl $0x0, %eax
jne 0x19c83
movq -0x50(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x50(%rbp), %rax
movq 0x108(%rax), %rax
movq %rax, -0x68(%rbp)
movq -0x50(%rbp), %rcx
movq -0x60(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x68(%rbp), %rsi
movq -0x38(%rbp), %rdx
callq 0x21d40
movb -0x39(%rbp), %cl
movq -0x58(%rbp), %rax
andb $0x1, %cl
movb %cl, 0x118(%rax)
movq -0x58(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x1a022
movq -0x50(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x19d4d
movq -0x50(%rbp), %rax
movq 0x108(%rax), %rax
cmpl $0x1a, (%rax)
jne 0x19d4d
cmpl $0x0, -0x24(%rbp)
jne 0x19d4d
movq -0x38(%rbp), %rax
cmpl $0x1a, (%rax)
jne 0x19d4d
movq -0x50(%rbp), %rax
movb 0x118(%rax), %al
andb $0x1, %al
movzbl %al, %eax
movb -0x39(%rbp), %cl
andb $0x1, %cl
movzbl %cl, %ecx
cmpl %ecx, %eax
jne 0x19d4d
movq -0x50(%rbp), %rdi
addq $0x4, %rdi
movq -0x30(%rbp), %rsi
callq 0x3220
cmpl $0x0, %eax
jne 0x19d4d
movq -0x50(%rbp), %rax
movq 0x108(%rax), %rdi
movq -0x38(%rbp), %rsi
callq 0x22790
testb $0x1, %al
jne 0x19d07
jmp 0x19d4d
movq -0x50(%rbp), %rax
cmpl $0x0, 0x11c(%rax)
jl 0x19d4d
movq -0x50(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x50(%rbp), %rax
movq 0x108(%rax), %rax
movq %rax, -0x78(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x78(%rbp), %rsi
movq -0x38(%rbp), %rdx
callq 0x21d40
movq -0x70(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x1a022
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x20(%rax), %rdi
movq -0x30(%rbp), %rdx
leaq 0x1bf4f5(%rip), %rsi    # 0x1d9264
movb $0x0, %al
callq *%rcx
jmp 0x19ddf
movq -0x30(%rbp), %rdi
callq 0x1a980
testb $0x1, %al
jne 0x19ddd
movq -0x30(%rbp), %rdi
callq 0x1a9a0
testb $0x1, %al
jne 0x19ddd
movq -0x50(%rbp), %rax
cmpl $0x0, 0x114(%rax)
je 0x19ddd
movq -0x20(%rbp), %rdi
movq -0x50(%rbp), %rsi
callq 0x199e0
testb $0x1, %al
jne 0x19ddd
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x10(%rax), %r8
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x20(%rax), %rdi
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rsi
movq -0x30(%rbp), %rcx
leaq 0x1bf4a4(%rip), %rdx    # 0x1d927c
movb $0x0, %al
callq *%r8
jmp 0x19ddf
jmp 0x19de1
testb $0x1, -0x39(%rbp)
je 0x19e1a
movq -0x20(%rbp), %rax
cmpl $0x0, 0x964(%rax)
je 0x19e1a
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x20(%rax), %rdi
movq -0x30(%rbp), %rdx
leaq 0x1bf47d(%rip), %rsi    # 0x1d9293
movb $0x0, %al
callq *%rcx
cmpl $0x0, -0x24(%rbp)
je 0x19e26
cmpl $0x1, -0x24(%rbp)
jne 0x19e86
movq -0x38(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x19e55
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x20(%rax), %rdi
movq -0x30(%rbp), %rdx
leaq 0x1bf469(%rip), %rsi    # 0x1d92ba
movb $0x0, %al
callq *%rcx
movq -0x38(%rbp), %rax
cmpl $0x2, (%rax)
jne 0x19e84
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x20(%rax), %rdi
movq -0x30(%rbp), %rdx
leaq 0x1bf465(%rip), %rsi    # 0x1d92e5
movb $0x0, %al
callq *%rcx
jmp 0x19e86
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
movl $0x148, %esi            # imm = 0x148
callq 0x4b20
movq %rax, -0x80(%rbp)
movl -0x24(%rbp), %ecx
movq -0x80(%rbp), %rax
movl %ecx, (%rax)
movq -0x80(%rbp), %rdi
addq $0x4, %rdi
movq -0x30(%rbp), %rsi
movl $0xff, %edx
callq 0x3080
movq -0x80(%rbp), %rax
movb $0x0, 0x103(%rax)
movq -0x30(%rbp), %rdi
callq 0x1a8f0
movl %eax, %ecx
movq -0x80(%rbp), %rax
movl %ecx, 0x104(%rax)
movq -0x38(%rbp), %rcx
movq -0x80(%rbp), %rax
movq %rcx, 0x108(%rax)
movq -0x20(%rbp), %rax
movl 0x968(%rax), %ecx
movq -0x80(%rbp), %rax
movl %ecx, 0x110(%rax)
movq -0x20(%rbp), %rax
movq -0x20(%rbp), %rcx
movslq 0x964(%rcx), %rcx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movl (%rax), %ecx
movq -0x80(%rbp), %rax
movl %ecx, 0x114(%rax)
movb -0x39(%rbp), %cl
movq -0x80(%rbp), %rax
andb $0x1, %cl
movb %cl, 0x118(%rax)
movq -0x80(%rbp), %rax
movb $0x0, 0x119(%rax)
movq -0x80(%rbp), %rax
movb $0x0, 0x11b(%rax)
movb $0x1, %al
testb $0x1, -0x39(%rbp)
movb %al, -0x81(%rbp)
jne 0x19fb0
movq -0x80(%rbp), %rcx
movb $0x1, %al
cmpl $0x0, 0x110(%rcx)
movb %al, -0x81(%rbp)
je 0x19fb0
movq -0x80(%rbp), %rdi
addq $0x4, %rdi
callq 0x1a980
movb %al, %cl
movb $0x1, %al
testb $0x1, %cl
movb %al, -0x81(%rbp)
jne 0x19fb0
movq -0x80(%rbp), %rdi
addq $0x4, %rdi
callq 0x1a9a0
movb %al, %cl
movb $0x1, %al
testb $0x1, %cl
movb %al, -0x81(%rbp)
jne 0x19fb0
movq -0x80(%rbp), %rdi
callq 0x1a840
movb %al, -0x81(%rbp)
movb -0x81(%rbp), %cl
movq -0x80(%rbp), %rax
andb $0x1, %cl
movb %cl, 0x11a(%rax)
movq -0x80(%rbp), %rax
movl $0xffffffff, 0x11c(%rax) # imm = 0xFFFFFFFF
movq -0x80(%rbp), %rax
movq -0x10(%rbp), %rcx
movq 0x20(%rcx), %rcx
movq (%rcx), %rdx
movq %rdx, 0x128(%rax)
movq 0x8(%rcx), %rdx
movq %rdx, 0x130(%rax)
movq 0x10(%rcx), %rcx
movq %rcx, 0x138(%rax)
movq -0x10(%rbp), %rax
movq (%rax), %rcx
movq -0x80(%rbp), %rax
movq %rcx, 0x140(%rax)
movq -0x80(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
movq -0x80(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0xa0, %rsp
popq %rbp
retq
nop