blob: ff317eb19e97cc37287c10365ab3e7f0ae0dc8cc [file] [log] [blame]
//===-- JavaASTContext.cpp --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Symbol/JavaASTContext.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/Stream.h"
#include <sstream>
#include "Plugins/SymbolFile/DWARF/DWARFASTParserJava.h"
using namespace lldb;
using namespace lldb_private;
namespace lldb_private {
class JavaASTContext::JavaType {
public:
enum LLVMCastKind {
eKindPrimitive,
eKindObject,
eKindReference,
eKindArray,
kNumKinds
};
JavaType(LLVMCastKind kind) : m_kind(kind) {}
virtual ~JavaType() = default;
virtual ConstString GetName() = 0;
virtual void Dump(Stream *s) = 0;
virtual bool IsCompleteType() = 0;
LLVMCastKind getKind() const { return m_kind; }
private:
LLVMCastKind m_kind;
};
} // end of namespace lldb_private
namespace {
class JavaPrimitiveType : public JavaASTContext::JavaType {
public:
enum TypeKind {
eTypeByte,
eTypeShort,
eTypeInt,
eTypeLong,
eTypeFloat,
eTypeDouble,
eTypeBoolean,
eTypeChar,
};
JavaPrimitiveType(TypeKind type_kind)
: JavaType(JavaType::eKindPrimitive), m_type_kind(type_kind) {}
ConstString GetName() override {
switch (m_type_kind) {
case eTypeByte:
return ConstString("byte");
case eTypeShort:
return ConstString("short");
case eTypeInt:
return ConstString("int");
case eTypeLong:
return ConstString("long");
case eTypeFloat:
return ConstString("float");
case eTypeDouble:
return ConstString("double");
case eTypeBoolean:
return ConstString("boolean");
case eTypeChar:
return ConstString("char");
}
return ConstString();
}
TypeKind GetTypeKind() { return m_type_kind; }
void Dump(Stream *s) override { s->Printf("%s\n", GetName().GetCString()); }
bool IsCompleteType() override { return true; }
static bool classof(const JavaType *jt) {
return jt->getKind() == JavaType::eKindPrimitive;
}
private:
const TypeKind m_type_kind;
};
class JavaDynamicType : public JavaASTContext::JavaType {
public:
JavaDynamicType(LLVMCastKind kind, const ConstString &linkage_name)
: JavaType(kind), m_linkage_name(linkage_name),
m_dynamic_type_id(nullptr) {}
ConstString GetLinkageName() const { return m_linkage_name; }
void SetDynamicTypeId(const DWARFExpression &type_id) {
m_dynamic_type_id = type_id;
}
uint64_t CalculateDynamicTypeId(ExecutionContext *exe_ctx,
ValueObject &value_obj) {
if (!m_dynamic_type_id.IsValid())
return UINT64_MAX;
Value obj_load_address = value_obj.GetValue();
obj_load_address.ResolveValue(exe_ctx);
obj_load_address.SetValueType(Value::eValueTypeLoadAddress);
Value result;
if (m_dynamic_type_id.Evaluate(exe_ctx->GetBestExecutionContextScope(), 0,
&obj_load_address, nullptr, result,
nullptr)) {
Status error;
lldb::addr_t type_id_addr = result.GetScalar().UInt();
lldb::ProcessSP process_sp = exe_ctx->GetProcessSP();
if (process_sp)
return process_sp->ReadUnsignedIntegerFromMemory(
type_id_addr, process_sp->GetAddressByteSize(), UINT64_MAX, error);
}
return UINT64_MAX;
}
public:
ConstString m_linkage_name;
DWARFExpression m_dynamic_type_id;
};
class JavaObjectType : public JavaDynamicType {
public:
struct Field {
ConstString m_name;
CompilerType m_type;
uint32_t m_offset;
};
JavaObjectType(const ConstString &name, const ConstString &linkage_name,
uint32_t byte_size)
: JavaDynamicType(JavaType::eKindObject, linkage_name), m_name(name),
m_byte_size(byte_size), m_base_class_offset(0), m_is_complete(false) {}
ConstString GetName() override { return m_name; }
uint32_t GetByteSize() const { return m_byte_size; }
uint32_t GetNumFields() { return m_fields.size(); }
void Dump(Stream *s) override {
if (m_base_class.IsValid())
s->Printf("%s : %s\n", GetName().GetCString(),
m_base_class.GetTypeName().GetCString());
else
s->Printf("%s\n", GetName().GetCString());
s->IndentMore();
for (const Field &f : m_fields)
s->Printf("%s %s\n", f.m_type.GetTypeName().GetCString(),
f.m_name.GetCString());
s->IndentLess();
}
Field *GetFieldAtIndex(size_t idx) {
if (idx < m_fields.size())
return &m_fields[idx];
return nullptr;
}
CompilerType GetBaseClass() { return m_base_class; }
uint32_t GetBaseClassOffset() { return m_base_class_offset; }
uint32_t GetNumInterfaces() { return m_interfaces.size(); }
CompilerType GetInterfaceAtIndex(uint32_t idx) {
if (m_interfaces.size() < idx)
return m_interfaces[idx];
return CompilerType();
}
bool IsCompleteType() override { return m_is_complete; }
void SetCompleteType(bool is_complete) {
m_is_complete = is_complete;
if (m_byte_size == 0) {
// Try to calcualte the size of the object based on it's values
for (const Field &field : m_fields) {
uint32_t field_end = field.m_offset + field.m_type.GetByteSize(nullptr);
if (field_end > m_byte_size)
m_byte_size = field_end;
}
}
}
void AddBaseClass(const CompilerType &type, uint32_t offset) {
// TODO: Check if type is an interface and add it to the interface list in
// that case
m_base_class = type;
m_base_class_offset = offset;
}
void AddField(const ConstString &name, const CompilerType &type,
uint32_t offset) {
m_fields.push_back({name, type, offset});
}
static bool classof(const JavaType *jt) {
return jt->getKind() == JavaType::eKindObject;
}
private:
ConstString m_name;
uint32_t m_byte_size;
CompilerType m_base_class;
uint32_t m_base_class_offset;
std::vector<CompilerType> m_interfaces;
std::vector<Field> m_fields;
bool m_is_complete;
};
class JavaReferenceType : public JavaASTContext::JavaType {
public:
JavaReferenceType(CompilerType pointee_type)
: JavaType(JavaType::eKindReference), m_pointee_type(pointee_type) {}
static bool classof(const JavaType *jt) {
return jt->getKind() == JavaType::eKindReference;
}
CompilerType GetPointeeType() { return m_pointee_type; }
ConstString GetName() override {
ConstString pointee_type_name =
static_cast<JavaType *>(GetPointeeType().GetOpaqueQualType())
->GetName();
return ConstString(std::string(pointee_type_name.AsCString()) + "&");
}
void Dump(Stream *s) override {
static_cast<JavaType *>(m_pointee_type.GetOpaqueQualType())->Dump(s);
}
bool IsCompleteType() override { return m_pointee_type.IsCompleteType(); }
private:
CompilerType m_pointee_type;
};
class JavaArrayType : public JavaDynamicType {
public:
JavaArrayType(const ConstString &linkage_name, CompilerType element_type,
const DWARFExpression &length_expression,
lldb::addr_t data_offset)
: JavaDynamicType(JavaType::eKindArray, linkage_name),
m_element_type(element_type), m_length_expression(length_expression),
m_data_offset(data_offset) {}
static bool classof(const JavaType *jt) {
return jt->getKind() == JavaType::eKindArray;
}
CompilerType GetElementType() { return m_element_type; }
ConstString GetName() override {
ConstString element_type_name =
static_cast<JavaType *>(GetElementType().GetOpaqueQualType())
->GetName();
return ConstString(std::string(element_type_name.AsCString()) + "[]");
}
void Dump(Stream *s) override { s->Printf("%s\n", GetName().GetCString()); }
bool IsCompleteType() override { return m_length_expression.IsValid(); }
uint32_t GetNumElements(ValueObject *value_obj) {
if (!m_length_expression.IsValid())
return UINT32_MAX;
Status error;
ValueObjectSP address_obj = value_obj->AddressOf(error);
if (error.Fail())
return UINT32_MAX;
Value obj_load_address = address_obj->GetValue();
obj_load_address.SetValueType(Value::eValueTypeLoadAddress);
Value result;
ExecutionContextScope *exec_ctx_scope = value_obj->GetExecutionContextRef()
.Lock(true)
.GetBestExecutionContextScope();
if (m_length_expression.Evaluate(exec_ctx_scope, 0, nullptr,
&obj_load_address, result, nullptr))
return result.GetScalar().UInt();
return UINT32_MAX;
}
uint64_t GetElementOffset(size_t idx) {
return m_data_offset + idx * m_element_type.GetByteSize(nullptr);
}
private:
CompilerType m_element_type;
DWARFExpression m_length_expression;
lldb::addr_t m_data_offset;
};
} // end of anonymous namespace
ConstString JavaASTContext::GetPluginNameStatic() {
return ConstString("java");
}
ConstString JavaASTContext::GetPluginName() {
return JavaASTContext::GetPluginNameStatic();
}
uint32_t JavaASTContext::GetPluginVersion() { return 1; }
lldb::TypeSystemSP JavaASTContext::CreateInstance(lldb::LanguageType language,
Module *module,
Target *target) {
if (language == eLanguageTypeJava) {
if (module)
return std::make_shared<JavaASTContext>(module->GetArchitecture());
if (target)
return std::make_shared<JavaASTContext>(target->GetArchitecture());
assert(false && "Either a module or a target has to be specifed to create "
"a JavaASTContext");
}
return lldb::TypeSystemSP();
}
void JavaASTContext::EnumerateSupportedLanguages(
std::set<lldb::LanguageType> &languages_for_types,
std::set<lldb::LanguageType> &languages_for_expressions) {
static std::vector<lldb::LanguageType> s_languages_for_types(
{lldb::eLanguageTypeJava});
static std::vector<lldb::LanguageType> s_languages_for_expressions({});
languages_for_types.insert(s_languages_for_types.begin(),
s_languages_for_types.end());
languages_for_expressions.insert(s_languages_for_expressions.begin(),
s_languages_for_expressions.end());
}
void JavaASTContext::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(), "AST context plug-in",
CreateInstance, EnumerateSupportedLanguages);
}
void JavaASTContext::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}
JavaASTContext::JavaASTContext(const ArchSpec &arch)
: TypeSystem(eKindJava), m_pointer_byte_size(arch.GetAddressByteSize()) {}
JavaASTContext::~JavaASTContext() {}
uint32_t JavaASTContext::GetPointerByteSize() { return m_pointer_byte_size; }
DWARFASTParser *JavaASTContext::GetDWARFParser() {
if (!m_dwarf_ast_parser_ap)
m_dwarf_ast_parser_ap.reset(new DWARFASTParserJava(*this));
return m_dwarf_ast_parser_ap.get();
}
ConstString JavaASTContext::DeclGetName(void *opaque_decl) {
return ConstString();
}
std::vector<CompilerDecl> JavaASTContext::DeclContextFindDeclByName(
void *opaque_decl_ctx, ConstString name, const bool ignore_imported_decls) {
return std::vector<CompilerDecl>();
}
bool JavaASTContext::DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) {
return false;
}
ConstString JavaASTContext::DeclContextGetName(void *opaque_decl_ctx) {
return ConstString();
}
bool JavaASTContext::DeclContextIsClassMethod(
void *opaque_decl_ctx, lldb::LanguageType *language_ptr,
bool *is_instance_method_ptr, ConstString *language_object_name_ptr) {
return false;
}
bool JavaASTContext::IsArrayType(lldb::opaque_compiler_type_t type,
CompilerType *element_type, uint64_t *size,
bool *is_incomplete) {
if (element_type)
element_type->Clear();
if (size)
*size = 0;
if (is_incomplete)
*is_incomplete = false;
if (JavaArrayType *array =
llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type))) {
if (element_type)
*element_type = array->GetElementType();
return true;
}
return false;
}
bool JavaASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) {
return llvm::isa<JavaObjectType>(static_cast<JavaType *>(type));
}
bool JavaASTContext::IsCharType(lldb::opaque_compiler_type_t type) {
if (JavaPrimitiveType *ptype =
llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type)))
return ptype->GetTypeKind() == JavaPrimitiveType::eTypeChar;
return false;
}
bool JavaASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type,
uint32_t &count, bool &is_complex) {
is_complex = true;
if (JavaPrimitiveType *ptype =
llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) {
switch (ptype->GetTypeKind()) {
case JavaPrimitiveType::eTypeFloat:
case JavaPrimitiveType::eTypeDouble:
count = 1;
return true;
default:
break;
}
}
count = 0;
return false;
}
bool JavaASTContext::IsFunctionType(lldb::opaque_compiler_type_t type,
bool *is_variadic_ptr) {
if (is_variadic_ptr)
*is_variadic_ptr = false;
return false;
}
size_t JavaASTContext::GetNumberOfFunctionArguments(
lldb::opaque_compiler_type_t type) {
return 0;
}
CompilerType
JavaASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
const size_t index) {
return CompilerType();
}
bool JavaASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) {
return false;
}
bool JavaASTContext::IsBlockPointerType(
lldb::opaque_compiler_type_t type,
CompilerType *function_pointer_type_ptr) {
return false;
}
bool JavaASTContext::IsIntegerType(lldb::opaque_compiler_type_t type,
bool &is_signed) {
if (JavaPrimitiveType *ptype =
llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) {
switch (ptype->GetTypeKind()) {
case JavaPrimitiveType::eTypeByte:
case JavaPrimitiveType::eTypeShort:
case JavaPrimitiveType::eTypeInt:
case JavaPrimitiveType::eTypeLong:
is_signed = true;
return true;
default:
break;
}
}
is_signed = false;
return false;
}
bool JavaASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
CompilerType *target_type,
bool check_cplusplus,
bool check_objc) {
return llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type));
}
bool JavaASTContext::IsPointerType(lldb::opaque_compiler_type_t type,
CompilerType *pointee_type) {
if (pointee_type)
pointee_type->Clear();
return false;
}
bool JavaASTContext::IsReferenceType(lldb::opaque_compiler_type_t type,
CompilerType *pointee_type,
bool *is_rvalue) {
if (is_rvalue)
*is_rvalue = false;
if (JavaReferenceType *ref =
llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) {
if (pointee_type)
*pointee_type = ref->GetPointeeType();
return true;
}
if (pointee_type)
pointee_type->Clear();
return false;
}
bool JavaASTContext::IsScalarType(lldb::opaque_compiler_type_t type) {
return llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type)) ||
llvm::isa<JavaPrimitiveType>(static_cast<JavaType *>(type));
}
bool JavaASTContext::IsVoidType(lldb::opaque_compiler_type_t type) {
return false; // TODO: Implement if we introduce the void type
}
bool JavaASTContext::SupportsLanguage(lldb::LanguageType language) {
return language == lldb::eLanguageTypeJava;
}
bool JavaASTContext::IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) {
return true;
}
bool JavaASTContext::IsPointerOrReferenceType(lldb::opaque_compiler_type_t type,
CompilerType *pointee_type) {
return IsPointerType(type, pointee_type) ||
IsReferenceType(type, pointee_type);
}
bool JavaASTContext::IsCStringType(lldb::opaque_compiler_type_t type,
uint32_t &length) {
return false; // TODO: Implement it if we need it for string literals
}
bool JavaASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) {
return false;
}
bool JavaASTContext::IsVectorType(lldb::opaque_compiler_type_t type,
CompilerType *element_type, uint64_t *size) {
if (element_type)
element_type->Clear();
if (size)
*size = 0;
return false;
}
bool JavaASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) {
return llvm::isa<JavaObjectType>(static_cast<JavaType *>(type));
}
uint32_t
JavaASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
CompilerType *base_type_ptr) {
return false;
}
bool JavaASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) {
return static_cast<JavaType *>(type)->IsCompleteType();
}
bool JavaASTContext::IsConst(lldb::opaque_compiler_type_t type) {
return false;
}
bool JavaASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) {
return false;
}
bool JavaASTContext::IsDefined(lldb::opaque_compiler_type_t type) {
return type != nullptr;
}
bool JavaASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) {
if (IsCompleteType(type))
return true;
if (JavaArrayType *array =
llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type)))
return GetCompleteType(array->GetElementType().GetOpaqueQualType());
if (JavaReferenceType *reference =
llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type)))
return GetCompleteType(reference->GetPointeeType().GetOpaqueQualType());
if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type))) {
SymbolFile *symbol_file = GetSymbolFile();
if (!symbol_file)
return false;
CompilerType object_type(this, type);
return symbol_file->CompleteType(object_type);
}
return false;
}
ConstString JavaASTContext::GetTypeName(lldb::opaque_compiler_type_t type) {
if (type)
return static_cast<JavaType *>(type)->GetName();
return ConstString();
}
uint32_t
JavaASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type,
CompilerType *pointee_or_element_compiler_type) {
if (pointee_or_element_compiler_type)
pointee_or_element_compiler_type->Clear();
if (!type)
return 0;
if (IsReferenceType(type, pointee_or_element_compiler_type))
return eTypeHasChildren | eTypeHasValue | eTypeIsReference;
if (IsArrayType(type, pointee_or_element_compiler_type, nullptr, nullptr))
return eTypeHasChildren | eTypeIsArray;
if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)))
return eTypeHasChildren | eTypeIsClass;
if (JavaPrimitiveType *ptype =
llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) {
switch (ptype->GetTypeKind()) {
case JavaPrimitiveType::eTypeByte:
case JavaPrimitiveType::eTypeShort:
case JavaPrimitiveType::eTypeInt:
case JavaPrimitiveType::eTypeLong:
return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsInteger |
eTypeIsSigned;
case JavaPrimitiveType::eTypeFloat:
case JavaPrimitiveType::eTypeDouble:
return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsFloat |
eTypeIsSigned;
case JavaPrimitiveType::eTypeBoolean:
return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar;
case JavaPrimitiveType::eTypeChar:
return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar;
}
}
return 0;
}
lldb::TypeClass
JavaASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) {
if (!type)
return eTypeClassInvalid;
if (llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type)))
return eTypeClassReference;
if (llvm::isa<JavaArrayType>(static_cast<JavaType *>(type)))
return eTypeClassArray;
if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)))
return eTypeClassClass;
if (llvm::isa<JavaPrimitiveType>(static_cast<JavaType *>(type)))
return eTypeClassBuiltin;
assert(false && "Java type with unhandled type class");
return eTypeClassInvalid;
}
lldb::LanguageType
JavaASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) {
return lldb::eLanguageTypeJava;
}
CompilerType
JavaASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type,
uint64_t *stride) {
if (stride)
*stride = 0;
CompilerType element_type;
if (IsArrayType(type, &element_type, nullptr, nullptr))
return element_type;
return CompilerType();
}
CompilerType JavaASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) {
CompilerType pointee_type;
if (IsPointerType(type, &pointee_type))
return pointee_type;
return CompilerType();
}
CompilerType JavaASTContext::GetPointerType(lldb::opaque_compiler_type_t type) {
return CompilerType(); // No pointer types in java
}
CompilerType
JavaASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) {
return CompilerType(this, type);
}
CompilerType
JavaASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) {
return CompilerType(this, type);
}
CompilerType
JavaASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) {
CompilerType pointee_type;
if (IsReferenceType(type, &pointee_type))
return pointee_type;
return CompilerType(this, type);
}
CompilerType
JavaASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) {
return CompilerType();
}
CompilerType JavaASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) {
return CompilerType();
}
CompilerType
JavaASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
size_t bit_size) {
return CompilerType();
}
size_t JavaASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) {
return 0;
}
lldb::BasicType
JavaASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) {
if (JavaPrimitiveType *ptype =
llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) {
switch (ptype->GetTypeKind()) {
case JavaPrimitiveType::eTypeByte:
return eBasicTypeOther;
case JavaPrimitiveType::eTypeShort:
return eBasicTypeShort;
case JavaPrimitiveType::eTypeInt:
return eBasicTypeInt;
case JavaPrimitiveType::eTypeLong:
return eBasicTypeLong;
case JavaPrimitiveType::eTypeFloat:
return eBasicTypeFloat;
case JavaPrimitiveType::eTypeDouble:
return eBasicTypeDouble;
case JavaPrimitiveType::eTypeBoolean:
return eBasicTypeBool;
case JavaPrimitiveType::eTypeChar:
return eBasicTypeChar;
}
}
return eBasicTypeInvalid;
}
uint64_t JavaASTContext::GetBitSize(lldb::opaque_compiler_type_t type,
ExecutionContextScope *exe_scope) {
if (JavaPrimitiveType *ptype =
llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) {
switch (ptype->GetTypeKind()) {
case JavaPrimitiveType::eTypeByte:
return 8;
case JavaPrimitiveType::eTypeShort:
return 16;
case JavaPrimitiveType::eTypeInt:
return 32;
case JavaPrimitiveType::eTypeLong:
return 64;
case JavaPrimitiveType::eTypeFloat:
return 32;
case JavaPrimitiveType::eTypeDouble:
return 64;
case JavaPrimitiveType::eTypeBoolean:
return 1;
case JavaPrimitiveType::eTypeChar:
return 16;
}
} else if (llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type))) {
return 32; // References are always 4 byte long in java
} else if (llvm::isa<JavaArrayType>(static_cast<JavaType *>(type))) {
return 64;
} else if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(
static_cast<JavaType *>(type))) {
return obj->GetByteSize() * 8;
}
return 0;
}
lldb::Encoding JavaASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
uint64_t &count) {
count = 1;
if (JavaPrimitiveType *ptype =
llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) {
switch (ptype->GetTypeKind()) {
case JavaPrimitiveType::eTypeByte:
case JavaPrimitiveType::eTypeShort:
case JavaPrimitiveType::eTypeInt:
case JavaPrimitiveType::eTypeLong:
return eEncodingSint;
case JavaPrimitiveType::eTypeFloat:
case JavaPrimitiveType::eTypeDouble:
return eEncodingIEEE754;
case JavaPrimitiveType::eTypeBoolean:
case JavaPrimitiveType::eTypeChar:
return eEncodingUint;
}
}
if (IsReferenceType(type))
return eEncodingUint;
return eEncodingInvalid;
}
lldb::Format JavaASTContext::GetFormat(lldb::opaque_compiler_type_t type) {
if (JavaPrimitiveType *ptype =
llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) {
switch (ptype->GetTypeKind()) {
case JavaPrimitiveType::eTypeByte:
case JavaPrimitiveType::eTypeShort:
case JavaPrimitiveType::eTypeInt:
case JavaPrimitiveType::eTypeLong:
return eFormatDecimal;
case JavaPrimitiveType::eTypeFloat:
case JavaPrimitiveType::eTypeDouble:
return eFormatFloat;
case JavaPrimitiveType::eTypeBoolean:
return eFormatBoolean;
case JavaPrimitiveType::eTypeChar:
return eFormatUnicode16;
}
}
if (IsReferenceType(type))
return eFormatHex;
return eFormatDefault;
}
unsigned JavaASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) {
return 0;
}
size_t
JavaASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
const char *s, uint8_t *dst,
size_t dst_size) {
assert(false && "Not implemented");
return 0;
}
size_t
JavaASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
return 0;
}
uint32_t JavaASTContext::GetNumFields(lldb::opaque_compiler_type_t type) {
if (JavaObjectType *obj =
llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
GetCompleteType(type);
return obj->GetNumFields();
}
return 0;
}
CompilerType JavaASTContext::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) {
if (bit_offset_ptr)
*bit_offset_ptr = 0;
if (bitfield_bit_size_ptr)
*bitfield_bit_size_ptr = 0;
if (is_bitfield_ptr)
*is_bitfield_ptr = false;
if (JavaObjectType *obj =
llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
GetCompleteType(type);
JavaObjectType::Field *field = obj->GetFieldAtIndex(idx);
if (!field)
return CompilerType();
name = field->m_name.AsCString();
if (bit_offset_ptr)
*bit_offset_ptr = field->m_offset * 8;
return field->m_type;
}
return CompilerType();
}
uint32_t JavaASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
bool omit_empty_base_classes) {
GetCompleteType(type);
if (JavaReferenceType *ref =
llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type)))
return ref->GetPointeeType().GetNumChildren(omit_empty_base_classes);
if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)))
return GetNumFields(type) + GetNumDirectBaseClasses(type);
return 0;
}
uint32_t
JavaASTContext::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) {
if (JavaObjectType *obj =
llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
GetCompleteType(type);
return obj->GetNumInterfaces() + (obj->GetBaseClass() ? 1 : 0);
}
return 0;
}
uint32_t
JavaASTContext::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) {
if (JavaObjectType *obj =
llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
GetCompleteType(type);
return obj->GetNumInterfaces();
}
return 0;
}
CompilerType JavaASTContext::GetDirectBaseClassAtIndex(
lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) {
if (JavaObjectType *obj =
llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
GetCompleteType(type);
if (CompilerType base_class = obj->GetBaseClass()) {
if (idx == 0)
return base_class;
else
--idx;
}
return obj->GetInterfaceAtIndex(idx);
}
return CompilerType();
}
CompilerType JavaASTContext::GetVirtualBaseClassAtIndex(
lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) {
if (JavaObjectType *obj =
llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
GetCompleteType(type);
return obj->GetInterfaceAtIndex(idx);
}
return CompilerType();
}
void JavaASTContext::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) {
assert(false && "Not implemented");
}
bool JavaASTContext::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) {
if (IsScalarType(type)) {
return DumpDataExtractor(data, s, data_offset, format, data_byte_size,
1, // count
UINT32_MAX, LLDB_INVALID_ADDRESS,
bitfield_bit_size, bitfield_bit_offset, exe_scope);
}
return false;
}
void JavaASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) {
StreamFile s(stdout, false);
DumpTypeDescription(type, &s);
}
void JavaASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type,
Stream *s) {
static_cast<JavaType *>(type)->Dump(s);
}
void JavaASTContext::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) {
assert(false && "Not implemented");
}
int JavaASTContext::GetFunctionArgumentCount(
lldb::opaque_compiler_type_t type) {
return 0;
}
CompilerType JavaASTContext::GetFunctionArgumentTypeAtIndex(
lldb::opaque_compiler_type_t type, size_t idx) {
return CompilerType();
}
CompilerType
JavaASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) {
return CompilerType();
}
size_t
JavaASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) {
return 0;
}
TypeMemberFunctionImpl
JavaASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
size_t idx) {
return TypeMemberFunctionImpl();
}
CompilerType JavaASTContext::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) {
child_name.clear();
child_byte_size = 0;
child_byte_offset = 0;
child_bitfield_bit_size = 0;
child_bitfield_bit_offset = 0;
child_is_base_class = false;
child_is_deref_of_parent = false;
language_flags = 0;
ExecutionContextScope *exec_ctx_scope =
exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
if (JavaObjectType *obj =
llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
GetCompleteType(type);
if (CompilerType base_class = obj->GetBaseClass()) {
if (idx == 0) {
JavaType *base_class_type =
static_cast<JavaType *>(base_class.GetOpaqueQualType());
child_name = base_class_type->GetName().GetCString();
child_byte_size = base_class.GetByteSize(
exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
child_byte_offset = obj->GetBaseClassOffset();
child_is_base_class = true;
return base_class;
}
idx -= 1;
}
JavaObjectType::Field *field = obj->GetFieldAtIndex(idx);
if (!field)
return CompilerType();
child_name = field->m_name.AsCString();
child_byte_size = field->m_type.GetByteSize(exec_ctx_scope);
child_byte_offset = field->m_offset;
return field->m_type;
} else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(
static_cast<JavaType *>(type))) {
CompilerType pointee_type = ref->GetPointeeType();
if (transparent_pointers)
return pointee_type.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);
if (idx != 0)
return CompilerType();
if (valobj && valobj->GetName())
child_name = valobj->GetName().GetCString();
child_is_deref_of_parent = true;
child_byte_offset = 0;
child_byte_size = pointee_type.GetByteSize(exec_ctx_scope);
return pointee_type;
}
return CompilerType();
}
uint32_t
JavaASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
const char *name,
bool omit_empty_base_classes) {
if (JavaObjectType *obj =
llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
GetCompleteType(type);
uint32_t index_offset = 0;
if (CompilerType base_class = obj->GetBaseClass()) {
if (base_class.GetTypeName() == ConstString(name))
return 0;
index_offset = 1;
}
for (uint32_t i = 0; i < obj->GetNumFields(); ++i) {
if (obj->GetFieldAtIndex(i)->m_name == ConstString(name))
return i + index_offset;
}
} else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(
static_cast<JavaType *>(type))) {
return GetIndexOfChildWithName(ref->GetPointeeType().GetOpaqueQualType(),
name, omit_empty_base_classes);
}
return UINT_MAX;
}
size_t JavaASTContext::GetIndexOfChildMemberWithName(
lldb::opaque_compiler_type_t type, const char *name,
bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
child_indexes.clear();
if (JavaObjectType *obj =
llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
GetCompleteType(type);
uint32_t index_offset = 0;
if (CompilerType base_class = obj->GetBaseClass()) {
if (GetIndexOfChildMemberWithName(base_class.GetOpaqueQualType(), name,
omit_empty_base_classes,
child_indexes) != 0) {
child_indexes.insert(child_indexes.begin(), 0);
return child_indexes.size();
}
index_offset = 1;
}
for (uint32_t i = 0; i < obj->GetNumFields(); ++i) {
if (obj->GetFieldAtIndex(i)->m_name == ConstString(name)) {
child_indexes.push_back(i + index_offset);
return child_indexes.size();
}
}
} else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(
static_cast<JavaType *>(type))) {
return GetIndexOfChildMemberWithName(
ref->GetPointeeType().GetOpaqueQualType(), name,
omit_empty_base_classes, child_indexes);
}
return 0;
}
CompilerType
JavaASTContext::GetLValueReferenceType(lldb::opaque_compiler_type_t type) {
return CreateReferenceType(CompilerType(this, type));
}
ConstString JavaASTContext::DeclContextGetScopeQualifiedName(
lldb::opaque_compiler_type_t opaque_decl_ctx) {
return GetTypeName(opaque_decl_ctx);
}
static void AddPrimitiveType(JavaASTContext::JavaTypeMap &type_map,
JavaPrimitiveType::TypeKind type_kind) {
JavaPrimitiveType *type = new JavaPrimitiveType(type_kind);
type_map.emplace(type->GetName(),
std::unique_ptr<JavaASTContext::JavaType>(type));
}
CompilerType JavaASTContext::CreateBaseType(const ConstString &name) {
if (m_base_type_map.empty()) {
AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeByte);
AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeShort);
AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeInt);
AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeLong);
AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeFloat);
AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeDouble);
AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeBoolean);
AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeChar);
}
auto it = m_base_type_map.find(name);
if (it != m_base_type_map.end())
return CompilerType(this, it->second.get());
return CompilerType();
}
CompilerType JavaASTContext::CreateObjectType(const ConstString &name,
const ConstString &linkage_name,
uint32_t byte_size) {
auto it = m_object_type_map.find(name);
if (it == m_object_type_map.end()) {
std::unique_ptr<JavaType> object_type(
new JavaObjectType(name, linkage_name, byte_size));
it = m_object_type_map.emplace(name, std::move(object_type)).first;
}
return CompilerType(this, it->second.get());
}
CompilerType JavaASTContext::CreateArrayType(
const ConstString &linkage_name, const CompilerType &element_type,
const DWARFExpression &length_expression, const lldb::addr_t data_offset) {
ConstString name = element_type.GetTypeName();
auto it = m_array_type_map.find(name);
if (it == m_array_type_map.end()) {
std::unique_ptr<JavaType> array_type(new JavaArrayType(
linkage_name, element_type, length_expression, data_offset));
it = m_array_type_map.emplace(name, std::move(array_type)).first;
}
return CompilerType(this, it->second.get());
}
CompilerType
JavaASTContext::CreateReferenceType(const CompilerType &pointee_type) {
ConstString name = pointee_type.GetTypeName();
auto it = m_reference_type_map.find(name);
if (it == m_reference_type_map.end())
it = m_reference_type_map
.emplace(name, std::unique_ptr<JavaType>(
new JavaReferenceType(pointee_type)))
.first;
return CompilerType(this, it->second.get());
}
void JavaASTContext::CompleteObjectType(const CompilerType &object_type) {
JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(
static_cast<JavaType *>(object_type.GetOpaqueQualType()));
assert(obj &&
"JavaASTContext::CompleteObjectType called with not a JavaObjectType");
obj->SetCompleteType(true);
}
void JavaASTContext::AddBaseClassToObject(const CompilerType &object_type,
const CompilerType &member_type,
uint32_t member_offset) {
JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(
static_cast<JavaType *>(object_type.GetOpaqueQualType()));
assert(obj &&
"JavaASTContext::AddMemberToObject called with not a JavaObjectType");
obj->AddBaseClass(member_type, member_offset);
}
void JavaASTContext::AddMemberToObject(const CompilerType &object_type,
const ConstString &name,
const CompilerType &member_type,
uint32_t member_offset) {
JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(
static_cast<JavaType *>(object_type.GetOpaqueQualType()));
assert(obj &&
"JavaASTContext::AddMemberToObject called with not a JavaObjectType");
obj->AddField(name, member_type, member_offset);
}
void JavaASTContext::SetDynamicTypeId(const CompilerType &type,
const DWARFExpression &type_id) {
JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(
static_cast<JavaType *>(type.GetOpaqueQualType()));
assert(obj &&
"JavaASTContext::SetDynamicTypeId called with not a JavaObjectType");
obj->SetDynamicTypeId(type_id);
}
uint64_t JavaASTContext::CalculateDynamicTypeId(ExecutionContext *exe_ctx,
const CompilerType &type,
ValueObject &in_value) {
if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(
static_cast<JavaType *>(type.GetOpaqueQualType())))
return obj->CalculateDynamicTypeId(exe_ctx, in_value);
if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(
static_cast<JavaType *>(type.GetOpaqueQualType())))
return arr->CalculateDynamicTypeId(exe_ctx, in_value);
return UINT64_MAX;
}
uint32_t JavaASTContext::CalculateArraySize(const CompilerType &type,
ValueObject &in_value) {
if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(
static_cast<JavaType *>(type.GetOpaqueQualType())))
return arr->GetNumElements(&in_value);
return UINT32_MAX;
}
uint64_t JavaASTContext::CalculateArrayElementOffset(const CompilerType &type,
size_t index) {
if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(
static_cast<JavaType *>(type.GetOpaqueQualType())))
return arr->GetElementOffset(index);
return UINT64_MAX;
}
ConstString JavaASTContext::GetLinkageName(const CompilerType &type) {
if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(
static_cast<JavaType *>(type.GetOpaqueQualType())))
return obj->GetLinkageName();
return ConstString();
}