// File: /workspace/github_c_makefile_star2_O0/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:
subq $0x98, %rsp
movq %rdi, 0x88(%rsp)
movq %rsi, 0x80(%rsp)
movq %rdx, 0x78(%rsp)
movq %rcx, 0x70(%rsp)
cmpq $0x0, 0x80(%rsp)
jne 0x6b56
movq 0x2c4d5(%rip), %rax     # 0x32ff8
movq (%rax), %rdi
leaq 0x23623(%rip), %rsi     # 0x2a150
leaq 0x23730(%rip), %rdx     # 0x2a264
leaq 0x237ba(%rip), %rcx     # 0x2a2f5
leaq 0x2365a(%rip), %r8      # 0x2a19c
movl $0x48e, %r9d            # imm = 0x48E
movb $0x0, %al
callq 0x2240
ud2
callq 0x2040
jmp 0x6b58
jmp 0x6b5a
cmpq $0x0, 0x78(%rsp)
jne 0x6b9c
movq 0x2c48f(%rip), %rax     # 0x32ff8
movq (%rax), %rdi
leaq 0x235dd(%rip), %rsi     # 0x2a150
leaq 0x236ea(%rip), %rdx     # 0x2a264
leaq 0x23774(%rip), %rcx     # 0x2a2f5
leaq 0x23614(%rip), %r8      # 0x2a19c
movl $0x48f, %r9d            # imm = 0x48F
movb $0x0, %al
callq 0x2240
ud2
callq 0x2040
jmp 0x6b9e
jmp 0x6ba0
cmpq $0x0, 0x70(%rsp)
jne 0x6be2
movq 0x2c449(%rip), %rax     # 0x32ff8
movq (%rax), %rdi
leaq 0x23597(%rip), %rsi     # 0x2a150
leaq 0x236a4(%rip), %rdx     # 0x2a264
leaq 0x2372e(%rip), %rcx     # 0x2a2f5
leaq 0x235ce(%rip), %r8      # 0x2a19c
movl $0x490, %r9d            # imm = 0x490
movb $0x0, %al
callq 0x2240
ud2
callq 0x2040
jmp 0x6be4
jmp 0x6be6
movq 0x88(%rsp), %rax
cmpq $0x0, 0x5f0(%rax)
jne 0x6c32
movq 0x2c3f9(%rip), %rax     # 0x32ff8
movq (%rax), %rdi
leaq 0x23547(%rip), %rsi     # 0x2a150
leaq 0x23654(%rip), %rdx     # 0x2a264
leaq 0x236de(%rip), %rcx     # 0x2a2f5
leaq 0x2357e(%rip), %r8      # 0x2a19c
movl $0x493, %r9d            # imm = 0x493
movb $0x0, %al
callq 0x2240
ud2
callq 0x2040
jmp 0x6c34
movq 0x80(%rsp), %rax
testb $0x1, 0x18(%rax)
je 0x6e0a
movq 0x88(%rsp), %rax
cmpq $0x0, 0xf8(%rax)
je 0x6dfd
movq 0x88(%rsp), %rax
movq 0x5f0(%rax), %rax
movq 0x38(%rax), %rax
movq %rax, 0x68(%rsp)
movabsq $0x7ffd000000000000, %rax # imm = 0x7FFD000000000000
movq %rax, 0x60(%rsp)
movq 0x88(%rsp), %rax
movq 0x5f0(%rax), %rax
leaq 0x60(%rsp), %rcx
movq %rcx, 0x38(%rax)
movq 0x78(%rsp), %rax
addq $0x1c, %rax
movq %rax, 0x40(%rsp)
movq $0x0, 0x48(%rsp)
movq $0x0, 0x50(%rsp)
movq 0x78(%rsp), %rax
movl 0x14(%rax), %eax
movl %eax, 0x58(%rsp)
movq 0x78(%rsp), %rax
movl 0x10(%rax), %eax
movl %eax, 0x5c(%rsp)
movq 0x88(%rsp), %rax
movq 0xf8(%rax), %rax
movq 0x88(%rsp), %rdi
movq 0x80(%rsp), %rcx
movq 0x20(%rcx), %rsi
movq 0x80(%rsp), %rcx
movl 0x1c(%rcx), %edx
leaq 0x40(%rsp), %rcx
movq (%rcx), %r8
movq %r8, (%rsp)
movq 0x8(%rcx), %r8
movq %r8, 0x8(%rsp)
movq 0x10(%rcx), %r8
movq %r8, 0x10(%rsp)
movq 0x18(%rcx), %rcx
movq %rcx, 0x18(%rsp)
callq *%rax
movq 0x68(%rsp), %rcx
movq 0x88(%rsp), %rax
movq 0x5f0(%rax), %rax
movq %rcx, 0x38(%rax)
movabsq $0x7ffd000000000000, %rax # imm = 0x7FFD000000000000
cmpq %rax, 0x60(%rsp)
jne 0x6de3
movq 0x78(%rsp), %rax
cmpl $0xbdef4147, 0x10(%rax) # imm = 0xBDEF4147
jne 0x6dd6
movq 0x78(%rsp), %rax
cmpl $0x9, 0x14(%rax)
jne 0x6dd6
movq 0x78(%rsp), %rdi
addq $0x1c, %rdi
leaq 0x23583(%rip), %rsi     # 0x2a303
movl $0x9, %edx
callq 0x2200
cmpl $0x0, %eax
jne 0x6dd6
movq 0x88(%rsp), %rdi
movq 0x80(%rsp), %rsi
movabsq $-0x4000000000000, %rax # imm = 0xFFFC000000000000
orq %rax, %rsi
callq 0x6fc0
movq %rax, %rcx
movabsq $-0x4000000000000, %rax # imm = 0xFFFC000000000000
orq %rax, %rcx
movq 0x70(%rsp), %rax
movq %rcx, (%rax)
movb $0x1, 0x97(%rsp)
jmp 0x6fae
movb $0x0, 0x97(%rsp)
jmp 0x6fae
movq 0x60(%rsp), %rcx
movq 0x70(%rsp), %rax
movq %rcx, (%rax)
movb $0x1, 0x97(%rsp)
jmp 0x6fae
movb $0x0, 0x97(%rsp)
jmp 0x6fae
movq 0x80(%rsp), %rax
movq 0x20(%rax), %rax
movq (%rax), %rax
movq %rax, 0x38(%rsp)
movl $0x0, 0x34(%rsp)
movl 0x34(%rsp), %eax
movq 0x38(%rsp), %rcx
cmpl 0x30(%rcx), %eax
jae 0x6fa6
jmp 0x6e3a
cmpl $0x0, 0x34(%rsp)
jb 0x6e4f
movl 0x34(%rsp), %eax
movq 0x38(%rsp), %rcx
cmpl 0x30(%rcx), %eax
jb 0x6e89
movq 0x2c1a2(%rip), %rax     # 0x32ff8
movq (%rax), %rdi
leaq 0x232f0(%rip), %rsi     # 0x2a150
leaq 0x234a6(%rip), %rdx     # 0x2a30d
leaq 0x23487(%rip), %rcx     # 0x2a2f5
leaq 0x23327(%rip), %r8      # 0x2a19c
movl $0x4c1, %r9d            # imm = 0x4C1
movb $0x0, %al
callq 0x2240
ud2
callq 0x2040
jmp 0x6e8b
jmp 0x6e8d
movq 0x38(%rsp), %rax
movq 0x28(%rax), %rax
movl 0x34(%rsp), %ecx
cmpl $0x0, (%rax,%rcx,4)
jb 0x6ebe
movq 0x38(%rsp), %rax
movq 0x28(%rax), %rax
movl 0x34(%rsp), %ecx
movl (%rax,%rcx,4), %eax
movq 0x38(%rsp), %rcx
movq 0x10(%rcx), %rcx
cmpl 0x68(%rcx), %eax
jb 0x6ef8
movq 0x2c133(%rip), %rax     # 0x32ff8
movq (%rax), %rdi
leaq 0x23281(%rip), %rsi     # 0x2a150
leaq 0x23437(%rip), %rdx     # 0x2a30d
leaq 0x23418(%rip), %rcx     # 0x2a2f5
leaq 0x232b8(%rip), %r8      # 0x2a19c
movl $0x4c2, %r9d            # imm = 0x4C2
movb $0x0, %al
callq 0x2240
ud2
callq 0x2040
jmp 0x6efa
movq 0x38(%rsp), %rax
movq 0x10(%rax), %rax
movq 0x60(%rax), %rax
movq 0x38(%rsp), %rcx
movq 0x28(%rcx), %rcx
movl 0x34(%rsp), %edx
movl (%rcx,%rdx,4), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, 0x28(%rsp)
movq 0x28(%rsp), %rax
movl 0x10(%rax), %eax
movq 0x78(%rsp), %rcx
cmpl 0x10(%rcx), %eax
jne 0x6f94
movq 0x28(%rsp), %rax
movl 0x14(%rax), %eax
movq 0x78(%rsp), %rcx
cmpl 0x14(%rcx), %eax
jne 0x6f94
movq 0x28(%rsp), %rdi
addq $0x1c, %rdi
movq 0x78(%rsp), %rsi
addq $0x1c, %rsi
movq 0x28(%rsp), %rax
movl 0x14(%rax), %eax
movl %eax, %edx
callq 0x2200
cmpl $0x0, %eax
jne 0x6f94
movq 0x80(%rsp), %rax
movq 0x20(%rax), %rax
movq 0x8(%rax), %rax
movl 0x34(%rsp), %ecx
movq (%rax,%rcx,8), %rcx
movq 0x70(%rsp), %rax
movq %rcx, (%rax)
movb $0x1, 0x97(%rsp)
jmp 0x6fae
jmp 0x6f96
movl 0x34(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x34(%rsp)
jmp 0x6e26
movb $0x0, 0x97(%rsp)
movb 0x97(%rsp), %al
andb $0x1, %al
addq $0x98, %rsp
retq
nop