blob: 0d8fa20ab227ef610c1a8876f9fb4ce171e5abf8 [file]
//===-- SwiftASTContext.cpp -------------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "lldb/Symbol/SwiftASTContext.h"
// C++ Includes
#include <mutex> // std::once
#include <queue>
#include <set>
#include <sstream>
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/DebuggerClient.h"
#include "swift/AST/Decl.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/SearchPathOptions.h"
#include "swift/AST/Type.h"
#include "swift/AST/Types.h"
#include "swift/ASTSectionImporter/ASTSectionImporter.h"
#include "swift/Basic/Dwarf.h"
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/Platform.h"
#include "swift/Basic/PrimarySpecificPaths.h"
#include "swift/Basic/SourceManager.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/ClangImporter/ClangImporterOptions.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Driver/Util.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/IDE/Utils.h"
#include "swift/IRGen/Linking.h"
#include "swift/SIL/SILModule.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Driver/Driver.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "swift/../../lib/IRGen/FixedTypeInfo.h"
#include "swift/../../lib/IRGen/GenEnum.h"
#include "swift/../../lib/IRGen/GenHeap.h"
#include "swift/../../lib/IRGen/IRGenMangler.h"
#include "swift/../../lib/IRGen/IRGenModule.h"
#include "swift/../../lib/IRGen/TypeInfo.h"
#include "swift/../../lib/IRGen/IRGenMangler.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "swift/Strings.h"
#include "Plugins/ExpressionParser/Swift/SwiftDiagnostic.h"
#include "Plugins/ExpressionParser/Swift/SwiftUserExpression.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ThreadSafeDenseMap.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SwiftLanguageRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
#include "Plugins/Platform/MacOSX/PlatformDarwin.h"
#include "Plugins/SymbolFile/DWARF/DWARFASTParserSwift.h"
#ifdef LLDB_CONFIGURATION_DEBUG
#define VALID_OR_RETURN(value) \
do { \
lldbassert(!HasFatalErrors()); \
if (HasFatalErrors()) { \
return (value); \
} \
} while (0)
#define VALID_OR_RETURN_VOID() \
do { \
lldbassert(!HasFatalErrors()); \
if (HasFatalErrors()) { \
return; \
} \
} while (0)
#else
#define VALID_OR_RETURN(value) \
do { \
if (HasFatalErrors()) { \
return (value); \
} \
} while (0)
#define VALID_OR_RETURN_VOID() \
do { \
if (HasFatalErrors()) { \
return; \
} \
} while (0)
#endif
using namespace lldb;
using namespace lldb_private;
typedef lldb_private::ThreadSafeDenseMap<swift::ASTContext *, SwiftASTContext *>
ThreadSafeSwiftASTMap;
static ThreadSafeSwiftASTMap &GetASTMap() {
// The global destructor list will tear down all of the modules when the LLDB
// shared library is being unloaded and this needs to live beyond all of those
// and not be destructed before they have all gone away. So we will leak this
// list intentionally so we can avoid global destructor problems.
static ThreadSafeSwiftASTMap *g_map_ptr = NULL;
static std::once_flag g_once_flag;
std::call_once(g_once_flag, []() {
g_map_ptr = new ThreadSafeSwiftASTMap(); // NOTE: Intentional leak
});
return *g_map_ptr;
}
static inline swift::Type GetSwiftType(void *opaque_ptr) {
return swift::Type((swift::TypeBase *)opaque_ptr);
}
static inline swift::CanType GetCanonicalSwiftType(void *opaque_ptr) {
return ((swift::TypeBase *)opaque_ptr)->getCanonicalType();
}
static inline swift::Type GetSwiftType(CompilerType type) {
return swift::Type((swift::TypeBase *)type.GetOpaqueQualType());
}
static inline swift::CanType GetCanonicalSwiftType(CompilerType type) {
return ((swift::TypeBase *)type.GetOpaqueQualType())->getCanonicalType();
}
enum class MemberType : uint32_t { Invalid, BaseClass, Field };
static const char *MemberTypeToCString(MemberType member_type) {
switch (member_type) {
case MemberType::Invalid:
return "invalid";
case MemberType::BaseClass:
return "base class";
case MemberType::Field:
return "field";
}
return "???";
}
struct MemberInfo {
CompilerType clang_type;
lldb_private::ConstString name;
uint64_t byte_size;
uint32_t byte_offset;
MemberType member_type;
bool is_fragile;
MemberInfo(MemberType member_type)
: clang_type(), name(), byte_size(0), byte_offset(0),
member_type(member_type), is_fragile(false) {}
void Dump(uint32_t idx) {
printf("[%i] %12s +%u (%s) %s <%" PRIu64 "> %s\n", idx,
MemberTypeToCString(member_type), byte_offset,
clang_type.GetTypeName().AsCString("<no type name>"),
name.AsCString("<NULL>"), byte_size, is_fragile ? "[fragile]" : "");
}
};
struct CachedMemberInfo {
std::vector<MemberInfo> member_infos;
};
struct EnumElementInfo {
CompilerType clang_type;
lldb_private::ConstString name;
uint64_t byte_size;
uint32_t value; // The value for this enumeration element
uint32_t extra_value; // If not UINT32_MAX, then this value is an extra value
// that appears at offset 0 to tell one or more empty
// enums apart. This value will only be filled in if there
// are one ore more enum elements that have a non-zero byte size
EnumElementInfo()
: clang_type(), name(), byte_size(0), extra_value(UINT32_MAX) {}
void Dump(Stream &strm) const {
strm.Printf("<%2" PRIu64 "> %4u", byte_size, value);
if (extra_value != UINT32_MAX)
strm.Printf("%4u: ", extra_value);
else
strm.Printf(" : ");
strm.Printf("case %s", name.GetCString());
if (clang_type)
strm.Printf("%s", clang_type.GetTypeName().AsCString("<no type name>"));
strm.EOL();
}
};
class SwiftEnumDescriptor;
typedef std::shared_ptr<CachedMemberInfo> CachedMemberInfoSP;
typedef std::shared_ptr<SwiftEnumDescriptor> SwiftEnumDescriptorSP;
typedef llvm::DenseMap<lldb::opaque_compiler_type_t, CachedMemberInfoSP>
MemberInfoCache;
typedef llvm::DenseMap<lldb::opaque_compiler_type_t, SwiftEnumDescriptorSP>
EnumInfoCache;
typedef std::shared_ptr<MemberInfoCache> MemberInfoCacheSP;
typedef std::shared_ptr<EnumInfoCache> EnumInfoCacheSP;
typedef llvm::DenseMap<const swift::ASTContext *, MemberInfoCacheSP>
ASTMemberInfoCacheMap;
typedef llvm::DenseMap<const swift::ASTContext *, EnumInfoCacheSP>
ASTEnumInfoCacheMap;
static MemberInfoCache *GetMemberInfoCache(const swift::ASTContext *a) {
static ASTMemberInfoCacheMap g_cache;
static std::mutex g_mutex;
std::lock_guard<std::mutex> locker(g_mutex);
ASTMemberInfoCacheMap::iterator pos = g_cache.find(a);
if (pos == g_cache.end()) {
g_cache.insert(std::make_pair(
a, std::shared_ptr<MemberInfoCache>(new MemberInfoCache())));
return g_cache.find(a)->second.get();
}
return pos->second.get();
}
static EnumInfoCache *GetEnumInfoCache(const swift::ASTContext *a) {
static ASTEnumInfoCacheMap g_cache;
static std::mutex g_mutex;
std::lock_guard<std::mutex> locker(g_mutex);
ASTEnumInfoCacheMap::iterator pos = g_cache.find(a);
if (pos == g_cache.end()) {
g_cache.insert(
std::make_pair(a, std::shared_ptr<EnumInfoCache>(new EnumInfoCache())));
return g_cache.find(a)->second.get();
}
return pos->second.get();
}
namespace {
bool IsDirectory(const FileSpec &spec) {
return llvm::sys::fs::is_directory(spec.GetPath());
}
bool IsRegularFile(const FileSpec &spec) {
return llvm::sys::fs::is_regular_file(spec.GetPath());
}
}
llvm::LLVMContext &SwiftASTContext::GetGlobalLLVMContext() {
// TODO check with Sean. Do we really want this to be static across
// an LLDB managing multiple Swift processes?
static llvm::LLVMContext s_global_context;
return s_global_context;
}
CachedMemberInfo *SwiftASTContext::GetCachedMemberInfo(void *type) {
VALID_OR_RETURN(nullptr);
if (type) {
// printf("CompilerType::GetCachedMemberInfo () for %s...",
// GetTypeName().c_str());
bool is_class = false;
bool is_protocol = false;
MemberInfoCache *member_info_cache = GetMemberInfoCache(GetASTContext());
MemberInfoCache::const_iterator pos = member_info_cache->find(type);
if (pos != member_info_cache->end()) {
// printf("cached: %p\n", pos->second.get());
return pos->second.get();
}
CachedMemberInfoSP member_infos_sp(new CachedMemberInfo());
// printf("creating in %p\n", member_infos_sp.get());
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
std::vector<const swift::irgen::TypeInfo *> field_type_infos;
swift::irgen::LayoutStrategy layout_strategy =
swift::irgen::LayoutStrategy::Optimal;
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Error:
case swift::TypeKind::BuiltinInteger:
case swift::TypeKind::BuiltinFloat:
case swift::TypeKind::BuiltinRawPointer:
case swift::TypeKind::BuiltinBridgeObject:
case swift::TypeKind::BuiltinNativeObject:
case swift::TypeKind::BuiltinUnsafeValueBuffer:
case swift::TypeKind::BuiltinUnknownObject:
case swift::TypeKind::BuiltinVector:
case swift::TypeKind::UnownedStorage:
case swift::TypeKind::WeakStorage:
case swift::TypeKind::UnmanagedStorage:
case swift::TypeKind::GenericTypeParam:
case swift::TypeKind::DependentMember:
case swift::TypeKind::Metatype:
case swift::TypeKind::Module:
case swift::TypeKind::Function:
case swift::TypeKind::GenericFunction:
case swift::TypeKind::LValue:
case swift::TypeKind::UnboundGeneric:
case swift::TypeKind::Enum:
case swift::TypeKind::BoundGenericEnum:
case swift::TypeKind::ExistentialMetatype:
case swift::TypeKind::DynamicSelf:
case swift::TypeKind::SILBox:
case swift::TypeKind::SILFunction:
case swift::TypeKind::SILBlockStorage:
case swift::TypeKind::InOut:
case swift::TypeKind::Unresolved:
assert(false &&
"Caller must only call this function with valid type_kind");
break;
case swift::TypeKind::Tuple: {
layout_strategy = swift::irgen::LayoutStrategy::Universal;
swift::TupleType *tuple_type = swift_can_type->castTo<swift::TupleType>();
for (auto tuple_field : tuple_type->getElements()) {
MemberInfo member_info(MemberType::Field);
member_info.clang_type =
CompilerType(GetASTContext(), tuple_field.getType().getPointer());
member_info.byte_size = member_info.clang_type.GetByteSize(nullptr);
const char *tuple_name = tuple_field.getName().get();
if (tuple_name) {
member_info.name.SetCString(tuple_name);
} else {
StreamString tuple_name_strm;
tuple_name_strm.Printf(
"%u", (uint32_t)member_infos_sp->member_infos.size());
member_info.name.SetCString(tuple_name_strm.GetString().data());
}
field_type_infos.push_back(
GetSwiftTypeInfo(member_info.clang_type.GetOpaqueQualType()));
assert(field_type_infos.back() != nullptr);
member_infos_sp->member_infos.push_back(member_info);
}
} break;
case swift::TypeKind::Protocol:
case swift::TypeKind::ProtocolComposition: {
ProtocolInfo protocol_info;
if (!GetProtocolTypeInfo(
CompilerType(GetASTContext(), GetSwiftType(type)), protocol_info))
break;
is_protocol = true;
uint32_t num_children = protocol_info.m_num_storage_words;
for (uint32_t idx = 0; idx < num_children; idx++) {
MemberInfo member_info(MemberType::Field);
member_info.clang_type = CompilerType(
GetASTContext(), GetASTContext()->TheRawPointerType.getPointer());
member_info.byte_size = member_info.clang_type.GetByteSize(nullptr);
member_info.byte_offset = idx * member_info.byte_size;
member_info.is_fragile = false;
StreamString child_name_stream;
// Opaque existentials have m_num_payload_words != 0.
if (idx < protocol_info.m_num_payload_words)
child_name_stream.Printf("payload_data_%u", idx);
else {
// After the payload, the first word is either the instance itself
// (for class or error existentials) or a metadata pointer
// (for opaque existentials).
//
// Class and opaque existentials have zero or more witness tables.
// Error existentials always store their witness table inline.
int l_idx = idx - protocol_info.m_num_payload_words;
if (l_idx == 0)
child_name_stream.Printf("instance_type");
else
child_name_stream.Printf("protocol_witness_%u", l_idx - 1);
}
member_info.name = ConstString(child_name_stream.GetData());
member_infos_sp->member_infos.push_back(member_info);
}
} break;
case swift::TypeKind::Struct:
case swift::TypeKind::Class:
case swift::TypeKind::BoundGenericStruct:
case swift::TypeKind::BoundGenericClass: {
auto t_decl = swift_can_type.getAnyNominal();
auto class_decl = swift::dyn_cast<swift::ClassDecl>(t_decl);
if (class_decl) {
is_class = true;
swift::Type superclass_type(swift_can_type->getSuperclass());
if (superclass_type) {
MemberInfo member_info(MemberType::BaseClass);
member_info.clang_type =
CompilerType(GetASTContext(), superclass_type.getPointer());
member_info.byte_size =
member_info.clang_type.GetByteSize(nullptr);
// Showing somemodule.sometype<A> is confusing to the user because
// it will show the *unboud* archetype name even though the type
// is actually properly bound (or it should!) and since one cannot
// overload a class on the number of generic arguments,
// somemodule.sometype is just as unique.
member_info.name.SetCString(
member_info.clang_type.GetUnboundType()
.GetTypeName()
.AsCString("<no type name>"));
field_type_infos.push_back(
GetSwiftTypeInfo(member_info.clang_type.GetOpaqueQualType()));
assert(field_type_infos.back() != nullptr);
member_infos_sp->member_infos.push_back(member_info);
}
}
for (auto decl : t_decl->getMembers()) {
// Find ivars that aren't properties
if (swift::isa<swift::VarDecl>(decl)) {
swift::VarDecl *var_decl = swift::cast<swift::VarDecl>(decl);
if (var_decl->hasStorage() && !var_decl->isStatic()) {
MemberInfo member_info(MemberType::Field);
swift::Type member_type = swift_can_type->getTypeOfMember(
t_decl->getModuleContext(), var_decl, nullptr);
member_info.clang_type =
CompilerType(GetASTContext(), member_type.getPointer());
member_info.byte_size =
member_info.clang_type.GetByteSize(nullptr);
member_info.is_fragile =
is_class; // Class fields are all fragile...
const char *child_name_cstr = var_decl->getName().get();
if (child_name_cstr)
member_info.name.SetCString(child_name_cstr);
field_type_infos.push_back(GetSwiftTypeInfo(
member_info.clang_type.GetOpaqueQualType()));
assert(field_type_infos.back() != nullptr);
member_infos_sp->member_infos.push_back(member_info);
}
}
}
} break;
case swift::TypeKind::TypeVariable:
case swift::TypeKind::Archetype:
break;
case swift::TypeKind::Optional:
case swift::TypeKind::NameAlias:
case swift::TypeKind::Paren:
case swift::TypeKind::Dictionary:
case swift::TypeKind::ArraySlice:
assert(false && "Not a canonical type");
break;
}
if (!member_infos_sp->member_infos.empty()) {
if (is_class) {
// If we have a class, then all offsets are fragile so we don't need to
// do layout since we will need to lookup the ivar offset symbol, or
// munge the runtime data to find the offsets.
} else if (!is_protocol) {
// Only do struct layout if we don't have a union since the only thing
// we need layout for currently is for the byte offset and the byte
// offset of everything in a union is zero.
// As for protocols, their fields are artificially generated from what a
// protocol_container contains in the Swift runtime itself, and it's
// just pointers, so no need to get fancy.
swift::irgen::StructLayout layout(
GetIRGenModule(), swift_can_type,
swift::irgen::LayoutKind::NonHeapObject, layout_strategy,
field_type_infos);
const size_t num_elements = layout.getElements().size();
assert(num_elements == member_infos_sp->member_infos.size());
for (int ii = 0; ii < num_elements; ++ii) {
auto element = layout.getElements()[ii];
// check or crash
if (element.getKind() == swift::irgen::ElementLayout::Kind::Fixed)
member_infos_sp->member_infos[ii].byte_offset =
element.getByteOffset().getValue();
else
member_infos_sp->member_infos[ii].byte_offset =
0; // TODO: dynamic layout
// member_infos_sp->member_infos[ii].Dump(ii);
}
}
member_info_cache->insert(std::make_pair(type, member_infos_sp));
return member_infos_sp.get();
}
}
return nullptr;
}
class SwiftEnumDescriptor {
public:
enum class Kind {
Empty, // no cases in this enum
CStyle, // no cases have payloads
AllPayload, // all cases have payloads
Mixed // some cases have payloads
};
struct ElementInfo {
lldb_private::ConstString name;
CompilerType payload_type;
bool has_payload : 1;
bool is_indirect : 1;
};
Kind GetKind() const { return m_kind; }
ConstString GetTypeName() { return m_type_name; }
virtual ElementInfo *
GetElementFromData(const lldb_private::DataExtractor &data) = 0;
virtual size_t GetNumElements() {
return GetNumElementsWithPayload() + GetNumCStyleElements();
}
virtual size_t GetNumElementsWithPayload() = 0;
virtual size_t GetNumCStyleElements() = 0;
virtual ElementInfo *GetElementWithPayloadAtIndex(size_t idx) = 0;
virtual ElementInfo *GetElementWithNoPayloadAtIndex(size_t idx) = 0;
virtual ~SwiftEnumDescriptor() = default;
static SwiftEnumDescriptor *CreateDescriptor(swift::ASTContext *ast,
swift::CanType swift_can_type,
swift::EnumDecl *enum_decl);
protected:
SwiftEnumDescriptor(swift::ASTContext *ast, swift::CanType swift_can_type,
swift::EnumDecl *enum_decl, SwiftEnumDescriptor::Kind k)
: m_kind(k), m_type_name() {
if (swift_can_type.getPointer()) {
if (auto nominal = swift_can_type->getAnyNominal()) {
swift::Identifier name(nominal->getName());
if (name.get())
m_type_name.SetCString(name.get());
}
}
}
private:
Kind m_kind;
ConstString m_type_name;
};
class SwiftEmptyEnumDescriptor : public SwiftEnumDescriptor {
public:
SwiftEmptyEnumDescriptor(swift::ASTContext *ast,
swift::CanType swift_can_type,
swift::EnumDecl *enum_decl)
: SwiftEnumDescriptor(ast, swift_can_type, enum_decl,
SwiftEnumDescriptor::Kind::Empty) {}
virtual ElementInfo *
GetElementFromData(const lldb_private::DataExtractor &data) {
return nullptr;
}
virtual size_t GetNumElementsWithPayload() { return 0; }
virtual size_t GetNumCStyleElements() { return 0; }
virtual ElementInfo *GetElementWithPayloadAtIndex(size_t idx) {
return nullptr;
}
virtual ElementInfo *GetElementWithNoPayloadAtIndex(size_t idx) {
return nullptr;
}
static bool classof(const SwiftEnumDescriptor *S) {
return S->GetKind() == SwiftEnumDescriptor::Kind::Empty;
}
virtual ~SwiftEmptyEnumDescriptor() = default;
};
namespace std {
template <> struct less<swift::ClusteredBitVector> {
bool operator()(const swift::ClusteredBitVector &lhs,
const swift::ClusteredBitVector &rhs) const {
int iL = lhs.size() - 1;
int iR = rhs.size() - 1;
for (; iL >= 0 && iR >= 0; --iL, --iR) {
bool bL = lhs[iL];
bool bR = rhs[iR];
if (bL and not bR)
return false;
if (bR and not bL)
return true;
}
return false;
}
};
}
static std::string Dump(const swift::ClusteredBitVector &bit_vector) {
std::string buffer;
llvm::raw_string_ostream ostream(buffer);
for (size_t i = 0; i < bit_vector.size(); i++) {
if (bit_vector[i])
ostream << '1';
else
ostream << '0';
if ((i % 4) == 3)
ostream << ' ';
}
ostream.flush();
return buffer;
}
class SwiftCStyleEnumDescriptor : public SwiftEnumDescriptor {
public:
SwiftCStyleEnumDescriptor(swift::ASTContext *ast,
swift::CanType swift_can_type,
swift::EnumDecl *enum_decl)
: SwiftEnumDescriptor(ast, swift_can_type, enum_decl,
SwiftEnumDescriptor::Kind::CStyle),
m_nopayload_elems_bitmask(), m_elements(), m_element_indexes() {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
if (log)
log->Printf("doing C-style enum layout for %s",
GetTypeName().AsCString());
SwiftASTContext *swift_ast_ctx = SwiftASTContext::GetSwiftASTContext(ast);
swift::irgen::IRGenModule &irgen_module = swift_ast_ctx->GetIRGenModule();
const swift::irgen::EnumImplStrategy &enum_impl_strategy =
swift::irgen::getEnumImplStrategy(irgen_module, swift_can_type);
llvm::ArrayRef<swift::irgen::EnumImplStrategy::Element>
elements_with_no_payload =
enum_impl_strategy.getElementsWithNoPayload();
const bool has_payload = false;
const bool is_indirect = false;
uint64_t case_counter = 0;
m_nopayload_elems_bitmask =
enum_impl_strategy.getBitMaskForNoPayloadElements();
if (log)
log->Printf("m_nopayload_elems_bitmask = %s",
Dump(m_nopayload_elems_bitmask).c_str());
for (auto enum_case : elements_with_no_payload) {
ConstString case_name(enum_case.decl->getName().str().data());
swift::ClusteredBitVector case_value =
enum_impl_strategy.getBitPatternForNoPayloadElement(enum_case.decl);
if (log)
log->Printf("case_name = %s, unmasked value = %s",
case_name.AsCString(), Dump(case_value).c_str());
case_value &= m_nopayload_elems_bitmask;
if (log)
log->Printf("case_name = %s, masked value = %s", case_name.AsCString(),
Dump(case_value).c_str());
std::unique_ptr<ElementInfo> elem_info(
new ElementInfo{case_name, CompilerType(), has_payload, is_indirect});
m_element_indexes.emplace(case_counter, elem_info.get());
case_counter++;
m_elements.emplace(case_value, std::move(elem_info));
}
}
virtual ElementInfo *
GetElementFromData(const lldb_private::DataExtractor &data) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
if (log)
log->Printf(
"C-style enum - inspecting data to find enum case for type %s",
GetTypeName().AsCString());
swift::ClusteredBitVector current_payload;
lldb::offset_t offset = 0;
for (size_t idx = 0; idx < data.GetByteSize(); idx++) {
uint64_t byte = data.GetU8(&offset);
current_payload.add(8, byte);
}
if (log) {
log->Printf("m_nopayload_elems_bitmask = %s",
Dump(m_nopayload_elems_bitmask).c_str());
log->Printf("current_payload = %s",
Dump(current_payload).c_str());
}
if (current_payload.size() != m_nopayload_elems_bitmask.size()) {
if (log)
log->Printf("sizes don't match; getting out with an error");
return nullptr;
}
current_payload &= m_nopayload_elems_bitmask;
if (log)
log->Printf("masked current_payload = %s",
Dump(current_payload).c_str());
auto iter = m_elements.find(current_payload), end = m_elements.end();
if (iter == end) {
if (log)
log->Printf("bitmask search failed");
return nullptr;
}
if (log)
log->Printf("bitmask search success - found case %s",
iter->second.get()->name.AsCString());
return iter->second.get();
}
virtual size_t GetNumElementsWithPayload() { return 0; }
virtual size_t GetNumCStyleElements() { return m_elements.size(); }
virtual ElementInfo *GetElementWithPayloadAtIndex(size_t idx) {
return nullptr;
}
virtual ElementInfo *GetElementWithNoPayloadAtIndex(size_t idx) {
if (idx >= m_element_indexes.size())
return nullptr;
return m_element_indexes[idx];
}
static bool classof(const SwiftEnumDescriptor *S) {
return S->GetKind() == SwiftEnumDescriptor::Kind::CStyle;
}
virtual ~SwiftCStyleEnumDescriptor() = default;
private:
swift::ClusteredBitVector m_nopayload_elems_bitmask;
std::map<swift::ClusteredBitVector, std::unique_ptr<ElementInfo>> m_elements;
std::map<uint64_t, ElementInfo *> m_element_indexes;
};
static CompilerType
GetFunctionArgumentTuple(const CompilerType &compiler_type) {
if (compiler_type.IsValid() &&
llvm::dyn_cast_or_null<SwiftASTContext>(compiler_type.GetTypeSystem())) {
swift::CanType swift_can_type(
GetCanonicalSwiftType(compiler_type.GetOpaqueQualType()));
auto func =
swift::dyn_cast_or_null<swift::AnyFunctionType>(
swift_can_type);
if (func) {
auto input = func.getInput();
// See comment in swift::AnyFunctionType for rationale here:
// A function can take either a tuple or a parentype, but if a parentype
// (i.e. (Foo)), then it will be reduced down to just Foo, so if the input
// is not a tuple, that must mean there is only 1 input.
auto tuple = swift::dyn_cast<swift::TupleType>(input);
if (tuple)
return CompilerType(compiler_type.GetTypeSystem(), tuple);
else
return CompilerType(compiler_type.GetTypeSystem(), input.getPointer());
}
}
return CompilerType();
}
class SwiftAllPayloadEnumDescriptor : public SwiftEnumDescriptor {
public:
SwiftAllPayloadEnumDescriptor(swift::ASTContext *ast,
swift::CanType swift_can_type,
swift::EnumDecl *enum_decl)
: SwiftEnumDescriptor(ast, swift_can_type, enum_decl,
SwiftEnumDescriptor::Kind::AllPayload),
m_tag_bits(), m_elements() {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
if (log)
log->Printf("doing ADT-style enum layout for %s",
GetTypeName().AsCString());
SwiftASTContext *swift_ast_ctx = SwiftASTContext::GetSwiftASTContext(ast);
swift::irgen::IRGenModule &irgen_module = swift_ast_ctx->GetIRGenModule();
const swift::irgen::EnumImplStrategy &enum_impl_strategy =
swift::irgen::getEnumImplStrategy(irgen_module, swift_can_type);
llvm::ArrayRef<swift::irgen::EnumImplStrategy::Element>
elements_with_payload = enum_impl_strategy.getElementsWithPayload();
m_tag_bits = enum_impl_strategy.getTagBitsForPayloads();
if (log)
log->Printf("tag_bits = %s", Dump(m_tag_bits).c_str());
auto module_ctx = enum_decl->getModuleContext();
const bool has_payload = true;
for (auto enum_case : elements_with_payload) {
ConstString case_name(enum_case.decl->getName().str().data());
swift::EnumElementDecl *case_decl = enum_case.decl;
assert(case_decl);
CompilerType case_type(
ast, swift_can_type->getTypeOfMember(module_ctx, case_decl, nullptr)
.getPointer());
case_type = GetFunctionArgumentTuple(case_type.GetFunctionReturnType());
const bool is_indirect = case_decl->isIndirect()
|| case_decl->getParentEnum()->isIndirect();
if (log)
log->Printf("case_name = %s, type = %s, is_indirect = %s",
case_name.AsCString(), case_type.GetTypeName().AsCString(),
is_indirect ? "yes" : "no");
std::unique_ptr<ElementInfo> elem_info(
new ElementInfo{case_name, case_type, has_payload, is_indirect});
m_elements.push_back(std::move(elem_info));
}
}
virtual ElementInfo *
GetElementFromData(const lldb_private::DataExtractor &data) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
if (log)
log->Printf(
"ADT-style enum - inspecting data to find enum case for type %s",
GetTypeName().AsCString());
if (m_elements.size() == 0) // no elements, just fail
{
if (log)
log->Printf("enum with no cases. getting out");
return nullptr;
}
if (m_elements.size() == 1) // one element, so it's gotta be it
{
if (log)
log->Printf("enum with one case. getting out easy with %s",
m_elements.front().get()->name.AsCString());
return m_elements.front().get();
}
swift::ClusteredBitVector current_payload;
lldb::offset_t offset = 0;
for (size_t idx = 0; idx < data.GetByteSize(); idx++) {
uint64_t byte = data.GetU8(&offset);
current_payload.add(8, byte);
}
if (log) {
log->Printf("tag_bits = %s", Dump(m_tag_bits).c_str());
log->Printf("current_payload = %s", Dump(current_payload).c_str());
}
if (current_payload.size() != m_tag_bits.size()) {
if (log)
log->Printf("sizes don't match; getting out with an error");
return nullptr;
}
size_t discriminator = 0;
size_t power_of_2 = 1;
auto enumerator = m_tag_bits.enumerateSetBits();
for (llvm::Optional<size_t> next = enumerator.findNext(); next.hasValue();
next = enumerator.findNext()) {
discriminator =
discriminator + (current_payload[next.getValue()] ? power_of_2 : 0);
power_of_2 <<= 1;
}
if (discriminator >= m_elements.size()) // discriminator too large, get out
{
if (log)
log->Printf("discriminator value of %" PRIu64 " too large, getting out",
(uint64_t)discriminator);
return nullptr;
} else {
auto ptr = m_elements[discriminator].get();
if (log) {
if (!ptr)
log->Printf("discriminator value of %" PRIu64
" acceptable, but null case matched - that's bad",
(uint64_t)discriminator);
else
log->Printf("discriminator value of %" PRIu64
" acceptable, case %s matched",
(uint64_t)discriminator, ptr->name.AsCString());
}
return ptr;
}
}
virtual size_t GetNumElementsWithPayload() { return m_elements.size(); }
virtual size_t GetNumCStyleElements() { return 0; }
virtual ElementInfo *GetElementWithPayloadAtIndex(size_t idx) {
if (idx >= m_elements.size())
return nullptr;
return m_elements[idx].get();
}
virtual ElementInfo *GetElementWithNoPayloadAtIndex(size_t idx) {
return nullptr;
}
static bool classof(const SwiftEnumDescriptor *S) {
return S->GetKind() == SwiftEnumDescriptor::Kind::AllPayload;
}
virtual ~SwiftAllPayloadEnumDescriptor() = default;
private:
swift::ClusteredBitVector m_tag_bits;
std::vector<std::unique_ptr<ElementInfo>> m_elements;
};
class SwiftMixedEnumDescriptor : public SwiftEnumDescriptor {
public:
SwiftMixedEnumDescriptor(swift::ASTContext *ast,
swift::CanType swift_can_type,
swift::EnumDecl *enum_decl)
: SwiftEnumDescriptor(ast, swift_can_type, enum_decl,
SwiftEnumDescriptor::Kind::Mixed),
m_non_payload_cases(ast, swift_can_type, enum_decl),
m_payload_cases(ast, swift_can_type, enum_decl) {}
virtual ElementInfo *
GetElementFromData(const lldb_private::DataExtractor &data) {
ElementInfo *elem_info = m_non_payload_cases.GetElementFromData(data);
return elem_info ? elem_info : m_payload_cases.GetElementFromData(data);
}
static bool classof(const SwiftEnumDescriptor *S) {
return S->GetKind() == SwiftEnumDescriptor::Kind::Mixed;
}
virtual size_t GetNumElementsWithPayload() {
return m_payload_cases.GetNumElementsWithPayload();
}
virtual size_t GetNumCStyleElements() {
return m_non_payload_cases.GetNumCStyleElements();
}
virtual ElementInfo *GetElementWithPayloadAtIndex(size_t idx) {
return m_payload_cases.GetElementWithPayloadAtIndex(idx);
}
virtual ElementInfo *GetElementWithNoPayloadAtIndex(size_t idx) {
return m_non_payload_cases.GetElementWithNoPayloadAtIndex(idx);
}
virtual ~SwiftMixedEnumDescriptor() = default;
private:
SwiftCStyleEnumDescriptor m_non_payload_cases;
SwiftAllPayloadEnumDescriptor m_payload_cases;
};
SwiftEnumDescriptor *
SwiftEnumDescriptor::CreateDescriptor(swift::ASTContext *ast,
swift::CanType swift_can_type,
swift::EnumDecl *enum_decl) {
assert(ast);
assert(enum_decl);
assert(swift_can_type.getPointer());
SwiftASTContext *swift_ast_ctx = SwiftASTContext::GetSwiftASTContext(ast);
assert(swift_ast_ctx);
swift::irgen::IRGenModule &irgen_module = swift_ast_ctx->GetIRGenModule();
const swift::irgen::EnumImplStrategy &enum_impl_strategy =
swift::irgen::getEnumImplStrategy(irgen_module, swift_can_type);
llvm::ArrayRef<swift::irgen::EnumImplStrategy::Element>
elements_with_payload = enum_impl_strategy.getElementsWithPayload();
llvm::ArrayRef<swift::irgen::EnumImplStrategy::Element>
elements_with_no_payload = enum_impl_strategy.getElementsWithNoPayload();
if (elements_with_no_payload.size() == 0) {
// nothing with no payload.. empty or all payloads?
if (elements_with_payload.size() == 0)
return new SwiftEmptyEnumDescriptor(ast, swift_can_type, enum_decl);
else
return new SwiftAllPayloadEnumDescriptor(ast, swift_can_type, enum_decl);
} else {
// something with no payload.. mixed or C-style?
if (elements_with_payload.size() == 0)
return new SwiftCStyleEnumDescriptor(ast, swift_can_type, enum_decl);
else
return new SwiftMixedEnumDescriptor(ast, swift_can_type, enum_decl);
}
}
static SwiftEnumDescriptor *
GetEnumInfoFromEnumDecl(swift::ASTContext *ast, swift::CanType swift_can_type,
swift::EnumDecl *enum_decl) {
return SwiftEnumDescriptor::CreateDescriptor(ast, swift_can_type, enum_decl);
}
SwiftEnumDescriptor *SwiftASTContext::GetCachedEnumInfo(void *type) {
VALID_OR_RETURN(nullptr);
if (type) {
EnumInfoCache *enum_info_cache = GetEnumInfoCache(GetASTContext());
EnumInfoCache::const_iterator pos = enum_info_cache->find(type);
if (pos != enum_info_cache->end())
return pos->second.get();
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
if (!SwiftASTContext::IsFullyRealized(
CompilerType(GetASTContext(), swift_can_type)))
return nullptr;
SwiftEnumDescriptorSP enum_info_sp;
if (auto *enum_type = swift_can_type->getAs<swift::EnumType>()) {
enum_info_sp.reset(GetEnumInfoFromEnumDecl(
GetASTContext(), swift_can_type, enum_type->getDecl()));
} else if (auto *bound_enum_type =
swift_can_type->getAs<swift::BoundGenericEnumType>()) {
enum_info_sp.reset(GetEnumInfoFromEnumDecl(
GetASTContext(), swift_can_type, bound_enum_type->getDecl()));
}
if (enum_info_sp.get())
enum_info_cache->insert(std::make_pair(type, enum_info_sp));
return enum_info_sp.get();
}
return nullptr;
}
namespace {
static inline bool
SwiftASTContextSupportsLanguage(lldb::LanguageType language) {
return language == eLanguageTypeSwift;
}
static bool IsDeviceSupport(const char *path) {
// The old-style check, which we preserve for safety.
if (path && strstr(path, "iOS DeviceSupport"))
return true;
// The new-style check, which should cover more devices.
if (path)
if (const char *Developer_Xcode = strstr(path, "Developer"))
if (const char *DeviceSupport = strstr(Developer_Xcode, "DeviceSupport"))
if (strstr(DeviceSupport, "Symbols"))
return true;
// Don't look in the simulator runtime frameworks either. They either
// duplicate what the SDK has, or for older simulators conflict with them.
if (path && strstr(path, ".simruntime/Contents/Resources/"))
return true;
return false;
}
}
SwiftASTContext::SwiftASTContext(const char *triple, Target *target)
: TypeSystem(TypeSystem::eKindSwift), m_source_manager_ap(),
m_diagnostic_engine_ap(), m_ast_context_ap(), m_ir_gen_module_ap(),
m_compiler_invocation_ap(new swift::CompilerInvocation()),
m_dwarf_ast_parser_ap(), m_scratch_module(NULL), m_sil_module_ap(),
m_serialized_module_loader(NULL), m_clang_importer(NULL),
m_swift_module_cache(), m_mangled_name_to_type_map(),
m_type_to_mangled_name_map(), m_pointer_byte_size(0),
m_pointer_bit_align(0), m_void_function_type(), m_target_wp(),
m_process(NULL), m_platform_sdk_path(), m_resource_dir(),
m_ast_file_data_map(), m_initialized_language_options(false),
m_initialized_search_path_options(false),
m_initialized_clang_importer_options(false),
m_reported_fatal_error(false), m_fatal_errors(), m_negative_type_cache(),
m_extra_type_info_cache(), m_swift_type_map() {
// Set the module-cache path if it has been specified:
if (target) {
FileSpec &module_cache = target->GetClangModulesCachePath();
if (module_cache && module_cache.Exists()) {
std::string module_cache_path = module_cache.GetPath();
llvm::StringRef module_cache_ref(module_cache_path);
m_compiler_invocation_ap->setClangModuleCachePath(module_cache_ref);
}
m_target_wp = target->shared_from_this();
}
if (triple)
SetTriple(triple);
swift::IRGenOptions &ir_gen_opts =
m_compiler_invocation_ap->getIRGenOptions();
ir_gen_opts.OutputKind = swift::IRGenOutputKind::Module;
ir_gen_opts.UseJIT = true;
ir_gen_opts.DWARFVersion = swift::DWARFVersion;
}
SwiftASTContext::SwiftASTContext(const SwiftASTContext &rhs)
: TypeSystem(rhs.getKind()), m_source_manager_ap(),
m_diagnostic_engine_ap(), m_ast_context_ap(), m_ir_gen_module_ap(),
m_compiler_invocation_ap(new swift::CompilerInvocation()),
m_dwarf_ast_parser_ap(), m_scratch_module(NULL), m_sil_module_ap(),
m_serialized_module_loader(NULL), m_clang_importer(NULL),
m_swift_module_cache(), m_mangled_name_to_type_map(),
m_type_to_mangled_name_map(), m_pointer_byte_size(0),
m_pointer_bit_align(0), m_void_function_type(), m_target_wp(),
m_process(NULL), m_platform_sdk_path(), m_resource_dir(),
m_ast_file_data_map(), m_initialized_language_options(false),
m_initialized_search_path_options(false),
m_initialized_clang_importer_options(false),
m_reported_fatal_error(false), m_fatal_errors(), m_negative_type_cache(),
m_extra_type_info_cache(), m_swift_type_map() {
if (rhs.m_compiler_invocation_ap) {
std::string rhs_triple = rhs.GetTriple();
if (!rhs_triple.empty()) {
SetTriple(rhs_triple.c_str());
}
llvm::StringRef module_cache_path =
rhs.m_compiler_invocation_ap->getClangModuleCachePath();
if (!module_cache_path.empty())
m_compiler_invocation_ap->setClangModuleCachePath(module_cache_path);
}
swift::IRGenOptions &ir_gen_opts =
m_compiler_invocation_ap->getIRGenOptions();
ir_gen_opts.OutputKind = swift::IRGenOutputKind::Module;
ir_gen_opts.UseJIT = true;
TargetSP target_sp = rhs.m_target_wp.lock();
if (target_sp)
m_target_wp = target_sp;
m_platform_sdk_path = rhs.m_platform_sdk_path;
m_resource_dir = rhs.m_resource_dir;
swift::ASTContext *lhs_ast = GetASTContext();
swift::ASTContext *rhs_ast =
const_cast<SwiftASTContext &>(rhs).GetASTContext();
if (lhs_ast && rhs_ast) {
lhs_ast->SearchPathOpts = rhs_ast->SearchPathOpts;
}
GetClangImporter();
}
SwiftASTContext::~SwiftASTContext() {
if (m_ast_context_ap.get()) {
GetASTMap().Erase(m_ast_context_ap.get());
}
}
ConstString SwiftASTContext::GetPluginNameStatic() {
return ConstString("swift");
}
ConstString SwiftASTContext::GetPluginName() {
return ClangASTContext::GetPluginNameStatic();
}
uint32_t SwiftASTContext::GetPluginVersion() { return 1; }
static std::string &GetDefaultResourceDir() {
static std::string s_resource_dir;
return s_resource_dir;
}
lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language,
Module &module) {
if (!SwiftASTContextSupportsLanguage(language))
return lldb::TypeSystemSP();
ArchSpec arch = module.GetArchitecture();
ObjectFile *objfile = module.GetObjectFile();
ArchSpec object_arch;
if (!objfile || !objfile->GetArchitecture(object_arch))
return TypeSystemSP();
lldb::CompUnitSP main_compile_unit_sp = module.GetCompileUnitAtIndex(0);
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
if (main_compile_unit_sp && !main_compile_unit_sp->Exists()) {
if (log) {
StreamString ss;
module.GetDescription(&ss);
log->Printf("Corresponding source not found for %s, loading module "
"%s is unlikely to succeed",
main_compile_unit_sp->GetCString(), ss.GetData());
}
}
std::shared_ptr<SwiftASTContext> swift_ast_sp(new SwiftASTContext());
swift_ast_sp->GetLanguageOptions().DebuggerSupport = true;
swift_ast_sp->GetLanguageOptions().EnableAccessControl = false;
if (!arch.IsValid())
return TypeSystemSP();
llvm::Triple triple = arch.GetTriple();
if (triple.getOS() == llvm::Triple::UnknownOS) {
// cl_kernels are the only binaries that don't have an LC_MIN_VERSION_xxx
// load command. This avoids a Swift assertion.
#if defined(__APPLE__)
switch (triple.getArch()) {
default:
triple.setOS(llvm::Triple::MacOSX);
break;
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
triple.setOS(llvm::Triple::IOS);
break;
}
#else
// Not an elegant hack on OS X, not an elegant hack elsewhere.
// But we shouldn't be claiming things are Mac binaries when they are
// not.
triple.setOS(HostInfo::GetArchitecture().GetTriple().getOS());
#endif
}
swift_ast_sp->SetTriple(triple.getTriple().c_str(), &module);
bool set_triple = false;
SymbolVendor *sym_vendor = module.GetSymbolVendor();
std::string resource_dir;
std::string target_triple;
if (sym_vendor) {
// Use the new loadFromSerializedAST if possible:
auto ast_file_datas = sym_vendor->GetASTData(eLanguageTypeSwift);
bool got_serialized_options = false;
DataBufferSP ast_file_data_sp;
if (!ast_file_datas.empty() &&
((ast_file_data_sp = ast_file_datas.front()) != nullptr)) {
if (log)
log->Printf("Found %d AST file data entries for library: %s.",
(int)ast_file_datas.size(),
module.GetSpecificationDescription().c_str());
// Retrieve the first serialized AST data blob and initialize
// the compiler invocation with it.
llvm::StringRef section_data_ref(
(const char *)ast_file_data_sp->GetBytes(),
ast_file_data_sp->GetByteSize());
auto result = swift_ast_sp->GetCompilerInvocation().loadFromSerializedAST(
section_data_ref);
switch (result) {
case swift::serialization::Status::Valid:
got_serialized_options = true;
break;
case swift::serialization::Status::FormatTooOld:
swift_ast_sp->m_fatal_errors.SetErrorString(
"the swift module file format is too old to be used by the "
"version of the swift compiler in LLDB");
return swift_ast_sp;
case swift::serialization::Status::FormatTooNew:
swift_ast_sp->m_fatal_errors.SetErrorString(
"the swift module file format is too new to be used by this "
"version of the swift compiler in LLDB");
return swift_ast_sp;
case swift::serialization::Status::MissingDependency:
swift_ast_sp->m_fatal_errors.SetErrorString(
"the swift module file depends on another module that can't be "
"loaded");
return swift_ast_sp;
case swift::serialization::Status::MissingShadowedModule:
swift_ast_sp->m_fatal_errors.SetErrorString(
"the swift module file is an overlay for a clang module, which "
"can't be found");
return swift_ast_sp;
case swift::serialization::Status::FailedToLoadBridgingHeader:
swift_ast_sp->m_fatal_errors.SetErrorString(
"the swift module file depends on a bridging header that can't "
"be loaded");
return swift_ast_sp;
case swift::serialization::Status::Malformed:
swift_ast_sp->m_fatal_errors.SetErrorString(
"the swift module file is malformed");
return swift_ast_sp;
case swift::serialization::Status::MalformedDocumentation:
swift_ast_sp->m_fatal_errors.SetErrorString(
"the swift module documentation file is malformed in some way");
return swift_ast_sp;
case swift::serialization::Status::NameMismatch:
swift_ast_sp->m_fatal_errors.SetErrorString(
"the swift module file's name does not match the module it is "
"being loaded into");
return swift_ast_sp;
case swift::serialization::Status::TargetIncompatible:
swift_ast_sp->m_fatal_errors.SetErrorString(
"the swift module file was built for a different target "
"platform");
return swift_ast_sp;
case swift::serialization::Status::TargetTooNew:
swift_ast_sp->m_fatal_errors.SetErrorString(
"the swift module file was built for a target newer than the "
"current target");
return swift_ast_sp;
}
}
// TODO: make sure we only get options for Swift files.
// We really should be passing down a language enumeration into
// sym_vendor->GetCompileOption() so we don't get compiler options
// for a C/C++ file...
if (got_serialized_options) {
// Some of the bits in the compiler options we keep separately, so we
// need to populate them from the serialized options:
llvm::StringRef serialized_triple =
swift_ast_sp->GetCompilerInvocation().getTargetTriple();
if (serialized_triple.empty()) {
if (log)
log->Printf("\tSerialized triple for %s was empty.",
module.GetSpecificationDescription().c_str());
} else {
if (log)
log->Printf("\tFound serialized triple for %s: %s.",
module.GetSpecificationDescription().c_str(),
serialized_triple.data());
swift_ast_sp->SetTriple(serialized_triple.data(), &module);
set_triple = true;
}
llvm::StringRef serialized_sdk_path =
swift_ast_sp->GetCompilerInvocation().getSDKPath();
if (serialized_sdk_path.empty()) {
if (log)
log->Printf("\tNo serialized SDK path.");
} else {
if (log)
log->Printf("\tGot serialized SDK path %s.",
serialized_sdk_path.data());
FileSpec sdk_spec(serialized_sdk_path.data(), false);
if (sdk_spec.Exists()) {
swift_ast_sp->SetPlatformSDKPath(serialized_sdk_path.data());
}
}
}
if (!got_serialized_options || !swift_ast_sp->GetPlatformSDKPath()) {
std::string platform_sdk_path;
if (sym_vendor->GetCompileOption("-sdk", platform_sdk_path)) {
FileSpec sdk_spec(platform_sdk_path.c_str(), false);
if (sdk_spec.Exists()) {
swift_ast_sp->SetPlatformSDKPath(platform_sdk_path.c_str());
}
if (sym_vendor->GetCompileOption("-target", target_triple)) {
llvm::StringRef parsed_triple(target_triple);
swift_ast_sp->SetTriple(target_triple.c_str(), &module);
set_triple = true;
}
}
}
if (sym_vendor->GetCompileOption("-resource-dir", resource_dir)) {
swift_ast_sp->SetResourceDir(resource_dir.c_str());
} else if (!GetDefaultResourceDir().empty()) {
// Use the first resource dir we found when setting up a target.
swift_ast_sp->SetResourceDir(GetDefaultResourceDir().c_str());
} else {
if (log)
log->Printf("No resource dir available for module's SwiftASTContext.");
}
if (!got_serialized_options) {
std::vector<std::string> framework_search_paths;
if (sym_vendor->GetCompileOptions("-F", framework_search_paths)) {
for (std::string &search_path : framework_search_paths) {
swift_ast_sp->AddFrameworkSearchPath(search_path.c_str());
}
}
std::vector<std::string> include_paths;
if (sym_vendor->GetCompileOptions("-I", include_paths)) {
for (std::string &search_path : include_paths) {
const FileSpec path_spec(search_path.c_str(), false);
if (path_spec.Exists()) {
static const ConstString s_hmap_extension("hmap");
if (IsDirectory(path_spec)) {
swift_ast_sp->AddModuleSearchPath(search_path.c_str());
} else if (IsRegularFile(path_spec) &&
path_spec.GetFileNameExtension() == s_hmap_extension) {
std::string argument("-I");
argument.append(search_path);
swift_ast_sp->AddClangArgument(argument.c_str());
}
}
}
}
std::vector<std::string> cc_options;
if (sym_vendor->GetCompileOptions("-Xcc", cc_options)) {
for (int i = 0; i < cc_options.size(); ++i) {
if (!cc_options[i].compare("-iquote") && i + 1 < cc_options.size()) {
swift_ast_sp->AddClangArgumentPair("-iquote",
cc_options[i + 1].c_str());
}
}
}
}
FileSpecList loaded_modules;
sym_vendor->GetLoadedModules(lldb::eLanguageTypeSwift, loaded_modules);
for (size_t mi = 0, me = loaded_modules.GetSize(); mi != me; ++mi) {
const FileSpec &loaded_module = loaded_modules.GetFileSpecAtIndex(mi);
if (loaded_module.Exists())
swift_ast_sp->AddModuleSearchPath(
loaded_module.GetDirectory().GetCString());
}
}
if (!set_triple) {
llvm::Triple llvm_triple(swift_ast_sp->GetTriple());
// LLVM wants this to be set to iOS or MacOSX; if we're working on
// a bare-boards type image, change the triple for LLVM's benefit.
if (llvm_triple.getVendor() == llvm::Triple::Apple &&
llvm_triple.getOS() == llvm::Triple::UnknownOS) {
if (llvm_triple.getArch() == llvm::Triple::arm ||
llvm_triple.getArch() == llvm::Triple::thumb) {
llvm_triple.setOS(llvm::Triple::IOS);
} else {
llvm_triple.setOS(llvm::Triple::MacOSX);
}
swift_ast_sp->SetTriple(llvm_triple.str().c_str(), &module);
}
}
if (!swift_ast_sp->GetClangImporter()) {
if (log) {
log->Printf("((Module*)%p) [%s]->GetSwiftASTContext() returning NULL "
"- couldn't create a ClangImporter",
&module,
module.GetFileSpec().GetFilename().AsCString("<anonymous>"));
}
return TypeSystemSP();
}
std::vector<std::string> module_names;
swift_ast_sp->RegisterSectionModules(module, module_names);
swift_ast_sp->ValidateSectionModules(module, module_names);
if (log) {
log->Printf("((Module*)%p) [%s]->GetSwiftASTContext() = %p", &module,
module.GetFileSpec().GetFilename().AsCString("<anonymous>"),
swift_ast_sp.get());
swift_ast_sp->DumpConfiguration(log);
}
return swift_ast_sp;
}
lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language,
Target &target,
const char *extra_options) {
if (!SwiftASTContextSupportsLanguage(language))
return lldb::TypeSystemSP();
ArchSpec arch = target.GetArchitecture();
// Make an AST but don't set the triple yet. We need to try and detect
// if we have a iOS simulator...
std::shared_ptr<SwiftASTContextForExpressions> swift_ast_sp(
new SwiftASTContextForExpressions(target));
if (!arch.IsValid())
return TypeSystemSP();
bool handled_sdk_path = false;
bool handled_resource_dir = false;
const size_t num_images = target.GetImages().GetSize();
// Set the SDK path and resource dir prior to doing search paths.
// Otherwise when we create search path options we put in the wrong SDK
// path.
FileSpec &target_sdk_spec = target.GetSDKPath();
if (target_sdk_spec && target_sdk_spec.Exists()) {
std::string platform_sdk_path(target_sdk_spec.GetPath());
swift_ast_sp->SetPlatformSDKPath(std::move(platform_sdk_path));
handled_sdk_path = true;
}
Status module_error;
for (size_t mi = 0; mi != num_images; ++mi) {
ModuleSP module_sp = target.GetImages().GetModuleAtIndex(mi);
SwiftASTContext *module_swift_ast = llvm::dyn_cast_or_null<SwiftASTContext>(
module_sp->GetTypeSystemForLanguage(lldb::eLanguageTypeSwift));
if (!module_swift_ast || module_swift_ast->HasFatalErrors() ||
!module_swift_ast->GetClangImporter()) {
// Make sure we warn about this module load failure, the one that
// comes from loading types often gets swallowed up and not seen,
// this is the only reliable point where we can show this.
// But only do it once per UUID so we don't overwhelm the user with
// warnings...
std::unordered_set<std::string> m_swift_warnings_issued;
UUID module_uuid(module_sp->GetUUID());
std::pair<std::unordered_set<std::string>::iterator, bool> result(
m_swift_warnings_issued.insert(module_uuid.GetAsString()));
if (result.second) {
StreamString ss;
module_sp->GetDescription(&ss, eDescriptionLevelBrief);
target.GetDebugger().GetErrorFile()->Printf(
"warning: Swift error in module %s" /*": \n %s\n"*/
".\nDebug info from this module will be unavailable in the "
"debugger.\n\n",
ss.GetData());
}
continue;
}
if (!handled_sdk_path) {
const char *platform_sdk_path = module_swift_ast->GetPlatformSDKPath();
if (platform_sdk_path) {
handled_sdk_path = true;
swift_ast_sp->SetPlatformSDKPath(platform_sdk_path);
}
}
if (!handled_resource_dir) {
const char *resource_dir = module_swift_ast->GetResourceDir();
if (resource_dir) {
handled_resource_dir = true;
swift_ast_sp->SetResourceDir(resource_dir);
if (GetDefaultResourceDir().empty()) {
// Tuck this away as a reasonable default resource dir
// for contexts that don't have one. The Swift parser
// will assert without one.
GetDefaultResourceDir() = resource_dir;
}
}
}
if (handled_sdk_path && handled_resource_dir)
break;
}
// First, prime the compiler with the options from the main executable:
bool read_options_from_ast = false;
ModuleSP exe_module_sp(target.GetExecutableModule());
// If we're debugging a testsuite, then treat the main test bundle as the
// executable.
if (exe_module_sp && PlatformDarwin::IsUnitTestExecutable(*exe_module_sp)) {
ModuleSP unit_test_module =
PlatformDarwin::GetUnitTestModule(target.GetImages());
if (unit_test_module) {
exe_module_sp = unit_test_module;
}
}
if (exe_module_sp) {
SymbolVendor *sym_vendor = exe_module_sp->GetSymbolVendor();
if (sym_vendor) {
// Retrieve the Swift ASTs from the symbol vendor.
auto ast_datas = sym_vendor->GetASTData(eLanguageTypeSwift);
if (!ast_datas.empty()) {
// We only initialize the compiler invocation with the first
// AST since it initializes some data that must remain static,
// like the SDK path and the triple for the produced output.
auto ast_data_sp = ast_datas.front();
llvm::StringRef section_data_ref((const char *)ast_data_sp->GetBytes(),
ast_data_sp->GetByteSize());
swift::serialization::Status result =
swift_ast_sp->GetCompilerInvocation().loadFromSerializedAST(
section_data_ref);
if (result == swift::serialization::Status::Valid) {
read_options_from_ast = true;
} else {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
if (log)
log->Printf("Attempt to load compiler options from Serialized "
"AST failed: %d (%zu AST data blobs total).",
result, ast_datas.size());
}
}
}
}
// Now if the user fully specified the triple, let that override the one
// we got from executable's options:
if (target.GetArchitecture().IsFullySpecifiedTriple()) {
swift_ast_sp->SetTriple(
target.GetArchitecture().GetTriple().str().c_str());
} else {
// Always run using the Host OS triple...
bool set_triple = false;
PlatformSP platform_sp(target.GetPlatform());
uint32_t major, minor, update;
if (platform_sp &&
platform_sp->GetOSVersion(major, minor, update,
target.GetProcessSP().get())) {
StreamString full_triple_name;
full_triple_name.PutCString(target.GetArchitecture().GetTriple().str());
if (major != UINT32_MAX) {
full_triple_name.Printf("%u", major);
if (minor != UINT32_MAX) {
full_triple_name.Printf(".%u", minor);
if (update != UINT32_MAX)
full_triple_name.Printf(".%u", update);
}
}
swift_ast_sp->SetTriple(full_triple_name.GetString().data());
set_triple = true;
}
if (!set_triple) {
ModuleSP exe_module_sp(target.GetExecutableModule());
if (exe_module_sp) {
Status exe_error;
SwiftASTContext *exe_swift_ctx =
llvm::dyn_cast_or_null<SwiftASTContext>(
exe_module_sp->GetTypeSystemForLanguage(
lldb::eLanguageTypeSwift));
if (exe_swift_ctx) {
swift_ast_sp->SetTriple(
exe_swift_ctx->GetLanguageOptions().Target.str().c_str());
}
}
}
}
const bool use_all_compiler_flags =
!read_options_from_ast || target.GetUseAllCompilerFlags();
std::function<void(ModuleSP &&)> process_one_module =
[&target, &swift_ast_sp, use_all_compiler_flags](ModuleSP &&module_sp) {
const FileSpec &module_file = module_sp->GetFileSpec();
std::string module_path = module_file.GetPath();
// Add the containing framework to the framework search path. Don't
// do that if this is the executable module, since it might be
// buried in some framework that we don't care about.
if (use_all_compiler_flags &&
target.GetExecutableModulePointer() != module_sp.get()) {
size_t framework_offset = module_path.rfind(".framework/");
if (framework_offset != std::string::npos) {
// Sometimes the version of the framework that got loaded has been
// stripped and in that case, adding it to the framework search
// path will just short-cut a clang search that might otherwise
// find the needed headers. So don't add these paths.
std::string framework_path =
module_path.substr(0, framework_offset);
framework_path.append(".framework");
FileSpec path_spec(framework_path, true);
FileSpec headers_spec =
path_spec.CopyByAppendingPathComponent("Headers");
bool add_it = false;
if (headers_spec.Exists())
add_it = true;
if (!add_it) {
FileSpec module_spec =
path_spec.CopyByAppendingPathComponent("Modules");
if (module_spec.Exists())
add_it = true;
}
if (!add_it) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
if (log)
log->Printf("process_one_module rejecting framework path"
" \"%s\" as it has no Headers "
"or Modules subdirectories.",
framework_path.c_str());
}
if (add_it) {
while (framework_offset && (module_path[framework_offset] != '/'))
framework_offset--;
if (module_path[framework_offset] == '/') {
// framework_offset now points to the '/';
std::string parent_path =
module_path.substr(0, framework_offset);
if (strncmp(parent_path.c_str(), "/System/Library",
strlen("/System/Library")) &&
!IsDeviceSupport(parent_path.c_str())) {
swift_ast_sp->AddFrameworkSearchPath(parent_path.c_str());
}
}
}
}
}
SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
if (sym_vendor) {
std::vector<std::string> module_names;
SymbolFile *sym_file = sym_vendor->GetSymbolFile();
if (sym_file) {
Status sym_file_error;
SwiftASTContext *ast_context =
llvm::dyn_cast_or_null<SwiftASTContext>(
sym_file->GetTypeSystemForLanguage(
lldb::eLanguageTypeSwift));
if (ast_context) {
if (use_all_compiler_flags ||
target.GetExecutableModulePointer() == module_sp.get()) {
for (size_t msi = 0,
mse = ast_context->GetNumModuleSearchPaths();
msi < mse; ++msi) {
const char *search_path =
ast_context->GetModuleSearchPathAtIndex(msi);
swift_ast_sp->AddModuleSearchPath(search_path);
}
for (size_t fsi = 0,
fse = ast_context->GetNumFrameworkSearchPaths();
fsi < fse; ++fsi) {
const char *search_path =
ast_context->GetFrameworkSearchPathAtIndex(fsi);
swift_ast_sp->AddFrameworkSearchPath(search_path);
}
for (size_t osi = 0, ose = ast_context->GetNumClangArguments();
osi < ose; ++osi) {
const char *clang_argument =
ast_context->GetClangArgumentAtIndex(osi);
swift_ast_sp->AddClangArgument(clang_argument, true);
}
}
swift_ast_sp->RegisterSectionModules(*module_sp, module_names);
}
}
}
};
for (size_t mi = 0; mi != num_images; ++mi) {
process_one_module(target.GetImages().GetModuleAtIndex(mi));
}
FileSpecList &framework_search_paths = target.GetSwiftFrameworkSearchPaths();
FileSpecList &module_search_paths = target.GetSwiftModuleSearchPaths();
for (size_t fi = 0, fe = framework_search_paths.GetSize(); fi != fe; ++fi) {
swift_ast_sp->AddFrameworkSearchPath(
framework_search_paths.GetFileSpecAtIndex(fi).GetPath().c_str());
}
for (size_t mi = 0, me = module_search_paths.GetSize(); mi != me; ++mi) {
swift_ast_sp->AddModuleSearchPath(
module_search_paths.GetFileSpecAtIndex(mi).GetPath().c_str());
}
// Now fold any extra options we were passed. This has to be done BEFORE
// the ClangImporter is made by calling GetClangImporter or these options
// will be ignored.
if (extra_options) {
swift::CompilerInvocation &compiler_invocation =
swift_ast_sp->GetCompilerInvocation();
Args extra_args(extra_options);
llvm::ArrayRef<const char *> extra_args_ref(extra_args.GetArgumentVector(),
extra_args.GetArgumentCount());
compiler_invocation.parseArgs(extra_args_ref,
swift_ast_sp->GetDiagnosticEngine());
}
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
// This needs to happen once all the import paths are set, or otherwise no
// modules will be found.
if (!swift_ast_sp->GetClangImporter()) {
if (log) {
log->Printf("((Target*)%p)->GetSwiftASTContext() returning NULL - "
"couldn't create a ClangImporter",
&target);
}
return TypeSystemSP();
}
if (log) {
log->Printf("((Target*)%p)->GetSwiftASTContext() = %p", &target,
swift_ast_sp.get());
swift_ast_sp->DumpConfiguration(log);
}
if (swift_ast_sp->HasFatalErrors()) {
swift_ast_sp->m_error.SetErrorStringWithFormat(
"Error creating target Swift AST context: %s",
swift_ast_sp->GetFatalErrors().AsCString());
return lldb::TypeSystemSP();
}
{
const bool can_create = true;
if (!swift_ast_sp->m_ast_context_ap->getStdlibModule(can_create)) {
// We need to be able to load the standard library!
return lldb::TypeSystemSP();
}
}
return swift_ast_sp;
}
void SwiftASTContext::EnumerateSupportedLanguages(
std::set<lldb::LanguageType> &languages_for_types,
std::set<lldb::LanguageType> &languages_for_expressions) {
static std::vector<lldb::LanguageType> s_supported_languages_for_types(
{lldb::eLanguageTypeSwift});
static std::vector<lldb::LanguageType> s_supported_languages_for_expressions(
{lldb::eLanguageTypeSwift});
languages_for_types.insert(s_supported_languages_for_types.begin(),
s_supported_languages_for_types.end());
languages_for_expressions.insert(
s_supported_languages_for_expressions.begin(),
s_supported_languages_for_expressions.end());
}
static lldb::TypeSystemSP CreateTypeSystemInstance(lldb::LanguageType language,
Module *module,
Target *target,
const char *extra_options) {
// This should be called with either a target or a module.
if (module) {
assert(!target);
assert(StringRef(extra_options).empty());
return SwiftASTContext::CreateInstance(language, *module);
} else if (target) {
assert(!module);
return SwiftASTContext::CreateInstance(language, *target, extra_options);
}
}
void SwiftASTContext::Initialize() {
PluginManager::RegisterPlugin(
GetPluginNameStatic(), "swift AST context plug-in",
CreateTypeSystemInstance, EnumerateSupportedLanguages);
}
void SwiftASTContext::Terminate() {
PluginManager::UnregisterPlugin(CreateTypeSystemInstance);
}
bool SwiftASTContext::SupportsLanguage(lldb::LanguageType language) {
return SwiftASTContextSupportsLanguage(language);
}
Status SwiftASTContext::IsCompatible() { return GetFatalErrors(); }
Status SwiftASTContext::GetFatalErrors() {
Status error;
if (HasFatalErrors()) {
error = m_fatal_errors;
if (error.Success())
error.SetErrorString("unknown fatal error in swift AST context");
}
return error;
}
swift::IRGenOptions &SwiftASTContext::GetIRGenOptions() {
return m_compiler_invocation_ap->getIRGenOptions();
}
std::string SwiftASTContext::GetTriple() const {
return m_compiler_invocation_ap->getTargetTriple();
}
// Conditions a triple string to be safe for use with Swift.
// Right now this just strips the Haswell marker off the CPU name.
// TODO make Swift more robust
static std::string GetSwiftFriendlyTriple(const std::string &triple) {
static std::string s_x86_64h("x86_64h");
static std::string::size_type s_x86_64h_size = s_x86_64h.size();
if (0 == triple.compare(0, s_x86_64h_size, s_x86_64h)) {
std::string fixed_triple("x86_64");
fixed_triple.append(
triple.substr(s_x86_64h_size, triple.size() - s_x86_64h_size));
return fixed_triple;
}
return triple;
}
bool SwiftASTContext::SetTriple(const char *triple_cstr, Module *module) {
if (triple_cstr && triple_cstr[0]) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
// We can change our triple up until we create the swift::irgen::IRGenModule
if (m_ir_gen_module_ap.get() == NULL) {
std::string raw_triple(triple_cstr);
std::string triple = GetSwiftFriendlyTriple(raw_triple);
llvm::Triple llvm_triple(triple);
const unsigned unspecified = 0;
// If the OS version is unspecified, do fancy things
if (llvm_triple.getOSMajorVersion() == unspecified) {
// If a triple is "<arch>-apple-darwin" change it to be
// "<arch>-apple-macosx" otherwise the major and minor OS version we
// append below would be wrong.
if (llvm_triple.getVendor() == llvm::Triple::VendorType::Apple &&
llvm_triple.getOS() == llvm::Triple::OSType::Darwin) {
llvm_triple.setOS(llvm::Triple::OSType::MacOSX);
triple = llvm_triple.str();
}
// Append the min OS to the triple if we have a target
ModuleSP module_sp;
if (module == NULL) {
TargetSP target_sp(m_target_wp.lock());
if (target_sp) {
module_sp = target_sp->GetExecutableModule();
if (module_sp)
module = module_sp.get();
}
}
if (module) {
ObjectFile *objfile = module->GetObjectFile();
uint32_t versions[3];
if (objfile) {
uint32_t num_versions = objfile->GetMinimumOSVersion(versions, 3);
StreamString strm;
if (num_versions) {
for (uint32_t v = 0; v < 3; ++v) {
if (v < num_versions) {
if (versions[v] == UINT32_MAX)
versions[v] = 0;
} else
versions[v] = 0;
}
strm.Printf("%s%u.%u.%u", llvm_triple.getOSName().str().c_str(),
versions[0], versions[1], versions[2]);
llvm_triple.setOSName(strm.GetString());
triple = llvm_triple.str();
}
}
}
}
if (log)
log->Printf("%p: SwiftASTContext::SetTriple('%s') setting to '%s'%s",
this, triple_cstr, triple.c_str(),
m_target_wp.lock() ? " (target)" : "");
m_compiler_invocation_ap->setTargetTriple(triple);
return true;
} else {
if (log)
log->Printf("%p: SwiftASTContext::SetTriple('%s') ignoring triple "
"since the IRGenModule has already been created",
this, triple_cstr);
}
}
return false;
}
static std::string GetXcodeContentsPath() {
const char substr[] = ".app/Contents/";
// First, try based on the current shlib's location
{
FileSpec fspec;
if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, fspec)) {
std::string path_to_shlib = fspec.GetPath();
size_t pos = path_to_shlib.rfind(substr);
if (pos != std::string::npos) {
path_to_shlib.erase(pos + strlen(substr));
return path_to_shlib;
}
}
}
// Fall back to using xcrun
{
int status = 0;
int signo = 0;
std::string output;
const char *command = "xcrun -sdk macosx --show-sdk-path";
lldb_private::Status error = Host::RunShellCommand(
command, // shell command to run
NULL, // current working directory
&status, // Put the exit status of the process in here
&signo, // Put the signal that caused the process to exit in here
&output, // Get the output from the command and place it in this string
3); // Timeout in seconds to wait for shell program to finish
if (status == 0 && !output.empty()) {
size_t first_non_newline = output.find_last_not_of("\r\n");
if (first_non_newline != std::string::npos) {
output.erase(first_non_newline + 1);
}
size_t pos = output.rfind(substr);
if (pos != std::string::npos) {
output.erase(pos + strlen(substr));
return output;
}
}
}
return std::string();
}
static std::string GetCurrentToolchainPath() {
const char substr[] = ".xctoolchain/";
{
FileSpec fspec;
if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, fspec)) {
std::string path_to_shlib = fspec.GetPath();
size_t pos = path_to_shlib.rfind(substr);
if (pos != std::string::npos) {
path_to_shlib.erase(pos + strlen(substr));
return path_to_shlib;
}
}
}
return std::string();
}
static std::string GetCurrentCLToolsPath() {
const char substr[] = "/CommandLineTools/";
{
FileSpec fspec;
if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, fspec)) {
std::string path_to_shlib = fspec.GetPath();
size_t pos = path_to_shlib.rfind(substr);
if (pos != std::string::npos) {
path_to_shlib.erase(pos + strlen(substr));
return path_to_shlib;
}
}
}
return std::string();
}
namespace {
enum class SDKType {
MacOSX = 0,
iPhoneSimulator,
iPhoneOS,
AppleTVSimulator,
AppleTVOS,
WatchSimulator,
watchOS,
numSDKTypes,
unknown = -1
};
const char *const sdk_strings[] = {
"macosx", "iphonesimulator", "iphoneos", "appletvsimulator",
"appletvos", "watchsimulator", "watchos",
};
struct SDKEnumeratorInfo {
FileSpec found_path;
SDKType sdk_type;
uint32_t least_major;
uint32_t least_minor;
};
static bool SDKSupportsSwift(const FileSpec &sdk_path, SDKType desired_type) {
ConstString last_path_component = sdk_path.GetLastPathComponent();
if (last_path_component) {
const llvm::StringRef sdk_name_raw = last_path_component.GetStringRef();
std::string sdk_name_lower = sdk_name_raw.lower();
const llvm::StringRef sdk_name(sdk_name_lower);
llvm::StringRef version_part;
SDKType sdk_type = SDKType::unknown;
if (desired_type == SDKType::unknown) {
for (int i = (int)SDKType::MacOSX; i < (int)SDKType::numSDKTypes; ++i) {
if (sdk_name.startswith(sdk_strings[i])) {
version_part = sdk_name.drop_front(strlen(sdk_strings[i]));
sdk_type = (SDKType)i;
break;
}
}
// For non-Darwin SDKs assume Swift is supported
if (sdk_type == SDKType::unknown)
return true;
} else {
if (sdk_name.startswith(sdk_strings[(int)desired_type])) {
version_part =
sdk_name.drop_front(strlen(sdk_strings[(int)desired_type]));
sdk_type = desired_type;
} else {
return false;
}
}
const size_t major_dot_offset = version_part.find('.');
if (major_dot_offset == llvm::StringRef::npos)
return false;
const llvm::StringRef major_version =
version_part.slice(0, major_dot_offset);
const llvm::StringRef minor_part =
version_part.drop_front(major_dot_offset + 1);
const size_t minor_dot_offset = minor_part.find('.');
if (minor_dot_offset == llvm::StringRef::npos)
return false;
const llvm::StringRef minor_version = minor_part.slice(0, minor_dot_offset);
unsigned int major = 0;
unsigned int minor = 0;
if (major_version.getAsInteger(10, major))
return false;
if (minor_version.getAsInteger(10, minor))
return false;
switch (sdk_type) {
case SDKType::MacOSX:
if (major > 10 || (major == 10 && minor >= 10))
return true;
break;
case SDKType::iPhoneOS:
case SDKType::iPhoneSimulator:
if (major >= 8)
return true;
break;
case SDKType::AppleTVSimulator:
case SDKType::AppleTVOS:
if (major >= 9)
return true;
break;
case SDKType::WatchSimulator:
case SDKType::watchOS:
if (major >= 2)
return true;
break;
default:
return false;
}
}
return false;
}
FileSpec::EnumerateDirectoryResult
DirectoryEnumerator(void *baton, llvm::sys::fs::file_type file_type,
const FileSpec &spec) {
SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo *>(baton);
if (SDKSupportsSwift(spec, enumerator_info->sdk_type)) {
enumerator_info->found_path = spec;
return FileSpec::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
}
return FileSpec::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
};
static ConstString EnumerateSDKsForVersion(FileSpec sdks_spec, SDKType sdk_type,
uint32_t least_major,
uint32_t least_minor) {
if (!IsDirectory(sdks_spec))
return ConstString();
const bool find_directories = true;
const bool find_files = false;
const bool find_other = true; // include symlinks
SDKEnumeratorInfo enumerator_info;
enumerator_info.sdk_type = sdk_type;
enumerator_info.least_major = least_major;
enumerator_info.least_minor = least_minor;
FileSpec::EnumerateDirectory(sdks_spec.GetPath().c_str(), find_directories,
find_files, find_other, DirectoryEnumerator,
&enumerator_info);
if (IsDirectory(enumerator_info.found_path))
return ConstString(enumerator_info.found_path.GetPath());
else
return ConstString();
}
static ConstString GetSDKDirectory(SDKType sdk_type, uint32_t least_major,
uint32_t least_minor) {
if (sdk_type != SDKType::MacOSX) {
// Look inside Xcode for the required installed iOS SDK version
std::string sdks_path = GetXcodeContentsPath();
sdks_path.append("Developer/Platforms");
if (sdk_type == SDKType::iPhoneSimulator) {
sdks_path.append("/iPhoneSimulator.platform/");
} else if (sdk_type == SDKType::AppleTVSimulator) {
sdks_path.append("/AppleTVSimulator.platform/");
} else if (sdk_type == SDKType::AppleTVOS) {
sdks_path.append("/AppleTVOS.platform/");
} else if (sdk_type == SDKType::WatchSimulator) {
sdks_path.append("/WatchSimulator.platform/");
} else if (sdk_type == SDKType::watchOS) {
// For now, we need to be prepared to handle either capitalization of this
// path.
std::string WatchOS_candidate_path = sdks_path + "/WatchOS.platform/";
if (IsDirectory(FileSpec(WatchOS_candidate_path.c_str(), false))) {
sdks_path = WatchOS_candidate_path;
} else {
std::string watchOS_candidate_path = sdks_path + "/watchOS.platform/";
if (IsDirectory(FileSpec(watchOS_candidate_path.c_str(), false))) {
sdks_path = watchOS_candidate_path;
} else {
return ConstString();
}
}
} else {
sdks_path.append("/iPhoneOS.platform/");
}
sdks_path.append("Developer/SDKs/");
FileSpec sdks_spec(sdks_path.c_str(), false);
return EnumerateSDKsForVersion(sdks_spec, sdk_type, least_major,
least_major);
}
// The SDK type is Mac OS X
uint32_t major = 0;
uint32_t minor = 0;
uint32_t update = 0;
if (!HostInfo::GetOSVersion(major, minor, update))
return ConstString();
// If there are minimum requirements that exceed the current OS, apply those
if (least_major > major) {
major = least_major;
minor = least_minor;
} else if (least_major == major) {
if (least_minor > minor)
minor = least_minor;
}
typedef std::map<uint64_t, ConstString> SDKDirectoryCache;
static std::mutex g_mutex;
static SDKDirectoryCache g_sdk_cache;
std::lock_guard<std::mutex> locker(g_mutex);
const uint64_t major_minor = (uint64_t)major << 32 | (uint64_t)minor;
SDKDirectoryCache::iterator pos = g_sdk_cache.find(major_minor);
if (pos != g_sdk_cache.end())
return pos->second;
FileSpec fspec;
std::string xcode_contents_path;
if (xcode_contents_path.empty())
xcode_contents_path = GetXcodeContentsPath();
if (!xcode_contents_path.empty()) {
StreamString sdk_path;
sdk_path.Printf(
"%sDeveloper/Platforms/MacOSX.platform/Developer/SDKs/MacOSX%u.%u.sdk",
xcode_contents_path.c_str(), major, minor);
fspec.SetFile(sdk_path.GetString(), false);
if (fspec.Exists()) {
ConstString path(sdk_path.GetString());
// Cache results
g_sdk_cache[major_minor] = path;
return path;
} else if ((least_major != major) || (least_minor != minor)) {
// Try the required SDK
sdk_path.Clear();
sdk_path.Printf("%sDeveloper/Platforms/MacOSX.platform/Developer/SDKs/"
"MacOSX%u.%u.sdk",
xcode_contents_path.c_str(), least_major, least_minor);
fspec.SetFile(sdk_path.GetString(), false);
if (fspec.Exists()) {
ConstString path(sdk_path.GetString());
// Cache results
g_sdk_cache[major_minor] = path;
return path;
} else {
// Okay, we're going to do an exhaustive search for *any* SDK that has
// an adequate version.
std::string sdks_path = GetXcodeContentsPath();
sdks_path.append("Developer/Platforms/MacOSX.platform/Developer/SDKs");
FileSpec sdks_spec(sdks_path.c_str(), false);
ConstString sdk_path = EnumerateSDKsForVersion(
sdks_spec, sdk_type, least_major, least_major);
if (sdk_path) {
g_sdk_cache[major_minor] = sdk_path;
return sdk_path;
}
}
}
}
// Cache results
g_sdk_cache[major_minor] = ConstString();
return ConstString();
}
static ConstString GetResourceDir() {
static ConstString g_cached_resource_dir;
static std::once_flag g_once_flag;
std::call_once(g_once_flag, []() {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
// First, check if there's something in our bundle
{
FileSpec swift_dir_spec;
if (HostInfo::GetLLDBPath(ePathTypeSwiftDir, swift_dir_spec)) {
if (log)
log->Printf("%s: trying ePathTypeSwiftDir: %s", __FUNCTION__,
swift_dir_spec.GetCString());
// We can't just check for the Swift directory, because that
// always exists. We have to look for "clang" inside that.
FileSpec swift_clang_dir_spec = swift_dir_spec;
swift_clang_dir_spec.AppendPathComponent("clang");
if (IsDirectory(swift_clang_dir_spec)) {
g_cached_resource_dir = ConstString(swift_dir_spec.GetPath());
if (log)
log->Printf("%s: found Swift resource dir via "
"ePathTypeSwiftDir': %s",
__FUNCTION__, g_cached_resource_dir.AsCString());
return;
}
}
}
// Nothing in our bundle. Are we in a toolchain that has its own Swift
// compiler resource dir?
{
std::string xcode_toolchain_path = GetCurrentToolchainPath();
if (log)
log->Printf("%s: trying toolchain path: %s", __FUNCTION__,
xcode_toolchain_path.c_str());
if (!xcode_toolchain_path.empty()) {
xcode_toolchain_path.append("usr/lib/swift");
if (log)
log->Printf("%s: trying toolchain-based lib path: %s", __FUNCTION__,
xcode_toolchain_path.c_str());
if (IsDirectory(FileSpec(xcode_toolchain_path, false))) {
g_cached_resource_dir = ConstString(xcode_toolchain_path);
if (log)
log->Printf("%s: found Swift resource dir via "
"toolchain path + 'usr/lib/swift': %s",
__FUNCTION__, g_cached_resource_dir.AsCString());
return;
}
}
}
// We're not in a toolchain that has one. Use the Xcode default toolchain.
{
std::string xcode_contents_path = GetXcodeContentsPath();
if (log)
log->Printf("%s: trying Xcode path: %s", __FUNCTION__,
xcode_contents_path.c_str());
if (!xcode_contents_path.empty()) {
xcode_contents_path.append("Developer/Toolchains/"
"XcodeDefault.xctoolchain"
"/usr/lib/swift");
if (log)
log->Printf("%s: trying Xcode-based lib path: %s", __FUNCTION__,
xcode_contents_path.c_str());
if (IsDirectory(FileSpec(xcode_contents_path, false))) {
g_cached_resource_dir = ConstString(xcode_contents_path);
if (log)
log->Printf("%s: found Swift resource dir via "
"Xcode contents path + default toolchain "
"relative dir: %s",
__FUNCTION__, g_cached_resource_dir.AsCString());
return;
}
}
}
// We're not in Xcode. We might be in the command-line tools.
{
std::string cl_tools_path = GetCurrentCLToolsPath();
if (log)
log->Printf("%s: trying command-line tools path: %s", __FUNCTION__,
cl_tools_path.c_str());
if (!cl_tools_path.empty()) {
cl_tools_path.append("usr/lib/swift");
if (log)
log->Printf("%s: trying command-line tools-based lib "
"path: %s",
__FUNCTION__, cl_tools_path.c_str());
if (IsDirectory(FileSpec(cl_tools_path, false))) {
g_cached_resource_dir = ConstString(cl_tools_path);
if (log)
log->Printf("%s: found Swift resource dir via "
"command-line tools path + "
"usr/lib/swift: %s",
__FUNCTION__, g_cached_resource_dir.AsCString());
return;
}
}
}
// We might be in the build-dir configuration for a build-script-driven
// LLDB build, which has the Swift build dir as a sibling directory
// to the lldb build dir. This looks much different than the install-
// dir layout that the previous checks would try.
{
FileSpec faux_swift_dir_spec;
if (HostInfo::GetLLDBPath(ePathTypeSwiftDir, faux_swift_dir_spec)) {
// We can't use a C++11 stdlib regex feature here because it
// doesn't work on Ubuntu 14.04 x86_64. Once we don't care
// about supporting that anymore, let's pull the code below
// back in since it is a simpler implementation using
// std::regex.
#if 0
// Let's try to regex this.
// We're looking for /some/path/lldb-{os}-{arch}, and want to
// build the following:
// /some/path/swift-{os}-{arch}/lib/swift/{os}/{arch}
// In a match, these are the following assignments for
// backrefs:
// $1 - first part of path before swift build dir
// $2 - the host OS path separator character
// $3 - all the stuff that should come after changing
// lldb to swift for the lib dir.
auto match_regex =
std::regex("^(.+([/\\\\]))lldb-(.+)$");
const std::string replace_format = "$1swift-$3";
const std::string faux_swift_dir =
faux_swift_dir_spec.GetCString();
const std::string build_tree_resource_dir =
std::regex_replace(faux_swift_dir, match_regex,
replace_format);
#else
std::string build_tree_resource_dir;
const std::string faux_swift_dir =
faux_swift_dir_spec.GetCString();
// Find something that matches lldb- (particularly,
// the last one).
const std::string lldb_dash("lldb-");
auto lldb_pos = faux_swift_dir.rfind(lldb_dash);
if ((lldb_pos != std::string::npos) &&
(lldb_pos > 0) &&
((faux_swift_dir[lldb_pos - 1] == '\\') ||
(faux_swift_dir[lldb_pos - 1] == '/')))
{
// We found something that matches ^.+[/\\]lldb-.+$
std::ostringstream stream;
// Take everything before lldb- (the path leading up to
// the lldb dir).
stream << faux_swift_dir.substr(0, lldb_pos);
// replace lldb- with swift-.
stream << "swift-";
// and now tack on the same components from after
// the lldb- part.
stream << faux_swift_dir.substr(lldb_pos +
lldb_dash.length());
const std::string build_tree_resource_dir = stream.str();
if (log)
log->Printf("%s: trying ePathTypeSwiftDir regex-based "
"build dir: %s",
__FUNCTION__,
build_tree_resource_dir.c_str());
FileSpec swift_resource_dir_spec(
build_tree_resource_dir.c_str(), false);
if (IsDirectory(swift_resource_dir_spec))
{
g_cached_resource_dir =
ConstString(swift_resource_dir_spec.GetPath());
if (log)
log->Printf("%s: found Swift resource dir via "
"ePathTypeSwiftDir + inferred "
"build-tree dir: %s", __FUNCTION__,
g_cached_resource_dir.AsCString());
return;
}
}
#endif
}
}
// We failed to find a reasonable Swift resource dir.
if (log)
log->Printf("%s: failed to find a Swift resource dir", __FUNCTION__);
});
return g_cached_resource_dir;
}
} // anonymous namespace
swift::CompilerInvocation &SwiftASTContext::GetCompilerInvocation() {
return *m_compiler_invocation_ap;
}
swift::SourceManager &SwiftASTContext::GetSourceManager() {
if (m_source_manager_ap.get() == NULL)
m_source_manager_ap.reset(new swift::SourceManager());
return *m_source_manager_ap;
}
swift::LangOptions &SwiftASTContext::GetLanguageOptions() {
return GetCompilerInvocation().getLangOptions();
}
swift::DiagnosticEngine &SwiftASTContext::GetDiagnosticEngine() {
if (m_diagnostic_engine_ap.get() == NULL)
m_diagnostic_engine_ap.reset(
new swift::DiagnosticEngine(GetSourceManager()));
return *m_diagnostic_engine_ap;
}
// This code comes from CompilerInvocation.cpp (setRuntimeResourcePath)
static void ConfigureResourceDirs(swift::CompilerInvocation &invocation,
FileSpec resource_dir, llvm::Triple triple) {
// Make sure the triple is right:
invocation.setTargetTriple(triple.str());
invocation.setRuntimeResourcePath(resource_dir.GetPath().c_str());
}
swift::SILOptions &SwiftASTContext::GetSILOptions() {
return GetCompilerInvocation().getSILOptions();
}
bool SwiftASTContext::TargetHasNoSDK() {
llvm::Triple triple(GetTriple());
switch (triple.getOS()) {
case llvm::Triple::OSType::MacOSX:
case llvm::Triple::OSType::Darwin:
case llvm::Triple::OSType::IOS:
return false;
default:
return true;
}
}
swift::ClangImporterOptions &SwiftASTContext::GetClangImporterOptions() {
swift::ClangImporterOptions &clang_importer_options =
GetCompilerInvocation().getClangImporterOptions();
if (!m_initialized_clang_importer_options) {
m_initialized_clang_importer_options = true;
// Set the Clang module search path.
llvm::SmallString<128> Path;
// FIXME: This should be querying
// target.GetClangModulesCachePath(), but most of the times there
// is no target available when this function is called.
clang::driver::Driver::getDefaultModuleCachePath(Path);
clang_importer_options.ModuleCachePath = Path.str();
FileSpec clang_dir_spec;
if (HostInfo::GetLLDBPath(ePathTypeClangDir, clang_dir_spec))
clang_importer_options.OverrideResourceDir =
std::move(clang_dir_spec.GetPath());
clang_importer_options.DebuggerSupport = true;
}
return clang_importer_options;
}
swift::SearchPathOptions &SwiftASTContext::GetSearchPathOptions() {
swift::SearchPathOptions &search_path_opts =
GetCompilerInvocation().getSearchPathOptions();
if (!m_initialized_search_path_options) {
m_initialized_search_path_options = true;
bool set_sdk = false;
bool set_resource_dir = false;
if (!search_path_opts.SDKPath.empty()) {
FileSpec provided_sdk_path(search_path_opts.SDKPath, false);
if (provided_sdk_path.Exists()) {
// We don't check whether the SDK supports swift because we figure if
// someone is passing this to us on the command line (e.g., for the
// REPL), they probably know what they're doing.
set_sdk = true;
}
} else if (!m_platform_sdk_path.empty()) {
FileSpec platform_sdk(m_platform_sdk_path.c_str(), false);
if (platform_sdk.Exists() &&
SDKSupportsSwift(platform_sdk, SDKType::unknown)) {
search_path_opts.SDKPath = m_platform_sdk_path.c_str();
set_sdk = true;
}
}
llvm::Triple triple(GetTriple());
if (!m_resource_dir.empty()) {
FileSpec resource_dir(m_resource_dir.c_str(), false);
if (resource_dir.Exists()) {
ConfigureResourceDirs(GetCompilerInvocation(), resource_dir, triple);
set_resource_dir = true;
}
}
if (!set_sdk) {
if (triple.getOS() == llvm::Triple::OSType::MacOSX ||
triple.getOS() == llvm::Triple::OSType::Darwin) {
search_path_opts.SDKPath = GetSDKDirectory(SDKType::MacOSX, 10, 10)
.AsCString(""); // we need the 10.10 SDK
} else if (triple.getOS() == llvm::Triple::OSType::IOS) {
if (triple.getArchName().startswith("arm")) {
search_path_opts.SDKPath =
GetSDKDirectory(SDKType::iPhoneOS, 8, 0).AsCString("");
} else {
search_path_opts.SDKPath =
GetSDKDirectory(SDKType::iPhoneSimulator, 8, 0).AsCString("");
}
}
// explicitly leave the SDKPath blank on other platforms
}
if (!set_resource_dir) {
FileSpec resource_dir(::GetResourceDir().AsCString(""), false);
if (resource_dir.Exists())
ConfigureResourceDirs(GetCompilerInvocation(), resource_dir, triple);
}
}
return search_path_opts;
}
namespace lldb_private {
class ANSIColorStringStream : public llvm::raw_string_ostream {
public:
ANSIColorStringStream(bool colorize)
: llvm::raw_string_ostream(m_buffer), m_colorize(colorize) {}
/// Changes the foreground color of text that will be output from this point
/// forward.
/// @param Color ANSI color to use, the special SAVEDCOLOR can be used to
/// change only the bold attribute, and keep colors untouched
/// @param Bold bold/brighter text, default false
/// @param BG if true change the background, default: change foreground
/// @returns itself so it can be used within << invocations
virtual raw_ostream &changeColor(enum Colors colors, bool bold = false,
bool bg = false) {
if (llvm::sys::Process::ColorNeedsFlush())
flush();
const char *colorcode;
if (colors == SAVEDCOLOR)
colorcode = llvm::sys::Process::OutputBold(bg);
else
colorcode = llvm::sys::Process::OutputColor(colors, bold, bg);
if (colorcode) {
size_t len = strlen(colorcode);
write(colorcode, len);
}
return *this;
}
/// Resets the colors to terminal defaults. Call this when you are done
/// outputting colored text, or before program exit.
virtual raw_ostream &resetColor() {
if (llvm::sys::Process::ColorNeedsFlush())
flush();
const char *colorcode = llvm::sys::Process::ResetColor();
if (colorcode) {
size_t len = strlen(colorcode);
write(colorcode, len);
}
return *this;
}
/// Reverses the forground and background colors.
virtual raw_ostream &reverseColor() {
if (llvm::sys::Process::ColorNeedsFlush())
flush();
const char *colorcode = llvm::sys::Process::OutputReverse();
if (colorcode) {
size_t len = strlen(colorcode);
write(colorcode, len);
}
return *this;
}
/// This function determines if this stream is connected to a "tty" or
/// "console" window. That is, the output would be displayed to the user
/// rather than being put on a pipe or stored in a file.
virtual bool is_displayed() const { return m_colorize; }
/// This function determines if this stream is displayed and supports colors.
virtual bool has_colors() const { return m_colorize; }
protected:
std::string m_buffer;
bool m_colorize;
};
class StoringDiagnosticConsumer : public swift::DiagnosticConsumer {
public:
StoringDiagnosticConsumer(SwiftASTContext &ast_context)
: m_ast_context(ast_context), m_diagnostics(), m_num_errors(0),
m_colorize(false) {
m_ast_context.GetDiagnosticEngine().resetHadAnyError();
m_ast_context.GetDiagnosticEngine().addConsumer(*this);
}
~StoringDiagnosticConsumer() {
m_ast_context.GetDiagnosticEngine().takeConsumers();
}
virtual void handleDiagnostic(swift::SourceManager &source_mgr,
swift::SourceLoc source_loc,
swift::DiagnosticKind kind,
llvm::StringRef formatString,
llvm::ArrayRef<swift::DiagnosticArgument> formatArgs,
const swift::DiagnosticInfo &info) {
llvm::StringRef bufferName = "<anonymous>";
unsigned bufferID = 0;
std::pair<unsigned, unsigned> line_col = {0, 0};
llvm::SmallString<256> text;
{
llvm::raw_svector_ostream out(text);
swift::DiagnosticEngine::formatDiagnosticText(out,
formatString,
formatArgs);
}
if (source_loc.isValid()) {
bufferID = source_mgr.findBufferContainingLoc(source_loc);
bufferName = source_mgr.getBufferIdentifierForLoc(source_loc);
line_col = source_mgr.getLineAndColumn(source_loc);
}
if (line_col.first != 0) {
ANSIColorStringStream os(m_colorize);
// Determine what kind of diagnostic we're emitting, and whether we want
// to use its fixits:
bool use_fixits = false;
llvm::SourceMgr::DiagKind source_mgr_kind;
switch (kind) {
default:
case swift::DiagnosticKind::Error:
source_mgr_kind = llvm::SourceMgr::DK_Error;
use_fixits = true;
break;
case swift::DiagnosticKind::Warning:
source_mgr_kind = llvm::SourceMgr::DK_Warning;
break;
case swift::DiagnosticKind::Note:
source_mgr_kind = llvm::SourceMgr::DK_Note;
break;
}
// Translate ranges.
llvm::SmallVector<llvm::SMRange, 2> ranges;
for (auto R : info.Ranges)
ranges.push_back(getRawRange(source_mgr, R));
// Translate fix-its.
llvm::SmallVector<llvm::SMFixIt, 2> fix_its;
for (swift::DiagnosticInfo::FixIt F : info.FixIts)
fix_its.push_back(getRawFixIt(source_mgr, F));
// Display the diagnostic.
auto message = source_mgr.GetMessage(source_loc, source_mgr_kind, text,
ranges, fix_its);
source_mgr.getLLVMSourceMgr().PrintMessage(os, message);
// Use the llvm::raw_string_ostream::str() accessor as it will flush
// the stream into our "message" and return us a reference to "message".
std::string &message_ref = os.str();
if (message_ref.empty())
m_diagnostics.push_back(RawDiagnostic(
text.str(), kind, bufferName, bufferID, line_col.first,
line_col.second,
use_fixits ? info.FixIts
: llvm::ArrayRef<swift::Diagnostic::FixIt>()));
else
m_diagnostics.push_back(RawDiagnostic(
message_ref, kind, bufferName, bufferID, line_col.first,
line_col.second,
use_fixits ? info.FixIts
: llvm::ArrayRef<swift::Diagnostic::FixIt>()));
} else {
m_diagnostics.push_back(RawDiagnostic(
text.str(), kind, bufferName, bufferID, line_col.first,
line_col.second, llvm::ArrayRef<swift::Diagnostic::FixIt>()));
}
if (kind == swift::DiagnosticKind::Error)
m_num_errors++;
}
void Clear() {
m_ast_context.GetDiagnosticEngine().resetHadAnyError();
m_diagnostics.clear();
m_num_errors = 0;
}
unsigned NumErrors() {
if (m_num_errors)
return m_num_errors;
else if (m_ast_context.GetASTContext()->hadError())
return 1;
else
return 0;
}
static DiagnosticSeverity SeverityForKind(swift::DiagnosticKind kind) {
switch (kind) {
case swift::DiagnosticKind::Error:
return eDiagnosticSeverityError;
case swift::DiagnosticKind::Warning:
return eDiagnosticSeverityWarning;
case swift::DiagnosticKind::Note:
return eDiagnosticSeverityRemark;
}
llvm_unreachable("Unhandled DiagnosticKind in switch.");
}
void PrintDiagnostics(DiagnosticManager &diagnostic_manager,
uint32_t bufferID = UINT32_MAX, uint32_t first_line = 0,
uint32_t last_line = UINT32_MAX,
uint32_t line_offset = 0) {
bool added_one_diagnostic = false;
for (const RawDiagnostic &diagnostic : m_diagnostics) {
// We often make expressions and wrap them in some code.
// When we see errors we want the line numbers to be correct so
// we correct them below. LLVM stores in SourceLoc objects as character
// offsets so there is no way to get LLVM to move its error line numbers
// around by adjusting the source location, we must do it manually. We
// also want to use the same error formatting as LLVM and Clang, so we
// must muck with the string.
const DiagnosticSeverity severity = SeverityForKind(diagnostic.kind);
const DiagnosticOrigin origin = eDiagnosticOriginSwift;
if (first_line > 0 && bufferID != UINT32_MAX &&
diagnostic.bufferID == bufferID && !diagnostic.bufferName.empty()) {
// Make sure the error line is in range
if (diagnostic.line >= first_line && diagnostic.line <= last_line) {
// Need to remap the error/warning to a different line
StreamString match;
match.Printf("%s:%u:", diagnostic.bufferName.str().c_str(),
diagnostic.line);
const size_t match_len = match.GetString().size();
size_t match_pos = diagnostic.description.find(match.GetString());
if (match_pos != std::string::npos) {
// We have some <file>:<line>:" instances that need to be updated
StreamString fixed_description;
size_t start_pos = 0;
do {
if (match_pos > start_pos)
fixed_description.Printf(
"%s", diagnostic.description.substr(start_pos, match_pos)
.c_str());
fixed_description.Printf("%s:%u:",
diagnostic.bufferName.str().c_str(),
diagnostic.line - first_line +
line_offset + 1);
start_pos = match_pos + match_len;
match_pos =
diagnostic.description.find(match.GetString(), start_pos);
} while (match_pos != std::string::npos);
// Append any last remainging text
if (start_pos < diagnostic.description.size())
fixed_description.Printf(
"%s",
diagnostic.description.substr(start_pos,
diagnostic.description.size() -
start_pos)
.c_str());
SwiftDiagnostic *new_diagnostic =
new SwiftDiagnostic(fixed_description.GetString().data(),
severity, origin, bufferID);
for (auto fixit : diagnostic.fixits)
new_diagnostic->AddFixIt(fixit);
diagnostic_manager.AddDiagnostic(new_diagnostic);
added_one_diagnostic = true;
continue;
}
}
}
}
// In general, we don't want to see diagnostics from outside of the source
// text range of the actual user expression. But if we didn't find any
// diagnostics in the text range, it's probably because the source range was
// not specified correctly, and we don't want to lose legit errors because
// of that. So in that case we'll add them all here:
if (!added_one_diagnostic) {
// This will report diagnostic errors from outside the expression's source
// range. Those are not interesting to users, so we only emit them in
// debug builds.
for (const RawDiagnostic &diagnostic : m_diagnostics) {
const DiagnosticSeverity severity = SeverityForKind(diagnostic.kind);
const DiagnosticOrigin origin = eDiagnosticOriginSwift;
diagnostic_manager.AddDiagnostic(diagnostic.description.c_str(),
severity, origin);
}
}
}
bool GetColorize() const { return m_colorize; }
bool SetColorize(bool b) {
const bool old = m_colorize;
m_colorize = b;
return old;
}
private:
// We don't currently use lldb_private::Diagostic or any of the lldb
// DiagnosticManager machinery to store diagnostics as they occur. Instead,
// we store them in raw form using this struct, then transcode them to
// SwiftDiagnostics in PrintDiagnostic.
struct RawDiagnostic {
RawDiagnostic(std::string in_desc, swift::DiagnosticKind in_kind,
llvm::StringRef in_bufferName, unsigned in_bufferID,
uint32_t in_line, uint32_t in_column,
llvm::ArrayRef<swift::Diagnostic::FixIt> in_fixits)
: description(in_desc), kind(in_kind), bufferName(in_bufferName),
bufferID(in_bufferID), line(in_line), column(in_column) {
for (auto fixit : in_fixits) {
fixits.push_back(fixit);
}
}
std::string description;
swift::DiagnosticKind kind;
const llvm::StringRef bufferName;
unsigned bufferID;
uint32_t line;
uint32_t column;
std::vector<swift::DiagnosticInfo::FixIt> fixits;
};
typedef std::vector<RawDiagnostic> RawDiagnosticBuffer;
SwiftASTContext &m_ast_context;
RawDiagnosticBuffer m_diagnostics;
unsigned m_num_errors = 0;
bool m_colorize;
};
}
swift::ASTContext *SwiftASTContext::GetASTContext() {
if (m_ast_context_ap.get() == NULL) {
m_ast_context_ap.reset(
new swift::ASTContext(GetLanguageOptions(), GetSearchPathOptions(),
GetSourceManager(), GetDiagnosticEngine()));
m_diagnostic_consumer_ap.reset(new StoringDiagnosticConsumer(*this));
if (getenv("LLDB_SWIFT_DUMP_DIAGS")) {
// NOTE: leaking a swift::PrintingDiagnosticConsumer() here, but this only
// gets enabled when the above environment variable is set.
GetDiagnosticEngine().addConsumer(
*new swift::PrintingDiagnosticConsumer());
}
// Install the serialized module loader
std::unique_ptr<swift::ModuleLoader> serialized_module_loader_ap(
swift::SerializedModuleLoader::create(*m_ast_context_ap));
if (serialized_module_loader_ap) {
m_serialized_module_loader =
(swift::SerializedModuleLoader *)serialized_module_loader_ap.get();
m_ast_context_ap->addModuleLoader(std::move(serialized_module_loader_ap));
}
GetASTMap().Insert(m_ast_context_ap.get(), this);
}
VALID_OR_RETURN(nullptr);
return m_ast_context_ap.get();
}
swift::SerializedModuleLoader *SwiftASTContext::GetSerializeModuleLoader() {
VALID_OR_RETURN(nullptr);
GetASTContext();
return m_serialized_module_loader;
}
swift::ClangImporter *SwiftASTContext::GetClangImporter() {
VALID_OR_RETURN(nullptr);
if (m_clang_importer == NULL) {
swift::ASTContext *ast_ctx = GetASTContext();
if (!ast_ctx) {
return nullptr;
}
// Install the Clang module loader
TargetSP target_sp(m_target_wp.lock());
if (true /*target_sp*/) {
// PlatformSP platform_sp = target_sp->GetPlatform();
if (true /*platform_sp*/) {
if (!ast_ctx->SearchPathOpts.SDKPath.empty() || TargetHasNoSDK()) {
swift::ClangImporterOptions &clang_importer_options =
GetClangImporterOptions();
if (!clang_importer_options.OverrideResourceDir.empty()) {
std::unique_ptr<swift::ModuleLoader> clang_importer_ap(
swift::ClangImporter::create(*m_ast_context_ap,
clang_importer_options));
if (clang_importer_ap) {
const bool isClang = true;
m_clang_importer =
(swift::ClangImporter *)clang_importer_ap.get();
m_ast_context_ap->addModuleLoader(std::move(clang_importer_ap),
isClang);
}
}
}
}
}
}
return m_clang_importer;
}
bool SwiftASTContext::AddModuleSearchPath(const char *path) {
VALID_OR_RETURN(false);
if (path && path[0]) {
swift::ASTContext *ast = GetASTContext();
std::string path_str(path);
bool add_search_path = true;
for (auto path : ast->SearchPathOpts.ImportSearchPaths) {
if (path == path_str) {
add_search_path = false;
break;
}
}
if (add_search_path) {
ast->SearchPathOpts.ImportSearchPaths.push_back(path);
return true;
}
}
return false;
}
bool SwiftASTContext::AddFrameworkSearchPath(const char *path) {
VALID_OR_RETURN(false);
if (path && path[0]) {
swift::ASTContext *ast = GetASTContext();
std::string path_str(path);
bool add_search_path = true;
for (const auto &swift_path : ast->SearchPathOpts.FrameworkSearchPaths) {
if (swift_path.Path == path_str) {
add_search_path = false;
break;
}
}
if (add_search_path) {
ast->SearchPathOpts.FrameworkSearchPaths.push_back({path, /*isSystem=*/false});
return true;
}
}
return false;
}
bool SwiftASTContext::AddClangArgument(const char *clang_arg, bool force) {
if (clang_arg && clang_arg[0]) {
swift::ClangImporterOptions &importer_options = GetClangImporterOptions();
bool add_hmap = true;
if (!force) {
for (std::string &arg : importer_options.ExtraArgs) {
if (!arg.compare(clang_arg)) {
add_hmap = false;
break;
}
}
}
if (add_hmap) {
importer_options.ExtraArgs.push_back(clang_arg);
return true;
}
}
return false;
}
bool SwiftASTContext::AddClangArgumentPair(const char *clang_arg_1,
const char *clang_arg_2) {
if (clang_arg_1 && clang_arg_2 && clang_arg_1[0] && clang_arg_2[0]) {
swift::ClangImporterOptions &importer_options = GetClangImporterOptions();
bool add_hmap = true;
for (ssize_t ai = 0, ae = importer_options.ExtraArgs.size() -
1; // -1 because we look at the next one too
ai < ae;
++ai) {
if (!importer_options.ExtraArgs[ai].compare(clang_arg_1) &&
!importer_options.ExtraArgs[ai + 1].compare(clang_arg_2)) {
add_hmap = false;
break;
}
}
if (add_hmap) {
importer_options.ExtraArgs.push_back(clang_arg_1);
importer_options.ExtraArgs.push_back(clang_arg_2);
return true;
}
}
return false;
}
size_t SwiftASTContext::GetNumModuleSearchPaths() const {
VALID_OR_RETURN(0);
if (m_ast_context_ap.get())
return m_ast_context_ap->SearchPathOpts.ImportSearchPaths.size();
return 0;
}
const char *SwiftASTContext::GetModuleSearchPathAtIndex(size_t idx) const {
VALID_OR_RETURN(nullptr);
if (m_ast_context_ap.get()) {
if (idx < m_ast_context_ap->SearchPathOpts.ImportSearchPaths.size())
return m_ast_context_ap->SearchPathOpts.ImportSearchPaths[idx].c_str();
}
return NULL;
}
size_t SwiftASTContext::GetNumFrameworkSearchPaths() const {
VALID_OR_RETURN(0);
if (m_ast_context_ap.get())
return m_ast_context_ap->SearchPathOpts.FrameworkSearchPaths.size();
return 0;
}
const char *SwiftASTContext::GetFrameworkSearchPathAtIndex(size_t idx) const {
VALID_OR_RETURN(nullptr);
if (m_ast_context_ap.get()) {
if (idx < m_ast_context_ap->SearchPathOpts.FrameworkSearchPaths.size())
return m_ast_context_ap->SearchPathOpts.FrameworkSearchPaths[idx].Path.c_str();
}
return NULL;
}
size_t SwiftASTContext::GetNumClangArguments() {
swift::ClangImporterOptions &importer_options = GetClangImporterOptions();
return importer_options.ExtraArgs.size();
}
const char *SwiftASTContext::GetClangArgumentAtIndex(size_t idx) {
swift::ClangImporterOptions &importer_options = GetClangImporterOptions();
if (idx < importer_options.ExtraArgs.size())
return importer_options.ExtraArgs[idx].c_str();
return NULL;
}
swift::ModuleDecl *
SwiftASTContext::GetCachedModule(const ConstString &module_name) {
VALID_OR_RETURN(nullptr);
SwiftModuleMap::const_iterator iter =
m_swift_module_cache.find(module_name.GetCString());
if (iter != m_swift_module_cache.end())
return iter->second;
return NULL;
}
swift::ModuleDecl *
SwiftASTContext::CreateModule(const ConstString &module_basename,
Status &error) {
VALID_OR_RETURN(nullptr);
if (module_basename) {
swift::ModuleDecl *module = GetCachedModule(module_basename);
if (module) {
error.SetErrorStringWithFormat("module already exists for '%s'",
module_basename.GetCString());
return NULL;
}
swift::ASTContext *ast = GetASTContext();
if (ast) {
swift::Identifier module_id(
ast->getIdentifier(module_basename.GetCString()));
module = swift::ModuleDecl::create(module_id, *ast);
if (module) {
m_swift_module_cache[module_basename.GetCString()] = module;
return module;
} else {
error.SetErrorStringWithFormat("invalid swift AST (NULL)");
}
} else {
error.SetErrorStringWithFormat("invalid swift AST (NULL)");
}
} else {
error.SetErrorStringWithFormat("invalid module name (empty)");
}
return NULL;
}
void SwiftASTContext::CacheModule(swift::ModuleDecl *module) {
VALID_OR_RETURN_VOID();
if (!module)
return;
auto ID = module->getName().get();
if (nullptr == ID || 0 == ID[0])
return;
if (m_swift_module_cache.find(ID) != m_swift_module_cache.end())
return;
m_swift_module_cache.insert({ID, module});
}
swift::ModuleDecl *
SwiftASTContext::GetModule(const ConstString &module_basename, Status &error) {
VALID_OR_RETURN(nullptr);
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
if (log)
log->Printf("((SwiftASTContext*)%p)->GetModule('%s')", this,
module_basename.AsCString("<no name>"));
if (module_basename) {
swift::ModuleDecl *module = GetCachedModule(module_basename);
if (module)
return module;
if (swift::ASTContext *ast = GetASTContext()) {
typedef std::pair<swift::Identifier, swift::SourceLoc> ModuleNameSpec;
llvm::StringRef module_basename_sref(module_basename.GetCString());
ModuleNameSpec name_pair(ast->getIdentifier(module_basename_sref),
swift::SourceLoc());
if (HasFatalErrors()) {
error.SetErrorStringWithFormat("failed to get module '%s' from AST "
"context:\nAST context is in a fatal "
"error state",
module_basename.GetCString());
printf("error in SwiftASTContext::GetModule(%s): AST context is in a "
"fatal error stat",
module_basename.GetCString());
return nullptr;
}
ClearDiagnostics();
module = ast->getModuleByName(module_basename_sref);
if (HasErrors()) {
DiagnosticManager diagnostic_manager;
PrintDiagnostics(diagnostic_manager);
error.SetErrorStringWithFormat(
"failed to get module '%s' from AST context:\n%s",
module_basename.GetCString(),
diagnostic_manager.GetString().data());
#ifdef LLDB_CONFIGURATION_DEBUG
printf("error in SwiftASTContext::GetModule(%s): '%s'",
module_basename.GetCString(),
diagnostic_manager.GetString().data());
#endif
if (log)
log->Printf("((SwiftASTContext*)%p)->GetModule('%s') -- error: %s",
this, module_basename.GetCString(),
diagnostic_manager.GetString().data());
} else if (module) {
if (log)
log->Printf("((SwiftASTContext*)%p)->GetModule('%s') -- found %s",
this, module_basename.GetCString(),
module->getName().str().str().c_str());
m_swift_module_cache[module_basename.GetCString()] = module;
return module;
} else {
if (log)
log->Printf(
"((SwiftASTContext*)%p)->GetModule('%s') -- failed with no error",
this, module_basename.GetCString());
error.SetErrorStringWithFormat(
"failed to get module '%s' from AST context",
module_basename.GetCString());
}
} else {
if (log)
log->Printf(
"((SwiftASTContext*)%p)->GetModule('%s') -- invalid ASTContext",
this, module_basename.GetCString());
error.SetErrorString("invalid swift::ASTContext");
}
} else {
if (log)
log->Printf(
"((SwiftASTContext*)%p)->GetModule('%s') -- empty module name", this,
module_basename.GetCString());
error.SetErrorString("invalid module name (empty)");
}
return NULL;
}
swift::ModuleDecl *SwiftASTContext::GetModule(const FileSpec &module_spec,
Status &error) {
VALID_OR_RETURN(nullptr);
ConstString module_basename(module_spec.GetFileNameStrippingExtension());
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
if (log)
log->Printf("((SwiftASTContext*)%p)->GetModule((FileSpec)'%s')", this,
module_spec.GetPath().c_str());
if (module_basename) {
SwiftModuleMap::const_iterator iter =
m_swift_module_cache.find(module_basename.GetCString());
if (iter != m_swift_module_cache.end())
return iter->second;
if (module_spec.Exists()) {
swift::ASTContext *ast = GetASTContext();
if (!GetClangImporter()) {
if (log)
log->Printf("((SwiftASTContext*)%p)->GetModule((FileSpec)'%s') -- no "
"ClangImporter so giving up",
this, module_spec.GetPath().c_str());
error.SetErrorStringWithFormat("couldn't get a ClangImporter");
return nullptr;
}
std::string module_directory(module_spec.GetDirectory().GetCString());
bool add_search_path = true;
for (auto path : ast->SearchPathOpts.ImportSearchPaths) {
if (path == module_directory) {
add_search_path = false;
break;
}
}
// Add the search path if needed so we can find the module by basename
if (add_search_path)
ast->SearchPathOpts.ImportSearchPaths.push_back(
std::move(module_directory));
typedef std::pair<swift::Identifier, swift::SourceLoc> ModuleNameSpec;
llvm::StringRef module_basename_sref(module_basename.GetCString());
ModuleNameSpec name_pair(ast->getIdentifier(module_basename_sref),
swift::SourceLoc());
swift::ModuleDecl *module =
ast->getModule(llvm::ArrayRef<ModuleNameSpec>(name_pair));
if (module) {
if (log)
log->Printf(
"((SwiftASTContext*)%p)->GetModule((FileSpec)'%s') -- found %s",
this, module_spec.GetPath().c_str(),
module->getName().str().str().c_str());
m_swift_module_cache[module_basename.GetCString()] = module;
return module;
} else {
if (log)
log->Printf("((SwiftASTContext*)%p)->GetModule((FileSpec)'%s') -- "
"couldn't get from AST context",
this, module_spec.GetPath().c_str());
error.SetErrorStringWithFormat(
"failed to get module '%s' from AST context",
module_basename.GetCString());
}
} else {
if (log)
log->Printf("((SwiftASTContext*)%p)->GetModule((FileSpec)'%s') -- "
"doesn't exist",
this, module_spec.GetPath().c_str());
error.SetErrorStringWithFormat("module '%s' doesn't exist",
module_spec.GetPath().c_str());
}
} else {
if (log)
log->Printf(
"((SwiftASTContext*)%p)->GetModule((FileSpec)'%s') -- no basename",
this, module_spec.GetPath().c_str());
error.SetErrorStringWithFormat("no module basename in '%s'",
module_spec.GetPath().c_str());
}
return NULL;
}
swift::ModuleDecl *
SwiftASTContext::FindAndLoadModule(const ConstString &module_basename,
Process &process, Status &error) {
VALID_OR_RETURN(nullptr);
swift::ModuleDecl *swift_module = GetModule(module_basename, error);
if (!swift_module)
return nullptr;
LoadModule(swift_module, process, error);
return swift_module;
}
swift::ModuleDecl *
SwiftASTContext::FindAndLoadModule(const FileSpec &module_spec,
Process &process, Status &error) {
VALID_OR_RETURN(nullptr);
swift::ModuleDecl *swift_module = GetModule(module_spec, error);
if (!swift_module)
return nullptr;
LoadModule(swift_module, process, error);
return swift_module;
}
bool SwiftASTContext::LoadOneImage(Process &process, FileSpec &link_lib_spec,
Status &error) {
VALID_OR_RETURN(false);
error.Clear();
PlatformSP platform_sp = process.GetTarget().GetPlatform();
if (platform_sp)
return platform_sp->LoadImage(&process, FileSpec(), link_lib_spec, error) !=
LLDB_INVALID_IMAGE_TOKEN;
else
return false;
}
static void
GetLibrarySearchPaths(std::vector<std::string> &paths,
const swift::SearchPathOptions &search_path_opts) {
paths.clear();
paths.resize(search_path_opts.LibrarySearchPaths.size() + 1);
std::copy(search_path_opts.LibrarySearchPaths.begin(),
search_path_opts.LibrarySearchPaths.end(), paths.begin());
paths.push_back(search_path_opts.RuntimeLibraryPath);
}
void SwiftASTContext::LoadModule(swift::ModuleDecl *swift_module,
Process &process, Status &error) {
VALID_OR_RETURN_VOID();
Status current_error;
auto addLinkLibrary = [&](swift::LinkLibrary link_lib) {
Status load_image_error;
StreamString all_dlopen_errors;
const char *library_name = link_lib.getName().data();
if (library_name == NULL || library_name[0] == '\0') {
error.SetErrorString("Empty library name passed to addLinkLibrary");
return;
}
SwiftLanguageRuntime *runtime = process.GetSwiftLanguageRuntime();
if (runtime && runtime->IsInLibraryNegativeCache(library_name))
return;
swift::LibraryKind library_kind = link_lib.getKind();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TYPES));
if (log)
log->Printf("\nLoading link library \"%s\" of kind: %d.", library_name,
library_kind);
switch (library_kind) {
case swift::LibraryKind::Framework: {
// First make sure the library isn't already loaded. Since this is a
// framework, we make sure the file name and the framework name are the
// same, and that we are contained in FileName.framework with no other
// intervening frameworks. We can get more restrictive if this gives
// false positives.
ConstString library_cstr(library_name);
std::string framework_name(library_name);
framework_name.append(".framework");
// Lookup the module by file basename and make sure that basename has
// "<basename>.framework" in the path.
ModuleSpec module_spec;
module_spec.GetFileSpec().GetFilename() = library_cstr;
lldb_private::ModuleList matching_module_list;
bool module_already_loaded = false;
if (process.GetTarget().GetImages().FindModules(module_spec,
matching_module_list)) {
matching_module_list.ForEach(
[&module_already_loaded, &module_spec,
&framework_name](const ModuleSP &module_sp) -> bool {
module_already_loaded = module_spec.GetFileSpec().GetPath().find(
framework_name) != std::string::npos;
return module_already_loaded ==
false; // Keep iterating if we didn't find the right module
});
}
// If we already have this library loaded, don't try and load it again.
if (module_already_loaded) {
if (log)
log->Printf("Skipping load of %s as it is already loaded.",
framework_name.c_str());
return;
}
for (auto module : process.GetTarget().GetImages().Modules()) {
FileSpec module_file = module->GetFileSpec();
if (module_file.GetFilename() == library_cstr) {
std::string module_path = module_file.GetPath();
size_t framework_offset = module_path.rfind(framework_name);
if (framework_offset != std::string::npos) {
// The Framework is already loaded, so we don't need to try to load
// it again.
if (log)
log->Printf("Skipping load of %s as it is already loaded.",
framework_name.c_str());
return;
}
}
}
std::string framework_path("@rpath/");
framework_path.append(library_name);
framework_path.append(".framework/");
framework_path.append(library_name);
FileSpec framework_spec(framework_path.c_str(), false);
if (LoadOneImage(process, framework_spec, load_image_error)) {
if (log)
log->Printf("Found framework at: %s.", framework_path.c_str());
return;
} else
all_dlopen_errors.Printf("Looking for \"%s\", error: %s\n",
framework_path.c_str(),
load_image_error.AsCString());
// And then in the various framework search paths.
std::unordered_set<std::string> seen_paths;
for (const auto &framework_search_dir :
swift_module->getASTContext().SearchPathOpts.FrameworkSearchPaths) {
// The framework search dir as it comes from the AST context often has
// duplicate entries, don't try to load along the same path twice.
std::pair<std::unordered_set<std::string>::iterator, bool>
insert_result = seen_paths.insert(framework_search_dir.Path);
if (!insert_result.second)
continue;
framework_path = framework_search_dir.Path;
framework_path.append("/");
framework_path.append(library_name);
framework_path.append(".framework/");
framework_path.append(library_name);
framework_spec.SetFile(framework_path.c_str(), false);
if (LoadOneImage(process, framework_spec, load_image_error)) {
if (log)
log->Printf("Found framework at: %s.", framework_path.c_str());
return;
} else
all_dlopen_errors.Printf("Looking for \"%s\"\n, error: %s\n",
framework_path.c_str(),
load_image_error.AsCString());
}
// Maybe we were told to add a link library that exists in the system. I
// tried just specifying Foo.framework/Foo and letting the system search
// figure that out, but if DYLD_FRAMEWORK_FALLBACK_PATH is set
// (e.g. in Xcode's test scheme) then these aren't found. So for now I
// dial them in explicitly:
std::string system_path("/System/Library/Frameworks/");
system_path.append(library_name);
system_path.append(".framework/");
system_path.append(library_name);
framework_spec.SetFile(system_path.c_str(), true);
if (LoadOneImage(process, framework_spec, load_image_error))
return;
else
all_dlopen_errors.Printf("Looking for \"%s\"\n, error: %s\n",
framework_path.c_str(),
load_image_error.AsCString());
} break;
case swift::LibraryKind::Library: {
std::vector<std::string> search_paths;
GetLibrarySearchPaths(search_paths,
swift_module->getASTContext().SearchPathOpts);
if (LoadLibraryUsingPaths(process, library_name, search_paths, true,
all_dlopen_errors))
return;
} break;
}
// If we get here, we aren't going to find this image, so add it to a
// negative cache:
if (runtime)
runtime->AddToLibraryNegativeCache(library_name);
current_error.SetErrorStringWithFormat(
"Failed to load linked library %s of module %s - errors:\n%s\n",
library_name, swift_module->getName().str().str().c_str(),
all_dlopen_errors.GetData());
};
swift_module->forAllVisibleModules({},
true, // includePrivateTopLevel
[&](swift::ModuleDecl::ImportedModule import) {
import.second->collectLinkLibraries(
addLinkLibrary);
});
error = current_error;
}
bool SwiftASTContext::LoadLibraryUsingPaths(
Process &process, llvm::StringRef library_name,
std::vector<std::string> &search_paths, bool check_rpath,
StreamString &all_dlopen_errors) {
VALID_OR_RETURN(false);
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TYPES));
SwiftLanguageRuntime *runtime = process.GetSwiftLanguageRuntime();
if (!runtime) {
all_dlopen_errors.PutCString(
"Can't load Swift libraries without a language runtime.");
return false;
}
if (ConstString::Equals(runtime->GetStandardLibraryBaseName(),
ConstString(library_name))) {
// Never dlopen the standard library. Some binaries statically link to the
// Swift standard library and dlopening it here will cause ObjC runtime
// conflicts.
// If you want to run Swift expressions you have to arrange to load the
// Swift standard library by hand before doing so.
if (log)
log->Printf("Skipping swift standard library \"%s\" - we don't hand load "
"that one.",
runtime->GetStandardLibraryBaseName().AsCString());
return true;
}
PlatformSP platform_sp(process.GetTarget().GetPlatform());
std::string library_fullname;
if (platform_sp) {
library_fullname =
platform_sp->GetFullNameForDylib(ConstString(library_name)).AsCString();
} else // This is the old way, and we shouldn't use it except on Mac OS
{
#ifdef __APPLE__
library_fullname = "lib";
library_fullname.append(library_name);
library_fullname.append(".dylib");
#else
return false;
#endif
}
ModuleSpec module_spec;
module_spec.GetFileSpec().GetFilename().SetCString(library_fullname.c_str());
lldb_private::ModuleList matching_module_list;
if (process.GetTarget().GetImages().FindModules(module_spec,
matching_module_list) > 0) {
if (log)
log->Printf("Skipping module %s as it is already loaded.",
library_fullname.c_str());
return true;
}
FileSpec library_spec;
std::string library_path;
std::unordered_set<std::string> seen_paths;
Status load_image_error;
for (const std::string &library_search_dir : search_paths) {
// The library search dir as it comes from the AST context often has
// duplicate entries, don't try to load along the same path twice.
std::pair<std::unordered_set<std::string>::iterator, bool> insert_result =
seen_paths.insert(library_search_dir);
if (!insert_result.second)
continue;
library_path = library_search_dir;
library_path.append("/");
library_path.append(library_fullname);
library_spec.SetFile(library_path.c_str(), false);
if (LoadOneImage(process, library_spec, load_image_error)) {
if (log)
log->Printf("Found library at: %s.", library_path.c_str());
return true;
} else
all_dlopen_errors.Printf("Looking for \"%s\"\n, error: %s\n",
library_path.c_str(),
load_image_error.AsCString());
}
if (check_rpath) {
// Let our RPATH help us out when finding the right library
library_path = "@rpath/";
library_path += library_fullname;
FileSpec link_lib_spec(library_path.c_str(), false);
if (LoadOneImage(process, link_lib_spec, load_image_error)) {
if (log)
log->Printf("Found library at: %s.", library_path.c_str());
return true;
} else
all_dlopen_errors.Printf("Looking for \"%s\", error: %s\n",
library_path.c_str(),
load_image_error.AsCString());
}
return false;
}
void SwiftASTContext::LoadExtraDylibs(Process &process, Status &error) {
VALID_OR_RETURN_VOID();
error.Clear();
swift::IRGenOptions &irgen_options = GetIRGenOptions();
for (const swift::LinkLibrary &link_lib : irgen_options.LinkLibraries) {
// We don't have to do frameworks here, they actually record their link
// libraries properly.
if (link_lib.getKind() == swift::LibraryKind::Library) {
const char *library_name = link_lib.getName().data();
StreamString errors;
std::vector<std::string> search_paths;
GetLibrarySearchPaths(search_paths,
m_compiler_invocation_ap->getSearchPathOptions());
bool success = LoadLibraryUsingPaths(process, library_name, search_paths,
false, errors);
if (!success) {
error.SetErrorString(errors.GetData());
}
}
}
}
bool SwiftASTContext::RegisterSectionModules(
Module &module, std::vector<std::string> &module_names) {
VALID_OR_RETURN(false);
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
swift::SerializedModuleLoader *sml = GetSerializeModuleLoader();
if (sml) {
SectionList *section_list = module.GetSectionList();
if (section_list) {
SectionSP section_sp(
section_list->FindSectionByType(eSectionTypeSwiftModules, true));
if (section_sp) {
DataExtractor section_data;
if (section_sp->GetSectionData(section_data)) {
llvm::StringRef section_data_ref(
(const char *)section_data.GetDataStart(),
section_data.GetByteSize());
llvm::SmallVector<std::string, 4> llvm_modules;
if (swift::parseASTSection(sml, section_data_ref, llvm_modules)) {
for (auto module_name : llvm_modules)
module_names.push_back(module_name);
return true;
}
}
} else {
if (m_ast_file_data_map.find(&module) != m_ast_file_data_map.end())
return true;
SymbolVendor *sym_vendor = module.GetSymbolVendor();
if (sym_vendor) {
// Grab all the AST blobs from the symbol vendor.
auto ast_file_datas = sym_vendor->GetASTData(eLanguageTypeSwift);
if (log)
log->Printf("SwiftASTContext::%s() retrieved %zu AST Data blobs "
"from the symbol vendor.",
__FUNCTION__, ast_file_datas.size());
// Add each of the AST blobs to the vector of AST blobs for the
// module.
auto &ast_vector = GetASTVectorForModule(&module);
ast_vector.insert(ast_vector.end(), ast_file_datas.begin(),
ast_file_datas.end());
// Retrieve the module names from the AST blobs retrieved from the
// symbol vendor.
size_t parse_fail_count = 0;
size_t ast_number = 0;
for (auto ast_file_data_sp : ast_file_datas) {
// Parse the AST section info from the AST blob.
++ast_number;
llvm::StringRef section_data_ref(
(const char *)ast_file_data_sp->GetBytes(),
ast_file_data_sp->GetByteSize());
llvm::SmallVector<std::string, 4> llvm_modules;
if (swift::parseASTSection(sml, section_data_ref, llvm_modules)) {
// Collect the LLVM module names referenced by the AST.
for (auto module_name : llvm_modules)
module_names.push_back(module_name);
if (log)
log->Printf("SwiftASTContext::%s() - parsed %zu llvm modules "
"from Swift AST section %zu of %zu.",
__FUNCTION__, llvm_modules.size(), ast_number,
ast_file_datas.size());
} else {
// Keep track of the fact that we failed to parse the AST
// section info.
if (log)
log->Printf("SwiftASTContext::%s() - failed to parse AST "
"section %zu of %zu.",
__FUNCTION__, ast_number, ast_file_datas.size());
++parse_fail_count;
}
}
if (!ast_file_datas.empty() && (parse_fail_count == 0)) {
// We found AST data entries and we successfully parsed all of
// them.
return true;
}
}
}
}
}
return false;
}
void SwiftASTContext::ValidateSectionModules(
Module &module, const std::vector<std::string> &module_names) {
VALID_OR_RETURN_VOID();
Status error;
for (const std::string &module_name : module_names)
if (!GetModule(ConstString(module_name.c_str()), error))
module.ReportWarning("unable to load swift module '%s' (%s)",
module_name.c_str(), error.AsCString());
}
swift::Identifier SwiftASTContext::GetIdentifier(const char *name) {
VALID_OR_RETURN(swift::Identifier());
return GetASTContext()->getIdentifier(llvm::StringRef(name));
}
swift::Identifier SwiftASTContext::GetIdentifier(const llvm::StringRef &name) {
VALID_OR_RETURN(swift::Identifier());
return GetASTContext()->getIdentifier(name);
}
ConstString SwiftASTContext::GetMangledTypeName(swift::TypeBase *type_base) {
VALID_OR_RETURN(ConstString());
auto iter = m_type_to_mangled_name_map.find(type_base),
end = m_type_to_mangled_name_map.end();
if (iter != end)
return ConstString(iter->second);
swift::Type swift_type(type_base);
bool has_archetypes = swift_type->hasArchetype();
if (!has_archetypes) {
swift::Mangle::ASTMangler mangler(true);
std::string s = mangler.mangleTypeForDebugger(swift_type, nullptr, nullptr);
if (!s.empty()) {
ConstString mangled_cs(s.c_str());
CacheDemangledType(mangled_cs.AsCString(), type_base);
return mangled_cs;
}
}
return ConstString();
}
void SwiftASTContext::CacheDemangledType(const char *name,
swift::TypeBase *found_type) {
VALID_OR_RETURN_VOID();
m_type_to_mangled_name_map.insert(std::make_pair(found_type, name));
m_mangled_name_to_type_map.insert(std::make_pair(name, found_type));
}
void SwiftASTContext::CacheDemangledTypeFailure(const char *name) {
VALID_OR_RETURN_VOID();
m_negative_type_cache.Insert(name);
}
CompilerType
SwiftASTContext::GetTypeFromMangledTypename(const char *mangled_typename,
Status &error) {
VALID_OR_RETURN(CompilerType());
if (mangled_typename
&& SwiftLanguageRuntime::IsSwiftMangledName(mangled_typename)) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
if (log)
log->Printf("((SwiftASTContext*)%p)->GetTypeFromMangledTypename('%s')",
this, mangled_typename);
swift::ASTContext *ast_ctx = GetASTContext();
if (!ast_ctx) {
if (log)
log->Printf("((SwiftASTContext*)%p)->GetTypeFromMangledTypename('%s') "
"-- null Swift AST Context",
this, mangled_typename);
error.SetErrorString("null Swift AST Context");
return CompilerType();
}
error.Clear();
// If we were to crash doing this, remember what type caused it
llvm::PrettyStackTraceFormat PST("error finding type for %s",
mangled_typename);
ConstString mangled_name(mangled_typename);
swift::TypeBase *found_type =
m_mangled_name_to_type_map.lookup(mangled_name.GetCString());
if (found_type) {
if (log)
log->Printf("((SwiftASTContext*)%p)->GetTypeFromMangledTypename('%s') "
"-- found in the positive cache",
this, mangled_typename);
return CompilerType(ast_ctx, found_type);
}
if (m_negative_type_cache.Lookup(mangled_name.GetCString())) {
if (log)
log->Printf("((SwiftASTContext*)%p)->GetTypeFromMangledTypename('%s') "
"-- found in the negative cache",
this, mangled_typename);
return CompilerType();
}
if (log)
log->Printf("((SwiftASTContext*)%p)->GetTypeFromMangledTypename('%s') -- "
"not cached, searching",
this, mangled_typename);
std::string swift_error;
found_type = swift::ide::getTypeFromMangledSymbolname(
*ast_ctx, mangled_typename, swift_error)
.getPointer();
if (found_type) {
// If we have an inout type at the top level, turn it into an lvalue type.
// Function parameters that are inout are treated the same as mutable vars
// here.
if (auto *inout_type = found_type->getAs<swift::InOutType>()) {
found_type = swift::LValueType::get(inout_type->getObjectType());
}
CacheDemangledType(mangled_name.GetCString(), found_type);
CompilerType result_type(ast_ctx, found_type);
if (log)
log->Printf("((SwiftASTContext*)%p)->GetTypeFromMangledTypename('%s') "
"-- found %s",
this, mangled_typename,
result_type.GetTypeName().GetCString());
return result_type;
} else {
if (log)
log->Printf("((SwiftASTContext*)%p)->GetTypeFromMangledTypename('%s') "
"-- error: %s",
this, mangled_typename, swift_error.c_str());
error.SetErrorStringWithFormat("type for typename '%s' was not found",
mangled_typename);
CacheDemangledTypeFailure(mangled_name.GetCString());
return CompilerType();
}
}
error.SetErrorStringWithFormat("typename '%s' is not a valid Swift mangled "
"typename, it should begin with _T",
mangled_typename);
return CompilerType();
}
CompilerType SwiftASTContext::GetVoidFunctionType() {
VALID_OR_RETURN(CompilerType());
if (!m_void_function_type) {
swift::ASTContext *ast = GetASTContext();
swift::Type empty_tuple_type(swift::TupleType::getEmpty(*ast));
m_void_function_type = CompilerType(
ast, swift::FunctionType::get(empty_tuple_type, empty_tuple_type));
}
return m_void_function_type;
}
static CompilerType ValueDeclToType(swift::ValueDecl *decl,
swift::ASTContext *ast) {
if (decl) {
switch (decl->getKind()) {
case swift::DeclKind::TypeAlias: {
swift::TypeAliasDecl *alias_decl = swift::cast<swift::TypeAliasDecl>(decl);
if (alias_decl->hasInterfaceType()) {
swift::Type swift_type = alias_decl->getDeclaredInterfaceType();
return CompilerType(ast, swift_type.getPointer());
}
break;
}
case swift::DeclKind::Enum:
case swift::DeclKind::Struct:
case swift::DeclKind::Protocol:
case swift::DeclKind::Class: {
swift::NominalTypeDecl *nominal_decl = swift::cast<swift::NominalTypeDecl>(decl);
if (nominal_decl->hasInterfaceType()) {
swift::Type swift_type = nominal_decl->getDeclaredType();
return CompilerType(ast, swift_type.getPointer());
}
} break;
default:
break;
}
}
return CompilerType();
}
CompilerType SwiftASTContext::FindQualifiedType(const char *qualified_name) {
VALID_OR_RETURN(CompilerType());
if (qualified_name && qualified_name[0]) {
const char *dot_pos = strchr(qualified_name, '.');
if (dot_pos) {
ConstString module_name(qualified_name, dot_pos - qualified_name);
swift::ModuleDecl *swift_module = GetCachedModule(module_name);
if (swift_module) {
swift::ModuleDecl::AccessPathTy access_path;
llvm::SmallVector<swift::ValueDecl *, 4> decls;
const char *module_type_name = dot_pos + 1;
swift_module->lookupValue(access_path, GetIdentifier(module_type_name),
swift::NLKind::UnqualifiedLookup, decls);
for (auto decl : decls) {
CompilerType type = ValueDeclToType(decl, GetASTContext());
if (type)
return type;
}
}
}
}
return CompilerType();
}
static CompilerType DeclToType(swift::Decl *decl, swift::ASTContext *ast) {
if (swift::ValueDecl *value_decl =
swift::dyn_cast_or_null<swift::ValueDecl>(decl))
return ValueDeclToType(value_decl, ast);
return CompilerType();
}
static SwiftASTContext::TypeOrDecl DeclToTypeOrDecl(swift::ASTContext *ast,
swift::Decl *decl) {
if (decl) {
switch (decl->getKind()) {
case swift::DeclKind::Import:
case swift::DeclKind::Extension:
case swift::DeclKind::PatternBinding:
case swift::DeclKind::TopLevelCode:
case swift::DeclKind::GenericTypeParam:
case swift::DeclKind::AssociatedType:
case swift::DeclKind::EnumElement:
case swift::DeclKind::EnumCase:
case swift::DeclKind::IfConfig:
case swift::DeclKind::Param:
case swift::DeclKind::Module:
case swift::DeclKind::MissingMember:
break;
case swift::DeclKind::InfixOperator:
case swift::DeclKind::PrefixOperator:
case swift::DeclKind::PostfixOperator:
case swift::DeclKind::PrecedenceGroup:
return decl;
case swift::DeclKind::TypeAlias: {
swift::TypeAliasDecl *alias_decl =
swift::cast<swift::TypeAliasDecl>(decl);
if (alias_decl->hasInterfaceType()) {
swift::Type swift_type = alias_decl->getDeclaredInterfaceType();
return CompilerType(ast, swift_type.getPointer());
}
} break;
case swift::DeclKind::Enum:
case swift::DeclKind::Struct:
case swift::DeclKind::Class:
case swift::DeclKind::Protocol: {
swift::NominalTypeDecl *nominal_decl =
swift::cast<swift::NominalTypeDecl>(decl);
if (nominal_decl->hasInterfaceType()) {
swift::Type swift_type = nominal_decl->getDeclaredType();
return CompilerType(ast, swift_type.getPointer());
}
} break;
case swift::DeclKind::Func:
case swift::DeclKind::Var:
return decl;
case swift::DeclKind::Subscript:
case swift::DeclKind::Constructor:
case swift::DeclKind::Destructor:
break;
}
}
return CompilerType();
}
size_t SwiftASTContext::FindContainedType(llvm::StringRef name,
CompilerType container_type,
std::set<CompilerType> &results,
bool append) {
VALID_OR_RETURN(0);
if (!append)
results.clear();
size_t size_before = results.size();
TypesOrDecls types_or_decl_results;
FindContainedTypeOrDecl(name, container_type, types_or_decl_results);
for (const auto &result : types_or_decl_results) {
CompilerType type = result.Apply<CompilerType>(
[](CompilerType type) -> CompilerType { return type; },
[this](swift::Decl *decl) -> CompilerType {
return DeclToType(decl, GetASTContext());
});
results.emplace(type);
}
return results.size() - size_before;
}
size_t
SwiftASTContext::FindContainedTypeOrDecl(llvm::StringRef name,
TypeOrDecl container_type_or_decl,
TypesOrDecls &results, bool append) {
VALID_OR_RETURN(0);
if (!append)
results.clear();
size_t size_before = results.size();
CompilerType container_type = container_type_or_decl.Apply<CompilerType>(
[](CompilerType type) -> CompilerType { return type; },
[this](swift::Decl *decl) -> CompilerType {
return DeclToType(decl, GetASTContext());
});
if (false == name.empty() &&
llvm::dyn_cast_or_null<SwiftASTContext>(container_type.GetTypeSystem())) {
swift::Type swift_type(GetSwiftType(container_type));
if (!swift_type)
return 0;
swift::CanType swift_can_type(swift_type->getCanonicalType());
swift::NominalType *nominal_type =
swift_can_type->getAs<swift::NominalType>();
if (!nominal_type)
return 0;
swift::NominalTypeDecl *nominal_decl = nominal_type->getDecl();
llvm::ArrayRef<swift::ValueDecl *> decls =
nominal_decl->lookupDirect(
swift::DeclName(m_ast_context_ap->getIdentifier(name)));
for (auto decl : decls)
results.emplace(DeclToTypeOrDecl(GetASTContext(), decl));
}
return results.size() - size_before;
}
CompilerType SwiftASTContext::FindType(const char *name,
swift::ModuleDecl *swift_module) {
VALID_OR_RETURN(CompilerType());
std::set<CompilerType> search_results;
FindTypes(name, swift_module, search_results, false);
if (search_results.empty())
return CompilerType();
else
return *search_results.begin();
}
llvm::Optional<SwiftASTContext::TypeOrDecl>
SwiftASTContext::FindTypeOrDecl(const char *name,
swift::ModuleDecl *swift_module) {
VALID_OR_RETURN(llvm::Optional<SwiftASTContext::TypeOrDecl>());
TypesOrDecls search_results;
FindTypesOrDecls(name, swift_module, search_results, false);
if (search_results.empty())
return llvm::Optional<SwiftASTContext::TypeOrDecl>();
else
return *search_results.begin();
}
size_t SwiftASTContext::FindTypes(const char *name,
swift::ModuleDecl *swift_module,
std::set<CompilerType> &results,
bool append) {
VALID_OR_RETURN(0);
if (!append)
results.clear();
size_t before = results.size();
TypesOrDecls types_or_decls_results;
FindTypesOrDecls(name, swift_module, types_or_decls_results);
for (const auto &result : types_or_decls_results) {
CompilerType type = result.Apply<CompilerType>(
[](CompilerType type) -> CompilerType { return type; },
[this](swift::Decl *decl) -> CompilerType {
if (swift::ValueDecl *value_decl =
swift::dyn_cast_or_null<swift::ValueDecl>(decl)) {
if (value_decl->hasInterfaceType()) {
swift::Type swift_type = value_decl->getInterfaceType();
swift::MetatypeType *meta_type =
swift_type->getAs<swift::MetatypeType>();
swift::ASTContext *ast = GetASTContext();
if (meta_type)
return CompilerType(ast,
meta_type->getInstanceType().getPointer());
else
return CompilerType(ast, swift_type.getPointer());
}
}
return CompilerType();
});
results.emplace(type);
}
return results.size() - before;
}
size_t SwiftASTContext::FindTypesOrDecls(const char *name,
swift::ModuleDecl *swift_module,
TypesOrDecls &results, bool append) {
VALID_OR_RETURN(0);
if (!append)
results.clear();
size_t before = results.size();
if (name && name[0] && swift_module) {
swift::ModuleDecl::AccessPathTy access_path;
llvm::SmallVector<swift::ValueDecl *, 4> value_decls;
swift::Identifier identifier(GetIdentifier(name));
if (strchr(name, '.'))
swift_module->lookupValue(access_path, identifier,
swift::NLKind::QualifiedLookup, value_decls);
else
swift_module->lookupValue(access_path, identifier,
swift::NLKind::UnqualifiedLookup, value_decls);
if (identifier.isOperator()) {
swift::OperatorDecl *op_decl =
swift_module->lookupPrefixOperator(identifier);
if (op_decl)
results.emplace(DeclToTypeOrDecl(GetASTContext(), op_decl));
if ((op_decl = swift_module->lookupInfixOperator(identifier)))
results.emplace(DeclToTypeOrDecl(GetASTContext(), op_decl));
if ((op_decl = swift_module->lookupPostfixOperator(identifier)))
results.emplace(DeclToTypeOrDecl(GetASTContext(), op_decl));
}
if (swift::PrecedenceGroupDecl *pg_decl =
swift_module->lookupPrecedenceGroup(identifier))
results.emplace(DeclToTypeOrDecl(GetASTContext(), pg_decl));
for (auto decl : value_decls)
results.emplace(DeclToTypeOrDecl(GetASTContext(), decl));
}
return results.size() - before;
}
size_t SwiftASTContext::FindType(const char *name,
std::set<CompilerType> &results, bool append) {
VALID_OR_RETURN(0);
if (!append)
results.clear();
auto iter = m_swift_module_cache.begin(), end = m_swift_module_cache.end();
size_t count = 0;
std::function<void(swift::ModuleDecl *)> lookup_func =
[this, name, &results, &count](swift::ModuleDecl *module) -> void {
CompilerType candidate(this->FindType(name, module));
if (candidate) {
++count;
results.insert(candidate);
}
};
for (; iter != end; iter++)
lookup_func(iter->second);
if (m_scratch_module)
lookup_func(m_scratch_module);
return count;
}
CompilerType SwiftASTContext::FindFirstType(const char *name,
const ConstString &module_name) {
VALID_OR_RETURN(CompilerType());
if (name && name[0]) {
if (module_name) {
return FindType(name, GetCachedModule(module_name));
} else {
std::set<CompilerType> types;
FindType(name, types);
if (!types.empty())
return *types.begin();
}
}
return CompilerType();
}
CompilerType SwiftASTContext::ImportType(CompilerType &type, Status &error) {
VALID_OR_RETURN(CompilerType());
if (m_ast_context_ap.get() == NULL)
return CompilerType();
SwiftASTContext *swift_ast_ctx =
llvm::dyn_cast_or_null<SwiftASTContext>(type.GetTypeSystem());
if (swift_ast_ctx == nullptr) {
error.SetErrorString("Can't import clang type into a Swift ASTContext.");
return CompilerType();
} else if (swift_ast_ctx == this) {
// This is the same AST context, so the type is already imported...
return type;
}
// For now we're going to do this all using mangled names. If we find that is
// too slow, we can use the TypeBase * in the CompilerType to match this to
// the version of the type we got from the mangled name in the original
// swift::ASTContext.
ConstString mangled_name(type.GetMangledTypeName());
if (mangled_name) {
swift::TypeBase *our_type_base =
m_mangled_name_to_type_map.lookup(mangled_name.GetCString());
if (our_type_base)
return CompilerType(m_ast_context_ap.get(), our_type_base);
else {
Status error;
CompilerType our_type(
GetTypeFromMangledTypename(mangled_name.GetCString(), error));
if (error.Success())
return our_type;
}
}
return CompilerType();
}
swift::IRGenDebugInfoKind SwiftASTContext::GetGenerateDebugInfo() {
return GetIRGenOptions().DebugInfoKind;
}
swift::PrintOptions SwiftASTContext::GetUserVisibleTypePrintingOptions(
bool print_help_if_available) {
swift::PrintOptions print_options;
print_options.SynthesizeSugarOnTypes = true;
print_options.VarInitializers = true;
print_options.TypeDefinitions = true;
print_options.PrintGetSetOnRWProperties = true;
print_options.SkipImplicit = false;
print_options.PreferTypeRepr = true;
print_options.FunctionDefinitions = true;
print_options.FullyQualifiedTypesIfAmbiguous = true;
print_options.FullyQualifiedTypes = true;
print_options.ExplodePatternBindingDecls = false;
print_options.PrintDocumentationComments =
print_options.PrintRegularClangComments = print_help_if_available;
return print_options;
}
void SwiftASTContext::SetGenerateDebugInfo(swift::IRGenDebugInfoKind b) {
GetIRGenOptions().DebugInfoKind = b;
}
llvm::TargetOptions *SwiftASTContext::getTargetOptions() {
if (m_target_options_ap.get() == NULL) {
m_target_options_ap.reset(new llvm::TargetOptions());
}
return m_target_options_ap.get();
}
swift::ModuleDecl *SwiftASTContext::GetScratchModule() {
VALID_OR_RETURN(nullptr);
if (m_scratch_module == nullptr)
m_scratch_module = swift::ModuleDecl::create(
GetASTContext()->getIdentifier("__lldb_scratch_module"),
*GetASTContext());
return m_scratch_module;
}
swift::SILModule *SwiftASTContext::GetSILModule() {
VALID_OR_RETURN(nullptr);
if (m_sil_module_ap.get() == NULL)
m_sil_module_ap = swift::SILModule::createEmptyModule(GetScratchModule(),
GetSILOptions());
return m_sil_module_ap.get();
}
swift::irgen::IRGenerator &
SwiftASTContext::GetIRGenerator(swift::IRGenOptions &opts,
swift::SILModule &module) {
if (m_ir_generator_ap.get() == nullptr) {
m_ir_generator_ap.reset(new swift::irgen::IRGenerator(opts, module));
}
return *m_ir_generator_ap.get();
}
swift::irgen::IRGenModule &SwiftASTContext::GetIRGenModule() {
VALID_OR_RETURN(*m_ir_gen_module_ap);
if (m_ir_gen_module_ap.get() == NULL) {
// Make sure we have a good ClangImporter.
GetClangImporter();
swift::IRGenOptions &ir_gen_opts = GetIRGenOptions();
std::string error_str;
std::string triple = GetTriple();
const llvm::Target *llvm_target =
llvm::TargetRegistry::lookupTarget(triple, error_str);
llvm::CodeGenOpt::Level optimization_level = llvm::CodeGenOpt::Level::None;
// Create a target machine.
llvm::TargetMachine *target_machine = llvm_target->createTargetMachine(
triple,
"generic", // cpu
"", // features
*getTargetOptions(),
llvm::Reloc::Static, // TODO verify with Sean, Default went away
llvm::None, optimization_level);
if (target_machine) {
// Set the module's string representation.
const llvm::DataLayout data_layout = target_machine->createDataLayout();
llvm::Triple llvm_triple(triple);
swift::SILModule *sil_module = GetSILModule();
if (sil_module != nullptr) {
swift::irgen::IRGenerator &ir_generator =
GetIRGenerator(ir_gen_opts, *sil_module);
swift::PrimarySpecificPaths PSPs =
GetCompilerInvocation()
.getFrontendOptions()
.InputsAndOutputs.getPrimarySpecificPathsForAtMostOnePrimary();
m_ir_gen_module_ap.reset(new swift::irgen::IRGenModule(
ir_generator, ir_generator.createTargetMachine(), nullptr,
GetGlobalLLVMContext(), ir_gen_opts.ModuleName, PSPs.OutputFilename,
PSPs.MainInputFilenameForDebugInfo));
llvm::Module *llvm_module = m_ir_gen_module_ap->getModule();
llvm_module->setDataLayout(data_layout.getStringRepresentation());
llvm_module->setTargetTriple(triple);
}
}
}
return *m_ir_gen_module_ap;
}
CompilerType
SwiftASTContext::CreateTupleType(const std::vector<CompilerType> &elements) {
VALID_OR_RETURN(CompilerType());
Status error;
if (elements.size() == 0)
return CompilerType(GetASTContext(), GetASTContext()->TheEmptyTupleType);
else {
std::vector<swift::TupleTypeElt> tuple_elems;
for (const CompilerType &type : elements) {
if (auto swift_type = GetSwiftType(type))
tuple_elems.push_back(swift::TupleTypeElt(swift_type));
else
return CompilerType();
}
llvm::ArrayRef<swift::TupleTypeElt> fields(tuple_elems);
return CompilerType(
GetASTContext(),
swift::TupleType::get(fields, *GetASTContext()).getPointer());
}
}
CompilerType
SwiftASTContext::CreateTupleType(const std::vector<TupleElement> &elements) {
VALID_OR_RETURN(CompilerType());
Status error;
if (elements.size() == 0)
return CompilerType(GetASTContext(), GetASTContext()->TheEmptyTupleType);
else {
std::vector<swift::TupleTypeElt> tuple_elems;
for (const TupleElement &element : elements) {
if (auto swift_type = GetSwiftType(element.element_type)) {
if (element.element_name.IsEmpty())
tuple_elems.push_back(swift::TupleTypeElt(swift_type));
else
tuple_elems.push_back(swift::TupleTypeElt(
swift_type, m_ast_context_ap->getIdentifier(
element.element_name.GetCString())));
} else
return CompilerType();
}
llvm::ArrayRef<swift::TupleTypeElt> fields(tuple_elems);
return CompilerType(
GetASTContext(),
swift::TupleType::get(fields, *GetASTContext()).getPointer());
}
}
CompilerType SwiftASTContext::CreateFunctionType(CompilerType arg_type,
CompilerType ret_type,
bool throws) {
VALID_OR_RETURN(CompilerType());
if (!llvm::dyn_cast_or_null<SwiftASTContext>(arg_type.GetTypeSystem()) ||
!llvm::dyn_cast_or_null<SwiftASTContext>(ret_type.GetTypeSystem()))
return CompilerType();
swift::FunctionType::ExtInfo ext_info;
if (throws)
ext_info = ext_info.withThrows();
return CompilerType(GetASTContext(), swift::FunctionType::get(
GetSwiftType(arg_type),
GetSwiftType(ret_type), ext_info));
}
CompilerType SwiftASTContext::GetErrorType() {
VALID_OR_RETURN(CompilerType());
swift::ASTContext *swift_ctx = GetASTContext();
if (swift_ctx) {
// Getting the error type requires the Stdlib module be loaded, but doesn't
// cause it to be loaded.
// Do that here:
swift_ctx->getStdlibModule(true);
swift::NominalTypeDecl *error_type_decl = GetASTContext()->getErrorDecl();
if (error_type_decl) {
auto error_type = error_type_decl->getDeclaredType().getPointer();
return CompilerType(GetASTContext(), error_type);
}
}
return CompilerType();
}
CompilerType SwiftASTContext::GetNSErrorType(Status &error) {
VALID_OR_RETURN(CompilerType());
return GetTypeFromMangledTypename(SwiftLanguageRuntime::GetCurrentMangledName("_TtC10Foundation7NSError").c_str(), error);
}
CompilerType SwiftASTContext::CreateMetatypeType(CompilerType instance_type) {
VALID_OR_RETURN(CompilerType());
if (llvm::dyn_cast_or_null<SwiftASTContext>(instance_type.GetTypeSystem()))
return CompilerType(GetASTContext(),
swift::MetatypeType::get(GetSwiftType(instance_type),
*GetASTContext()));
return CompilerType();
}
SwiftASTContext *SwiftASTContext::GetSwiftASTContext(swift::ASTContext *ast) {
SwiftASTContext *swift_ast = GetASTMap().Lookup(ast);
return swift_ast;
}
uint32_t SwiftASTContext::GetPointerByteSize() {
VALID_OR_RETURN(0);
if (m_pointer_byte_size == 0) {
swift::ASTContext *ast = GetASTContext();
m_pointer_byte_size = CompilerType(ast, ast->TheRawPointerType.getPointer())
.GetByteSize(nullptr);
}
return m_pointer_byte_size;
}
uint32_t SwiftASTContext::GetPointerBitAlignment() {
VALID_OR_RETURN(0);
if (m_pointer_bit_align == 0) {
swift::ASTContext *ast = GetASTContext();
m_pointer_bit_align = CompilerType(ast, ast->TheRawPointerType.getPointer())
.GetAlignedBitSize();
}
return m_pointer_bit_align;
}
bool SwiftASTContext::HasErrors() {
if (m_diagnostic_consumer_ap.get())
return (
static_cast<StoringDiagnosticConsumer *>(m_diagnostic_consumer_ap.get())
->NumErrors() != 0);
else
return false;
}
bool SwiftASTContext::HasFatalErrors(swift::ASTContext *ast_context) {
return (ast_context && ast_context->Diags.hasFatalErrorOccurred());
}
void SwiftASTContext::ClearDiagnostics() {
assert(!HasFatalErrors() && "Never clear a fatal diagnostic!");
if (m_diagnostic_consumer_ap.get())
static_cast<StoringDiagnosticConsumer *>(m_diagnostic_consumer_ap.get())
->Clear();
}
bool SwiftASTContext::SetColorizeDiagnostics(bool b) {
if (m_diagnostic_consumer_ap.get())
return static_cast<StoringDiagnosticConsumer *>(
m_diagnostic_consumer_ap.get())
->SetColorize(b);
return false;
}
void SwiftASTContext::PrintDiagnostics(DiagnosticManager &diagnostic_manager,
uint32_t bufferID, uint32_t first_line,
uint32_t last_line,
uint32_t line_offset) {
// If this is a fatal error, copy the error into the AST context's fatal error
// field, and then put it to the stream, otherwise just dump the diagnostics
// to the stream.
// N.B. you cannot use VALID_OR_RETURN_VOID here since that exits if you have
// fatal errors, which are what we are trying to print here.
if (!m_ast_context_ap.get()) {
SymbolFile *sym_file = GetSymbolFile();
if (sym_file) {
ConstString name
= sym_file->GetObjectFile()->GetModule()->GetObjectName();
m_fatal_errors.SetErrorStringWithFormat(
"Null context for %s.", name.AsCString());
} else {
m_fatal_errors.SetErrorString("Unknown fatal error occurred.");
}
return;
}
if (m_ast_context_ap->Diags.hasFatalErrorOccurred() &&
!m_reported_fatal_error) {
DiagnosticManager fatal_diagnostics;
if (m_diagnostic_consumer_ap.get())
static_cast<StoringDiagnosticConsumer *>(m_diagnostic_consumer_ap.get())
->PrintDiagnostics(fatal_diagnostics, bufferID, first_line, last_line,
line_offset);
if (fatal_diagnostics.Diagnostics().size())
m_fatal_errors.SetErrorString(fatal_diagnostics.GetString().data());
else
m_fatal_errors.SetErrorString("Unknown fatal error occurred.");
m_reported_fatal_error = true;
for (const DiagnosticList::value_type &fatal_diagnostic :
fatal_diagnostics.Diagnostics()) {
// FIXME: need to add a CopyDiagnostic operation for copying diagnostics
// from one manager to another.
diagnostic_manager.AddDiagnostic(
fatal_diagnostic->GetMessage(), fatal_diagnostic->GetSeverity(),
fatal_diagnostic->getKind(), fatal_diagnostic->GetCompilerID());
}
} else {
if (m_diagnostic_consumer_ap.get())
static_cast<StoringDiagnosticConsumer *>(m_diagnostic_consumer_ap.get())
->PrintDiagnostics(diagnostic_manager, bufferID, first_line,
last_line, line_offset);
}
}
void SwiftASTContext::ModulesDidLoad(ModuleList &module_list) {
ClearModuleDependentCaches();
}
void SwiftASTContext::ClearModuleDependentCaches() {
m_negative_type_cache.Clear();
m_extra_type_info_cache.Clear();
}
void SwiftASTContext::DumpConfiguration(Log *log) {
VALID_OR_RETURN_VOID();
if (!log)
return;
log->Printf("(SwiftASTContext*)%p:", this);
if (!m_ast_context_ap)
log->Printf(" (no AST context)");
log->Printf(" Architecture : %s",
m_ast_context_ap->LangOpts.Target.getTriple().c_str());
log->Printf(" SDK path : %s",
m_ast_context_ap->SearchPathOpts.SDKPath.c_str());
log->Printf(" Runtime resource path : %s",
m_ast_context_ap->SearchPathOpts.RuntimeResourcePath.c_str());
log->Printf(" Runtime library path : %s",
m_ast_context_ap->SearchPathOpts.RuntimeLibraryPath.c_str());
log->Printf(
" Runtime library import path : %s",
m_ast_context_ap->SearchPathOpts.RuntimeLibraryImportPath.c_str());
log->Printf(" Framework search paths : (%llu items)",
(unsigned long long)
m_ast_context_ap->SearchPathOpts.FrameworkSearchPaths.size());
for (const auto &framework_search_path :
m_ast_context_ap->SearchPathOpts.FrameworkSearchPaths) {
log->Printf(" %s", framework_search_path.Path.c_str());
}
log->Printf(" Import search paths : (%llu items)",
(unsigned long long)
m_ast_context_ap->SearchPathOpts.ImportSearchPaths.size());
for (std::string &import_search_path :
m_ast_context_ap->SearchPathOpts.ImportSearchPaths) {
log->Printf(" %s", import_search_path.c_str());
}
swift::ClangImporterOptions &clang_importer_options =
GetClangImporterOptions();
log->Printf(" Extra clang arguments : (%llu items)",
(unsigned long long)clang_importer_options.ExtraArgs.size());
for (std::string &extra_arg : clang_importer_options.ExtraArgs) {
log->Printf(" %s", extra_arg.c_str());
}
}
bool SwiftASTContext::HasTarget() const {
lldb::TargetWP empty_wp;
// If either call to "std::weak_ptr::owner_before(...) value returns true,
// this indicates that m_section_wp once contained (possibly still does) a
// reference to a valid shared pointer. This helps us know if we had a valid
// reference to a target which is now invalid because the target was deleted.
return empty_wp.owner_before(m_target_wp) ||
m_target_wp.owner_before(empty_wp);
}
bool SwiftASTContext::CheckProcessChanged() {
if (HasTarget()) {
TargetSP target_sp(m_target_wp.lock());
if (target_sp) {
Process *process = target_sp->GetProcessSP().get();
if (m_process == NULL) {
if (process)
m_process = process;
} else {
if (m_process != process)
return true;
}
}
}
return false;
}
void SwiftASTContext::AddDebuggerClient(
swift::DebuggerClient *debugger_client) {
m_debugger_clients.push_back(
std::unique_ptr<swift::DebuggerClient>(debugger_client));
}
SwiftASTContext::ExtraTypeInformation::ExtraTypeInformation()
: m_flags(false, false) {}
SwiftASTContext::ExtraTypeInformation::ExtraTypeInformation(
swift::CanType swift_can_type)
: m_flags(false, false) {
static ConstString g_rawValue("rawValue");
swift::ASTContext &ast_ctx = swift_can_type->getASTContext();
SwiftASTContext *swift_ast = SwiftASTContext::GetSwiftASTContext(&ast_ctx);
if (swift_ast) {
swift::ProtocolDecl *option_set =
ast_ctx.getProtocol(swift::KnownProtocolKind::OptionSet);
if (option_set) {
if (auto nominal_decl =
swift_can_type.getNominalOrBoundGenericNominal()) {
for (swift::ProtocolDecl *protocol_decl :
nominal_decl->getAllProtocols()) {
if (protocol_decl == option_set) {
for (swift::VarDecl *stored_property :
nominal_decl->getStoredProperties()) {
swift::Identifier name = stored_property->getName();
if (name.str() == g_rawValue.GetStringRef()) {
m_flags.m_is_trivial_option_set = true;
break;
}
}
}
}
}
}
}
if (auto metatype_type = swift::dyn_cast_or_null<swift::MetatypeType>(
swift_can_type)) {
if (!metatype_type->hasRepresentation() ||
(swift::MetatypeRepresentation::Thin ==
metatype_type->getRepresentation()))
m_flags.m_is_zero_size = true;
} else if (auto enum_decl = swift_can_type->getEnumOrBoundGenericEnum()) {
size_t num_nopayload = 0, num_payload = 0;
for (auto the_case : enum_decl->getAllElements()) {
if (the_case->getArgumentInterfaceType()) {
num_payload = 1;
break;
} else {
if (++num_nopayload > 1)
break;
}
}
if (num_nopayload == 1 && num_payload == 0)
m_flags.m_is_zero_size = true;
} else if (auto struct_decl =
swift_can_type->getStructOrBoundGenericStruct()) {
bool has_storage = false;
auto members = struct_decl->getMembers();
for (const auto &member : members) {
if (swift::VarDecl *var_decl =
swift::dyn_cast<swift::VarDecl>(member)) {
if (!var_decl->isStatic() && var_decl->hasStorage()) {
has_storage = true;
break;
}
}
}
m_flags.m_is_zero_size = !has_storage;
} else if (auto tuple_type = swift::dyn_cast_or_null<swift::TupleType>(
swift_can_type)) {
m_flags.m_is_zero_size = (tuple_type->getNumElements() == 0);
}
}
SwiftASTContext::ExtraTypeInformation
SwiftASTContext::GetExtraTypeInformation(void *type) {
if (!type)
return ExtraTypeInformation();
swift::CanType swift_can_type;
void *swift_can_type_ptr = nullptr;
if (auto swift_type = GetSwiftType(type)) {
swift_can_type = swift_type->getCanonicalType();
swift_can_type_ptr = swift_can_type.getPointer();
}
if (!swift_can_type_ptr)
return ExtraTypeInformation();
ExtraTypeInformation eti;
if (!m_extra_type_info_cache.Lookup(swift_can_type_ptr, eti)) {
ExtraTypeInformation extra_info(swift_can_type);
m_extra_type_info_cache.Insert(swift_can_type_ptr, extra_info);
return extra_info;
} else {
return eti;
}
}
bool SwiftASTContext::DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) {
return false;
}
ConstString SwiftASTContext::DeclContextGetName(void *opaque_decl_ctx) {
return ConstString();
}
ConstString
SwiftASTContext::DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) {
return ConstString();
}
bool SwiftASTContext::DeclContextIsClassMethod(
void *opaque_decl_ctx, lldb::LanguageType *language_ptr,
bool *is_instance_method_ptr, ConstString *language_object_name_ptr) {
return false;
}
///////////
////////////////////
///////////
bool SwiftASTContext::IsArrayType(void *type, CompilerType *element_type_ptr,
uint64_t *size, bool *is_incomplete) {
VALID_OR_RETURN(false);
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
swift::BoundGenericStructType *struct_type =
swift_can_type->getAs<swift::BoundGenericStructType>();
if (struct_type) {
swift::StructDecl *struct_decl = struct_type->getDecl();
if (strcmp(struct_decl->getName().get(), "Array") != 0)
return false;
if (!struct_decl->getModuleContext()->isStdlibModule())
return false;
const llvm::ArrayRef<swift::Type> &args = struct_type->getGenericArgs();
if (args.size() != 1)
return false;
if (is_incomplete)
*is_incomplete = true;
if (size)
*size = 0;
if (element_type_ptr)
*element_type_ptr =
CompilerType(GetASTContext(), args[0].getPointer());
return true;
}
return false;
}
bool SwiftASTContext::IsAggregateType(void *type) {
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
auto referent_type = swift_can_type->getReferenceStorageReferent();
return (referent_type->is<swift::TupleType>() ||
referent_type->is<swift::BuiltinVectorType>() ||
referent_type->getAnyNominal());
}
return false;
}
bool SwiftASTContext::IsVectorType(void *type, CompilerType *element_type,
uint64_t *size) {
return false;
}
bool SwiftASTContext::IsRuntimeGeneratedType(void *type) { return false; }
bool SwiftASTContext::IsCharType(void *type) { return false; }
bool SwiftASTContext::IsCompleteType(void *type) { return true; }
bool SwiftASTContext::IsConst(void *type) { return false; }
bool SwiftASTContext::IsCStringType(void *type, uint32_t &length) {
return false;
}
bool SwiftASTContext::IsFunctionType(void *type, bool *is_variadic_ptr) {
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Function:
case swift::TypeKind::GenericFunction:
return true;
case swift::TypeKind::SILFunction:
return false; // TODO: is this correct?
default:
return false;
}
}
return false;
}
// Used to detect "Homogeneous Floating-point Aggregates"
uint32_t SwiftASTContext::IsHomogeneousAggregate(void *type,
CompilerType *base_type_ptr) {
return 0;
}
size_t SwiftASTContext::GetNumberOfFunctionArguments(void *type) {
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
auto func =
swift::dyn_cast_or_null<swift::AnyFunctionType>(
swift_can_type);
if (func) {
auto input = func.getInput();
// See comment in swift::AnyFunctionType for rationale here:
// A function can take either a tuple or a parentype, but if a parentype
// (i.e. (Foo)), then it will be reduced down to just Foo, so if the input
// is not a tuple, that must mean there is only 1 input.
auto tuple = swift::dyn_cast<swift::TupleType>(input);
if (tuple)
return tuple->getNumElements();
else
return 1;
}
}
return 0;
}
CompilerType SwiftASTContext::GetFunctionArgumentAtIndex(void *type,
const size_t index) {
VALID_OR_RETURN(CompilerType());
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
auto func =
swift::dyn_cast<swift::AnyFunctionType>(
swift_can_type);
if (func) {
auto input = func.getInput();
// See comment in swift::AnyFunctionType for rationale here:
// A function can take either a tuple or a parentype, but if a parentype
// (i.e. (Foo)), then it will be reduced down to just Foo, so if the input
// is not a tuple, that must mean there is only 1 input.
auto tuple = swift::dyn_cast<swift::TupleType>(input);
if (tuple) {
if (index < tuple->getNumElements())
return CompilerType(GetASTContext(),
tuple->getElementType(index));
} else
return CompilerType(GetASTContext(), input);
}
}
return CompilerType();
}
bool SwiftASTContext::IsFunctionPointerType(void *type) {
return IsFunctionType(type, nullptr); // FIXME: think about this
}
bool SwiftASTContext::IsBlockPointerType(
void *type, CompilerType *function_pointer_type_ptr) {
return false;
}
bool SwiftASTContext::IsIntegerType(void *type, bool &is_signed) {
return (GetTypeInfo(type, nullptr) & eTypeIsInteger);
}
bool SwiftASTContext::IsPointerType(void *type, CompilerType *pointee_type) {
VALID_OR_RETURN(false);
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
auto referent_type = swift_can_type->getReferenceStorageReferent();
return (referent_type->is<swift::BuiltinRawPointerType>() ||
referent_type->is<swift::BuiltinNativeObjectType>() ||
referent_type->is<swift::BuiltinUnsafeValueBufferType>() ||
referent_type->is<swift::BuiltinUnknownObjectType>() ||
referent_type->is<swift::BuiltinBridgeObjectType>());
}
if (pointee_type)
pointee_type->Clear();
return false;
}
bool SwiftASTContext::IsPointerOrReferenceType(void *type,
CompilerType *pointee_type) {
return IsPointerType(type, pointee_type) ||
IsReferenceType(type, pointee_type, nullptr);
}
bool SwiftASTContext::ShouldTreatScalarValueAsAddress(
lldb::opaque_compiler_type_t type) {
return Flags(GetTypeInfo(type, nullptr))
.AnySet(eTypeInstanceIsPointer | eTypeIsReference);
}
bool SwiftASTContext::IsReferenceType(void *type, CompilerType *pointee_type,
bool *is_rvalue) {
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::InOut:
case swift::TypeKind::LValue:
if (pointee_type)
*pointee_type = GetNonReferenceType(type);
return true;
default:
break;
}
}
if (pointee_type)
pointee_type->Clear();
return false;
}
bool SwiftASTContext::IsFloatingPointType(void *type, uint32_t &count,
bool &is_complex) {
if (type) {
if (GetTypeInfo(type, nullptr) & eTypeIsFloat) {
count = 1;
is_complex = false;
return true;
}
}
count = 0;
is_complex = false;
return false;
}
bool SwiftASTContext::IsDefined(void *type) {
if (!type)
return false;
return true;
}
bool SwiftASTContext::IsPolymorphicClass(void *type) { return false; }
bool SwiftASTContext::IsPossibleDynamicType(void *type,
CompilerType *dynamic_pointee_type,
bool check_cplusplus,
bool check_objc, bool check_swift) {
VALID_OR_RETURN(false);
if (type && check_swift) {
// FIXME: use the dynamic_pointee_type
Flags type_flags(GetTypeInfo(type, nullptr));
if (type_flags.AnySet(eTypeIsArchetype | eTypeIsClass | eTypeIsProtocol))
return true;
if (type_flags.AnySet(eTypeIsStructUnion | eTypeIsEnumeration |
eTypeIsTuple)) {
CompilerType compiler_type(GetASTContext(), GetCanonicalSwiftType(type));
return !SwiftASTContext::IsFullyRealized(compiler_type);
}
auto can_type = GetCanonicalSwiftType(type).getPointer();
if (can_type == GetASTContext()->TheRawPointerType.getPointer())
return true;
if (can_type == GetASTContext()->TheUnknownObjectType.getPointer())
return true;
if (can_type == GetASTContext()->TheNativeObjectType.getPointer())
return true;
if (can_type == GetASTContext()->TheBridgeObjectType.getPointer())
return true;
}
if (dynamic_pointee_type)
dynamic_pointee_type->Clear();
return false;
}
bool SwiftASTContext::IsScalarType(void *type) {
if (!type)
return false;
return (GetTypeInfo(type, nullptr) & eTypeIsScalar) != 0;
}
bool SwiftASTContext::IsTypedefType(void *type) {
if (!type)
return false;
swift::Type swift_type(GetSwiftType(type));
return swift::isa<swift::NameAliasType>(swift_type.getPointer());
}
bool SwiftASTContext::IsVoidType(void *type) {
VALID_OR_RETURN(false);
if (!type)
return false;
return type == GetASTContext()->TheEmptyTupleType.getPointer();
}
bool SwiftASTContext::IsArchetypeType(const CompilerType &compiler_type) {
if (!compiler_type.IsValid())
return false;
if (llvm::dyn_cast_or_null<SwiftASTContext>(compiler_type.GetTypeSystem())) {
swift::Type swift_type(GetSwiftType(compiler_type));
return swift_type->is<swift::ArchetypeType>();
}
return false;
}
bool SwiftASTContext::IsSelfArchetypeType(const CompilerType &compiler_type) {
if (!compiler_type.IsValid())
return false;
if (llvm::dyn_cast_or_null<SwiftASTContext>(compiler_type.GetTypeSystem())) {
if (swift::isa<swift::ArchetypeType>(
(swift::TypeBase *)compiler_type.GetOpaqueQualType())) {
// Hack: Just assume if we have an archetype as the type of 'self',
// it's going to be a protocol 'Self' type.
return true;
}
}
return false;
}
bool SwiftASTContext::IsPossibleZeroSizeType(
const CompilerType &compiler_type) {
if (!compiler_type.IsValid())
return false;
if (auto ast = llvm::dyn_cast_or_null<SwiftASTContext>(
compiler_type.GetTypeSystem()))
return ast
->GetExtraTypeInformation(
GetCanonicalSwiftType(compiler_type).getPointer())
.m_flags.m_is_zero_size;
return false;
}
bool SwiftASTContext::IsErrorType(const CompilerType &compiler_type) {
if (compiler_type.IsValid() &&
llvm::dyn_cast_or_null<SwiftASTContext>(compiler_type.GetTypeSystem())) {
ProtocolInfo protocol_info;
if (GetProtocolTypeInfo(compiler_type, protocol_info))
return protocol_info.m_is_errortype;
return false;
}
return false;
}
CompilerType
SwiftASTContext::GetReferentType(const CompilerType &compiler_type) {
VALID_OR_RETURN(CompilerType());
if (compiler_type.IsValid() &&
llvm::dyn_cast_or_null<SwiftASTContext>(compiler_type.GetTypeSystem())) {
swift::CanType swift_can_type(GetCanonicalSwiftType(compiler_type));
auto ref_type = swift_can_type->getReferenceStorageReferent();
return CompilerType(GetASTContext(), ref_type);
}
return CompilerType();
}
bool SwiftASTContext::IsTrivialOptionSetType(
const CompilerType &compiler_type) {
if (compiler_type.IsValid() &&
llvm::dyn_cast_or_null<SwiftASTContext>(compiler_type.GetTypeSystem()))
return GetExtraTypeInformation(compiler_type.GetOpaqueQualType())
.m_flags.m_is_trivial_option_set;
return false;
}
bool SwiftASTContext::IsFullyRealized(const CompilerType &compiler_type) {
if (!compiler_type.IsValid())
return false;
if (auto ast = llvm::dyn_cast_or_null<SwiftASTContext>(
compiler_type.GetTypeSystem())) {
swift::CanType swift_can_type(GetCanonicalSwiftType(compiler_type));
if (swift::isa<swift::MetatypeType>(swift_can_type))
return true;
return !swift_can_type->hasArchetype();
}
return false;
}
bool SwiftASTContext::GetProtocolTypeInfo(const CompilerType &type,
ProtocolInfo &protocol_info) {
if (auto ast =
llvm::dyn_cast_or_null<SwiftASTContext>(type.GetTypeSystem())) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
if (!swift_can_type.isExistentialType())
return false;
swift::ExistentialLayout layout = swift_can_type.getExistentialLayout();
protocol_info.m_is_class_only = layout.requiresClass();
protocol_info.m_num_protocols = layout.getProtocols().size();
protocol_info.m_is_objc = layout.isObjC();
protocol_info.m_is_anyobject = layout.isAnyObject();
protocol_info.m_is_errortype = layout.isErrorExistential();
unsigned num_witness_tables = 0;
for (auto protoTy : layout.getProtocols()) {
if (!protoTy->getDecl()->isObjC() &&
!protoTy->isAnyObject())
num_witness_tables++;
}
if (layout.isErrorExistential()) {
// Error existential -- instance pointer only
protocol_info.m_num_payload_words = 0;
protocol_info.m_num_storage_words = 1;
} else if (layout.requiresClass()) {
// Class-constrained existential -- instance pointer plus witness tables
protocol_info.m_num_payload_words = 0;
protocol_info.m_num_storage_words = 1 + num_witness_tables;
} else {
// Opaque existential -- three words of inline storage, metadata and
// witness tables
protocol_info.m_num_payload_words = 3;
protocol_info.m_num_storage_words = 3 + 1 + num_witness_tables;
}
return true;
}
return false;
}
SwiftASTContext::TypeAllocationStrategy
SwiftASTContext::GetAllocationStrategy(const CompilerType &type) {
if (auto ast =
llvm::dyn_cast_or_null<SwiftASTContext>(type.GetTypeSystem())) {
const swift::irgen::TypeInfo *type_info =
ast->GetSwiftTypeInfo(type.GetOpaqueQualType());
if (!type_info)
return TypeAllocationStrategy::eUnknown;
switch (type_info->getFixedPacking(ast->GetIRGenModule())) {
case swift::irgen::FixedPacking::OffsetZero:
return TypeAllocationStrategy::eInline;
case swift::irgen::FixedPacking::Allocate:
return TypeAllocationStrategy::ePointer;
case swift::irgen::FixedPacking::Dynamic:
return TypeAllocationStrategy::eDynamic;
default:
break;
}
}
return TypeAllocationStrategy::eUnknown;
}
bool SwiftASTContext::IsBeingDefined(void *type) { return false; }
bool SwiftASTContext::IsObjCObjectPointerType(const CompilerType &type,
CompilerType *class_type_ptr) {
if (!type)
return false;
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
if (type_kind == swift::TypeKind::BuiltinNativeObject ||
type_kind == swift::TypeKind::BuiltinUnknownObject)
return true;
if (class_type_ptr)
class_type_ptr->Clear();
return false;
}
//----------------------------------------------------------------------
// Type Completion
//----------------------------------------------------------------------
bool SwiftASTContext::GetCompleteType(void *type) { return true; }
ConstString SwiftASTContext::GetTypeName(void *type) {
std::string type_name;
if (type) {
swift::Type swift_type(GetSwiftType(type));
swift::Type normalized_type =
swift_type.transform([](swift::Type type) -> swift::Type {
if (swift::SyntaxSugarType *syntax_sugar_type =
swift::dyn_cast<swift::SyntaxSugarType>(type.getPointer())) {
return syntax_sugar_type->getSinglyDesugaredType();
}
if (swift::DictionaryType *dictionary_type =
swift::dyn_cast<swift::DictionaryType>(type.getPointer())) {
return dictionary_type->getSinglyDesugaredType();
}
return type;
});
swift::PrintOptions print_options;
print_options.FullyQualifiedTypes = true;
print_options.SynthesizeSugarOnTypes = false;
type_name = normalized_type.getString(print_options);
}
return ConstString(type_name);
}
ConstString SwiftASTContext::GetDisplayTypeName(void *type) {
std::string type_name(GetTypeName(type).AsCString(""));
if (type) {
swift::Type swift_type(GetSwiftType(type));
swift::PrintOptions print_options;
print_options.FullyQualifiedTypes = false;
print_options.SynthesizeSugarOnTypes = true;
print_options.FullyQualifiedTypesIfAmbiguous = true;
type_name = swift_type.getString(print_options);
}
return ConstString(type_name);
}
ConstString SwiftASTContext::GetTypeSymbolName(void *type) {
swift::Type swift_type(GetSwiftType(type));
return GetTypeName(swift_type->getWithoutParens().getPointer());
}
ConstString SwiftASTContext::GetMangledTypeName(void *type) {
return GetMangledTypeName(GetSwiftType(type).getPointer());
}
uint32_t
SwiftASTContext::GetTypeInfo(void *type,
CompilerType *pointee_or_element_clang_type) {
VALID_OR_RETURN(0);
if (!type)
return 0;
if (pointee_or_element_clang_type)
pointee_or_element_clang_type->Clear();
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
uint32_t swift_flags = eTypeIsSwift;
switch (type_kind) {
case swift::TypeKind::DependentMember:
case swift::TypeKind::Error:
case swift::TypeKind::GenericTypeParam:
case swift::TypeKind::Module:
case swift::TypeKind::TypeVariable:
break;
case swift::TypeKind::UnboundGeneric:
swift_flags |= eTypeIsGeneric;
break;
case swift::TypeKind::GenericFunction:
swift_flags |= eTypeIsGeneric;
case swift::TypeKind::Function:
swift_flags |=
eTypeIsBuiltIn | eTypeHasValue | eTypeIsScalar | eTypeInstanceIsPointer;
break;
case swift::TypeKind::BuiltinInteger:
swift_flags |=
eTypeIsBuiltIn | eTypeHasValue | eTypeIsScalar | eTypeIsInteger;
break;
case swift::TypeKind::BuiltinFloat:
swift_flags |=
eTypeIsBuiltIn | eTypeHasValue | eTypeIsScalar | eTypeIsFloat;
break;
case swift::TypeKind::BuiltinRawPointer:
swift_flags |= eTypeIsBuiltIn | eTypeHasChildren | eTypeIsPointer |
eTypeIsScalar | eTypeHasValue;
break;
case swift::TypeKind::BuiltinNativeObject:
swift_flags |= eTypeIsBuiltIn | eTypeHasChildren | eTypeIsPointer |
eTypeIsScalar | eTypeHasValue;
break;
case swift::TypeKind::BuiltinUnknownObject:
swift_flags |= eTypeIsBuiltIn | eTypeHasChildren | eTypeIsPointer |
eTypeIsScalar | eTypeHasValue | eTypeIsObjC;
break;
case swift::TypeKind::BuiltinBridgeObject:
swift_flags |= eTypeIsBuiltIn | eTypeHasChildren | eTypeIsPointer |
eTypeIsScalar | eTypeHasValue | eTypeIsObjC;
break;
case swift::TypeKind::BuiltinUnsafeValueBuffer:
swift_flags |=
eTypeIsBuiltIn | eTypeIsPointer | eTypeIsScalar | eTypeHasValue;
break;
case swift::TypeKind::BuiltinVector:
// TODO: OR in eTypeIsFloat or eTypeIsInteger as needed
return eTypeIsBuiltIn | eTypeHasChildren | eTypeIsVector;
break;
case swift::TypeKind::Tuple:
swift_flags |= eTypeHasChildren | eTypeIsTuple;
break;
case swift::TypeKind::UnmanagedStorage:
case swift::TypeKind::UnownedStorage:
case swift::TypeKind::WeakStorage:
swift_flags |=
CompilerType(GetASTContext(),
swift_can_type->getReferenceStorageReferent())
.GetTypeInfo(pointee_or_element_clang_type);
break;
case swift::TypeKind::BoundGenericEnum:
swift_flags |= eTypeIsGeneric | eTypeIsBound;
case swift::TypeKind::Enum: {
SwiftEnumDescriptor *cached_enum_info = GetCachedEnumInfo(type);
if (cached_enum_info) {
if (cached_enum_info->GetNumElementsWithPayload() == 0)
swift_flags |= eTypeHasValue | eTypeIsEnumeration;
else
swift_flags |= eTypeHasValue | eTypeIsEnumeration | eTypeHasChildren;
} else
swift_flags |= eTypeIsEnumeration;
} break;
case swift::TypeKind::BoundGenericStruct:
swift_flags |= eTypeIsGeneric | eTypeIsBound;
case swift::TypeKind::Struct:
swift_flags |= eTypeHasChildren | eTypeIsStructUnion;
break;
case swift::TypeKind::BoundGenericClass:
swift_flags |= eTypeIsGeneric | eTypeIsBound;
case swift::TypeKind::Class:
swift_flags |= eTypeHasChildren | eTypeIsClass | eTypeHasValue |
eTypeInstanceIsPointer;
break;
case swift::TypeKind::Protocol:
case swift::TypeKind::ProtocolComposition:
swift_flags |= eTypeHasChildren | eTypeIsStructUnion | eTypeIsProtocol;
break;
case swift::TypeKind::ExistentialMetatype:
case swift::TypeKind::Metatype:
swift_flags |= eTypeIsMetatype | eTypeHasValue;
break;
case swift::TypeKind::Archetype:
swift_flags |=
eTypeHasValue | eTypeIsScalar | eTypeIsPointer | eTypeIsArchetype;
break;
case swift::TypeKind::InOut:
case swift::TypeKind::LValue:
if (pointee_or_element_clang_type)
*pointee_or_element_clang_type = GetNonReferenceType(type);
swift_flags |= eTypeHasChildren | eTypeIsReference | eTypeHasValue;
break;
case swift::TypeKind::DynamicSelf:
case swift::TypeKind::SILBox:
case swift::TypeKind::SILFunction:
case swift::TypeKind::SILBlockStorage:
case swift::TypeKind::Unresolved:
break;
case swift::TypeKind::Optional:
case swift::TypeKind::NameAlias:
case swift::TypeKind::Paren:
case swift::TypeKind::Dictionary:
case swift::TypeKind::ArraySlice:
assert(false && "Not a canonical type");
break;
}
return swift_flags;
}
lldb::LanguageType SwiftASTContext::GetMinimumLanguage(void *type) {
if (!type)
return lldb::eLanguageTypeC;
return lldb::eLanguageTypeSwift;
}
lldb::TypeClass SwiftASTContext::GetTypeClass(void *type) {
VALID_OR_RETURN(lldb::eTypeClassInvalid);
if (!type)
return lldb::eTypeClassInvalid;
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Error:
return lldb::eTypeClassOther;
case swift::TypeKind::BuiltinInteger:
return lldb::eTypeClassBuiltin;
case swift::TypeKind::BuiltinFloat:
return lldb::eTypeClassBuiltin;
case swift::TypeKind::BuiltinRawPointer:
return lldb::eTypeClassBuiltin;
case swift::TypeKind::BuiltinNativeObject:
return lldb::eTypeClassBuiltin;
case swift::TypeKind::BuiltinUnsafeValueBuffer:
return lldb::eTypeClassBuiltin;
case swift::TypeKind::BuiltinUnknownObject:
return lldb::eTypeClassBuiltin;
case swift::TypeKind::BuiltinBridgeObject:
return lldb::eTypeClassBuiltin;
case swift::TypeKind::BuiltinVector:
return lldb::eTypeClassVector;
case swift::TypeKind::Tuple:
return lldb::eTypeClassArray;
case swift::TypeKind::UnmanagedStorage:
case swift::TypeKind::UnownedStorage:
case swift::TypeKind::WeakStorage:
return CompilerType(GetASTContext(),
swift_can_type->getReferenceStorageReferent())
.GetTypeClass();
case swift::TypeKind::GenericTypeParam:
return lldb::eTypeClassOther;
case swift::TypeKind::DependentMember:
return lldb::eTypeClassOther;
case swift::TypeKind::Enum:
return lldb::eTypeClassUnion;
case swift::TypeKind::Struct:
return lldb::eTypeClassStruct;
case swift::TypeKind::Class:
return lldb::eTypeClassClass;
case swift::TypeKind::Protocol:
return lldb::eTypeClassOther;
case swift::TypeKind::Metatype:
return lldb::eTypeClassOther;
case swift::TypeKind::Module:
return lldb::eTypeClassOther;
case swift::TypeKind::Archetype:
return lldb::eTypeClassOther;
case swift::TypeKind::Function:
return lldb::eTypeClassFunction;
case swift::TypeKind::GenericFunction:
return lldb::eTypeClassFunction;
case swift::TypeKind::ProtocolComposition:
return lldb::eTypeClassOther;
case swift::TypeKind::LValue:
return lldb::eTypeClassReference;
case swift::TypeKind::UnboundGeneric:
return lldb::eTypeClassOther;
case swift::TypeKind::BoundGenericClass:
return lldb::eTypeClassClass;
case swift::TypeKind::BoundGenericEnum:
return lldb::eTypeClassUnion;
case swift::TypeKind::BoundGenericStruct:
return lldb::eTypeClassStruct;
case swift::TypeKind::TypeVariable:
return lldb::eTypeClassOther;
case swift::TypeKind::ExistentialMetatype:
return lldb::eTypeClassOther;
case swift::TypeKind::DynamicSelf:
return lldb::eTypeClassOther;
case swift::TypeKind::SILBox:
return lldb::eTypeClassOther;
case swift::TypeKind::SILFunction:
return lldb::eTypeClassFunction;
case swift::TypeKind::SILBlockStorage:
return lldb::eTypeClassOther;
case swift::TypeKind::InOut:
return lldb::eTypeClassOther;
case swift::TypeKind::Unresolved:
return lldb::eTypeClassOther;
case swift::TypeKind::Optional:
case swift::TypeKind::NameAlias:
case swift::TypeKind::Paren:
case swift::TypeKind::Dictionary:
case swift::TypeKind::ArraySlice:
assert(false && "Not a canonical type");
break;
}
return lldb::eTypeClassOther;
}
unsigned SwiftASTContext::GetTypeQualifiers(void *type) { return 0; }
//----------------------------------------------------------------------
// Creating related types
//----------------------------------------------------------------------
CompilerType SwiftASTContext::GetArrayElementType(void *type,
uint64_t *stride) {
VALID_OR_RETURN(CompilerType());
CompilerType element_type;
if (type) {
swift::CanType swift_type(GetCanonicalSwiftType(type));
// There are a couple of structs that mean "Array" in Swift:
// Array<T>
// NativeArray<T>
// Slice<T>
// Treat them as arrays for convenience sake.
swift::BoundGenericStructType *boundGenericStructType(
swift_type->getAs<swift::BoundGenericStructType>());
if (boundGenericStructType) {
auto args = boundGenericStructType->getGenericArgs();
swift::StructDecl *decl = boundGenericStructType->getDecl();
if (args.size() == 1 &&
decl->getModuleContext()->isStdlibModule()) {
const char *declname = decl->getName().get();
if (0 == strcmp(declname, "NativeArray") ||
0 == strcmp(declname, "Array") || 0 == strcmp(declname, "ArraySlice"))
element_type = CompilerType(GetASTContext(), args[0].getPointer());
}
}
}
return element_type;
}
CompilerType SwiftASTContext::GetCanonicalType(void *type) {
VALID_OR_RETURN(CompilerType());
if (type)
return CompilerType(GetASTContext(),
GetCanonicalSwiftType(type).getPointer());
return CompilerType();
}
CompilerType SwiftASTContext::GetInstanceType(void *type) {
VALID_OR_RETURN(CompilerType());
if (!type)
return CompilerType();
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
switch (swift_can_type->getKind()) {
case swift::TypeKind::ExistentialMetatype:
case swift::TypeKind::Metatype: {
auto metatype_type =
swift::dyn_cast<swift::AnyMetatypeType>(swift_can_type);
if (metatype_type)
return CompilerType(GetASTContext(),
metatype_type.getInstanceType().getPointer());
return CompilerType();
}
default:
break;
}
return CompilerType(GetASTContext(), GetSwiftType(type));
}
CompilerType SwiftASTContext::GetFullyUnqualifiedType(void *type) {
VALID_OR_RETURN(CompilerType());
return CompilerType(GetASTContext(), GetSwiftType(type));
}
int SwiftASTContext::GetFunctionArgumentCount(void *type) {
return GetNumberOfFunctionArguments(type);
}
CompilerType SwiftASTContext::GetFunctionArgumentTypeAtIndex(void *type,
size_t idx) {
return GetFunctionArgumentAtIndex(type, idx);
}
CompilerType SwiftASTContext::GetFunctionReturnType(void *type) {
VALID_OR_RETURN(CompilerType());
if (type) {
auto func = swift::dyn_cast<swift::AnyFunctionType>(
GetCanonicalSwiftType(type));
if (func)
return CompilerType(GetASTContext(), func.getResult().getPointer());
}
return CompilerType();
}
size_t SwiftASTContext::GetNumMemberFunctions(void *type) {
size_t num_functions = 0;
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
auto nominal_decl = swift_can_type.getAnyNominal();
if (nominal_decl) {
auto iter = nominal_decl->getMembers().begin();
auto end = nominal_decl->getMembers().end();
for (; iter != end; iter++) {
switch (iter->getKind()) {
case swift::DeclKind::Constructor:
case swift::DeclKind::Destructor:
case swift::DeclKind::Func:
num_functions += 1;
break;
default:
break;
}
}
}
}
return num_functions;
}
TypeMemberFunctionImpl SwiftASTContext::GetMemberFunctionAtIndex(void *type,
size_t idx) {
VALID_OR_RETURN(TypeMemberFunctionImpl());
std::string name("");
CompilerType result_type;
MemberFunctionKind kind(MemberFunctionKind::eMemberFunctionKindUnknown);
swift::AbstractFunctionDecl *the_decl_we_care_about = nullptr;
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
auto nominal_decl = swift_can_type.getAnyNominal();
if (nominal_decl) {
auto iter = nominal_decl->getMembers().begin();
auto end = nominal_decl->getMembers().end();
for (; iter != end; iter++) {
auto decl_kind = iter->getKind();
switch (decl_kind) {
case swift::DeclKind::Constructor:
case swift::DeclKind::Destructor:
case swift::DeclKind::Func: {
if (idx == 0) {
swift::AbstractFunctionDecl *abstract_func_decl =
llvm::dyn_cast_or_null<swift::AbstractFunctionDecl>(*iter);
if (abstract_func_decl) {
switch (decl_kind) {
case swift::DeclKind::Constructor:
name.clear();
kind = lldb::eMemberFunctionKindConstructor;
the_decl_we_care_about = abstract_func_decl;
break;
case swift::DeclKind::Destructor:
name.clear();
kind = lldb::eMemberFunctionKindDestructor;
the_decl_we_care_about = abstract_func_decl;
break;
case swift::DeclKind::Func:
default: // I know that this can only be one of three kinds
// since I am here..
{
swift::FuncDecl *func_decl =
llvm::dyn_cast<swift::FuncDecl>(*iter);
if (func_decl) {
if (func_decl->getName().empty())
name.clear();
else
name.assign(func_decl->getName().get());
if (func_decl->isStatic())
kind = lldb::eMemberFunctionKindStaticMethod;
else
kind = lldb::eMemberFunctionKindInstanceMethod;
the_decl_we_care_about = func_decl;
}
}
}
result_type =
CompilerType(GetASTContext(),
abstract_func_decl->getInterfaceType().getPointer());
}
} else
--idx;
} break;
default:
break;
}
}
}
}
if (type && the_decl_we_care_about && (kind != eMemberFunctionKindUnknown))
return TypeMemberFunctionImpl(
result_type, CompilerDecl(this, the_decl_we_care_about), name, kind);
return TypeMemberFunctionImpl();
}
CompilerType SwiftASTContext::GetLValueReferenceType(void *type) {
VALID_OR_RETURN(CompilerType());
if (type)
return CompilerType(GetASTContext(),
swift::LValueType::get(GetSwiftType(type)));
return CompilerType();
}
CompilerType SwiftASTContext::GetRValueReferenceType(void *type) {
return CompilerType();
}
CompilerType SwiftASTContext::GetNonReferenceType(void *type) {
VALID_OR_RETURN(CompilerType());
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
swift::LValueType *lvalue = swift_can_type->getAs<swift::LValueType>();
if (lvalue)
return CompilerType(GetASTContext(),
lvalue->getObjectType().getPointer());
swift::InOutType *inout = swift_can_type->getAs<swift::InOutType>();
if (inout)
return CompilerType(GetASTContext(),
inout->getObjectType().getPointer());
}
return CompilerType();
}
CompilerType SwiftASTContext::GetPointeeType(void *type) {
return CompilerType();
}
CompilerType SwiftASTContext::GetPointerType(void *type) {
VALID_OR_RETURN(CompilerType());
if (type) {
swift::Type swift_type(::GetSwiftType(type));
const swift::TypeKind type_kind = swift_type->getKind();
if (type_kind == swift::TypeKind::BuiltinRawPointer)
return CompilerType(GetASTContext(), swift_type);
else if (type_kind == swift::TypeKind::Struct)
return CompilerType(GetASTContext(), swift::InOutType::get(swift_type));
}
return CompilerType();
}
CompilerType SwiftASTContext::GetTypedefedType(void *type) {
VALID_OR_RETURN(CompilerType());
if (type) {
swift::Type swift_type(::GetSwiftType(type));
swift::NameAliasType *name_alias_type =
swift::dyn_cast<swift::NameAliasType>(swift_type.getPointer());
if (name_alias_type) {
return CompilerType(GetASTContext(),
name_alias_type->getSinglyDesugaredType());
}
}
return CompilerType();
}
CompilerType
SwiftASTContext::GetUnboundType(lldb::opaque_compiler_type_t type) {
VALID_OR_RETURN(CompilerType());
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
swift::BoundGenericType *bound_generic_type =
swift_can_type->getAs<swift::BoundGenericType>();
if (bound_generic_type) {
swift::NominalTypeDecl *nominal_type_decl = bound_generic_type->getDecl();
if (nominal_type_decl)
return CompilerType(GetASTContext(),
nominal_type_decl->getDeclaredType());
}
}
return CompilerType(GetASTContext(), GetSwiftType(type));
}
//----------------------------------------------------------------------
// Create related types using the current type's AST
//----------------------------------------------------------------------
CompilerType SwiftASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) {
return CompilerType();
}
CompilerType SwiftASTContext::GetIntTypeFromBitSize(size_t bit_size,
bool is_signed) {
return CompilerType();
}
CompilerType SwiftASTContext::GetFloatTypeFromBitSize(size_t bit_size) {
return CompilerType();
}
//----------------------------------------------------------------------
// Exploring the type
//----------------------------------------------------------------------
const swift::irgen::TypeInfo *
SwiftASTContext::GetSwiftTypeInfo(swift::Type container_type,
swift::VarDecl *item_decl) {
VALID_OR_RETURN(nullptr);
if (container_type && item_decl) {
auto &irgen_module = GetIRGenModule();
swift::CanType container_can_type(
GetCanonicalSwiftType(container_type.getPointer()));
swift::SILType lowered_container_type =
irgen_module.getLoweredType(container_can_type);
swift::SILType lowered_field_type =
lowered_container_type.getFieldType(item_decl, *GetSILModule());
return &irgen_module.getTypeInfo(lowered_field_type);
}
return nullptr;
}
const swift::irgen::TypeInfo *SwiftASTContext::GetSwiftTypeInfo(void *type) {
VALID_OR_RETURN(nullptr);
if (type) {
auto &irgen_module = GetIRGenModule();
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
swift::SILType swift_sil_type = irgen_module.getLoweredType(
swift_can_type);
return &irgen_module.getTypeInfo(swift_sil_type);
}
return nullptr;
}
const swift::irgen::FixedTypeInfo *
SwiftASTContext::GetSwiftFixedTypeInfo(void *type) {
VALID_OR_RETURN(nullptr);
const swift::irgen::TypeInfo *type_info = GetSwiftTypeInfo(type);
if (type_info) {
if (type_info->isFixedSize())
return swift::cast<const swift::irgen::FixedTypeInfo>(type_info);
}
return nullptr;
}
uint64_t SwiftASTContext::GetBitSize(lldb::opaque_compiler_type_t type,
ExecutionContextScope *exe_scope) {
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Archetype:
case swift::TypeKind::LValue:
case swift::TypeKind::UnboundGeneric:
case swift::TypeKind::GenericFunction:
case swift::TypeKind::Function:
return GetPointerByteSize() * 8;
default:
break;
}
const swift::irgen::FixedTypeInfo *fixed_type_info =
GetSwiftFixedTypeInfo(type);
if (fixed_type_info)
return fixed_type_info->getFixedSize().getValue() * 8;
}
return 0;
}
uint64_t SwiftASTContext::GetByteStride(lldb::opaque_compiler_type_t type) {
if (type) {
const swift::irgen::FixedTypeInfo *fixed_type_info =
GetSwiftFixedTypeInfo(type);
if (fixed_type_info)
return fixed_type_info->getFixedStride().getValue();
}
return 0;
}
size_t SwiftASTContext::GetTypeBitAlign(void *type) {
if (type) {
const swift::irgen::FixedTypeInfo *fixed_type_info =
GetSwiftFixedTypeInfo(type);
if (fixed_type_info)
return fixed_type_info->getFixedAlignment().getValue();
}
return 0;
}
lldb::Encoding SwiftASTContext::GetEncoding(void *type, uint64_t &count) {
VALID_OR_RETURN(lldb::eEncodingInvalid);
if (!type)
return lldb::eEncodingInvalid;
count = 1;
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Error:
break;
case swift::TypeKind::BuiltinInteger:
return lldb::eEncodingSint; // TODO: detect if an integer is unsigned
case swift::TypeKind::BuiltinFloat:
return lldb::eEncodingIEEE754; // TODO: detect if an integer is unsigned
case swift::TypeKind::Archetype:
case swift::TypeKind::BuiltinRawPointer:
case swift::TypeKind::BuiltinNativeObject:
case swift::TypeKind::BuiltinUnsafeValueBuffer:
case swift::TypeKind::BuiltinUnknownObject:
case swift::TypeKind::BuiltinBridgeObject:
case swift::TypeKind::Class: // Classes are pointers in swift...
case swift::TypeKind::BoundGenericClass:
return lldb::eEncodingUint;
case swift::TypeKind::BuiltinVector:
break;
case swift::TypeKind::Tuple:
break;
case swift::TypeKind::UnmanagedStorage:
case swift::TypeKind::UnownedStorage:
case swift::TypeKind::WeakStorage:
return CompilerType(GetASTContext(),
swift_can_type->getReferenceStorageReferent())
.GetEncoding(count);
case swift::TypeKind::GenericTypeParam:
case swift::TypeKind::DependentMember:
break;
case swift::TypeKind::ExistentialMetatype:
case swift::TypeKind::Metatype:
return lldb::eEncodingUint;
case swift::TypeKind::GenericFunction:
case swift::TypeKind::Function:
return lldb::eEncodingUint;
case swift::TypeKind::Enum:
case swift::TypeKind::BoundGenericEnum:
break;
case swift::TypeKind::Struct:
case swift::TypeKind::Protocol:
case swift::TypeKind::Module:
case swift::TypeKind::ProtocolComposition:
break;
case swift::TypeKind::LValue:
return lldb::eEncodingUint;
case swift::TypeKind::UnboundGeneric:
case swift::TypeKind::BoundGenericStruct:
case swift::TypeKind::TypeVariable:
case swift::TypeKind::DynamicSelf:
case swift::TypeKind::SILBox:
case swift::TypeKind::SILFunction:
case swift::TypeKind::SILBlockStorage:
case swift::TypeKind::InOut:
case swift::TypeKind::Unresolved:
break;
case swift::TypeKind::Optional:
case swift::TypeKind::NameAlias:
case swift::TypeKind::Paren:
case swift::TypeKind::Dictionary:
case swift::TypeKind::ArraySlice:
assert(false && "Not a canonical type");
break;
}
count = 0;
return lldb::eEncodingInvalid;
}
lldb::Format SwiftASTContext::GetFormat(void *type) {
VALID_OR_RETURN(lldb::eFormatInvalid);
if (!type)
return lldb::eFormatDefault;
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Error:
break;
case swift::TypeKind::BuiltinInteger:
return eFormatDecimal; // TODO: detect if an integer is unsigned
case swift::TypeKind::BuiltinFloat:
return eFormatFloat; // TODO: detect if an integer is unsigned
case swift::TypeKind::BuiltinRawPointer:
case swift::TypeKind::BuiltinNativeObject:
case swift::TypeKind::BuiltinUnknownObject:
case swift::TypeKind::BuiltinUnsafeValueBuffer:
case swift::TypeKind::BuiltinBridgeObject:
case swift::TypeKind::Archetype:
return eFormatAddressInfo;
// Classes are always pointers in swift...
case swift::TypeKind::Class:
case swift::TypeKind::BoundGenericClass:
return eFormatHex;
case swift::TypeKind::BuiltinVector:
break;
case swift::TypeKind::Tuple:
break;
case swift::TypeKind::UnmanagedStorage:
case swift::TypeKind::UnownedStorage:
case swift::TypeKind::WeakStorage:
return CompilerType(GetASTContext(),
swift_can_type->getReferenceStorageReferent())
.GetFormat();
case swift::TypeKind::GenericTypeParam:
case swift::TypeKind::DependentMember:
break;
case swift::TypeKind::Enum:
case swift::TypeKind::BoundGenericEnum:
return eFormatUnsigned;
case swift::TypeKind::GenericFunction:
case swift::TypeKind::Function:
return lldb::eFormatAddressInfo;
case swift::TypeKind::Struct:
case swift::TypeKind::Protocol:
case swift::TypeKind::Metatype:
case swift::TypeKind::Module:
case swift::TypeKind::ProtocolComposition:
break;
case swift::TypeKind::LValue:
return lldb::eFormatHex;
case swift::TypeKind::UnboundGeneric:
case swift::TypeKind::BoundGenericStruct:
case swift::TypeKind::TypeVariable:
case swift::TypeKind::ExistentialMetatype:
case swift::TypeKind::DynamicSelf:
case swift::TypeKind::SILBox:
case swift::TypeKind::SILFunction:
case swift::TypeKind::SILBlockStorage:
case swift::TypeKind::InOut:
case swift::TypeKind::Unresolved:
break;
case swift::TypeKind::Optional:
case swift::TypeKind::NameAlias:
case swift::TypeKind::Paren:
case swift::TypeKind::Dictionary:
case swift::TypeKind::ArraySlice:
assert(false && "Not a canonical type");
break;
}
// We don't know hot to display this type...
return lldb::eFormatBytes;
}
uint32_t SwiftASTContext::GetNumChildren(void *type,
bool omit_empty_base_classes) {
VALID_OR_RETURN(0);
if (!type)
return 0;
uint32_t num_children = 0;
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Error:
case swift::TypeKind::BuiltinInteger:
case swift::TypeKind::BuiltinFloat:
case swift::TypeKind::BuiltinRawPointer:
case swift::TypeKind::BuiltinNativeObject:
case swift::TypeKind::BuiltinUnknownObject:
case swift::TypeKind::BuiltinUnsafeValueBuffer:
case swift::TypeKind::BuiltinBridgeObject:
case swift::TypeKind::BuiltinVector:
case swift::TypeKind::Module:
case swift::TypeKind::Function:
case swift::TypeKind::GenericFunction:
case swift::TypeKind::DynamicSelf:
case swift::TypeKind::SILBox:
case swift::TypeKind::SILFunction:
case swift::TypeKind::InOut:
break;
case swift::TypeKind::UnmanagedStorage:
case swift::TypeKind::UnownedStorage:
case swift::TypeKind::WeakStorage:
return CompilerType(GetASTContext(),
swift_can_type->getReferenceStorageReferent())
.GetNumChildren(omit_empty_base_classes);
case swift::TypeKind::GenericTypeParam:
case swift::TypeKind::DependentMember:
break;
case swift::TypeKind::Enum:
case swift::TypeKind::BoundGenericEnum: {
SwiftEnumDescriptor *cached_enum_info = GetCachedEnumInfo(type);
if (cached_enum_info)
return cached_enum_info->GetNumElementsWithPayload();
} break;
case swift::TypeKind::Tuple:
case swift::TypeKind::Struct:
case swift::TypeKind::Class:
case swift::TypeKind::BoundGenericClass:
case swift::TypeKind::BoundGenericStruct:
case swift::TypeKind::Protocol:
case swift::TypeKind::ProtocolComposition:
case swift::TypeKind::Archetype: {
CachedMemberInfo *cached_member_info = GetCachedMemberInfo(type);
if (cached_member_info)
return cached_member_info->member_infos.size();
} break;
case swift::TypeKind::ExistentialMetatype:
case swift::TypeKind::Metatype:
return 0;
case swift::TypeKind::LValue: {
swift::LValueType *lvalue_type = swift_can_type->castTo<swift::LValueType>();
swift::TypeBase *deref_type = lvalue_type->getObjectType().getPointer();
uint32_t num_pointee_children =
CompilerType(GetASTContext(), deref_type)
.GetNumChildren(omit_empty_base_classes);
// If this type points to a simple type (or to a class), then it has 1 child
if (num_pointee_children == 0 || deref_type->getClassOrBoundGenericClass())
num_children = 1;
else
num_children = num_pointee_children;
} break;
case swift::TypeKind::UnboundGeneric:
break;
case swift::TypeKind::TypeVariable:
break;
case swift::TypeKind::SILBlockStorage:
case swift::TypeKind::Unresolved:
break;
case swift::TypeKind::Optional:
case swift::TypeKind::NameAlias:
case swift::TypeKind::Paren:
case swift::TypeKind::Dictionary:
case swift::TypeKind::ArraySlice:
assert(false && "Not a canonical type");
break;
}
return num_children;
}
lldb::BasicType SwiftASTContext::GetBasicTypeEnumeration(void *type) {
return eBasicTypeInvalid;
}
#pragma mark Aggregate Types
uint32_t SwiftASTContext::GetNumDirectBaseClasses(void *opaque_type) {
if (!opaque_type)
return 0;
swift::CanType swift_can_type(GetCanonicalSwiftType(opaque_type));
swift::ClassDecl *class_decl = swift_can_type->getClassOrBoundGenericClass();
if (class_decl) {
if (class_decl->hasSuperclass())
return 1;
}
return 0;
}
uint32_t SwiftASTContext::GetNumVirtualBaseClasses(void *opaque_type) {
return 0;
}
uint32_t SwiftASTContext::GetNumFields(void *type) {
VALID_OR_RETURN(0);
if (!type)
return 0;
uint32_t count = 0;
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Error:
case swift::TypeKind::BuiltinInteger:
case swift::TypeKind::BuiltinFloat:
case swift::TypeKind::BuiltinRawPointer:
case swift::TypeKind::BuiltinNativeObject:
case swift::TypeKind::BuiltinUnknownObject:
case swift::TypeKind::BuiltinUnsafeValueBuffer:
case swift::TypeKind::BuiltinBridgeObject:
case swift::TypeKind::BuiltinVector:
break;
case swift::TypeKind::UnmanagedStorage:
case swift::TypeKind::UnownedStorage:
case swift::TypeKind::WeakStorage:
return CompilerType(GetASTContext(),
swift_can_type->getReferenceStorageReferent())
.GetNumFields();
case swift::TypeKind::GenericTypeParam:
case swift::TypeKind::DependentMember:
break;
case swift::TypeKind::Enum:
case swift::TypeKind::BoundGenericEnum: {
SwiftEnumDescriptor *cached_enum_info = GetCachedEnumInfo(type);
if (cached_enum_info)
return cached_enum_info->GetNumElementsWithPayload();
} break;
case swift::TypeKind::Tuple:
case swift::TypeKind::Struct:
case swift::TypeKind::Class:
case swift::TypeKind::Protocol:
case swift::TypeKind::ProtocolComposition:
case swift::TypeKind::BoundGenericClass:
case swift::TypeKind::BoundGenericStruct: {
CachedMemberInfo *cached_member_info = GetCachedMemberInfo(type);
if (cached_member_info) {
const size_t num_members = cached_member_info->member_infos.size();
if (num_members > 0 &&
cached_member_info->member_infos.front().member_type ==
MemberType::BaseClass)
return num_members - 1;
else
return num_members;
}
} break;
case swift::TypeKind::ExistentialMetatype:
case swift::TypeKind::Metatype:
return 0;
case swift::TypeKind::Module:
case swift::TypeKind::Archetype:
case swift::TypeKind::Function:
case swift::TypeKind::GenericFunction:
case swift::TypeKind::LValue:
case swift::TypeKind::UnboundGeneric:
case swift::TypeKind::TypeVariable:
case swift::TypeKind::DynamicSelf:
case swift::TypeKind::SILBox:
case swift::TypeKind::SILFunction:
case swift::TypeKind::SILBlockStorage:
case swift::TypeKind::InOut:
case swift::TypeKind::Unresolved:
break;
case swift::TypeKind::Optional:
case swift::TypeKind::NameAlias:
case swift::TypeKind::Paren:
case swift::TypeKind::Dictionary:
case swift::TypeKind::ArraySlice:
assert(false && "Not a canonical type");
break;
}
return count;
}
CompilerType
SwiftASTContext::GetDirectBaseClassAtIndex(void *opaque_type, size_t idx,
uint32_t *bit_offset_ptr) {
VALID_OR_RETURN(CompilerType());
if (opaque_type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(opaque_type));
swift::ClassDecl *class_decl =
swift_can_type->getClassOrBoundGenericClass();
if (class_decl) {
swift::Type base_class_type = class_decl->getSuperclass();
if (base_class_type)
return CompilerType(GetASTContext(), base_class_type.getPointer());
}
}
return CompilerType();
}
CompilerType
SwiftASTContext::GetVirtualBaseClassAtIndex(void *opaque_type, size_t idx,
uint32_t *bit_offset_ptr) {
return CompilerType();
}
CompilerType SwiftASTContext::GetFieldAtIndex(void *type, size_t idx,
std::string &name,
uint64_t *bit_offset_ptr,
uint32_t *bitfield_bit_size_ptr,
bool *is_bitfield_ptr) {
VALID_OR_RETURN(CompilerType());
if (!type)
return CompilerType();
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Error:
case swift::TypeKind::BuiltinInteger:
case swift::TypeKind::BuiltinFloat:
case swift::TypeKind::BuiltinRawPointer:
case swift::TypeKind::BuiltinNativeObject:
case swift::TypeKind::BuiltinUnsafeValueBuffer:
case swift::TypeKind::BuiltinUnknownObject:
case swift::TypeKind::BuiltinBridgeObject:
case swift::TypeKind::BuiltinVector:
break;
case swift::TypeKind::UnmanagedStorage:
case swift::TypeKind::UnownedStorage:
case swift::TypeKind::WeakStorage:
return CompilerType(GetASTContext(),
swift_can_type->getReferenceStorageReferent())
.GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr,
is_bitfield_ptr);
case swift::TypeKind::GenericTypeParam:
case swift::TypeKind::DependentMember:
break;
case swift::TypeKind::Enum:
case swift::TypeKind::BoundGenericEnum: {
SwiftEnumDescriptor *cached_enum_info = GetCachedEnumInfo(type);
if (cached_enum_info &&
idx < cached_enum_info->GetNumElementsWithPayload()) {
const SwiftEnumDescriptor::ElementInfo *enum_element_info =
cached_enum_info->GetElementWithPayloadAtIndex(idx);
name.assign(enum_element_info->name.GetCString());
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;
return enum_element_info->payload_type;
}
} break;
case swift::TypeKind::Tuple:
case swift::TypeKind::Struct:
case swift::TypeKind::Class:
case swift::TypeKind::Protocol:
case swift::TypeKind::ProtocolComposition:
case swift::TypeKind::BoundGenericClass:
case swift::TypeKind::BoundGenericStruct: {
CachedMemberInfo *cached_member_info = GetCachedMemberInfo(type);
if (cached_member_info) {
const size_t num_members = cached_member_info->member_infos.size();
uint32_t actual_idx = idx;
if (num_members > 0 &&
cached_member_info->member_infos.front().member_type ==
MemberType::BaseClass)
++actual_idx; // Skip base class since we are looking for fields only
if (actual_idx < num_members) {
if (cached_member_info->member_infos[actual_idx].name)
name = cached_member_info->member_infos[actual_idx].name.GetCString();
if (bit_offset_ptr)
*bit_offset_ptr =
cached_member_info->member_infos[actual_idx].byte_offset * 8;
if (bitfield_bit_size_ptr)
*bitfield_bit_size_ptr = 0;
if (is_bitfield_ptr)
*is_bitfield_ptr = false;
return cached_member_info->member_infos[actual_idx].clang_type;
}
}
} break;
case swift::TypeKind::ExistentialMetatype:
case swift::TypeKind::Metatype:
break;
case swift::TypeKind::Module:
case swift::TypeKind::Archetype:
case swift::TypeKind::Function:
case swift::TypeKind::GenericFunction:
case swift::TypeKind::LValue:
case swift::TypeKind::UnboundGeneric:
case swift::TypeKind::TypeVariable:
case swift::TypeKind::DynamicSelf:
case swift::TypeKind::SILBox:
case swift::TypeKind::SILFunction:
case swift::TypeKind::SILBlockStorage:
case swift::TypeKind::InOut:
case swift::TypeKind::Unresolved:
break;
case swift::TypeKind::Optional:
case swift::TypeKind::NameAlias:
case swift::TypeKind::Paren:
case swift::TypeKind::Dictionary:
case swift::TypeKind::ArraySlice:
assert(false && "Not a canonical type");
break;
}
return CompilerType();
}
// If a pointer to a pointee type (the clang_type arg) says that it has no
// children, then we either need to trust it, or override it and return a
// different result. For example, an "int *" has one child that is an integer,
// but a function pointer doesn't have any children. Likewise if a Record type
// claims it has no children, then there really is nothing to show.
uint32_t SwiftASTContext::GetNumPointeeChildren(void *type) {
if (!type)
return 0;
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Error:
return 0;
case swift::TypeKind::BuiltinInteger:
return 1;
case swift::TypeKind::BuiltinFloat:
return 1;
case swift::TypeKind::BuiltinRawPointer:
return 1;
case swift::TypeKind::BuiltinUnsafeValueBuffer:
return 1;
case swift::TypeKind::BuiltinNativeObject:
return 1;
case swift::TypeKind::BuiltinUnknownObject:
return 1;
case swift::TypeKind::BuiltinBridgeObject:
return 1;
case swift::TypeKind::BuiltinVector:
return 0;
case swift::TypeKind::UnmanagedStorage:
case swift::TypeKind::UnownedStorage:
case swift::TypeKind::WeakStorage:
return GetNumPointeeChildren(
swift::cast<swift::ReferenceStorageType>(swift_can_type)
.getPointer());
case swift::TypeKind::Tuple:
return 0;
case swift::TypeKind::GenericTypeParam:
return 0;
case swift::TypeKind::DependentMember:
return 0;
case swift::TypeKind::Enum:
return 0;
case swift::TypeKind::Struct:
return 0;
case swift::TypeKind::Class:
return 0;
case swift::TypeKind::Protocol:
return 0;
case swift::TypeKind::Metatype:
return 0;
case swift::TypeKind::Module:
return 0;
case swift::TypeKind::Archetype:
return 0;
case swift::TypeKind::Function:
return 0;
case swift::TypeKind::GenericFunction:
return 0;
case swift::TypeKind::ProtocolComposition:
return 0;
case swift::TypeKind::LValue:
return 1;
case swift::TypeKind::UnboundGeneric:
return 0;
case swift::TypeKind::BoundGenericClass:
return 0;
case swift::TypeKind::BoundGenericEnum:
return 0;
case swift::TypeKind::BoundGenericStruct:
return 0;
case swift::TypeKind::TypeVariable:
return 0;
case swift::TypeKind::ExistentialMetatype:
return 0;
case swift::TypeKind::DynamicSelf:
return 0;
case swift::TypeKind::SILBox:
return 0;
case swift::TypeKind::SILFunction:
return 0;
case swift::TypeKind::SILBlockStorage:
return 0;
case swift::TypeKind::InOut:
return 0;
case swift::TypeKind::Unresolved:
return 0;
case swift::TypeKind::Optional:
case swift::TypeKind::NameAlias:
case swift::TypeKind::Paren:
case swift::TypeKind::Dictionary:
case swift::TypeKind::ArraySlice:
assert(false && "Not a canonical type");
break;
}
return 0;
}
static int64_t GetInstanceVariableOffset_Symbol(ExecutionContext *exe_ctx,
const CompilerType &type,
const char *ivar_name,
const CompilerType &ivar_type) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
ConstString class_name(type.GetTypeSymbolName());
Target *target = exe_ctx->GetTargetPtr();
if (log)
log->Printf("[GetInstanceVariableOffset_Symbol] ivar_name = %s, type = %s "
"class_name = %s",
ivar_name, type.GetTypeName().AsCString(),
class_name.AsCString());
if (target && class_name && ivar_type.IsValid() && ivar_name) {
swift::NominalTypeDecl *nominal_decl =
GetSwiftType(type)->getNominalOrBoundGenericNominal();
if (nominal_decl) {
swift::ValueDecl *the_value_decl = nullptr;
SwiftASTContext *swift_ast_ctx =
llvm::dyn_cast_or_null<SwiftASTContext>(type.GetTypeSystem());
auto decls = nominal_decl->lookupDirect(swift::DeclName(
swift_ast_ctx->GetASTContext()->getIdentifier(ivar_name)));
for (auto &decl : decls) {
swift::VarDecl *var_decl = llvm::dyn_cast_or_null<swift::VarDecl>(decl);
if (var_decl && var_decl->hasStorage()) {
the_value_decl = var_decl;
break;
}
}
if (the_value_decl) {
swift::irgen::IRGenMangler mangler;
std::string buffer = mangler.mangleFieldOffset(the_value_decl);
StreamString symbol_name;
symbol_name.Printf("%s", buffer.c_str());
ConstString ivar_const_str(symbol_name.GetString());
lldb::addr_t ivar_offset_ptr =
target->FindLoadAddrForNameInSymbolsAndPersistentVariables(
ivar_const_str, eSymbolTypeIVarOffset);
if (log)
log->Printf("[GetInstanceVariableOffset_Symbol] symbol_name = %s "
"ivar_offset_ptr = 0x%" PRIx64,
ivar_const_str.AsCString(), ivar_offset_ptr);
if (ivar_offset_ptr != LLDB_INVALID_ADDRESS) {
Status error;
return target->ReadUnsignedIntegerFromMemory(
ivar_offset_ptr,
false, // prefer_file_cache
type.GetPointerByteSize(), // byte size of integer to read
LLDB_INVALID_IVAR_OFFSET, error);
}
} else if (log)
log->Printf("[GetInstanceVariableOffset_Symbol] no the_value_decl");
} else if (log)
log->Printf("[GetInstanceVariableOffset_Symbol] no nominal_decl");
}
return LLDB_INVALID_IVAR_OFFSET;
}
static int64_t GetInstanceVariableOffset_Metadata(
ValueObject *valobj, ExecutionContext *exe_ctx, const CompilerType &type,
ConstString ivar_name, const CompilerType &ivar_type) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
if (log)
log->Printf(
"[GetInstanceVariableOffset_Metadata] ivar_name = %s, type = %s",
ivar_name.AsCString(), type.GetTypeName().AsCString());
Process *process = exe_ctx->GetProcessPtr();
if (process) {
SwiftLanguageRuntime *runtime = process->GetSwiftLanguageRuntime();
if (runtime) {
if (auto resolver_sp = runtime->GetMemberVariableOffsetResolver(type)) {
Status error;
if (auto result = resolver_sp->ResolveOffset(valobj, ivar_name, &error))
{
if (log)
log->Printf("[GetInstanceVariableOffset_Metadata] for %s: %llu",
ivar_name.AsCString(), result.getValue());
return result.getValue();
}
else if (log)
log->Printf(
"[GetInstanceVariableOffset_Metadata] resolver failure: %s",
error.AsCString());
} else if (log)
log->Printf("[GetInstanceVariableOffset_Metadata] no offset resolver");
} else if (log)
log->Printf("[GetInstanceVariableOffset_Metadata] no runtime");
} else if (log)
log->Printf("[GetInstanceVariableOffset_Metadata] no process");
return LLDB_INVALID_IVAR_OFFSET;
}
static int64_t GetInstanceVariableOffset(ValueObject *valobj,
ExecutionContext *exe_ctx,
const CompilerType &class_type,
const char *ivar_name,
const CompilerType &ivar_type) {
int64_t offset = LLDB_INVALID_IVAR_OFFSET;
if (ivar_name && ivar_name[0]) {
if (exe_ctx) {
Target *target = exe_ctx->GetTargetPtr();
if (target) {
// Given a type there are three cases:
// non generic type - field offset symbols are emitted
// generic type:
// iVar offsets depend on the type arguments - no field offsets
// emitted
// iVar offsets do not depend on the type arguments - field offsets
// emitted for the *unbound* type
bool is_generic = (class_type.GetTypeInfo() & eTypeIsGeneric);
bool try_symbol = false;
bool try_metadata = true;
if (!is_generic)
try_symbol = true;
if (try_symbol) {
offset = GetInstanceVariableOffset_Symbol(exe_ctx, class_type,
ivar_name, ivar_type);
if (offset != LLDB_INVALID_IVAR_OFFSET)
return offset;
}
if (try_metadata) {
offset = GetInstanceVariableOffset_Symbol(exe_ctx, class_type,
ivar_name, ivar_type);
if (offset == LLDB_INVALID_IVAR_OFFSET)
offset = GetInstanceVariableOffset_Metadata(
valobj, exe_ctx, class_type, ConstString(ivar_name), ivar_type);
}
}
}
}
return offset;
}
bool SwiftASTContext::IsNonTriviallyManagedReferenceType(
const CompilerType &type, NonTriviallyManagedReferenceStrategy &strategy,
CompilerType *underlying_type) {
if (auto ast =
llvm::dyn_cast_or_null<SwiftASTContext>(type.GetTypeSystem())) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
default:
break;
case swift::TypeKind::UnmanagedStorage: {
strategy = NonTriviallyManagedReferenceStrategy::eUnmanaged;
if (underlying_type)
*underlying_type = CompilerType(
ast, swift_can_type->getReferenceStorageReferent()
.getPointer());
}
return true;
case swift::TypeKind::UnownedStorage: {
strategy = NonTriviallyManagedReferenceStrategy::eUnowned;
if (underlying_type)
*underlying_type = CompilerType(
ast, swift_can_type->getReferenceStorageReferent()
.getPointer());
}
return true;
case swift::TypeKind::WeakStorage: {
strategy = NonTriviallyManagedReferenceStrategy::eWeak;
if (underlying_type)
*underlying_type = CompilerType(
ast, swift_can_type->getReferenceStorageReferent()
.getPointer());
}
return true;
}
}
return false;
}
CompilerType SwiftASTContext::GetChildCompilerTypeAtIndex(
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, uint64_t &language_flags) {
VALID_OR_RETURN(CompilerType());
if (!type)
return CompilerType();
language_flags = 0;
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Error:
case swift::TypeKind::BuiltinInteger:
case swift::TypeKind::BuiltinFloat:
case swift::TypeKind::BuiltinRawPointer:
case swift::TypeKind::BuiltinNativeObject:
case swift::TypeKind::BuiltinUnknownObject:
case swift::TypeKind::BuiltinUnsafeValueBuffer:
case swift::TypeKind::BuiltinBridgeObject:
case swift::TypeKind::BuiltinVector:
// case swift::TypeKind::Tuple:
// {
// swift::TupleType *tuple_type =
// swift_can_type->getAs<swift::TupleType>();
// if (tuple_type && idx < tuple_type->getNumElements())
// {
// child_byte_offset = 0; // TODO: figure out how to
// get byte offset of tuple field...
// child_bitfield_bit_size = 0;
// child_bitfield_bit_offset = 0;
// child_is_base_class = false;
// child_is_deref_of_parent = false;
//
// uint32_t tuple_idx = 0;
// for (auto tuple_field : tuple_type->getFields())
// {
// CompilerType tuple_field_type(m_swift_ast,
// tuple_field.getType().getPointer());
// auto tuple_field_byte_size =
// tuple_field_type.GetByteSize();
//
// if (tuple_idx == idx)
// {
// child_byte_size = tuple_field_byte_size;
// const char *tuple_name =
// tuple_field.getName().get();
// if (tuple_name)
// {
// child_name = tuple_name;
// }
// else
// {
// StreamString tuple_name_strm;
// tuple_name_strm.Printf("%u",
// (uint32_t)idx);
// child_name =
// std::move(tuple_name_strm.GetString());
// }
// return tuple_field_type;
// }
// else
// {
// const uint64_t tuple_field_bit_size =
// tuple_field_byte_size * 8;
// const uint64_t tuple_aligned_bit_size =
// tuple_field_type.GetAlignedBitSize();
// child_byte_offset +=
// llvm::RoundUpToAlignment(tuple_field_bit_size,
// tuple_aligned_bit_size) / 8;
// ++tuple_idx;
// }
// }
// }
// }
// break;
case swift::TypeKind::UnmanagedStorage:
case swift::TypeKind::UnownedStorage:
case swift::TypeKind::WeakStorage:
return CompilerType(GetASTContext(),
swift_can_type->getReferenceStorageReferent())
.GetChildCompilerTypeAtIndex(
exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
child_bitfield_bit_size, child_bitfield_bit_offset,
child_is_base_class, child_is_deref_of_parent, valobj,
language_flags);
case swift::TypeKind::GenericTypeParam:
case swift::TypeKind::DependentMember:
break;
case swift::TypeKind::Enum:
case swift::TypeKind::BoundGenericEnum: {
SwiftEnumDescriptor *cached_enum_info = GetCachedEnumInfo(type);
if (cached_enum_info &&
idx < cached_enum_info->GetNumElementsWithPayload()) {
const SwiftEnumDescriptor::ElementInfo *element_info =
cached_enum_info->GetElementWithPayloadAtIndex(idx);
child_name.assign(element_info->name.GetCString());
child_byte_size = element_info->payload_type.GetByteSize(
exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
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 (element_info->is_indirect) {
language_flags |= LanguageFlags::eIsIndirectEnumCase;
return CompilerType(GetASTContext(),
GetASTContext()->TheRawPointerType.getPointer());
} else
return element_info->payload_type;
}
} break;
case swift::TypeKind::Tuple:
case swift::TypeKind::Struct:
case swift::TypeKind::Class:
case swift::TypeKind::BoundGenericClass:
case swift::TypeKind::BoundGenericStruct:
case swift::TypeKind::Protocol:
case swift::TypeKind::ProtocolComposition: {
CachedMemberInfo *cached_member_info = GetCachedMemberInfo(type);
if (cached_member_info) {
const size_t num_members = cached_member_info->member_infos.size();
if (idx < num_members) {
if (cached_member_info->member_infos[idx].name)
child_name = cached_member_info->member_infos[idx].name.GetCString();
else
child_name.clear();
child_byte_size = cached_member_info->member_infos[idx].byte_size;
// Check for fragile ivar offsets and look them up and cache them.
if (cached_member_info->member_infos[idx].is_fragile &&
cached_member_info->member_infos[idx].byte_offset == 0) {
CompilerType compiler_type(GetASTContext(), GetSwiftType(type));
const int64_t fragile_ivar_offset = GetInstanceVariableOffset(
valobj, exe_ctx, compiler_type, child_name.c_str(),
cached_member_info->member_infos[idx].clang_type);
if (fragile_ivar_offset != LLDB_INVALID_IVAR_OFFSET)
cached_member_info->member_infos[idx].byte_offset =
fragile_ivar_offset;
}
child_byte_offset = cached_member_info->member_infos[idx].byte_offset;
child_bitfield_bit_size = 0;
child_bitfield_bit_offset = 0;
if ((child_is_base_class =
cached_member_info->member_infos[idx].member_type ==
MemberType::BaseClass)) {
language_flags |= LanguageFlags::eIgnoreInstancePointerness;
}
child_is_deref_of_parent = false;
return cached_member_info->member_infos[idx].clang_type;
}
}
} break;
case swift::TypeKind::ExistentialMetatype:
case swift::TypeKind::Metatype:
break;
case swift::TypeKind::Module:
case swift::TypeKind::Archetype:
case swift::TypeKind::Function:
case swift::TypeKind::GenericFunction:
break;
case swift::TypeKind::LValue:
if (idx < GetNumChildren(type, omit_empty_base_classes)) {
CompilerType pointee_clang_type(GetNonReferenceType(type));
Flags pointee_clang_type_flags(pointee_clang_type.GetTypeInfo());
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 a simple type
if (idx == 0) {
child_byte_size = pointee_clang_type.GetByteSize(
exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
child_byte_offset = 0;
return pointee_clang_type;
}
}
break;
case swift::TypeKind::UnboundGeneric:
break;
case swift::TypeKind::TypeVariable:
break;
case swift::TypeKind::DynamicSelf:
case swift::TypeKind::SILBox:
case swift::TypeKind::SILFunction:
case swift::TypeKind::SILBlockStorage:
case swift::TypeKind::InOut:
case swift::TypeKind::Unresolved:
break;
case swift::TypeKind::Optional:
case swift::TypeKind::NameAlias:
case swift::TypeKind::Paren:
case swift::TypeKind::Dictionary:
case swift::TypeKind::ArraySlice:
assert(false && "Not a canonical type");
break;
}
return CompilerType();
}
// Look for a child member (doesn't include base classes, but it does include
// their members) in the type hierarchy. Returns an index path into "clang_type"
// on how to reach the appropriate member.
//
// class A
// {
// public:
// int m_a;
// int m_b;
// };
//
// class B
// {
// };
//
// class C :
// public B,
// public A
// {
// };
//
// If we have a clang type that describes "class C", and we wanted to look for
// "m_b" in it:
//
// With omit_empty_base_classes == false we would get an integer array back
// with:
// { 1, 1 }
// The first index 1 is the child index for "class A" within class C.
// The second index 1 is the child index for "m_b" within class A.
//
// With omit_empty_base_classes == true we would get an integer array back with:
// { 0, 1 }
// The first index 0 is the child index for "class A" within class C (since
// class B doesn't have any members it doesn't count).
// The second index 1 is the child index for "m_b" within class A.
size_t SwiftASTContext::GetIndexOfChildMemberWithName(
void *type, const char *name, bool omit_empty_base_classes,
std::vector<uint32_t> &child_indexes) {
VALID_OR_RETURN(0);
if (type && name && name[0]) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Error:
case swift::TypeKind::BuiltinInteger:
case swift::TypeKind::BuiltinFloat:
case swift::TypeKind::BuiltinRawPointer:
case swift::TypeKind::BuiltinNativeObject:
case swift::TypeKind::BuiltinUnknownObject:
case swift::TypeKind::BuiltinUnsafeValueBuffer:
case swift::TypeKind::BuiltinBridgeObject:
case swift::TypeKind::BuiltinVector:
break;
case swift::TypeKind::UnmanagedStorage:
case swift::TypeKind::UnownedStorage:
case swift::TypeKind::WeakStorage:
return CompilerType(GetASTContext(),
swift_can_type->getReferenceStorageReferent())
.GetIndexOfChildMemberWithName(name, omit_empty_base_classes,
child_indexes);
case swift::TypeKind::GenericTypeParam:
case swift::TypeKind::DependentMember:
break;
case swift::TypeKind::Enum:
case swift::TypeKind::BoundGenericEnum: {
SwiftEnumDescriptor *cached_enum_info = GetCachedEnumInfo(type);
if (cached_enum_info) {
ConstString const_name(name);
const size_t num_sized_elements =
cached_enum_info->GetNumElementsWithPayload();
for (size_t i = 0; i < num_sized_elements; ++i) {
if (cached_enum_info->GetElementWithPayloadAtIndex(i)->name ==
const_name) {
child_indexes.push_back(i);
return child_indexes.size();
}
}
}
} break;
case swift::TypeKind::Tuple: {
// For tuples only always look for the member by number first as a tuple
// element can be named, yet still be accessed by the number...
swift::TupleType *tuple_type = swift_can_type->castTo<swift::TupleType>();
uint32_t tuple_idx = StringConvert::ToUInt32(name, UINT32_MAX);
if (tuple_idx != UINT32_MAX) {
if (tuple_idx < tuple_type->getNumElements()) {
child_indexes.push_back(tuple_idx);
return child_indexes.size();
} else
return 0;
}
}
// Fall through to class/union/struct case...
case swift::TypeKind::Struct:
case swift::TypeKind::Class:
case swift::TypeKind::Protocol:
case swift::TypeKind::ProtocolComposition:
case swift::TypeKind::BoundGenericClass:
case swift::TypeKind::BoundGenericStruct: {
CachedMemberInfo *cached_member_info = GetCachedMemberInfo(type);
if (cached_member_info) {
ConstString const_name(name);
const size_t num_members = cached_member_info->member_infos.size();
if (num_members > 0) {
for (size_t i = 0; i < num_members; ++i) {
const MemberInfo &member_info = cached_member_info->member_infos[i];
if (member_info.name &&
member_info.member_type != MemberType::BaseClass) {
if (const_name == member_info.name) {
child_indexes.push_back(i);
return child_indexes.size();
}
}
}
// Check the base class if we have one...
if (cached_member_info->member_infos[0].member_type ==
MemberType::BaseClass) {
// Push index zero for the base class
child_indexes.push_back(0);
if (cached_member_info->member_infos[0]
.clang_type.GetIndexOfChildMemberWithName(
name, omit_empty_base_classes, child_indexes)) {
// We did find an ivar in a superclass so just
// return the results!
return child_indexes.size();
}
// We didn't find an ivar matching "name" in our
// superclass, pop the superclass zero index that
// we pushed on above.
child_indexes.pop_back();
}
}
}
} break;
case swift::TypeKind::ExistentialMetatype:
case swift::TypeKind::Metatype:
break;
case swift::TypeKind::Module:
case swift::TypeKind::Archetype:
case swift::TypeKind::Function:
case swift::TypeKind::GenericFunction:
break;
case swift::TypeKind::InOut:
case swift::TypeKind::LValue: {
CompilerType pointee_clang_type(GetNonReferenceType(type));
if (pointee_clang_type.IsAggregateType()) {
return pointee_clang_type.GetIndexOfChildMemberWithName(
name, omit_empty_base_classes, child_indexes);
}
} break;
case swift::TypeKind::UnboundGeneric:
break;
case swift::TypeKind::TypeVariable:
break;
case swift::TypeKind::DynamicSelf:
case swift::TypeKind::SILBox:
case swift::TypeKind::SILFunction:
case swift::TypeKind::SILBlockStorage:
case swift::TypeKind::Unresolved:
break;
case swift::TypeKind::Optional:
case swift::TypeKind::NameAlias:
case swift::TypeKind::Paren:
case swift::TypeKind::Dictionary:
case swift::TypeKind::ArraySlice:
assert(false && "Not a canonical type");
break;
}
}
return 0;
}
// Get the index of the child of "clang_type" whose name matches. This function
// doesn't descend into the children, but only looks one level deep and name
// matches can include base class names.
uint32_t
SwiftASTContext::GetIndexOfChildWithName(void *type, const char *name,
bool omit_empty_base_classes) {
VALID_OR_RETURN(UINT32_MAX);
if (type && name && name[0]) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Error:
case swift::TypeKind::BuiltinInteger:
case swift::TypeKind::BuiltinFloat:
case swift::TypeKind::BuiltinRawPointer:
case swift::TypeKind::BuiltinNativeObject:
case swift::TypeKind::BuiltinUnsafeValueBuffer:
case swift::TypeKind::BuiltinUnknownObject:
case swift::TypeKind::BuiltinBridgeObject:
case swift::TypeKind::BuiltinVector:
break;
case swift::TypeKind::UnmanagedStorage:
case swift::TypeKind::UnownedStorage:
case swift::TypeKind::WeakStorage:
return CompilerType(GetASTContext(),
swift_can_type->getReferenceStorageReferent())
.GetIndexOfChildWithName(name, omit_empty_base_classes);
case swift::TypeKind::GenericTypeParam:
case swift::TypeKind::DependentMember:
break;
case swift::TypeKind::Enum:
case swift::TypeKind::BoundGenericEnum: {
SwiftEnumDescriptor *cached_enum_info = GetCachedEnumInfo(type);
if (cached_enum_info) {
ConstString const_name(name);
const size_t num_sized_elements =
cached_enum_info->GetNumElementsWithPayload();
for (size_t i = 0; i < num_sized_elements; ++i) {
if (cached_enum_info->GetElementWithPayloadAtIndex(i)->name ==
const_name)
return i;
}
}
} break;
case swift::TypeKind::Tuple: {
swift::TupleType *tuple_type = swift_can_type->castTo<swift::TupleType>();
uint32_t tuple_idx = StringConvert::ToUInt32(name, UINT32_MAX);
if (tuple_idx != UINT32_MAX) {
if (tuple_idx < tuple_type->getNumElements())
return tuple_idx;
}
}
// Fall through to struct/union/class case...
case swift::TypeKind::Struct:
case swift::TypeKind::Class:
case swift::TypeKind::Protocol:
case swift::TypeKind::ProtocolComposition:
case swift::TypeKind::BoundGenericClass:
case swift::TypeKind::BoundGenericStruct: {
CachedMemberInfo *cached_member_info = GetCachedMemberInfo(type);
if (cached_member_info) {
ConstString const_name(name);
const size_t num_members = cached_member_info->member_infos.size();
if (num_members > 0) {
for (size_t i = 0; i < num_members; ++i) {
const MemberInfo &member_info = cached_member_info->member_infos[i];
if (member_info.name &&
member_info.member_type != MemberType::BaseClass) {
if (const_name == member_info.name)
return i;
}
}
// Check the base class name if we have one...
if (cached_member_info->member_infos[0].member_type ==
MemberType::BaseClass &&
cached_member_info->member_infos[0].name == const_name) {
return 0;
}
}
}
}
break;
case swift::TypeKind::ExistentialMetatype:
case swift::TypeKind::Metatype:
break;
case swift::TypeKind::Module:
case swift::TypeKind::Archetype:
case swift::TypeKind::Function:
case swift::TypeKind::GenericFunction:
break;
case swift::TypeKind::InOut:
case swift::TypeKind::LValue: {
CompilerType pointee_type(GetNonReferenceType(type));
if (pointee_type.IsAggregateType()) {
return pointee_type.GetIndexOfChildWithName(name,
omit_empty_base_classes);
}
} break;
case swift::TypeKind::UnboundGeneric:
break;
case swift::TypeKind::TypeVariable:
break;
case swift::TypeKind::DynamicSelf:
case swift::TypeKind::SILBox:
case swift::TypeKind::SILFunction:
case swift::TypeKind::SILBlockStorage:
case swift::TypeKind::Unresolved:
break;
case swift::TypeKind::Optional:
case swift::TypeKind::NameAlias:
case swift::TypeKind::Paren:
case swift::TypeKind::Dictionary:
case swift::TypeKind::ArraySlice:
assert(false && "Not a canonical type");
break;
}
}
return UINT32_MAX;
}
size_t SwiftASTContext::GetNumTemplateArguments(void *type) {
if (!type)
return 0;
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::UnboundGeneric: {
swift::UnboundGenericType *unbound_generic_type =
swift_can_type->castTo<swift::UnboundGenericType>();
auto *nominal_type_decl = unbound_generic_type->getDecl();
swift::GenericParamList *generic_param_list =
nominal_type_decl->getGenericParams();
return generic_param_list->getParams().size();
} break;
case swift::TypeKind::BoundGenericClass:
case swift::TypeKind::BoundGenericStruct:
case swift::TypeKind::BoundGenericEnum: {
swift::BoundGenericType *bound_generic_type =
swift_can_type->castTo<swift::BoundGenericType>();
return bound_generic_type->getGenericArgs().size();
}
default:
break;
}
return 0;
}
bool SwiftASTContext::GetSelectedEnumCase(const CompilerType &type,
const DataExtractor &data,
ConstString *name, bool *has_payload,
CompilerType *payload,
bool *is_indirect) {
if (auto ast =
llvm::dyn_cast_or_null<SwiftASTContext>(type.GetTypeSystem())) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
default:
break;
case swift::TypeKind::Enum:
case swift::TypeKind::BoundGenericEnum: {
SwiftEnumDescriptor *cached_enum_info =
ast->GetCachedEnumInfo(swift_can_type.getPointer());
if (cached_enum_info) {
auto enum_elem_info = cached_enum_info->GetElementFromData(data);
if (enum_elem_info) {
if (name)
*name = enum_elem_info->name;
if (has_payload)
*has_payload = enum_elem_info->has_payload;
if (payload)
*payload = enum_elem_info->payload_type;
if (is_indirect)
*is_indirect = enum_elem_info->is_indirect;
return true;
}
}
} break;
}
}
return false;
}
lldb::GenericKind SwiftASTContext::GetGenericArgumentKind(void *type,
size_t idx) {
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
if (auto *unbound_generic_type =
swift_can_type->getAs<swift::UnboundGenericType>())
return eUnboundGenericKindType;
if (auto *bound_generic_type =
swift_can_type->getAs<swift::BoundGenericType>())
if (idx < bound_generic_type->getGenericArgs().size())
return eBoundGenericKindType;
}
return eNullGenericKindType;
}
CompilerType SwiftASTContext::GetBoundGenericType(void *type, size_t idx) {
VALID_OR_RETURN(CompilerType());
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
if (auto *bound_generic_type =
swift_can_type->getAs<swift::BoundGenericType>())
if (idx < bound_generic_type->getGenericArgs().size())
return CompilerType(
GetASTContext(),
bound_generic_type->getGenericArgs()[idx].getPointer());
}
return CompilerType();
}
CompilerType SwiftASTContext::GetUnboundGenericType(void *type, size_t idx) {
VALID_OR_RETURN(CompilerType());
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
if (auto *unbound_generic_type =
swift_can_type->getAs<swift::UnboundGenericType>()) {
auto *nominal_type_decl = unbound_generic_type->getDecl();
swift::GenericSignature *generic_sig =
nominal_type_decl->getGenericSignature();
auto depTy = generic_sig->getGenericParams()[idx];
return CompilerType(GetASTContext(),
nominal_type_decl->mapTypeIntoContext(depTy)
->castTo<swift::ArchetypeType>());
}
}
return CompilerType();
}
CompilerType SwiftASTContext::GetGenericArgumentType(void *type, size_t idx) {
VALID_OR_RETURN(CompilerType());
switch (GetGenericArgumentKind(type, idx)) {
case eBoundGenericKindType:
return GetBoundGenericType(type, idx);
case eUnboundGenericKindType:
return GetUnboundGenericType(type, idx);
default:
break;
}
return CompilerType();
}
CompilerType SwiftASTContext::GetTypeForFormatters(void *type) {
VALID_OR_RETURN(CompilerType());
if (type) {
swift::Type swift_type(GetSwiftType(type));
return CompilerType(GetASTContext(), swift_type);
}
return CompilerType();
}
LazyBool SwiftASTContext::ShouldPrintAsOneLiner(void *type,
ValueObject *valobj) {
if (type) {
CompilerType can_compiler_type(GetCanonicalType(type));
if (IsImportedType(can_compiler_type, nullptr))
return eLazyBoolNo;
}
if (valobj) {
if (valobj->IsBaseClass())
return eLazyBoolNo;
if ((valobj->GetLanguageFlags() & LanguageFlags::eIsIndirectEnumCase) ==
LanguageFlags::eIsIndirectEnumCase)
return eLazyBoolNo;
}
return eLazyBoolCalculate;
}
bool SwiftASTContext::IsMeaninglessWithoutDynamicResolution(void *type) {
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Archetype:
return true;
default:
return false;
}
}
return false;
}
//----------------------------------------------------------------------
// Dumping types
//----------------------------------------------------------------------
#define DEPTH_INCREMENT 2
void SwiftASTContext::DumpValue(
void *type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format,
const lldb_private::DataExtractor &data, lldb::offset_t data_byte_offset,
size_t data_byte_size, uint32_t bitfield_bit_size,
uint32_t bitfield_bit_offset, bool show_types, bool show_summary,
bool verbose, uint32_t depth) {}
bool SwiftASTContext::DumpTypeValue(
void *type, Stream *s, lldb::Format format,
const lldb_private::DataExtractor &data, lldb::offset_t byte_offset,
size_t byte_size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
ExecutionContextScope *exe_scope, bool is_base_class) {
VALID_OR_RETURN(false);
if (!type)
return false;
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
const swift::TypeKind type_kind = swift_can_type->getKind();
switch (type_kind) {
case swift::TypeKind::Error:
break;
case swift::TypeKind::Class:
case swift::TypeKind::BoundGenericClass:
// If we have a class that is in a variable then it is a pointer,
// else if it is a base class, it has no value.
if (is_base_class)
break;
// Fall through to case below
case swift::TypeKind::BuiltinInteger:
case swift::TypeKind::BuiltinFloat:
case swift::TypeKind::BuiltinRawPointer:
case swift::TypeKind::BuiltinNativeObject:
case swift::TypeKind::BuiltinUnsafeValueBuffer:
case swift::TypeKind::BuiltinUnknownObject:
case swift::TypeKind::BuiltinBridgeObject:
case swift::TypeKind::Archetype:
case swift::TypeKind::Function:
case swift::TypeKind::GenericFunction:
case swift::TypeKind::LValue: {
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 eFormatAddressInfo:
if (byte_size == 0) {
byte_size = exe_scope->CalculateTarget()
->GetArchitecture()
.GetAddressByteSize();
item_count = 1;
}
break;
case eFormatChar:
case eFormatCharPrintable:
case eFormatCharArray:
case eFormatBytes:
case eFormatBytesWithASCII:
item_count = byte_size;
byte_size = 1;
break;
case eFormatUnicode16:
item_count = byte_size / 2;
byte_size = 2;
break;
case eFormatUnicode32:
item_count = byte_size / 4;
byte_size = 4;
break;
}
return DumpDataExtractor(data, s, byte_offset, format, byte_size, item_count, UINT32_MAX,
LLDB_INVALID_ADDRESS, bitfield_bit_size,
bitfield_bit_offset, exe_scope);
} break;
case swift::TypeKind::BuiltinVector:
break;
case swift::TypeKind::Tuple:
break;
case swift::TypeKind::UnmanagedStorage:
case swift::TypeKind::UnownedStorage:
case swift::TypeKind::WeakStorage:
return CompilerType(GetASTContext(),
swift_can_type->getReferenceStorageReferent())
.DumpTypeValue(s, format, data, byte_offset, byte_size,
bitfield_bit_size, bitfield_bit_offset, exe_scope,
is_base_class);
case swift::TypeKind::Enum:
case swift::TypeKind::BoundGenericEnum: {
SwiftEnumDescriptor *cached_enum_info = GetCachedEnumInfo(type);
if (cached_enum_info) {
auto enum_elem_info = cached_enum_info->GetElementFromData(data);
if (enum_elem_info)
s->Printf("%s", enum_elem_info->name.GetCString());
else {
lldb::offset_t ptr = 0;
if (data.GetByteSize())
s->Printf("<invalid> (0x%" PRIx8 ")", data.GetU8(&ptr));
else
s->Printf("<empty>");
}
return true;
} else
s->Printf("<unknown type>");
} break;
case swift::TypeKind::Struct:
case swift::TypeKind::Protocol:
case swift::TypeKind::GenericTypeParam:
case swift::TypeKind::DependentMember:
return false;
case swift::TypeKind::ExistentialMetatype:
case swift::TypeKind::Metatype: {
return DumpDataExtractor(data, s, byte_offset, eFormatPointer, byte_size, 1, UINT32_MAX,
LLDB_INVALID_ADDRESS, bitfield_bit_size,
bitfield_bit_offset, exe_scope);
} break;
case swift::TypeKind::Module:
case swift::TypeKind::ProtocolComposition:
case swift::TypeKind::UnboundGeneric:
case swift::TypeKind::BoundGenericStruct:
case swift::TypeKind::TypeVariable:
case swift::TypeKind::DynamicSelf:
case swift::TypeKind::SILBox:
case swift::TypeKind::SILFunction:
case swift::TypeKind::SILBlockStorage:
case swift::TypeKind::InOut:
case swift::TypeKind::Unresolved:
break;
case swift::TypeKind::Optional:
case swift::TypeKind::NameAlias:
case swift::TypeKind::Paren:
case swift::TypeKind::Dictionary:
case swift::TypeKind::ArraySlice:
assert(false && "Not a canonical type");
break;
}
return 0;
}
bool SwiftASTContext::IsImportedType(const CompilerType &type,
CompilerType *original_type) {
bool success = false;
if (llvm::dyn_cast_or_null<SwiftASTContext>(type.GetTypeSystem())) {
do {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
swift::NominalType *nominal_type =
swift_can_type->getAs<swift::NominalType>();
if (!nominal_type)
break;
swift::NominalTypeDecl *nominal_type_decl = nominal_type->getDecl();
if (nominal_type_decl && nominal_type_decl->hasClangNode()) {
const clang::Decl *clang_decl = nominal_type_decl->getClangDecl();
if (!clang_decl)
break;
success = true;
if (!original_type)
break;
if (const clang::ObjCInterfaceDecl *objc_interface_decl =
llvm::dyn_cast<clang::ObjCInterfaceDecl>(
clang_decl)) // ObjCInterfaceDecl is not a TypeDecl
{
*original_type =
CompilerType(&objc_interface_decl->getASTContext(),
clang::QualType::getFromOpaquePtr(
objc_interface_decl->getTypeForDecl()));
} else if (const clang::TypeDecl *type_decl =
llvm::dyn_cast<clang::TypeDecl>(clang_decl)) {
*original_type = CompilerType(
&type_decl->getASTContext(),
clang::QualType::getFromOpaquePtr(type_decl->getTypeForDecl()));
} else // TODO: any more cases that we care about?
{
*original_type = CompilerType();
}
}
} while (0);
}
return success;
}
bool SwiftASTContext::IsImportedObjectiveCType(const CompilerType &type,
CompilerType *original_type) {
bool success = false;
if (llvm::dyn_cast_or_null<SwiftASTContext>(type.GetTypeSystem())) {
CompilerType local_original_type;
if (IsImportedType(type, &local_original_type)) {
if (local_original_type.IsValid()) {
ClangASTContext *clang_ast = llvm::dyn_cast_or_null<ClangASTContext>(
local_original_type.GetTypeSystem());
if (clang_ast &&
clang_ast->IsObjCObjectOrInterfaceType(local_original_type)) {
if (original_type)
*original_type = local_original_type;
success = true;
}
}
}
}
return success;
}
void SwiftASTContext::DumpSummary(void *type, ExecutionContext *exe_ctx,
Stream *s,
const lldb_private::DataExtractor &data,
lldb::offset_t data_byte_offset,
size_t data_byte_size) {}
size_t SwiftASTContext::ConvertStringToFloatValue(void *type, const char *s,
uint8_t *dst,
size_t dst_size) {
return 0;
}
void SwiftASTContext::DumpTypeDescription(void *type) {
StreamFile s(stdout, false);
DumpTypeDescription(type, &s);
}
void SwiftASTContext::DumpTypeDescription(void *type, Stream *s) {
DumpTypeDescription(type, s, false, true);
}
void SwiftASTContext::DumpTypeDescription(void *type,
bool print_help_if_available,
bool print_extensions_if_available) {
StreamFile s(stdout, false);
DumpTypeDescription(type, &s, print_help_if_available,
print_extensions_if_available);
}
static void PrintSwiftNominalType(swift::NominalTypeDecl *nominal_type_decl,
Stream *s, bool print_help_if_available,
bool print_extensions_if_available) {
if (nominal_type_decl && s) {
std::string buffer;
llvm::raw_string_ostream ostream(buffer);
const swift::PrintOptions &print_options(
SwiftASTContext::GetUserVisibleTypePrintingOptions(
print_help_if_available));
nominal_type_decl->print(ostream, print_options);
ostream.flush();
if (buffer.empty() == false)
s->Printf("%s\n", buffer.c_str());
if (print_extensions_if_available) {
for (auto ext : nominal_type_decl->getExtensions()) {
if (ext) {
buffer.clear();
llvm::raw_string_ostream ext_ostream(buffer);
ext->print(ext_ostream, print_options);
ext_ostream.flush();
if (buffer.empty() == false)
s->Printf("%s\n", buffer.c_str());
}
}
}
}
}
void SwiftASTContext::DumpTypeDescription(void *type, Stream *s,
bool print_help_if_available,
bool print_extensions_if_available) {
llvm::SmallVector<char, 1024> buf;
llvm::raw_svector_ostream llvm_ostrm(buf);
if (type) {
swift::CanType swift_can_type(GetCanonicalSwiftType(type));
switch (swift_can_type->getKind()) {
case swift::TypeKind::Module: {
swift::ModuleType *module_type =
swift_can_type->castTo<swift::ModuleType>();
swift::ModuleDecl *module = module_type->getModule();
llvm::SmallVector<swift::Decl *, 10> decls;
module->getDisplayDecls(decls);
for (swift::Decl *decl : decls) {
swift::DeclKind kind = decl->getKind();
if (kind >= swift::DeclKind::First_TypeDecl &&
kind <= swift::DeclKind::Last_TypeDecl) {
swift::TypeDecl *type_decl =
llvm::dyn_cast_or_null<swift::TypeDecl>(decl);
if (type_decl) {
CompilerType clang_type(&module->getASTContext(),
type_decl->getDeclaredInterfaceType().getPointer());
if (clang_type) {
Flags clang_type_flags(clang_type.GetTypeInfo());
DumpTypeDescription(clang_type.GetOpaqueQualType(), s,
print_help_if_available,
print_extensions_if_available);
}
}
} else if (kind == swift::DeclKind::Func ||
kind == swift::DeclKind::Var) {
std::string buffer;
llvm::raw_string_ostream stream(buffer);
decl->print(stream,
SwiftASTContext::GetUserVisibleTypePrintingOptions(
print_help_if_available));
stream.flush();
s->Printf("%s\n", buffer.c_str());
} else if (kind == swift::DeclKind::Import) {
swift::ImportDecl *import_decl =
llvm::dyn_cast_or_null<swift::ImportDecl>(decl);
if (import_decl) {
switch (import_decl->getImportKind()) {
case swift::ImportKind::Module: {
swift::ModuleDecl *imported_module = import_decl->getModule();
if (imported_module) {
s->Printf("import %s\n", imported_module->getName().get());
}
} break;
default: {
for (swift::Decl *imported_decl : import_decl->getDecls()) {
// all of the non-module things you can import should be a
// ValueDecl
if (swift::ValueDecl *imported_value_decl =
llvm::dyn_cast_or_null<swift::ValueDecl>(
imported_decl)) {
if (swift::TypeBase *decl_type =
imported_value_decl->getInterfaceType().getPointer()) {
DumpTypeDescription(decl_type, s,
print_help_if_available,
print_extensions_if_available);
}
}
}
} break;
}
}
}
}
break;
}
case swift::TypeKind::Metatype: {
s->PutCString("metatype ");
swift::MetatypeType *metatype_type =
swift_can_type->castTo<swift::MetatypeType>();
DumpTypeDescription(metatype_type->getInstanceType().getPointer(),
print_help_if_available,
print_extensions_if_available);
} break;
case swift::TypeKind::UnboundGeneric: {
swift::UnboundGenericType *unbound_generic_type =
swift_can_type->castTo<swift::UnboundGenericType>();
auto nominal_type_decl = llvm::dyn_cast<swift::NominalTypeDecl>(
unbound_generic_type->getDecl());
if (nominal_type_decl) {
PrintSwiftNominalType(nominal_type_decl, s, print_help_if_available,
print_extensions_if_available);
}
} break;
case swift::TypeKind::GenericFunction:
case swift::TypeKind::Function: {
swift::AnyFunctionType *any_function_type =
swift_can_type->castTo<swift::AnyFunctionType>();
std::string buffer;
llvm::raw_string_ostream ostream(buffer);
const swift::PrintOptions &print_options(
SwiftASTContext::GetUserVisibleTypePrintingOptions(
print_help_if_available));
any_function_type->print(ostream, print_options);
ostream.flush();
if (buffer.empty() == false)
s->Printf("%s\n", buffer.c_str());
} break;
case swift::TypeKind::Tuple: {
swift::TupleType *tuple_type = swift_can_type->castTo<swift::TupleType>();
std::string buffer;
llvm::raw_string_ostream ostream(buffer);
const swift::PrintOptions &print_options(
SwiftASTContext::GetUserVisibleTypePrintingOptions(
print_help_if_available));
tuple_type->print(ostream, print_options);
ostream.flush();
if (buffer.empty() == false)
s->Printf("%s\n", buffer.c_str());
} break;
case swift::TypeKind::BoundGenericClass:
case swift::TypeKind::BoundGenericEnum:
case swift::TypeKind::BoundGenericStruct: {
swift::BoundGenericType *bound_generic_type =
swift_can_type->castTo<swift::BoundGenericType>();
swift::NominalTypeDecl *nominal_type_decl =
bound_generic_type->getDecl();
PrintSwiftNominalType(nominal_type_decl, s, print_help_if_available,
print_extensions_if_available);
} break;
case swift::TypeKind::BuiltinInteger: {
swift::BuiltinIntegerType *builtin_integer_type =
swift_can_type->castTo<swift::BuiltinIntegerType>();
s->Printf("builtin integer type of width %u bits\n",
builtin_integer_type->getWidth().getGreatestWidth());
break;
}
case swift::TypeKind::BuiltinFloat: {
swift::BuiltinFloatType *builtin_float_type =
swift_can_type->castTo<swift::BuiltinFloatType>();
s->Printf("builtin floating-point type of width %u bits\n",
builtin_float_type->getBitWidth());
break;
}
case swift::TypeKind::ProtocolComposition: {
swift::ProtocolCompositionType *protocol_composition_type =
swift_can_type->castTo<swift::ProtocolCompositionType>();
std::string buffer;
llvm::raw_string_ostream ostream(buffer);
const swift::PrintOptions &print_options(
SwiftASTContext::GetUserVisibleTypePrintingOptions(
print_help_if_available));
protocol_composition_type->print(ostream, print_options);
ostream.flush();
if (buffer.empty() == false)
s->Printf("%s\n", buffer.c_str());
break;
}
default: {
swift::NominalType *nominal_type =
llvm::dyn_cast_or_null<swift::NominalType>(
swift_can_type.getPointer());
if (nominal_type) {
swift::NominalTypeDecl *nominal_type_decl = nominal_type->getDecl();
PrintSwiftNominalType(nominal_type_decl, s, print_help_if_available,
print_extensions_if_available);
}
} break;
}
if (buf.size() > 0) {
s->Write(buf.data(), buf.size());
}
}
}
TypeSP SwiftASTContext::GetCachedType(const ConstString &mangled) {
TypeSP type_sp;
if (m_swift_type_map.Lookup(mangled.GetCString(), type_sp))
return type_sp;
else
return TypeSP();
}
void SwiftASTContext::SetCachedType(const ConstString &mangled,
const TypeSP &type_sp) {
m_swift_type_map.Insert(mangled.GetCString(), type_sp);
}
DWARFASTParser *SwiftASTContext::GetDWARFParser() {
if (!m_dwarf_ast_parser_ap)
m_dwarf_ast_parser_ap.reset(new DWARFASTParserSwift(*this));
return m_dwarf_ast_parser_ap.get();
}
std::vector<lldb::DataBufferSP> &
SwiftASTContext::GetASTVectorForModule(const Module *module) {
return m_ast_file_data_map[const_cast<Module *>(module)];
}
SwiftASTContextForExpressions::SwiftASTContextForExpressions(Target &target)
: SwiftASTContext(target.GetArchitecture().GetTriple().getTriple().c_str(),
&target),
m_persistent_state_up(new SwiftPersistentExpressionState) {}
UserExpression *SwiftASTContextForExpressions::GetUserExpression(
llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language,
Expression::ResultType desired_type,
const EvaluateExpressionOptions &options) {
TargetSP target_sp = m_target_wp.lock();
if (!target_sp)
return nullptr;
return new SwiftUserExpression(*target_sp.get(), expr, prefix, language,
desired_type, options);
}
PersistentExpressionState *
SwiftASTContextForExpressions::GetPersistentExpressionState() {
return m_persistent_state_up.get();
}