// File: /workspace/github_c_makefile_star2_O0/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 %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0xd14c0
movq %rax, -0x20(%rbp)
movq 0xe0df0(%rip), %rdi     # 0x1b2368
movq -0x20(%rbp), %rsi
callq 0xd1300
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
je 0xd1599
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd1796
movq 0xe0dc8(%rip), %rdi     # 0x1b2368
addq $0x60, %rdi
callq 0x10fc20
movq 0xe0db8(%rip), %rdi     # 0x1b2368
addq $0x20, %rdi
movq -0x20(%rbp), %rsi
callq 0xab640
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
je 0xd15ff
movq 0xe0d99(%rip), %rdi     # 0x1b2368
movq -0x20(%rbp), %rsi
movq -0x30(%rbp), %rax
movq (%rax), %rdx
callq 0xd1370
movq 0xe0d82(%rip), %rdi     # 0x1b2368
addq $0x60, %rdi
callq 0x10fc70
movq -0x30(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0xd1796
movq $0x100, -0x38(%rbp)     # imm = 0x100
movq 0xe0d62(%rip), %rax     # 0x1b2370
addq $0x1, %rax
movq %rax, 0xe0d57(%rip)     # 0x1b2370
movq 0xe0d48(%rip), %rdi     # 0x1b2368
addq $0x60, %rdi
callq 0x10fc70
cmpq $0x100, 0xe0d3c(%rip) # imm = 0x100
jle 0xd1669
movq -0x18(%rbp), %rdi
callq 0xd17a0
movq %rax, %r9
leaq 0x811c7(%rip), %rdi     # 0x152810
leaq 0x811d6(%rip), %rsi     # 0x152826
movl $0x134, %edx            # imm = 0x134
leaq 0x811d8(%rip), %rcx     # 0x152834
movl $0x100, %r8d            # imm = 0x100
movb $0x0, %al
callq 0x9d0f0
movq -0x10(%rbp), %rdi
callq 0xa7590
movq %rax, -0x40(%rbp)
movq -0x18(%rbp), %rdi
callq 0xa7590
movq %rax, -0x48(%rbp)
movq $0x0, -0x50(%rbp)
movq $0x0, -0x58(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0x68(%rbp)
leaq 0x81381(%rip), %rdi     # 0x152a23
callq 0xc17b0
movq -0x68(%rbp), %rdi
movq %rax, %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0xa6a30
movq %rax, -0x60(%rbp)
cmpq $0x0, -0x60(%rbp)
je 0xd16d2
movq -0x60(%rbp), %rax
movq -0x48(%rbp), %rdi
callq *%rax
movq %rax, -0x50(%rbp)
jmp 0xd16e3
movq -0x40(%rbp), %rdi
movq -0x48(%rbp), %rsi
callq 0xd17f0
movq %rax, -0x50(%rbp)
movq 0xe0c7e(%rip), %rdi     # 0x1b2368
addq $0x60, %rdi
callq 0x10fc20
movq 0xe0c76(%rip), %rax     # 0x1b2370
addq $-0x1, %rax
movq %rax, 0xe0c6b(%rip)     # 0x1b2370
movq 0xe0c5c(%rip), %rdi     # 0x1b2368
addq $0x20, %rdi
movq -0x20(%rbp), %rsi
callq 0xac3f0
testb $0x1, %al
jne 0xd171f
jmp 0xd1744
movq -0x50(%rbp), %rax
movq %rax, -0x58(%rbp)
movq 0xe0c3a(%rip), %rdi     # 0x1b2368
addq $0x20, %rdi
movq -0x20(%rbp), %rsi
callq 0xab640
movq (%rax), %rax
movq %rax, -0x50(%rbp)
jmp 0xd176e
movq 0xe0c1d(%rip), %rdi     # 0x1b2368
movq -0x50(%rbp), %rsi
callq 0x96df0
movq 0xe0c0d(%rip), %rdi     # 0x1b2368
addq $0x20, %rdi
movq -0x20(%rbp), %rsi
movq -0x50(%rbp), %rdx
xorl %ecx, %ecx
callq 0xab870
movq 0xe0bf3(%rip), %rdi     # 0x1b2368
addq $0x60, %rdi
callq 0x10fc70
cmpq $0x0, -0x58(%rbp)
je 0xd178e
movq -0x58(%rbp), %rdi
callq 0xd20c0
movq -0x50(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x70, %rsp
popq %rbp
retq