// File: /workspace/github_c_makefile_star2_O0/cogbee[P]vmir-latest/src/vmir_transform.c
// Function: replace_call
static ir_instr_t *
replace_call(ir_unit_t *iu, ir_instr_call_t *ii, ir_function_t *self)
{
  const ir_function_t *f = value_function(iu, ii->callee.value);
  if(f == NULL)
    return &ii->super;

  int op = f->if_vmop;

  if(op == 0) {
    // Not VMOP
    return &ii->super;
  }
  switch(op) {
  case VM_NOP:
    {
      ir_instr_t *next = TAILQ_NEXT(&ii->super, ii_link);
      instr_destroy(&ii->super);
      return next;
    }
  case VM_VASTART:
    {
      ir_instr_call_t *c =
        instr_add_before(sizeof(ir_instr_call_t) +
                         sizeof(ir_instr_arg_t) * 2,
                         IR_IC_CALL, &ii->super);

      c->callee = ii->callee;
      c->argc = 2;
      c->argv[0] = ii->argv[0];
      c->argv[1].value = value_create_const32(iu, self->if_callarg_size,
                                              IR_TYPE_INT32);
      c->argv[1].copy_size = 0;

      instr_destroy(&ii->super);
      ii = c;
      break;
    }
  }

  if(ii->argc < f->if_vmop_args)
    parser_error(iu, "Too few arguments for vmop %s", f->if_name);

  ii->argc = f->if_vmop_args;

  // All arguments must be passed as a register
  for(int i = 0; i < ii->argc; i++) {
    if(ii->argv[i].copy_size) {
      parser_error(iu, "help with vmop registerify");
    }
    registerify(iu, &ii->super, &ii->argv[i].value);
  }
  ii->vmop = f->if_vmop;

  if(ii->super.ii_class == IR_IC_INVOKE) {
    // VMOPs never throws so the invoke needs to get an unconditional
    // branch to the true block
    ir_instr_br_t *br =
      instr_add_after(sizeof(ir_instr_br_t), IR_IC_BR, &ii->super);
    br->true_branch = ii->normal_dest;
    br->condition.value = -1;
  }

  // We just reuse the call struct for the VMOP call
  ii->super.ii_class = IR_IC_VMOP;
  return &ii->super;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0x58(%rax), %esi
callq 0x24040
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
jne 0x25d9c
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x25fa4
movq -0x28(%rbp), %rax
movl 0x38(%rax), %eax
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x25db9
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x25fa4
movl -0x2c(%rbp), %eax
movl %eax, -0x5c(%rbp)
subl $0x1de, %eax            # imm = 0x1DE
je 0x25df9
jmp 0x25dc8
movl -0x5c(%rbp), %eax
subl $0x1fc, %eax            # imm = 0x1FC
jne 0x25e90
jmp 0x25dd8
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x18(%rbp), %rdi
callq 0x1cad0
movq -0x38(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x25fa4
movq -0x18(%rbp), %rdx
movl $0x88, %edi
movl $0xa, %esi
callq 0x26380
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq -0x18(%rbp), %rcx
movq 0x58(%rcx), %rcx
movq %rcx, 0x58(%rax)
movq -0x40(%rbp), %rax
movl $0x2, 0x6c(%rax)
movq -0x40(%rbp), %rax
movq -0x18(%rbp), %rcx
movq 0x70(%rcx), %rdx
movq %rdx, 0x70(%rax)
movl 0x78(%rcx), %ecx
movl %ecx, 0x78(%rax)
movq -0x40(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rax
movl 0x30(%rax), %esi
movl $0x5, %edx
callq 0x1f0f0
movq %rax, %rcx
movq -0x68(%rbp), %rax
movq %rcx, -0x48(%rbp)
movq -0x48(%rbp), %rcx
movq %rcx, 0x7c(%rax)
movq -0x40(%rbp), %rax
movl $0x0, 0x84(%rax)
movq -0x18(%rbp), %rdi
callq 0x1cad0
movq -0x40(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movl 0x6c(%rax), %eax
movq -0x28(%rbp), %rcx
cmpl 0x3c(%rcx), %eax
jge 0x25ec6
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rax
movq 0x20(%rax), %r8
leaq 0x1953a(%rip), %rsi     # 0x3f3ed
movl $0x136, %edx            # imm = 0x136
leaq 0x196e5(%rip), %rcx     # 0x3f5a4
movb $0x0, %al
callq 0x18220
movq -0x28(%rbp), %rax
movl 0x3c(%rax), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x6c(%rax)
movl $0x0, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
movq -0x18(%rbp), %rcx
cmpl 0x6c(%rcx), %eax
jge 0x25f49
movq -0x18(%rbp), %rax
addq $0x70, %rax
movslq -0x4c(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
cmpl $0x0, 0x8(%rax)
je 0x25f1e
movq -0x10(%rbp), %rdi
leaq 0x194e2(%rip), %rsi     # 0x3f3ed
movl $0x13d, %edx            # imm = 0x13D
leaq 0x196ab(%rip), %rcx     # 0x3f5c2
movb $0x0, %al
callq 0x18220
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x18(%rbp), %rdx
addq $0x70, %rdx
movslq -0x4c(%rbp), %rax
imulq $0xc, %rax, %rax
addq %rax, %rdx
callq 0x26400
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x25edb
movq -0x28(%rbp), %rax
movl 0x38(%rax), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x60(%rax)
movq -0x18(%rbp), %rax
cmpl $0xb, 0x28(%rax)
jne 0x25f91
movq -0x18(%rbp), %rdx
movl $0x68, %edi
movl $0x8, %esi
callq 0x265e0
movq %rax, -0x58(%rbp)
movq -0x18(%rbp), %rax
movl 0x64(%rax), %ecx
movq -0x58(%rbp), %rax
movl %ecx, 0x60(%rax)
movq -0x58(%rbp), %rax
movl $0xffffffff, 0x58(%rax) # imm = 0xFFFFFFFF
movq -0x18(%rbp), %rax
movl $0x16, 0x28(%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x70, %rsp
popq %rbp
retq
nop