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/Log.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"
23 #include "Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h"
26 using namespace lldb_private;
28 namespace lldb_private {
29 class OCamlASTContext::OCamlType {
39 OCamlType(LLVMCastKind kind) : m_kind(kind) {}
41 virtual ~OCamlType() = default;
43 virtual ConstString GetName() = 0;
45 virtual void Dump(Stream *s) = 0;
47 virtual bool IsCompleteType() = 0;
49 LLVMCastKind getKind() const { return m_kind; }
55 } // end of namespace lldb_private
59 class OCamlPrimitiveType : public OCamlASTContext::OCamlType {
65 OCamlPrimitiveType(TypeKind type_kind, uint32_t byte_size)
66 : OCamlType(OCamlType::eKindPrimitive), m_type_kind(type_kind),
67 m_type(ConstString()), m_byte_size(byte_size) {}
69 OCamlPrimitiveType(TypeKind type_kind, ConstString s, uint32_t byte_size)
70 : OCamlType(OCamlType::eKindPrimitive), m_type_kind(type_kind), m_type(s),
71 m_byte_size(byte_size) {}
73 ConstString GetName() override {
74 switch (m_type_kind) {
81 TypeKind GetTypeKind() { return m_type_kind; }
83 void Dump(Stream *s) override { s->Printf("%s\n", GetName().GetCString()); }
85 bool IsCompleteType() override { return true; }
87 static bool classof(const OCamlType *ot) {
88 return ot->getKind() == OCamlType::eKindPrimitive;
91 uint64_t GetByteSize() const { return m_byte_size; }
94 const TypeKind m_type_kind;
95 const ConstString m_type;
100 OCamlASTContext::OCamlASTContext()
101 : TypeSystem(eKindOCaml), m_pointer_byte_size(0) {}
103 OCamlASTContext::~OCamlASTContext() {}
105 ConstString OCamlASTContext::GetPluginNameStatic() {
106 return ConstString("ocaml");
109 ConstString OCamlASTContext::GetPluginName() {
110 return OCamlASTContext::GetPluginNameStatic();
113 uint32_t OCamlASTContext::GetPluginVersion() { return 1; }
115 lldb::TypeSystemSP OCamlASTContext::CreateInstance(lldb::LanguageType language,
118 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
120 if (language == lldb::eLanguageTypeOCaml) {
121 std::shared_ptr<OCamlASTContext> ocaml_ast_sp;
125 arch = module->GetArchitecture();
127 ObjectFile *objfile = module->GetObjectFile();
128 ArchSpec object_arch;
130 if (!objfile || !objfile->GetArchitecture(object_arch))
131 return lldb::TypeSystemSP();
133 ocaml_ast_sp = std::shared_ptr<OCamlASTContext>(new OCamlASTContext);
137 "((Module*)%p) [%s]->GetOCamlASTContext() = %p", (void *)module,
138 module->GetFileSpec().GetFilename().AsCString("<anonymous>"),
139 (void *)ocaml_ast_sp.get());
143 arch = target->GetArchitecture();
144 ocaml_ast_sp = std::shared_ptr<OCamlASTContextForExpr>(
145 new OCamlASTContextForExpr(target->shared_from_this()));
148 log->Printf("((Target*)%p)->GetOCamlASTContext() = %p", (void *)target,
149 (void *)ocaml_ast_sp.get());
153 if (arch.IsValid()) {
154 ocaml_ast_sp->SetAddressByteSize(arch.GetAddressByteSize());
159 return lldb::TypeSystemSP();
162 void OCamlASTContext::EnumerateSupportedLanguages(
163 std::set<lldb::LanguageType> &languages_for_types,
164 std::set<lldb::LanguageType> &languages_for_expressions) {
165 static std::vector<lldb::LanguageType> s_supported_languages_for_types(
166 {lldb::eLanguageTypeOCaml});
167 static std::vector<lldb::LanguageType> s_supported_languages_for_expressions(
170 languages_for_types.insert(s_supported_languages_for_types.begin(),
171 s_supported_languages_for_types.end());
172 languages_for_expressions.insert(
173 s_supported_languages_for_expressions.begin(),
174 s_supported_languages_for_expressions.end());
177 void OCamlASTContext::Initialize() {
178 PluginManager::RegisterPlugin(GetPluginNameStatic(),
179 "OCaml AST context plug-in", CreateInstance,
180 EnumerateSupportedLanguages);
183 void OCamlASTContext::Terminate() {
184 PluginManager::UnregisterPlugin(CreateInstance);
187 DWARFASTParser *OCamlASTContext::GetDWARFParser() {
188 if (!m_dwarf_ast_parser_ap) {
189 m_dwarf_ast_parser_ap.reset(new DWARFASTParserOCaml(*this));
192 return m_dwarf_ast_parser_ap.get();
195 bool OCamlASTContext::IsArrayType(lldb::opaque_compiler_type_t type,
196 CompilerType *element_type, uint64_t *size,
197 bool *is_incomplete) {
201 bool OCamlASTContext::IsVectorType(lldb::opaque_compiler_type_t type,
202 CompilerType *element_type, uint64_t *size) {
206 bool OCamlASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) {
210 bool OCamlASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) {
214 bool OCamlASTContext::IsCharType(lldb::opaque_compiler_type_t type) {
218 bool OCamlASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) {
219 return static_cast<OCamlPrimitiveType *>(type)->IsCompleteType();
222 bool OCamlASTContext::IsConst(lldb::opaque_compiler_type_t type) {
226 bool OCamlASTContext::IsCStringType(lldb::opaque_compiler_type_t type,
231 bool OCamlASTContext::IsDefined(lldb::opaque_compiler_type_t type) {
232 return type != nullptr;
235 bool OCamlASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type,
236 uint32_t &count, bool &is_complex) {
240 bool OCamlASTContext::IsFunctionType(lldb::opaque_compiler_type_t type,
241 bool *is_variadic_ptr) {
246 OCamlASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
247 CompilerType *base_type_ptr) {
251 size_t OCamlASTContext::GetNumberOfFunctionArguments(
252 lldb::opaque_compiler_type_t type) {
257 OCamlASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
258 const size_t index) {
259 return CompilerType();
262 bool OCamlASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) {
263 return IsFunctionType(type);
266 bool OCamlASTContext::IsBlockPointerType(
267 lldb::opaque_compiler_type_t type,
268 CompilerType *function_pointer_type_ptr) {
272 bool OCamlASTContext::IsIntegerType(lldb::opaque_compiler_type_t type,
274 if (OCamlPrimitiveType *ptype =
275 llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) {
276 switch (ptype->GetTypeKind()) {
277 case OCamlPrimitiveType::eTypeInt:
287 bool OCamlASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) {
291 bool OCamlASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
292 CompilerType *target_type,
293 bool check_cplusplus,
298 bool OCamlASTContext::IsRuntimeGeneratedType(
299 lldb::opaque_compiler_type_t type) {
303 bool OCamlASTContext::IsPointerType(lldb::opaque_compiler_type_t type,
304 CompilerType *pointee_type) {
306 pointee_type->Clear();
310 bool OCamlASTContext::IsPointerOrReferenceType(
311 lldb::opaque_compiler_type_t type, CompilerType *pointee_type) {
312 return IsPointerType(type, pointee_type);
315 bool OCamlASTContext::IsReferenceType(lldb::opaque_compiler_type_t type,
316 CompilerType *pointee_type,
321 bool OCamlASTContext::IsScalarType(lldb::opaque_compiler_type_t type) {
322 return llvm::isa<OCamlPrimitiveType>(static_cast<OCamlType *>(type));
325 bool OCamlASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) {
329 bool OCamlASTContext::IsVoidType(lldb::opaque_compiler_type_t type) {
333 bool OCamlASTContext::SupportsLanguage(lldb::LanguageType language) {
334 return language == lldb::eLanguageTypeOCaml;
337 bool OCamlASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) {
338 if (IsCompleteType(type))
344 uint32_t OCamlASTContext::GetPointerByteSize() { return m_pointer_byte_size; }
346 ConstString OCamlASTContext::GetTypeName(lldb::opaque_compiler_type_t type) {
348 return static_cast<OCamlPrimitiveType *>(type)->GetName();
350 return ConstString();
354 OCamlASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type,
355 CompilerType *pointee_or_element_compiler_type) {
356 if (pointee_or_element_compiler_type)
357 pointee_or_element_compiler_type->Clear();
361 if (OCamlPrimitiveType *ptype =
362 llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) {
363 switch (ptype->GetTypeKind()) {
364 case OCamlPrimitiveType::eTypeInt:
365 return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsInteger |
374 OCamlASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) {
375 if (llvm::isa<OCamlPrimitiveType>(static_cast<OCamlType *>(type)))
376 return eTypeClassBuiltin;
378 return lldb::eTypeClassInvalid;
382 OCamlASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) {
383 return lldb::eBasicTypeInvalid;
387 OCamlASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) {
388 return lldb::eLanguageTypeOCaml;
391 unsigned OCamlASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) {
395 //----------------------------------------------------------------------
396 // Creating related types
397 //----------------------------------------------------------------------
400 OCamlASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type,
402 return CompilerType();
406 OCamlASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) {
407 return CompilerType(this, type);
411 OCamlASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) {
412 return CompilerType(this, type);
415 int OCamlASTContext::GetFunctionArgumentCount(
416 lldb::opaque_compiler_type_t type) {
417 return GetNumberOfFunctionArguments(type);
420 CompilerType OCamlASTContext::GetFunctionArgumentTypeAtIndex(
421 lldb::opaque_compiler_type_t type, size_t idx) {
422 return GetFunctionArgumentAtIndex(type, idx);
426 OCamlASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) {
427 return CompilerType();
431 OCamlASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) {
435 TypeMemberFunctionImpl
436 OCamlASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
438 return TypeMemberFunctionImpl();
442 OCamlASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) {
443 return CompilerType(this, type);
447 OCamlASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) {
448 return CompilerType();
452 OCamlASTContext::GetPointerType(lldb::opaque_compiler_type_t type) {
453 return CompilerType();
457 OCamlASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) {
458 return CompilerType();
461 CompilerType OCamlASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) {
462 return CompilerType();
466 OCamlASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
468 return CompilerType();
471 uint64_t OCamlASTContext::GetBitSize(lldb::opaque_compiler_type_t type,
472 ExecutionContextScope *exe_scope) {
473 if (OCamlPrimitiveType *ptype =
474 llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) {
475 switch (ptype->GetTypeKind()) {
476 case OCamlPrimitiveType::eTypeInt:
477 return ptype->GetByteSize() * 8;
483 lldb::Encoding OCamlASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
487 if (IsIntegerType(type, is_signed))
488 return is_signed ? lldb::eEncodingSint : lldb::eEncodingUint;
490 uint32_t complex_count;
491 if (IsFloatingPointType(type, complex_count, is_complex)) {
492 count = complex_count;
493 return lldb::eEncodingIEEE754;
495 if (IsPointerType(type))
496 return lldb::eEncodingUint;
497 return lldb::eEncodingInvalid;
500 lldb::Format OCamlASTContext::GetFormat(lldb::opaque_compiler_type_t type) {
502 return lldb::eFormatDefault;
503 return lldb::eFormatBytes;
506 size_t OCamlASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) {
510 uint32_t OCamlASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
511 bool omit_empty_base_classes) {
512 if (!type || !GetCompleteType(type))
515 return GetNumFields(type);
518 uint32_t OCamlASTContext::GetNumFields(lldb::opaque_compiler_type_t type) {
519 if (!type || !GetCompleteType(type))
524 CompilerType OCamlASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
525 size_t idx, std::string &name,
526 uint64_t *bit_offset_ptr,
527 uint32_t *bitfield_bit_size_ptr,
528 bool *is_bitfield_ptr) {
531 if (bitfield_bit_size_ptr)
532 *bitfield_bit_size_ptr = 0;
534 *is_bitfield_ptr = false;
536 if (!type || !GetCompleteType(type))
537 return CompilerType();
539 return CompilerType();
542 CompilerType OCamlASTContext::GetChildCompilerTypeAtIndex(
543 lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
544 bool transparent_pointers, bool omit_empty_base_classes,
545 bool ignore_array_bounds, std::string &child_name,
546 uint32_t &child_byte_size, int32_t &child_byte_offset,
547 uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
548 bool &child_is_base_class, bool &child_is_deref_of_parent,
549 ValueObject *valobj, uint64_t &language_flags) {
552 child_byte_offset = 0;
553 child_bitfield_bit_size = 0;
554 child_bitfield_bit_offset = 0;
555 child_is_base_class = false;
556 child_is_deref_of_parent = false;
559 if (!type || !GetCompleteType(type))
560 return CompilerType();
562 return CompilerType();
566 OCamlASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
568 bool omit_empty_base_classes) {
569 if (!type || !GetCompleteType(type))
575 size_t OCamlASTContext::GetIndexOfChildMemberWithName(
576 lldb::opaque_compiler_type_t type, const char *name,
577 bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
578 uint32_t index = GetIndexOfChildWithName(type, name, omit_empty_base_classes);
579 if (index == UINT_MAX)
581 child_indexes.push_back(index);
586 OCamlASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
587 const char *s, uint8_t *dst,
592 //----------------------------------------------------------------------
594 //----------------------------------------------------------------------
596 void OCamlASTContext::DumpValue(
597 lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s,
598 lldb::Format format, const DataExtractor &data,
599 lldb::offset_t data_byte_offset, size_t data_byte_size,
600 uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types,
601 bool show_summary, bool verbose, uint32_t depth) {
603 s->Printf("no type\n");
607 s->Printf("no value\n");
610 DumpSummary(type, exe_ctx, s, data, data_byte_offset, data_byte_size);
613 bool OCamlASTContext::DumpTypeValue(
614 lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format,
615 const DataExtractor &data, lldb::offset_t byte_offset, size_t byte_size,
616 uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
617 ExecutionContextScope *exe_scope) {
619 s->Printf("no type value\n");
623 if (IsScalarType(type)) {
624 return data.Dump(s, byte_offset, format, byte_size, 1, SIZE_MAX,
625 LLDB_INVALID_ADDRESS, bitfield_bit_size,
626 bitfield_bit_offset, exe_scope);
632 void OCamlASTContext::DumpSummary(lldb::opaque_compiler_type_t type,
633 ExecutionContext *exe_ctx, Stream *s,
634 const DataExtractor &data,
635 lldb::offset_t data_offset,
636 size_t data_byte_size) {
637 s->Printf("no summary\n");
640 void OCamlASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) {
641 StreamFile s(stdout, false);
642 DumpTypeDescription(type, &s);
645 void OCamlASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type,
647 static_cast<OCamlType *>(type)->Dump(s);
650 CompilerType OCamlASTContext::CreateBaseType(const ConstString &name,
651 uint64_t byte_size) {
652 if (m_base_type_map.empty()) {
653 OCamlPrimitiveType *type = new OCamlPrimitiveType(
654 OCamlPrimitiveType::eTypeInt, ConstString("ocaml_int"), byte_size);
655 m_base_type_map.emplace(type->GetName(),
656 std::unique_ptr<OCamlASTContext::OCamlType>(type));
659 auto it = m_base_type_map.find(name);
660 if (it == m_base_type_map.end()) {
661 OCamlPrimitiveType *type =
662 new OCamlPrimitiveType(OCamlPrimitiveType::eTypeInt, name, byte_size);
664 .emplace(name, std::unique_ptr<OCamlASTContext::OCamlType>(type))
668 return CompilerType(this, it->second.get());