// File: /workspace/github_c_makefile_star2_O3/atomlang[P]atomlang/src/pk_var.c
// Function: instGetAttrib
bool instGetAttrib(PKVM* vm, Instance* inst, String* attrib, Var* value) {
  ASSERT(inst != NULL, OOPS);
  ASSERT(attrib != NULL, OOPS);
  ASSERT(value != NULL, OOPS);

  // This function should only be called at runtime.
  ASSERT(vm->fiber != NULL, OOPS);

  if (inst->is_native) {

    if (vm->config.inst_get_attrib_fn) {
      // Temproarly change the fiber's "return address" to points to the
      // below var 'val' so that the users can use 'pkReturn...()' function
      // to return the attribute as well.
      Var* temp = vm->fiber->ret;
      Var val = VAR_UNDEFINED;

      vm->fiber->ret = &val;
      PkStringPtr attr = { attrib->data, NULL, NULL,
                           attrib->length, attrib->hash };
      vm->config.inst_get_attrib_fn(vm, inst->native, inst->native_id, attr);
      vm->fiber->ret = temp;

      if (IS_UNDEF(val)) {

        // FIXME: add a list of attribute overrides.
        if (IS_CSTR_EQ(attrib, "as_string", 9,
          CHECK_HASH("as_string", 0xbdef4147))) {
          *value = VAR_OBJ(toRepr(vm, VAR_OBJ(inst)));
          return true;
        }

        // If we reached here, the native instance don't have the attribute
        // and no overriden attributes found, return false to indicate that the
        // attribute doesn't exists.
        return false;
      }

      // Attribute [val] updated by the hosting application.
      *value = val;
      return true;
    }

    // If the hosting application doesn't provided a getter function, we treat
    // it as if the instance don't has the attribute.
    return false;

  } else {

    // TODO: Optimize this with binary search.
    Class* ty = inst->ins->type;
    for (uint32_t i = 0; i < ty->field_names.count; i++) {
      ASSERT_INDEX(i, ty->field_names.count);
      ASSERT_INDEX(ty->field_names.data[i], ty->owner->names.count);
      String* f_name = ty->owner->names.data[ty->field_names.data[i]];
      if (IS_STR_EQ(f_name, attrib)) {
        *value = inst->ins->fields.data[i];
        return true;
      }
    }

    // Couldn't find the attribute in it's type class, return false.
    return false;
  }

  UNREACHABLE();
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
testq %rsi, %rsi
je 0xa6c1
movq %rdx, %r14
testq %rdx, %rdx
je 0xa6c6
testq %rcx, %rcx
je 0xa6cb
movq %rdi, %r12
movq 0x5f0(%rdi), %rdx
testq %rdx, %rdx
je 0xa6d0
movq %rsi, %r15
cmpb $0x1, 0x18(%rsi)
jne 0xa623
movq 0xf8(%r12), %rax
testq %rax, %rax
je 0xa692
movq %rcx, 0x28(%rsp)
movq 0x38(%rdx), %r13
movabsq $0x7ffd000000000000, %rcx # imm = 0x7FFD000000000000
leaq 0x60(%rsp), %rbp
movq %rcx, (%rbp)
movq %rbp, 0x38(%rdx)
leaq 0x1c(%r14), %rbx
movq %rbx, 0x40(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, 0x48(%rsp)
movl 0x14(%r14), %ecx
movl %ecx, 0x58(%rsp)
movl 0x10(%r14), %ecx
movl %ecx, 0x5c(%rsp)
movq 0x20(%r15), %rsi
movl 0x1c(%r15), %edx
movups 0x40(%rsp), %xmm0
movups 0x50(%rsp), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movq %r12, %rdi
callq *%rax
movq 0x5f0(%r12), %rax
movq %r13, 0x38(%rax)
movq (%rbp), %rax
movabsq $0x7ffd000000000000, %rcx # imm = 0x7FFD000000000000
cmpq %rcx, %rax
jne 0xa6a3
cmpl $0xbdef4147, 0x10(%r14) # imm = 0xBDEF4147
jne 0xa692
cmpl $0x9, 0x14(%r14)
jne 0xa692
movabsq $0x6e697274735f7361, %rax # imm = 0x6E697274735F7361
xorq (%rbx), %rax
movzbl 0x8(%rbx), %ecx
xorq $0x67, %rcx
orq %rax, %rcx
jne 0xa692
movabsq $-0x4000000000000, %rbx # imm = 0xFFFC000000000000
orq %rbx, %r15
movq %r12, %rdi
movq %r15, %rsi
callq 0xa6d5
orq %rbx, %rax
jmp 0xa6a3
movq 0x20(%r15), %rdx
movq (%rdx), %rax
movl 0x30(%rax), %r13d
testq %r13, %r13
je 0xa692
movq %rdx, 0x30(%rsp)
movq %rcx, 0x28(%rsp)
movq 0x10(%rax), %rbp
movq 0x28(%rax), %rbx
movl 0x68(%rbp), %r15d
leaq 0x1c(%r14), %rax
movq %rax, 0x38(%rsp)
xorl %r12d, %r12d
movl (%rbx,%r12,4), %eax
cmpl %r15d, %eax
jae 0xa6bc
movq 0x60(%rbp), %rcx
movq (%rcx,%rax,8), %rdi
movl 0x10(%rdi), %eax
cmpl 0x10(%r14), %eax
jne 0xa68a
movl 0x14(%rdi), %edx
cmpl 0x14(%r14), %edx
jne 0xa68a
addq $0x1c, %rdi
movq 0x38(%rsp), %rsi
callq 0x22d0
testl %eax, %eax
je 0xa696
incq %r12
cmpq %r12, %r13
jne 0xa655
xorl %eax, %eax
jmp 0xa6ad
movq 0x30(%rsp), %rax
movq 0x8(%rax), %rax
movq (%rax,%r12,8), %rax
movq 0x28(%rsp), %rcx
movq %rax, (%rcx)
movb $0x1, %al
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x2760
callq 0x2838
callq 0x2802
callq 0x27cc
callq 0x2796