// File: /workspace/github_c_makefile_star2_O1/johsteffens[P]beth/lib/bcore/bcore_spect.c
// Function: bcore_spect_get_typed
vc_t bcore_spect_get_typed( tp_t p_type, tp_t o_type )
{
    assert( hmap_s_g != NULL );

    tp_t sig = bcore_tp_fold_tp( p_type, o_type );
    vc_t val = hmap_s_cache_get( hmap_s_g, sig );
    if( val ) return val;

    bcore_mutex_s_lock( &hmap_s_g->mutex );
    vd_t* vdp = bcore_hmap_u3vd_s_get( &hmap_s_g->map, sig );
    if( vdp )
    {
        hmap_s_cache_set( hmap_s_g, sig, *vdp );
        bcore_mutex_s_unlock( &hmap_s_g->mutex );
        return *vdp;
    }

    /** Recursion counter used to detect recursions in bcore_spect_get_typed.
     *  This allows detecting certain types of cyclic reflections, which the
     *  framework cannot handle.
     */
    static sz_t recursion_count = 0;
    const sz_t recursion_count_limit = 256;
    recursion_count++;

    // Unlock because create_from_self may make use of registry
    bcore_mutex_s_unlock( &hmap_s_g->mutex );

    if( recursion_count > recursion_count_limit )
    {
        ERR_fa
        (
            "Recursion limit '#<sz_t>' was reached at object '#<sc_t>'.\n"
            "\n"
            "\tThis happens when static elements across multiple reflections form a cycle.\n"
            "\n"
            "\tPossible Solution:\n"
            "\t   1. Determine the cycle.\n"
            "\t   2. Unspecify the type in one element or make it non-static.\n"
            "\n"
            "\tTyped-links and aware-links are both non-static links.\n"
            "\n"
            "\tExample:\n"
            "\t  foo_s => bar;       // could be cyclic\n"
            "\t  aware foo_s => bar; // not cyclic (foo_s must be aware)\n"
            "\t  typed foo_s => bar; // not cyclic\n"
            "\t  vd_t bar;           // not cyclic\n"
            "\n",
            recursion_count_limit,
            ifnameof( o_type )
        );
    }

    const bcore_self_s* p_self = bcore_flect_get_self( p_type );
    const bcore_self_s* o_self = bcore_flect_get_self( o_type );
    vd_t spect = NULL;
    vd_t discard_spect = NULL; // in case multiple threads try to register, redundant creations must be discarded

    fp_t create_from_self = bcore_self_s_try_external_fp( p_self, bcore_name_enroll( "bcore_spect_fp_create_from_self" ), 0 );
    if( create_from_self )
    {
        spect = ( ( bcore_spect_fp_create_from_self )create_from_self )( o_self );
    }
    else // use generic creation
    {
        spect = bcore_spect_create_from_self( p_self, o_self );
    }

    // Lock for registering the perspective (if still not registered)
    bcore_mutex_s_lock( &hmap_s_g->mutex );

    recursion_count--;

    // Due to the unlocked period, the perspective might have
    // been registered by another thread meanwhile.
    // In that case we discard spect and retrieve the registered version.
    if( bcore_hmap_u3vd_s_exists( &hmap_s_g->map, sig ) )
    {
        discard_spect = spect;
        spect = *bcore_hmap_u3vd_s_get( &hmap_s_g->map, sig );
    }
    else
    {
        bcore_arr_vd_s_push( &hmap_s_g->arr, spect );
        bcore_hmap_u3vd_s_set( &hmap_s_g->map, sig, spect, false );
    }

    bcore_mutex_s_unlock( &hmap_s_g->mutex );

    if( discard_spect ) bcore_inst_a_discard( discard_spect );
    return spect;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %r14
movq %rdi, %r15
movl $0xff, %ecx
movq %rsi, %rdx
andq %rcx, %rdx
xorq %rdi, %rdx
movabsq $0x100000001b3, %rax    # imm = 0x100000001B3
imulq %rax, %rdx
shrl $0x8, %esi
movl $0xff, %edi
andl %edi, %esi
xorq %rdx, %rsi
imulq %rax, %rsi
movl %r14d, %edx
shrl $0x10, %edx
andl %edi, %edx
xorq %rsi, %rdx
imulq %rax, %rdx
movl %r14d, %esi
shrl $0x18, %esi
xorq %rdx, %rsi
imulq %rax, %rsi
movq %r14, %rdx
shrq $0x20, %rdx
andq %rcx, %rdx
xorq %rsi, %rdx
imulq %rax, %rdx
movq %r14, %rsi
shrq $0x28, %rsi
andq %rcx, %rsi
xorq %rdx, %rsi
imulq %rax, %rsi
movq %r14, %rdx
shrq $0x30, %rdx
andq %rcx, %rdx
xorq %rsi, %rdx
imulq %rax, %rdx
movq %r14, %rbx
shrq $0x38, %rbx
xorq %rdx, %rbx
imulq %rax, %rbx
movq 0xb4de4(%rip), %rdi     # 0x1a8e08
movq %rbx, %rsi
callq 0xf3db7
movq %rax, %r12
testq %rax, %rax
jne 0xf425f
movq 0xb4dc9(%rip), %rdi     # 0x1a8e08
addq $0x60, %rdi
callq 0x11f515
movq 0xb4db9(%rip), %rdi     # 0x1a8e08
addq $0x20, %rdi
movq %rbx, %rsi
callq 0xd192d
testq %rax, %rax
je 0xf4093
movq %rax, %r12
movq (%rax), %rdx
movl $0x88, %edi
addq 0xb4d96(%rip), %rdi     # 0x1a8e08
movq %rbx, %rsi
callq 0x12128c
movq 0xb4d87(%rip), %rdi     # 0x1a8e08
addq $0x60, %rdi
callq 0x11f547
movq (%r12), %r12
jmp 0xf425f
incq 0xb4d76(%rip)           # 0x1a8e10
movq 0xb4d67(%rip), %rdi     # 0x1a8e08
addq $0x60, %rdi
callq 0x11f547
cmpq $0x101, 0xb4d5b(%rip) # imm = 0x101
jl 0xf40f4
movq %r14, %rdi
callq 0xe0cbc
testq %rax, %rax
leaq 0x5f626(%rip), %r9      # 0x1536ef
cmovneq %rax, %r9
leaq 0x5f409(%rip), %rdi     # 0x1534dd
leaq 0x5f418(%rip), %rsi     # 0x1534f3
leaq 0x5f41f(%rip), %rcx     # 0x153501
movl $0x100, %r8d            # imm = 0x100
movl $0x134, %edx            # imm = 0x134
xorl %eax, %eax
callq 0xc825d
movq %r15, %rdi
callq 0xcf1a2
movq %rax, %r15
movq %r14, %rdi
callq 0xcf1a2
movq %rax, %r14
leaq 0x5f5df(%rip), %rdi     # 0x1536f0
callq 0xe1270
movq %r15, %rdi
movq %rax, %rsi
xorl %edx, %edx
callq 0xce882
testq %rax, %rax
je 0xf412f
movq %r14, %rdi
callq *%rax
jmp 0xf413a
movq %r15, %rdi
movq %r14, %rsi
callq 0xf4273
movq %rax, %r14
movq 0xb4cc4(%rip), %rdi     # 0x1a8e08
addq $0x60, %rdi
callq 0x11f515
decq 0xb4cbc(%rip)           # 0x1a8e10
movq 0xb4cad(%rip), %rdi     # 0x1a8e08
addq $0x20, %rdi
movq %rbx, %rsi
callq 0xd2280
movq 0xb4c9a(%rip), %rdi     # 0x1a8e08
testb %al, %al
je 0xf4183
addq $0x20, %rdi
movq %rbx, %rsi
callq 0xd192d
movq (%rax), %r12
jmp 0xf41a9
movq %r14, %rsi
callq 0xc40a2
movq 0xb4c76(%rip), %rdi     # 0x1a8e08
addq $0x20, %rdi
movq %rbx, %rsi
movq %r14, %rdx
xorl %ecx, %ecx
callq 0xd1a23
movq %r14, %r12
xorl %r14d, %r14d
movq 0xb4c58(%rip), %rdi     # 0x1a8e08
addq $0x60, %rdi
callq 0x11f547
testq %r14, %r14
je 0xf425f
movq (%r14), %rbx
leaq 0xb529c(%rip), %rax     # 0x1a9468
movl (%rax), %ecx
movslq %ecx, %rcx
leaq (%rcx,%rcx,2), %rcx
movq 0x20(%rax,%rcx,8), %rdx
movq 0x18(%rax,%rcx,8), %rcx
andq %rbx, %rcx
shlq $0x4, %rcx
leaq (%rdx,%rcx), %rax
movq (%rdx,%rcx), %rdx
movl $0x8, %ecx
cmpq %rbx, %rdx
je 0xf4222
movq 0x10(%rax), %rdx
movl $0x18, %ecx
cmpq %rbx, %rdx
je 0xf4222
movq 0x20(%rax), %rdx
movl $0x28, %ecx
cmpq %rbx, %rdx
je 0xf4222
movq 0x30(%rax), %rdx
movl $0x38, %ecx
cmpq %rbx, %rdx
jne 0xf426e
movq (%rax,%rcx), %r15
testq %r15, %r15
jne 0xf4252
movabsq $0x782b96602f424981, %rdi # imm = 0x782B96602F424981
movq %rbx, %rsi
callq 0xf3f85
movq %rax, %r15
leaq 0xb5221(%rip), %rdi     # 0x1a9468
movq %rbx, %rsi
movq %rax, %rdx
callq 0x12128c
movq %r15, %rdi
movq %r14, %rsi
callq *0xb8(%r15)
movq %r12, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
xorl %r15d, %r15d
jmp 0xf4226