// File: /workspace/github_c_makefile_star2_O1/atomlang[P]atomlang/src/pk_vm.c
// Function: vmPrepareFiber
bool vmPrepareFiber(PKVM* vm, Fiber* fiber, int argc, Var** argv) {
  ASSERT(fiber->func->arity >= -1, OOPS " (Forget to initialize arity.)");

  if (argc != fiber->func->arity) {
    char buff[STR_INT_BUFF_SIZE]; sprintf(buff, "%d", fiber->func->arity);
    _ERR_FAIL(stringFormat(vm, "Expected exactly $ argument(s).", buff));
  }

  if (fiber->state != FIBER_NEW) {
    switch (fiber->state) {
      case FIBER_NEW: UNREACHABLE();
      case FIBER_RUNNING:
        _ERR_FAIL(newString(vm, "The fiber has already been running."));
      case FIBER_YIELDED:
        _ERR_FAIL(newString(vm, "Cannot run a fiber which is yielded, use "
          "fiber_resume() instead."));
      case FIBER_DONE:
        _ERR_FAIL(newString(vm, "The fiber has done running."));
    }
    UNREACHABLE();
  }

  ASSERT(fiber->stack != NULL && fiber->sp == fiber->stack + 1, OOPS);
  ASSERT(fiber->ret + 1 == fiber->sp, OOPS);

  // Pass the function arguments.

  // Assert we have the first frame (to push the arguments). And assert we have
  // enough stack space for parameters.
  ASSERT(fiber->frame_count == 1, OOPS);
  ASSERT(fiber->frames[0].rbp == fiber->ret, OOPS);
  ASSERT((fiber->stack + fiber->stack_size) - fiber->sp >= argc, OOPS);

  // ARG1 is fiber, function arguments are ARG(2), ARG(3), ... ARG(argc).
  // And ret[0] is the return value, parameters starts at ret[1], ...
  for (int i = 0; i < argc; i++) {
    fiber->ret[1 + i] = *argv[i]; // +1: ret[0] is return value.
  }
  fiber->sp += argc; // Parameters.

  // Set the new fiber as the vm's fiber.
  fiber->caller = vm->fiber;
  vm->fiber = fiber;

  // On success return true.
  return true;
}

// Assembly:
pushq %rbx
subq $0x10, %rsp
movq 0x18(%rsi), %rax
movl 0x20(%rax), %eax
cmpl $-0x2, %eax
jle 0xe1f6
movq %rdi, %rbx
cmpl %edx, %eax
jne 0xe128
movl 0x10(%rsi), %eax
cmpq $0x3, %rax
ja 0xe205
leaq 0xf518(%rip), %rdi      # 0x1d598
movslq (%rdi,%rax,4), %rax
addq %rdi, %rax
jmpq *%rax
movq 0x20(%rsi), %r8
testq %r8, %r8
je 0xe200
movq 0x30(%rsi), %rax
leaq 0x8(%r8), %rdi
cmpq %rdi, %rax
jne 0xe200
movq 0x38(%rsi), %r9
leaq 0x8(%r9), %rdi
cmpq %rax, %rdi
jne 0xe20a
cmpl $0x1, 0x4c(%rsi)
jne 0xe20f
movq 0x40(%rsi), %r10
cmpq %r9, 0x10(%r10)
jne 0xe214
movslq 0x28(%rsi), %r9
leaq (%r8,%r9,8), %r9
subq %rax, %r9
sarq $0x3, %r9
movslq %edx, %r8
cmpq %r8, %r9
jl 0xe219
testl %edx, %edx
jle 0xe107
movl %edx, %edx
xorl %r9d, %r9d
movq (%rcx,%r9,8), %r10
movq (%r10), %r10
movq %r10, (%rdi,%r9,8)
incq %r9
cmpq %r9, %rdx
jne 0xe0f4
leaq (%rax,%r8,8), %rax
movq %rax, 0x30(%rsi)
movq 0x5f0(%rbx), %rax
movq %rax, 0x50(%rsi)
movq %rsi, 0x5f0(%rbx)
movb $0x1, %al
jmp 0xe1f0
leaq 0x128be(%rip), %rsi     # 0x209ed
leaq 0x4(%rsp), %rdi
movl %eax, %edx
xorl %eax, %eax
callq 0x2360
movq 0x5f0(%rbx), %rax
testq %rax, %rax
je 0xe1ee
cmpq $0x0, 0x58(%rax)
jne 0xe1fb
leaq 0xf5f8(%rip), %rsi      # 0x1d757
leaq 0x4(%rsp), %rdx
movq %rbx, %rdi
xorl %eax, %eax
callq 0x95d0
jmp 0xe1e3
movq 0x5f0(%rbx), %rax
testq %rax, %rax
je 0xe1ee
cmpq $0x0, 0x58(%rax)
jne 0xe21e
leaq 0xf60d(%rip), %rsi      # 0x1d79b
movq %rbx, %rdi
movl $0x40, %edx
jmp 0xe1de
movq 0x5f0(%rbx), %rax
testq %rax, %rax
je 0xe1ee
cmpq $0x0, 0x58(%rax)
jne 0xe223
leaq 0xf62a(%rip), %rsi      # 0x1d7dc
movq %rbx, %rdi
movl $0x1b, %edx
jmp 0xe1de
movq 0x5f0(%rbx), %rax
testq %rax, %rax
je 0xe1ee
cmpq $0x0, 0x58(%rax)
jne 0xe228
leaq 0xf5a1(%rip), %rsi      # 0x1d777
movq %rbx, %rdi
movl $0x23, %edx
callq 0x7fc8
movq 0x5f0(%rbx), %rcx
movq %rax, 0x58(%rcx)
xorl %eax, %eax
addq $0x10, %rsp
popq %rbx
retq
callq 0x43cd
callq 0x4403
callq 0x45b3
callq 0x45e9
callq 0x44db
callq 0x4511
callq 0x4547
callq 0x457d
callq 0x4439
callq 0x44a5
callq 0x446f