// File: /workspace/github_c_makefile_star2_O2/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 $0x58, %rsp
testq %rsi, %rsi
je 0x4b78
movq %rdx, %r14
testq %rdx, %rdx
je 0x4ba6
testq %rcx, %rcx
je 0x4bd4
movq %rdi, %r12
movq 0x5f0(%rdi), %rdx
testq %rdx, %rdx
je 0x4c05
movq %rsi, %r15
cmpb $0x1, 0x18(%rsi)
jne 0x4aa9
movq 0xf8(%r12), %rax
testq %rax, %rax
je 0x4aa5
movq %rcx, 0x28(%rsp)
movq 0x38(%rdx), %rbx
movabsq $0x7ffd000000000000, %rcx # imm = 0x7FFD000000000000
leaq 0x50(%rsp), %rbp
movq %rcx, (%rbp)
movq %rbp, 0x38(%rdx)
leaq 0x1c(%r14), %r13
movq %r13, 0x30(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, 0x38(%rsp)
movl 0x14(%r14), %ecx
movl %ecx, 0x48(%rsp)
movl 0x10(%r14), %ecx
movl %ecx, 0x4c(%rsp)
movq 0x20(%r15), %rsi
movl 0x1c(%r15), %edx
movups 0x30(%rsp), %xmm0
movups 0x40(%rsp), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movq %r12, %rdi
callq *%rax
movq 0x5f0(%r12), %rax
movq %rbx, 0x38(%rax)
movq (%rbp), %rax
movabsq $0x7ffd000000000000, %rcx # imm = 0x7FFD000000000000
cmpq %rcx, %rax
jne 0x4b0d
cmpl $0xbdef4147, 0x10(%r14) # imm = 0xBDEF4147
jne 0x4aa5
cmpl $0x9, 0x14(%r14)
jne 0x4aa5
leaq 0x13811(%rip), %rsi     # 0x182a3
pushq $0x9
popq %rdx
movq %r13, %rdi
callq 0x22d0
testl %eax, %eax
je 0x4b26
xorl %eax, %eax
jmp 0x4b17
movq %rcx, 0x28(%rsp)
movq 0x20(%r15), %r12
movq (%r12), %r13
movl 0x30(%r13), %ebp
leaq 0x1c(%r14), %r15
xorl %ebx, %ebx
cmpq %rbx, %rbp
je 0x4aa5
movq 0x10(%r13), %rax
movq 0x28(%r13), %rcx
movl (%rcx,%rbx,4), %ecx
cmpl 0x68(%rax), %ecx
jae 0x4b43
movq 0x60(%rax), %rax
movq (%rax,%rcx,8), %rdi
movl 0x10(%rdi), %eax
cmpl 0x10(%r14), %eax
jne 0x4aff
movl 0x14(%rdi), %edx
cmpl 0x14(%r14), %edx
jne 0x4aff
addq $0x1c, %rdi
movq %r15, %rsi
callq 0x22d0
testl %eax, %eax
je 0x4b04
incq %rbx
jmp 0x4ac0
movq 0x8(%r12), %rax
movq (%rax,%rbx,8), %rax
movq 0x28(%rsp), %rcx
movq %rax, (%rcx)
movb $0x1, %al
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movabsq $-0x4000000000000, %rbx # imm = 0xFFFC000000000000
orq %rbx, %r15
movq %r12, %rdi
movq %r15, %rsi
callq 0x4c36
orq %rbx, %rax
jmp 0x4b0d
movq 0x1e4ae(%rip), %rax     # 0x22ff8
movq (%rax), %rdi
leaq 0x1359c(%rip), %rsi     # 0x180f0
leaq 0x13752(%rip), %rdx     # 0x182ad
leaq 0x13733(%rip), %rcx     # 0x18295
leaq 0x135d3(%rip), %r8      # 0x1813c
movl $0x4c2, %r9d            # imm = 0x4C2
xorl %eax, %eax
callq 0x2250
ud2
movq 0x1e479(%rip), %rax     # 0x22ff8
movq (%rax), %rdi
leaq 0x13567(%rip), %rsi     # 0x180f0
leaq 0x13674(%rip), %rdx     # 0x18204
leaq 0x136fe(%rip), %rcx     # 0x18295
leaq 0x1359e(%rip), %r8      # 0x1813c
movl $0x48e, %r9d            # imm = 0x48E
jmp 0x4b6f
movq 0x1e44b(%rip), %rax     # 0x22ff8
movq (%rax), %rdi
leaq 0x13539(%rip), %rsi     # 0x180f0
leaq 0x13646(%rip), %rdx     # 0x18204
leaq 0x136d0(%rip), %rcx     # 0x18295
leaq 0x13570(%rip), %r8      # 0x1813c
movl $0x48f, %r9d            # imm = 0x48F
jmp 0x4b6f
movq 0x1e41d(%rip), %rax     # 0x22ff8
movq (%rax), %rdi
leaq 0x1350b(%rip), %rsi     # 0x180f0
leaq 0x13618(%rip), %rdx     # 0x18204
leaq 0x136a2(%rip), %rcx     # 0x18295
leaq 0x13542(%rip), %r8      # 0x1813c
movl $0x490, %r9d            # imm = 0x490
jmp 0x4b6f
movq 0x1e3ec(%rip), %rax     # 0x22ff8
movq (%rax), %rdi
leaq 0x134da(%rip), %rsi     # 0x180f0
leaq 0x135e7(%rip), %rdx     # 0x18204
leaq 0x13671(%rip), %rcx     # 0x18295
leaq 0x13511(%rip), %r8      # 0x1813c
movl $0x493, %r9d            # imm = 0x493
jmp 0x4b6f