//===-- OCamlASTContext.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/OCamlASTContext.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/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/Type.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Target.h" #include "lldb/Utility/Log.h" #include "Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h" using namespace lldb; using namespace lldb_private; namespace lldb_private { class OCamlASTContext::OCamlType { public: enum LLVMCastKind { eKindPrimitive, eKindObject, eKindReference, eKindArray, kNumKinds }; OCamlType(LLVMCastKind kind) : m_kind(kind) {} virtual ~OCamlType() = 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 OCamlPrimitiveType : public OCamlASTContext::OCamlType { public: enum TypeKind { eTypeInt, }; OCamlPrimitiveType(TypeKind type_kind, uint32_t byte_size) : OCamlType(OCamlType::eKindPrimitive), m_type_kind(type_kind), m_type(ConstString()), m_byte_size(byte_size) {} OCamlPrimitiveType(TypeKind type_kind, ConstString s, uint32_t byte_size) : OCamlType(OCamlType::eKindPrimitive), m_type_kind(type_kind), m_type(s), m_byte_size(byte_size) {} ConstString GetName() override { switch (m_type_kind) { case eTypeInt: return m_type; } 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 OCamlType *ot) { return ot->getKind() == OCamlType::eKindPrimitive; } uint64_t GetByteSize() const { return m_byte_size; } private: const TypeKind m_type_kind; const ConstString m_type; uint64_t m_byte_size; }; } OCamlASTContext::OCamlASTContext() : TypeSystem(eKindOCaml), m_pointer_byte_size(0) {} OCamlASTContext::~OCamlASTContext() {} ConstString OCamlASTContext::GetPluginNameStatic() { return ConstString("ocaml"); } ConstString OCamlASTContext::GetPluginName() { return OCamlASTContext::GetPluginNameStatic(); } uint32_t OCamlASTContext::GetPluginVersion() { return 1; } lldb::TypeSystemSP OCamlASTContext::CreateInstance(lldb::LanguageType language, Module *module, Target *target) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (language == lldb::eLanguageTypeOCaml) { std::shared_ptr ocaml_ast_sp; ArchSpec arch; if (module) { arch = module->GetArchitecture(); ObjectFile *objfile = module->GetObjectFile(); ArchSpec object_arch; if (!objfile || !objfile->GetArchitecture(object_arch)) return lldb::TypeSystemSP(); ocaml_ast_sp = std::shared_ptr(new OCamlASTContext); if (log) { log->Printf( "((Module*)%p) [%s]->GetOCamlASTContext() = %p", (void *)module, module->GetFileSpec().GetFilename().AsCString(""), (void *)ocaml_ast_sp.get()); } } else if (target) { arch = target->GetArchitecture(); ocaml_ast_sp = std::shared_ptr( new OCamlASTContextForExpr(target->shared_from_this())); if (log) { log->Printf("((Target*)%p)->GetOCamlASTContext() = %p", (void *)target, (void *)ocaml_ast_sp.get()); } } if (arch.IsValid()) { ocaml_ast_sp->SetAddressByteSize(arch.GetAddressByteSize()); return ocaml_ast_sp; } } return lldb::TypeSystemSP(); } void OCamlASTContext::EnumerateSupportedLanguages( std::set &languages_for_types, std::set &languages_for_expressions) { static std::vector s_supported_languages_for_types( {lldb::eLanguageTypeOCaml}); static std::vector s_supported_languages_for_expressions( {}); 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()); } void OCamlASTContext::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), "OCaml AST context plug-in", CreateInstance, EnumerateSupportedLanguages); } void OCamlASTContext::Terminate() { PluginManager::UnregisterPlugin(CreateInstance); } DWARFASTParser *OCamlASTContext::GetDWARFParser() { if (!m_dwarf_ast_parser_ap) { m_dwarf_ast_parser_ap.reset(new DWARFASTParserOCaml(*this)); } return m_dwarf_ast_parser_ap.get(); } bool OCamlASTContext::IsArrayType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size, bool *is_incomplete) { return false; } bool OCamlASTContext::IsVectorType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size) { return false; } bool OCamlASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) { return false; } bool OCamlASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) { return false; } bool OCamlASTContext::IsCharType(lldb::opaque_compiler_type_t type) { return false; } bool OCamlASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) { return static_cast(type)->IsCompleteType(); } bool OCamlASTContext::IsConst(lldb::opaque_compiler_type_t type) { return false; } bool OCamlASTContext::IsCStringType(lldb::opaque_compiler_type_t type, uint32_t &length) { return false; } bool OCamlASTContext::IsDefined(lldb::opaque_compiler_type_t type) { return type != nullptr; } bool OCamlASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex) { return false; } bool OCamlASTContext::IsFunctionType(lldb::opaque_compiler_type_t type, bool *is_variadic_ptr) { return false; } uint32_t OCamlASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, CompilerType *base_type_ptr) { return false; } size_t OCamlASTContext::GetNumberOfFunctionArguments( lldb::opaque_compiler_type_t type) { return 0; } CompilerType OCamlASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, const size_t index) { return CompilerType(); } bool OCamlASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) { return IsFunctionType(type); } bool OCamlASTContext::IsBlockPointerType( lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) { return false; } bool OCamlASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) { if (OCamlPrimitiveType *ptype = llvm::dyn_cast(static_cast(type))) { switch (ptype->GetTypeKind()) { case OCamlPrimitiveType::eTypeInt: is_signed = true; return true; } } is_signed = false; return false; } bool OCamlASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) { return false; } bool OCamlASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, CompilerType *target_type, bool check_cplusplus, bool check_objc) { return false; } bool OCamlASTContext::IsRuntimeGeneratedType( lldb::opaque_compiler_type_t type) { return false; } bool OCamlASTContext::IsPointerType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type) { if (pointee_type) pointee_type->Clear(); return false; } bool OCamlASTContext::IsPointerOrReferenceType( lldb::opaque_compiler_type_t type, CompilerType *pointee_type) { return IsPointerType(type, pointee_type); } bool OCamlASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type, bool *is_rvalue) { return false; } bool OCamlASTContext::IsScalarType(lldb::opaque_compiler_type_t type) { return llvm::isa(static_cast(type)); } bool OCamlASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) { return false; } bool OCamlASTContext::IsVoidType(lldb::opaque_compiler_type_t type) { return false; } bool OCamlASTContext::SupportsLanguage(lldb::LanguageType language) { return language == lldb::eLanguageTypeOCaml; } bool OCamlASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) { if (IsCompleteType(type)) return true; return false; } uint32_t OCamlASTContext::GetPointerByteSize() { return m_pointer_byte_size; } ConstString OCamlASTContext::GetTypeName(lldb::opaque_compiler_type_t type) { if (type) return static_cast(type)->GetName(); return ConstString(); } uint32_t OCamlASTContext::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 (OCamlPrimitiveType *ptype = llvm::dyn_cast(static_cast(type))) { switch (ptype->GetTypeKind()) { case OCamlPrimitiveType::eTypeInt: return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsInteger | eTypeIsSigned; } } return 0; } lldb::TypeClass OCamlASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) { if (llvm::isa(static_cast(type))) return eTypeClassBuiltin; return lldb::eTypeClassInvalid; } lldb::BasicType OCamlASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) { return lldb::eBasicTypeInvalid; } lldb::LanguageType OCamlASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) { return lldb::eLanguageTypeOCaml; } unsigned OCamlASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) { return 0; } //---------------------------------------------------------------------- // Creating related types //---------------------------------------------------------------------- CompilerType OCamlASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, uint64_t *stride) { return CompilerType(); } CompilerType OCamlASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) { return CompilerType(this, type); } CompilerType OCamlASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) { return CompilerType(this, type); } int OCamlASTContext::GetFunctionArgumentCount( lldb::opaque_compiler_type_t type) { return GetNumberOfFunctionArguments(type); } CompilerType OCamlASTContext::GetFunctionArgumentTypeAtIndex( lldb::opaque_compiler_type_t type, size_t idx) { return GetFunctionArgumentAtIndex(type, idx); } CompilerType OCamlASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) { return CompilerType(); } size_t OCamlASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) { return 0; } TypeMemberFunctionImpl OCamlASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, size_t idx) { return TypeMemberFunctionImpl(); } CompilerType OCamlASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) { return CompilerType(this, type); } CompilerType OCamlASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) { return CompilerType(); } CompilerType OCamlASTContext::GetPointerType(lldb::opaque_compiler_type_t type) { return CompilerType(); } CompilerType OCamlASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) { return CompilerType(); } CompilerType OCamlASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) { return CompilerType(); } CompilerType OCamlASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size) { return CompilerType(); } uint64_t OCamlASTContext::GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) { if (OCamlPrimitiveType *ptype = llvm::dyn_cast(static_cast(type))) { switch (ptype->GetTypeKind()) { case OCamlPrimitiveType::eTypeInt: return ptype->GetByteSize() * 8; } } return 0; } lldb::Encoding OCamlASTContext::GetEncoding(lldb::opaque_compiler_type_t type, uint64_t &count) { count = 1; bool is_signed; if (IsIntegerType(type, is_signed)) return is_signed ? lldb::eEncodingSint : lldb::eEncodingUint; bool is_complex; uint32_t complex_count; if (IsFloatingPointType(type, complex_count, is_complex)) { count = complex_count; return lldb::eEncodingIEEE754; } if (IsPointerType(type)) return lldb::eEncodingUint; return lldb::eEncodingInvalid; } lldb::Format OCamlASTContext::GetFormat(lldb::opaque_compiler_type_t type) { if (!type) return lldb::eFormatDefault; return lldb::eFormatBytes; } size_t OCamlASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) { return 0; } uint32_t OCamlASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, bool omit_empty_base_classes) { if (!type || !GetCompleteType(type)) return 0; return GetNumFields(type); } uint32_t OCamlASTContext::GetNumFields(lldb::opaque_compiler_type_t type) { if (!type || !GetCompleteType(type)) return 0; return 0; } CompilerType OCamlASTContext::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 (!type || !GetCompleteType(type)) return CompilerType(); return CompilerType(); } CompilerType OCamlASTContext::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; if (!type || !GetCompleteType(type)) return CompilerType(); return CompilerType(); } uint32_t OCamlASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, const char *name, bool omit_empty_base_classes) { if (!type || !GetCompleteType(type)) return UINT_MAX; return UINT_MAX; } size_t OCamlASTContext::GetIndexOfChildMemberWithName( lldb::opaque_compiler_type_t type, const char *name, bool omit_empty_base_classes, std::vector &child_indexes) { uint32_t index = GetIndexOfChildWithName(type, name, omit_empty_base_classes); if (index == UINT_MAX) return 0; child_indexes.push_back(index); return 1; } size_t OCamlASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, const char *s, uint8_t *dst, size_t dst_size) { assert(false); return 0; } //---------------------------------------------------------------------- // Dumping types //---------------------------------------------------------------------- void OCamlASTContext::DumpValue( lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format, const 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) { if (!type) { s->Printf("no type\n"); return; } s->Printf("no value\n"); if (show_summary) DumpSummary(type, exe_ctx, s, data, data_byte_offset, data_byte_size); } bool OCamlASTContext::DumpTypeValue( lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format, const DataExtractor &data, lldb::offset_t byte_offset, size_t byte_size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope) { if (!type) { s->Printf("no type value\n"); return false; } if (IsScalarType(type)) { return DumpDataExtractor(data, s, byte_offset, format, byte_size, 1, SIZE_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size, bitfield_bit_offset, exe_scope); } return false; } void OCamlASTContext::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) { s->Printf("no summary\n"); } void OCamlASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) { StreamFile s(stdout, false); DumpTypeDescription(type, &s); } void OCamlASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, Stream *s) { static_cast(type)->Dump(s); } CompilerType OCamlASTContext::CreateBaseType(const ConstString &name, uint64_t byte_size) { if (m_base_type_map.empty()) { OCamlPrimitiveType *type = new OCamlPrimitiveType( OCamlPrimitiveType::eTypeInt, ConstString("ocaml_int"), byte_size); m_base_type_map.emplace(type->GetName(), std::unique_ptr(type)); } auto it = m_base_type_map.find(name); if (it == m_base_type_map.end()) { OCamlPrimitiveType *type = new OCamlPrimitiveType(OCamlPrimitiveType::eTypeInt, name, byte_size); it = m_base_type_map .emplace(name, std::unique_ptr(type)) .first; } return CompilerType(this, it->second.get()); }