// File: eniac[P]Mantis/src/compile/compile_p4.cpp
// Function: duplicateActions(MblRefNode*, ActionNode*, std::vector<MblRefNode*, std::allocator<MblRefNode*>>*, std::vector<AstNode*, std::allocator<AstNode*>>*, P4RMalleableFieldNode const&)
static void duplicateActions(MblRefNode* ref, ActionNode* action,
                      vector<MblRefNode*>* mblRefs,
                      vector<AstNode*>* nodeArray,
                      const P4RMalleableFieldNode& variable) {
    const string actionName = *action->name_->word_;
    const string variableName = *ref->name_->word_;

    // Assemble list of alts
    vector<FieldNode*> alts = findAllAlts(variable);

    // Instantiate the duplicate actions
    // Keep a copy of the names for when we fiddle with the table actions
    vector<string> altNames = vector<string>();
    bool first = true;
    for (FieldNode* fn : alts) {
        const string& headerName = *fn->headerName_->word_;
        const string& fieldName = *fn->fieldName_->word_;

        if (first) {
            ostringstream oss;
            oss << "__" << headerName << "__" << fieldName
                << "__" << actionName;
            altNames.push_back(oss.str());

            // Change action to the instantiated name
            *action->name_->word_ = oss.str();

            // Replace the varref inside the alt with an actual ref
            findAndTransformMblRefsInAction(action, NULL, variableName,
                                            headerName, fieldName);

            first = false;
        } else {
            ostringstream oss;
            oss << "__" << headerName << "__" << fieldName
                << "__" << actionName;
            altNames.push_back(oss.str());

            // Create action with the instantiated name
            ActionNode* newAction = action->duplicateAction(oss.str());

            // Inject Action right after the first
            InputNode* firstInput = dynamic_cast<InputNode*>(action->parent_);
            InputNode* secondInput = new InputNode(firstInput->next_, newAction);
            firstInput->next_ = secondInput;
            secondInput->parent_ = firstInput;
            newAction->parent_ = secondInput;

            // Add any newly created mblRefs from the action
            findAndTransformMblRefsInAction(newAction, mblRefs, variableName,
                                            headerName, fieldName);
        }
    }

    // Modify all tables that use the original action
    auto actionStmtMap = findTableActionStmts(*nodeArray, actionName);
    for (auto kv : actionStmtMap) {
        // Change all tables to have all possible actions
        first = true;
        for (auto altName : altNames) {
            if (first) {
                *kv.first->name_->word_ = altName;
                first = false;
            } else {
                auto newActionStmtNode =
                    new TableActionStmtNode(new NameNode(new string(altName)));
                kv.second->actions_->push_back(newActionStmtNode);
            }
        }

        // Add the alt field match to the table if it does not already exist
        ostringstream oss;
        oss << kP4rIngMetadataName << "." << variableName << kP4rIndexSuffix;

        if (!findTableReadStmt(*kv.second, oss.str())) {
            auto newReadStmtNode =
                new TableReadStmtNode(TableReadStmtNode::EXACT,
                                      new StrNode(new string(oss.str())));
            kv.second->reads_->push_back(newReadStmtNode);
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x780, %rsp            # imm = 0x780
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rax
movq 0x40(%rax), %rsi
leaq -0x48(%rbp), %rdi
callq 0xaa290
movq -0x8(%rbp), %rax
movq 0x80(%rax), %rax
movq 0x40(%rax), %rsi
leaq -0x68(%rbp), %rdi
callq 0xaa290
jmp 0x12564e
movq -0x28(%rbp), %rsi
leaq -0x90(%rbp), %rdi
callq 0x12d7e0
jmp 0x125660
leaq -0xa8(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0xaa330
leaq -0xa8(%rbp), %rdi
callq 0xc0210
movb $0x1, -0xa9(%rbp)
leaq -0x90(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0xb8(%rbp), %rdi
callq 0xb7b80
movq %rax, -0xc0(%rbp)
movq -0xb8(%rbp), %rdi
callq 0xb7a10
movq %rax, -0xc8(%rbp)
leaq -0xc0(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0xcb0f0
testb $0x1, %al
jne 0x1256d6
jmp 0x125ba7
leaq -0xc0(%rbp), %rdi
callq 0xcb130
movq (%rax), %rax
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rax
movq 0x40(%rax), %rax
movq 0x40(%rax), %rax
movq %rax, -0xd8(%rbp)
movq -0xd0(%rbp), %rax
movq 0x48(%rax), %rax
movq 0x40(%rax), %rax
movq %rax, -0xe0(%rbp)
testb $0x1, -0xa9(%rbp)
je 0x1258ea
leaq -0x258(%rbp), %rdi
callq 0xaa7b0
jmp 0x125733
leaq 0x18a92(%rip), %rsi     # 0x13e1cc
leaq -0x258(%rbp), %rdi
callq 0xaa540
movq %rax, -0x6b0(%rbp)
jmp 0x12574f
movq -0x6b0(%rbp), %rdi
movq -0xd8(%rbp), %rsi
callq 0xaa4c0
movq %rax, -0x6b8(%rbp)
jmp 0x12576b
movq -0x6b8(%rbp), %rdi
leaq 0x18a53(%rip), %rsi     # 0x13e1cc
callq 0xaa540
movq %rax, -0x6c0(%rbp)
jmp 0x125787
movq -0x6c0(%rbp), %rdi
movq -0xe0(%rbp), %rsi
callq 0xaa4c0
movq %rax, -0x6c8(%rbp)
jmp 0x1257a3
movq -0x6c8(%rbp), %rdi
leaq 0x18a1b(%rip), %rsi     # 0x13e1cc
callq 0xaa540
movq %rax, -0x6d0(%rbp)
jmp 0x1257bf
movq -0x6d0(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0xaa4c0
jmp 0x1257d1
leaq -0x278(%rbp), %rdi
leaq -0x258(%rbp), %rsi
callq 0xaa580
jmp 0x1257e6
leaq -0xa8(%rbp), %rdi
leaq -0x278(%rbp), %rsi
callq 0x128020
jmp 0x1257fb
leaq -0x278(%rbp), %rdi
callq 0xaabe8
leaq -0x298(%rbp), %rdi
leaq -0x258(%rbp), %rsi
callq 0xaa580
jmp 0x12581c
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rax
movq 0x40(%rax), %rdi
leaq -0x298(%rbp), %rsi
movq %rsi, -0x6d8(%rbp)
callq 0xaa6d0
movq -0x6d8(%rbp), %rdi
callq 0xaabe8
movq -0x10(%rbp), %rdi
movq -0xd8(%rbp), %rcx
movq -0xe0(%rbp), %r8
xorl %eax, %eax
movl %eax, %esi
leaq -0x68(%rbp), %rdx
callq 0x12d5e0
jmp 0x125868
movb $0x0, -0xa9(%rbp)
leaq -0x258(%rbp), %rdi
callq 0xaa130
jmp 0x125b94
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x1260a1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x126098
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x126080
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x1258d9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x278(%rbp), %rdi
callq 0xaabe8
leaq -0x258(%rbp), %rdi
callq 0xaa130
jmp 0x126080
leaq -0x410(%rbp), %rdi
callq 0xaa7b0
jmp 0x1258f8
leaq 0x188cd(%rip), %rsi     # 0x13e1cc
leaq -0x410(%rbp), %rdi
callq 0xaa540
movq %rax, -0x6e0(%rbp)
jmp 0x125914
movq -0x6e0(%rbp), %rdi
movq -0xd8(%rbp), %rsi
callq 0xaa4c0
movq %rax, -0x6e8(%rbp)
jmp 0x125930
movq -0x6e8(%rbp), %rdi
leaq 0x1888e(%rip), %rsi     # 0x13e1cc
callq 0xaa540
movq %rax, -0x6f0(%rbp)
jmp 0x12594c
movq -0x6f0(%rbp), %rdi
movq -0xe0(%rbp), %rsi
callq 0xaa4c0
movq %rax, -0x6f8(%rbp)
jmp 0x125968
movq -0x6f8(%rbp), %rdi
leaq 0x18856(%rip), %rsi     # 0x13e1cc
callq 0xaa540
movq %rax, -0x700(%rbp)
jmp 0x125984
movq -0x700(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0xaa4c0
jmp 0x125996
leaq -0x430(%rbp), %rdi
leaq -0x410(%rbp), %rsi
callq 0xaa580
jmp 0x1259ab
leaq -0xa8(%rbp), %rdi
leaq -0x430(%rbp), %rsi
callq 0x128020
jmp 0x1259c0
leaq -0x430(%rbp), %rdi
callq 0xaabe8
movq -0x10(%rbp), %rax
movq %rax, -0x708(%rbp)
leaq -0x458(%rbp), %rdi
leaq -0x410(%rbp), %rsi
callq 0xaa580
jmp 0x1259ec
movq -0x708(%rbp), %rdi
leaq -0x458(%rbp), %rsi
callq 0xbfb60
movq %rax, -0x710(%rbp)
jmp 0x125a08
leaq -0x458(%rbp), %rdi
callq 0xaabe8
movq -0x710(%rbp), %rax
movq %rax, -0x438(%rbp)
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x718(%rbp)
cmpq $0x0, %rax
je 0x125aa9
movq -0x718(%rbp), %rdi
leaq 0x4cb9b(%rip), %rsi     # 0x1725e0
leaq 0x4cecc(%rip), %rdx     # 0x172918
xorl %eax, %eax
movl %eax, %ecx
callq 0xaa660
movq %rax, -0x720(%rbp)
jmp 0x125ab4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x125b83
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x430(%rbp), %rdi
callq 0xaabe8
jmp 0x125b83
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x458(%rbp), %rdi
callq 0xaabe8
jmp 0x125b83
xorl %eax, %eax
movq %rax, -0x720(%rbp)
jmp 0x125ab4
movq -0x720(%rbp), %rax
movq %rax, -0x460(%rbp)
movl $0x50, %edi
callq 0xaa560
movq %rax, -0x728(%rbp)
jmp 0x125ad5
movq -0x728(%rbp), %rdi
movq -0x460(%rbp), %rax
movq 0x40(%rax), %rsi
movq -0x438(%rbp), %rdx
callq 0xb2350
jmp 0x125af5
movq -0x728(%rbp), %rax
movq %rax, -0x468(%rbp)
movq -0x468(%rbp), %rcx
movq -0x460(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x460(%rbp), %rcx
movq -0x468(%rbp), %rax
movq %rcx, 0x30(%rax)
movq -0x468(%rbp), %rcx
movq -0x438(%rbp), %rax
movq %rcx, 0x30(%rax)
movq -0x438(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0xd8(%rbp), %rcx
movq -0xe0(%rbp), %r8
leaq -0x68(%rbp), %rdx
callq 0x12d5e0
jmp 0x125b5d
leaq -0x410(%rbp), %rdi
callq 0xaa130
jmp 0x125b94
movq -0x728(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
callq 0xaa4e0
leaq -0x410(%rbp), %rdi
callq 0xaa130
jmp 0x126080
jmp 0x125b96
leaq -0xc0(%rbp), %rdi
callq 0xcb150
jmp 0x1256ba
movq -0x20(%rbp), %rsi
leaq -0x4a0(%rbp), %rdi
leaq -0x48(%rbp), %rdx
callq 0x12d280
jmp 0x125bbd
leaq -0x4a0(%rbp), %rax
movq %rax, -0x4a8(%rbp)
movq -0x4a8(%rbp), %rdi
callq 0x128050
movq %rax, -0x4b0(%rbp)
movq -0x4a8(%rbp), %rdi
callq 0x128080
movq %rax, -0x4b8(%rbp)
leaq -0x4b0(%rbp), %rdi
leaq -0x4b8(%rbp), %rsi
callq 0x1280b0
testb $0x1, %al
jne 0x125c0d
jmp 0x126035
leaq -0x4b0(%rbp), %rdi
callq 0x1280e0
movq (%rax), %rcx
movq %rcx, -0x4c8(%rbp)
movq 0x8(%rax), %rax
movq %rax, -0x4c0(%rbp)
movb $0x1, -0xa9(%rbp)
leaq -0xa8(%rbp), %rax
movq %rax, -0x4d0(%rbp)
movq -0x4d0(%rbp), %rdi
callq 0xc0590
movq %rax, -0x4d8(%rbp)
movq -0x4d0(%rbp), %rdi
callq 0xc05c0
movq %rax, -0x4e0(%rbp)
leaq -0x4d8(%rbp), %rdi
leaq -0x4e0(%rbp), %rsi
callq 0xc05f0
testb $0x1, %al
jne 0x125c85
jmp 0x125e13
leaq -0x4d8(%rbp), %rdi
callq 0xc0630
movq %rax, %rsi
leaq -0x500(%rbp), %rdi
callq 0xaa290
jmp 0x125ca2
testb $0x1, -0xa9(%rbp)
je 0x125cf6
movq -0x4c8(%rbp), %rax
movq 0x40(%rax), %rax
movq 0x40(%rax), %rdi
leaq -0x500(%rbp), %rsi
callq 0xaa070
jmp 0x125cc8
movb $0x0, -0xa9(%rbp)
jmp 0x125de5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x126074
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x125e02
movl $0x48, %edi
callq 0xaa560
movq %rax, -0x730(%rbp)
jmp 0x125d09
movl $0x48, %edi
callq 0xaa560
movq %rax, -0x738(%rbp)
jmp 0x125d1c
movl $0x20, %edi
callq 0xaa560
movq %rax, -0x740(%rbp)
jmp 0x125d2f
movq -0x740(%rbp), %rdi
leaq -0x500(%rbp), %rsi
callq 0xaa290
jmp 0x125d44
movq -0x740(%rbp), %rsi
movq -0x738(%rbp), %rdi
callq 0xb26f0
jmp 0x125d59
movq -0x738(%rbp), %rsi
movq -0x730(%rbp), %rdi
callq 0xbcdf0
jmp 0x125d6e
movq -0x730(%rbp), %rax
movq %rax, -0x508(%rbp)
movq -0x4c0(%rbp), %rax
movq 0x50(%rax), %rdi
movq -0x508(%rbp), %rsi
callq 0xb25b0
jmp 0x125d95
jmp 0x125de5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x125dd7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x125dcb
movq -0x740(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
callq 0xaa4e0
movq -0x738(%rbp), %rdi
callq 0xaa4e0
movq -0x730(%rbp), %rdi
callq 0xaa4e0
jmp 0x125e02
leaq -0x500(%rbp), %rdi
callq 0xaabe8
leaq -0x4d8(%rbp), %rdi
callq 0xc0650
jmp 0x125c69
leaq -0x500(%rbp), %rdi
callq 0xaabe8
jmp 0x126074
leaq -0x680(%rbp), %rdi
callq 0xaa7b0
jmp 0x125e21
leaq 0x1609b(%rip), %rsi     # 0x13bec3
leaq -0x680(%rbp), %rdi
callq 0xaa540
movq %rax, -0x748(%rbp)
jmp 0x125e3d
movq -0x748(%rbp), %rdi
leaq 0x15da6(%rip), %rsi     # 0x13bbf1
callq 0xaa540
movq %rax, -0x750(%rbp)
jmp 0x125e59
movq -0x750(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0xaa4c0
movq %rax, -0x758(%rbp)
jmp 0x125e72
movq -0x758(%rbp), %rdi
leaq 0x16386(%rip), %rsi     # 0x13c206
callq 0xaa540
jmp 0x125e87
movq -0x4c0(%rbp), %rax
movq %rax, -0x760(%rbp)
leaq -0x6a0(%rbp), %rdi
leaq -0x680(%rbp), %rsi
callq 0xaa580
jmp 0x125eaa
movq -0x760(%rbp), %rdi
leaq -0x6a0(%rbp), %rsi
callq 0x12d4d0
movb %al, -0x761(%rbp)
jmp 0x125ec5
movb -0x761(%rbp), %al
xorb $-0x1, %al
movb %al, -0x762(%rbp)
leaq -0x6a0(%rbp), %rdi
callq 0xaabe8
movb -0x762(%rbp), %al
testb $0x1, %al
jne 0x125eee
jmp 0x12600a
movl $0x48, %edi
callq 0xaa560
movq %rax, -0x770(%rbp)
jmp 0x125f01
movl $0x48, %edi
callq 0xaa560
movq %rax, -0x778(%rbp)
jmp 0x125f14
movl $0x20, %edi
callq 0xaa560
movq %rax, -0x780(%rbp)
jmp 0x125f27
movq -0x780(%rbp), %rdi
leaq -0x680(%rbp), %rsi
callq 0xaa580
jmp 0x125f3c
movq -0x780(%rbp), %rsi
movq -0x778(%rbp), %rdi
callq 0xb2890
jmp 0x125f51
movq -0x778(%rbp), %rdx
movq -0x770(%rbp), %rdi
xorl %esi, %esi
callq 0xbc9c0
jmp 0x125f68
movq -0x770(%rbp), %rax
movq %rax, -0x6a8(%rbp)
movq -0x4c0(%rbp), %rax
movq 0x48(%rax), %rdi
movq -0x6a8(%rbp), %rsi
callq 0xb2570
jmp 0x125f8f
jmp 0x12600a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x126027
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x6a0(%rbp), %rdi
callq 0xaabe8
jmp 0x126027
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x125ffc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x125ff0
movq -0x780(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
callq 0xaa4e0
movq -0x778(%rbp), %rdi
callq 0xaa4e0
movq -0x770(%rbp), %rdi
callq 0xaa4e0
jmp 0x126027
leaq -0x680(%rbp), %rdi
callq 0xaa130
leaq -0x4b0(%rbp), %rdi
callq 0x128110
jmp 0x125bf1
leaq -0x680(%rbp), %rdi
callq 0xaa130
jmp 0x126074
leaq -0x4a0(%rbp), %rdi
callq 0x128140
leaq -0xa8(%rbp), %rdi
callq 0xc0530
leaq -0x90(%rbp), %rdi
callq 0x127f90
leaq -0x68(%rbp), %rdi
callq 0xaabe8
leaq -0x48(%rbp), %rdi
callq 0xaabe8
addq $0x780, %rsp            # imm = 0x780
popq %rbp
retq
leaq -0x4a0(%rbp), %rdi
callq 0x128140
leaq -0xa8(%rbp), %rdi
callq 0xc0530
leaq -0x90(%rbp), %rdi
callq 0x127f90
leaq -0x68(%rbp), %rdi
callq 0xaabe8
leaq -0x48(%rbp), %rdi
callq 0xaabe8
movq -0x70(%rbp), %rdi
callq 0xaaa60
nopw %cs:(%rax,%rax)