[Lldb-commits] [lldb] r247629 - Add a TypeSystem for Go
Ryan Brown via lldb-commits
lldb-commits at lists.llvm.org
Mon Sep 14 15:45:12 PDT 2015
Author: ribrdb
Date: Mon Sep 14 17:45:11 2015
New Revision: 247629
URL: http://llvm.org/viewvc/llvm-project?rev=247629&view=rev
Log:
Add a TypeSystem for Go
Add GoASTContext and DWARFASTParserGo to support go.
Differential Revision: http://reviews.llvm.org/D12585
Added:
lldb/trunk/include/lldb/Symbol/GoASTContext.h
lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
lldb/trunk/source/Symbol/GoASTContext.cpp
lldb/trunk/test/lang/go/
lldb/trunk/test/lang/go/types/
lldb/trunk/test/lang/go/types/TestGoASTContext.py
lldb/trunk/test/lang/go/types/main.go
Modified:
lldb/trunk/include/lldb/Core/Module.h
lldb/trunk/include/lldb/Symbol/ClangASTContext.h
lldb/trunk/include/lldb/Symbol/CompilerType.h
lldb/trunk/include/lldb/lldb-forward.h
lldb/trunk/lldb.xcodeproj/project.pbxproj
lldb/trunk/source/Core/Module.cpp
lldb/trunk/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
lldb/trunk/source/Symbol/CMakeLists.txt
lldb/trunk/source/Symbol/ClangASTContext.cpp
lldb/trunk/source/Symbol/SymbolFile.cpp
lldb/trunk/test/lldbtest.py
Modified: lldb/trunk/include/lldb/Core/Module.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Module.h?rev=247629&r1=247628&r2=247629&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Module.h (original)
+++ lldb/trunk/include/lldb/Core/Module.h Mon Sep 14 17:45:11 2015
@@ -1119,7 +1119,8 @@ protected:
lldb::SymbolVendorUP m_symfile_ap; ///< A pointer to the symbol vendor for this module.
std::vector<lldb::SymbolVendorUP> m_old_symfiles; ///< If anyone calls Module::SetSymbolFileFileSpec() and changes the symbol file,
///< we need to keep all old symbol files around in case anyone has type references to them
- lldb::ClangASTContextUP m_ast; ///< The AST context for this module.
+ lldb::ClangASTContextUP m_ast; ///< The Clang AST context for this module.
+ lldb::GoASTContextUP m_go_ast; ///< The Go AST context for this module.
PathMappingList m_source_mappings; ///< Module specific source remappings for when you have debug info for a module that doesn't match where the sources currently are
lldb::SectionListUP m_sections_ap; ///< Unified section list for module that is used by the ObjectFile and and ObjectFile instances for the debug info
Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=247629&r1=247628&r2=247629&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Mon Sep 14 17:45:11 2015
@@ -485,7 +485,6 @@ public:
//------------------------------------------------------------------
// TypeSystem methods
//------------------------------------------------------------------
-
DWARFASTParser *
GetDWARFParser () override;
Modified: lldb/trunk/include/lldb/Symbol/CompilerType.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/CompilerType.h?rev=247629&r1=247628&r2=247629&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/CompilerType.h (original)
+++ lldb/trunk/include/lldb/Symbol/CompilerType.h Mon Sep 14 17:45:11 2015
@@ -318,7 +318,6 @@ public:
static lldb::BasicType
GetBasicTypeEnumeration (const ConstString &name);
-
//----------------------------------------------------------------------
// If this type is an enumeration, iterate through all of its enumerators
// using a callback. If the callback returns true, keep iterating, else
Added: lldb/trunk/include/lldb/Symbol/GoASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/GoASTContext.h?rev=247629&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Symbol/GoASTContext.h (added)
+++ lldb/trunk/include/lldb/Symbol/GoASTContext.h Mon Sep 14 17:45:11 2015
@@ -0,0 +1,335 @@
+//===-- GoASTContext.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __lldb__GoASTContext__
+#define __lldb__GoASTContext__
+
+#include <map>
+#include "lldb/Core/ConstString.h"
+#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Symbol/CompilerType.h"
+
+namespace lldb_private
+{
+
+class Declaration;
+class GoType;
+
+class GoASTContext : public TypeSystem
+{
+ public:
+ GoASTContext();
+ ~GoASTContext();
+
+ DWARFASTParser *GetDWARFParser() override;
+
+ void
+ SetAddressByteSize(int byte_size)
+ {
+ m_pointer_byte_size = byte_size;
+ }
+
+ //------------------------------------------------------------------
+ // llvm casting support
+ //------------------------------------------------------------------
+ static bool classof(const TypeSystem *ts)
+ {
+ return ts->getKind() == TypeSystem::eKindGo;
+ }
+
+ //----------------------------------------------------------------------
+ // CompilerDeclContext functions
+ //----------------------------------------------------------------------
+
+ virtual bool
+ DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) override
+ {
+ return false;
+ }
+
+ virtual ConstString
+ DeclContextGetName(void *opaque_decl_ctx) override
+ {
+ return ConstString();
+ }
+
+ virtual bool
+ DeclContextIsClassMethod(void *opaque_decl_ctx, lldb::LanguageType *language_ptr, bool *is_instance_method_ptr,
+ ConstString *language_object_name_ptr) override
+ {
+ return false;
+ }
+
+ //----------------------------------------------------------------------
+ // Creating Types
+ //----------------------------------------------------------------------
+
+ CompilerType CreateArrayType(const ConstString &name, const CompilerType &element_type, int64_t length);
+
+ CompilerType CreateBaseType(int go_kind, const ConstString &type_name_const_str, uint64_t byte_size);
+
+ // For interface, map, chan.
+ CompilerType CreateTypedef(int kind, const ConstString &name, CompilerType impl);
+
+ CompilerType CreateVoidType(const ConstString &name);
+ CompilerType CreateFunctionType(const lldb_private::ConstString &name, CompilerType *params, size_t params_count,
+ bool is_variadic);
+
+ CompilerType CreateStructType(int kind, const ConstString &name, uint32_t byte_size);
+
+ void CompleteStructType(const CompilerType &type);
+
+ void AddFieldToStruct(const CompilerType &struct_type, const ConstString &name, const CompilerType &field_type,
+ uint32_t byte_offset);
+
+ //----------------------------------------------------------------------
+ // Tests
+ //----------------------------------------------------------------------
+
+ static bool IsGoString(const CompilerType &type);
+ static bool IsGoSlice(const CompilerType &type);
+ static bool IsGoInterface(const CompilerType &type);
+ static bool IsDirectIface(uint8_t kind);
+ static bool IsPointerKind(uint8_t kind);
+
+ virtual bool IsArrayType(void *type, CompilerType *element_type, uint64_t *size, bool *is_incomplete) override;
+
+ virtual bool IsAggregateType(void *type) override;
+
+ virtual bool IsCharType(void *type) override;
+
+ virtual bool IsCompleteType(void *type) override;
+
+ virtual bool IsDefined(void *type) override;
+
+ virtual bool IsFloatingPointType(void *type, uint32_t &count, bool &is_complex) override;
+
+ virtual bool IsFunctionType(void *type, bool *is_variadic_ptr = NULL) override;
+
+ virtual size_t GetNumberOfFunctionArguments(void *type) override;
+
+ virtual CompilerType GetFunctionArgumentAtIndex(void *type, const size_t index) override;
+
+ virtual bool IsFunctionPointerType(void *type) override;
+
+ virtual bool IsIntegerType(void *type, bool &is_signed) override;
+
+ virtual bool IsPossibleDynamicType(void *type,
+ CompilerType *target_type, // Can pass NULL
+ bool check_cplusplus, bool check_objc) override;
+
+ virtual bool IsPointerType(void *type, CompilerType *pointee_type = NULL) override;
+
+ virtual bool IsScalarType(void *type) override;
+
+ virtual bool IsVoidType(void *type) override;
+
+ //----------------------------------------------------------------------
+ // Type Completion
+ //----------------------------------------------------------------------
+
+ virtual bool GetCompleteType(void *type) override;
+
+ //----------------------------------------------------------------------
+ // AST related queries
+ //----------------------------------------------------------------------
+
+ virtual uint32_t GetPointerByteSize() override;
+
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+
+ virtual ConstString GetTypeName(void *type) override;
+
+ virtual uint32_t GetTypeInfo(void *type, CompilerType *pointee_or_element_clang_type = NULL) override;
+
+ virtual lldb::LanguageType GetMinimumLanguage(void *type) override;
+
+ virtual lldb::TypeClass GetTypeClass(void *type) override;
+
+ //----------------------------------------------------------------------
+ // Creating related types
+ //----------------------------------------------------------------------
+
+ virtual CompilerType GetArrayElementType(void *type, uint64_t *stride = nullptr) override;
+
+ virtual CompilerType GetCanonicalType(void *type) override;
+
+ // 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.
+ virtual int GetFunctionArgumentCount(void *type) override;
+
+ virtual CompilerType GetFunctionArgumentTypeAtIndex(void *type, size_t idx) override;
+
+ virtual CompilerType GetFunctionReturnType(void *type) override;
+
+ virtual size_t GetNumMemberFunctions(void *type) override;
+
+ virtual TypeMemberFunctionImpl GetMemberFunctionAtIndex(void *type, size_t idx) override;
+
+ virtual CompilerType GetPointeeType(void *type) override;
+
+ virtual CompilerType GetPointerType(void *type) override;
+
+ //----------------------------------------------------------------------
+ // Exploring the type
+ //----------------------------------------------------------------------
+
+ virtual uint64_t GetBitSize(void *type, ExecutionContextScope *exe_scope) override;
+
+ virtual lldb::Encoding GetEncoding(void *type, uint64_t &count) override;
+
+ virtual lldb::Format GetFormat(void *type) override;
+
+ virtual uint32_t GetNumChildren(void *type, bool omit_empty_base_classes) override;
+
+ virtual lldb::BasicType GetBasicTypeEnumeration(void *type) override;
+ virtual CompilerType GetIntTypeFromBitSize (size_t bit_size, bool is_signed) override;
+ virtual CompilerType GetFloatTypeFromBitSize (size_t bit_size) override;
+
+
+ virtual uint32_t GetNumFields(void *type) override;
+
+ virtual CompilerType GetFieldAtIndex(void *type, size_t idx, std::string &name, uint64_t *bit_offset_ptr,
+ uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) override;
+
+ virtual uint32_t
+ GetNumDirectBaseClasses(void *type) override
+ {
+ return 0;
+ }
+
+ virtual uint32_t
+ GetNumVirtualBaseClasses(void *type) override
+ {
+ return 0;
+ }
+
+ virtual CompilerType
+ GetDirectBaseClassAtIndex(void *type, size_t idx, uint32_t *bit_offset_ptr) override
+ {
+ return CompilerType();
+ }
+
+ virtual CompilerType
+ GetVirtualBaseClassAtIndex(void *type, size_t idx, uint32_t *bit_offset_ptr) override
+ {
+ return CompilerType();
+ }
+
+ virtual CompilerType GetChildClangTypeAtIndex(void *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) override;
+
+ // Lookup a child given a name. This function will match base class names
+ // and member member names in "clang_type" only, not descendants.
+ virtual uint32_t GetIndexOfChildWithName(void *type, const char *name, bool omit_empty_base_classes) override;
+
+ // 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.
+ virtual size_t GetIndexOfChildMemberWithName(void *type, const char *name, bool omit_empty_base_classes,
+ std::vector<uint32_t> &child_indexes) override;
+
+ virtual size_t
+ GetNumTemplateArguments(void *type) override
+ {
+ return 0;
+ }
+
+ virtual CompilerType
+ GetTemplateArgument(void *type, size_t idx, lldb::TemplateArgumentKind &kind) override
+ {
+ return CompilerType();
+ }
+
+ //----------------------------------------------------------------------
+ // Dumping types
+ //----------------------------------------------------------------------
+ virtual void DumpValue(void *type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format,
+ const DataExtractor &data, lldb::offset_t data_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) override;
+
+ virtual bool DumpTypeValue(void *type, Stream *s, lldb::Format format, const DataExtractor &data,
+ lldb::offset_t data_offset, size_t data_byte_size, uint32_t bitfield_bit_size,
+ uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope) override;
+
+ virtual void DumpTypeDescription(void *type) override; // Dump to stdout
+
+ virtual void DumpTypeDescription(void *type, Stream *s) override;
+
+ //----------------------------------------------------------------------
+ // TODO: These methods appear unused. Should they be removed?
+ //----------------------------------------------------------------------
+
+ virtual bool IsRuntimeGeneratedType(void *type) override;
+
+ virtual void DumpSummary(void *type, ExecutionContext *exe_ctx, Stream *s, const DataExtractor &data,
+ lldb::offset_t data_offset, size_t data_byte_size) override;
+
+ // Converts "s" to a floating point value and place resulting floating
+ // point bytes in the "dst" buffer.
+ virtual size_t ConvertStringToFloatValue(void *type, const char *s, uint8_t *dst, size_t dst_size) override;
+
+ //----------------------------------------------------------------------
+ // TODO: Determine if these methods should move to ClangASTContext.
+ //----------------------------------------------------------------------
+
+ virtual bool IsPointerOrReferenceType(void *type, CompilerType *pointee_type = NULL) override;
+
+ virtual unsigned GetTypeQualifiers(void *type) override;
+
+ virtual bool IsCStringType(void *type, uint32_t &length) override;
+
+ virtual size_t GetTypeBitAlign(void *type) override;
+
+ virtual CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) override;
+
+ virtual bool IsBeingDefined(void *type) override;
+
+ virtual bool IsConst(void *type) override;
+
+ virtual uint32_t IsHomogeneousAggregate(void *type, CompilerType *base_type_ptr) override;
+
+ virtual bool IsPolymorphicClass(void *type) override;
+
+ virtual bool IsTypedefType(void *type) override;
+
+ // If the current object represents a typedef type, get the underlying type
+ virtual CompilerType GetTypedefedType(void *type) override;
+
+ virtual bool IsVectorType(void *type, CompilerType *element_type, uint64_t *size) override;
+
+ virtual CompilerType GetFullyUnqualifiedType(void *type) override;
+
+ virtual CompilerType GetNonReferenceType(void *type) override;
+
+ virtual bool IsReferenceType(void *type, CompilerType *pointee_type = nullptr, bool *is_rvalue = nullptr) override;
+
+ private:
+ typedef std::map<ConstString, std::unique_ptr<GoType>> TypeMap;
+ int m_pointer_byte_size;
+ int m_int_byte_size;
+ std::unique_ptr<TypeMap> m_types;
+ std::unique_ptr<DWARFASTParser> m_dwarf_ast_parser_ap;
+
+ GoASTContext(const GoASTContext &) = delete;
+ const GoASTContext &operator=(const GoASTContext &) = delete;
+};
+}
+
+#endif /* defined(__lldb__GoASTContext__) */
Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=247629&r1=247628&r2=247629&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Mon Sep 14 17:45:11 2015
@@ -99,6 +99,7 @@ class File;
class FileSpec;
class FileSpecList;
class Flags;
+class GoASTContext;
class TypeCategoryImpl;
class FormatManager;
class FormattersMatchCandidate;
@@ -326,6 +327,7 @@ namespace lldb {
typedef std::shared_ptr<lldb_private::File> FileSP;
typedef std::shared_ptr<lldb_private::Function> FunctionSP;
typedef std::shared_ptr<lldb_private::FuncUnwinders> FuncUnwindersSP;
+ typedef std::unique_ptr<lldb_private::GoASTContext> GoASTContextUP;
typedef std::shared_ptr<lldb_private::InlineFunctionInfo> InlineFunctionInfoSP;
typedef std::shared_ptr<lldb_private::Instruction> InstructionSP;
typedef std::shared_ptr<lldb_private::InstrumentationRuntime> InstrumentationRuntimeSP;
Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=247629&r1=247628&r2=247629&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Mon Sep 14 17:45:11 2015
@@ -814,6 +814,8 @@
9AC703AF117675410086C050 /* SBInstruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703AE117675410086C050 /* SBInstruction.cpp */; };
9AC703B1117675490086C050 /* SBInstructionList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703B0117675490086C050 /* SBInstructionList.cpp */; };
A36FF33C17D8E94600244D40 /* OptionParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A36FF33B17D8E94600244D40 /* OptionParser.cpp */; };
+ AE6897281B94F6DE0018845D /* DWARFASTParserGo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE6897261B94F6DE0018845D /* DWARFASTParserGo.cpp */; };
+ AE7F56291B8FE418001377A8 /* GoASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEFFBA7C1AC4835D0087B932 /* GoASTContext.cpp */; };
AEEA34051AC88A7400AB639D /* TypeSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEEA34041AC88A7400AB639D /* TypeSystem.cpp */; };
AF061F87182C97ED00B6A19C /* RegisterContextHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF061F85182C97ED00B6A19C /* RegisterContextHistory.cpp */; };
AF0C112818580CD800C4C45B /* QueueItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF0C112718580CD800C4C45B /* QueueItem.cpp */; };
@@ -2611,8 +2613,12 @@
9AF16CC7114086A1007A7B3F /* SBBreakpointLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBBreakpointLocation.cpp; path = source/API/SBBreakpointLocation.cpp; sourceTree = "<group>"; };
A36FF33B17D8E94600244D40 /* OptionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OptionParser.cpp; sourceTree = "<group>"; };
A36FF33D17D8E98800244D40 /* OptionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionParser.h; path = include/lldb/Host/OptionParser.h; sourceTree = "<group>"; };
+ AE6897261B94F6DE0018845D /* DWARFASTParserGo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFASTParserGo.cpp; sourceTree = "<group>"; };
+ AE6897271B94F6DE0018845D /* DWARFASTParserGo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFASTParserGo.h; sourceTree = "<group>"; };
AEEA33F61AC74FE700AB639D /* TypeSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeSystem.h; path = include/lldb/Symbol/TypeSystem.h; sourceTree = "<group>"; };
AEEA34041AC88A7400AB639D /* TypeSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeSystem.cpp; path = source/Symbol/TypeSystem.cpp; sourceTree = "<group>"; };
+ AEEA340F1ACA08A000AB639D /* GoASTContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GoASTContext.h; path = include/lldb/Symbol/GoASTContext.h; sourceTree = "<group>"; };
+ AEFFBA7C1AC4835D0087B932 /* GoASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoASTContext.cpp; path = source/Symbol/GoASTContext.cpp; sourceTree = "<group>"; };
AF061F85182C97ED00B6A19C /* RegisterContextHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextHistory.cpp; path = Utility/RegisterContextHistory.cpp; sourceTree = "<group>"; };
AF061F86182C97ED00B6A19C /* RegisterContextHistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextHistory.h; path = Utility/RegisterContextHistory.h; sourceTree = "<group>"; };
AF061F89182C980000B6A19C /* HistoryThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HistoryThread.h; path = Utility/HistoryThread.h; sourceTree = "<group>"; };
@@ -3124,6 +3130,8 @@
269DDD451B8FD01A00D0DBD8 /* DWARFASTParser.h */,
269DDD491B8FD1C300D0DBD8 /* DWARFASTParserClang.h */,
269DDD481B8FD1C300D0DBD8 /* DWARFASTParserClang.cpp */,
+ AE6897271B94F6DE0018845D /* DWARFASTParserGo.h */,
+ AE6897261B94F6DE0018845D /* DWARFASTParserGo.cpp */,
260C89B610F57C5600BB2B04 /* DWARFAttribute.h */,
266E829C1B8E542C008FCA06 /* DWARFAttribute.cpp */,
260C89B710F57C5600BB2B04 /* DWARFCompileUnit.cpp */,
@@ -4208,6 +4216,8 @@
26BC7F1810F1B8EC00F91463 /* Function.cpp */,
269FF07D12494F7D00225026 /* FuncUnwinders.h */,
961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */,
+ AEEA340F1ACA08A000AB639D /* GoASTContext.h */,
+ AEFFBA7C1AC4835D0087B932 /* GoASTContext.cpp */,
26BC7C5B10F1B6E900F91463 /* LineEntry.h */,
26BC7F1910F1B8EC00F91463 /* LineEntry.cpp */,
26BC7C5C10F1B6E900F91463 /* LineTable.h */,
@@ -6314,6 +6324,7 @@
2689007C13353E1A00698AC0 /* Symbols.cpp in Sources */,
2689007D13353E2200698AC0 /* Args.cpp in Sources */,
2689007F13353E2200698AC0 /* CommandCompletions.cpp in Sources */,
+ AE6897281B94F6DE0018845D /* DWARFASTParserGo.cpp in Sources */,
945261C41B9A11FC00BF138D /* LibCxxUnorderedMap.cpp in Sources */,
26CEB5F218762056008F575A /* CommandObjectGUI.cpp in Sources */,
2689008013353E2200698AC0 /* CommandInterpreter.cpp in Sources */,
@@ -6630,6 +6641,7 @@
260CC64C15D0440D002BF2E0 /* OptionValueDictionary.cpp in Sources */,
49DCF6FE170E6B4A0092F75E /* IRMemoryMap.cpp in Sources */,
260CC64D15D0440D002BF2E0 /* OptionValueEnumeration.cpp in Sources */,
+ AE7F56291B8FE418001377A8 /* GoASTContext.cpp in Sources */,
260CC64E15D0440D002BF2E0 /* OptionValueFileSpec.cpp in Sources */,
AF2BCA6C18C7EFDE005B4526 /* JITLoaderGDB.cpp in Sources */,
260CC64F15D0440D002BF2E0 /* OptionValueFileSpecLIst.cpp in Sources */,
Modified: lldb/trunk/source/Core/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Module.cpp?rev=247629&r1=247628&r2=247629&view=diff
==============================================================================
--- lldb/trunk/source/Core/Module.cpp (original)
+++ lldb/trunk/source/Core/Module.cpp Mon Sep 14 17:45:11 2015
@@ -25,6 +25,7 @@
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/GoASTContext.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolVendor.h"
@@ -148,6 +149,7 @@ Module::Module (const ModuleSpec &module
m_objfile_sp (),
m_symfile_ap (),
m_ast (new ClangASTContext),
+ m_go_ast(),
m_source_mappings (),
m_sections_ap(),
m_did_load_objfile (false),
@@ -252,6 +254,7 @@ Module::Module(const FileSpec& file_spec
m_objfile_sp (),
m_symfile_ap (),
m_ast (new ClangASTContext),
+ m_go_ast(),
m_source_mappings (),
m_sections_ap(),
m_did_load_objfile (false),
@@ -298,6 +301,7 @@ Module::Module () :
m_objfile_sp (),
m_symfile_ap (),
m_ast (new ClangASTContext),
+ m_go_ast(),
m_source_mappings (),
m_sections_ap(),
m_did_load_objfile (false),
@@ -420,7 +424,22 @@ Module::GetUUID()
TypeSystem *
Module::GetTypeSystemForLanguage (LanguageType language)
{
- if (language != eLanguageTypeSwift)
+ if (language == eLanguageTypeGo)
+ {
+ Mutex::Locker locker (m_mutex);
+ if (!m_go_ast)
+ {
+ ObjectFile * objfile = GetObjectFile();
+ ArchSpec object_arch;
+ if (objfile && objfile->GetArchitecture(object_arch))
+ {
+ m_go_ast.reset(new GoASTContext);
+ m_go_ast->SetAddressByteSize(object_arch.GetAddressByteSize());
+ }
+ }
+ return m_go_ast.get();
+ }
+ else if (language != eLanguageTypeSwift)
{
// For now assume all languages except swift use the ClangASTContext for types
return &GetClangASTContext();
Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/CMakeLists.txt?rev=247629&r1=247628&r2=247629&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/CMakeLists.txt Mon Sep 14 17:45:11 2015
@@ -2,6 +2,7 @@ add_lldb_library(lldbPluginSymbolFileDWA
DIERef.cpp
DWARFAbbreviationDeclaration.cpp
DWARFASTParserClang.cpp
+ DWARFASTParserGo.cpp
DWARFAttribute.cpp
DWARFCompileUnit.cpp
DWARFDataExtractor.cpp
Added: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp?rev=247629&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp (added)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp Mon Sep 14 17:45:11 2015
@@ -0,0 +1,828 @@
+//===-- DWARFASTParserGo.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFASTParserGo.h"
+
+#include "DWARFASTParserGo.h"
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDeclContext.h"
+#include "DWARFDefines.h"
+#include "DWARFDIE.h"
+#include "DWARFDIECollection.h"
+#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDebugMap.h"
+#include "UniqueDWARFASTType.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/TypeList.h"
+
+//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
+
+#ifdef ENABLE_DEBUG_PRINTF
+#include <stdio.h>
+#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
+#else
+#define DEBUG_PRINTF(fmt, ...)
+#endif
+
+#define DW_AT_go_kind 0x2900
+#define DW_AT_go_key 0x2901
+#define DW_AT_go_elem 0x2902
+
+using namespace lldb;
+using namespace lldb_private;
+DWARFASTParserGo::DWARFASTParserGo(GoASTContext &ast)
+ : m_ast(ast)
+{
+}
+
+DWARFASTParserGo::~DWARFASTParserGo()
+{
+}
+
+TypeSP
+DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log,
+ bool *type_is_new_ptr)
+{
+ TypeSP type_sp;
+
+ if (type_is_new_ptr)
+ *type_is_new_ptr = false;
+
+ if (die)
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ if (log)
+ {
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log, "DWARFASTParserGo::ParseTypeFromDWARF (die = 0x%8.8x) %s name = '%s')", die.GetOffset(),
+ DW_TAG_value_to_name(die.Tag()), die.GetName());
+ }
+
+ Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE());
+ TypeList *type_list = dwarf->GetTypeList();
+ if (type_ptr == NULL)
+ {
+ if (type_is_new_ptr)
+ *type_is_new_ptr = true;
+
+ const dw_tag_t tag = die.Tag();
+
+ bool is_forward_declaration = false;
+ DWARFAttributes attributes;
+ const char *type_name_cstr = NULL;
+ ConstString type_name_const_str;
+ Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
+ uint64_t byte_size = 0;
+ uint64_t go_kind = 0;
+ Declaration decl;
+
+ Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
+ CompilerType clang_type;
+ DWARFFormValue form_value;
+
+ dw_attr_t attr;
+
+ switch (tag)
+ {
+ case DW_TAG_base_type:
+ case DW_TAG_pointer_type:
+ case DW_TAG_typedef:
+ case DW_TAG_unspecified_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ const size_t num_attributes = die.GetAttributes(attributes);
+ uint32_t encoding = 0;
+ lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
+
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ if (type_name_cstr)
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+ case DW_AT_byte_size:
+ byte_size = form_value.Unsigned();
+ break;
+ case DW_AT_encoding:
+ encoding = form_value.Unsigned();
+ break;
+ case DW_AT_type:
+ encoding_uid = form_value.Reference();
+ break;
+ case DW_AT_go_kind:
+ go_kind = form_value.Unsigned();
+ break;
+ default:
+ // Do we care about DW_AT_go_key or DW_AT_go_elem?
+ break;
+ }
+ }
+ }
+ }
+
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid);
+
+ switch (tag)
+ {
+ default:
+ break;
+
+ case DW_TAG_unspecified_type:
+ resolve_state = Type::eResolveStateFull;
+ clang_type = m_ast.CreateVoidType(type_name_const_str);
+ break;
+
+ case DW_TAG_base_type:
+ resolve_state = Type::eResolveStateFull;
+ clang_type = m_ast.CreateBaseType(go_kind, type_name_const_str, byte_size);
+ break;
+
+ case DW_TAG_pointer_type:
+ encoding_data_type = Type::eEncodingIsPointerUID;
+ break;
+ case DW_TAG_typedef:
+ encoding_data_type = Type::eEncodingIsTypedefUID;
+ CompilerType impl;
+ Type *type = dwarf->ResolveTypeUID(encoding_uid);
+ if (type)
+ {
+ if (go_kind == 0 && type->GetName() == type_name_const_str)
+ {
+ // Go emits extra typedefs as a forward declaration. Ignore these.
+ dwarf->m_die_to_type[die.GetDIE()] = type;
+ return type->shared_from_this();
+ }
+ impl = type->GetForwardCompilerType();
+ clang_type = m_ast.CreateTypedef(go_kind, type_name_const_str, impl);
+ }
+ break;
+ }
+
+ type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size,
+ NULL, encoding_uid, encoding_data_type, &decl, clang_type, resolve_state));
+
+ dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
+ }
+ break;
+
+ case DW_TAG_structure_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
+ bool byte_size_valid = false;
+
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_byte_size:
+ byte_size = form_value.Unsigned();
+ byte_size_valid = true;
+ break;
+
+ case DW_AT_go_kind:
+ go_kind = form_value.Unsigned();
+ break;
+
+ // TODO: Should we use SLICETYPE's DW_AT_go_elem?
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ // TODO(ribrdb): Do we need this?
+
+ // UniqueDWARFASTType is large, so don't create a local variables on the
+ // stack, put it on the heap. This function is often called recursively
+ // and clang isn't good and sharing the stack space for variables in different blocks.
+ std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType());
+
+ // Only try and unique the type if it has a name.
+ if (type_name_const_str &&
+ dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl,
+ byte_size_valid ? byte_size : -1, *unique_ast_entry_ap))
+ {
+ // We have already parsed this type or from another
+ // compile unit. GCC loves to use the "one definition
+ // rule" which can result in multiple definitions
+ // of the same class over and over in each compile
+ // unit.
+ type_sp = unique_ast_entry_ap->m_type_sp;
+ if (type_sp)
+ {
+ dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
+ return type_sp;
+ }
+ }
+
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type_name_cstr);
+
+ bool clang_type_was_created = false;
+ clang_type.SetCompilerType(&m_ast, dwarf->m_forward_decl_die_to_clang_type.lookup(die.GetDIE()));
+ if (!clang_type)
+ {
+ clang_type_was_created = true;
+ clang_type = m_ast.CreateStructType(go_kind, type_name_const_str, byte_size);
+ }
+
+ type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size,
+ NULL, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, clang_type,
+ Type::eResolveStateForward));
+
+ // Add our type to the unique type map so we don't
+ // end up creating many copies of the same type over
+ // and over in the ASTContext for our module
+ unique_ast_entry_ap->m_type_sp = type_sp;
+ unique_ast_entry_ap->m_die = die;
+ unique_ast_entry_ap->m_declaration = decl;
+ unique_ast_entry_ap->m_byte_size = byte_size;
+ dwarf->GetUniqueDWARFASTTypeMap().Insert(type_name_const_str, *unique_ast_entry_ap);
+
+ if (!is_forward_declaration)
+ {
+ // Always start the definition for a class type so that
+ // if the class has child classes or types that require
+ // the class to be created for use as their decl contexts
+ // the class will be ready to accept these child definitions.
+ if (die.HasChildren() == false)
+ {
+ // No children for this struct/union/class, lets finish it
+ m_ast.CompleteStructType(clang_type);
+ }
+ else if (clang_type_was_created)
+ {
+ // Leave this as a forward declaration until we need
+ // to know the details of the type. lldb_private::Type
+ // will automatically call the SymbolFile virtual function
+ // "SymbolFileDWARF::CompleteType(Type *)"
+ // When the definition needs to be defined.
+ dwarf->m_forward_decl_die_to_clang_type[die.GetDIE()] = clang_type.GetOpaqueQualType();
+ dwarf->m_forward_decl_clang_type_to_die[clang_type.GetOpaqueQualType()] = die.GetDIERef();
+ // SetHasExternalStorage (clang_type.GetOpaqueQualType(), true);
+ }
+ }
+ }
+ break;
+
+ case DW_TAG_subprogram:
+ case DW_TAG_subroutine_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ bool is_variadic = false;
+ clang::StorageClass storage = clang::SC_None; //, Extern, Static, PrivateExtern
+
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_external:
+ if (form_value.Unsigned())
+ {
+ if (storage == clang::SC_None)
+ storage = clang::SC_Extern;
+ else
+ storage = clang::SC_PrivateExtern;
+ }
+ break;
+
+ case DW_AT_high_pc:
+ case DW_AT_low_pc:
+ break;
+ }
+ }
+ }
+ }
+
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type_name_cstr);
+
+ std::vector<CompilerType> function_param_types;
+
+ // Parse the function children for the parameters
+
+ if (die.HasChildren())
+ {
+ ParseChildParameters(sc, die, is_variadic, function_param_types);
+ }
+
+ // clang_type will get the function prototype clang type after this call
+ clang_type = m_ast.CreateFunctionType(type_name_const_str, function_param_types.data(),
+ function_param_types.size(), is_variadic);
+
+ type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, 0, NULL,
+ LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, clang_type,
+ Type::eResolveStateFull));
+ assert(type_sp.get());
+ }
+ break;
+
+ case DW_TAG_array_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ lldb::user_id_t type_die_offset = DW_INVALID_OFFSET;
+ int64_t first_index = 0;
+ uint32_t byte_stride = 0;
+ uint32_t bit_stride = 0;
+ const size_t num_attributes = die.GetAttributes(attributes);
+
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_type:
+ type_die_offset = form_value.Reference();
+ break;
+ case DW_AT_byte_size:
+ break; // byte_size = form_value.Unsigned(); break;
+ case DW_AT_go_kind:
+ go_kind = form_value.Unsigned();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type_name_cstr);
+
+ Type *element_type = dwarf->ResolveTypeUID(type_die_offset);
+
+ if (element_type)
+ {
+ std::vector<uint64_t> element_orders;
+ ParseChildArrayInfo(sc, die, first_index, element_orders, byte_stride, bit_stride);
+ if (byte_stride == 0)
+ byte_stride = element_type->GetByteSize();
+ CompilerType array_element_type = element_type->GetForwardCompilerType();
+ if (element_orders.size() > 0)
+ {
+ if (element_orders.size() > 1)
+ printf("golang: unsupported multi-dimensional array %s\n", type_name_cstr);
+ clang_type =
+ m_ast.CreateArrayType(type_name_const_str, array_element_type, element_orders[0]);
+ }
+ else
+ {
+ clang_type = m_ast.CreateArrayType(type_name_const_str, array_element_type, 0);
+ }
+ type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str,
+ byte_stride, NULL, type_die_offset, Type::eEncodingIsUID, &decl,
+ clang_type, Type::eResolveStateFull));
+ type_sp->SetEncodingType(element_type);
+ }
+ }
+ }
+ break;
+
+ default:
+ dwarf->GetObjectFile()->GetModule()->ReportError("{0x%8.8x}: unhandled type tag 0x%4.4x (%s), "
+ "please file a bug and attach the file at the "
+ "start of this error message",
+ die.GetOffset(), tag, DW_TAG_value_to_name(tag));
+ break;
+ }
+
+ if (type_sp.get())
+ {
+ DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
+ dw_tag_t sc_parent_tag = sc_parent_die.Tag();
+
+ SymbolContextScope *symbol_context_scope = NULL;
+ if (sc_parent_tag == DW_TAG_compile_unit)
+ {
+ symbol_context_scope = sc.comp_unit;
+ }
+ else if (sc.function != NULL && sc_parent_die)
+ {
+ symbol_context_scope =
+ sc.function->GetBlock(true).FindBlockByID(dwarf->MakeUserID(sc_parent_die.GetOffset()));
+ if (symbol_context_scope == NULL)
+ symbol_context_scope = sc.function;
+ }
+
+ if (symbol_context_scope != NULL)
+ {
+ type_sp->SetSymbolContextScope(symbol_context_scope);
+ }
+
+ // We are ready to put this type into the uniqued list up at the module level
+ type_list->Insert(type_sp);
+
+ dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
+ }
+ }
+ else if (type_ptr != DIE_IS_BEING_PARSED)
+ {
+ type_sp = type_ptr->shared_from_this();
+ }
+ }
+ return type_sp;
+}
+
+size_t
+DWARFASTParserGo::ParseChildParameters(const SymbolContext &sc,
+
+ const DWARFDIE &parent_die, bool &is_variadic,
+ std::vector<CompilerType> &function_param_types)
+{
+ if (!parent_die)
+ return 0;
+
+ size_t arg_idx = 0;
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+
+ dw_tag_t tag = die.Tag();
+ switch (tag)
+ {
+ case DW_TAG_formal_parameter:
+ {
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ const char *name = NULL;
+ Declaration decl;
+ dw_offset_t param_type_die_offset = DW_INVALID_OFFSET;
+
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ name = form_value.AsCString();
+ break;
+ case DW_AT_type:
+ param_type_die_offset = form_value.Reference();
+ break;
+ case DW_AT_location:
+ // if (form_value.BlockData())
+ // {
+ // const DWARFDataExtractor& debug_info_data =
+ // debug_info();
+ // uint32_t block_length = form_value.Unsigned();
+ // DWARFDataExtractor location(debug_info_data,
+ // form_value.BlockData() - debug_info_data.GetDataStart(),
+ // block_length);
+ // }
+ // else
+ // {
+ // }
+ // break;
+ default:
+ break;
+ }
+ }
+ }
+
+ Type *type = parent_die.ResolveTypeUID(param_type_die_offset);
+ if (type)
+ {
+ function_param_types.push_back(type->GetForwardCompilerType());
+ }
+ }
+ arg_idx++;
+ }
+ break;
+
+ case DW_TAG_unspecified_parameters:
+ is_variadic = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return arg_idx;
+}
+
+void
+DWARFASTParserGo::ParseChildArrayInfo(const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index,
+ std::vector<uint64_t> &element_orders, uint32_t &byte_stride,
+ uint32_t &bit_stride)
+{
+ if (!parent_die)
+ return;
+
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+ const dw_tag_t tag = die.Tag();
+ switch (tag)
+ {
+ case DW_TAG_subrange_type:
+ {
+ DWARFAttributes attributes;
+ const size_t num_child_attributes = die.GetAttributes(attributes);
+ if (num_child_attributes > 0)
+ {
+ uint64_t num_elements = 0;
+ uint32_t i;
+ for (i = 0; i < num_child_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_count:
+ num_elements = form_value.Unsigned();
+ break;
+
+ default:
+ case DW_AT_type:
+ break;
+ }
+ }
+ }
+
+ element_orders.push_back(num_elements);
+ }
+ }
+ break;
+ }
+ }
+}
+
+bool
+DWARFASTParserGo::CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, CompilerType &clang_type)
+{
+ if (!die)
+ return false;
+
+ const dw_tag_t tag = die.Tag();
+
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
+ log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type->GetName().AsCString());
+ assert(clang_type);
+ DWARFAttributes attributes;
+
+ switch (tag)
+ {
+ case DW_TAG_structure_type:
+ {
+ {
+ if (die.HasChildren())
+ {
+ SymbolContext sc(die.GetLLDBCompileUnit());
+
+ ParseChildMembers(sc, die, clang_type);
+ }
+ }
+ m_ast.CompleteStructType(clang_type);
+ return (bool)clang_type;
+ }
+
+ default:
+ assert(false && "not a forward go type decl!");
+ break;
+ }
+
+ return false;
+}
+
+size_t
+DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, const DWARFDIE &parent_die, CompilerType &class_clang_type)
+{
+ size_t count = 0;
+ uint32_t member_idx = 0;
+
+ ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
+ GoASTContext *ast = llvm::dyn_cast_or_null<GoASTContext>(class_clang_type.GetTypeSystem());
+ if (ast == nullptr)
+ return 0;
+
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+ dw_tag_t tag = die.Tag();
+
+ switch (tag)
+ {
+ case DW_TAG_member:
+ {
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ Declaration decl;
+ const char *name = NULL;
+
+ lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
+ uint32_t member_byte_offset = UINT32_MAX;
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ name = form_value.AsCString();
+ break;
+ case DW_AT_type:
+ encoding_uid = form_value.Reference();
+ break;
+ case DW_AT_data_member_location:
+ if (form_value.BlockData())
+ {
+ Value initialValue(0);
+ Value memberOffset(0);
+ const DWARFDataExtractor &debug_info_data =
+ die.GetDWARF()->get_debug_info_data();
+ uint32_t block_length = form_value.Unsigned();
+ uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+ if (DWARFExpression::Evaluate(NULL, // ExecutionContext *
+ NULL, // ClangExpressionVariableList *
+ NULL, // ClangExpressionDeclMap *
+ NULL, // RegisterContext *
+ module_sp, debug_info_data, die.GetCU(),
+ block_offset, block_length, eRegisterKindDWARF,
+ &initialValue, memberOffset, NULL))
+ {
+ member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
+ }
+ }
+ else
+ {
+ // With DWARF 3 and later, if the value is an integer constant,
+ // this form value is the offset in bytes from the beginning
+ // of the containing entity.
+ member_byte_offset = form_value.Unsigned();
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ Type *member_type = die.ResolveTypeUID(encoding_uid);
+ if (member_type)
+ {
+ CompilerType member_go_type = member_type->GetFullCompilerType();
+ ConstString name_const_str(name);
+ m_ast.AddFieldToStruct(class_clang_type, name_const_str, member_go_type, member_byte_offset);
+ }
+ }
+ ++member_idx;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return count;
+}
+
+Function *
+DWARFASTParserGo::ParseFunctionFromDWARF(const SymbolContext &sc, const DWARFDIE &die)
+{
+ DWARFRangeList func_ranges;
+ const char *name = NULL;
+ const char *mangled = NULL;
+ int decl_file = 0;
+ int decl_line = 0;
+ int decl_column = 0;
+ int call_file = 0;
+ int call_line = 0;
+ int call_column = 0;
+ DWARFExpression frame_base(die.GetCU());
+
+ assert(die.Tag() == DW_TAG_subprogram);
+
+ if (die.Tag() != DW_TAG_subprogram)
+ return NULL;
+
+ if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line, decl_column, call_file, call_line,
+ call_column, &frame_base))
+ {
+ // Union of all ranges in the function DIE (if the function is discontiguous)
+ AddressRange func_range;
+ lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0);
+ lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0);
+ if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr)
+ {
+ ModuleSP module_sp(die.GetModule());
+ func_range.GetBaseAddress().ResolveAddressUsingFileSections(lowest_func_addr, module_sp->GetSectionList());
+ if (func_range.GetBaseAddress().IsValid())
+ func_range.SetByteSize(highest_func_addr - lowest_func_addr);
+ }
+
+ if (func_range.GetBaseAddress().IsValid())
+ {
+ Mangled func_name;
+ func_name.SetValue(ConstString(name), false);
+
+ FunctionSP func_sp;
+ std::unique_ptr<Declaration> decl_ap;
+ if (decl_file != 0 || decl_line != 0 || decl_column != 0)
+ decl_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), decl_line,
+ decl_column));
+
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ // Supply the type _only_ if it has already been parsed
+ Type *func_type = dwarf->m_die_to_type.lookup(die.GetDIE());
+
+ assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
+
+ if (dwarf->FixupAddress(func_range.GetBaseAddress()))
+ {
+ const user_id_t func_user_id = dwarf->MakeUserID(die.GetOffset());
+ func_sp.reset(new Function(sc.comp_unit,
+ dwarf->MakeUserID(func_user_id), // UserID is the DIE offset
+ dwarf->MakeUserID(func_user_id), func_name, func_type,
+ func_range)); // first address range
+
+ if (func_sp.get() != NULL)
+ {
+ if (frame_base.IsValid())
+ func_sp->GetFrameBaseExpression() = frame_base;
+ sc.comp_unit->AddFunction(func_sp);
+ return func_sp.get();
+ }
+ }
+ }
+ }
+ return NULL;
+}
Added: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h?rev=247629&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h (added)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h Mon Sep 14 17:45:11 2015
@@ -0,0 +1,66 @@
+//===-- DWARFASTParserGo.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFASTParserGo_h_
+#define SymbolFileDWARF_DWARFASTParserGo_h_
+
+#include "DWARFDefines.h"
+#include "DWARFASTParser.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Symbol/GoASTContext.h"
+
+class DWARFDebugInfoEntry;
+class DWARFDIECollection;
+
+class DWARFASTParserGo : public DWARFASTParser
+{
+ public:
+ DWARFASTParserGo(lldb_private::GoASTContext &ast);
+
+ virtual ~DWARFASTParserGo();
+
+ lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log,
+ bool *type_is_new_ptr) override;
+
+ virtual lldb_private::Function *ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
+ const DWARFDIE &die) override;
+
+ virtual bool CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type,
+ lldb_private::CompilerType &go_type) override;
+
+ virtual lldb_private::CompilerDeclContext
+ GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override
+ {
+ return lldb_private::CompilerDeclContext();
+ }
+
+ virtual lldb_private::CompilerDeclContext
+ GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override
+ {
+ return lldb_private::CompilerDeclContext();
+ }
+
+ private:
+ size_t ParseChildParameters(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, bool &is_variadic,
+ std::vector<lldb_private::CompilerType> &function_param_types);
+ void ParseChildArrayInfo(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index,
+ std::vector<uint64_t> &element_orders, uint32_t &byte_stride, uint32_t &bit_stride);
+
+ size_t ParseChildMembers(const lldb_private::SymbolContext &sc, const DWARFDIE &die,
+ lldb_private::CompilerType &class_clang_type);
+
+ lldb_private::GoASTContext &m_ast;
+};
+
+#endif // SymbolFileDWARF_DWARFASTParserGo_h_
Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=247629&r1=247628&r2=247629&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Mon Sep 14 17:45:11 2015
@@ -49,6 +49,7 @@
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/GoASTContext.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolVendor.h"
@@ -507,10 +508,18 @@ TypeSystem *
SymbolFileDWARF::GetTypeSystemForLanguage (LanguageType language)
{
SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile ();
+ TypeSystem *type_system;
if (debug_map_symfile)
- return debug_map_symfile->GetTypeSystemForLanguage (language);
+ {
+ type_system = debug_map_symfile->GetTypeSystemForLanguage(language);
+ }
else
- return m_obj_file->GetModule()->GetTypeSystemForLanguage (language);
+ {
+ type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
+ if (type_system)
+ type_system->SetSymbolFile(this);
+ }
+ return type_system;
}
void
Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h?rev=247629&r1=247628&r2=247629&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h Mon Sep 14 17:45:11 2015
@@ -69,6 +69,7 @@ public:
friend class DebugMapModule;
friend class DWARFCompileUnit;
friend class DWARFASTParserClang;
+ friend class DWARFASTParserGo;
//------------------------------------------------------------------
// Static Functions
Modified: lldb/trunk/source/Symbol/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/CMakeLists.txt?rev=247629&r1=247628&r2=247629&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/CMakeLists.txt (original)
+++ lldb/trunk/source/Symbol/CMakeLists.txt Mon Sep 14 17:45:11 2015
@@ -12,6 +12,7 @@ add_lldb_library(lldbSymbol
DWARFCallFrameInfo.cpp
Function.cpp
FuncUnwinders.cpp
+ GoASTContext.cpp
LineEntry.cpp
LineTable.cpp
ObjectFile.cpp
Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=247629&r1=247628&r2=247629&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Mon Sep 14 17:45:11 2015
@@ -3021,7 +3021,7 @@ ClangASTContext::IsObjCClassType (const
bool
ClangASTContext::IsObjCObjectOrInterfaceType (const CompilerType& type)
{
- if (type)
+ if (IsClangType(type))
return GetCanonicalQualType(type)->isObjCObjectOrInterfaceType();
return false;
}
@@ -3269,12 +3269,14 @@ ClangASTContext::GetCXXClassName (const
if (type)
{
clang::QualType qual_type (GetCanonicalQualType(type));
-
- clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl)
+ if (!qual_type.isNull())
{
- class_name.assign (cxx_record_decl->getIdentifier()->getNameStart());
- return true;
+ clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ {
+ class_name.assign(cxx_record_decl->getIdentifier()->getNameStart());
+ return true;
+ }
}
}
class_name.clear();
@@ -3289,7 +3291,7 @@ ClangASTContext::IsCXXClassType (const C
return false;
clang::QualType qual_type (GetCanonicalQualType(type));
- if (qual_type->getAsCXXRecordDecl() != nullptr)
+ if (!qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr)
return true;
return false;
}
@@ -3313,8 +3315,8 @@ ClangASTContext::IsObjCObjectPointerType
return false;
clang::QualType qual_type (GetCanonicalQualType(type));
-
- if (qual_type->isObjCObjectPointerType())
+
+ if (!qual_type.isNull() && qual_type->isObjCObjectPointerType())
{
if (class_type_ptr)
{
@@ -3750,7 +3752,7 @@ ClangASTContext::GetTypeQualifiers(void*
CompilerType
ClangASTContext::AddConstModifier (const CompilerType& type)
{
- if (type && llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()))
+ if (IsClangType(type))
{
// Make sure this type is a clang AST type
clang::QualType result(GetQualType(type));
@@ -3764,7 +3766,7 @@ ClangASTContext::AddConstModifier (const
CompilerType
ClangASTContext::AddRestrictModifier (const CompilerType& type)
{
- if (type && llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()))
+ if (IsClangType(type))
{
clang::QualType result(GetQualType(type));
result.getQualifiers().setRestrict (true);
@@ -3776,7 +3778,7 @@ ClangASTContext::AddRestrictModifier (co
CompilerType
ClangASTContext::AddVolatileModifier (const CompilerType& type)
{
- if (type && llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()))
+ if (IsClangType(type))
{
clang::QualType result(GetQualType(type));
result.getQualifiers().setVolatile (true);
@@ -4077,11 +4079,10 @@ ClangASTContext::GetMemberFunctionAtInde
CompilerType
ClangASTContext::GetLValueReferenceType (const CompilerType& type)
{
- if (type)
+ if (IsClangType(type))
{
ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
- if (ast)
- return CompilerType(ast->getASTContext(), ast->getASTContext()->getLValueReferenceType(GetQualType(type)));
+ return CompilerType(ast->getASTContext(), ast->getASTContext()->getLValueReferenceType(GetQualType(type)));
}
return CompilerType();
}
@@ -4089,11 +4090,10 @@ ClangASTContext::GetLValueReferenceType
CompilerType
ClangASTContext::GetRValueReferenceType (const CompilerType& type)
{
- if (type)
+ if (IsClangType(type))
{
ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
- if (ast)
- return CompilerType(ast->getASTContext(), ast->getASTContext()->getRValueReferenceType(GetQualType(type)));
+ return CompilerType(ast->getASTContext(), ast->getASTContext()->getRValueReferenceType(GetQualType(type)));
}
return CompilerType();
}
@@ -4186,7 +4186,7 @@ ClangASTContext::GetTypedefedType (void*
CompilerType
ClangASTContext::RemoveFastQualifiers (const CompilerType& type)
{
- if (type && llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()))
+ if (IsClangType(type))
{
clang::QualType qual_type(GetQualType(type));
qual_type.getQualifiers().removeFastQualifiers();
Added: lldb/trunk/source/Symbol/GoASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/GoASTContext.cpp?rev=247629&view=auto
==============================================================================
--- lldb/trunk/source/Symbol/GoASTContext.cpp (added)
+++ lldb/trunk/source/Symbol/GoASTContext.cpp Mon Sep 14 17:45:11 2015
@@ -0,0 +1,1417 @@
+//===-- 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/UniqueCStringMap.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/GoASTContext.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Target/ExecutionContext.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, int64_t length, const CompilerType &elem)
+ : GoElem(KIND_ARRAY, name, elem)
+ , m_length(length)
+ {
+ }
+
+ int64_t
+ GetLength() const
+ {
+ return m_length;
+ }
+
+ private:
+ int64_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, 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()
+{
+}
+
+//----------------------------------------------------------------------
+// Tests
+//----------------------------------------------------------------------
+
+bool
+GoASTContext::IsArrayType(void *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 (array->GetLength() == -1)
+ {
+ if (is_incomplete)
+ {
+ *is_incomplete = true;
+ }
+ }
+ else if (size)
+ {
+ *size = array->GetLength();
+ }
+ if (element_type)
+ *element_type = array->GetElementType();
+ return true;
+ }
+ return false;
+}
+
+bool
+GoASTContext::IsVectorType(void *type, CompilerType *element_type, uint64_t *size)
+{
+ if (element_type)
+ element_type->Clear();
+ if (size)
+ *size = 0;
+ return false;
+}
+
+bool
+GoASTContext::IsAggregateType(void *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_STRING)
+ return false;
+ if (kind == GoType::KIND_UNSAFEPOINTER)
+ return false;
+ return true;
+}
+
+bool
+GoASTContext::IsBeingDefined(void *type)
+{
+ return false;
+}
+
+bool
+GoASTContext::IsCharType(void *type)
+{
+ // Go's DWARF doesn't distinguish between rune and int32.
+ return false;
+}
+
+bool
+GoASTContext::IsCompleteType(void *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(void *type)
+{
+ return false;
+}
+
+bool
+GoASTContext::IsCStringType(void *type, uint32_t &length)
+{
+ return false;
+}
+
+bool
+GoASTContext::IsDefined(void *type)
+{
+ return type != nullptr;
+}
+
+bool
+GoASTContext::IsFloatingPointType(void *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(void *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(void *type, CompilerType *base_type_ptr)
+{
+ return false;
+}
+
+size_t
+GoASTContext::GetNumberOfFunctionArguments(void *type)
+{
+ return 0;
+}
+
+CompilerType
+GoASTContext::GetFunctionArgumentAtIndex(void *type, const size_t index)
+{
+ return CompilerType();
+}
+
+bool
+GoASTContext::IsFunctionPointerType(void *type)
+{
+ return IsFunctionType(type);
+}
+
+bool
+GoASTContext::IsIntegerType(void *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(void *type)
+{
+ return false;
+}
+
+bool
+GoASTContext::IsPossibleDynamicType(void *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(void *type)
+{
+ return false;
+}
+
+bool
+GoASTContext::IsPointerType(void *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:
+ // TODO: is map a pointer? string? function?
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+GoASTContext::IsPointerOrReferenceType(void *type, CompilerType *pointee_type)
+{
+ return IsPointerType(type, pointee_type);
+}
+
+bool
+GoASTContext::IsReferenceType(void *type, CompilerType *pointee_type, bool *is_rvalue)
+{
+ return false;
+}
+
+bool
+GoASTContext::IsScalarType(void *type)
+{
+ return !IsAggregateType(type);
+}
+
+bool
+GoASTContext::IsTypedefType(void *type)
+{
+ if (type)
+ return static_cast<GoType *>(type)->IsTypedef();
+ return false;
+}
+
+bool
+GoASTContext::IsVoidType(void *type)
+{
+ if (!type)
+ return false;
+ return static_cast<GoType *>(type)->GetGoKind() == GoType::KIND_LLDB_VOID;
+}
+
+//----------------------------------------------------------------------
+// Type Completion
+//----------------------------------------------------------------------
+
+bool
+GoASTContext::GetCompleteType(void *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(void *type)
+{
+ if (type)
+ return static_cast<GoType *>(type)->GetName();
+ return ConstString();
+}
+
+uint32_t
+GoASTContext::GetTypeInfo(void *type, CompilerType *pointee_or_element_clang_type)
+{
+ if (pointee_or_element_clang_type)
+ pointee_or_element_clang_type->Clear();
+ if (!type)
+ return 0;
+ GoType *t = static_cast<GoType *>(type);
+ if (pointee_or_element_clang_type)
+ *pointee_or_element_clang_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(void *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(void *type)
+{
+ ConstString name = GetTypeName(type);
+ if (name)
+ {
+ typedef UniqueCStringMap<lldb::BasicType> TypeNameToBasicTypeMap;
+ static TypeNameToBasicTypeMap g_type_map;
+ static std::once_flag g_once_flag;
+ std::call_once(g_once_flag, [](){
+ // "void"
+ g_type_map.Append(ConstString("void").GetCString(), eBasicTypeVoid);
+ // "int"
+ g_type_map.Append(ConstString("int").GetCString(), eBasicTypeInt);
+ g_type_map.Append(ConstString("uint").GetCString(), eBasicTypeUnsignedInt);
+
+ // Miscellaneous
+ g_type_map.Append(ConstString("bool").GetCString(), eBasicTypeBool);
+
+ // Others. Should these map to C types?
+ g_type_map.Append(ConstString("byte").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("uint8").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("uint16").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("uint32").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("uint64").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("int8").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("int16").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("int32").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("int64").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("float32").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("float64").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("uintptr").GetCString(), eBasicTypeOther);
+
+ g_type_map.Sort();
+ });
+
+ return g_type_map.Find(name.GetCString(), eBasicTypeInvalid);
+ }
+ return eBasicTypeInvalid;
+}
+
+lldb::LanguageType
+GoASTContext::GetMinimumLanguage(void *type)
+{
+ return lldb::eLanguageTypeGo;
+}
+
+unsigned
+GoASTContext::GetTypeQualifiers(void *type)
+{
+ return 0;
+}
+
+//----------------------------------------------------------------------
+// Creating related types
+//----------------------------------------------------------------------
+
+CompilerType
+GoASTContext::GetArrayElementType(void *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(void *type)
+{
+ GoType *t = static_cast<GoType *>(type);
+ if (t->IsTypedef())
+ return t->GetElementType();
+ return CompilerType(this, type);
+}
+
+CompilerType
+GoASTContext::GetFullyUnqualifiedType(void *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(void *type)
+{
+ return GetNumberOfFunctionArguments(type);
+}
+
+CompilerType
+GoASTContext::GetFunctionArgumentTypeAtIndex(void *type, size_t idx)
+{
+ return GetFunctionArgumentAtIndex(type, idx);
+}
+
+CompilerType
+GoASTContext::GetFunctionReturnType(void *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(void *type)
+{
+ return 0;
+}
+
+TypeMemberFunctionImpl
+GoASTContext::GetMemberFunctionAtIndex(void *type, size_t idx)
+{
+ return TypeMemberFunctionImpl();
+}
+
+CompilerType
+GoASTContext::GetNonReferenceType(void *type)
+{
+ return CompilerType(this, type);
+}
+
+CompilerType
+GoASTContext::GetPointeeType(void *type)
+{
+ if (!type)
+ return CompilerType();
+ return static_cast<GoType *>(type)->GetElementType();
+}
+
+CompilerType
+GoASTContext::GetPointerType(void *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(void *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::GetIntTypeFromBitSize (size_t bit_size, bool is_signed)
+{
+ return CompilerType();
+}
+CompilerType GoASTContext::GetFloatTypeFromBitSize (size_t bit_size)
+{
+ return CompilerType();
+}
+
+
+//----------------------------------------------------------------------
+// Exploring the type
+//----------------------------------------------------------------------
+
+uint64_t
+GoASTContext::GetBitSize(void *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);
+ }
+}
+
+lldb::Encoding
+GoASTContext::GetEncoding(void *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(void *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(void *type)
+{
+ return 0;
+}
+
+uint32_t
+GoASTContext::GetNumChildren(void *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();
+ }
+ return GetNumFields(type);
+}
+
+uint32_t
+GoASTContext::GetNumFields(void *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(void *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::GetChildClangTypeAtIndex(void *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)
+{
+ 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;
+
+ 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.GetChildClangTypeAtIndex(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);
+ }
+ 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().GetChildClangTypeAtIndex(
+ 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);
+ }
+ 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(void *type, const char *name, bool omit_empty_base_classes)
+{
+ 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(void *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(void *type, const char *s, uint8_t *dst, size_t dst_size)
+{
+ assert(false);
+}
+//----------------------------------------------------------------------
+// Dumping types
+//----------------------------------------------------------------------
+void
+GoASTContext::DumpValue(void *type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format,
+ const DataExtractor &data, lldb::offset_t data_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)
+{
+ assert(false);
+}
+
+bool
+GoASTContext::DumpTypeValue(void *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_clang_type = t->GetElementType();
+ if (format == eFormatDefault)
+ format = typedef_clang_type.GetFormat();
+ uint64_t typedef_byte_size = typedef_clang_type.GetByteSize(exe_scope);
+
+ return typedef_clang_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 data.Dump(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(void *type, ExecutionContext *exe_ctx, Stream *s, const DataExtractor &data,
+ lldb::offset_t data_offset, size_t data_byte_size)
+{
+ assert(false);
+}
+
+void
+GoASTContext::DumpTypeDescription(void *type)
+{
+ assert(false);
+} // Dump to stdout
+
+void
+GoASTContext::DumpTypeDescription(void *type, Stream *s)
+{
+ assert(false);
+}
+
+CompilerType
+GoASTContext::CreateArrayType(const ConstString &name, const CompilerType &element_type, int64_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::CreateTypedef(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();
+}
Modified: lldb/trunk/source/Symbol/SymbolFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/SymbolFile.cpp?rev=247629&r1=247628&r2=247629&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/SymbolFile.cpp (original)
+++ lldb/trunk/source/Symbol/SymbolFile.cpp Mon Sep 14 17:45:11 2015
@@ -93,7 +93,10 @@ SymbolFile::GetClangASTContext ()
TypeSystem *
SymbolFile::GetTypeSystemForLanguage (lldb::LanguageType language)
{
- return m_obj_file->GetModule()->GetTypeSystemForLanguage (language);
+ TypeSystem *type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
+ if (type_system)
+ type_system->SetSymbolFile(this);
+ return type_system;
}
uint32_t
Added: lldb/trunk/test/lang/go/types/TestGoASTContext.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/go/types/TestGoASTContext.py?rev=247629&view=auto
==============================================================================
--- lldb/trunk/test/lang/go/types/TestGoASTContext.py (added)
+++ lldb/trunk/test/lang/go/types/TestGoASTContext.py Mon Sep 14 17:45:11 2015
@@ -0,0 +1,134 @@
+"""Test the go DWARF type parsing."""
+
+import os, time
+import unittest2
+import lldb
+import lldbutil
+from lldbtest import *
+
+class TestGoASTContext(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @python_api_test
+ @skipUnlessGoInstalled
+ def test_with_dsym_and_python_api(self):
+ """Test GoASTContext dwarf parsing."""
+ self.buildGo()
+ self.launchProcess()
+ self.go_builtin_types()
+ self.check_main_vars()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Find the line numbers to break inside main().
+ self.main_source = "main.go"
+ self.break_line = line_number(self.main_source, '// Set breakpoint here.')
+
+ def check_builtin(self, name, size=0, typeclass=lldb.eTypeClassBuiltin):
+ tl = self.target().FindTypes(name)
+ self.assertEqual(1, len(tl))
+ t = list(tl)[0]
+ self.assertEqual(name, t.name)
+ self.assertEqual(typeclass, t.type)
+ if size > 0:
+ self.assertEqual(size, t.size)
+
+ def launchProcess(self):
+ exe = os.path.join(os.getcwd(), "a.out")
+
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+
+ bpt = target.BreakpointCreateByLocation(self.main_source, self.break_line)
+ self.assertTrue(bpt, VALID_BREAKPOINT)
+
+ # Now launch the process, and do not stop at entry point.
+ process = target.LaunchSimple (None, None, self.get_process_working_directory())
+
+ self.assertTrue(process, PROCESS_IS_VALID)
+
+ # The stop reason of the thread should be breakpoint.
+ thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt)
+
+ # Make sure we stopped at the first breakpoint.
+ self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.")
+ self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.")
+
+ frame = thread_list[0].GetFrameAtIndex(0)
+ self.assertTrue (frame, "Got a valid frame 0 frame.")
+
+ def go_builtin_types(self):
+ address_size = self.target().GetAddressByteSize()
+ self.check_builtin('bool')
+ self.check_builtin('uint8', 1)
+ self.check_builtin('int8', 1)
+ self.check_builtin('uint16', 2)
+ self.check_builtin('int16', 2)
+ self.check_builtin('uint32', 4)
+ self.check_builtin('int32', 4)
+ self.check_builtin('uint64', 8)
+ self.check_builtin('int64', 8)
+ self.check_builtin('uintptr', address_size)
+ self.check_builtin('int', address_size)
+ self.check_builtin('uint', address_size)
+ self.check_builtin('float32', 4)
+ self.check_builtin('float64', 8)
+ self.check_builtin('complex64', 8, lldb.eTypeClassComplexFloat)
+ self.check_builtin('complex128', 16, lldb.eTypeClassComplexFloat)
+
+ def var(self, name):
+ var = self.frame().FindVariable(name)
+ self.assertTrue(var.IsValid(), "%s %s" % (VALID_VARIABLE, name))
+ return var
+
+ def check_main_vars(self):
+ v = self.var('theBool')
+ self.assertEqual('true', v.value)
+
+ v = self.var('theInt')
+ self.assertEqual('-7', v.value)
+
+ v = self.var('theComplex')
+ self.assertEqual('1 + 2i', v.value)
+
+ v = self.var('thePointer')
+ self.assertTrue(v.TypeIsPointerType())
+ self.assertEqual('-10', v.Dereference().value)
+ self.assertEqual(1, v.GetNumChildren())
+ self.assertEqual('-10', v.GetChildAtIndex(0).value)
+
+ # print
+ # print os.getpid()
+ # time.sleep(60)
+ v = self.var('theStruct')
+ if v.TypeIsPointerType():
+ v = v.Dereference()
+ self.assertEqual(2, v.GetNumChildren())
+ self.assertEqual('7', v.GetChildAtIndex(0).value)
+ self.assertEqual('7', v.GetChildMemberWithName('myInt').value)
+ self.assertEqual(v.load_addr, v.GetChildAtIndex(1).GetValueAsUnsigned())
+ self.assertEqual(v.load_addr, v.GetChildMemberWithName('myPointer').GetValueAsUnsigned())
+
+ # Test accessing struct fields through pointers.
+ v = v.GetChildMemberWithName('myPointer')
+ self.assertTrue(v.TypeIsPointerType())
+ self.assertEqual(2, v.GetNumChildren())
+ self.assertEqual('7', v.GetChildAtIndex(0).value)
+ c = v.GetChildMemberWithName('myPointer')
+ self.assertTrue(c.TypeIsPointerType())
+ self.assertEqual(2, c.GetNumChildren())
+ self.assertEqual('7', c.GetChildAtIndex(0).value)
+
+ v = self.var('theArray')
+ self.assertEqual(5, v.GetNumChildren())
+ for i in xrange(5):
+ self.assertEqual(str(i + 1), v.GetChildAtIndex(i).value)
+
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
Added: lldb/trunk/test/lang/go/types/main.go
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/go/types/main.go?rev=247629&view=auto
==============================================================================
--- lldb/trunk/test/lang/go/types/main.go (added)
+++ lldb/trunk/test/lang/go/types/main.go Mon Sep 14 17:45:11 2015
@@ -0,0 +1,47 @@
+package main
+
+import "fmt"
+
+type Fooer interface {
+ Foo() int
+}
+
+type SomeFooer struct {
+ val int
+}
+
+func (s SomeFooer) Foo() int {
+ return s.val
+}
+
+type mystruct struct {
+ myInt int
+ myPointer *mystruct
+}
+
+func main() {
+ theBool := true
+ theInt := -7
+ theComplex := 1 + 2i
+ pointee := -10
+ thePointer := &pointee
+ theStruct := &mystruct { myInt: 7}
+ theStruct.myPointer = theStruct
+ theArray := [5]byte{1, 2, 3, 4, 5}
+ theSlice := theArray[1:2]
+ theString := "abc"
+
+ f := SomeFooer {9}
+ var theEface interface{} = f
+ var theFooer Fooer = f
+
+ theChan := make(chan int)
+ theMap := make(map[int]string)
+ theMap[1] = "1"
+
+ fmt.Println(theBool) // Set breakpoint here.
+ // Reference all the variables so the compiler is happy.
+ fmt.Println(theInt, theComplex, thePointer, theStruct.myInt)
+ fmt.Println(theArray[0], theSlice[0], theString)
+ fmt.Println(theEface, theFooer, theChan, theMap)
+}
\ No newline at end of file
Modified: lldb/trunk/test/lldbtest.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lldbtest.py?rev=247629&r1=247628&r2=247629&view=diff
==============================================================================
--- lldb/trunk/test/lldbtest.py (original)
+++ lldb/trunk/test/lldbtest.py Mon Sep 14 17:45:11 2015
@@ -893,6 +893,21 @@ def skipUnlessDarwin(func):
"""Decorate the item to skip tests that should be skipped on any non Darwin platform."""
return skipUnlessPlatform(getDarwinOSTriples())(func)
+def skipUnlessGoInstalled(func):
+ """Decorate the item to skip tests when no Go compiler is available."""
+ if isinstance(func, type) and issubclass(func, unittest2.TestCase):
+ raise Exception("@skipIfGcc can only be used to decorate a test method")
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ from unittest2 import case
+ self = args[0]
+ compiler = self.getGoCompilerVersion()
+ if not compiler:
+ self.skipTest("skipping because go compiler not found")
+ else:
+ func(*args, **kwargs)
+ return wrapper
+
def getPlatform():
"""Returns the target platform which the tests are running on."""
platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2]
@@ -1868,6 +1883,18 @@ class Base(unittest2.TestCase):
version = m.group(1)
return version
+ def getGoCompilerVersion(self):
+ """ Returns a string that represents the go compiler version, or None if go is not found.
+ """
+ compiler = which("go")
+ if compiler:
+ version_output = system([[compiler, "version"]])[0]
+ for line in version_output.split(os.linesep):
+ m = re.search('go version (devel|go\\S+)', line)
+ if m:
+ return m.group(1)
+ return None
+
def platformIsDarwin(self):
"""Returns true if the OS triple for the selected platform is any valid apple OS"""
return platformIsDarwin()
@@ -2053,6 +2080,11 @@ class Base(unittest2.TestCase):
if not module.buildDwarf(self, architecture, compiler, dictionary, clean):
raise Exception("Don't know how to build binary with dwarf")
+ def buildGo(self):
+ """Build the default go binary.
+ """
+ system([[which('go'), 'build -gcflags "-N -l" -o a.out main.go']])
+
def signBinary(self, binary_path):
if sys.platform.startswith("darwin"):
codesign_cmd = "codesign --force --sign lldb_codesign %s" % (binary_path)
More information about the lldb-commits
mailing list