// File: WShabti-Team[P]WShabtiPict/wshabtilib/api/deriver.cpp
// Function: pictcore::ExclusionDeriver::DeriveExclusions()
void ExclusionDeriver::DeriveExclusions()
{
    // For preview generation we don't invoke the core of the deriver at all
    if( m_task->GetGenerationMode() != Regular ) return;

    DOUT( L"Exclusions:\n" );
    for( auto & exclusion : m_exclusions )
    {
        exclusion.Print();
    }
    DOUT( L"Derivation: Started\n" );

    // Add pointers to referencing exclusions to each parameter
    // for_each(m_exclusions.begin(), m_exclusions.end(), AddExclusionParamBackPtrs);
    for( ExclusionCollection::iterator ie = m_exclusions.begin(); ie != m_exclusions.end(); ++ie )
    {
        AddExclusionParamBackPtrs( ie );
    }

    // Initialize the worklist
    for( vector<Parameter*>::iterator i = m_parameters.begin(); i != m_parameters.end(); ++i )
    {
        if( ( *i )->GetExclusionCount() >= ( *i )->GetValueCount() )
        {
            m_worklist.push_back( &**i );
        }
    }

    while( !m_worklist.empty() )
    {
        DOUT( L"worklist size: " << static_cast<int>( m_worklist.size() ) << L"\n" );
        DOUT( L"excl col size: " << static_cast<int>( m_exclusions.size() ) << L"\n"; )

        m_currentParam = m_worklist[ 0 ];
        m_worklist.pop_front();

        DOUT( L"worklist item: [" << m_currentParam->GetName() << L"]" <<
              L", avg excl size: " << m_currentParam->GetAverageExclusionSize() <<
              L", num excls: " << m_currentParam->GetExclusionCount() <<
              L"\n"; )

        // We need buckets to hold the exclusions pertaining to each value
        vector<list<Exclusion *> > buckets( m_currentParam->GetValueCount() );

        for( ExclIterCollection::iterator ie =  m_currentParam->GetExclusions().begin();
                                          ie != m_currentParam->GetExclusions().end();
                                        ++ie )
        {
            // put ref to each exclusion in appropriate value-relative bucket
            // find this parameter in the exclusion
            Exclusion::iterator iExcl = find_if( ( *ie )->begin(), ( *ie )->end(),
                                                 bind2nd( MatchParameterPointer(), m_currentParam ) );

            // put the exclusion in the right bucket
            assert( iExcl != ( *ie )->end() );
            Exclusion* pExcl = const_cast<Exclusion*>( &**ie );
            buckets.at( iExcl->second ).push_back( pExcl );
        }

        // if all the buckets have something in them
        int n;
        for( n = 0; n < m_currentParam->GetValueCount(); ++n )
        {
            if( buckets[ n ].empty() ) break;
        }

        // if there was an empty bucket, go to the next entry in the worklist
        if( n < m_currentParam->GetValueCount() ) continue;

        // recursively build all cover sets, building up exclusion on other params
        Exclusion exclImplied;
        m_end = buckets.end();
        buildExclusion( exclImplied, buckets.begin() );

        peformDelete();
    }

    DOUT( L"Derivation: Finished\n" );
    DOUT( L"Exclusions:\n" );
    for( auto & exclusion : m_exclusions )
    {
        exclusion.Print();
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1e0, %rsp            # imm = 0x1E0
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x160(%rbp)
movq 0x50(%rax), %rdi
callq 0xb310
cmpl $0x0, %eax
je 0xa32d
jmp 0xa95c
movq -0x160(%rbp), %rax
addq $0x18, %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rdi
callq 0xaf20
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rdi
callq 0xab70
movq %rax, -0x20(%rbp)
leaq -0x18(%rbp), %rdi
leaq -0x20(%rbp), %rsi
callq 0xaf50
testb $0x1, %al
jne 0xa369
jmp 0xa38a
leaq -0x18(%rbp), %rdi
callq 0xafa0
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rdi
callq 0x14ec0
leaq -0x18(%rbp), %rdi
callq 0xb000
jmp 0xa356
movq -0x160(%rbp), %rdi
addq $0x18, %rdi
callq 0xaf20
movq %rax, -0x30(%rbp)
movq -0x160(%rbp), %rdi
addq $0x18, %rdi
callq 0xab70
movq %rax, -0x38(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0xaf50
testb $0x1, %al
jne 0xa3c5
jmp 0xa3d9
leaq -0x30(%rbp), %rdi
callq 0xa0e0
leaq -0x30(%rbp), %rdi
callq 0xb000
jmp 0xa39e
movq -0x160(%rbp), %rdi
callq 0x8c90
movq %rax, -0x40(%rbp)
movq -0x160(%rbp), %rdi
callq 0x8cc0
movq %rax, -0x48(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x8cf0
testb $0x1, %al
jne 0xa40c
jmp 0xa482
leaq -0x40(%rbp), %rdi
callq 0x8d30
movq (%rax), %rdi
callq 0xb330
movl %eax, -0x164(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x8d30
movq (%rax), %rdi
callq 0x8eb0
movl %eax, %ecx
movl -0x164(%rbp), %eax
cmpl %ecx, %eax
jl 0xa472
movq -0x160(%rbp), %rax
addq $0x60, %rax
movq %rax, -0x170(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x8d30
movq -0x170(%rbp), %rdi
movq (%rax), %rax
movq %rax, -0x50(%rbp)
leaq -0x50(%rbp), %rsi
callq 0xb350
jmp 0xa474
leaq -0x40(%rbp), %rdi
callq 0x8d70
jmp 0xa3e9
jmp 0xa484
movq -0x160(%rbp), %rdi
addq $0x60, %rdi
callq 0xb380
xorb $-0x1, %al
testb $0x1, %al
jne 0xa49f
jmp 0xa8de
movq -0x160(%rbp), %rdi
addq $0x60, %rdi
movq %rdi, -0x188(%rbp)
xorl %eax, %eax
movl %eax, %esi
callq 0xb3b0
movq -0x188(%rbp), %rdi
movq %rax, %rcx
movq -0x160(%rbp), %rax
movq (%rcx), %rcx
movq %rcx, 0x48(%rax)
callq 0xb3e0
movq -0x160(%rbp), %rax
movq 0x48(%rax), %rdi
callq 0x8eb0
cltq
movq %rax, -0x180(%rbp)
leaq -0x69(%rbp), %rdi
movq %rdi, -0x178(%rbp)
callq 0xb450
movq -0x180(%rbp), %rsi
movq -0x178(%rbp), %rdx
leaq -0x68(%rbp), %rdi
callq 0xb470
jmp 0xa519
leaq -0x69(%rbp), %rdi
callq 0xb4e0
movq -0x160(%rbp), %rax
movq 0x48(%rax), %rdi
callq 0xb500
movq %rax, -0x190(%rbp)
jmp 0xa53b
movq -0x190(%rbp), %rdi
callq 0xb520
movq %rax, -0x88(%rbp)
movq -0x160(%rbp), %rax
movq 0x48(%rax), %rdi
callq 0xb500
movq %rax, -0x198(%rbp)
jmp 0xa567
movq -0x198(%rbp), %rdi
callq 0xb580
movq %rax, -0x90(%rbp)
leaq -0x88(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0xb550
testb $0x1, %al
jne 0xa596
jmp 0xa758
leaq -0x88(%rbp), %rdi
callq 0xb5b0
movq %rax, %rdi
callq 0xaed0
movq %rax, %rdi
callq 0xb030
movq %rax, -0x1a0(%rbp)
jmp 0xa5bb
movq -0x1a0(%rbp), %rax
movq %rax, -0xa0(%rbp)
leaq -0x88(%rbp), %rdi
callq 0xb5b0
movq %rax, %rdi
callq 0xaed0
movq %rax, %rdi
callq 0xb060
movq %rax, -0x1a8(%rbp)
jmp 0xa5ee
movq -0x160(%rbp), %rsi
movq -0x1a8(%rbp), %rax
movq %rax, -0xa8(%rbp)
addq $0x48, %rsi
leaq -0xb9(%rbp), %rdi
callq 0x90f0
movq %rax, -0x1b0(%rbp)
jmp 0xa61c
movq -0x1b0(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0xa0(%rbp), %rdi
movq -0xa8(%rbp), %rsi
movq -0xb0(%rbp), %rdx
callq 0x9030
movq %rax, -0x1b8(%rbp)
jmp 0xa64d
movq -0x1b8(%rbp), %rax
movq %rax, -0x98(%rbp)
leaq -0x88(%rbp), %rdi
callq 0xb5b0
movq %rax, %rdi
callq 0xaed0
movq %rax, %rdi
callq 0xb060
movq %rax, -0x1c0(%rbp)
jmp 0xa680
movq -0x1c0(%rbp), %rax
movq %rax, -0xc8(%rbp)
leaq -0x98(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x9130
testb $0x1, %al
jne 0xa6a7
jmp 0xa6a9
jmp 0xa6f3
leaq 0x59ac4(%rip), %rdi     # 0x64174
leaq 0x59ad5(%rip), %rsi     # 0x6418c
movl $0x152, %edx            # imm = 0x152
leaq 0x59ae4(%rip), %rcx     # 0x641a7
callq 0x7450
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x69(%rbp), %rdi
callq 0xb4e0
jmp 0xa965
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0xa8d0
leaq -0x88(%rbp), %rdi
callq 0xb5b0
movq %rax, %rdi
callq 0xafa0
movq %rax, -0xd0(%rbp)
leaq -0x98(%rbp), %rdi
callq 0x9160
movslq 0x8(%rax), %rsi
leaq -0x68(%rbp), %rdi
callq 0xb5d0
movq %rax, -0x1c8(%rbp)
jmp 0xa730
movq -0x1c8(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0xb610
jmp 0xa745
jmp 0xa747
leaq -0x88(%rbp), %rdi
callq 0xb650
jmp 0xa54e
movl $0x0, -0xd4(%rbp)
movq -0x160(%rbp), %rax
movl -0xd4(%rbp), %ecx
movl %ecx, -0x1d0(%rbp)
movq 0x48(%rax), %rdi
callq 0x8eb0
movl %eax, -0x1cc(%rbp)
jmp 0xa786
movl -0x1d0(%rbp), %eax
movl -0x1cc(%rbp), %ecx
cmpl %ecx, %eax
jge 0xa7c9
movslq -0xd4(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0xb680
movq %rax, %rdi
callq 0xb6a0
testb $0x1, %al
jne 0xa7b4
jmp 0xa7b6
jmp 0xa7c9
jmp 0xa7b8
movl -0xd4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd4(%rbp)
jmp 0xa762
movq -0x160(%rbp), %rax
movl -0xd4(%rbp), %ecx
movl %ecx, -0x1d8(%rbp)
movq 0x48(%rax), %rdi
callq 0x8eb0
movl %eax, -0x1d4(%rbp)
jmp 0xa7ed
movl -0x1d8(%rbp), %eax
movl -0x1d4(%rbp), %ecx
cmpl %ecx, %eax
jge 0xa80c
movl $0xa, -0xd8(%rbp)
jmp 0xa899
leaq -0x128(%rbp), %rdi
callq 0xb6c0
jmp 0xa81a
leaq -0x68(%rbp), %rdi
movq %rdi, -0x1e0(%rbp)
callq 0xb700
movq -0x1e0(%rbp), %rdi
movq %rax, %rcx
movq -0x160(%rbp), %rax
movq %rcx, -0x130(%rbp)
movq -0x130(%rbp), %rcx
movq %rcx, 0x58(%rax)
callq 0xbc40
movq -0x160(%rbp), %rdi
movq %rax, -0x138(%rbp)
movq -0x138(%rbp), %rdx
leaq -0x128(%rbp), %rsi
callq 0xb730
jmp 0xa875
movq -0x160(%rbp), %rdi
callq 0xa160
jmp 0xa883
leaq -0x128(%rbp), %rdi
callq 0xbc70
movl $0x0, -0xd8(%rbp)
leaq -0x68(%rbp), %rdi
callq 0xbca0
movl -0xd8(%rbp), %eax
testl %eax, %eax
je 0xa8b3
jmp 0xa8ae
jmp 0xa484
jmp 0xa484
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x128(%rbp), %rdi
callq 0xbc70
leaq -0x68(%rbp), %rdi
callq 0xbca0
jmp 0xa965
movq -0x160(%rbp), %rax
addq $0x18, %rax
movq %rax, -0x140(%rbp)
movq -0x140(%rbp), %rdi
callq 0xaf20
movq %rax, -0x148(%rbp)
movq -0x140(%rbp), %rdi
callq 0xab70
movq %rax, -0x150(%rbp)
leaq -0x148(%rbp), %rdi
leaq -0x150(%rbp), %rsi
callq 0xaf50
testb $0x1, %al
jne 0xa92f
jmp 0xa95c
leaq -0x148(%rbp), %rdi
callq 0xafa0
movq %rax, -0x158(%rbp)
movq -0x158(%rbp), %rdi
callq 0x14ec0
leaq -0x148(%rbp), %rdi
callq 0xb000
jmp 0xa916
addq $0x1e0, %rsp            # imm = 0x1E0
popq %rbp
retq
movq -0x78(%rbp), %rdi
callq 0x79d0
nop