blob: 39226eb9712f6f7ac443908fcdf39c3136bdff71 [file] [log] [blame]
//===-- TypeSystem.h ------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_TypeSystem_h_
#define liblldb_TypeSystem_h_
#include <functional>
#include <map>
#include <mutex>
#include <string>
#include "llvm/ADT/APSInt.h"
#include "llvm/Support/Casting.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Expression/Expression.h"
#include "lldb/Symbol/CompilerDecl.h"
#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/lldb-private.h"
class DWARFDIE;
class DWARFASTParser;
class PDBASTParser;
namespace lldb_private {
// Interface for representing the Type Systems in different languages.
class TypeSystem : public PluginInterface {
public:
// Intrusive type system that allows us to use llvm casting.
//
// To add a new type system:
//
// 1 - Add a new enumeration for llvm casting below for your TypeSystem
// subclass, here we will use eKindFoo
//
// 2 - Your TypeSystem subclass will inherit from TypeSystem and needs
// to implement a static classof() function that returns your
// enumeration:
//
// class Foo : public lldb_private::TypeSystem
// {
// static bool classof(const TypeSystem *ts)
// {
// return ts->getKind() == TypeSystem::eKindFoo;
// }
// };
//
// 3 - Contruct your TypeSystem subclass with the enumeration from below
//
// Foo() :
// TypeSystem(TypeSystem::eKindFoo),
// ...
// {
// }
//
// Then you can use the llvm casting on any "TypeSystem *" to get an instance
// of your subclass.
enum LLVMCastKind {
eKindClang,
eKindSwift,
eKindOCaml,
kNumKinds
};
// Constructors and Destructors
TypeSystem(LLVMCastKind kind);
~TypeSystem() override;
LLVMCastKind getKind() const { return m_kind; }
static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
Module *module);
static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
Target *target);
// Free up any resources associated with this TypeSystem. Done before
// removing all the TypeSystems from the TypeSystemMap.
virtual void Finalize() {}
virtual DWARFASTParser *GetDWARFParser() { return nullptr; }
virtual PDBASTParser *GetPDBParser() { return nullptr; }
virtual SymbolFile *GetSymbolFile() const { return m_sym_file; }
// Returns true if the symbol file changed during the set accessor.
virtual void SetSymbolFile(SymbolFile *sym_file) { m_sym_file = sym_file; }
// CompilerDecl functions
virtual ConstString DeclGetName(void *opaque_decl) = 0;
virtual ConstString DeclGetMangledName(void *opaque_decl);
virtual CompilerDeclContext DeclGetDeclContext(void *opaque_decl);
virtual CompilerType DeclGetFunctionReturnType(void *opaque_decl);
virtual size_t DeclGetFunctionNumArguments(void *opaque_decl);
virtual CompilerType DeclGetFunctionArgumentType(void *opaque_decl,
size_t arg_idx);
// CompilerDeclContext functions
virtual std::vector<CompilerDecl>
DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
const bool ignore_imported_decls);
virtual bool DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) = 0;
virtual ConstString DeclContextGetName(void *opaque_decl_ctx) = 0;
virtual ConstString
DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) = 0;
virtual bool DeclContextIsClassMethod(
void *opaque_decl_ctx, lldb::LanguageType *language_ptr,
bool *is_instance_method_ptr, ConstString *language_object_name_ptr) = 0;
virtual bool DeclContextIsContainedInLookup(void *opaque_decl_ctx,
void *other_opaque_decl_ctx) = 0;
// Tests
virtual bool IsArrayType(lldb::opaque_compiler_type_t type,
CompilerType *element_type, uint64_t *size,
bool *is_incomplete) = 0;
virtual bool IsAggregateType(lldb::opaque_compiler_type_t type) = 0;
virtual bool IsAnonymousType(lldb::opaque_compiler_type_t type);
virtual bool IsCharType(lldb::opaque_compiler_type_t type) = 0;
virtual bool IsCompleteType(lldb::opaque_compiler_type_t type) = 0;
virtual bool IsDefined(lldb::opaque_compiler_type_t type) = 0;
virtual bool IsFloatingPointType(lldb::opaque_compiler_type_t type,
uint32_t &count, bool &is_complex) = 0;
virtual bool IsFunctionType(lldb::opaque_compiler_type_t type,
bool *is_variadic_ptr) = 0;
virtual size_t
GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) = 0;
virtual CompilerType
GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
const size_t index) = 0;
virtual bool IsFunctionPointerType(lldb::opaque_compiler_type_t type) = 0;
virtual bool IsBlockPointerType(lldb::opaque_compiler_type_t type,
CompilerType *function_pointer_type_ptr) = 0;
virtual bool IsIntegerType(lldb::opaque_compiler_type_t type,
bool &is_signed) = 0;
virtual bool IsEnumerationType(lldb::opaque_compiler_type_t type,
bool &is_signed) {
is_signed = false;
return false;
}
virtual bool IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
CompilerType *target_type, // Can pass NULL
bool check_cplusplus, bool check_objc) = 0;
virtual bool IsPointerType(lldb::opaque_compiler_type_t type,
CompilerType *pointee_type) = 0;
virtual bool IsScalarType(lldb::opaque_compiler_type_t type) = 0;
virtual bool IsVoidType(lldb::opaque_compiler_type_t type) = 0;
// TypeSystems can support more than one language
virtual bool SupportsLanguage(lldb::LanguageType language) = 0;
// Type Completion
virtual bool GetCompleteType(lldb::opaque_compiler_type_t type) = 0;
// AST related queries
virtual uint32_t GetPointerByteSize() = 0;
// Accessors
virtual ConstString GetTypeName(lldb::opaque_compiler_type_t type) = 0;
virtual uint32_t
GetTypeInfo(lldb::opaque_compiler_type_t type,
CompilerType *pointee_or_element_compiler_type) = 0;
virtual lldb::LanguageType
GetMinimumLanguage(lldb::opaque_compiler_type_t type) = 0;
virtual lldb::TypeClass GetTypeClass(lldb::opaque_compiler_type_t type) = 0;
// Creating related types
virtual CompilerType GetArrayElementType(lldb::opaque_compiler_type_t type,
uint64_t *stride) = 0;
virtual CompilerType GetArrayType(lldb::opaque_compiler_type_t type,
uint64_t size);
virtual CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) = 0;
// Returns -1 if this isn't a function of if the function doesn't have a
// prototype Returns a value >= 0 if there is a prototype.
virtual int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) = 0;
virtual CompilerType
GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type,
size_t idx) = 0;
virtual CompilerType
GetFunctionReturnType(lldb::opaque_compiler_type_t type) = 0;
virtual size_t GetNumMemberFunctions(lldb::opaque_compiler_type_t type) = 0;
virtual TypeMemberFunctionImpl
GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, size_t idx) = 0;
virtual CompilerType GetPointeeType(lldb::opaque_compiler_type_t type) = 0;
virtual CompilerType GetPointerType(lldb::opaque_compiler_type_t type) = 0;
virtual CompilerType
GetLValueReferenceType(lldb::opaque_compiler_type_t type);
virtual CompilerType
GetRValueReferenceType(lldb::opaque_compiler_type_t type);
virtual CompilerType AddConstModifier(lldb::opaque_compiler_type_t type);
virtual CompilerType AddVolatileModifier(lldb::opaque_compiler_type_t type);
virtual CompilerType AddRestrictModifier(lldb::opaque_compiler_type_t type);
virtual CompilerType CreateTypedef(lldb::opaque_compiler_type_t type,
const char *name,
const CompilerDeclContext &decl_ctx);
// Exploring the type
virtual llvm::Optional<uint64_t>
GetBitSize(lldb::opaque_compiler_type_t type,
ExecutionContextScope *exe_scope) = 0;
virtual lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type,
uint64_t &count) = 0;
virtual lldb::Format GetFormat(lldb::opaque_compiler_type_t type) = 0;
virtual uint32_t GetNumChildren(lldb::opaque_compiler_type_t type,
bool omit_empty_base_classes,
const ExecutionContext *exe_ctx) = 0;
virtual CompilerType GetBuiltinTypeByName(ConstString name);
virtual lldb::BasicType
GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) = 0;
virtual void ForEachEnumerator(
lldb::opaque_compiler_type_t type,
std::function<bool(const CompilerType &integer_type,
ConstString name,
const llvm::APSInt &value)> const &callback) {}
virtual uint32_t GetNumFields(lldb::opaque_compiler_type_t type) = 0;
virtual CompilerType GetFieldAtIndex(lldb::opaque_compiler_type_t type,
size_t idx, std::string &name,
uint64_t *bit_offset_ptr,
uint32_t *bitfield_bit_size_ptr,
bool *is_bitfield_ptr) = 0;
virtual uint32_t
GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) = 0;
virtual uint32_t
GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) = 0;
virtual CompilerType
GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx,
uint32_t *bit_offset_ptr) = 0;
virtual CompilerType
GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx,
uint32_t *bit_offset_ptr) = 0;
virtual CompilerType GetChildCompilerTypeAtIndex(
lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
bool transparent_pointers, bool omit_empty_base_classes,
bool ignore_array_bounds, std::string &child_name,
uint32_t &child_byte_size, int32_t &child_byte_offset,
uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
bool &child_is_base_class, bool &child_is_deref_of_parent,
ValueObject *valobj, uint64_t &language_flags) = 0;
// Lookup a child given a name. This function will match base class names and
// member member names in "clang_type" only, not descendants.
virtual uint32_t GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
const char *name,
bool omit_empty_base_classes) = 0;
// Lookup a child member given a name. This function will match member names
// only and will descend into "clang_type" children in search for the first
// member in this class, or any base class that matches "name".
// TODO: Return all matches for a given name by returning a
// vector<vector<uint32_t>>
// so we catch all names that match a given child name, not just the first.
virtual size_t
GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type,
const char *name, bool omit_empty_base_classes,
std::vector<uint32_t> &child_indexes) = 0;
virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type);
virtual lldb::TemplateArgumentKind
GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx);
virtual CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type,
size_t idx);
virtual llvm::Optional<CompilerType::IntegralTemplateArgument>
GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx);
// Dumping types
#ifndef NDEBUG
/// Convenience LLVM-style dump method for use in the debugger only.
LLVM_DUMP_METHOD virtual void
dump(lldb::opaque_compiler_type_t type) const = 0;
#endif
virtual void DumpValue(lldb::opaque_compiler_type_t type,
ExecutionContext *exe_ctx, Stream *s,
lldb::Format format, const DataExtractor &data,
lldb::offset_t data_offset, size_t data_byte_size,
uint32_t bitfield_bit_size,
uint32_t bitfield_bit_offset, bool show_types,
bool show_summary, bool verbose, uint32_t depth) = 0;
virtual bool DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s,
lldb::Format format, const DataExtractor &data,
lldb::offset_t data_offset, size_t data_byte_size,
uint32_t bitfield_bit_size,
uint32_t bitfield_bit_offset,
ExecutionContextScope *exe_scope) = 0;
virtual void
DumpTypeDescription(lldb::opaque_compiler_type_t type) = 0; // Dump to stdout
virtual void DumpTypeDescription(lldb::opaque_compiler_type_t type,
Stream *s) = 0;
// TODO: These methods appear unused. Should they be removed?
virtual bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) = 0;
virtual void DumpSummary(lldb::opaque_compiler_type_t type,
ExecutionContext *exe_ctx, Stream *s,
const DataExtractor &data,
lldb::offset_t data_offset,
size_t data_byte_size) = 0;
// Converts "s" to a floating point value and place resulting floating point
// bytes in the "dst" buffer.
virtual size_t ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
const char *s, uint8_t *dst,
size_t dst_size) = 0;
// TODO: Determine if these methods should move to ClangASTContext.
virtual bool IsPointerOrReferenceType(lldb::opaque_compiler_type_t type,
CompilerType *pointee_type) = 0;
virtual unsigned GetTypeQualifiers(lldb::opaque_compiler_type_t type) = 0;
virtual bool IsCStringType(lldb::opaque_compiler_type_t type,
uint32_t &length) = 0;
virtual size_t GetTypeBitAlign(lldb::opaque_compiler_type_t type) = 0;
virtual CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) = 0;
virtual CompilerType
GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
size_t bit_size) = 0;
virtual bool IsBeingDefined(lldb::opaque_compiler_type_t type) = 0;
virtual bool IsConst(lldb::opaque_compiler_type_t type) = 0;
virtual uint32_t IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
CompilerType *base_type_ptr) = 0;
virtual bool IsPolymorphicClass(lldb::opaque_compiler_type_t type) = 0;
virtual bool IsTypedefType(lldb::opaque_compiler_type_t type) = 0;
// If the current object represents a typedef type, get the underlying type
virtual CompilerType GetTypedefedType(lldb::opaque_compiler_type_t type) = 0;
virtual bool IsVectorType(lldb::opaque_compiler_type_t type,
CompilerType *element_type, uint64_t *size) = 0;
virtual CompilerType
GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) = 0;
virtual CompilerType
GetNonReferenceType(lldb::opaque_compiler_type_t type) = 0;
virtual bool IsReferenceType(lldb::opaque_compiler_type_t type,
CompilerType *pointee_type, bool *is_rvalue) = 0;
virtual bool
ShouldTreatScalarValueAsAddress(lldb::opaque_compiler_type_t type) {
return IsPointerOrReferenceType(type, nullptr);
}
virtual UserExpression *
GetUserExpression(llvm::StringRef expr, llvm::StringRef prefix,
lldb::LanguageType language,
Expression::ResultType desired_type,
const EvaluateExpressionOptions &options,
ValueObject *ctx_obj) {
return nullptr;
}
virtual FunctionCaller *GetFunctionCaller(const CompilerType &return_type,
const Address &function_address,
const ValueList &arg_value_list,
const char *name) {
return nullptr;
}
virtual UtilityFunction *GetUtilityFunction(const char *text,
const char *name) {
return nullptr;
}
virtual PersistentExpressionState *GetPersistentExpressionState() {
return nullptr;
}
virtual CompilerType GetTypeForFormatters(void *type);
virtual LazyBool ShouldPrintAsOneLiner(void *type, ValueObject *valobj);
// Type systems can have types that are placeholder types, which are meant to
// indicate the presence of a type, but offer no actual information about
// said types, and leave the burden of actually figuring type information out
// to dynamic type resolution. For instance a language with a generics
// system, can use placeholder types to indicate "type argument goes here",
// without promising uniqueness of the placeholder, nor attaching any
// actually idenfiable information to said placeholder. This API allows type
// systems to tell LLDB when such a type has been encountered In response,
// the debugger can react by not using this type as a cache entry in any
// type-specific way For instance, LLDB will currently not cache any
// formatters that are discovered on such a type as attributable to the
// meaningless type itself, instead preferring to use the dynamic type
virtual bool IsMeaninglessWithoutDynamicResolution(void *type);
protected:
const LLVMCastKind m_kind; // Support for llvm casting
SymbolFile *m_sym_file;
};
class TypeSystemMap {
public:
TypeSystemMap();
~TypeSystemMap();
// Clear calls Finalize on all the TypeSystems managed by this map, and then
// empties the map.
void Clear();
// Iterate through all of the type systems that are created. Return true from
// callback to keep iterating, false to stop iterating.
void ForEach(std::function<bool(TypeSystem *)> const &callback);
TypeSystem *GetTypeSystemForLanguage(lldb::LanguageType language,
Module *module, bool can_create);
TypeSystem *GetTypeSystemForLanguage(lldb::LanguageType language,
Target *target, bool can_create);
protected:
// This function does not take the map mutex, and should only be called from
// functions that do take the mutex.
void AddToMap(lldb::LanguageType language,
lldb::TypeSystemSP const &type_system_sp);
typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> collection;
mutable std::mutex m_mutex; ///< A mutex to keep this object happy in
///multi-threaded environments.
collection m_map;
bool m_clear_in_progress;
};
} // namespace lldb_private
#endif // liblldb_TypeSystem_h_