// File: eniac[P]Mantis/src/compile/compile.cpp
// Function: compileP4Code(std::vector<AstNode*, std::allocator<AstNode*>>*)
vector<AstNode*> compileP4Code(vector<AstNode*>* nodeArray) {

    ing_iso_opt = inferIsoOptForIng(nodeArray, true);
    egr_iso_opt = inferIsoOptForIng(nodeArray, false);

    transformPragma(nodeArray);

    findAndRemoveMalleables(&mblValues, &mblFields, &mblTables, *nodeArray);

    vector<MblRefNode*> mblRefs;
    findMalleableRefs(&mblRefs, *nodeArray);

    // Visitor pass to find the corresponding usage
    findMalleableUsage(mblRefs, mblValues, mblFields, nodeArray, &mblUsages);

    // Transform all references to mbls into references to the appropriate metadata
    transformMalleableRefs(&mblRefs, mblValues, mblFields, nodeArray);

    transformMalleableTables(&mblTables, *nodeArray, ing_iso_opt, egr_iso_opt);

    auto newNodes = vector<AstNode*>();

    generateMetadata(&newNodes, mblValues, mblFields, ing_iso_opt, egr_iso_opt);
    num_init_mbls_ing = generateInitTableForIng(&mblUsages, &newNodes, mblValues, mblFields, ing_iso_opt, true);
    num_init_mbls_egr = generateInitTableForIng(&mblUsages, &newNodes, mblValues, mblFields, egr_iso_opt, false);

    generateSetvarControl(&newNodes);

    // Measurement code
    HeaderDecsMap headerDecsMap = findHeaderDecs(*nodeArray);
    vector<ReactionArgNode*> reaction_args = findReactionArgs(*nodeArray);

    global_ing_bins = generateIngDigestPacking(&newNodes, reaction_args, headerDecsMap,
                    mblValues, mblFields, *nodeArray, &ing_iso_opt);
    global_egr_bins = generateEgrDigestPacking(&newNodes, reaction_args, headerDecsMap,
                    mblValues, mblFields, *nodeArray, &egr_iso_opt);    

    // After packing, iso_opt is firm
    augmentRegisterArgProgForIng(&newNodes, nodeArray, reaction_args, ing_iso_opt, true);   
    augmentRegisterArgProgForIng(&newNodes, nodeArray, reaction_args, egr_iso_opt, false);  

    generateDupRegArgProg(&newNodes, nodeArray, reaction_args, ing_iso_opt, egr_iso_opt);

    generateRegArgGateControl(&newNodes, nodeArray, reaction_args, ing_iso_opt, egr_iso_opt);

    generateExportControl(&newNodes, global_ing_bins, global_egr_bins);

    // Finally, assemble ingress/egress
    augmentIngress(nodeArray);
    augmentEgress(nodeArray); 

    return newNodes;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1a0, %rsp            # imm = 0x1A0
movq %rdi, -0x178(%rbp)
movq %rdi, %rax
movq %rax, -0x170(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rdi
movl $0x1, %esi
callq 0x117930
movl %eax, 0xa9048(%rip)     # 0x174620
movq -0x10(%rbp), %rdi
xorl %esi, %esi
callq 0x117930
movl %eax, 0xa903b(%rip)     # 0x174624
movq -0x10(%rbp), %rdi
callq 0x117800
movq -0x10(%rbp), %rcx
leaq 0xa95cb(%rip), %rdi     # 0x174bc8
leaq 0xa95fc(%rip), %rsi     # 0x174c00
leaq 0xa962d(%rip), %rdx     # 0x174c38
callq 0x12cf40
leaq -0x28(%rbp), %rdi
movq %rdi, -0x168(%rbp)
callq 0xcc990
movq -0x168(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x12d1b0
jmp 0xcb632
leaq -0x50(%rbp), %rdi
leaq -0x28(%rbp), %rsi
callq 0xcc9b0
jmp 0xcb641
leaq 0xa9580(%rip), %rsi     # 0x174bc8
leaq -0x88(%rbp), %rdi
callq 0xccaa0
jmp 0xcb656
leaq 0xa95a3(%rip), %rsi     # 0x174c00
leaq -0xc0(%rbp), %rdi
callq 0xccad0
jmp 0xcb66b
movq -0x10(%rbp), %rcx
leaq 0xa951a(%rip), %r8      # 0x174b90
leaq -0x50(%rbp), %rdi
leaq -0x88(%rbp), %rsi
leaq -0xc0(%rbp), %rdx
callq 0x1189f0
jmp 0xcb68f
leaq -0xc0(%rbp), %rdi
callq 0xcc8f0
leaq -0x88(%rbp), %rdi
callq 0xcc8b0
leaq -0x50(%rbp), %rdi
callq 0xccb00
movq -0x10(%rbp), %rcx
leaq 0xa950d(%rip), %rsi     # 0x174bc8
leaq 0xa953e(%rip), %rdx     # 0x174c00
leaq -0x28(%rbp), %rdi
callq 0x119120
jmp 0xcb6cd
movq -0x10(%rbp), %rsi
leaq -0xd8(%rbp), %rdi
callq 0xb2bc0
jmp 0xcb6df
movl 0xa8f3b(%rip), %edx     # 0x174620
movl 0xa8f39(%rip), %ecx     # 0x174624
leaq 0xa9546(%rip), %rdi     # 0x174c38
leaq -0xd8(%rbp), %rsi
callq 0x119570
jmp 0xcb700
leaq -0xd8(%rbp), %rdi
callq 0xb22f0
movq -0x178(%rbp), %rdi
movb $0x0, -0xd9(%rbp)
xorps %xmm0, %xmm0
movups %xmm0, (%rdi)
movq $0x0, 0x10(%rdi)
callq 0xb22d0
movq -0x178(%rbp), %rdi
movl 0xa8ee6(%rip), %ecx     # 0x174620
movl 0xa8ee3(%rip), %r8d     # 0x174624
leaq 0xa9480(%rip), %rsi     # 0x174bc8
leaq 0xa94b1(%rip), %rdx     # 0x174c00
callq 0x1233d0
jmp 0xcb756
movq -0x178(%rbp), %rsi
movl 0xa8ebc(%rip), %r8d     # 0x174620
leaq 0xa9425(%rip), %rdi     # 0x174b90
leaq 0xa9456(%rip), %rdx     # 0x174bc8
leaq 0xa9487(%rip), %rcx     # 0x174c00
movl $0x1, %r9d
callq 0x123fc0
movl %eax, -0x17c(%rbp)
jmp 0xcb78c
movq -0x178(%rbp), %rsi
movl -0x17c(%rbp), %eax
movl %eax, 0xa8e89(%rip)     # 0x174628
movl 0xa8e7e(%rip), %r8d     # 0x174624
leaq 0xa93e3(%rip), %rdi     # 0x174b90
leaq 0xa9414(%rip), %rdx     # 0x174bc8
leaq 0xa9445(%rip), %rcx     # 0x174c00
xorl %r9d, %r9d
callq 0x123fc0
movl %eax, -0x180(%rbp)
jmp 0xcb7cb
movq -0x178(%rbp), %rdi
movl -0x180(%rbp), %eax
movl %eax, 0xa8e4e(%rip)     # 0x17462c
callq 0x124fe0
jmp 0xcb7e5
movq -0x10(%rbp), %rsi
leaq -0x118(%rbp), %rdi
callq 0x12dd40
jmp 0xcb7f7
movq -0x10(%rbp), %rsi
leaq -0x130(%rbp), %rdi
callq 0x12dc10
jmp 0xcb809
movq -0x178(%rbp), %rsi
movq -0x10(%rbp), %rcx
leaq 0xa8e05(%rip), %rdx     # 0x174620
movq %rsp, %rax
movq %rdx, 0x8(%rax)
movq %rcx, (%rax)
leaq 0xa939c(%rip), %r8      # 0x174bc8
leaq 0xa93cd(%rip), %r9      # 0x174c00
leaq -0x148(%rbp), %rdi
leaq -0x130(%rbp), %rdx
leaq -0x118(%rbp), %rcx
callq 0x11fca0
jmp 0xcb84f
leaq 0xa930a(%rip), %rdi     # 0x174b60
leaq -0x148(%rbp), %rsi
movq %rsi, -0x188(%rbp)
callq 0xccb60
movq -0x188(%rbp), %rdi
callq 0xcc7f0
movq -0x178(%rbp), %rsi
movq -0x10(%rbp), %rcx
leaq 0xa8d9d(%rip), %rdx     # 0x174624
movq %rsp, %rax
movq %rdx, 0x8(%rax)
movq %rcx, (%rax)
leaq 0xa9330(%rip), %r8      # 0x174bc8
leaq 0xa9361(%rip), %r9      # 0x174c00
leaq -0x160(%rbp), %rdi
leaq -0x130(%rbp), %rdx
leaq -0x118(%rbp), %rcx
callq 0x123070
jmp 0xcb8bb
leaq 0xa92b6(%rip), %rdi     # 0x174b78
leaq -0x160(%rbp), %rsi
movq %rsi, -0x190(%rbp)
callq 0xccb60
movq -0x190(%rbp), %rdi
callq 0xcc7f0
movq -0x178(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl 0xa8d2e(%rip), %ecx     # 0x174620
leaq -0x130(%rbp), %rdx
movl $0x1, %r8d
callq 0x11e090
jmp 0xcb906
movq -0x178(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl 0xa8d0d(%rip), %ecx     # 0x174624
leaq -0x130(%rbp), %rdx
xorl %r8d, %r8d
callq 0x11e090
jmp 0xcb928
movq -0x178(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl 0xa8ce7(%rip), %ecx     # 0x174620
movl 0xa8ce4(%rip), %r8d     # 0x174624
leaq -0x130(%rbp), %rdx
callq 0x11b170
jmp 0xcb94e
movq -0x178(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl 0xa8cc1(%rip), %ecx     # 0x174620
movl 0xa8cbe(%rip), %r8d     # 0x174624
leaq -0x130(%rbp), %rdx
callq 0x11a430
jmp 0xcb974
movq -0x178(%rbp), %rdi
leaq 0xa91de(%rip), %rsi     # 0x174b60
leaq 0xa91ef(%rip), %rdx     # 0x174b78
callq 0x119c70
jmp 0xcb990
movq -0x10(%rbp), %rdi
callq 0x118130
jmp 0xcb99b
movq -0x10(%rbp), %rdi
callq 0x118590
jmp 0xcb9a6
movb $0x1, -0xd9(%rbp)
leaq -0x130(%rbp), %rdi
callq 0xccb90
leaq -0x118(%rbp), %rdi
callq 0xccbf0
testb $0x1, -0xd9(%rbp)
jne 0xcba9e
jmp 0xcba92
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0xcbac3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0xcba28
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0xcba1c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0xcc8f0
leaq -0x88(%rbp), %rdi
callq 0xcc8b0
leaq -0x50(%rbp), %rdi
callq 0xccb00
jmp 0xcbac3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0xb22f0
jmp 0xcbac3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0xcbab7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0xcba84
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0x130(%rbp), %rdi
callq 0xccb90
leaq -0x118(%rbp), %rdi
callq 0xccbf0
jmp 0xcbab7
movq -0x178(%rbp), %rdi
callq 0xb22f0
leaq -0x28(%rbp), %rdi
callq 0xccb00
movq -0x170(%rbp), %rax
addq $0x1a0, %rsp            # imm = 0x1A0
popq %rbp
retq
movq -0x178(%rbp), %rdi
callq 0xb22f0
leaq -0x28(%rbp), %rdi
callq 0xccb00
movq -0x30(%rbp), %rdi
callq 0xaaa60
nopw %cs:(%rax,%rax)