12 changes: 12 additions & 0 deletions lldb/lldb.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -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>"; };
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down
21 changes: 20 additions & 1 deletion lldb/source/Core/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -148,6 +149,7 @@ Module::Module (const ModuleSpec &module_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),
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ add_lldb_library(lldbPluginSymbolFileDWARF
DIERef.cpp
DWARFAbbreviationDeclaration.cpp
DWARFASTParserClang.cpp
DWARFASTParserGo.cpp
DWARFAttribute.cpp
DWARFCompileUnit.cpp
DWARFDataExtractor.cpp
Expand Down
828 changes: 828 additions & 0 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp

Large diffs are not rendered by default.

66 changes: 66 additions & 0 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
Original file line number Diff line number Diff line change
@@ -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_
13 changes: 11 additions & 2 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class SymbolFileDWARF : public lldb_private::SymbolFile, public lldb_private::Us
friend class DebugMapModule;
friend class DWARFCompileUnit;
friend class DWARFASTParserClang;
friend class DWARFASTParserGo;

//------------------------------------------------------------------
// Static Functions
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Symbol/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ add_lldb_library(lldbSymbol
DWARFCallFrameInfo.cpp
Function.cpp
FuncUnwinders.cpp
GoASTContext.cpp
LineEntry.cpp
LineTable.cpp
ObjectFile.cpp
Expand Down
38 changes: 19 additions & 19 deletions lldb/source/Symbol/ClangASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3021,7 +3021,7 @@ ClangASTContext::IsObjCClassType (const CompilerType& type)
bool
ClangASTContext::IsObjCObjectOrInterfaceType (const CompilerType& type)
{
if (type)
if (IsClangType(type))
return GetCanonicalQualType(type)->isObjCObjectOrInterfaceType();
return false;
}
Expand Down Expand Up @@ -3269,12 +3269,14 @@ ClangASTContext::GetCXXClassName (const CompilerType& type, std::string &class_n
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();
Expand All @@ -3289,7 +3291,7 @@ ClangASTContext::IsCXXClassType (const CompilerType& type)
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;
}
Expand All @@ -3313,8 +3315,8 @@ ClangASTContext::IsObjCObjectPointerType (const CompilerType& type, CompilerType
return false;

clang::QualType qual_type (GetCanonicalQualType(type));
if (qual_type->isObjCObjectPointerType())

if (!qual_type.isNull() && qual_type->isObjCObjectPointerType())
{
if (class_type_ptr)
{
Expand Down Expand Up @@ -3750,7 +3752,7 @@ ClangASTContext::GetTypeQualifiers(void* type)
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));
Expand All @@ -3764,7 +3766,7 @@ ClangASTContext::AddConstModifier (const CompilerType& type)
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);
Expand All @@ -3776,7 +3778,7 @@ ClangASTContext::AddRestrictModifier (const CompilerType& type)
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);
Expand Down Expand Up @@ -4077,23 +4079,21 @@ ClangASTContext::GetMemberFunctionAtIndex (void* type, size_t idx)
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();
}

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();
}
Expand Down Expand Up @@ -4186,7 +4186,7 @@ ClangASTContext::GetTypedefedType (void* type)
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();
Expand Down
1,417 changes: 1,417 additions & 0 deletions lldb/source/Symbol/GoASTContext.cpp

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion lldb/source/Symbol/SymbolFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
134 changes: 134 additions & 0 deletions lldb/test/lang/go/types/TestGoASTContext.py
Original file line number Diff line number Diff line change
@@ -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()
47 changes: 47 additions & 0 deletions lldb/test/lang/go/types/main.go
Original file line number Diff line number Diff line change
@@ -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)
}
32 changes: 32 additions & 0 deletions lldb/test/lldbtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -1868,6 +1883,18 @@ def getCompilerVersion(self):
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()
Expand Down Expand Up @@ -2053,6 +2080,11 @@ def buildDwarf(self, architecture=None, compiler=None, dictionary=None, clean=Tr
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)
Expand Down