// File: eniac[P]Mantis/src/compile/compile_p4.cpp
// Function: findMalleableUsage(std::vector<MblRefNode*, std::allocator<MblRefNode*>>, std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, P4RMalleableValueNode*, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, P4RMalleableValueNode*>>>, std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, P4RMalleableFieldNode*, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, P4RMalleableFieldNode*>>>, std::vector<AstNode*, std::allocator<AstNode*>>*, std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, int, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, int>>>*)
void findMalleableUsage(
            vector<MblRefNode*> mblRefs,
            const unordered_map<string, P4RMalleableValueNode*> mblValues,
            const unordered_map<string, P4RMalleableFieldNode*> mblFields,
            vector<AstNode*>* nodeArray,
            unordered_map<string, int>* mblUsage) {

    while (!mblRefs.empty()) {
        MblRefNode* varRef = mblRefs.front();
        mblRefs.erase(mblRefs.begin());

        string* varName = varRef->name_->word_;

        if(mblUsage->find(*varName) != mblUsage->end()) {
            continue;
        }

        // Find the usage index: 0 - ingress, 1 - egress, 2 - both
        bool in_ingress = false;
        bool in_egress = false;
        // One var could be used in multiple tbls
        for (auto node : *nodeArray) {
            // Though filter P4RMalleableTableNode, its table node is still searched
            if(typeContains(node, "TableNode") && !typeContains(node, "P4R")) {
                TableNode* table = dynamic_cast<TableNode*>(node);
                string table_name = *(table->name_->word_);

                // Try to determine if the table uses the mblRef
                bool useMblRef = false;
                if(table->toString().find(*varName) != string::npos) {
                    useMblRef = true;
                } else {
                    // Check if used actions
                    for (auto action : *table->actions_->list_) {
                        for (auto tmp_node : *nodeArray) {
                            if(typeContains(tmp_node, "ActionNode")) {
                                ActionNode* tmp_action_node = dynamic_cast<ActionNode*>(tmp_node);
                                string tmp_action_name = tmp_action_node->name_->toString();
                                if(tmp_action_name.compare(action->name_->toString())==0) {
                                    if(tmp_action_node->toString().find(*varName) != string::npos) {
                                        useMblRef = true;
                                        break;
                                    }
                                }
                            }
                        }
                        if(useMblRef) {
                            break;
                        }                        
                    }
                }
                if(useMblRef) {
                    if(findTblInIng(table_name, *nodeArray)) {
                        in_ingress = true;
                    } else {
                        in_egress = true;
                    }
                }
            }
        }
        if(in_ingress && in_egress) {
            mblUsage->emplace(*varName, USAGE::BOTH);
        } else if (in_ingress) {
            mblUsage->emplace(*varName, USAGE::INGRESS);
        } else if (in_egress) {
            mblUsage->emplace(*varName, USAGE::EGRESS);
        } else {
            PANIC("Can not find the target mblRef %s usage\n", varName->c_str());
        }
    }
    PRINT_VERBOSE("mbl usage dict:\n");
    for (auto i : *mblUsage) {
        PRINT_VERBOSE("  %s : %d\n", i.first.c_str(), i.second);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2a0, %rsp            # imm = 0x2A0
movq %rdi, -0x248(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq -0x248(%rbp), %rdi
callq 0x127560
xorb $-0x1, %al
testb $0x1, %al
jne 0x118a2d
jmp 0x11908b
movq -0x248(%rbp), %rdi
callq 0x1275a0
movq -0x248(%rbp), %rdi
movq (%rax), %rax
movq %rax, -0x30(%rbp)
callq 0x127640
movq %rax, -0x40(%rbp)
leaq -0x38(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x127670
movq -0x248(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x1275d0
movq %rax, -0x48(%rbp)
movq -0x30(%rbp), %rax
movq 0x80(%rax), %rax
movq 0x40(%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x28(%rbp), %rdi
movq -0x50(%rbp), %rsi
callq 0x1276e0
movq %rax, -0x58(%rbp)
movq -0x28(%rbp), %rdi
callq 0x127710
movq %rax, -0x60(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x1276b0
testb $0x1, %al
jne 0x118ab5
jmp 0x118aba
jmp 0x118a16
movb $0x0, -0x61(%rbp)
movb $0x0, -0x62(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rdi
callq 0xb2ae0
movq %rax, -0x78(%rbp)
movq -0x70(%rbp), %rdi
callq 0xb2b10
movq %rax, -0x80(%rbp)
leaq -0x78(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0xb2b40
testb $0x1, %al
jne 0x118afa
jmp 0x118f8e
leaq -0x78(%rbp), %rdi
callq 0xb2b80
movq (%rax), %rax
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rdi
leaq 0x2339e(%rip), %rsi     # 0x13beb9
callq 0x12c730
testb $0x1, %al
jne 0x118b29
jmp 0x118f7e
movq -0x88(%rbp), %rdi
leaq 0x2305b(%rip), %rsi     # 0x13bb92
callq 0x12c730
testb $0x1, %al
jne 0x118f7e
movq -0x88(%rbp), %rax
movq %rax, -0x250(%rbp)
cmpq $0x0, %rax
je 0x118b7f
movq -0x250(%rbp), %rdi
leaq 0x59a7a(%rip), %rsi     # 0x1725e0
leaq 0x5a28b(%rip), %rdx     # 0x172df8
xorl %eax, %eax
movl %eax, %ecx
callq 0xaa660
movq %rax, -0x258(%rbp)
jmp 0x118b8a
xorl %eax, %eax
movq %rax, -0x258(%rbp)
jmp 0x118b8a
movq -0x258(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rax
movq 0x40(%rax), %rax
movq 0x40(%rax), %rsi
leaq -0xb0(%rbp), %rdi
callq 0xaa290
movb $0x0, -0xb1(%rbp)
movq -0x90(%rbp), %rsi
movq (%rsi), %rax
movq (%rax), %rax
leaq -0xd8(%rbp), %rdi
callq *%rax
jmp 0x118bd2
movq -0x50(%rbp), %rsi
leaq -0xd8(%rbp), %rdi
xorl %eax, %eax
movl %eax, %edx
callq 0xaabb0
movq %rax, -0x260(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0xaabe8
movq -0x260(%rbp), %rax
cmpq $-0x1, %rax
je 0x118c29
movb $0x1, -0xb1(%rbp)
jmp 0x118ee5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe0(%rbp)
movl %eax, -0xe4(%rbp)
jmp 0x118f6d
movq -0x90(%rbp), %rax
movq 0x50(%rax), %rax
movq 0x40(%rax), %rax
movq %rax, -0xf0(%rbp)
movq -0xf0(%rbp), %rdi
callq 0xb4ca0
movq %rax, -0xf8(%rbp)
movq -0xf0(%rbp), %rdi
callq 0xb4b30
movq %rax, -0x100(%rbp)
leaq -0xf8(%rbp), %rdi
leaq -0x100(%rbp), %rsi
callq 0xc0190
testb $0x1, %al
jne 0x118c81
jmp 0x118ee3
leaq -0xf8(%rbp), %rdi
callq 0xc01d0
movq (%rax), %rax
movq %rax, -0x108(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x110(%rbp)
movq -0x110(%rbp), %rdi
callq 0xb2ae0
movq %rax, -0x118(%rbp)
movq -0x110(%rbp), %rdi
callq 0xb2b10
movq %rax, -0x120(%rbp)
leaq -0x118(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0xb2b40
testb $0x1, %al
jne 0x118ce4
jmp 0x118ec5
leaq -0x118(%rbp), %rdi
callq 0xb2b80
movq (%rax), %rax
movq %rax, -0x128(%rbp)
movq -0x128(%rbp), %rdi
leaq 0x22f2f(%rip), %rsi     # 0x13bc37
callq 0x12c730
movb %al, -0x261(%rbp)
jmp 0x118d15
movb -0x261(%rbp), %al
testb $0x1, %al
jne 0x118d24
jmp 0x118eb2
movq -0x128(%rbp), %rax
movq %rax, -0x270(%rbp)
cmpq $0x0, %rax
je 0x118d5f
movq -0x270(%rbp), %rdi
leaq 0x5989a(%rip), %rsi     # 0x1725e0
leaq 0x5a153(%rip), %rdx     # 0x172ea0
xorl %eax, %eax
movl %eax, %ecx
callq 0xaa660
movq %rax, -0x278(%rbp)
jmp 0x118d6a
xorl %eax, %eax
movq %rax, -0x278(%rbp)
jmp 0x118d6a
movq -0x278(%rbp), %rax
movq %rax, -0x130(%rbp)
movq -0x130(%rbp), %rax
movq 0x40(%rax), %rsi
movq (%rsi), %rax
movq (%rax), %rax
leaq -0x150(%rbp), %rdi
callq *%rax
jmp 0x118d94
movq -0x108(%rbp), %rax
movq 0x40(%rax), %rsi
movq (%rsi), %rax
movq (%rax), %rax
leaq -0x170(%rbp), %rdi
callq *%rax
jmp 0x118db0
leaq -0x150(%rbp), %rdi
leaq -0x170(%rbp), %rsi
callq 0xaa060
movl %eax, -0x27c(%rbp)
jmp 0x118dcb
leaq -0x170(%rbp), %rdi
callq 0xaabe8
movl -0x27c(%rbp), %eax
cmpl $0x0, %eax
jne 0x118e7b
movq -0x130(%rbp), %rsi
movq (%rsi), %rax
movq (%rax), %rax
leaq -0x190(%rbp), %rdi
callq *%rax
jmp 0x118dfe
movq -0x50(%rbp), %rsi
leaq -0x190(%rbp), %rdi
xorl %eax, %eax
movl %eax, %edx
callq 0xaabb0
movq %rax, -0x288(%rbp)
leaq -0x190(%rbp), %rdi
callq 0xaabe8
movq -0x288(%rbp), %rax
cmpq $-0x1, %rax
je 0x118e79
movb $0x1, -0xb1(%rbp)
movl $0x8, -0x194(%rbp)
jmp 0x118e85
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe0(%rbp)
movl %eax, -0xe4(%rbp)
jmp 0x118ea1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe0(%rbp)
movl %eax, -0xe4(%rbp)
leaq -0x170(%rbp), %rdi
callq 0xaabe8
jmp 0x118ea1
jmp 0x118e7b
movl $0x0, -0x194(%rbp)
leaq -0x150(%rbp), %rdi
callq 0xaabe8
movl -0x194(%rbp), %eax
testl %eax, %eax
je 0x118e9f
jmp 0x118e9d
jmp 0x118ec5
jmp 0x118eb2
leaq -0x150(%rbp), %rdi
callq 0xaabe8
jmp 0x118f6d
jmp 0x118eb4
leaq -0x118(%rbp), %rdi
callq 0xb2ba0
jmp 0x118cc8
testb $0x1, -0xb1(%rbp)
je 0x118ed0
jmp 0x118ee3
jmp 0x118ed2
leaq -0xf8(%rbp), %rdi
callq 0xc01f0
jmp 0x118c65
jmp 0x118ee5
testb $0x1, -0xb1(%rbp)
je 0x118f5f
leaq -0x1b8(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0xaa290
jmp 0x118f03
movq -0x20(%rbp), %rsi
leaq -0x1b8(%rbp), %rdi
callq 0x12e680
movb %al, -0x289(%rbp)
jmp 0x118f1b
leaq -0x1b8(%rbp), %rdi
callq 0xaabe8
movb -0x289(%rbp), %al
testb $0x1, %al
jne 0x118f33
jmp 0x118f59
movb $0x1, -0x61(%rbp)
jmp 0x118f5d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe0(%rbp)
movl %eax, -0xe4(%rbp)
leaq -0x1b8(%rbp), %rdi
callq 0xaabe8
jmp 0x118f6d
movb $0x1, -0x62(%rbp)
jmp 0x118f5f
leaq -0xb0(%rbp), %rdi
callq 0xaabe8
jmp 0x118f7e
leaq -0xb0(%rbp), %rdi
callq 0xaabe8
jmp 0x119113
jmp 0x118f80
leaq -0x78(%rbp), %rdi
callq 0xb2ba0
jmp 0x118ae4
testb $0x1, -0x61(%rbp)
je 0x118fca
testb $0x1, -0x62(%rbp)
je 0x118fca
movq -0x28(%rbp), %rdi
movq -0x50(%rbp), %rsi
movl $0x2, -0x1bc(%rbp)
leaq -0x1bc(%rbp), %rdx
callq 0x127740
movq %rax, -0x1d0(%rbp)
movb %dl, -0x1c8(%rbp)
jmp 0x119086
testb $0x1, -0x61(%rbp)
je 0x119000
movq -0x28(%rbp), %rdi
movq -0x50(%rbp), %rsi
movl $0x0, -0x1d4(%rbp)
leaq -0x1d4(%rbp), %rdx
callq 0x127740
movq %rax, -0x1e8(%rbp)
movb %dl, -0x1e0(%rbp)
jmp 0x119084
testb $0x1, -0x62(%rbp)
je 0x119033
movq -0x28(%rbp), %rdi
movq -0x50(%rbp), %rsi
movl $0x1, -0x1ec(%rbp)
leaq -0x1ec(%rbp), %rdx
callq 0x127740
movq %rax, -0x200(%rbp)
movb %dl, -0x1f8(%rbp)
jmp 0x119082
movq 0x5af76(%rip), %rax     # 0x173fb0
movq (%rax), %rax
movq %rax, -0x298(%rbp)
movq -0x50(%rbp), %rdi
callq 0xaa270
movq -0x298(%rbp), %rdi
movq %rax, %r9
leaq 0x24e2f(%rip), %rsi     # 0x13de8d
leaq 0x24cf2(%rip), %rdx     # 0x13dd57
movl $0x1ac, %ecx            # imm = 0x1AC
leaq 0x24e56(%rip), %r8      # 0x13dec7
movb $0x0, %al
callq 0xaa850
movl $0x1, %edi
callq 0xaa6c0
jmp 0x119084
jmp 0x119086
jmp 0x118a16
movq -0x28(%rbp), %rax
movq %rax, -0x208(%rbp)
movq -0x208(%rbp), %rdi
callq 0x127790
movq %rax, -0x210(%rbp)
movq -0x208(%rbp), %rdi
callq 0x127710
movq %rax, -0x218(%rbp)
leaq -0x210(%rbp), %rdi
leaq -0x218(%rbp), %rsi
callq 0x1276b0
testb $0x1, %al
jne 0x1190d5
jmp 0x11910a
leaq -0x210(%rbp), %rdi
callq 0x1277c0
movq %rax, %rsi
leaq -0x240(%rbp), %rdi
callq 0x1277f0
leaq -0x240(%rbp), %rdi
callq 0xcd2d0
leaq -0x210(%rbp), %rdi
callq 0x127830
jmp 0x1190bc
addq $0x2a0, %rsp            # imm = 0x2A0
popq %rbp
retq
movq -0xe0(%rbp), %rdi
callq 0xaaa60
nop