bool GoASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) { if (!type) return false; GoType *t = static_cast<GoType *>(type); if (t->IsTypedef() || t->GetGoKind() == GoType::KIND_PTR || t->GetArray()) return t->GetElementType().GetCompleteType(); if (GoStruct *s = t->GetStruct()) { if (s->IsComplete()) return true; CompilerType compiler_type(this, s); SymbolFile *symbols = GetSymbolFile(); return symbols && symbols->CompleteType(compiler_type); } return true; }
uint32_t GoASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, CompilerType *pointee_or_element_compiler_type) { if (pointee_or_element_compiler_type) pointee_or_element_compiler_type->Clear(); if (!type) return 0; GoType *t = static_cast<GoType *>(type); if (pointee_or_element_compiler_type) *pointee_or_element_compiler_type = t->GetElementType(); int kind = t->GetGoKind(); if (kind == GoType::KIND_ARRAY) return eTypeHasChildren | eTypeIsArray; if (kind < GoType::KIND_ARRAY) { uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue; if (kind < GoType::KIND_FLOAT32) { builtin_type_flags |= eTypeIsInteger | eTypeIsScalar; if (kind >= GoType::KIND_INT && kind <= GoType::KIND_INT64) builtin_type_flags |= eTypeIsSigned; } else { builtin_type_flags |= eTypeIsFloat; if (kind < GoType::KIND_COMPLEX64) builtin_type_flags |= eTypeIsComplex; else builtin_type_flags |= eTypeIsScalar; } return builtin_type_flags; } if (kind == GoType::KIND_STRING) return eTypeHasValue | eTypeIsBuiltIn; if (kind == GoType::KIND_FUNC) return eTypeIsFuncPrototype | eTypeHasValue; if (IsPointerType(type)) return eTypeIsPointer | eTypeHasValue | eTypeHasChildren; if (kind == GoType::KIND_LLDB_VOID) return 0; return eTypeHasChildren | eTypeIsStructUnion; }
bool GoASTContext::IsPointerType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type) { if (!type) return false; GoType *t = static_cast<GoType *>(type); if (pointee_type) { *pointee_type = t->GetElementType(); } switch (t->GetGoKind()) { case GoType::KIND_PTR: case GoType::KIND_UNSAFEPOINTER: case GoType::KIND_CHAN: case GoType::KIND_MAP: // TODO: is function a pointer? return true; default: return false; } }
// Lookup a child given a name. This function will match base class names // and member member names in "clang_type" only, not descendants. uint32_t GoASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, const char *name, bool omit_empty_base_classes) { if (!type || !GetCompleteType(type)) return UINT_MAX; GoType *t = static_cast<GoType *>(type); GoStruct *s = t->GetStruct(); if (s) { for (uint32_t i = 0; i < s->GetNumFields(); ++i) { const GoStruct::Field *f = s->GetField(i); if (f->m_name.GetStringRef() == name) return i; } } else if (t->GetGoKind() == GoType::KIND_PTR || t->IsTypedef()) { return t->GetElementType().GetIndexOfChildWithName(name, omit_empty_base_classes); } return UINT_MAX; }
uint32_t GoASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, bool omit_empty_base_classes) { if (!type || !GetCompleteType(type)) return 0; GoType *t = static_cast<GoType *>(type); if (t->GetGoKind() == GoType::KIND_PTR) { CompilerType elem = t->GetElementType(); if (elem.IsAggregateType()) return elem.GetNumChildren(omit_empty_base_classes); return 1; } else if (GoArray *array = t->GetArray()) { return array->GetLength(); } else if (t->IsTypedef()) { return t->GetElementType().GetNumChildren(omit_empty_base_classes); } return GetNumFields(type); }
CompilerType GoASTContext::GetChildCompilerTypeAtIndex(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers, bool omit_empty_base_classes, bool ignore_array_bounds, std::string &child_name, uint32_t &child_byte_size, int32_t &child_byte_offset, uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset, bool &child_is_base_class, bool &child_is_deref_of_parent, ValueObject *valobj, uint64_t &language_flags) { child_name.clear(); child_byte_size = 0; child_byte_offset = 0; child_bitfield_bit_size = 0; child_bitfield_bit_offset = 0; child_is_base_class = false; child_is_deref_of_parent = false; language_flags = 0; if (!type || !GetCompleteType(type)) return CompilerType(); GoType *t = static_cast<GoType *>(type); if (t->GetStruct()) { uint64_t bit_offset; CompilerType ret = GetFieldAtIndex(type, idx, child_name, &bit_offset, nullptr, nullptr); child_byte_size = ret.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); child_byte_offset = bit_offset / 8; return ret; } else if (t->GetGoKind() == GoType::KIND_PTR) { CompilerType pointee = t->GetElementType(); if (!pointee.IsValid() || pointee.IsVoidType()) return CompilerType(); if (transparent_pointers && pointee.IsAggregateType()) { bool tmp_child_is_deref_of_parent = false; return pointee.GetChildCompilerTypeAtIndex(exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, tmp_child_is_deref_of_parent, valobj, language_flags); } else { child_is_deref_of_parent = true; const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL; if (parent_name) { child_name.assign(1, '*'); child_name += parent_name; } // We have a pointer to an simple type if (idx == 0 && pointee.GetCompleteType()) { child_byte_size = pointee.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); child_byte_offset = 0; return pointee; } } } else if (GoArray *a = t->GetArray()) { if (ignore_array_bounds || idx < a->GetLength()) { CompilerType element_type = a->GetElementType(); if (element_type.GetCompleteType()) { char element_name[64]; ::snprintf(element_name, sizeof(element_name), "[%zu]", idx); child_name.assign(element_name); child_byte_size = element_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; return element_type; } } } else if (t->IsTypedef()) { return t->GetElementType().GetChildCompilerTypeAtIndex( exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent, valobj, language_flags); } return CompilerType(); }