// File: /workspace/github_c_makefile_star2_O3/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 0xb21a4(%rip), %rdi     # 0x19be08
movq %rbx, %rsi
callq 0xe9a0f
movq %rax, %r12
testq %rax, %rax
jne 0xe9eb0
movq 0xb2189(%rip), %rdi     # 0x19be08
addq $0x60, %rdi
callq 0x1142c9
movq 0xb2179(%rip), %rdi     # 0x19be08
addq $0x20, %rdi
movq %rbx, %rsi
callq 0xc7708
testq %rax, %rax
je 0xe9cd3
movq %rax, %r12
movq (%rax), %rdx
movl $0x88, %edi
addq 0xb2156(%rip), %rdi     # 0x19be08
movq %rbx, %rsi
callq 0x115fac
movq 0xb2147(%rip), %rdi     # 0x19be08
addq $0x60, %rdi
callq 0x1142fb
movq (%r12), %r12
jmp 0xe9eb0
incq 0xb2136(%rip)           # 0x19be10
movq 0xb2127(%rip), %rdi     # 0x19be08
addq $0x60, %rdi
callq 0x1142fb
cmpq $0x101, 0xb211b(%rip) # imm = 0x101
jl 0xe9d34
movq %r14, %rdi
callq 0xd6ec4
testq %rax, %rax
leaq 0x5ea0c(%rip), %r9      # 0x148715
cmovneq %rax, %r9
leaq 0x5e7ef(%rip), %rdi     # 0x148503
leaq 0x5e7fe(%rip), %rsi     # 0x148519
leaq 0x5e805(%rip), %rcx     # 0x148527
movl $0x100, %r8d            # imm = 0x100
movl $0x134, %edx            # imm = 0x134
xorl %eax, %eax
callq 0xbe6f9
movq %r15, %rdi
callq 0xc5028
movq %rax, %r15
movq %r14, %rdi
callq 0xc5028
movq %rax, %r14
leaq 0x5e9c5(%rip), %rdi     # 0x148716
callq 0xd7476
movq %r15, %rdi
movq %rax, %rsi
xorl %edx, %edx
callq 0xc473a
testq %rax, %rax
je 0xe9d6f
movq %r14, %rdi
callq *%rax
jmp 0xe9d7a
movq %r15, %rdi
movq %r14, %rsi
callq 0xe9ebf
movq %rax, %r14
movq 0xb2084(%rip), %rdi     # 0x19be08
addq $0x60, %rdi
callq 0x1142c9
decq 0xb207c(%rip)           # 0x19be10
movq 0xb206d(%rip), %rdi     # 0x19be08
addq $0x20, %rdi
movq %rbx, %rsi
callq 0xc8069
movq 0xb205a(%rip), %rdi     # 0x19be08
testb %al, %al
je 0xe9e7d
addq $0x20, %rdi
movq %rbx, %rsi
callq 0xc7708
movq (%rax), %r12
movq 0xb203c(%rip), %rdi     # 0x19be08
addq $0x60, %rdi
callq 0x1142fb
testq %r14, %r14
je 0xe9eb0
movq (%r14), %rbx
leaq 0xb2680(%rip), %rax     # 0x19c468
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 0xe9e3e
movq 0x10(%rax), %rdx
movl $0x18, %ecx
cmpq %rbx, %rdx
je 0xe9e3e
movq 0x20(%rax), %rdx
movl $0x28, %ecx
cmpq %rbx, %rdx
je 0xe9e3e
movq 0x30(%rax), %rdx
movl $0x38, %ecx
cmpq %rbx, %rdx
jne 0xe9e47
movq (%rax,%rcx), %r15
testq %r15, %r15
jne 0xe9e6e
movabsq $0x782b96602f424981, %rdi # imm = 0x782B96602F424981
movq %rbx, %rsi
callq 0xe9bc5
movq %rax, %r15
leaq 0xb2605(%rip), %rdi     # 0x19c468
movq %rbx, %rsi
movq %rax, %rdx
callq 0x115fac
movq %r15, %rdi
movq %r14, %rsi
callq *0xb8(%r15)
jmp 0xe9eb0
movq %r14, %rsi
callq 0xba5ed
movq 0xb1f7c(%rip), %rdi     # 0x19be08
addq $0x20, %rdi
movq %rbx, %rsi
movq %r14, %rdx
xorl %ecx, %ecx
callq 0xc77e4
movq 0xb1f64(%rip), %rdi     # 0x19be08
addq $0x60, %rdi
callq 0x1142fb
movq %r14, %r12
movq %r12, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq