[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