1 //===-- OCamlASTContext.cpp ----------------------------------------*- C++
4 // The LLVM Compiler Infrastructure
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
9 //===----------------------------------------------------------------------===//
11 #include "lldb/Symbol/OCamlASTContext.h"
12 #include "lldb/Core/DumpDataExtractor.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/PluginManager.h"
15 #include "lldb/Core/StreamFile.h"
16 #include "lldb/Core/ValueObject.h"
17 #include "lldb/Symbol/ObjectFile.h"
18 #include "lldb/Symbol/SymbolFile.h"
19 #include "lldb/Symbol/Type.h"
20 #include "lldb/Target/ExecutionContext.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Utility/Log.h"
24 #include "Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h"
27 using namespace lldb_private;
29 namespace lldb_private {
30 class OCamlASTContext::OCamlType {
40 OCamlType(LLVMCastKind kind) : m_kind(kind) {}
42 virtual ~OCamlType() = default;
44 virtual ConstString GetName() = 0;
46 virtual void Dump(Stream *s) = 0;
48 virtual bool IsCompleteType() = 0;
50 LLVMCastKind getKind() const { return m_kind; }
56 } // end of namespace lldb_private
60 class OCamlPrimitiveType : public OCamlASTContext::OCamlType {
66 OCamlPrimitiveType(TypeKind type_kind, uint32_t byte_size)
67 : OCamlType(OCamlType::eKindPrimitive), m_type_kind(type_kind),
68 m_type(ConstString()), m_byte_size(byte_size) {}
70 OCamlPrimitiveType(TypeKind type_kind, ConstString s, uint32_t byte_size)
71 : OCamlType(OCamlType::eKindPrimitive), m_type_kind(type_kind), m_type(s),
72 m_byte_size(byte_size) {}
74 ConstString GetName() override {
75 switch (m_type_kind) {
82 TypeKind GetTypeKind() { return m_type_kind; }
84 void Dump(Stream *s) override { s->Printf("%s\n", GetName().GetCString()); }
86 bool IsCompleteType() override { return true; }
88 static bool classof(const OCamlType *ot) {
89 return ot->getKind() == OCamlType::eKindPrimitive;
92 uint64_t GetByteSize() const { return m_byte_size; }
95 const TypeKind m_type_kind;
96 const ConstString m_type;
101 OCamlASTContext::OCamlASTContext()
102 : TypeSystem(eKindOCaml), m_pointer_byte_size(0) {}
104 OCamlASTContext::~OCamlASTContext() {}
106 ConstString OCamlASTContext::GetPluginNameStatic() {
107 return ConstString("ocaml");
110 ConstString OCamlASTContext::GetPluginName() {
111 return OCamlASTContext::GetPluginNameStatic();
114 uint32_t OCamlASTContext::GetPluginVersion() { return 1; }
116 lldb::TypeSystemSP OCamlASTContext::CreateInstance(lldb::LanguageType language,
119 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
121 if (language == lldb::eLanguageTypeOCaml) {
122 std::shared_ptr<OCamlASTContext> ocaml_ast_sp;
126 arch = module->GetArchitecture();
128 ObjectFile *objfile = module->GetObjectFile();
129 ArchSpec object_arch;
131 if (!objfile || !objfile->GetArchitecture(object_arch))
132 return lldb::TypeSystemSP();
134 ocaml_ast_sp = std::shared_ptr<OCamlASTContext>(new OCamlASTContext);
138 "((Module*)%p) [%s]->GetOCamlASTContext() = %p", (void *)module,
139 module->GetFileSpec().GetFilename().AsCString("<anonymous>"),
140 (void *)ocaml_ast_sp.get());
144 arch = target->GetArchitecture();
145 ocaml_ast_sp = std::shared_ptr<OCamlASTContextForExpr>(
146 new OCamlASTContextForExpr(target->shared_from_this()));
149 log->Printf("((Target*)%p)->GetOCamlASTContext() = %p", (void *)target,
150 (void *)ocaml_ast_sp.get());
154 if (arch.IsValid()) {
155 ocaml_ast_sp->SetAddressByteSize(arch.GetAddressByteSize());
160 return lldb::TypeSystemSP();
163 void OCamlASTContext::EnumerateSupportedLanguages(
164 std::set<lldb::LanguageType> &languages_for_types,
165 std::set<lldb::LanguageType> &languages_for_expressions) {
166 static std::vector<lldb::LanguageType> s_supported_languages_for_types(
167 {lldb::eLanguageTypeOCaml});
168 static std::vector<lldb::LanguageType> s_supported_languages_for_expressions(
171 languages_for_types.insert(s_supported_languages_for_types.begin(),
172 s_supported_languages_for_types.end());
173 languages_for_expressions.insert(
174 s_supported_languages_for_expressions.begin(),
175 s_supported_languages_for_expressions.end());
178 void OCamlASTContext::Initialize() {
179 PluginManager::RegisterPlugin(GetPluginNameStatic(),
180 "OCaml AST context plug-in", CreateInstance,
181 EnumerateSupportedLanguages);
184 void OCamlASTContext::Terminate() {
185 PluginManager::UnregisterPlugin(CreateInstance);
188 DWARFASTParser *OCamlASTContext::GetDWARFParser() {
189 if (!m_dwarf_ast_parser_ap) {
190 m_dwarf_ast_parser_ap.reset(new DWARFASTParserOCaml(*this));
193 return m_dwarf_ast_parser_ap.get();
196 bool OCamlASTContext::IsArrayType(lldb::opaque_compiler_type_t type,
197 CompilerType *element_type, uint64_t *size,
198 bool *is_incomplete) {
202 bool OCamlASTContext::IsVectorType(lldb::opaque_compiler_type_t type,
203 CompilerType *element_type, uint64_t *size) {
207 bool OCamlASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) {
211 bool OCamlASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) {
215 bool OCamlASTContext::IsCharType(lldb::opaque_compiler_type_t type) {
219 bool OCamlASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) {
220 return static_cast<OCamlPrimitiveType *>(type)->IsCompleteType();
223 bool OCamlASTContext::IsConst(lldb::opaque_compiler_type_t type) {
227 bool OCamlASTContext::IsCStringType(lldb::opaque_compiler_type_t type,
232 bool OCamlASTContext::IsDefined(lldb::opaque_compiler_type_t type) {
233 return type != nullptr;
236 bool OCamlASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type,
237 uint32_t &count, bool &is_complex) {
241 bool OCamlASTContext::IsFunctionType(lldb::opaque_compiler_type_t type,
242 bool *is_variadic_ptr) {
247 OCamlASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
248 CompilerType *base_type_ptr) {
252 size_t OCamlASTContext::GetNumberOfFunctionArguments(
253 lldb::opaque_compiler_type_t type) {
258 OCamlASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
259 const size_t index) {
260 return CompilerType();
263 bool OCamlASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) {
264 return IsFunctionType(type);
267 bool OCamlASTContext::IsBlockPointerType(
268 lldb::opaque_compiler_type_t type,
269 CompilerType *function_pointer_type_ptr) {
273 bool OCamlASTContext::IsIntegerType(lldb::opaque_compiler_type_t type,
275 if (OCamlPrimitiveType *ptype =
276 llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) {
277 switch (ptype->GetTypeKind()) {
278 case OCamlPrimitiveType::eTypeInt:
288 bool OCamlASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) {
292 bool OCamlASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
293 CompilerType *target_type,
294 bool check_cplusplus,
299 bool OCamlASTContext::IsRuntimeGeneratedType(
300 lldb::opaque_compiler_type_t type) {
304 bool OCamlASTContext::IsPointerType(lldb::opaque_compiler_type_t type,
305 CompilerType *pointee_type) {
307 pointee_type->Clear();
311 bool OCamlASTContext::IsPointerOrReferenceType(
312 lldb::opaque_compiler_type_t type, CompilerType *pointee_type) {
313 return IsPointerType(type, pointee_type);
316 bool OCamlASTContext::IsReferenceType(lldb::opaque_compiler_type_t type,
317 CompilerType *pointee_type,
322 bool OCamlASTContext::IsScalarType(lldb::opaque_compiler_type_t type) {
323 return llvm::isa<OCamlPrimitiveType>(static_cast<OCamlType *>(type));
326 bool OCamlASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) {
330 bool OCamlASTContext::IsVoidType(lldb::opaque_compiler_type_t type) {
334 bool OCamlASTContext::SupportsLanguage(lldb::LanguageType language) {
335 return language == lldb::eLanguageTypeOCaml;
338 bool OCamlASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) {
339 if (IsCompleteType(type))
345 uint32_t OCamlASTContext::GetPointerByteSize() { return m_pointer_byte_size; }
347 ConstString OCamlASTContext::GetTypeName(lldb::opaque_compiler_type_t type) {
349 return static_cast<OCamlPrimitiveType *>(type)->GetName();
351 return ConstString();
355 OCamlASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type,
356 CompilerType *pointee_or_element_compiler_type) {
357 if (pointee_or_element_compiler_type)
358 pointee_or_element_compiler_type->Clear();
362 if (OCamlPrimitiveType *ptype =
363 llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) {
364 switch (ptype->GetTypeKind()) {
365 case OCamlPrimitiveType::eTypeInt:
366 return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsInteger |
375 OCamlASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) {
376 if (llvm::isa<OCamlPrimitiveType>(static_cast<OCamlType *>(type)))
377 return eTypeClassBuiltin;
379 return lldb::eTypeClassInvalid;
383 OCamlASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) {
384 return lldb::eBasicTypeInvalid;
388 OCamlASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) {
389 return lldb::eLanguageTypeOCaml;
392 unsigned OCamlASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) {
396 //----------------------------------------------------------------------
397 // Creating related types
398 //----------------------------------------------------------------------
401 OCamlASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type,
403 return CompilerType();
407 OCamlASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) {
408 return CompilerType(this, type);
412 OCamlASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) {
413 return CompilerType(this, type);
416 int OCamlASTContext::GetFunctionArgumentCount(
417 lldb::opaque_compiler_type_t type) {
418 return GetNumberOfFunctionArguments(type);
421 CompilerType OCamlASTContext::GetFunctionArgumentTypeAtIndex(
422 lldb::opaque_compiler_type_t type, size_t idx) {
423 return GetFunctionArgumentAtIndex(type, idx);
427 OCamlASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) {
428 return CompilerType();
432 OCamlASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) {
436 TypeMemberFunctionImpl
437 OCamlASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
439 return TypeMemberFunctionImpl();
443 OCamlASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) {
444 return CompilerType(this, type);
448 OCamlASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) {
449 return CompilerType();
453 OCamlASTContext::GetPointerType(lldb::opaque_compiler_type_t type) {
454 return CompilerType();
458 OCamlASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) {
459 return CompilerType();
462 CompilerType OCamlASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) {
463 return CompilerType();
467 OCamlASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
469 return CompilerType();
472 uint64_t OCamlASTContext::GetBitSize(lldb::opaque_compiler_type_t type,
473 ExecutionContextScope *exe_scope) {
474 if (OCamlPrimitiveType *ptype =
475 llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) {
476 switch (ptype->GetTypeKind()) {
477 case OCamlPrimitiveType::eTypeInt:
478 return ptype->GetByteSize() * 8;
484 lldb::Encoding OCamlASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
488 if (IsIntegerType(type, is_signed))
489 return is_signed ? lldb::eEncodingSint : lldb::eEncodingUint;
491 uint32_t complex_count;
492 if (IsFloatingPointType(type, complex_count, is_complex)) {
493 count = complex_count;
494 return lldb::eEncodingIEEE754;
496 if (IsPointerType(type))
497 return lldb::eEncodingUint;
498 return lldb::eEncodingInvalid;
501 lldb::Format OCamlASTContext::GetFormat(lldb::opaque_compiler_type_t type) {
503 return lldb::eFormatDefault;
504 return lldb::eFormatBytes;
507 size_t OCamlASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) {
511 uint32_t OCamlASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
512 bool omit_empty_base_classes) {
513 if (!type || !GetCompleteType(type))
516 return GetNumFields(type);
519 uint32_t OCamlASTContext::GetNumFields(lldb::opaque_compiler_type_t type) {
520 if (!type || !GetCompleteType(type))
525 CompilerType OCamlASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
526 size_t idx, std::string &name,
527 uint64_t *bit_offset_ptr,
528 uint32_t *bitfield_bit_size_ptr,
529 bool *is_bitfield_ptr) {
532 if (bitfield_bit_size_ptr)
533 *bitfield_bit_size_ptr = 0;
535 *is_bitfield_ptr = false;
537 if (!type || !GetCompleteType(type))
538 return CompilerType();
540 return CompilerType();
543 CompilerType OCamlASTContext::GetChildCompilerTypeAtIndex(
544 lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
545 bool transparent_pointers, bool omit_empty_base_classes,
546 bool ignore_array_bounds, std::string &child_name,
547 uint32_t &child_byte_size, int32_t &child_byte_offset,
548 uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
549 bool &child_is_base_class, bool &child_is_deref_of_parent,
550 ValueObject *valobj, uint64_t &language_flags) {
553 child_byte_offset = 0;
554 child_bitfield_bit_size = 0;
555 child_bitfield_bit_offset = 0;
556 child_is_base_class = false;
557 child_is_deref_of_parent = false;
560 if (!type || !GetCompleteType(type))
561 return CompilerType();
563 return CompilerType();
567 OCamlASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
569 bool omit_empty_base_classes) {
570 if (!type || !GetCompleteType(type))
576 size_t OCamlASTContext::GetIndexOfChildMemberWithName(
577 lldb::opaque_compiler_type_t type, const char *name,
578 bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
579 uint32_t index = GetIndexOfChildWithName(type, name, omit_empty_base_classes);
580 if (index == UINT_MAX)
582 child_indexes.push_back(index);
587 OCamlASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
588 const char *s, uint8_t *dst,
593 //----------------------------------------------------------------------
595 //----------------------------------------------------------------------
597 void OCamlASTContext::DumpValue(
598 lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s,
599 lldb::Format format, const DataExtractor &data,
600 lldb::offset_t data_byte_offset, size_t data_byte_size,
601 uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types,
602 bool show_summary, bool verbose, uint32_t depth) {
604 s->Printf("no type\n");
608 s->Printf("no value\n");
611 DumpSummary(type, exe_ctx, s, data, data_byte_offset, data_byte_size);
614 bool OCamlASTContext::DumpTypeValue(
615 lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format,
616 const DataExtractor &data, lldb::offset_t byte_offset, size_t byte_size,
617 uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
618 ExecutionContextScope *exe_scope) {
620 s->Printf("no type value\n");
624 if (IsScalarType(type)) {
625 return DumpDataExtractor(data, s, byte_offset, format, byte_size, 1,
626 SIZE_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size,
627 bitfield_bit_offset, exe_scope);
633 void OCamlASTContext::DumpSummary(lldb::opaque_compiler_type_t type,
634 ExecutionContext *exe_ctx, Stream *s,
635 const DataExtractor &data,
636 lldb::offset_t data_offset,
637 size_t data_byte_size) {
638 s->Printf("no summary\n");
641 void OCamlASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) {
642 StreamFile s(stdout, false);
643 DumpTypeDescription(type, &s);
646 void OCamlASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type,
648 static_cast<OCamlType *>(type)->Dump(s);
651 CompilerType OCamlASTContext::CreateBaseType(const ConstString &name,
652 uint64_t byte_size) {
653 if (m_base_type_map.empty()) {
654 OCamlPrimitiveType *type = new OCamlPrimitiveType(
655 OCamlPrimitiveType::eTypeInt, ConstString("ocaml_int"), byte_size);
656 m_base_type_map.emplace(type->GetName(),
657 std::unique_ptr<OCamlASTContext::OCamlType>(type));
660 auto it = m_base_type_map.find(name);
661 if (it == m_base_type_map.end()) {
662 OCamlPrimitiveType *type =
663 new OCamlPrimitiveType(OCamlPrimitiveType::eTypeInt, name, byte_size);
665 .emplace(name, std::unique_ptr<OCamlASTContext::OCamlType>(type))
669 return CompilerType(this, it->second.get());