// File: /workspace/github_c_makefile_star2_O0/alexj136[P]minijit/src/icodegen.c
// Function: icodegen_Expr
ICodeOperationVector *icodegen_Expr(Prog *prog, Expr *expr, int *next_label,
        int *func_labels) {

    BEGIN_CODE_GENERATION;

    if(Expr_isInt(expr)) {

        // Just load the literal value into the accumulator
        INSERT_OPERATION(LOADIMM    , Int_value(expr)   , ACCUMULATOR   );
    }
    else if(Expr_isAdd(expr) || Expr_isSub(expr)) {

        // Evaluate the RHS
        if(Expr_isAdd(expr)) {
            INSERT_EXPR_CODE(Add_rhs(expr));
        }
        else /* if(Expr_isSub(expr)) */ {
            INSERT_EXPR_CODE(Sub_rhs(expr));
        }

        // Push the RHS result on the stack
        INSERT_OPERATION(STORE      , ACCUMULATOR       , STACK_POINTER );
        INSERT_OPERATION(LOADIMM    , 1                 , ACCUMULATOR   );
        INSERT_OPERATION(ADD        , STACK_POINTER     , ACCUMULATOR   );

        // Evaluate the LHS
        INSERT_EXPR_CODE(Add_lhs(expr));

        // Pop the RHS into temporary register
        INSERT_OPERATION(LOADIMM    , 1                 , TEMPORARY     );
        INSERT_OPERATION(SUB        , STACK_POINTER     , TEMPORARY     );
        INSERT_OPERATION(LOAD       , STACK_POINTER     , TEMPORARY     );

        // Do the operation
        if(Expr_isAdd(expr)) {
            INSERT_OPERATION(ADD        , ACCUMULATOR       , TEMPORARY     );
        }
        else /* if(Expr_isSub(expr)) */ {
            INSERT_OPERATION(SUB        , ACCUMULATOR       , TEMPORARY     );
        }
    }
    else if(Expr_isCall(expr)) {

        // Determine the label number to jump to in the call
        int callee_label = func_labels[Call_name(expr)];
        int num_args     = Call_num_args(expr);
        int num_vars     = Func_num_vars(Prog_func(prog, Call_name(expr)));
        int idx;

        // Push the current frame pointer on the stack
        INSERT_OPERATION(STORE      , FRAME_POINTER     , STACK_POINTER );
        INSERT_OPERATION(LOADIMM    , 1                 , ACCUMULATOR   );
        INSERT_OPERATION(ADD        , STACK_POINTER     , ACCUMULATOR   );

        // Push the current return address on the stack
        INSERT_OPERATION(STORE      , RETURN_ADDRESS    , STACK_POINTER );
        INSERT_OPERATION(LOADIMM    , 1                 , ACCUMULATOR   );
        INSERT_OPERATION(ADD        , STACK_POINTER     , ACCUMULATOR   );

        // Add zeros to the stack for the non-argument variables in the callee
        for(idx = num_vars - 1; idx >= num_args; idx--) {

            INSERT_OPERATION(LOADIMM    , 0                 , ACCUMULATOR   );
            INSERT_OPERATION(STORE      , ACCUMULATOR       , STACK_POINTER );
            INSERT_OPERATION(LOADIMM    , 1                 , ACCUMULATOR   );
            INSERT_OPERATION(ADD        , STACK_POINTER     , ACCUMULATOR   );
        }

        // For each argument expression, evaluate and push the result on the
        // stack
        for(idx = num_args - 1; idx >= 0; idx--) {

            // Evaluate the idxth argument expression
            INSERT_EXPR_CODE(Call_arg(expr, idx));

            // Push the result on the stack
            INSERT_OPERATION(STORE      , ACCUMULATOR       , STACK_POINTER );
            INSERT_OPERATION(LOADIMM    , 1                 , ACCUMULATOR   );
            INSERT_OPERATION(ADD        , STACK_POINTER     , ACCUMULATOR   );
        }

        // Set the frame pointer for the callee (one less than the stack
        // pointer)
        INSERT_OPERATION(MOVE       , STACK_POINTER     , FRAME_POINTER );
        INSERT_OPERATION(LOADIMM    , 1                 , TEMPORARY     );
        INSERT_OPERATION(SUB        , FRAME_POINTER     , TEMPORARY     );

        // Jump to the function
        INSERT_OPERATION(JUMPLINK   , callee_label      , 0             );

        // Pop the arguments and variables off the stack
        INSERT_OPERATION(LOADIMM    , num_vars          , TEMPORARY     );
        INSERT_OPERATION(SUB        , STACK_POINTER     , TEMPORARY     );

        // Restore the return address
        INSERT_OPERATION(LOADIMM    , 1                 , TEMPORARY     );
        INSERT_OPERATION(SUB        , STACK_POINTER     , TEMPORARY     );
        INSERT_OPERATION(LOAD       , STACK_POINTER     , RETURN_ADDRESS);

        // Restore the frame pointer
        INSERT_OPERATION(LOADIMM    , 1                 , TEMPORARY     );
        INSERT_OPERATION(SUB        , STACK_POINTER     , TEMPORARY     );
        INSERT_OPERATION(LOAD       , STACK_POINTER     , FRAME_POINTER );
    }
    else if(Expr_isVar(expr)) {

        // Calculate the address from which to load
        INSERT_OPERATION(LOADIMM    , Var_name(expr)    , ACCUMULATOR   );
        INSERT_OPERATION(MOVE       , FRAME_POINTER     , TEMPORARY     );
        INSERT_OPERATION(SUB        , TEMPORARY         , ACCUMULATOR   );

        // Perform the load operation with the calculated address
        INSERT_OPERATION(LOAD       , TEMPORARY         , ACCUMULATOR   );
    }
    else {
        ERROR("Expr type not recognised.");
    }

    RETURN_GENERATED_CODE;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20f0, %rsp           # imm = 0x20F0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movb $0x0, %al
callq 0x1a4f0
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x1c114
movq -0x28(%rbp), %rax
movq %rax, -0x1fc0(%rbp)
movq -0x10(%rbp), %rax
movl 0x4(%rax), %esi
movl $0x5, %edi
movl $0x4, %edx
callq 0x19c90
movq -0x1fc0(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
jmp 0x1c9f1
movq -0x10(%rbp), %rax
cmpl $0x1, (%rax)
je 0x1c12a
movq -0x10(%rbp), %rax
cmpl $0x2, (%rax)
jne 0x1c342
movq -0x10(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x1c16a
jmp 0x1c135
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0x1c0b0
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x1a7a0
movq -0x30(%rbp), %rdi
callq 0x1afa0
jmp 0x1c1a1
jmp 0x1c16c
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0x1c0b0
movq %rax, -0x38(%rbp)
movq -0x28(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x1a7a0
movq -0x38(%rbp), %rdi
callq 0x1afa0
jmp 0x1c1a1
movq -0x28(%rbp), %rax
movq %rax, -0x1fd8(%rbp)
movl $0x2, %edi
movl $0x4, %esi
xorl %edx, %edx
callq 0x19c90
movq -0x1fd8(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x1fd0(%rbp)
movl $0x5, %edi
movl $0x1, %esi
movl $0x4, %edx
callq 0x19c90
movq -0x1fd0(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x1fc8(%rbp)
movl $0x3, %edi
xorl %esi, %esi
movl $0x4, %edx
callq 0x19c90
movq -0x1fc8(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0x1c0b0
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x1a7a0
movq -0x40(%rbp), %rdi
callq 0x1afa0
movq -0x28(%rbp), %rax
movq %rax, -0x1ff0(%rbp)
movl $0x5, %edx
movl $0x1, %esi
movl %edx, %edi
callq 0x19c90
movq -0x1ff0(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x1fe8(%rbp)
movl $0x4, %edi
xorl %esi, %esi
movl $0x5, %edx
callq 0x19c90
movq -0x1fe8(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x1fe0(%rbp)
movl $0x1, %edi
xorl %esi, %esi
movl $0x5, %edx
callq 0x19c90
movq -0x1fe0(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x10(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x1c312
movq -0x28(%rbp), %rax
movq %rax, -0x1ff8(%rbp)
movl $0x3, %edi
movl $0x4, %esi
movl $0x5, %edx
callq 0x19c90
movq -0x1ff8(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
jmp 0x1c33d
movq -0x28(%rbp), %rax
movq %rax, -0x2000(%rbp)
movl $0x4, %esi
movl $0x5, %edx
movl %esi, %edi
callq 0x19c90
movq -0x2000(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
jmp 0x1c9ef
movq -0x10(%rbp), %rax
cmpl $0x3, (%rax)
jne 0x1c85c
movq -0x20(%rbp), %rax
movq -0x10(%rbp), %rcx
movslq 0x4(%rcx), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x44(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0xb790
movl %eax, -0x48(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movq -0x10(%rbp), %rax
movl 0x4(%rax), %esi
callq 0x9860
movq 0x8(%rax), %rdi
callq 0x7e20
movl %eax, -0x4c(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x2030(%rbp)
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x19c90
movq -0x2030(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2028(%rbp)
movl $0x5, %edi
movl $0x1, %esi
movl $0x4, %edx
callq 0x19c90
movq -0x2028(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2020(%rbp)
movl $0x3, %edi
xorl %esi, %esi
movl $0x4, %edx
callq 0x19c90
movq -0x2020(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2018(%rbp)
movl $0x2, %esi
xorl %edx, %edx
movl %esi, %edi
callq 0x19c90
movq -0x2018(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2010(%rbp)
movl $0x5, %edi
movl $0x1, %esi
movl $0x4, %edx
callq 0x19c90
movq -0x2010(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2008(%rbp)
movl $0x3, %edi
xorl %esi, %esi
movl $0x4, %edx
callq 0x19c90
movq -0x2008(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movl -0x4c(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x50(%rbp)
movl -0x50(%rbp), %eax
cmpl -0x48(%rbp), %eax
jl 0x1c567
movq -0x28(%rbp), %rax
movq %rax, -0x2050(%rbp)
movl $0x5, %edi
xorl %esi, %esi
movl $0x4, %edx
callq 0x19c90
movq -0x2050(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2048(%rbp)
movl $0x2, %edi
movl $0x4, %esi
xorl %edx, %edx
callq 0x19c90
movq -0x2048(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2040(%rbp)
movl $0x5, %edi
movl $0x1, %esi
movl $0x4, %edx
callq 0x19c90
movq -0x2040(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2038(%rbp)
movl $0x3, %edi
xorl %esi, %esi
movl $0x4, %edx
callq 0x19c90
movq -0x2038(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movl -0x50(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x1c49e
movl -0x48(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x50(%rbp)
cmpl $0x0, -0x50(%rbp)
jl 0x1c65a
jmp 0x1c57c
movq -0x8(%rbp), %rax
movq %rax, -0x2058(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
movl -0x50(%rbp), %esi
callq 0xbb50
movq -0x2058(%rbp), %rdi
movq %rax, %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0x1c0b0
movq %rax, -0x58(%rbp)
movq -0x28(%rbp), %rdi
movq -0x58(%rbp), %rsi
callq 0x1a7a0
movq -0x58(%rbp), %rdi
callq 0x1afa0
movq -0x28(%rbp), %rax
movq %rax, -0x2070(%rbp)
movl $0x2, %edi
movl $0x4, %esi
xorl %edx, %edx
callq 0x19c90
movq -0x2070(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2068(%rbp)
movl $0x5, %edi
movl $0x1, %esi
movl $0x4, %edx
callq 0x19c90
movq -0x2068(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2060(%rbp)
movl $0x3, %edi
xorl %esi, %esi
movl $0x4, %edx
callq 0x19c90
movq -0x2060(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movl -0x50(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x1c570
movq -0x28(%rbp), %rax
movq %rax, -0x20d0(%rbp)
xorl %esi, %esi
movl $0x1, %edx
movl %esi, %edi
callq 0x19c90
movq -0x20d0(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x20c8(%rbp)
movl $0x5, %edx
movl $0x1, %esi
movl %edx, %edi
callq 0x19c90
movq -0x20c8(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x20c0(%rbp)
movl $0x4, %edi
movl $0x1, %esi
movl $0x5, %edx
callq 0x19c90
movq -0x20c0(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x20b8(%rbp)
movl -0x44(%rbp), %esi
movl $0x8, %edi
xorl %edx, %edx
callq 0x19c90
movq -0x20b8(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x20b0(%rbp)
movl -0x4c(%rbp), %esi
movl $0x5, %edx
movl %edx, %edi
callq 0x19c90
movq -0x20b0(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x20a8(%rbp)
movl $0x4, %edi
xorl %esi, %esi
movl $0x5, %edx
callq 0x19c90
movq -0x20a8(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x20a0(%rbp)
movl $0x5, %edx
movl $0x1, %esi
movl %edx, %edi
callq 0x19c90
movq -0x20a0(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2098(%rbp)
movl $0x4, %edi
xorl %esi, %esi
movl $0x5, %edx
callq 0x19c90
movq -0x2098(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2090(%rbp)
movl $0x1, %edi
xorl %esi, %esi
movl $0x2, %edx
callq 0x19c90
movq -0x2090(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2088(%rbp)
movl $0x5, %edx
movl $0x1, %esi
movl %edx, %edi
callq 0x19c90
movq -0x2088(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2080(%rbp)
movl $0x4, %edi
xorl %esi, %esi
movl $0x5, %edx
callq 0x19c90
movq -0x2080(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x2078(%rbp)
movl $0x1, %edx
xorl %esi, %esi
movl %edx, %edi
callq 0x19c90
movq -0x2078(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
jmp 0x1c9ed
movq -0x10(%rbp), %rax
cmpl $0x4, (%rax)
jne 0x1c922
movq -0x28(%rbp), %rax
movq %rax, -0x20f0(%rbp)
movq -0x10(%rbp), %rax
movl 0x4(%rax), %esi
movl $0x5, %edi
movl $0x4, %edx
callq 0x19c90
movq -0x20f0(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x20e8(%rbp)
xorl %edi, %edi
movl $0x1, %esi
movl $0x5, %edx
callq 0x19c90
movq -0x20e8(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x20e0(%rbp)
movl $0x4, %edx
movl $0x5, %esi
movl %edx, %edi
callq 0x19c90
movq -0x20e0(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
movq -0x28(%rbp), %rax
movq %rax, -0x20d8(%rbp)
movl $0x1, %edi
movl $0x5, %esi
movl $0x4, %edx
callq 0x19c90
movq -0x20d8(%rbp), %rdi
movq %rax, %rsi
callq 0x1a640
jmp 0x1c9eb
jmp 0x1c924
leaq 0x76d9(%rip), %rdi      # 0x24004
leaq 0x8db9(%rip), %rsi      # 0x256eb
movl $0x105, %edx            # imm = 0x105
leaq 0x8dca(%rip), %rcx      # 0x25708
movb $0x0, %al
callq 0x60f0
leaq 0x76e0(%rip), %rdi      # 0x2402c
leaq 0x7a7f(%rip), %rsi      # 0x243d2
movb $0x0, %al
callq 0x60f0
leaq -0x1fa0(%rbp), %rdi
movl $0x3e8, %esi            # imm = 0x3E8
callq 0x60d0
movl %eax, -0x1fa4(%rbp)
leaq -0x1fa0(%rbp), %rdi
movl -0x1fa4(%rbp), %esi
callq 0x60a0
movq %rax, -0x1fb0(%rbp)
leaq 0x76ba(%rip), %rdi      # 0x2404b
movb $0x0, %al
callq 0x60f0
movl $0x0, -0x1fb4(%rbp)
movl -0x1fb4(%rbp), %eax
cmpl -0x1fa4(%rbp), %eax
jge 0x1c9e1
movq -0x1fb0(%rbp), %rax
movslq -0x1fb4(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
leaq 0x7663(%rip), %rdi      # 0x2402c
movb $0x0, %al
callq 0x60f0
movl -0x1fb4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1fb4(%rbp)
jmp 0x1c9a2
movl $0x1, %edi
callq 0x61a0
jmp 0x1c9ed
jmp 0x1c9ef
jmp 0x1c9f1
movq -0x28(%rbp), %rax
addq $0x20f0, %rsp           # imm = 0x20F0
popq %rbp
retq
nop