| //===-- GoASTContext.cpp ----------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include <mutex> |
| #include <utility> |
| #include <vector> |
| |
| #include "lldb/Core/DumpDataExtractor.h" |
| #include "lldb/Core/Module.h" |
| #include "lldb/Core/PluginManager.h" |
| #include "lldb/Core/StreamFile.h" |
| #include "lldb/Core/UniqueCStringMap.h" |
| #include "lldb/Core/ValueObject.h" |
| #include "lldb/Symbol/CompilerType.h" |
| #include "lldb/Symbol/GoASTContext.h" |
| #include "lldb/Symbol/ObjectFile.h" |
| #include "lldb/Symbol/SymbolFile.h" |
| #include "lldb/Symbol/Type.h" |
| #include "lldb/Target/ExecutionContext.h" |
| #include "lldb/Target/Target.h" |
| |
| #include "llvm/Support/Threading.h" |
| |
| #include "Plugins/ExpressionParser/Go/GoUserExpression.h" |
| #include "Plugins/SymbolFile/DWARF/DWARFASTParserGo.h" |
| |
| using namespace lldb; |
| |
| namespace lldb_private { |
| class GoArray; |
| class GoFunction; |
| class GoStruct; |
| |
| class GoType { |
| public: |
| enum { |
| KIND_BOOL = 1, |
| KIND_INT = 2, |
| KIND_INT8 = 3, |
| KIND_INT16 = 4, |
| KIND_INT32 = 5, |
| KIND_INT64 = 6, |
| KIND_UINT = 7, |
| KIND_UINT8 = 8, |
| KIND_UINT16 = 9, |
| KIND_UINT32 = 10, |
| KIND_UINT64 = 11, |
| KIND_UINTPTR = 12, |
| KIND_FLOAT32 = 13, |
| KIND_FLOAT64 = 14, |
| KIND_COMPLEX64 = 15, |
| KIND_COMPLEX128 = 16, |
| KIND_ARRAY = 17, |
| KIND_CHAN = 18, |
| KIND_FUNC = 19, |
| KIND_INTERFACE = 20, |
| KIND_MAP = 21, |
| KIND_PTR = 22, |
| KIND_SLICE = 23, |
| KIND_STRING = 24, |
| KIND_STRUCT = 25, |
| KIND_UNSAFEPOINTER = 26, |
| KIND_LLDB_VOID, // Extension for LLDB, not used by go runtime. |
| KIND_MASK = (1 << 5) - 1, |
| KIND_DIRECT_IFACE = 1 << 5 |
| }; |
| GoType(int kind, const ConstString &name) |
| : m_kind(kind & KIND_MASK), m_name(name) { |
| if (m_kind == KIND_FUNC) |
| m_kind = KIND_FUNC; |
| } |
| virtual ~GoType() {} |
| |
| int GetGoKind() const { return m_kind; } |
| const ConstString &GetName() const { return m_name; } |
| virtual CompilerType GetElementType() const { return CompilerType(); } |
| |
| bool IsTypedef() const { |
| switch (m_kind) { |
| case KIND_CHAN: |
| case KIND_MAP: |
| case KIND_INTERFACE: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| GoArray *GetArray(); |
| GoFunction *GetFunction(); |
| GoStruct *GetStruct(); |
| |
| private: |
| int m_kind; |
| ConstString m_name; |
| GoType(const GoType &) = delete; |
| const GoType &operator=(const GoType &) = delete; |
| }; |
| |
| class GoElem : public GoType { |
| public: |
| GoElem(int kind, const ConstString &name, const CompilerType &elem) |
| : GoType(kind, name), m_elem(elem) {} |
| virtual CompilerType GetElementType() const { return m_elem; } |
| |
| private: |
| // TODO: should we store this differently? |
| CompilerType m_elem; |
| |
| GoElem(const GoElem &) = delete; |
| const GoElem &operator=(const GoElem &) = delete; |
| }; |
| |
| class GoArray : public GoElem { |
| public: |
| GoArray(const ConstString &name, uint64_t length, const CompilerType &elem) |
| : GoElem(KIND_ARRAY, name, elem), m_length(length) {} |
| |
| uint64_t GetLength() const { return m_length; } |
| |
| private: |
| uint64_t m_length; |
| GoArray(const GoArray &) = delete; |
| const GoArray &operator=(const GoArray &) = delete; |
| }; |
| |
| class GoFunction : public GoType { |
| public: |
| GoFunction(const ConstString &name, bool is_variadic) |
| : GoType(KIND_FUNC, name), m_is_variadic(is_variadic) {} |
| |
| bool IsVariadic() const { return m_is_variadic; } |
| |
| private: |
| bool m_is_variadic; |
| GoFunction(const GoFunction &) = delete; |
| const GoFunction &operator=(const GoFunction &) = delete; |
| }; |
| |
| class GoStruct : public GoType { |
| public: |
| struct Field { |
| Field(const ConstString &name, const CompilerType &type, uint64_t offset) |
| : m_name(name), m_type(type), m_byte_offset(offset) {} |
| ConstString m_name; |
| CompilerType m_type; |
| uint64_t m_byte_offset; |
| }; |
| |
| GoStruct(int kind, const ConstString &name, int64_t byte_size) |
| : GoType(kind == 0 ? KIND_STRUCT : kind, name), m_is_complete(false), |
| m_byte_size(byte_size) {} |
| |
| uint32_t GetNumFields() const { return m_fields.size(); } |
| |
| const Field *GetField(uint32_t i) const { |
| if (i < m_fields.size()) |
| return &m_fields[i]; |
| return nullptr; |
| } |
| |
| void AddField(const ConstString &name, const CompilerType &type, |
| uint64_t offset) { |
| m_fields.push_back(Field(name, type, offset)); |
| } |
| |
| bool IsComplete() const { return m_is_complete; } |
| |
| void SetComplete() { m_is_complete = true; } |
| |
| int64_t GetByteSize() const { return m_byte_size; } |
| |
| private: |
| bool m_is_complete; |
| int64_t m_byte_size; |
| std::vector<Field> m_fields; |
| |
| GoStruct(const GoStruct &) = delete; |
| const GoStruct &operator=(const GoStruct &) = delete; |
| }; |
| |
| GoArray *GoType::GetArray() { |
| if (m_kind == KIND_ARRAY) { |
| return static_cast<GoArray *>(this); |
| } |
| return nullptr; |
| } |
| |
| GoFunction *GoType::GetFunction() { |
| if (m_kind == KIND_FUNC) { |
| return static_cast<GoFunction *>(this); |
| } |
| return nullptr; |
| } |
| |
| GoStruct *GoType::GetStruct() { |
| switch (m_kind) { |
| case KIND_STRING: |
| case KIND_STRUCT: |
| case KIND_SLICE: |
| return static_cast<GoStruct *>(this); |
| } |
| return nullptr; |
| } |
| } // namespace lldb_private |
| using namespace lldb_private; |
| |
| GoASTContext::GoASTContext() |
| : TypeSystem(eKindGo), m_pointer_byte_size(0), m_int_byte_size(0), |
| m_types(new TypeMap) {} |
| GoASTContext::~GoASTContext() {} |
| |
| //------------------------------------------------------------------ |
| // PluginInterface functions |
| //------------------------------------------------------------------ |
| |
| ConstString GoASTContext::GetPluginNameStatic() { return ConstString("go"); } |
| |
| ConstString GoASTContext::GetPluginName() { |
| return GoASTContext::GetPluginNameStatic(); |
| } |
| |
| uint32_t GoASTContext::GetPluginVersion() { return 1; } |
| |
| lldb::TypeSystemSP GoASTContext::CreateInstance(lldb::LanguageType language, |
| Module *module, |
| Target *target) { |
| if (language == eLanguageTypeGo) { |
| ArchSpec arch; |
| std::shared_ptr<GoASTContext> go_ast_sp; |
| if (module) { |
| arch = module->GetArchitecture(); |
| go_ast_sp = std::shared_ptr<GoASTContext>(new GoASTContext); |
| } else if (target) { |
| arch = target->GetArchitecture(); |
| go_ast_sp = std::shared_ptr<GoASTContextForExpr>( |
| new GoASTContextForExpr(target->shared_from_this())); |
| } |
| |
| if (arch.IsValid()) { |
| go_ast_sp->SetAddressByteSize(arch.GetAddressByteSize()); |
| return go_ast_sp; |
| } |
| } |
| return lldb::TypeSystemSP(); |
| } |
| |
| void GoASTContext::EnumerateSupportedLanguages( |
| std::set<lldb::LanguageType> &languages_for_types, |
| std::set<lldb::LanguageType> &languages_for_expressions) { |
| static std::vector<lldb::LanguageType> s_supported_languages_for_types( |
| {lldb::eLanguageTypeGo}); |
| |
| static std::vector<lldb::LanguageType> s_supported_languages_for_expressions( |
| {}); |
| |
| languages_for_types.insert(s_supported_languages_for_types.begin(), |
| s_supported_languages_for_types.end()); |
| languages_for_expressions.insert( |
| s_supported_languages_for_expressions.begin(), |
| s_supported_languages_for_expressions.end()); |
| } |
| |
| void GoASTContext::Initialize() { |
| PluginManager::RegisterPlugin(GetPluginNameStatic(), "AST context plug-in", |
| CreateInstance, EnumerateSupportedLanguages); |
| } |
| |
| void GoASTContext::Terminate() { |
| PluginManager::UnregisterPlugin(CreateInstance); |
| } |
| |
| //---------------------------------------------------------------------- |
| // Tests |
| //---------------------------------------------------------------------- |
| |
| bool GoASTContext::IsArrayType(lldb::opaque_compiler_type_t type, |
| CompilerType *element_type, uint64_t *size, |
| bool *is_incomplete) { |
| if (element_type) |
| element_type->Clear(); |
| if (size) |
| *size = 0; |
| if (is_incomplete) |
| *is_incomplete = false; |
| GoArray *array = static_cast<GoType *>(type)->GetArray(); |
| if (array) { |
| if (size) |
| *size = array->GetLength(); |
| if (element_type) |
| *element_type = array->GetElementType(); |
| return true; |
| } |
| return false; |
| } |
| |
| bool GoASTContext::IsVectorType(lldb::opaque_compiler_type_t type, |
| CompilerType *element_type, uint64_t *size) { |
| if (element_type) |
| element_type->Clear(); |
| if (size) |
| *size = 0; |
| return false; |
| } |
| |
| bool GoASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) { |
| int kind = static_cast<GoType *>(type)->GetGoKind(); |
| if (kind < GoType::KIND_ARRAY) |
| return false; |
| if (kind == GoType::KIND_PTR) |
| return false; |
| if (kind == GoType::KIND_CHAN) |
| return false; |
| if (kind == GoType::KIND_MAP) |
| return false; |
| if (kind == GoType::KIND_STRING) |
| return false; |
| if (kind == GoType::KIND_UNSAFEPOINTER) |
| return false; |
| return true; |
| } |
| |
| bool GoASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) { |
| return false; |
| } |
| |
| bool GoASTContext::IsCharType(lldb::opaque_compiler_type_t type) { |
| // Go's DWARF doesn't distinguish between rune and int32. |
| return false; |
| } |
| |
| bool GoASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) { |
| if (!type) |
| return false; |
| GoType *t = static_cast<GoType *>(type); |
| if (GoStruct *s = t->GetStruct()) |
| return s->IsComplete(); |
| if (t->IsTypedef() || t->GetGoKind() == GoType::KIND_PTR) |
| return t->GetElementType().IsCompleteType(); |
| return true; |
| } |
| |
| bool GoASTContext::IsConst(lldb::opaque_compiler_type_t type) { return false; } |
| |
| bool GoASTContext::IsCStringType(lldb::opaque_compiler_type_t type, |
| uint32_t &length) { |
| return false; |
| } |
| |
| bool GoASTContext::IsDefined(lldb::opaque_compiler_type_t type) { |
| return type != nullptr; |
| } |
| |
| bool GoASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type, |
| uint32_t &count, bool &is_complex) { |
| int kind = static_cast<GoType *>(type)->GetGoKind(); |
| if (kind >= GoType::KIND_FLOAT32 && kind <= GoType::KIND_COMPLEX128) { |
| if (kind >= GoType::KIND_COMPLEX64) { |
| is_complex = true; |
| count = 2; |
| } else { |
| is_complex = false; |
| count = 1; |
| } |
| return true; |
| } |
| count = 0; |
| is_complex = false; |
| return false; |
| } |
| |
| bool GoASTContext::IsFunctionType(lldb::opaque_compiler_type_t type, |
| bool *is_variadic_ptr) { |
| GoFunction *func = static_cast<GoType *>(type)->GetFunction(); |
| if (func) { |
| if (is_variadic_ptr) |
| *is_variadic_ptr = func->IsVariadic(); |
| return true; |
| } |
| if (is_variadic_ptr) |
| *is_variadic_ptr = false; |
| return false; |
| } |
| |
| uint32_t GoASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, |
| CompilerType *base_type_ptr) { |
| return false; |
| } |
| |
| size_t |
| GoASTContext::GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) { |
| return 0; |
| } |
| |
| CompilerType |
| GoASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, |
| const size_t index) { |
| return CompilerType(); |
| } |
| |
| bool GoASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) { |
| return IsFunctionType(type); |
| } |
| |
| bool GoASTContext::IsBlockPointerType(lldb::opaque_compiler_type_t type, |
| CompilerType *function_pointer_type_ptr) { |
| return false; |
| } |
| |
| bool GoASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, |
| bool &is_signed) { |
| is_signed = false; |
| // TODO: Is bool an integer? |
| if (type) { |
| int kind = static_cast<GoType *>(type)->GetGoKind(); |
| if (kind <= GoType::KIND_UINTPTR) { |
| is_signed = (kind != GoType::KIND_BOOL) & (kind <= GoType::KIND_INT64); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| bool GoASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) { |
| return false; |
| } |
| |
| bool GoASTContext::IsPossibleDynamicType( |
| lldb::opaque_compiler_type_t type, |
| CompilerType *target_type, // Can pass NULL |
| bool check_cplusplus, bool check_objc) { |
| if (target_type) |
| target_type->Clear(); |
| if (type) |
| return static_cast<GoType *>(type)->GetGoKind() == GoType::KIND_INTERFACE; |
| return false; |
| } |
| |
| bool GoASTContext::IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) { |
| return false; |
| } |
| |
| 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; |
| } |
| } |
| |
| bool GoASTContext::IsPointerOrReferenceType(lldb::opaque_compiler_type_t type, |
| CompilerType *pointee_type) { |
| return IsPointerType(type, pointee_type); |
| } |
| |
| bool GoASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, |
| CompilerType *pointee_type, |
| bool *is_rvalue) { |
| return false; |
| } |
| |
| bool GoASTContext::IsScalarType(lldb::opaque_compiler_type_t type) { |
| return !IsAggregateType(type); |
| } |
| |
| bool GoASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) { |
| if (type) |
| return static_cast<GoType *>(type)->IsTypedef(); |
| return false; |
| } |
| |
| bool GoASTContext::IsVoidType(lldb::opaque_compiler_type_t type) { |
| if (!type) |
| return false; |
| return static_cast<GoType *>(type)->GetGoKind() == GoType::KIND_LLDB_VOID; |
| } |
| |
| bool GoASTContext::SupportsLanguage(lldb::LanguageType language) { |
| return language == eLanguageTypeGo; |
| } |
| |
| //---------------------------------------------------------------------- |
| // Type Completion |
| //---------------------------------------------------------------------- |
| |
| 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; |
| } |
| |
| //---------------------------------------------------------------------- |
| // AST related queries |
| //---------------------------------------------------------------------- |
| |
| uint32_t GoASTContext::GetPointerByteSize() { return m_pointer_byte_size; } |
| |
| //---------------------------------------------------------------------- |
| // Accessors |
| //---------------------------------------------------------------------- |
| |
| ConstString GoASTContext::GetTypeName(lldb::opaque_compiler_type_t type) { |
| if (type) |
| return static_cast<GoType *>(type)->GetName(); |
| return ConstString(); |
| } |
| |
| 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; |
| } |
| |
| lldb::TypeClass GoASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) { |
| if (!type) |
| return eTypeClassInvalid; |
| int kind = static_cast<GoType *>(type)->GetGoKind(); |
| if (kind == GoType::KIND_FUNC) |
| return eTypeClassFunction; |
| if (IsPointerType(type)) |
| return eTypeClassPointer; |
| if (kind < GoType::KIND_COMPLEX64) |
| return eTypeClassBuiltin; |
| if (kind <= GoType::KIND_COMPLEX128) |
| return eTypeClassComplexFloat; |
| if (kind == GoType::KIND_LLDB_VOID) |
| return eTypeClassInvalid; |
| return eTypeClassStruct; |
| } |
| |
| lldb::BasicType |
| GoASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) { |
| ConstString name = GetTypeName(type); |
| if (name) { |
| typedef UniqueCStringMap<lldb::BasicType> TypeNameToBasicTypeMap; |
| static TypeNameToBasicTypeMap g_type_map; |
| static llvm::once_flag g_once_flag; |
| llvm::call_once(g_once_flag, []() { |
| // "void" |
| g_type_map.Append(ConstString("void"), eBasicTypeVoid); |
| // "int" |
| g_type_map.Append(ConstString("int"), eBasicTypeInt); |
| g_type_map.Append(ConstString("uint"), eBasicTypeUnsignedInt); |
| |
| // Miscellaneous |
| g_type_map.Append(ConstString("bool"), eBasicTypeBool); |
| |
| // Others. Should these map to C types? |
| g_type_map.Append(ConstString("byte"), eBasicTypeOther); |
| g_type_map.Append(ConstString("uint8"), eBasicTypeOther); |
| g_type_map.Append(ConstString("uint16"), eBasicTypeOther); |
| g_type_map.Append(ConstString("uint32"), eBasicTypeOther); |
| g_type_map.Append(ConstString("uint64"), eBasicTypeOther); |
| g_type_map.Append(ConstString("int8"), eBasicTypeOther); |
| g_type_map.Append(ConstString("int16"), eBasicTypeOther); |
| g_type_map.Append(ConstString("int32"), eBasicTypeOther); |
| g_type_map.Append(ConstString("int64"), eBasicTypeOther); |
| g_type_map.Append(ConstString("float32"), eBasicTypeOther); |
| g_type_map.Append(ConstString("float64"), eBasicTypeOther); |
| g_type_map.Append(ConstString("uintptr"), eBasicTypeOther); |
| |
| g_type_map.Sort(); |
| }); |
| |
| return g_type_map.Find(name, eBasicTypeInvalid); |
| } |
| return eBasicTypeInvalid; |
| } |
| |
| lldb::LanguageType |
| GoASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) { |
| return lldb::eLanguageTypeGo; |
| } |
| |
| unsigned GoASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) { |
| return 0; |
| } |
| |
| //---------------------------------------------------------------------- |
| // Creating related types |
| //---------------------------------------------------------------------- |
| |
| CompilerType |
| GoASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, |
| uint64_t *stride) { |
| GoArray *array = static_cast<GoType *>(type)->GetArray(); |
| if (array) { |
| if (stride) { |
| *stride = array->GetElementType().GetByteSize(nullptr); |
| } |
| return array->GetElementType(); |
| } |
| return CompilerType(); |
| } |
| |
| CompilerType GoASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) { |
| GoType *t = static_cast<GoType *>(type); |
| if (t->IsTypedef()) |
| return t->GetElementType(); |
| return CompilerType(this, type); |
| } |
| |
| CompilerType |
| GoASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) { |
| return CompilerType(this, type); |
| } |
| |
| // Returns -1 if this isn't a function of if the function doesn't have a |
| // prototype Returns a value >= 0 if there is a prototype. |
| int GoASTContext::GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) { |
| return GetNumberOfFunctionArguments(type); |
| } |
| |
| CompilerType |
| GoASTContext::GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type, |
| size_t idx) { |
| return GetFunctionArgumentAtIndex(type, idx); |
| } |
| |
| CompilerType |
| GoASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) { |
| CompilerType result; |
| if (type) { |
| GoType *t = static_cast<GoType *>(type); |
| if (t->GetGoKind() == GoType::KIND_FUNC) |
| result = t->GetElementType(); |
| } |
| return result; |
| } |
| |
| size_t GoASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) { |
| return 0; |
| } |
| |
| TypeMemberFunctionImpl |
| GoASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, |
| size_t idx) { |
| return TypeMemberFunctionImpl(); |
| } |
| |
| CompilerType |
| GoASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) { |
| return CompilerType(this, type); |
| } |
| |
| CompilerType GoASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) { |
| if (!type) |
| return CompilerType(); |
| return static_cast<GoType *>(type)->GetElementType(); |
| } |
| |
| CompilerType GoASTContext::GetPointerType(lldb::opaque_compiler_type_t type) { |
| if (!type) |
| return CompilerType(); |
| ConstString type_name = GetTypeName(type); |
| ConstString pointer_name(std::string("*") + type_name.GetCString()); |
| GoType *pointer = (*m_types)[pointer_name].get(); |
| if (pointer == nullptr) { |
| pointer = |
| new GoElem(GoType::KIND_PTR, pointer_name, CompilerType(this, type)); |
| (*m_types)[pointer_name].reset(pointer); |
| } |
| return CompilerType(this, pointer); |
| } |
| |
| // If the current object represents a typedef type, get the underlying type |
| CompilerType GoASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) { |
| if (IsTypedefType(type)) |
| return static_cast<GoType *>(type)->GetElementType(); |
| return CompilerType(); |
| } |
| |
| //---------------------------------------------------------------------- |
| // Create related types using the current type's AST |
| //---------------------------------------------------------------------- |
| CompilerType GoASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) { |
| return CompilerType(); |
| } |
| |
| CompilerType |
| GoASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, |
| size_t bit_size) { |
| return CompilerType(); |
| } |
| |
| //---------------------------------------------------------------------- |
| // Exploring the type |
| //---------------------------------------------------------------------- |
| |
| uint64_t GoASTContext::GetBitSize(lldb::opaque_compiler_type_t type, |
| ExecutionContextScope *exe_scope) { |
| if (!type) |
| return 0; |
| if (!GetCompleteType(type)) |
| return 0; |
| GoType *t = static_cast<GoType *>(type); |
| GoArray *array = nullptr; |
| switch (t->GetGoKind()) { |
| case GoType::KIND_BOOL: |
| case GoType::KIND_INT8: |
| case GoType::KIND_UINT8: |
| return 8; |
| case GoType::KIND_INT16: |
| case GoType::KIND_UINT16: |
| return 16; |
| case GoType::KIND_INT32: |
| case GoType::KIND_UINT32: |
| case GoType::KIND_FLOAT32: |
| return 32; |
| case GoType::KIND_INT64: |
| case GoType::KIND_UINT64: |
| case GoType::KIND_FLOAT64: |
| case GoType::KIND_COMPLEX64: |
| return 64; |
| case GoType::KIND_COMPLEX128: |
| return 128; |
| case GoType::KIND_INT: |
| case GoType::KIND_UINT: |
| return m_int_byte_size * 8; |
| case GoType::KIND_UINTPTR: |
| case GoType::KIND_FUNC: // I assume this is a pointer? |
| case GoType::KIND_CHAN: |
| case GoType::KIND_PTR: |
| case GoType::KIND_UNSAFEPOINTER: |
| case GoType::KIND_MAP: |
| return m_pointer_byte_size * 8; |
| case GoType::KIND_ARRAY: |
| array = t->GetArray(); |
| return array->GetLength() * array->GetElementType().GetBitSize(exe_scope); |
| case GoType::KIND_INTERFACE: |
| return t->GetElementType().GetBitSize(exe_scope); |
| case GoType::KIND_SLICE: |
| case GoType::KIND_STRING: |
| case GoType::KIND_STRUCT: |
| return t->GetStruct()->GetByteSize() * 8; |
| default: |
| assert(false); |
| } |
| return 0; |
| } |
| |
| lldb::Encoding GoASTContext::GetEncoding(lldb::opaque_compiler_type_t type, |
| uint64_t &count) { |
| count = 1; |
| bool is_signed; |
| if (IsIntegerType(type, is_signed)) |
| return is_signed ? lldb::eEncodingSint : eEncodingUint; |
| bool is_complex; |
| uint32_t complex_count; |
| if (IsFloatingPointType(type, complex_count, is_complex)) { |
| count = complex_count; |
| return eEncodingIEEE754; |
| } |
| if (IsPointerType(type)) |
| return eEncodingUint; |
| return eEncodingInvalid; |
| } |
| |
| lldb::Format GoASTContext::GetFormat(lldb::opaque_compiler_type_t type) { |
| if (!type) |
| return eFormatDefault; |
| switch (static_cast<GoType *>(type)->GetGoKind()) { |
| case GoType::KIND_BOOL: |
| return eFormatBoolean; |
| case GoType::KIND_INT: |
| case GoType::KIND_INT8: |
| case GoType::KIND_INT16: |
| case GoType::KIND_INT32: |
| case GoType::KIND_INT64: |
| return eFormatDecimal; |
| case GoType::KIND_UINT: |
| case GoType::KIND_UINT8: |
| case GoType::KIND_UINT16: |
| case GoType::KIND_UINT32: |
| case GoType::KIND_UINT64: |
| return eFormatUnsigned; |
| case GoType::KIND_FLOAT32: |
| case GoType::KIND_FLOAT64: |
| return eFormatFloat; |
| case GoType::KIND_COMPLEX64: |
| case GoType::KIND_COMPLEX128: |
| return eFormatComplexFloat; |
| case GoType::KIND_UINTPTR: |
| case GoType::KIND_CHAN: |
| case GoType::KIND_PTR: |
| case GoType::KIND_MAP: |
| case GoType::KIND_UNSAFEPOINTER: |
| return eFormatHex; |
| case GoType::KIND_STRING: |
| return eFormatCString; |
| case GoType::KIND_ARRAY: |
| case GoType::KIND_INTERFACE: |
| case GoType::KIND_SLICE: |
| case GoType::KIND_STRUCT: |
| default: |
| // Don't know how to display this. |
| return eFormatBytes; |
| } |
| } |
| |
| size_t GoASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) { |
| return 0; |
| } |
| |
| 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); |
| } |
| |
| uint32_t GoASTContext::GetNumFields(lldb::opaque_compiler_type_t type) { |
| if (!type || !GetCompleteType(type)) |
| return 0; |
| GoType *t = static_cast<GoType *>(type); |
| if (t->IsTypedef()) |
| return t->GetElementType().GetNumFields(); |
| GoStruct *s = t->GetStruct(); |
| if (s) |
| return s->GetNumFields(); |
| return 0; |
| } |
| |
| CompilerType GoASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, |
| size_t idx, std::string &name, |
| uint64_t *bit_offset_ptr, |
| uint32_t *bitfield_bit_size_ptr, |
| bool *is_bitfield_ptr) { |
| if (bit_offset_ptr) |
| *bit_offset_ptr = 0; |
| if (bitfield_bit_size_ptr) |
| *bitfield_bit_size_ptr = 0; |
| if (is_bitfield_ptr) |
| *is_bitfield_ptr = false; |
| |
| if (!type || !GetCompleteType(type)) |
| return CompilerType(); |
| |
| GoType *t = static_cast<GoType *>(type); |
| if (t->IsTypedef()) |
| return t->GetElementType().GetFieldAtIndex( |
| idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr); |
| |
| GoStruct *s = t->GetStruct(); |
| if (s) { |
| const auto *field = s->GetField(idx); |
| if (field) { |
| name = field->m_name.GetStringRef(); |
| if (bit_offset_ptr) |
| *bit_offset_ptr = field->m_byte_offset * 8; |
| return field->m_type; |
| } |
| } |
| return CompilerType(); |
| } |
| |
| 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(); |
| } |
| |
| // 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; |
| } |
| |
| // Lookup a child member given a name. This function will match member names |
| // only and will descend into "clang_type" children in search for the first |
| // member in this class, or any base class that matches "name". |
| // TODO: Return all matches for a given name by returning a |
| // vector<vector<uint32_t>> |
| // so we catch all names that match a given child name, not just the first. |
| size_t GoASTContext::GetIndexOfChildMemberWithName( |
| lldb::opaque_compiler_type_t type, const char *name, |
| bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) { |
| uint32_t index = GetIndexOfChildWithName(type, name, omit_empty_base_classes); |
| if (index == UINT_MAX) |
| return 0; |
| child_indexes.push_back(index); |
| return 1; |
| } |
| |
| // Converts "s" to a floating point value and place resulting floating point |
| // bytes in the "dst" buffer. |
| size_t |
| GoASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, |
| const char *s, uint8_t *dst, |
| size_t dst_size) { |
| assert(false); |
| return 0; |
| } |
| //---------------------------------------------------------------------- |
| // Dumping types |
| //---------------------------------------------------------------------- |
| #define DEPTH_INCREMENT 2 |
| |
| void GoASTContext::DumpValue(lldb::opaque_compiler_type_t type, |
| ExecutionContext *exe_ctx, Stream *s, |
| lldb::Format format, const DataExtractor &data, |
| lldb::offset_t data_byte_offset, |
| size_t data_byte_size, uint32_t bitfield_bit_size, |
| uint32_t bitfield_bit_offset, bool show_types, |
| bool show_summary, bool verbose, uint32_t depth) { |
| if (IsTypedefType(type)) |
| type = GetTypedefedType(type).GetOpaqueQualType(); |
| if (!type) |
| return; |
| GoType *t = static_cast<GoType *>(type); |
| |
| if (GoStruct *st = t->GetStruct()) { |
| if (GetCompleteType(type)) { |
| uint32_t field_idx = 0; |
| for (auto *field = st->GetField(field_idx); field != nullptr; |
| field_idx++) { |
| // Print the starting squiggly bracket (if this is the first member) or |
| // comma (for member 2 and beyond) for the struct/union/class member. |
| if (field_idx == 0) |
| s->PutChar('{'); |
| else |
| s->PutChar(','); |
| |
| // Indent |
| s->Printf("\n%*s", depth + DEPTH_INCREMENT, ""); |
| |
| // Print the member type if requested |
| if (show_types) { |
| ConstString field_type_name = field->m_type.GetTypeName(); |
| s->Printf("(%s) ", field_type_name.AsCString()); |
| } |
| // Print the member name and equal sign |
| s->Printf("%s = ", field->m_name.AsCString()); |
| |
| // Dump the value of the member |
| CompilerType field_type = field->m_type; |
| field_type.DumpValue( |
| exe_ctx, |
| s, // Stream to dump to |
| field_type |
| .GetFormat(), // The format with which to display the member |
| data, // Data buffer containing all bytes for this type |
| data_byte_offset + field->m_byte_offset, // Offset into "data" where |
| // to grab value from |
| field->m_type.GetByteSize( |
| exe_ctx->GetBestExecutionContextScope()), // Size of this type |
| // in bytes |
| 0, // Bitfield bit size |
| 0, // Bitfield bit offset |
| show_types, // Boolean indicating if we should show the variable |
| // types |
| show_summary, // Boolean indicating if we should show a summary for |
| // the current type |
| verbose, // Verbose output? |
| depth + DEPTH_INCREMENT); // Scope depth for any types that have |
| // children |
| } |
| |
| // Indent the trailing squiggly bracket |
| if (field_idx > 0) |
| s->Printf("\n%*s}", depth, ""); |
| } |
| } |
| |
| if (GoArray *a = t->GetArray()) { |
| CompilerType element_clang_type = a->GetElementType(); |
| lldb::Format element_format = element_clang_type.GetFormat(); |
| uint32_t element_byte_size = |
| element_clang_type.GetByteSize(exe_ctx->GetBestExecutionContextScope()); |
| |
| uint64_t element_idx; |
| for (element_idx = 0; element_idx < a->GetLength(); ++element_idx) { |
| // Print the starting squiggly bracket (if this is the first member) or |
| // comman (for member 2 and beyong) for the struct/union/class member. |
| if (element_idx == 0) |
| s->PutChar('{'); |
| else |
| s->PutChar(','); |
| |
| // Indent and print the index |
| s->Printf("\n%*s[%" PRIu64 "] ", depth + DEPTH_INCREMENT, "", |
| element_idx); |
| |
| // Figure out the field offset within the current struct/union/class type |
| uint64_t element_offset = element_idx * element_byte_size; |
| |
| // Dump the value of the member |
| element_clang_type.DumpValue( |
| exe_ctx, |
| s, // Stream to dump to |
| element_format, // The format with which to display the element |
| data, // Data buffer containing all bytes for this type |
| data_byte_offset + |
| element_offset, // Offset into "data" where to grab value from |
| element_byte_size, // Size of this type in bytes |
| 0, // Bitfield bit size |
| 0, // Bitfield bit offset |
| show_types, // Boolean indicating if we should show the variable types |
| show_summary, // Boolean indicating if we should show a summary for |
| // the current type |
| verbose, // Verbose output? |
| depth + |
| DEPTH_INCREMENT); // Scope depth for any types that have children |
| } |
| |
| // Indent the trailing squiggly bracket |
| if (element_idx > 0) |
| s->Printf("\n%*s}", depth, ""); |
| } |
| |
| if (show_summary) |
| DumpSummary(type, exe_ctx, s, data, data_byte_offset, data_byte_size); |
| } |
| |
| bool GoASTContext::DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s, |
| lldb::Format format, const DataExtractor &data, |
| lldb::offset_t byte_offset, size_t byte_size, |
| uint32_t bitfield_bit_size, |
| uint32_t bitfield_bit_offset, |
| ExecutionContextScope *exe_scope) { |
| if (!type) |
| return false; |
| if (IsAggregateType(type)) { |
| return false; |
| } else { |
| GoType *t = static_cast<GoType *>(type); |
| if (t->IsTypedef()) { |
| CompilerType typedef_compiler_type = t->GetElementType(); |
| if (format == eFormatDefault) |
| format = typedef_compiler_type.GetFormat(); |
| uint64_t typedef_byte_size = typedef_compiler_type.GetByteSize(exe_scope); |
| |
| return typedef_compiler_type.DumpTypeValue( |
| s, |
| format, // The format with which to display the element |
| data, // Data buffer containing all bytes for this type |
| byte_offset, // Offset into "data" where to grab value from |
| typedef_byte_size, // Size of this type in bytes |
| bitfield_bit_size, // Size in bits of a bitfield value, if zero don't |
| // treat as a bitfield |
| bitfield_bit_offset, // Offset in bits of a bitfield value if |
| // bitfield_bit_size != 0 |
| exe_scope); |
| } |
| |
| uint32_t item_count = 1; |
| // A few formats, we might need to modify our size and count for depending |
| // on how we are trying to display the value... |
| switch (format) { |
| default: |
| case eFormatBoolean: |
| case eFormatBinary: |
| case eFormatComplex: |
| case eFormatCString: // NULL terminated C strings |
| case eFormatDecimal: |
| case eFormatEnum: |
| case eFormatHex: |
| case eFormatHexUppercase: |
| case eFormatFloat: |
| case eFormatOctal: |
| case eFormatOSType: |
| case eFormatUnsigned: |
| case eFormatPointer: |
| case eFormatVectorOfChar: |
| case eFormatVectorOfSInt8: |
| case eFormatVectorOfUInt8: |
| case eFormatVectorOfSInt16: |
| case eFormatVectorOfUInt16: |
| case eFormatVectorOfSInt32: |
| case eFormatVectorOfUInt32: |
| case eFormatVectorOfSInt64: |
| case eFormatVectorOfUInt64: |
| case eFormatVectorOfFloat32: |
| case eFormatVectorOfFloat64: |
| case eFormatVectorOfUInt128: |
| break; |
| |
| case eFormatChar: |
| case eFormatCharPrintable: |
| case eFormatCharArray: |
| case eFormatBytes: |
| case eFormatBytesWithASCII: |
| item_count = byte_size; |
| byte_size = 1; |
| break; |
| |
| case eFormatUnicode16: |
| item_count = byte_size / 2; |
| byte_size = 2; |
| break; |
| |
| case eFormatUnicode32: |
| item_count = byte_size / 4; |
| byte_size = 4; |
| break; |
| } |
| return DumpDataExtractor(data, s, byte_offset, format, byte_size, |
| item_count, UINT32_MAX, LLDB_INVALID_ADDRESS, |
| bitfield_bit_size, bitfield_bit_offset, exe_scope); |
| } |
| return 0; |
| } |
| |
| void GoASTContext::DumpSummary(lldb::opaque_compiler_type_t type, |
| ExecutionContext *exe_ctx, Stream *s, |
| const DataExtractor &data, |
| lldb::offset_t data_offset, |
| size_t data_byte_size) { |
| if (type && GoType::KIND_STRING == static_cast<GoType *>(type)->GetGoKind()) { |
| // TODO(ribrdb): read length and data |
| } |
| } |
| |
| void GoASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) { |
| // Dump to stdout |
| StreamFile s(stdout, false); |
| DumpTypeDescription(type, &s); |
| } |
| |
| void GoASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, |
| Stream *s) { |
| if (!type) |
| return; |
| ConstString name = GetTypeName(type); |
| GoType *t = static_cast<GoType *>(type); |
| |
| if (GoStruct *st = t->GetStruct()) { |
| if (GetCompleteType(type)) { |
| if (NULL == strchr(name.AsCString(), '{')) |
| s->Printf("type %s ", name.AsCString()); |
| s->PutCString("struct {"); |
| if (st->GetNumFields() == 0) { |
| s->PutChar('}'); |
| return; |
| } |
| s->IndentMore(); |
| uint32_t field_idx = 0; |
| for (auto *field = st->GetField(field_idx); field != nullptr; |
| field_idx++) { |
| s->PutChar('\n'); |
| s->Indent(); |
| s->Printf("%s %s", field->m_name.AsCString(), |
| field->m_type.GetTypeName().AsCString()); |
| } |
| s->IndentLess(); |
| s->PutChar('\n'); |
| s->Indent("}"); |
| return; |
| } |
| } |
| |
| s->PutCString(name.AsCString()); |
| } |
| |
| CompilerType GoASTContext::CreateArrayType(const ConstString &name, |
| const CompilerType &element_type, |
| uint64_t length) { |
| GoType *type = new GoArray(name, length, element_type); |
| (*m_types)[name].reset(type); |
| return CompilerType(this, type); |
| } |
| |
| CompilerType GoASTContext::CreateBaseType(int go_kind, |
| const lldb_private::ConstString &name, |
| uint64_t byte_size) { |
| if (go_kind == GoType::KIND_UINT || go_kind == GoType::KIND_INT) |
| m_int_byte_size = byte_size; |
| GoType *type = new GoType(go_kind, name); |
| (*m_types)[name].reset(type); |
| return CompilerType(this, type); |
| } |
| |
| CompilerType GoASTContext::CreateTypedefType(int kind, const ConstString &name, |
| CompilerType impl) { |
| GoType *type = new GoElem(kind, name, impl); |
| (*m_types)[name].reset(type); |
| return CompilerType(this, type); |
| } |
| |
| CompilerType |
| GoASTContext::CreateVoidType(const lldb_private::ConstString &name) { |
| GoType *type = new GoType(GoType::KIND_LLDB_VOID, name); |
| (*m_types)[name].reset(type); |
| return CompilerType(this, type); |
| } |
| |
| CompilerType |
| GoASTContext::CreateStructType(int kind, const lldb_private::ConstString &name, |
| uint32_t byte_size) { |
| GoType *type = new GoStruct(kind, name, byte_size); |
| (*m_types)[name].reset(type); |
| return CompilerType(this, type); |
| } |
| |
| void GoASTContext::AddFieldToStruct( |
| const lldb_private::CompilerType &struct_type, |
| const lldb_private::ConstString &name, |
| const lldb_private::CompilerType &field_type, uint32_t byte_offset) { |
| if (!struct_type) |
| return; |
| GoASTContext *ast = |
| llvm::dyn_cast_or_null<GoASTContext>(struct_type.GetTypeSystem()); |
| if (!ast) |
| return; |
| GoType *type = static_cast<GoType *>(struct_type.GetOpaqueQualType()); |
| if (GoStruct *s = type->GetStruct()) |
| s->AddField(name, field_type, byte_offset); |
| } |
| |
| void GoASTContext::CompleteStructType( |
| const lldb_private::CompilerType &struct_type) { |
| if (!struct_type) |
| return; |
| GoASTContext *ast = |
| llvm::dyn_cast_or_null<GoASTContext>(struct_type.GetTypeSystem()); |
| if (!ast) |
| return; |
| GoType *type = static_cast<GoType *>(struct_type.GetOpaqueQualType()); |
| if (GoStruct *s = type->GetStruct()) |
| s->SetComplete(); |
| } |
| |
| CompilerType |
| GoASTContext::CreateFunctionType(const lldb_private::ConstString &name, |
| CompilerType *params, size_t params_count, |
| bool is_variadic) { |
| GoType *type = new GoFunction(name, is_variadic); |
| (*m_types)[name].reset(type); |
| return CompilerType(this, type); |
| } |
| |
| bool GoASTContext::IsGoString(const lldb_private::CompilerType &type) { |
| if (!type.IsValid() || |
| !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem())) |
| return false; |
| return GoType::KIND_STRING == |
| static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind(); |
| } |
| |
| bool GoASTContext::IsGoSlice(const lldb_private::CompilerType &type) { |
| if (!type.IsValid() || |
| !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem())) |
| return false; |
| return GoType::KIND_SLICE == |
| static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind(); |
| } |
| |
| bool GoASTContext::IsGoInterface(const lldb_private::CompilerType &type) { |
| if (!type.IsValid() || |
| !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem())) |
| return false; |
| return GoType::KIND_INTERFACE == |
| static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind(); |
| } |
| |
| bool GoASTContext::IsPointerKind(uint8_t kind) { |
| return (kind & GoType::KIND_MASK) == GoType::KIND_PTR; |
| } |
| |
| bool GoASTContext::IsDirectIface(uint8_t kind) { |
| return (kind & GoType::KIND_DIRECT_IFACE) == GoType::KIND_DIRECT_IFACE; |
| } |
| |
| DWARFASTParser *GoASTContext::GetDWARFParser() { |
| if (!m_dwarf_ast_parser_ap) |
| m_dwarf_ast_parser_ap.reset(new DWARFASTParserGo(*this)); |
| return m_dwarf_ast_parser_ap.get(); |
| } |
| |
| UserExpression *GoASTContextForExpr::GetUserExpression( |
| llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language, |
| Expression::ResultType desired_type, |
| const EvaluateExpressionOptions &options) { |
| TargetSP target = m_target_wp.lock(); |
| if (target) |
| return new GoUserExpression(*target, expr, prefix, language, desired_type, |
| options); |
| return nullptr; |
| } |