[Lldb-commits] [lldb] [llvm] lldb simplified template names rebuild without clang ast (PR #90008)
David Blaikie via lldb-commits
lldb-commits at lists.llvm.org
Wed Sep 11 09:21:02 PDT 2024
https://github.com/dwblaikie updated https://github.com/llvm/llvm-project/pull/90008
>From 2922fed151d345f12b944754fa10b9994acc7edb Mon Sep 17 00:00:00 2001
From: David Blaikie <dblaikie at gmail.com>
Date: Fri, 19 Apr 2024 03:34:27 +0000
Subject: [PATCH 1/7] DO NOT SUBMIT: lldb DWARF-Clang AST parsing tracing
---
.../SymbolFile/DWARF/DWARFASTParserClang.cpp | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index dc4cfc96b86f0e..971bddc3e78675 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include <cstdlib>
+#include <iostream>
#include "DWARFASTParser.h"
#include "DWARFASTParserClang.h"
@@ -1621,6 +1622,15 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) {
const char *name = die.GetName();
if (!name)
return "";
+ static int indent = 0;
+ std::cerr << std::string(indent, ' ') << "starting qualified name for: " << name << '\n';
+ auto &FS = die.GetCU()->GetSymbolFileDWARF().GetObjectFile()->GetFileSpec();
+ std::string Directory = FS.GetDirectory().AsCString("");
+ std::cerr << std::string(indent, ' ')
+ << Directory.substr(std::min(59ul, Directory.size())) << '/'
+ << FS.GetFilename().AsCString("") << ':' << std::hex
+ << die.GetDIE()->GetOffset() << '\n';
+ ++indent;
std::string qualified_name;
DWARFDIE parent_decl_ctx_die = die.GetParentDeclContextDIE();
// TODO: change this to get the correct decl context parent....
@@ -1666,6 +1676,9 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) {
qualified_name.append(name);
qualified_name.append(GetDIEClassTemplateParams(die).AsCString(""));
+ --indent;
+ std::cerr << std::string(indent, ' ') << "computed qualified name: " << qualified_name << '\n';
+
return qualified_name;
}
>From b98e417de184ea44ce7a88241cd03f07be0e94ec Mon Sep 17 00:00:00 2001
From: David Blaikie <dblaikie at gmail.com>
Date: Thu, 25 Apr 2024 00:28:57 +0000
Subject: [PATCH 2/7] Fix scope operator ordering
---
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 971bddc3e78675..0c605893293712 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -1655,9 +1655,9 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) {
case DW_TAG_structure_type:
case DW_TAG_union_type: {
if (const char *class_union_struct_name = parent_decl_ctx_die.GetName()) {
+ qualified_name.insert(0, "::");
qualified_name.insert(
0, GetDIEClassTemplateParams(parent_decl_ctx_die).AsCString(""));
- qualified_name.insert(0, "::");
qualified_name.insert(0, class_union_struct_name);
}
parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();
>From 3966ec6c39262f5e055e9cb7deded5f6554a8d8d Mon Sep 17 00:00:00 2001
From: David Blaikie <dblaikie at gmail.com>
Date: Thu, 25 Apr 2024 00:46:48 +0000
Subject: [PATCH 3/7] DO NOT SUBMIT: Really dodgy demonstration of
DWARFTypePrinter reuse in lldb
The hacks necessary to make lldb's DWARFDIE APIs sufficiently compatible
with LLVM's DWARFDie API aren't shippable, but maybe somewhere to start
the conversation.
With all these changes, an internal example that would crash expanding
too many types (computing the fully qualified name for 414671 types before
crashing due to running out of stack) - but with these patches applied,
it comes down to 856 expansions (compared to 848 for non-simplified
template names inputs)
---
.../SymbolFile/DWARF/DWARFASTParserClang.cpp | 11 +
.../Plugins/SymbolFile/DWARF/DWARFBaseDIE.h | 10 +
.../Plugins/SymbolFile/DWARF/DWARFDIE.cpp | 21 +-
.../Plugins/SymbolFile/DWARF/DWARFDIE.h | 13 +
.../Plugins/SymbolFile/DWARF/DWARFFormValue.h | 37 +
.../SymbolFile/DWARF/SymbolFileDWARF.cpp | 24 +-
llvm/include/llvm-c/Error.h | 8 +
llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h | 2 +
.../llvm/DebugInfo/DWARF/DWARFFormValue.h | 7 +-
.../llvm/DebugInfo/DWARF/DWARFTypePrinter.h | 734 +++++++++++++++++-
llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 4 +-
llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp | 674 ----------------
12 files changed, 830 insertions(+), 715 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 0c605893293712..a70d788f8eae85 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -8,6 +8,7 @@
#include <cstdlib>
#include <iostream>
+#include <algorithm>
#include "DWARFASTParser.h"
#include "DWARFASTParserClang.h"
@@ -45,6 +46,8 @@
#include "clang/AST/Type.h"
#include "llvm/Demangle/Demangle.h"
+#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
+
#include <map>
#include <memory>
#include <optional>
@@ -866,11 +869,19 @@ DWARFASTParserClang::GetDIEClassTemplateParams(const DWARFDIE &die) {
if (llvm::StringRef(die.GetName()).contains("<"))
return ConstString();
+#if 1
+ std::string R;
+ llvm::raw_string_ostream OS(R);
+ llvm::DWARFTypePrinter<DWARFDIE> p(OS);
+ p.appendAndTerminateTemplateParameters(die);
+ return ConstString(R);
+#else
TypeSystemClang::TemplateParameterInfos template_param_infos;
if (ParseTemplateParameterInfos(die, template_param_infos)) {
return ConstString(m_ast.PrintTemplateParams(template_param_infos));
}
return ConstString();
+#endif
}
TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
index 235343d2271223..2cb7b247f59400 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
@@ -24,6 +24,7 @@ class DWARFUnit;
class DWARFDebugInfoEntry;
class DWARFDeclContext;
class SymbolFileDWARF;
+class DWARFFormValue;
class DWARFBaseDIE {
public:
@@ -47,6 +48,8 @@ class DWARFBaseDIE {
bool IsValid() const { return m_cu && m_die; }
+ bool isValid() const { return IsValid(); }
+
bool HasChildren() const;
bool Supports_DW_AT_APPLE_objc_complete_type() const;
@@ -84,6 +87,10 @@ class DWARFBaseDIE {
// Accessing information about a DIE
dw_tag_t Tag() const;
+ dw_tag_t getTag() const {
+ return Tag();
+ }
+ using DWARFFormValue = dwarf::DWARFFormValue;
dw_offset_t GetOffset() const;
@@ -94,6 +101,9 @@ class DWARFBaseDIE {
lldb::user_id_t GetID() const;
const char *GetName() const;
+ const char *getShortName() const {
+ return GetName();
+ }
lldb::ModuleSP GetModule() const;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index 7cf92adc6ef578..23eeaa0c937f51 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -118,7 +118,13 @@ DWARFDIE::GetReferencedDIE(const dw_attr_t attr) const {
}
DWARFDIE
-DWARFDIE::GetDIE(dw_offset_t die_offset) const {
+DWARFDIE::getAttributeValueAsReferencedDie(DWARFFormValue value) const {
+ if (IsValid())
+ return value.Reference();
+ return {};
+}
+
+DWARFDIE DWARFDIE::GetDIE(dw_offset_t die_offset) const {
if (IsValid())
return m_cu->GetDIE(die_offset);
else
@@ -545,3 +551,16 @@ bool DWARFDIE::GetDIENamesAndRanges(
llvm::iterator_range<DWARFDIE::child_iterator> DWARFDIE::children() const {
return llvm::make_range(child_iterator(*this), child_iterator());
}
+
+DWARFDIE::child_iterator DWARFDIE::begin() const {
+ return child_iterator(*this);
+}
+DWARFDIE::child_iterator DWARFDIE::end() const {
+ return child_iterator();
+}
+std::optional<DWARFFormValue> DWARFDIE::find(const dw_attr_t attr) const {
+ DWARFFormValue form_value;
+ if (m_die->GetAttributeValue(m_cu, attr, form_value, nullptr, false))
+ return form_value;
+ return std::nullopt;
+}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
index 511ca62d0197a8..e3e2f725cfdf69 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -47,6 +47,8 @@ class DWARFDIE : public DWARFBaseDIE {
DWARFDIE
GetParent() const;
+ DWARFDIE getParent() const { return GetParent(); }
+
DWARFDIE
GetFirstChild() const;
@@ -56,6 +58,12 @@ class DWARFDIE : public DWARFBaseDIE {
DWARFDIE
GetReferencedDIE(const dw_attr_t attr) const;
+ DWARFDIE getAttributeValueAsReferencedDie(const dw_attr_t attr) const {
+ return GetReferencedDIE(attr);
+ }
+
+ DWARFDIE getAttributeValueAsReferencedDie(DWARFFormValue) const;
+
// Get a another DIE from the same DWARF file as this DIE. This will
// check the current DIE's compile unit first to see if "die_offset" is
// in the same compile unit, and fall back to checking the DWARF file.
@@ -97,6 +105,8 @@ class DWARFDIE : public DWARFBaseDIE {
DWARFDIE
GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const;
+ std::optional<DWARFFormValue> find(const dw_attr_t attr) const;
+
bool GetDIENamesAndRanges(
const char *&name, const char *&mangled, DWARFRangeList &ranges,
std::optional<int> &decl_file, std::optional<int> &decl_line,
@@ -106,6 +116,9 @@ class DWARFDIE : public DWARFBaseDIE {
/// The range of all the children of this DIE.
llvm::iterator_range<child_iterator> children() const;
+
+ child_iterator begin() const;
+ child_iterator end() const;
};
class DWARFDIE::child_iterator
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index fdd5b3c278a4e8..42a9b9e8e7f50f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -69,6 +69,30 @@ class DWARFFormValue {
uint64_t Reference(dw_offset_t offset) const;
bool Boolean() const { return m_value.value.uval != 0; }
uint64_t Unsigned() const { return m_value.value.uval; }
+ std::optional<uint64_t> getAsUnsignedConstant() const {
+ if ((!IsDataForm(m_form)) || m_form == lldb_private::dwarf::DW_FORM_sdata)
+ return std::nullopt;
+ return m_value.value.uval;
+ }
+ std::optional<int64_t> getAsSignedConstant() const {
+ if ((!IsDataForm(m_form)) ||
+ (m_form == lldb_private::dwarf::DW_FORM_udata &&
+ uint64_t(std::numeric_limits<int64_t>::max()) < m_value.value.uval))
+ return std::nullopt;
+ switch (m_form) {
+ case lldb_private::dwarf::DW_FORM_data4:
+ return int32_t(m_value.value.uval);
+ case lldb_private::dwarf::DW_FORM_data2:
+ return int16_t(m_value.value.uval);
+ case lldb_private::dwarf::DW_FORM_data1:
+ return int8_t(m_value.value.uval);
+ case lldb_private::dwarf::DW_FORM_sdata:
+ case lldb_private::dwarf::DW_FORM_data8:
+ default:
+ return m_value.value.sval;
+ }
+ }
+
void SetUnsigned(uint64_t uval) { m_value.value.uval = uval; }
int64_t Signed() const { return m_value.value.sval; }
void SetSigned(int64_t sval) { m_value.value.sval = sval; }
@@ -93,6 +117,19 @@ class DWARFFormValue {
dw_form_t m_form = dw_form_t(0); // Form for this value
ValueType m_value; // Contains all data for the form
};
+
+inline const char* toString(DWARFFormValue Value, const char* Default) {
+ if (const char* R = Value.AsCString())
+ return R;
+ return Default;
+}
+inline const char* toString(std::optional<DWARFFormValue> Value, const char* Default) {
+ if (!Value)
+ return Default;
+ if (const char* R = Value->AsCString())
+ return R;
+ return Default;
+}
} // namespace dwarf
} // namespace lldb_private::plugin
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 661e4a78a02159..9500096a9f5b6e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3219,31 +3219,21 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) {
type_dwarf_decl_ctx.GetQualifiedName());
}
- Type *resolved_type = ResolveType(type_die, false);
- if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED)
- return true;
-
// With -gsimple-template-names, the DIE name may not contain the template
// parameters. If the declaration has template parameters but doesn't
// contain '<', check that the child template parameters match.
if (template_params) {
- llvm::StringRef test_base_name =
- GetTypeForDIE(type_die)->GetBaseName().GetStringRef();
- auto i = test_base_name.find('<');
-
- // Full name from clang AST doesn't contain '<' so this type_die isn't
- // a template parameter, but we're expecting template parameters, so
- // bail.
- if (i == llvm::StringRef::npos)
- return true;
-
- llvm::StringRef test_template_params =
- test_base_name.slice(i, test_base_name.size());
+ ConstString test_template_params =
+ type_system->GetDWARFParser()->GetDIEClassTemplateParams(type_die);
// Bail if template parameters don't match.
- if (test_template_params != template_params.GetStringRef())
+ if (test_template_params != template_params)
return true;
}
+ Type *resolved_type = ResolveType(type_die, false);
+ if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED)
+ return true;
+
type_sp = resolved_type->shared_from_this();
return false;
});
diff --git a/llvm/include/llvm-c/Error.h b/llvm/include/llvm-c/Error.h
index c3baaf65186aac..81a30133d58352 100644
--- a/llvm/include/llvm-c/Error.h
+++ b/llvm/include/llvm-c/Error.h
@@ -51,6 +51,14 @@ LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err);
*/
void LLVMConsumeError(LLVMErrorRef Err);
+/**
+ * Report a fatal error if Err is a failure value.
+ *
+ * This function can be used to wrap calls to fallible functions ONLY when it
+ * is known that the Error will always be a success value.
+ */
+void LLVMCantFail(LLVMErrorRef Err);
+
/**
* Returns the given string's error message. This operation consumes the error,
* and the given LLVMErrorRef value is not usable once this call returns.
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
index 421b84d644db64..50eabdf6b05111 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
@@ -17,6 +17,7 @@
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFAttribute.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
#include <cassert>
#include <cstdint>
@@ -44,6 +45,7 @@ class DWARFDie {
const DWARFDebugInfoEntry *Die = nullptr;
public:
+ using DWARFFormValue = llvm::DWARFFormValue;
DWARFDie() = default;
DWARFDie(DWARFUnit *Unit, const DWARFDebugInfoEntry *D) : U(Unit), Die(D) {}
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
index 2dcd7805b6c96b..88d207d9847776 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
@@ -168,8 +168,6 @@ class DWARFFormValue {
void dumpString(raw_ostream &OS) const;
};
-namespace dwarf {
-
/// Take an optional DWARFFormValue and try to extract a string value from it.
///
/// \param V and optional DWARFFormValue to attempt to extract the value from.
@@ -219,6 +217,11 @@ inline const char *toString(const std::optional<DWARFFormValue> &V,
return Default;
}
+namespace dwarf {
+
+using llvm::toString;
+using llvm::toStringRef;
+
/// Take an optional DWARFFormValue and try to extract an unsigned constant.
///
/// \param V and optional DWARFFormValue to attempt to extract the value from.
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
index e05271740e6157..abc0ab8e27976a 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
@@ -11,7 +11,6 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include <string>
@@ -21,7 +20,7 @@ class raw_ostream;
// FIXME: We should have pretty printers per language. Currently we print
// everything as if it was C++ and fall back to the TAG type name.
-struct DWARFTypePrinter {
+template <typename DieType> struct DWARFTypePrinter {
raw_ostream &OS;
bool Word = true;
bool EndedWithTemplate = false;
@@ -31,37 +30,734 @@ struct DWARFTypePrinter {
/// Dump the name encoded in the type tag.
void appendTypeTagName(dwarf::Tag T);
- void appendArrayType(const DWARFDie &D);
+ void appendArrayType(const DieType &D);
- DWARFDie skipQualifiers(DWARFDie D);
+ DieType skipQualifiers(DieType D);
- bool needsParens(DWARFDie D);
+ bool needsParens(DieType D);
- void appendPointerLikeTypeBefore(DWARFDie D, DWARFDie Inner, StringRef Ptr);
+ void appendPointerLikeTypeBefore(DieType D, DieType Inner, StringRef Ptr);
- DWARFDie appendUnqualifiedNameBefore(DWARFDie D,
- std::string *OriginalFullName = nullptr);
+ DieType appendUnqualifiedNameBefore(DieType D,
+ std::string *OriginalFullName = nullptr);
- void appendUnqualifiedNameAfter(DWARFDie D, DWARFDie Inner,
+ void appendUnqualifiedNameAfter(DieType D, DieType Inner,
bool SkipFirstParamIfArtificial = false);
- void appendQualifiedName(DWARFDie D);
- DWARFDie appendQualifiedNameBefore(DWARFDie D);
- bool appendTemplateParameters(DWARFDie D, bool *FirstParameter = nullptr);
- void decomposeConstVolatile(DWARFDie &N, DWARFDie &T, DWARFDie &C,
- DWARFDie &V);
- void appendConstVolatileQualifierAfter(DWARFDie N);
- void appendConstVolatileQualifierBefore(DWARFDie N);
+ void appendQualifiedName(DieType D);
+ DieType appendQualifiedNameBefore(DieType D);
+ bool appendTemplateParameters(DieType D, bool *FirstParameter = nullptr);
+ void appendAndTerminateTemplateParameters(DieType D);
+ void decomposeConstVolatile(DieType &N, DieType &T, DieType &C, DieType &V);
+ void appendConstVolatileQualifierAfter(DieType N);
+ void appendConstVolatileQualifierBefore(DieType N);
/// Recursively append the DIE type name when applicable.
- void appendUnqualifiedName(DWARFDie D,
+ void appendUnqualifiedName(DieType D,
std::string *OriginalFullName = nullptr);
- void appendSubroutineNameAfter(DWARFDie D, DWARFDie Inner,
+ void appendSubroutineNameAfter(DieType D, DieType Inner,
bool SkipFirstParamIfArtificial, bool Const,
bool Volatile);
- void appendScopes(DWARFDie D);
+ void appendScopes(DieType D);
};
+template <typename DieType>
+void DWARFTypePrinter<DieType>::appendTypeTagName(dwarf::Tag T) {
+ StringRef TagStr = TagString(T);
+ static constexpr StringRef Prefix = "dwarf::DW_TAG_";
+ static constexpr StringRef Suffix = "_type";
+ if (!TagStr.starts_with(Prefix) || !TagStr.ends_with(Suffix))
+ return;
+ OS << TagStr.substr(Prefix.size(),
+ TagStr.size() - (Prefix.size() + Suffix.size()))
+ << " ";
+}
+
+template <typename DieType>
+void DWARFTypePrinter<DieType>::appendArrayType(const DieType &D) {
+ for (const DieType &C : D.children()) {
+ if (C.getTag() != dwarf::DW_TAG_subrange_type)
+ continue;
+ std::optional<uint64_t> LB;
+ std::optional<uint64_t> Count;
+ std::optional<uint64_t> UB;
+ std::optional<unsigned> DefaultLB;
+ if (std::optional<typename DieType::DWARFFormValue> L = C.find(dwarf::DW_AT_lower_bound))
+ LB = L->getAsUnsignedConstant();
+ if (std::optional<typename DieType::DWARFFormValue> CountV = C.find(dwarf::DW_AT_count))
+ Count = CountV->getAsUnsignedConstant();
+ if (std::optional<typename DieType::DWARFFormValue> UpperV = C.find(dwarf::DW_AT_upper_bound))
+ UB = UpperV->getAsUnsignedConstant();
+ /*
+ if (std::optional<typename DieType::DWARFFormValue> LV =
+ D.getDwarfUnit()->getUnitDIE().find(dwarf::DW_AT_language))
+ if (std::optional<uint64_t> LC = LV->getAsUnsignedConstant())
+ if ((DefaultLB =
+ LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LC))))
+ if (LB && *LB == *DefaultLB)
+ LB = std::nullopt;
+ */
+ if (!LB && !Count && !UB)
+ OS << "[]";
+ else if (!LB && (Count || UB) && DefaultLB)
+ OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']';
+ else {
+ OS << "[[";
+ if (LB)
+ OS << *LB;
+ else
+ OS << '?';
+ OS << ", ";
+ if (Count)
+ if (LB)
+ OS << *LB + *Count;
+ else
+ OS << "? + " << *Count;
+ else if (UB)
+ OS << *UB + 1;
+ else
+ OS << '?';
+ OS << ")]";
+ }
+ }
+ EndedWithTemplate = false;
+}
+
+namespace detail {
+template<typename DieType>
+DieType resolveReferencedType(DieType D,
+ dwarf::Attribute Attr = dwarf::DW_AT_type) {
+ return D.getAttributeValueAsReferencedDie(Attr); // .resolveTypeUnitReference();
+}
+template <typename DieType>
+DieType resolveReferencedType(DieType D, typename DieType::DWARFFormValue F) {
+ return D.getAttributeValueAsReferencedDie(F); // .resolveTypeUnitReference();
+}
+} // namespace detail
+
+template <typename DieType>
+DieType DWARFTypePrinter<DieType>::skipQualifiers(DieType D) {
+ while (D && (D.getTag() == dwarf::DW_TAG_const_type ||
+ D.getTag() == dwarf::DW_TAG_volatile_type))
+ D = detail::resolveReferencedType(D);
+ return D;
+}
+
+template <typename DieType>
+bool DWARFTypePrinter<DieType>::needsParens(DieType D) {
+ D = skipQualifiers(D);
+ return D && (D.getTag() == dwarf::DW_TAG_subroutine_type ||
+ D.getTag() == dwarf::DW_TAG_array_type);
+}
+
+template <typename DieType>
+void DWARFTypePrinter<DieType>::appendPointerLikeTypeBefore(DieType D,
+ DieType Inner,
+ StringRef Ptr) {
+ appendQualifiedNameBefore(Inner);
+ if (Word)
+ OS << ' ';
+ if (needsParens(Inner))
+ OS << '(';
+ OS << Ptr;
+ Word = false;
+ EndedWithTemplate = false;
+}
+
+template <typename DieType>
+DieType DWARFTypePrinter<DieType>::appendUnqualifiedNameBefore(
+ DieType D, std::string *OriginalFullName) {
+ Word = true;
+ if (!D) {
+ OS << "void";
+ return DieType();
+ }
+ DieType InnerDIE;
+ auto Inner = [&] { return InnerDIE = detail::resolveReferencedType(D); };
+ const dwarf::Tag T = D.getTag();
+ switch (T) {
+ case dwarf::DW_TAG_pointer_type: {
+ appendPointerLikeTypeBefore(D, Inner(), "*");
+ break;
+ }
+ case dwarf::DW_TAG_subroutine_type: {
+ appendQualifiedNameBefore(Inner());
+ if (Word) {
+ OS << ' ';
+ }
+ Word = false;
+ break;
+ }
+ case dwarf::DW_TAG_array_type: {
+ appendQualifiedNameBefore(Inner());
+ break;
+ }
+ case dwarf::DW_TAG_reference_type:
+ appendPointerLikeTypeBefore(D, Inner(), "&");
+ break;
+ case dwarf::DW_TAG_rvalue_reference_type:
+ appendPointerLikeTypeBefore(D, Inner(), "&&");
+ break;
+ case dwarf::DW_TAG_ptr_to_member_type: {
+ appendQualifiedNameBefore(Inner());
+ if (needsParens(InnerDIE))
+ OS << '(';
+ else if (Word)
+ OS << ' ';
+ if (DieType Cont = detail::resolveReferencedType(D, dwarf::DW_AT_containing_type)) {
+ appendQualifiedName(Cont);
+ EndedWithTemplate = false;
+ OS << "::";
+ }
+ OS << "*";
+ Word = false;
+ break;
+ }
+ case dwarf::DW_TAG_LLVM_ptrauth_type:
+ appendQualifiedNameBefore(Inner());
+ break;
+ case dwarf::DW_TAG_const_type:
+ case dwarf::DW_TAG_volatile_type:
+ appendConstVolatileQualifierBefore(D);
+ break;
+ case dwarf::DW_TAG_namespace: {
+ if (const char *Name = toString(D.find(dwarf::DW_AT_name), nullptr))
+ OS << Name;
+ else
+ OS << "(anonymous namespace)";
+ break;
+ }
+ case dwarf::DW_TAG_unspecified_type: {
+ StringRef TypeName = D.getShortName();
+ if (TypeName == "decltype(nullptr)")
+ TypeName = "std::nullptr_t";
+ Word = true;
+ OS << TypeName;
+ EndedWithTemplate = false;
+ break;
+ }
+ /*
+ case dwarf::DW_TAG_structure_type:
+ case dwarf::DW_TAG_class_type:
+ case dwarf::DW_TAG_enumeration_type:
+ case dwarf::DW_TAG_base_type:
+ */
+ default: {
+ const char *NamePtr = toString(D.find(dwarf::DW_AT_name), nullptr);
+ if (!NamePtr) {
+ appendTypeTagName(D.getTag());
+ return DieType();
+ }
+ Word = true;
+ StringRef Name = NamePtr;
+ static constexpr StringRef MangledPrefix = "_STN|";
+ if (Name.consume_front(MangledPrefix)) {
+ auto Separator = Name.find('|');
+ assert(Separator != StringRef::npos);
+ StringRef BaseName = Name.substr(0, Separator);
+ StringRef TemplateArgs = Name.substr(Separator + 1);
+ if (OriginalFullName)
+ *OriginalFullName = (BaseName + TemplateArgs).str();
+ Name = BaseName;
+ } else
+ EndedWithTemplate = Name.ends_with(">");
+ OS << Name;
+ // This check would be insufficient for operator overloads like
+ // "operator>>" - but for now Clang doesn't try to simplify them, so this
+ // is OK. Add more nuanced operator overload handling here if/when needed.
+ if (Name.ends_with(">"))
+ break;
+ appendAndTerminateTemplateParameters(D);
+ break;
+ }
+ }
+ return InnerDIE;
+}
+
+template <typename DieType>
+void DWARFTypePrinter<DieType>::appendAndTerminateTemplateParameters(DieType D) {
+ if (!appendTemplateParameters(D))
+ return;
+
+ if (EndedWithTemplate)
+ OS << ' ';
+ OS << '>';
+ EndedWithTemplate = true;
+ Word = true;
+}
+
+template <typename DieType>
+void DWARFTypePrinter<DieType>::appendUnqualifiedNameAfter(
+ DieType D, DieType Inner, bool SkipFirstParamIfArtificial) {
+ if (!D)
+ return;
+ switch (D.getTag()) {
+ case dwarf::DW_TAG_subroutine_type: {
+ appendSubroutineNameAfter(D, Inner, SkipFirstParamIfArtificial, false,
+ false);
+ break;
+ }
+ case dwarf::DW_TAG_array_type: {
+ appendArrayType(D);
+ break;
+ }
+ case dwarf::DW_TAG_const_type:
+ case dwarf::DW_TAG_volatile_type:
+ appendConstVolatileQualifierAfter(D);
+ break;
+ case dwarf::DW_TAG_ptr_to_member_type:
+ case dwarf::DW_TAG_reference_type:
+ case dwarf::DW_TAG_rvalue_reference_type:
+ case dwarf::DW_TAG_pointer_type: {
+ if (needsParens(Inner))
+ OS << ')';
+ appendUnqualifiedNameAfter(Inner, detail::resolveReferencedType(Inner),
+ /*SkipFirstParamIfArtificial=*/D.getTag() ==
+ dwarf::DW_TAG_ptr_to_member_type);
+ break;
+ }
+ case dwarf::DW_TAG_LLVM_ptrauth_type: {
+ auto getValOrNull = [&](dwarf::Attribute Attr) -> uint64_t {
+ if (auto Form = D.find(Attr))
+ return *Form->getAsUnsignedConstant();
+ return 0;
+ };
+ SmallVector<const char *, 2> optionsVec;
+ if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_isa_pointer))
+ optionsVec.push_back("isa-pointer");
+ if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_authenticates_null_values))
+ optionsVec.push_back("authenticates-null-values");
+ if (auto AuthenticationMode =
+ D.find(dwarf::DW_AT_LLVM_ptrauth_authentication_mode)) {
+ switch (*AuthenticationMode->getAsUnsignedConstant()) {
+ case 0:
+ case 1:
+ optionsVec.push_back("strip");
+ break;
+ case 2:
+ optionsVec.push_back("sign-and-strip");
+ break;
+ default:
+ // Default authentication policy
+ break;
+ }
+ }
+ std::string options;
+ for (const auto *option : optionsVec) {
+ if (options.size())
+ options += ",";
+ options += option;
+ }
+ if (options.size())
+ options = ", \"" + options + "\"";
+ std::string PtrauthString;
+ llvm::raw_string_ostream PtrauthStream(PtrauthString);
+ PtrauthStream
+ << "__ptrauth(" << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_key) << ", "
+ << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_address_discriminated) << ", 0x0"
+ << utohexstr(getValOrNull(dwarf::DW_AT_LLVM_ptrauth_extra_discriminator), true)
+ << options << ")";
+ OS << PtrauthStream.str();
+ break;
+ }
+ /*
+ case dwarf::DW_TAG_structure_type:
+ case dwarf::DW_TAG_class_type:
+ case dwarf::DW_TAG_enumeration_type:
+ case dwarf::DW_TAG_base_type:
+ case dwarf::DW_TAG_namespace:
+ */
+ default:
+ break;
+ }
+}
+
+namespace detail {
+/// Returns True if the DIE TAG is one of the ones that is scopped.
+inline bool scopedTAGs(dwarf::Tag Tag) {
+ switch (Tag) {
+ case dwarf::DW_TAG_structure_type:
+ case dwarf::DW_TAG_class_type:
+ case dwarf::DW_TAG_union_type:
+ case dwarf::DW_TAG_namespace:
+ case dwarf::DW_TAG_enumeration_type:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+} // namespace detail
+template <typename DieType>
+void DWARFTypePrinter<DieType>::appendQualifiedName(DieType D) {
+ if (D && detail::scopedTAGs(D.getTag()))
+ appendScopes(D.getParent());
+ appendUnqualifiedName(D);
+}
+template <typename DieType>
+DieType DWARFTypePrinter<DieType>::appendQualifiedNameBefore(DieType D) {
+ if (D && detail::scopedTAGs(D.getTag()))
+ appendScopes(D.getParent());
+ return appendUnqualifiedNameBefore(D);
+}
+template <typename DieType>
+bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
+ bool *FirstParameter) {
+ bool FirstParameterValue = true;
+ bool IsTemplate = false;
+ if (!FirstParameter)
+ FirstParameter = &FirstParameterValue;
+ for (const DieType &C : D) {
+ auto Sep = [&] {
+ if (*FirstParameter)
+ OS << '<';
+ else
+ OS << ", ";
+ IsTemplate = true;
+ EndedWithTemplate = false;
+ *FirstParameter = false;
+ };
+ if (C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) {
+ IsTemplate = true;
+ appendTemplateParameters(C, FirstParameter);
+ }
+ if (C.getTag() == dwarf::DW_TAG_template_value_parameter) {
+ DieType T = detail::resolveReferencedType(C);
+ Sep();
+ if (T.getTag() == dwarf::DW_TAG_enumeration_type) {
+ OS << '(';
+ appendQualifiedName(T);
+ OS << ')';
+ auto V = C.find(dwarf::DW_AT_const_value);
+ OS << std::to_string(*V->getAsSignedConstant());
+ continue;
+ }
+ // /Maybe/ we could do pointer type parameters, looking for the
+ // symbol in the ELF symbol table to get back to the variable...
+ // but probably not worth it.
+ if (T.getTag() == dwarf::DW_TAG_pointer_type)
+ continue;
+ const char *RawName = toString(T.find(dwarf::DW_AT_name), nullptr);
+ assert(RawName);
+ StringRef Name = RawName;
+ auto V = C.find(dwarf::DW_AT_const_value);
+ bool IsQualifiedChar = false;
+ if (Name == "bool") {
+ OS << (*V->getAsUnsignedConstant() ? "true" : "false");
+ } else if (Name == "short") {
+ OS << "(short)";
+ OS << std::to_string(*V->getAsSignedConstant());
+ } else if (Name == "unsigned short") {
+ OS << "(unsigned short)";
+ OS << std::to_string(*V->getAsSignedConstant());
+ } else if (Name == "int")
+ OS << std::to_string(*V->getAsSignedConstant());
+ else if (Name == "long") {
+ OS << std::to_string(*V->getAsSignedConstant());
+ OS << "L";
+ } else if (Name == "long long") {
+ OS << std::to_string(*V->getAsSignedConstant());
+ OS << "LL";
+ } else if (Name == "unsigned int") {
+ OS << std::to_string(*V->getAsUnsignedConstant());
+ OS << "U";
+ } else if (Name == "unsigned long") {
+ OS << std::to_string(*V->getAsUnsignedConstant());
+ OS << "UL";
+ } else if (Name == "unsigned long long") {
+ OS << std::to_string(*V->getAsUnsignedConstant());
+ OS << "ULL";
+ } else if (Name == "char" ||
+ (IsQualifiedChar =
+ (Name == "unsigned char" || Name == "signed char"))) {
+ // FIXME: check T's dwarf::DW_AT_type to see if it's signed or not (since
+ // char signedness is implementation defined).
+ auto Val = *V->getAsSignedConstant();
+ // Copied/hacked up from Clang's CharacterLiteral::print - incomplete
+ // (doesn't actually support different character types/widths, sign
+ // handling's not done, and doesn't correctly test if a character is
+ // printable or needs to use a numeric escape sequence instead)
+ if (IsQualifiedChar) {
+ OS << '(';
+ OS << Name;
+ OS << ')';
+ }
+ switch (Val) {
+ case '\\':
+ OS << "'\\\\'";
+ break;
+ case '\'':
+ OS << "'\\''";
+ break;
+ case '\a':
+ // TODO: K&R: the meaning of '\\a' is different in traditional C
+ OS << "'\\a'";
+ break;
+ case '\b':
+ OS << "'\\b'";
+ break;
+ case '\f':
+ OS << "'\\f'";
+ break;
+ case '\n':
+ OS << "'\\n'";
+ break;
+ case '\r':
+ OS << "'\\r'";
+ break;
+ case '\t':
+ OS << "'\\t'";
+ break;
+ case '\v':
+ OS << "'\\v'";
+ break;
+ default:
+ if ((Val & ~0xFFu) == ~0xFFu)
+ Val &= 0xFFu;
+ if (Val < 127 && Val >= 32) {
+ OS << "'";
+ OS << (char)Val;
+ OS << "'";
+ } else if (Val < 256)
+ OS << llvm::format("'\\x%02" PRIx64 "'", Val);
+ else if (Val <= 0xFFFF)
+ OS << llvm::format("'\\u%04" PRIx64 "'", Val);
+ else
+ OS << llvm::format("'\\U%08" PRIx64 "'", Val);
+ }
+ }
+ continue;
+ }
+ if (C.getTag() == dwarf::DW_TAG_GNU_template_template_param) {
+ const char *RawName =
+ toString(C.find(dwarf::DW_AT_GNU_template_name), nullptr);
+ assert(RawName);
+ StringRef Name = RawName;
+ Sep();
+ OS << Name;
+ continue;
+ }
+ if (C.getTag() != dwarf::DW_TAG_template_type_parameter)
+ continue;
+ auto TypeAttr = C.find(dwarf::DW_AT_type);
+ Sep();
+ appendQualifiedName(TypeAttr ? detail::resolveReferencedType(C, *TypeAttr)
+ : DieType());
+ }
+ if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {
+ OS << '<';
+ EndedWithTemplate = false;
+ }
+ return IsTemplate;
+}
+template <typename DieType>
+void DWARFTypePrinter<DieType>::decomposeConstVolatile(DieType &N, DieType &T,
+ DieType &C, DieType &V) {
+ (N.getTag() == dwarf::DW_TAG_const_type ? C : V) = N;
+ T = detail::resolveReferencedType(N);
+ if (T) {
+ auto Tag = T.getTag();
+ if (Tag == dwarf::DW_TAG_const_type) {
+ C = T;
+ T = detail::resolveReferencedType(T);
+ } else if (Tag == dwarf::DW_TAG_volatile_type) {
+ V = T;
+ T = detail::resolveReferencedType(T);
+ }
+ }
+}
+template <typename DieType>
+void DWARFTypePrinter<DieType>::appendConstVolatileQualifierAfter(DieType N) {
+ DieType C;
+ DieType V;
+ DieType T;
+ decomposeConstVolatile(N, T, C, V);
+ if (T && T.getTag() == dwarf::DW_TAG_subroutine_type)
+ appendSubroutineNameAfter(T, detail::resolveReferencedType(T), false, C.isValid(),
+ V.isValid());
+ else
+ appendUnqualifiedNameAfter(T, detail::resolveReferencedType(T));
+}
+template <typename DieType>
+void DWARFTypePrinter<DieType>::appendConstVolatileQualifierBefore(DieType N) {
+ DieType C;
+ DieType V;
+ DieType T;
+ decomposeConstVolatile(N, T, C, V);
+ bool Subroutine = T && T.getTag() == dwarf::DW_TAG_subroutine_type;
+ DieType A = T;
+ while (A && A.getTag() == dwarf::DW_TAG_array_type)
+ A = detail::resolveReferencedType(A);
+ bool Leading =
+ (!A || (A.getTag() != dwarf::DW_TAG_pointer_type &&
+ A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
+ !Subroutine;
+ if (Leading) {
+ if (C)
+ OS << "const ";
+ if (V)
+ OS << "volatile ";
+ }
+ appendQualifiedNameBefore(T);
+ if (!Leading && !Subroutine) {
+ Word = true;
+ if (C)
+ OS << "const";
+ if (V) {
+ if (C)
+ OS << ' ';
+ OS << "volatile";
+ }
+ }
+}
+template <typename DieType>
+void DWARFTypePrinter<DieType>::appendUnqualifiedName(
+ DieType D, std::string *OriginalFullName) {
+ // FIXME: We should have pretty printers per language. Currently we print
+ // everything as if it was C++ and fall back to the TAG type name.
+ DieType Inner = appendUnqualifiedNameBefore(D, OriginalFullName);
+ appendUnqualifiedNameAfter(D, Inner);
+}
+template <typename DieType>
+void DWARFTypePrinter<DieType>::appendSubroutineNameAfter(
+ DieType D, DieType Inner, bool SkipFirstParamIfArtificial, bool Const,
+ bool Volatile) {
+ DieType FirstParamIfArtificial;
+ OS << '(';
+ EndedWithTemplate = false;
+ bool First = true;
+ bool RealFirst = true;
+ for (DieType P : D) {
+ if (P.getTag() != dwarf::DW_TAG_formal_parameter &&
+ P.getTag() != dwarf::DW_TAG_unspecified_parameters)
+ return;
+ DieType T = detail::resolveReferencedType(P);
+ if (SkipFirstParamIfArtificial && RealFirst && P.find(dwarf::DW_AT_artificial)) {
+ FirstParamIfArtificial = T;
+ RealFirst = false;
+ continue;
+ }
+ if (!First) {
+ OS << ", ";
+ }
+ First = false;
+ if (P.getTag() == dwarf::DW_TAG_unspecified_parameters)
+ OS << "...";
+ else
+ appendQualifiedName(T);
+ }
+ EndedWithTemplate = false;
+ OS << ')';
+ if (FirstParamIfArtificial) {
+ if (DieType P = FirstParamIfArtificial) {
+ if (P.getTag() == dwarf::DW_TAG_pointer_type) {
+ auto CVStep = [&](DieType CV) {
+ if (DieType U = detail::resolveReferencedType(CV)) {
+ Const |= U.getTag() == dwarf::DW_TAG_const_type;
+ Volatile |= U.getTag() == dwarf::DW_TAG_volatile_type;
+ return U;
+ }
+ return DieType();
+ };
+ if (DieType CV = CVStep(P)) {
+ CVStep(CV);
+ }
+ }
+ }
+ }
+
+ if (auto CC = D.find(dwarf::DW_AT_calling_convention)) {
+ switch (*CC->getAsUnsignedConstant()) {
+ case dwarf::CallingConvention::DW_CC_BORLAND_stdcall:
+ OS << " __attribute__((stdcall))";
+ break;
+ case dwarf::CallingConvention::DW_CC_BORLAND_msfastcall:
+ OS << " __attribute__((fastcall))";
+ break;
+ case dwarf::CallingConvention::DW_CC_BORLAND_thiscall:
+ OS << " __attribute__((thiscall))";
+ break;
+ case dwarf::CallingConvention::DW_CC_LLVM_vectorcall:
+ OS << " __attribute__((vectorcall))";
+ break;
+ case dwarf::CallingConvention::DW_CC_BORLAND_pascal:
+ OS << " __attribute__((pascal))";
+ break;
+ case dwarf::CallingConvention::DW_CC_LLVM_Win64:
+ OS << " __attribute__((ms_abi))";
+ break;
+ case dwarf::CallingConvention::DW_CC_LLVM_X86_64SysV:
+ OS << " __attribute__((sysv_abi))";
+ break;
+ case dwarf::CallingConvention::DW_CC_LLVM_AAPCS:
+ // AArch64VectorCall missing?
+ OS << " __attribute__((pcs(\"aapcs\")))";
+ break;
+ case dwarf::CallingConvention::DW_CC_LLVM_AAPCS_VFP:
+ OS << " __attribute__((pcs(\"aapcs-vfp\")))";
+ break;
+ case dwarf::CallingConvention::DW_CC_LLVM_IntelOclBicc:
+ OS << " __attribute__((intel_ocl_bicc))";
+ break;
+ case dwarf::CallingConvention::DW_CC_LLVM_SpirFunction:
+ case dwarf::CallingConvention::DW_CC_LLVM_OpenCLKernel:
+ // These aren't available as attributes, but maybe we should still
+ // render them somehow? (Clang doesn't render them, but that's an issue
+ // for template names too - since then the DWARF names of templates
+ // instantiated with function types with these calling conventions won't
+ // have distinct names - so we'd need to fix that too)
+ break;
+ case dwarf::CallingConvention::DW_CC_LLVM_Swift:
+ // SwiftAsync missing
+ OS << " __attribute__((swiftcall))";
+ break;
+ case dwarf::CallingConvention::DW_CC_LLVM_PreserveMost:
+ OS << " __attribute__((preserve_most))";
+ break;
+ case dwarf::CallingConvention::DW_CC_LLVM_PreserveAll:
+ OS << " __attribute__((preserve_all))";
+ break;
+ case dwarf::CallingConvention::DW_CC_LLVM_PreserveNone:
+ OS << " __attribute__((preserve_none))";
+ break;
+ case dwarf::CallingConvention::DW_CC_LLVM_X86RegCall:
+ OS << " __attribute__((regcall))";
+ break;
+ case dwarf::CallingConvention::DW_CC_LLVM_M68kRTD:
+ OS << " __attribute__((m68k_rtd))";
+ break;
+ }
+ }
+
+ if (Const)
+ OS << " const";
+ if (Volatile)
+ OS << " volatile";
+ if (D.find(dwarf::DW_AT_reference))
+ OS << " &";
+ if (D.find(dwarf::DW_AT_rvalue_reference))
+ OS << " &&";
+
+ appendUnqualifiedNameAfter(Inner, detail::resolveReferencedType(Inner));
+}
+template <typename DieType>
+void DWARFTypePrinter<DieType>::appendScopes(DieType D) {
+ if (D.getTag() == dwarf::DW_TAG_compile_unit)
+ return;
+ if (D.getTag() == dwarf::DW_TAG_type_unit)
+ return;
+ if (D.getTag() == dwarf::DW_TAG_skeleton_unit)
+ return;
+ if (D.getTag() == dwarf::DW_TAG_subprogram)
+ return;
+ if (D.getTag() == dwarf::DW_TAG_lexical_block)
+ return;
+ //D = D.resolveTypeUnitReference();
+ if (DieType P = D.getParent())
+ appendScopes(P);
+ appendUnqualifiedName(D);
+ OS << "::";
+}
} // namespace llvm
#endif // LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index 410842a80b0151..8686717e9e9006 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -775,12 +775,12 @@ bool DWARFAttribute::mayHaveLocationExpr(dwarf::Attribute Attr) {
namespace llvm {
void dumpTypeQualifiedName(const DWARFDie &DIE, raw_ostream &OS) {
- DWARFTypePrinter(OS).appendQualifiedName(DIE);
+ DWARFTypePrinter<DWARFDie>(OS).appendQualifiedName(DIE);
}
void dumpTypeUnqualifiedName(const DWARFDie &DIE, raw_ostream &OS,
std::string *OriginalFullName) {
- DWARFTypePrinter(OS).appendUnqualifiedName(DIE, OriginalFullName);
+ DWARFTypePrinter<DWARFDie>(OS).appendUnqualifiedName(DIE, OriginalFullName);
}
} // namespace llvm
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp b/llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp
index 05dee8a3d71298..e69de29bb2d1d6 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp
@@ -1,674 +0,0 @@
-#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
-#include "llvm/DebugInfo/DWARF/DWARFDie.h"
-#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
-#include "llvm/Support/ScopedPrinter.h"
-namespace llvm {
-using namespace dwarf;
-void DWARFTypePrinter::appendTypeTagName(dwarf::Tag T) {
- StringRef TagStr = TagString(T);
- static constexpr StringRef Prefix = "DW_TAG_";
- static constexpr StringRef Suffix = "_type";
- if (!TagStr.starts_with(Prefix) || !TagStr.ends_with(Suffix))
- return;
- OS << TagStr.substr(Prefix.size(),
- TagStr.size() - (Prefix.size() + Suffix.size()))
- << " ";
-}
-
-void DWARFTypePrinter::appendArrayType(const DWARFDie &D) {
- for (const DWARFDie &C : D.children()) {
- if (C.getTag() != DW_TAG_subrange_type)
- continue;
- std::optional<uint64_t> LB;
- std::optional<uint64_t> Count;
- std::optional<uint64_t> UB;
- std::optional<unsigned> DefaultLB;
- if (std::optional<DWARFFormValue> L = C.find(DW_AT_lower_bound))
- LB = L->getAsUnsignedConstant();
- if (std::optional<DWARFFormValue> CountV = C.find(DW_AT_count))
- Count = CountV->getAsUnsignedConstant();
- if (std::optional<DWARFFormValue> UpperV = C.find(DW_AT_upper_bound))
- UB = UpperV->getAsUnsignedConstant();
- if (std::optional<DWARFFormValue> LV =
- D.getDwarfUnit()->getUnitDIE().find(DW_AT_language))
- if (std::optional<uint64_t> LC = LV->getAsUnsignedConstant())
- if ((DefaultLB =
- LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LC))))
- if (LB && *LB == *DefaultLB)
- LB = std::nullopt;
- if (!LB && !Count && !UB)
- OS << "[]";
- else if (!LB && (Count || UB) && DefaultLB)
- OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']';
- else {
- OS << "[[";
- if (LB)
- OS << *LB;
- else
- OS << '?';
- OS << ", ";
- if (Count)
- if (LB)
- OS << *LB + *Count;
- else
- OS << "? + " << *Count;
- else if (UB)
- OS << *UB + 1;
- else
- OS << '?';
- OS << ")]";
- }
- }
- EndedWithTemplate = false;
-}
-
-static DWARFDie resolveReferencedType(DWARFDie D,
- dwarf::Attribute Attr = DW_AT_type) {
- return D.getAttributeValueAsReferencedDie(Attr).resolveTypeUnitReference();
-}
-static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {
- return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference();
-}
-DWARFDie DWARFTypePrinter::skipQualifiers(DWARFDie D) {
- while (D && (D.getTag() == DW_TAG_const_type ||
- D.getTag() == DW_TAG_volatile_type))
- D = resolveReferencedType(D);
- return D;
-}
-
-bool DWARFTypePrinter::needsParens(DWARFDie D) {
- D = skipQualifiers(D);
- return D && (D.getTag() == DW_TAG_subroutine_type ||
- D.getTag() == DW_TAG_array_type);
-}
-
-void DWARFTypePrinter::appendPointerLikeTypeBefore(DWARFDie D, DWARFDie Inner,
- StringRef Ptr) {
- appendQualifiedNameBefore(Inner);
- if (Word)
- OS << ' ';
- if (needsParens(Inner))
- OS << '(';
- OS << Ptr;
- Word = false;
- EndedWithTemplate = false;
-}
-
-DWARFDie
-DWARFTypePrinter::appendUnqualifiedNameBefore(DWARFDie D,
- std::string *OriginalFullName) {
- Word = true;
- if (!D) {
- OS << "void";
- return DWARFDie();
- }
- DWARFDie InnerDIE;
- auto Inner = [&] { return InnerDIE = resolveReferencedType(D); };
- const dwarf::Tag T = D.getTag();
- switch (T) {
- case DW_TAG_pointer_type: {
- appendPointerLikeTypeBefore(D, Inner(), "*");
- break;
- }
- case DW_TAG_subroutine_type: {
- appendQualifiedNameBefore(Inner());
- if (Word) {
- OS << ' ';
- }
- Word = false;
- break;
- }
- case DW_TAG_array_type: {
- appendQualifiedNameBefore(Inner());
- break;
- }
- case DW_TAG_reference_type:
- appendPointerLikeTypeBefore(D, Inner(), "&");
- break;
- case DW_TAG_rvalue_reference_type:
- appendPointerLikeTypeBefore(D, Inner(), "&&");
- break;
- case DW_TAG_ptr_to_member_type: {
- appendQualifiedNameBefore(Inner());
- if (needsParens(InnerDIE))
- OS << '(';
- else if (Word)
- OS << ' ';
- if (DWARFDie Cont = resolveReferencedType(D, DW_AT_containing_type)) {
- appendQualifiedName(Cont);
- EndedWithTemplate = false;
- OS << "::";
- }
- OS << "*";
- Word = false;
- break;
- }
- case DW_TAG_LLVM_ptrauth_type:
- appendQualifiedNameBefore(Inner());
- break;
- case DW_TAG_const_type:
- case DW_TAG_volatile_type:
- appendConstVolatileQualifierBefore(D);
- break;
- case DW_TAG_namespace: {
- if (const char *Name = dwarf::toString(D.find(DW_AT_name), nullptr))
- OS << Name;
- else
- OS << "(anonymous namespace)";
- break;
- }
- case DW_TAG_unspecified_type: {
- StringRef TypeName = D.getShortName();
- if (TypeName == "decltype(nullptr)")
- TypeName = "std::nullptr_t";
- Word = true;
- OS << TypeName;
- EndedWithTemplate = false;
- break;
- }
- /*
- case DW_TAG_structure_type:
- case DW_TAG_class_type:
- case DW_TAG_enumeration_type:
- case DW_TAG_base_type:
- */
- default: {
- const char *NamePtr = dwarf::toString(D.find(DW_AT_name), nullptr);
- if (!NamePtr) {
- appendTypeTagName(D.getTag());
- return DWARFDie();
- }
- Word = true;
- StringRef Name = NamePtr;
- static constexpr StringRef MangledPrefix = "_STN|";
- if (Name.consume_front(MangledPrefix)) {
- auto Separator = Name.find('|');
- assert(Separator != StringRef::npos);
- StringRef BaseName = Name.substr(0, Separator);
- StringRef TemplateArgs = Name.substr(Separator + 1);
- if (OriginalFullName)
- *OriginalFullName = (BaseName + TemplateArgs).str();
- Name = BaseName;
- } else
- EndedWithTemplate = Name.ends_with(">");
- OS << Name;
- // This check would be insufficient for operator overloads like
- // "operator>>" - but for now Clang doesn't try to simplify them, so this
- // is OK. Add more nuanced operator overload handling here if/when needed.
- if (Name.ends_with(">"))
- break;
- if (!appendTemplateParameters(D))
- break;
-
- if (EndedWithTemplate)
- OS << ' ';
- OS << '>';
- EndedWithTemplate = true;
- Word = true;
- break;
- }
- }
- return InnerDIE;
-}
-
-void DWARFTypePrinter::appendUnqualifiedNameAfter(
- DWARFDie D, DWARFDie Inner, bool SkipFirstParamIfArtificial) {
- if (!D)
- return;
- switch (D.getTag()) {
- case DW_TAG_subroutine_type: {
- appendSubroutineNameAfter(D, Inner, SkipFirstParamIfArtificial, false,
- false);
- break;
- }
- case DW_TAG_array_type: {
- appendArrayType(D);
- break;
- }
- case DW_TAG_const_type:
- case DW_TAG_volatile_type:
- appendConstVolatileQualifierAfter(D);
- break;
- case DW_TAG_ptr_to_member_type:
- case DW_TAG_reference_type:
- case DW_TAG_rvalue_reference_type:
- case DW_TAG_pointer_type: {
- if (needsParens(Inner))
- OS << ')';
- appendUnqualifiedNameAfter(Inner, resolveReferencedType(Inner),
- /*SkipFirstParamIfArtificial=*/D.getTag() ==
- DW_TAG_ptr_to_member_type);
- break;
- }
- case DW_TAG_LLVM_ptrauth_type: {
- auto getValOrNull = [&](dwarf::Attribute Attr) -> uint64_t {
- if (auto Form = D.find(Attr))
- return *Form->getAsUnsignedConstant();
- return 0;
- };
- SmallVector<const char *, 2> optionsVec;
- if (getValOrNull(DW_AT_LLVM_ptrauth_isa_pointer))
- optionsVec.push_back("isa-pointer");
- if (getValOrNull(DW_AT_LLVM_ptrauth_authenticates_null_values))
- optionsVec.push_back("authenticates-null-values");
- if (auto AuthenticationMode =
- D.find(DW_AT_LLVM_ptrauth_authentication_mode)) {
- switch (*AuthenticationMode->getAsUnsignedConstant()) {
- case 0:
- case 1:
- optionsVec.push_back("strip");
- break;
- case 2:
- optionsVec.push_back("sign-and-strip");
- break;
- default:
- // Default authentication policy
- break;
- }
- }
- std::string options;
- for (const auto *option : optionsVec) {
- if (options.size())
- options += ",";
- options += option;
- }
- if (options.size())
- options = ", \"" + options + "\"";
- std::string PtrauthString;
- llvm::raw_string_ostream PtrauthStream(PtrauthString);
- PtrauthStream
- << "__ptrauth(" << getValOrNull(DW_AT_LLVM_ptrauth_key) << ", "
- << getValOrNull(DW_AT_LLVM_ptrauth_address_discriminated) << ", 0x0"
- << utohexstr(getValOrNull(DW_AT_LLVM_ptrauth_extra_discriminator), true)
- << options << ")";
- OS << PtrauthStream.str();
- break;
- }
- /*
- case DW_TAG_structure_type:
- case DW_TAG_class_type:
- case DW_TAG_enumeration_type:
- case DW_TAG_base_type:
- case DW_TAG_namespace:
- */
- default:
- break;
- }
-}
-
-/// Returns True if the DIE TAG is one of the ones that is scopped.
-static bool scopedTAGs(dwarf::Tag Tag) {
- switch (Tag) {
- case dwarf::DW_TAG_structure_type:
- case dwarf::DW_TAG_class_type:
- case dwarf::DW_TAG_union_type:
- case dwarf::DW_TAG_namespace:
- case dwarf::DW_TAG_enumeration_type:
- return true;
- default:
- break;
- }
- return false;
-}
-void DWARFTypePrinter::appendQualifiedName(DWARFDie D) {
- if (D && scopedTAGs(D.getTag()))
- appendScopes(D.getParent());
- appendUnqualifiedName(D);
-}
-DWARFDie DWARFTypePrinter::appendQualifiedNameBefore(DWARFDie D) {
- if (D && scopedTAGs(D.getTag()))
- appendScopes(D.getParent());
- return appendUnqualifiedNameBefore(D);
-}
-bool DWARFTypePrinter::appendTemplateParameters(DWARFDie D,
- bool *FirstParameter) {
- bool FirstParameterValue = true;
- bool IsTemplate = false;
- if (!FirstParameter)
- FirstParameter = &FirstParameterValue;
- for (const DWARFDie &C : D) {
- auto Sep = [&] {
- if (*FirstParameter)
- OS << '<';
- else
- OS << ", ";
- IsTemplate = true;
- EndedWithTemplate = false;
- *FirstParameter = false;
- };
- if (C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) {
- IsTemplate = true;
- appendTemplateParameters(C, FirstParameter);
- }
- if (C.getTag() == dwarf::DW_TAG_template_value_parameter) {
- DWARFDie T = resolveReferencedType(C);
- Sep();
- if (T.getTag() == DW_TAG_enumeration_type) {
- OS << '(';
- appendQualifiedName(T);
- OS << ')';
- auto V = C.find(DW_AT_const_value);
- OS << std::to_string(*V->getAsSignedConstant());
- continue;
- }
- // /Maybe/ we could do pointer type parameters, looking for the
- // symbol in the ELF symbol table to get back to the variable...
- // but probably not worth it.
- if (T.getTag() == DW_TAG_pointer_type)
- continue;
- const char *RawName = dwarf::toString(T.find(DW_AT_name), nullptr);
- assert(RawName);
- StringRef Name = RawName;
- auto V = C.find(DW_AT_const_value);
- bool IsQualifiedChar = false;
- if (Name == "bool") {
- OS << (*V->getAsUnsignedConstant() ? "true" : "false");
- } else if (Name == "short") {
- OS << "(short)";
- OS << std::to_string(*V->getAsSignedConstant());
- } else if (Name == "unsigned short") {
- OS << "(unsigned short)";
- OS << std::to_string(*V->getAsSignedConstant());
- } else if (Name == "int")
- OS << std::to_string(*V->getAsSignedConstant());
- else if (Name == "long") {
- OS << std::to_string(*V->getAsSignedConstant());
- OS << "L";
- } else if (Name == "long long") {
- OS << std::to_string(*V->getAsSignedConstant());
- OS << "LL";
- } else if (Name == "unsigned int") {
- OS << std::to_string(*V->getAsUnsignedConstant());
- OS << "U";
- } else if (Name == "unsigned long") {
- OS << std::to_string(*V->getAsUnsignedConstant());
- OS << "UL";
- } else if (Name == "unsigned long long") {
- OS << std::to_string(*V->getAsUnsignedConstant());
- OS << "ULL";
- } else if (Name == "char" ||
- (IsQualifiedChar =
- (Name == "unsigned char" || Name == "signed char"))) {
- // FIXME: check T's DW_AT_type to see if it's signed or not (since
- // char signedness is implementation defined).
- auto Val = *V->getAsSignedConstant();
- // Copied/hacked up from Clang's CharacterLiteral::print - incomplete
- // (doesn't actually support different character types/widths, sign
- // handling's not done, and doesn't correctly test if a character is
- // printable or needs to use a numeric escape sequence instead)
- if (IsQualifiedChar) {
- OS << '(';
- OS << Name;
- OS << ')';
- }
- switch (Val) {
- case '\\':
- OS << "'\\\\'";
- break;
- case '\'':
- OS << "'\\''";
- break;
- case '\a':
- // TODO: K&R: the meaning of '\\a' is different in traditional C
- OS << "'\\a'";
- break;
- case '\b':
- OS << "'\\b'";
- break;
- case '\f':
- OS << "'\\f'";
- break;
- case '\n':
- OS << "'\\n'";
- break;
- case '\r':
- OS << "'\\r'";
- break;
- case '\t':
- OS << "'\\t'";
- break;
- case '\v':
- OS << "'\\v'";
- break;
- default:
- if ((Val & ~0xFFu) == ~0xFFu)
- Val &= 0xFFu;
- if (Val < 127 && Val >= 32) {
- OS << "'";
- OS << (char)Val;
- OS << "'";
- } else if (Val < 256)
- OS << llvm::format("'\\x%02" PRIx64 "'", Val);
- else if (Val <= 0xFFFF)
- OS << llvm::format("'\\u%04" PRIx64 "'", Val);
- else
- OS << llvm::format("'\\U%08" PRIx64 "'", Val);
- }
- }
- continue;
- }
- if (C.getTag() == dwarf::DW_TAG_GNU_template_template_param) {
- const char *RawName =
- dwarf::toString(C.find(DW_AT_GNU_template_name), nullptr);
- assert(RawName);
- StringRef Name = RawName;
- Sep();
- OS << Name;
- continue;
- }
- if (C.getTag() != dwarf::DW_TAG_template_type_parameter)
- continue;
- auto TypeAttr = C.find(DW_AT_type);
- Sep();
- appendQualifiedName(TypeAttr ? resolveReferencedType(C, *TypeAttr)
- : DWARFDie());
- }
- if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {
- OS << '<';
- EndedWithTemplate = false;
- }
- return IsTemplate;
-}
-void DWARFTypePrinter::decomposeConstVolatile(DWARFDie &N, DWARFDie &T,
- DWARFDie &C, DWARFDie &V) {
- (N.getTag() == DW_TAG_const_type ? C : V) = N;
- T = resolveReferencedType(N);
- if (T) {
- auto Tag = T.getTag();
- if (Tag == DW_TAG_const_type) {
- C = T;
- T = resolveReferencedType(T);
- } else if (Tag == DW_TAG_volatile_type) {
- V = T;
- T = resolveReferencedType(T);
- }
- }
-}
-void DWARFTypePrinter::appendConstVolatileQualifierAfter(DWARFDie N) {
- DWARFDie C;
- DWARFDie V;
- DWARFDie T;
- decomposeConstVolatile(N, T, C, V);
- if (T && T.getTag() == DW_TAG_subroutine_type)
- appendSubroutineNameAfter(T, resolveReferencedType(T), false, C.isValid(),
- V.isValid());
- else
- appendUnqualifiedNameAfter(T, resolveReferencedType(T));
-}
-void DWARFTypePrinter::appendConstVolatileQualifierBefore(DWARFDie N) {
- DWARFDie C;
- DWARFDie V;
- DWARFDie T;
- decomposeConstVolatile(N, T, C, V);
- bool Subroutine = T && T.getTag() == DW_TAG_subroutine_type;
- DWARFDie A = T;
- while (A && A.getTag() == DW_TAG_array_type)
- A = resolveReferencedType(A);
- bool Leading =
- (!A || (A.getTag() != DW_TAG_pointer_type &&
- A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
- !Subroutine;
- if (Leading) {
- if (C)
- OS << "const ";
- if (V)
- OS << "volatile ";
- }
- appendQualifiedNameBefore(T);
- if (!Leading && !Subroutine) {
- Word = true;
- if (C)
- OS << "const";
- if (V) {
- if (C)
- OS << ' ';
- OS << "volatile";
- }
- }
-}
-void DWARFTypePrinter::appendUnqualifiedName(DWARFDie D,
- std::string *OriginalFullName) {
- // FIXME: We should have pretty printers per language. Currently we print
- // everything as if it was C++ and fall back to the TAG type name.
- DWARFDie Inner = appendUnqualifiedNameBefore(D, OriginalFullName);
- appendUnqualifiedNameAfter(D, Inner);
-}
-void DWARFTypePrinter::appendSubroutineNameAfter(
- DWARFDie D, DWARFDie Inner, bool SkipFirstParamIfArtificial, bool Const,
- bool Volatile) {
- DWARFDie FirstParamIfArtificial;
- OS << '(';
- EndedWithTemplate = false;
- bool First = true;
- bool RealFirst = true;
- for (DWARFDie P : D) {
- if (P.getTag() != DW_TAG_formal_parameter &&
- P.getTag() != DW_TAG_unspecified_parameters)
- return;
- DWARFDie T = resolveReferencedType(P);
- if (SkipFirstParamIfArtificial && RealFirst && P.find(DW_AT_artificial)) {
- FirstParamIfArtificial = T;
- RealFirst = false;
- continue;
- }
- if (!First) {
- OS << ", ";
- }
- First = false;
- if (P.getTag() == DW_TAG_unspecified_parameters)
- OS << "...";
- else
- appendQualifiedName(T);
- }
- EndedWithTemplate = false;
- OS << ')';
- if (FirstParamIfArtificial) {
- if (DWARFDie P = FirstParamIfArtificial) {
- if (P.getTag() == DW_TAG_pointer_type) {
- auto CVStep = [&](DWARFDie CV) {
- if (DWARFDie U = resolveReferencedType(CV)) {
- Const |= U.getTag() == DW_TAG_const_type;
- Volatile |= U.getTag() == DW_TAG_volatile_type;
- return U;
- }
- return DWARFDie();
- };
- if (DWARFDie CV = CVStep(P)) {
- CVStep(CV);
- }
- }
- }
- }
-
- if (auto CC = D.find(DW_AT_calling_convention)) {
- switch (*CC->getAsUnsignedConstant()) {
- case CallingConvention::DW_CC_BORLAND_stdcall:
- OS << " __attribute__((stdcall))";
- break;
- case CallingConvention::DW_CC_BORLAND_msfastcall:
- OS << " __attribute__((fastcall))";
- break;
- case CallingConvention::DW_CC_BORLAND_thiscall:
- OS << " __attribute__((thiscall))";
- break;
- case CallingConvention::DW_CC_LLVM_vectorcall:
- OS << " __attribute__((vectorcall))";
- break;
- case CallingConvention::DW_CC_BORLAND_pascal:
- OS << " __attribute__((pascal))";
- break;
- case CallingConvention::DW_CC_LLVM_Win64:
- OS << " __attribute__((ms_abi))";
- break;
- case CallingConvention::DW_CC_LLVM_X86_64SysV:
- OS << " __attribute__((sysv_abi))";
- break;
- case CallingConvention::DW_CC_LLVM_AAPCS:
- // AArch64VectorCall missing?
- OS << " __attribute__((pcs(\"aapcs\")))";
- break;
- case CallingConvention::DW_CC_LLVM_AAPCS_VFP:
- OS << " __attribute__((pcs(\"aapcs-vfp\")))";
- break;
- case CallingConvention::DW_CC_LLVM_IntelOclBicc:
- OS << " __attribute__((intel_ocl_bicc))";
- break;
- case CallingConvention::DW_CC_LLVM_SpirFunction:
- case CallingConvention::DW_CC_LLVM_OpenCLKernel:
- // These aren't available as attributes, but maybe we should still
- // render them somehow? (Clang doesn't render them, but that's an issue
- // for template names too - since then the DWARF names of templates
- // instantiated with function types with these calling conventions won't
- // have distinct names - so we'd need to fix that too)
- break;
- case CallingConvention::DW_CC_LLVM_Swift:
- // SwiftAsync missing
- OS << " __attribute__((swiftcall))";
- break;
- case CallingConvention::DW_CC_LLVM_PreserveMost:
- OS << " __attribute__((preserve_most))";
- break;
- case CallingConvention::DW_CC_LLVM_PreserveAll:
- OS << " __attribute__((preserve_all))";
- break;
- case CallingConvention::DW_CC_LLVM_PreserveNone:
- OS << " __attribute__((preserve_none))";
- break;
- case CallingConvention::DW_CC_LLVM_X86RegCall:
- OS << " __attribute__((regcall))";
- break;
- case CallingConvention::DW_CC_LLVM_M68kRTD:
- OS << " __attribute__((m68k_rtd))";
- break;
- }
- }
-
- if (Const)
- OS << " const";
- if (Volatile)
- OS << " volatile";
- if (D.find(DW_AT_reference))
- OS << " &";
- if (D.find(DW_AT_rvalue_reference))
- OS << " &&";
-
- appendUnqualifiedNameAfter(Inner, resolveReferencedType(Inner));
-}
-void DWARFTypePrinter::appendScopes(DWARFDie D) {
- if (D.getTag() == DW_TAG_compile_unit)
- return;
- if (D.getTag() == DW_TAG_type_unit)
- return;
- if (D.getTag() == DW_TAG_skeleton_unit)
- return;
- if (D.getTag() == DW_TAG_subprogram)
- return;
- if (D.getTag() == DW_TAG_lexical_block)
- return;
- D = D.resolveTypeUnitReference();
- if (DWARFDie P = D.getParent())
- appendScopes(P);
- appendUnqualifiedName(D);
- OS << "::";
-}
-} // namespace llvm
>From ff1d538fac78dae91e8e4599767a1159a7e0359d Mon Sep 17 00:00:00 2001
From: David Blaikie <dblaikie at gmail.com>
Date: Mon, 29 Apr 2024 18:28:59 +0000
Subject: [PATCH 4/7] More prototyping
---
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index a70d788f8eae85..f7c33f39a8a890 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -869,6 +869,7 @@ DWARFASTParserClang::GetDIEClassTemplateParams(const DWARFDIE &die) {
if (llvm::StringRef(die.GetName()).contains("<"))
return ConstString();
+ //std::cerr << "rebuilding template params for " << die.GetDIE()->GetOffset() << "\n";
#if 1
std::string R;
llvm::raw_string_ostream OS(R);
@@ -1633,6 +1634,7 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) {
const char *name = die.GetName();
if (!name)
return "";
+#if 0
static int indent = 0;
std::cerr << std::string(indent, ' ') << "starting qualified name for: " << name << '\n';
auto &FS = die.GetCU()->GetSymbolFileDWARF().GetObjectFile()->GetFileSpec();
@@ -1642,6 +1644,7 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) {
<< FS.GetFilename().AsCString("") << ':' << std::hex
<< die.GetDIE()->GetOffset() << '\n';
++indent;
+#endif
std::string qualified_name;
DWARFDIE parent_decl_ctx_die = die.GetParentDeclContextDIE();
// TODO: change this to get the correct decl context parent....
@@ -1687,8 +1690,10 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) {
qualified_name.append(name);
qualified_name.append(GetDIEClassTemplateParams(die).AsCString(""));
+#if 0
--indent;
std::cerr << std::string(indent, ' ') << "computed qualified name: " << qualified_name << '\n';
+#endif
return qualified_name;
}
>From ae672eddc50312604876f1c8948022f10fd56c91 Mon Sep 17 00:00:00 2001
From: David Blaikie <dblaikie at gmail.com>
Date: Fri, 31 May 2024 22:08:03 +0000
Subject: [PATCH 5/7] Another case of string comparison rather than AST
comparison
---
.../SymbolFile/DWARF/SymbolFileDWARF.cpp | 38 ++++++-------------
1 file changed, 11 insertions(+), 27 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 9500096a9f5b6e..94283adeee960c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -38,6 +38,8 @@
#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Interpreter/OptionValueProperties.h"
+#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
+
#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
#include "Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
@@ -2785,33 +2787,15 @@ void SymbolFileDWARF::FindTypes(const TypeQuery &query, TypeResults &results) {
return true; // Keep iterating over index types, language mismatch.
}
- // Check the context matches
- std::vector<lldb_private::CompilerContext> die_context;
- if (query.GetModuleSearch())
- die_context = die.GetDeclContext();
- else
- die_context = die.GetTypeLookupContext();
- assert(!die_context.empty());
- if (!query_simple.ContextMatches(die_context))
- return true; // Keep iterating over index types, context mismatch.
-
- // Try to resolve the type.
- if (Type *matching_type = ResolveType(die, true, true)) {
- ConstString name = matching_type->GetQualifiedName();
- // We have found a type that still might not match due to template
- // parameters. If we create a new TypeQuery that uses the new type's
- // fully qualified name, we can find out if this type matches at all
- // context levels. We can't use just the "match_simple" context
- // because all template parameters were stripped off. The fully
- // qualified name of the type will have the template parameters and
- // will allow us to make sure it matches correctly.
- TypeQuery die_query(name.GetStringRef(),
- TypeQueryOptions::e_exact_match);
- if (!query.ContextMatches(die_query.GetContextRef()))
- return true; // Keep iterating over index types, context mismatch.
-
- results.InsertUnique(matching_type->shared_from_this());
- }
+ std::string R;
+ llvm::raw_string_ostream OS(R);
+ llvm::DWARFTypePrinter<DWARFDIE> p(OS);
+ p.appendQualifiedName(die);
+
+ TypeQuery die_query(R, TypeQueryOptions::e_exact_match);
+ if (query.ContextMatches(die_query.GetContextRef()))
+ if (Type *matching_type = ResolveType(die, true, true))
+ results.InsertUnique(matching_type->shared_from_this());
return !results.Done(query); // Keep iterating if we aren't done.
});
if (results.Done(query))
>From 5da641c7e7c4ac638fde003a571ac6da74dc8cd2 Mon Sep 17 00:00:00 2001
From: David Blaikie <dblaikie at gmail.com>
Date: Wed, 5 Jun 2024 23:35:35 +0000
Subject: [PATCH 6/7] Perform DIE-to-string comparison
Rough prototype, doesn't handle namespace/context
---
lldb/include/lldb/Symbol/Type.h | 3 +
.../SymbolFile/DWARF/SymbolFileDWARF.cpp | 15 +-
.../llvm/DebugInfo/DWARF/DWARFTypePrinter.h | 327 ++++++++++--------
3 files changed, 194 insertions(+), 151 deletions(-)
diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h
index c6f30cde818674..eda74475a764e3 100644
--- a/lldb/include/lldb/Symbol/Type.h
+++ b/lldb/include/lldb/Symbol/Type.h
@@ -286,6 +286,9 @@ class TypeQuery {
std::vector<lldb_private::CompilerContext> &GetContextRef() {
return m_context;
}
+ const std::vector<lldb_private::CompilerContext> &GetContextRef() const {
+ return m_context;
+ }
protected:
/// A full or partial compiler context array where the parent declaration
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 94283adeee960c..c8cf87cfb549d4 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -2787,15 +2787,20 @@ void SymbolFileDWARF::FindTypes(const TypeQuery &query, TypeResults &results) {
return true; // Keep iterating over index types, language mismatch.
}
- std::string R;
- llvm::raw_string_ostream OS(R);
- llvm::DWARFTypePrinter<DWARFDIE> p(OS);
+ bool Success = true;
+ const auto &Context = query.GetContextRef();
+ assert(Context.size() == 1);
+ llvm::StringRef remaining = Context.front().name;
+ auto Visitor = [&](llvm::StringRef S) {
+ Success &= remaining.consume_front(S);
+ };
+ llvm::DWARFTypePrinter<DWARFDIE, decltype(Visitor)> p(Visitor);
p.appendQualifiedName(die);
- TypeQuery die_query(R, TypeQueryOptions::e_exact_match);
- if (query.ContextMatches(die_query.GetContextRef()))
+ if (Success && remaining.empty())
if (Type *matching_type = ResolveType(die, true, true))
results.InsertUnique(matching_type->shared_from_this());
+
return !results.Done(query); // Keep iterating if we aren't done.
});
if (results.Done(query))
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
index abc0ab8e27976a..59f1b2f6ee9215 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/ADT/SmallString.h"
#include <string>
@@ -18,14 +19,48 @@ namespace llvm {
class raw_ostream;
+namespace detail {
+struct DefaultVisitor {
+ raw_ostream &OS;
+ DefaultVisitor(raw_ostream &OS) : OS(OS) { }
+ void operator()(StringRef S) const {
+ OS << S;
+ }
+};
+
+inline llvm::SmallString<128> toString(const llvm::format_object_base &Fmt) {
+ size_t NextBufferSize = 127;
+ llvm::SmallString<128> V;
+
+ while (true) {
+ V.resize(NextBufferSize);
+
+ // Try formatting into the SmallVector.
+ size_t BytesUsed = Fmt.print(V.data(), NextBufferSize);
+
+ // If BytesUsed fit into the vector, we win.
+ if (BytesUsed <= NextBufferSize)
+ return V;
+
+ // Otherwise, try again with a new size.
+ assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?");
+ NextBufferSize = BytesUsed;
+ }
+}
+}
+
// FIXME: We should have pretty printers per language. Currently we print
// everything as if it was C++ and fall back to the TAG type name.
-template <typename DieType> struct DWARFTypePrinter {
- raw_ostream &OS;
+template <typename DieType, typename Visitor = detail::DefaultVisitor>
+struct DWARFTypePrinter {
+ Visitor V;
bool Word = true;
bool EndedWithTemplate = false;
- DWARFTypePrinter(raw_ostream &OS) : OS(OS) {}
+ DWARFTypePrinter(raw_ostream &OS) : V(OS) {
+ }
+ template<typename T>
+ DWARFTypePrinter(T &&V) : V(std::forward<T>(V)) {}
/// Dump the name encoded in the type tag.
void appendTypeTagName(dwarf::Tag T);
@@ -61,20 +96,20 @@ template <typename DieType> struct DWARFTypePrinter {
void appendScopes(DieType D);
};
-template <typename DieType>
-void DWARFTypePrinter<DieType>::appendTypeTagName(dwarf::Tag T) {
+template <typename DieType, typename Visitor>
+void DWARFTypePrinter<DieType, Visitor>::appendTypeTagName(dwarf::Tag T) {
StringRef TagStr = TagString(T);
static constexpr StringRef Prefix = "dwarf::DW_TAG_";
static constexpr StringRef Suffix = "_type";
if (!TagStr.starts_with(Prefix) || !TagStr.ends_with(Suffix))
return;
- OS << TagStr.substr(Prefix.size(),
- TagStr.size() - (Prefix.size() + Suffix.size()))
- << " ";
+ V(TagStr.substr(Prefix.size(),
+ TagStr.size() - (Prefix.size() + Suffix.size())));
+ V(" ");
}
-template <typename DieType>
-void DWARFTypePrinter<DieType>::appendArrayType(const DieType &D) {
+template <typename DieType, typename Visitor>
+void DWARFTypePrinter<DieType, Visitor>::appendArrayType(const DieType &D) {
for (const DieType &C : D.children()) {
if (C.getTag() != dwarf::DW_TAG_subrange_type)
continue;
@@ -98,26 +133,26 @@ void DWARFTypePrinter<DieType>::appendArrayType(const DieType &D) {
LB = std::nullopt;
*/
if (!LB && !Count && !UB)
- OS << "[]";
+ V("[]");
else if (!LB && (Count || UB) && DefaultLB)
- OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']';
+ V("["), V(Twine(Count ? *Count : *UB - *DefaultLB + 1).str()), V("]");
else {
- OS << "[[";
+ V("[[");
if (LB)
- OS << *LB;
+ V(Twine(*LB).str());
else
- OS << '?';
- OS << ", ";
+ V("?");
+ V(", ");
if (Count)
if (LB)
- OS << *LB + *Count;
+ V(Twine(*LB + *Count).str());
else
- OS << "? + " << *Count;
+ V("? + "), V(Twine(*Count).str());
else if (UB)
- OS << *UB + 1;
+ V(Twine(*UB + 1).str());
else
- OS << '?';
- OS << ")]";
+ V("?");
+ V(")]");
}
}
EndedWithTemplate = false;
@@ -135,41 +170,41 @@ DieType resolveReferencedType(DieType D, typename DieType::DWARFFormValue F) {
}
} // namespace detail
-template <typename DieType>
-DieType DWARFTypePrinter<DieType>::skipQualifiers(DieType D) {
+template <typename DieType, typename Visitor>
+DieType DWARFTypePrinter<DieType, Visitor>::skipQualifiers(DieType D) {
while (D && (D.getTag() == dwarf::DW_TAG_const_type ||
D.getTag() == dwarf::DW_TAG_volatile_type))
D = detail::resolveReferencedType(D);
return D;
}
-template <typename DieType>
-bool DWARFTypePrinter<DieType>::needsParens(DieType D) {
+template <typename DieType, typename Visitor>
+bool DWARFTypePrinter<DieType, Visitor>::needsParens(DieType D) {
D = skipQualifiers(D);
return D && (D.getTag() == dwarf::DW_TAG_subroutine_type ||
D.getTag() == dwarf::DW_TAG_array_type);
}
-template <typename DieType>
-void DWARFTypePrinter<DieType>::appendPointerLikeTypeBefore(DieType D,
+template <typename DieType, typename Visitor>
+void DWARFTypePrinter<DieType, Visitor>::appendPointerLikeTypeBefore(DieType D,
DieType Inner,
StringRef Ptr) {
appendQualifiedNameBefore(Inner);
if (Word)
- OS << ' ';
+ V(" ");
if (needsParens(Inner))
- OS << '(';
- OS << Ptr;
+ V("(");
+ V(Ptr);
Word = false;
EndedWithTemplate = false;
}
-template <typename DieType>
-DieType DWARFTypePrinter<DieType>::appendUnqualifiedNameBefore(
+template <typename DieType, typename Visitor>
+DieType DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedNameBefore(
DieType D, std::string *OriginalFullName) {
Word = true;
if (!D) {
- OS << "void";
+ V("void");
return DieType();
}
DieType InnerDIE;
@@ -183,7 +218,7 @@ DieType DWARFTypePrinter<DieType>::appendUnqualifiedNameBefore(
case dwarf::DW_TAG_subroutine_type: {
appendQualifiedNameBefore(Inner());
if (Word) {
- OS << ' ';
+ V(" ");
}
Word = false;
break;
@@ -201,15 +236,15 @@ DieType DWARFTypePrinter<DieType>::appendUnqualifiedNameBefore(
case dwarf::DW_TAG_ptr_to_member_type: {
appendQualifiedNameBefore(Inner());
if (needsParens(InnerDIE))
- OS << '(';
+ V("(");
else if (Word)
- OS << ' ';
+ V(" ");
if (DieType Cont = detail::resolveReferencedType(D, dwarf::DW_AT_containing_type)) {
appendQualifiedName(Cont);
EndedWithTemplate = false;
- OS << "::";
+ V("::");
}
- OS << "*";
+ V("*");
Word = false;
break;
}
@@ -222,9 +257,9 @@ DieType DWARFTypePrinter<DieType>::appendUnqualifiedNameBefore(
break;
case dwarf::DW_TAG_namespace: {
if (const char *Name = toString(D.find(dwarf::DW_AT_name), nullptr))
- OS << Name;
+ V(Name);
else
- OS << "(anonymous namespace)";
+ V("(anonymous namespace)");
break;
}
case dwarf::DW_TAG_unspecified_type: {
@@ -232,7 +267,7 @@ DieType DWARFTypePrinter<DieType>::appendUnqualifiedNameBefore(
if (TypeName == "decltype(nullptr)")
TypeName = "std::nullptr_t";
Word = true;
- OS << TypeName;
+ V(TypeName);
EndedWithTemplate = false;
break;
}
@@ -261,7 +296,7 @@ DieType DWARFTypePrinter<DieType>::appendUnqualifiedNameBefore(
Name = BaseName;
} else
EndedWithTemplate = Name.ends_with(">");
- OS << Name;
+ V(Name);
// This check would be insufficient for operator overloads like
// "operator>>" - but for now Clang doesn't try to simplify them, so this
// is OK. Add more nuanced operator overload handling here if/when needed.
@@ -274,20 +309,20 @@ DieType DWARFTypePrinter<DieType>::appendUnqualifiedNameBefore(
return InnerDIE;
}
-template <typename DieType>
-void DWARFTypePrinter<DieType>::appendAndTerminateTemplateParameters(DieType D) {
+template <typename DieType, typename Visitor>
+void DWARFTypePrinter<DieType, Visitor>::appendAndTerminateTemplateParameters(DieType D) {
if (!appendTemplateParameters(D))
return;
if (EndedWithTemplate)
- OS << ' ';
- OS << '>';
+ V(" ");
+ V(">");
EndedWithTemplate = true;
Word = true;
}
-template <typename DieType>
-void DWARFTypePrinter<DieType>::appendUnqualifiedNameAfter(
+template <typename DieType, typename Visitor>
+void DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedNameAfter(
DieType D, DieType Inner, bool SkipFirstParamIfArtificial) {
if (!D)
return;
@@ -310,7 +345,7 @@ void DWARFTypePrinter<DieType>::appendUnqualifiedNameAfter(
case dwarf::DW_TAG_rvalue_reference_type:
case dwarf::DW_TAG_pointer_type: {
if (needsParens(Inner))
- OS << ')';
+ V(")");
appendUnqualifiedNameAfter(Inner, detail::resolveReferencedType(Inner),
/*SkipFirstParamIfArtificial=*/D.getTag() ==
dwarf::DW_TAG_ptr_to_member_type);
@@ -357,7 +392,7 @@ void DWARFTypePrinter<DieType>::appendUnqualifiedNameAfter(
<< getValOrNull(dwarf::DW_AT_LLVM_ptrauth_address_discriminated) << ", 0x0"
<< utohexstr(getValOrNull(dwarf::DW_AT_LLVM_ptrauth_extra_discriminator), true)
<< options << ")";
- OS << PtrauthStream.str();
+ V(PtrauthStream.str());
break;
}
/*
@@ -388,20 +423,20 @@ inline bool scopedTAGs(dwarf::Tag Tag) {
return false;
}
} // namespace detail
-template <typename DieType>
-void DWARFTypePrinter<DieType>::appendQualifiedName(DieType D) {
+template <typename DieType, typename Visitor>
+void DWARFTypePrinter<DieType, Visitor>::appendQualifiedName(DieType D) {
if (D && detail::scopedTAGs(D.getTag()))
appendScopes(D.getParent());
appendUnqualifiedName(D);
}
-template <typename DieType>
-DieType DWARFTypePrinter<DieType>::appendQualifiedNameBefore(DieType D) {
+template <typename DieType, typename Visitor>
+DieType DWARFTypePrinter<DieType, Visitor>::appendQualifiedNameBefore(DieType D) {
if (D && detail::scopedTAGs(D.getTag()))
appendScopes(D.getParent());
return appendUnqualifiedNameBefore(D);
}
-template <typename DieType>
-bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
+template <typename DieType, typename Visitor>
+bool DWARFTypePrinter<DieType, Visitor>::appendTemplateParameters(DieType D,
bool *FirstParameter) {
bool FirstParameterValue = true;
bool IsTemplate = false;
@@ -410,9 +445,9 @@ bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
for (const DieType &C : D) {
auto Sep = [&] {
if (*FirstParameter)
- OS << '<';
+ V("<");
else
- OS << ", ";
+ V(", ");
IsTemplate = true;
EndedWithTemplate = false;
*FirstParameter = false;
@@ -425,11 +460,11 @@ bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
DieType T = detail::resolveReferencedType(C);
Sep();
if (T.getTag() == dwarf::DW_TAG_enumeration_type) {
- OS << '(';
+ V("(");
appendQualifiedName(T);
- OS << ')';
- auto V = C.find(dwarf::DW_AT_const_value);
- OS << std::to_string(*V->getAsSignedConstant());
+ V(")");
+ auto Value = C.find(dwarf::DW_AT_const_value);
+ V(std::to_string(*Value->getAsSignedConstant()));
continue;
}
// /Maybe/ we could do pointer type parameters, looking for the
@@ -440,90 +475,90 @@ bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
const char *RawName = toString(T.find(dwarf::DW_AT_name), nullptr);
assert(RawName);
StringRef Name = RawName;
- auto V = C.find(dwarf::DW_AT_const_value);
+ auto Value = C.find(dwarf::DW_AT_const_value);
bool IsQualifiedChar = false;
if (Name == "bool") {
- OS << (*V->getAsUnsignedConstant() ? "true" : "false");
+ V((*Value->getAsUnsignedConstant() ? "true" : "false"));
} else if (Name == "short") {
- OS << "(short)";
- OS << std::to_string(*V->getAsSignedConstant());
+ V("(short)");
+ V(std::to_string(*Value->getAsSignedConstant()));
} else if (Name == "unsigned short") {
- OS << "(unsigned short)";
- OS << std::to_string(*V->getAsSignedConstant());
+ V("(unsigned short)");
+ V(std::to_string(*Value->getAsSignedConstant()));
} else if (Name == "int")
- OS << std::to_string(*V->getAsSignedConstant());
+ V(std::to_string(*Value->getAsSignedConstant()));
else if (Name == "long") {
- OS << std::to_string(*V->getAsSignedConstant());
- OS << "L";
+ V(std::to_string(*Value->getAsSignedConstant()));
+ V("L");
} else if (Name == "long long") {
- OS << std::to_string(*V->getAsSignedConstant());
- OS << "LL";
+ V(std::to_string(*Value->getAsSignedConstant()));
+ V("LL");
} else if (Name == "unsigned int") {
- OS << std::to_string(*V->getAsUnsignedConstant());
- OS << "U";
+ V(std::to_string(*Value->getAsUnsignedConstant()));
+ V("U");
} else if (Name == "unsigned long") {
- OS << std::to_string(*V->getAsUnsignedConstant());
- OS << "UL";
+ V(std::to_string(*Value->getAsUnsignedConstant()));
+ V("UL");
} else if (Name == "unsigned long long") {
- OS << std::to_string(*V->getAsUnsignedConstant());
- OS << "ULL";
+ V(std::to_string(*Value->getAsUnsignedConstant()));
+ V("ULL");
} else if (Name == "char" ||
(IsQualifiedChar =
(Name == "unsigned char" || Name == "signed char"))) {
// FIXME: check T's dwarf::DW_AT_type to see if it's signed or not (since
// char signedness is implementation defined).
- auto Val = *V->getAsSignedConstant();
+ auto Val = *Value->getAsSignedConstant();
// Copied/hacked up from Clang's CharacterLiteral::print - incomplete
// (doesn't actually support different character types/widths, sign
// handling's not done, and doesn't correctly test if a character is
// printable or needs to use a numeric escape sequence instead)
if (IsQualifiedChar) {
- OS << '(';
- OS << Name;
- OS << ')';
+ V("(");
+ V(Name);
+ V(")");
}
switch (Val) {
case '\\':
- OS << "'\\\\'";
+ V("'\\\\'");
break;
case '\'':
- OS << "'\\''";
+ V("'\\''");
break;
case '\a':
// TODO: K&R: the meaning of '\\a' is different in traditional C
- OS << "'\\a'";
+ V("'\\a'");
break;
case '\b':
- OS << "'\\b'";
+ V("'\\b'");
break;
case '\f':
- OS << "'\\f'";
+ V("'\\f'");
break;
case '\n':
- OS << "'\\n'";
+ V("'\\n'");
break;
case '\r':
- OS << "'\\r'";
+ V("'\\r'");
break;
case '\t':
- OS << "'\\t'";
+ V("'\\t'");
break;
case '\v':
- OS << "'\\v'";
+ V("'\\v'");
break;
default:
if ((Val & ~0xFFu) == ~0xFFu)
Val &= 0xFFu;
if (Val < 127 && Val >= 32) {
- OS << "'";
- OS << (char)Val;
- OS << "'";
+ V("'");
+ V(Twine((char)Val).str());
+ V("'");
} else if (Val < 256)
- OS << llvm::format("'\\x%02" PRIx64 "'", Val);
+ V(detail::toString(llvm::format("'\\x%02" PRIx64 "'", Val)));
else if (Val <= 0xFFFF)
- OS << llvm::format("'\\u%04" PRIx64 "'", Val);
+ V(detail::toString(llvm::format("'\\u%04" PRIx64 "'", Val)));
else
- OS << llvm::format("'\\U%08" PRIx64 "'", Val);
+ V(detail::toString(llvm::format("'\\U%08" PRIx64 "'", Val)));
}
}
continue;
@@ -534,7 +569,7 @@ bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
assert(RawName);
StringRef Name = RawName;
Sep();
- OS << Name;
+ V(Name);
continue;
}
if (C.getTag() != dwarf::DW_TAG_template_type_parameter)
@@ -545,13 +580,13 @@ bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
: DieType());
}
if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {
- OS << '<';
+ V("<");
EndedWithTemplate = false;
}
return IsTemplate;
}
-template <typename DieType>
-void DWARFTypePrinter<DieType>::decomposeConstVolatile(DieType &N, DieType &T,
+template <typename DieType, typename Visitor>
+void DWARFTypePrinter<DieType, Visitor>::decomposeConstVolatile(DieType &N, DieType &T,
DieType &C, DieType &V) {
(N.getTag() == dwarf::DW_TAG_const_type ? C : V) = N;
T = detail::resolveReferencedType(N);
@@ -566,8 +601,8 @@ void DWARFTypePrinter<DieType>::decomposeConstVolatile(DieType &N, DieType &T,
}
}
}
-template <typename DieType>
-void DWARFTypePrinter<DieType>::appendConstVolatileQualifierAfter(DieType N) {
+template <typename DieType, typename Visitor>
+void DWARFTypePrinter<DieType, Visitor>::appendConstVolatileQualifierAfter(DieType N) {
DieType C;
DieType V;
DieType T;
@@ -578,12 +613,12 @@ void DWARFTypePrinter<DieType>::appendConstVolatileQualifierAfter(DieType N) {
else
appendUnqualifiedNameAfter(T, detail::resolveReferencedType(T));
}
-template <typename DieType>
-void DWARFTypePrinter<DieType>::appendConstVolatileQualifierBefore(DieType N) {
+template <typename DieType, typename Visitor>
+void DWARFTypePrinter<DieType, Visitor>::appendConstVolatileQualifierBefore(DieType N) {
DieType C;
- DieType V;
+ DieType Vol;
DieType T;
- decomposeConstVolatile(N, T, C, V);
+ decomposeConstVolatile(N, T, C, Vol);
bool Subroutine = T && T.getTag() == dwarf::DW_TAG_subroutine_type;
DieType A = T;
while (A && A.getTag() == dwarf::DW_TAG_array_type)
@@ -594,36 +629,36 @@ void DWARFTypePrinter<DieType>::appendConstVolatileQualifierBefore(DieType N) {
!Subroutine;
if (Leading) {
if (C)
- OS << "const ";
- if (V)
- OS << "volatile ";
+ V("const ");
+ if (Vol)
+ V("volatile ");
}
appendQualifiedNameBefore(T);
if (!Leading && !Subroutine) {
Word = true;
if (C)
- OS << "const";
- if (V) {
+ V("const");
+ if (Vol) {
if (C)
- OS << ' ';
- OS << "volatile";
+ V(" ");
+ V("volatile");
}
}
}
-template <typename DieType>
-void DWARFTypePrinter<DieType>::appendUnqualifiedName(
+template <typename DieType, typename Visitor>
+void DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedName(
DieType D, std::string *OriginalFullName) {
// FIXME: We should have pretty printers per language. Currently we print
// everything as if it was C++ and fall back to the TAG type name.
DieType Inner = appendUnqualifiedNameBefore(D, OriginalFullName);
appendUnqualifiedNameAfter(D, Inner);
}
-template <typename DieType>
-void DWARFTypePrinter<DieType>::appendSubroutineNameAfter(
+template <typename DieType, typename Visitor>
+void DWARFTypePrinter<DieType, Visitor>::appendSubroutineNameAfter(
DieType D, DieType Inner, bool SkipFirstParamIfArtificial, bool Const,
bool Volatile) {
DieType FirstParamIfArtificial;
- OS << '(';
+ V("(");
EndedWithTemplate = false;
bool First = true;
bool RealFirst = true;
@@ -638,16 +673,16 @@ void DWARFTypePrinter<DieType>::appendSubroutineNameAfter(
continue;
}
if (!First) {
- OS << ", ";
+ V(", ");
}
First = false;
if (P.getTag() == dwarf::DW_TAG_unspecified_parameters)
- OS << "...";
+ V("...");
else
appendQualifiedName(T);
}
EndedWithTemplate = false;
- OS << ')';
+ V(")");
if (FirstParamIfArtificial) {
if (DieType P = FirstParamIfArtificial) {
if (P.getTag() == dwarf::DW_TAG_pointer_type) {
@@ -669,35 +704,35 @@ void DWARFTypePrinter<DieType>::appendSubroutineNameAfter(
if (auto CC = D.find(dwarf::DW_AT_calling_convention)) {
switch (*CC->getAsUnsignedConstant()) {
case dwarf::CallingConvention::DW_CC_BORLAND_stdcall:
- OS << " __attribute__((stdcall))";
+ V(" __attribute__((stdcall))");
break;
case dwarf::CallingConvention::DW_CC_BORLAND_msfastcall:
- OS << " __attribute__((fastcall))";
+ V(" __attribute__((fastcall))");
break;
case dwarf::CallingConvention::DW_CC_BORLAND_thiscall:
- OS << " __attribute__((thiscall))";
+ V(" __attribute__((thiscall))");
break;
case dwarf::CallingConvention::DW_CC_LLVM_vectorcall:
- OS << " __attribute__((vectorcall))";
+ V(" __attribute__((vectorcall))");
break;
case dwarf::CallingConvention::DW_CC_BORLAND_pascal:
- OS << " __attribute__((pascal))";
+ V(" __attribute__((pascal))");
break;
case dwarf::CallingConvention::DW_CC_LLVM_Win64:
- OS << " __attribute__((ms_abi))";
+ V(" __attribute__((ms_abi))");
break;
case dwarf::CallingConvention::DW_CC_LLVM_X86_64SysV:
- OS << " __attribute__((sysv_abi))";
+ V(" __attribute__((sysv_abi))");
break;
case dwarf::CallingConvention::DW_CC_LLVM_AAPCS:
// AArch64VectorCall missing?
- OS << " __attribute__((pcs(\"aapcs\")))";
+ V(" __attribute__((pcs(\"aapcs\")))");
break;
case dwarf::CallingConvention::DW_CC_LLVM_AAPCS_VFP:
- OS << " __attribute__((pcs(\"aapcs-vfp\")))";
+ V(" __attribute__((pcs(\"aapcs-vfp\")))");
break;
case dwarf::CallingConvention::DW_CC_LLVM_IntelOclBicc:
- OS << " __attribute__((intel_ocl_bicc))";
+ V(" __attribute__((intel_ocl_bicc))");
break;
case dwarf::CallingConvention::DW_CC_LLVM_SpirFunction:
case dwarf::CallingConvention::DW_CC_LLVM_OpenCLKernel:
@@ -709,39 +744,39 @@ void DWARFTypePrinter<DieType>::appendSubroutineNameAfter(
break;
case dwarf::CallingConvention::DW_CC_LLVM_Swift:
// SwiftAsync missing
- OS << " __attribute__((swiftcall))";
+ V(" __attribute__((swiftcall))");
break;
case dwarf::CallingConvention::DW_CC_LLVM_PreserveMost:
- OS << " __attribute__((preserve_most))";
+ V(" __attribute__((preserve_most))");
break;
case dwarf::CallingConvention::DW_CC_LLVM_PreserveAll:
- OS << " __attribute__((preserve_all))";
+ V(" __attribute__((preserve_all))");
break;
case dwarf::CallingConvention::DW_CC_LLVM_PreserveNone:
- OS << " __attribute__((preserve_none))";
+ V(" __attribute__((preserve_none))");
break;
case dwarf::CallingConvention::DW_CC_LLVM_X86RegCall:
- OS << " __attribute__((regcall))";
+ V(" __attribute__((regcall))");
break;
case dwarf::CallingConvention::DW_CC_LLVM_M68kRTD:
- OS << " __attribute__((m68k_rtd))";
+ V(" __attribute__((m68k_rtd))");
break;
}
}
if (Const)
- OS << " const";
+ V(" const");
if (Volatile)
- OS << " volatile";
+ V(" volatile");
if (D.find(dwarf::DW_AT_reference))
- OS << " &";
+ V(" &");
if (D.find(dwarf::DW_AT_rvalue_reference))
- OS << " &&";
+ V(" &&");
appendUnqualifiedNameAfter(Inner, detail::resolveReferencedType(Inner));
}
-template <typename DieType>
-void DWARFTypePrinter<DieType>::appendScopes(DieType D) {
+template <typename DieType, typename Visitor>
+void DWARFTypePrinter<DieType, Visitor>::appendScopes(DieType D) {
if (D.getTag() == dwarf::DW_TAG_compile_unit)
return;
if (D.getTag() == dwarf::DW_TAG_type_unit)
@@ -756,7 +791,7 @@ void DWARFTypePrinter<DieType>::appendScopes(DieType D) {
if (DieType P = D.getParent())
appendScopes(P);
appendUnqualifiedName(D);
- OS << "::";
+ V("::");
}
} // namespace llvm
>From 334301ae2ede954c21bc7f228d079341ea372b5a Mon Sep 17 00:00:00 2001
From: David Blaikie <dblaikie at gmail.com>
Date: Fri, 7 Jun 2024 20:20:38 +0000
Subject: [PATCH 7/7] DIE-to-consumer (string, in this case) matching, with
quick exit on failure
---
.../Plugins/SymbolFile/DWARF/DWARFDIE.cpp | 7 +
.../Plugins/SymbolFile/DWARF/DWARFDIE.h | 4 +
.../SymbolFile/DWARF/SymbolFileDWARF.cpp | 1 +
.../llvm/DebugInfo/DWARF/DWARFTypePrinter.h | 498 ++++++++++--------
4 files changed, 288 insertions(+), 222 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index 23eeaa0c937f51..a3d6237ada87b3 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -564,3 +564,10 @@ std::optional<DWARFFormValue> DWARFDIE::find(const dw_attr_t attr) const {
return form_value;
return std::nullopt;
}
+
+std::optional<uint64_t> llvm::getLanguage(lldb_private::plugin::dwarf::DWARFDIE D) {
+ if (auto I = D.GetCU()->GetDWARFLanguageType())
+ return I;
+ return std::nullopt;
+}
+
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
index e3e2f725cfdf69..ae32f980db2414 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -156,4 +156,8 @@ class DWARFDIE::child_iterator
} // namespace dwarf
} // namespace lldb_private::plugin
+namespace llvm {
+std::optional<uint64_t> getLanguage(lldb_private::plugin::dwarf::DWARFDIE D);
+}
+
#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDIE_H
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index c8cf87cfb549d4..dacf2ce6094c1d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -2793,6 +2793,7 @@ void SymbolFileDWARF::FindTypes(const TypeQuery &query, TypeResults &results) {
llvm::StringRef remaining = Context.front().name;
auto Visitor = [&](llvm::StringRef S) {
Success &= remaining.consume_front(S);
+ return Success;
};
llvm::DWARFTypePrinter<DWARFDIE, decltype(Visitor)> p(Visitor);
p.appendQualifiedName(die);
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
index 59f1b2f6ee9215..698eaf822afc36 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
@@ -19,12 +19,20 @@ namespace llvm {
class raw_ostream;
+inline std::optional<uint64_t> getLanguage(DWARFDie D) {
+ if (std::optional<DWARFFormValue> LV =
+ D.getDwarfUnit()->getUnitDIE().find(dwarf::DW_AT_language))
+ return LV->getAsUnsignedConstant();
+ return std::nullopt;
+}
+
namespace detail {
struct DefaultVisitor {
raw_ostream &OS;
DefaultVisitor(raw_ostream &OS) : OS(OS) { }
- void operator()(StringRef S) const {
+ bool operator()(StringRef S) const {
OS << S;
+ return true;
}
};
@@ -33,14 +41,16 @@ inline llvm::SmallString<128> toString(const llvm::format_object_base &Fmt) {
llvm::SmallString<128> V;
while (true) {
- V.resize(NextBufferSize);
+ V.resize_for_overwrite(NextBufferSize);
// Try formatting into the SmallVector.
size_t BytesUsed = Fmt.print(V.data(), NextBufferSize);
// If BytesUsed fit into the vector, we win.
- if (BytesUsed <= NextBufferSize)
+ if (BytesUsed <= NextBufferSize) {
+ V.resize(BytesUsed);
return V;
+ }
// Otherwise, try again with a new size.
assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?");
@@ -49,6 +59,9 @@ inline llvm::SmallString<128> toString(const llvm::format_object_base &Fmt) {
}
}
+#define LLVM_QUICK_EXIT(expr) if (!(expr)) return false
+#define LLVM_QUICK_EXIT_NONE(expr) if (!(expr)) return std::nullopt
+
// FIXME: We should have pretty printers per language. Currently we print
// everything as if it was C++ and fall back to the TAG type name.
template <typename DieType, typename Visitor = detail::DefaultVisitor>
@@ -63,99 +76,105 @@ struct DWARFTypePrinter {
DWARFTypePrinter(T &&V) : V(std::forward<T>(V)) {}
/// Dump the name encoded in the type tag.
- void appendTypeTagName(dwarf::Tag T);
+ bool appendTypeTagName(dwarf::Tag T);
- void appendArrayType(const DieType &D);
+ bool appendArrayType(const DieType &D);
DieType skipQualifiers(DieType D);
bool needsParens(DieType D);
- void appendPointerLikeTypeBefore(DieType D, DieType Inner, StringRef Ptr);
+ bool appendPointerLikeTypeBefore(DieType D, DieType Inner, StringRef Ptr);
- DieType appendUnqualifiedNameBefore(DieType D,
- std::string *OriginalFullName = nullptr);
+ std::optional<DieType>
+ appendUnqualifiedNameBefore(DieType D,
+ std::string *OriginalFullName = nullptr);
- void appendUnqualifiedNameAfter(DieType D, DieType Inner,
+ bool appendUnqualifiedNameAfter(DieType D, DieType Inner,
bool SkipFirstParamIfArtificial = false);
- void appendQualifiedName(DieType D);
- DieType appendQualifiedNameBefore(DieType D);
- bool appendTemplateParameters(DieType D, bool *FirstParameter = nullptr);
- void appendAndTerminateTemplateParameters(DieType D);
+ bool appendQualifiedName(DieType D);
+ std::optional<DieType> appendQualifiedNameBefore(DieType D);
+ std::optional<bool> appendTemplateParameters(DieType D, bool *FirstParameter = nullptr);
+ bool appendAndTerminateTemplateParameters(DieType D);
void decomposeConstVolatile(DieType &N, DieType &T, DieType &C, DieType &V);
- void appendConstVolatileQualifierAfter(DieType N);
- void appendConstVolatileQualifierBefore(DieType N);
+ bool appendConstVolatileQualifierAfter(DieType N);
+ bool appendConstVolatileQualifierBefore(DieType N);
/// Recursively append the DIE type name when applicable.
- void appendUnqualifiedName(DieType D,
+ bool appendUnqualifiedName(DieType D,
std::string *OriginalFullName = nullptr);
- void appendSubroutineNameAfter(DieType D, DieType Inner,
+ bool appendSubroutineNameAfter(DieType D, DieType Inner,
bool SkipFirstParamIfArtificial, bool Const,
bool Volatile);
- void appendScopes(DieType D);
+ bool appendScopes(DieType D);
};
template <typename DieType, typename Visitor>
-void DWARFTypePrinter<DieType, Visitor>::appendTypeTagName(dwarf::Tag T) {
+bool DWARFTypePrinter<DieType, Visitor>::appendTypeTagName(dwarf::Tag T) {
StringRef TagStr = TagString(T);
static constexpr StringRef Prefix = "dwarf::DW_TAG_";
static constexpr StringRef Suffix = "_type";
if (!TagStr.starts_with(Prefix) || !TagStr.ends_with(Suffix))
- return;
- V(TagStr.substr(Prefix.size(),
- TagStr.size() - (Prefix.size() + Suffix.size())));
- V(" ");
+ return true;
+ LLVM_QUICK_EXIT(V(TagStr.substr(
+ Prefix.size(), TagStr.size() - (Prefix.size() + Suffix.size()))));
+ LLVM_QUICK_EXIT(V(" "));
+ return true;
}
template <typename DieType, typename Visitor>
-void DWARFTypePrinter<DieType, Visitor>::appendArrayType(const DieType &D) {
+bool DWARFTypePrinter<DieType, Visitor>::appendArrayType(const DieType &D) {
for (const DieType &C : D.children()) {
if (C.getTag() != dwarf::DW_TAG_subrange_type)
continue;
std::optional<uint64_t> LB;
std::optional<uint64_t> Count;
std::optional<uint64_t> UB;
- std::optional<unsigned> DefaultLB;
+ std::optional<uint64_t> DefaultLB;
if (std::optional<typename DieType::DWARFFormValue> L = C.find(dwarf::DW_AT_lower_bound))
LB = L->getAsUnsignedConstant();
if (std::optional<typename DieType::DWARFFormValue> CountV = C.find(dwarf::DW_AT_count))
Count = CountV->getAsUnsignedConstant();
if (std::optional<typename DieType::DWARFFormValue> UpperV = C.find(dwarf::DW_AT_upper_bound))
UB = UpperV->getAsUnsignedConstant();
- /*
- if (std::optional<typename DieType::DWARFFormValue> LV =
- D.getDwarfUnit()->getUnitDIE().find(dwarf::DW_AT_language))
- if (std::optional<uint64_t> LC = LV->getAsUnsignedConstant())
- if ((DefaultLB =
- LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LC))))
- if (LB && *LB == *DefaultLB)
- LB = std::nullopt;
- */
- if (!LB && !Count && !UB)
- V("[]");
- else if (!LB && (Count || UB) && DefaultLB)
- V("["), V(Twine(Count ? *Count : *UB - *DefaultLB + 1).str()), V("]");
- else {
- V("[[");
- if (LB)
- V(Twine(*LB).str());
- else
- V("?");
- V(", ");
- if (Count)
- if (LB)
- V(Twine(*LB + *Count).str());
- else
- V("? + "), V(Twine(*Count).str());
- else if (UB)
- V(Twine(*UB + 1).str());
- else
- V("?");
- V(")]");
+
+ if (std::optional<uint64_t> LC = getLanguage(D))
+ DefaultLB =
+ LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LC));
+
+ if (DefaultLB == LB)
+ LB = std::nullopt;
+ if (!LB && !Count && !UB) {
+ LLVM_QUICK_EXIT(V("[]"));
+ } else if (!LB && (Count || UB) && DefaultLB) {
+ LLVM_QUICK_EXIT(V("[") &&
+ V(Twine(Count ? *Count : *UB - *DefaultLB + 1).str()) &&
+ V("]"));
+ } else {
+ LLVM_QUICK_EXIT(V("[["));
+ if (LB) {
+ LLVM_QUICK_EXIT(V(Twine(*LB).str()));
+ } else {
+ LLVM_QUICK_EXIT(V("?"));
+ }
+ LLVM_QUICK_EXIT(V(", "));
+ if (Count) {
+ if (LB) {
+ LLVM_QUICK_EXIT(V(Twine(*LB + *Count).str()));
+ } else {
+ LLVM_QUICK_EXIT(V("? + ") && V(Twine(*Count).str()));
+ }
+ } else if (UB) {
+ LLVM_QUICK_EXIT(V(Twine(*UB + 1).str()));
+ } else {
+ LLVM_QUICK_EXIT(V("?"));
+ }
+ LLVM_QUICK_EXIT(V(")]"));
}
}
EndedWithTemplate = false;
+ return true;
}
namespace detail {
@@ -186,25 +205,25 @@ bool DWARFTypePrinter<DieType, Visitor>::needsParens(DieType D) {
}
template <typename DieType, typename Visitor>
-void DWARFTypePrinter<DieType, Visitor>::appendPointerLikeTypeBefore(DieType D,
- DieType Inner,
- StringRef Ptr) {
- appendQualifiedNameBefore(Inner);
+bool DWARFTypePrinter<DieType, Visitor>::appendPointerLikeTypeBefore(
+ DieType D, DieType Inner, StringRef Ptr) {
+ LLVM_QUICK_EXIT(appendQualifiedNameBefore(Inner));
if (Word)
- V(" ");
+ LLVM_QUICK_EXIT(V(" "));
if (needsParens(Inner))
- V("(");
- V(Ptr);
+ LLVM_QUICK_EXIT(V("("));
+ LLVM_QUICK_EXIT(V(Ptr));
Word = false;
EndedWithTemplate = false;
+ return true;
}
template <typename DieType, typename Visitor>
-DieType DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedNameBefore(
+std::optional<DieType> DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedNameBefore(
DieType D, std::string *OriginalFullName) {
Word = true;
if (!D) {
- V("void");
+ LLVM_QUICK_EXIT_NONE(V("void"));
return DieType();
}
DieType InnerDIE;
@@ -212,54 +231,55 @@ DieType DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedNameBefore(
const dwarf::Tag T = D.getTag();
switch (T) {
case dwarf::DW_TAG_pointer_type: {
- appendPointerLikeTypeBefore(D, Inner(), "*");
+ LLVM_QUICK_EXIT_NONE(appendPointerLikeTypeBefore(D, Inner(), "*"));
break;
}
case dwarf::DW_TAG_subroutine_type: {
- appendQualifiedNameBefore(Inner());
+ LLVM_QUICK_EXIT_NONE(appendQualifiedNameBefore(Inner()));
if (Word) {
- V(" ");
+ LLVM_QUICK_EXIT_NONE(V(" "));
}
Word = false;
break;
}
case dwarf::DW_TAG_array_type: {
- appendQualifiedNameBefore(Inner());
+ LLVM_QUICK_EXIT_NONE(appendQualifiedNameBefore(Inner()));
break;
}
case dwarf::DW_TAG_reference_type:
- appendPointerLikeTypeBefore(D, Inner(), "&");
+ LLVM_QUICK_EXIT_NONE(appendPointerLikeTypeBefore(D, Inner(), "&"));
break;
case dwarf::DW_TAG_rvalue_reference_type:
- appendPointerLikeTypeBefore(D, Inner(), "&&");
+ LLVM_QUICK_EXIT_NONE(appendPointerLikeTypeBefore(D, Inner(), "&&"));
break;
case dwarf::DW_TAG_ptr_to_member_type: {
- appendQualifiedNameBefore(Inner());
- if (needsParens(InnerDIE))
- V("(");
- else if (Word)
- V(" ");
- if (DieType Cont = detail::resolveReferencedType(D, dwarf::DW_AT_containing_type)) {
+ LLVM_QUICK_EXIT_NONE(appendQualifiedNameBefore(Inner()));
+ if (needsParens(InnerDIE)) {
+ LLVM_QUICK_EXIT_NONE(V("("));
+ } else if (Word) {
+ LLVM_QUICK_EXIT_NONE(V(" "));
+ } if (DieType Cont = detail::resolveReferencedType(D, dwarf::DW_AT_containing_type)) {
appendQualifiedName(Cont);
EndedWithTemplate = false;
- V("::");
+ LLVM_QUICK_EXIT_NONE(V("::"));
}
- V("*");
+ LLVM_QUICK_EXIT_NONE(V("*"));
Word = false;
break;
}
case dwarf::DW_TAG_LLVM_ptrauth_type:
- appendQualifiedNameBefore(Inner());
+ LLVM_QUICK_EXIT_NONE(appendQualifiedNameBefore(Inner()));
break;
case dwarf::DW_TAG_const_type:
case dwarf::DW_TAG_volatile_type:
- appendConstVolatileQualifierBefore(D);
+ LLVM_QUICK_EXIT_NONE(appendConstVolatileQualifierBefore(D));
break;
case dwarf::DW_TAG_namespace: {
- if (const char *Name = toString(D.find(dwarf::DW_AT_name), nullptr))
- V(Name);
- else
- V("(anonymous namespace)");
+ if (const char *Name = toString(D.find(dwarf::DW_AT_name), nullptr)) {
+ LLVM_QUICK_EXIT_NONE(V(Name));
+ } else {
+ LLVM_QUICK_EXIT_NONE(V("(anonymous namespace)"));
+ }
break;
}
case dwarf::DW_TAG_unspecified_type: {
@@ -267,7 +287,7 @@ DieType DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedNameBefore(
if (TypeName == "decltype(nullptr)")
TypeName = "std::nullptr_t";
Word = true;
- V(TypeName);
+ LLVM_QUICK_EXIT_NONE(V(TypeName));
EndedWithTemplate = false;
break;
}
@@ -280,7 +300,7 @@ DieType DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedNameBefore(
default: {
const char *NamePtr = toString(D.find(dwarf::DW_AT_name), nullptr);
if (!NamePtr) {
- appendTypeTagName(D.getTag());
+ LLVM_QUICK_EXIT_NONE(appendTypeTagName(D.getTag()));
return DieType();
}
Word = true;
@@ -296,13 +316,13 @@ DieType DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedNameBefore(
Name = BaseName;
} else
EndedWithTemplate = Name.ends_with(">");
- V(Name);
+ LLVM_QUICK_EXIT_NONE(V(Name));
// This check would be insufficient for operator overloads like
// "operator>>" - but for now Clang doesn't try to simplify them, so this
// is OK. Add more nuanced operator overload handling here if/when needed.
if (Name.ends_with(">"))
break;
- appendAndTerminateTemplateParameters(D);
+ LLVM_QUICK_EXIT_NONE(appendAndTerminateTemplateParameters(D));
break;
}
}
@@ -310,42 +330,46 @@ DieType DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedNameBefore(
}
template <typename DieType, typename Visitor>
-void DWARFTypePrinter<DieType, Visitor>::appendAndTerminateTemplateParameters(DieType D) {
- if (!appendTemplateParameters(D))
- return;
+bool DWARFTypePrinter<DieType, Visitor>::appendAndTerminateTemplateParameters(DieType D) {
+ std::optional<bool> R = appendTemplateParameters(D);
+ if (!R)
+ return false;
+ if (!*R)
+ return true;
if (EndedWithTemplate)
- V(" ");
- V(">");
+ LLVM_QUICK_EXIT(V(" "));
+ LLVM_QUICK_EXIT(V(">"));
EndedWithTemplate = true;
Word = true;
+ return true;
}
template <typename DieType, typename Visitor>
-void DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedNameAfter(
+bool DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedNameAfter(
DieType D, DieType Inner, bool SkipFirstParamIfArtificial) {
if (!D)
- return;
+ return true;
switch (D.getTag()) {
case dwarf::DW_TAG_subroutine_type: {
- appendSubroutineNameAfter(D, Inner, SkipFirstParamIfArtificial, false,
- false);
+ LLVM_QUICK_EXIT(appendSubroutineNameAfter(
+ D, Inner, SkipFirstParamIfArtificial, false, false));
break;
}
case dwarf::DW_TAG_array_type: {
- appendArrayType(D);
+ LLVM_QUICK_EXIT(appendArrayType(D));
break;
}
case dwarf::DW_TAG_const_type:
case dwarf::DW_TAG_volatile_type:
- appendConstVolatileQualifierAfter(D);
+ LLVM_QUICK_EXIT(appendConstVolatileQualifierAfter(D));
break;
case dwarf::DW_TAG_ptr_to_member_type:
case dwarf::DW_TAG_reference_type:
case dwarf::DW_TAG_rvalue_reference_type:
case dwarf::DW_TAG_pointer_type: {
if (needsParens(Inner))
- V(")");
+ LLVM_QUICK_EXIT(V(")"));
appendUnqualifiedNameAfter(Inner, detail::resolveReferencedType(Inner),
/*SkipFirstParamIfArtificial=*/D.getTag() ==
dwarf::DW_TAG_ptr_to_member_type);
@@ -392,7 +416,7 @@ void DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedNameAfter(
<< getValOrNull(dwarf::DW_AT_LLVM_ptrauth_address_discriminated) << ", 0x0"
<< utohexstr(getValOrNull(dwarf::DW_AT_LLVM_ptrauth_extra_discriminator), true)
<< options << ")";
- V(PtrauthStream.str());
+ LLVM_QUICK_EXIT(V(PtrauthStream.str()));
break;
}
/*
@@ -405,6 +429,7 @@ void DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedNameAfter(
default:
break;
}
+ return true;
}
namespace detail {
@@ -424,33 +449,37 @@ inline bool scopedTAGs(dwarf::Tag Tag) {
}
} // namespace detail
template <typename DieType, typename Visitor>
-void DWARFTypePrinter<DieType, Visitor>::appendQualifiedName(DieType D) {
+bool DWARFTypePrinter<DieType, Visitor>::appendQualifiedName(DieType D) {
if (D && detail::scopedTAGs(D.getTag()))
- appendScopes(D.getParent());
- appendUnqualifiedName(D);
+ LLVM_QUICK_EXIT(appendScopes(D.getParent()));
+ LLVM_QUICK_EXIT(appendUnqualifiedName(D));
+ return true;
}
template <typename DieType, typename Visitor>
-DieType DWARFTypePrinter<DieType, Visitor>::appendQualifiedNameBefore(DieType D) {
+std::optional<DieType> DWARFTypePrinter<DieType, Visitor>::appendQualifiedNameBefore(DieType D) {
if (D && detail::scopedTAGs(D.getTag()))
- appendScopes(D.getParent());
+ LLVM_QUICK_EXIT_NONE(appendScopes(D.getParent()));
return appendUnqualifiedNameBefore(D);
}
template <typename DieType, typename Visitor>
-bool DWARFTypePrinter<DieType, Visitor>::appendTemplateParameters(DieType D,
- bool *FirstParameter) {
+std::optional<bool>
+DWARFTypePrinter<DieType, Visitor>::appendTemplateParameters(
+ DieType D, bool *FirstParameter) {
bool FirstParameterValue = true;
bool IsTemplate = false;
if (!FirstParameter)
FirstParameter = &FirstParameterValue;
for (const DieType &C : D) {
auto Sep = [&] {
- if (*FirstParameter)
- V("<");
- else
- V(", ");
+ if (*FirstParameter) {
+ LLVM_QUICK_EXIT(V("<"));
+ } else {
+ LLVM_QUICK_EXIT(V(", "));
+ }
IsTemplate = true;
EndedWithTemplate = false;
*FirstParameter = false;
+ return true;
};
if (C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) {
IsTemplate = true;
@@ -458,13 +487,13 @@ bool DWARFTypePrinter<DieType, Visitor>::appendTemplateParameters(DieType D,
}
if (C.getTag() == dwarf::DW_TAG_template_value_parameter) {
DieType T = detail::resolveReferencedType(C);
- Sep();
+ LLVM_QUICK_EXIT_NONE(Sep());
if (T.getTag() == dwarf::DW_TAG_enumeration_type) {
- V("(");
+ LLVM_QUICK_EXIT_NONE(V("("));
appendQualifiedName(T);
- V(")");
+ LLVM_QUICK_EXIT_NONE(V(")"));
auto Value = C.find(dwarf::DW_AT_const_value);
- V(std::to_string(*Value->getAsSignedConstant()));
+ LLVM_QUICK_EXIT_NONE(V(std::to_string(*Value->getAsSignedConstant())));
continue;
}
// /Maybe/ we could do pointer type parameters, looking for the
@@ -478,30 +507,30 @@ bool DWARFTypePrinter<DieType, Visitor>::appendTemplateParameters(DieType D,
auto Value = C.find(dwarf::DW_AT_const_value);
bool IsQualifiedChar = false;
if (Name == "bool") {
- V((*Value->getAsUnsignedConstant() ? "true" : "false"));
+ LLVM_QUICK_EXIT_NONE(V((*Value->getAsUnsignedConstant() ? "true" : "false")));
} else if (Name == "short") {
- V("(short)");
- V(std::to_string(*Value->getAsSignedConstant()));
+ LLVM_QUICK_EXIT_NONE(V("(short)"));
+ LLVM_QUICK_EXIT_NONE(V(std::to_string(*Value->getAsSignedConstant())));
} else if (Name == "unsigned short") {
- V("(unsigned short)");
- V(std::to_string(*Value->getAsSignedConstant()));
- } else if (Name == "int")
- V(std::to_string(*Value->getAsSignedConstant()));
- else if (Name == "long") {
- V(std::to_string(*Value->getAsSignedConstant()));
- V("L");
+ LLVM_QUICK_EXIT_NONE(V("(unsigned short)"));
+ LLVM_QUICK_EXIT_NONE(V(std::to_string(*Value->getAsSignedConstant())));
+ } else if (Name == "int") {
+ LLVM_QUICK_EXIT_NONE(V(std::to_string(*Value->getAsSignedConstant())));
+ } else if (Name == "long") {
+ LLVM_QUICK_EXIT_NONE(V(std::to_string(*Value->getAsSignedConstant())));
+ LLVM_QUICK_EXIT_NONE(V("L"));
} else if (Name == "long long") {
- V(std::to_string(*Value->getAsSignedConstant()));
- V("LL");
+ LLVM_QUICK_EXIT_NONE(V(std::to_string(*Value->getAsSignedConstant())));
+ LLVM_QUICK_EXIT_NONE(V("LL"));
} else if (Name == "unsigned int") {
- V(std::to_string(*Value->getAsUnsignedConstant()));
- V("U");
+ LLVM_QUICK_EXIT_NONE(V(std::to_string(*Value->getAsUnsignedConstant())));
+ LLVM_QUICK_EXIT_NONE(V("U"));
} else if (Name == "unsigned long") {
- V(std::to_string(*Value->getAsUnsignedConstant()));
- V("UL");
+ LLVM_QUICK_EXIT_NONE(V(std::to_string(*Value->getAsUnsignedConstant())));
+ LLVM_QUICK_EXIT_NONE(V("UL"));
} else if (Name == "unsigned long long") {
- V(std::to_string(*Value->getAsUnsignedConstant()));
- V("ULL");
+ LLVM_QUICK_EXIT_NONE(V(std::to_string(*Value->getAsUnsignedConstant())));
+ LLVM_QUICK_EXIT_NONE(V("ULL"));
} else if (Name == "char" ||
(IsQualifiedChar =
(Name == "unsigned char" || Name == "signed char"))) {
@@ -513,52 +542,55 @@ bool DWARFTypePrinter<DieType, Visitor>::appendTemplateParameters(DieType D,
// handling's not done, and doesn't correctly test if a character is
// printable or needs to use a numeric escape sequence instead)
if (IsQualifiedChar) {
- V("(");
- V(Name);
- V(")");
+ LLVM_QUICK_EXIT_NONE(V("("));
+ LLVM_QUICK_EXIT_NONE(V(Name));
+ LLVM_QUICK_EXIT_NONE(V(")"));
}
switch (Val) {
case '\\':
- V("'\\\\'");
+ LLVM_QUICK_EXIT_NONE(V("'\\\\'"));
break;
case '\'':
- V("'\\''");
+ LLVM_QUICK_EXIT_NONE(V("'\\''"));
break;
case '\a':
// TODO: K&R: the meaning of '\\a' is different in traditional C
- V("'\\a'");
+ LLVM_QUICK_EXIT_NONE(V("'\\a'"));
break;
case '\b':
- V("'\\b'");
+ LLVM_QUICK_EXIT_NONE(V("'\\b'"));
break;
case '\f':
- V("'\\f'");
+ LLVM_QUICK_EXIT_NONE(V("'\\f'"));
break;
case '\n':
- V("'\\n'");
+ LLVM_QUICK_EXIT_NONE(V("'\\n'"));
break;
case '\r':
- V("'\\r'");
+ LLVM_QUICK_EXIT_NONE(V("'\\r'"));
break;
case '\t':
- V("'\\t'");
+ LLVM_QUICK_EXIT_NONE(V("'\\t'"));
break;
case '\v':
- V("'\\v'");
+ LLVM_QUICK_EXIT_NONE(V("'\\v'"));
break;
default:
if ((Val & ~0xFFu) == ~0xFFu)
Val &= 0xFFu;
if (Val < 127 && Val >= 32) {
- V("'");
- V(Twine((char)Val).str());
- V("'");
- } else if (Val < 256)
- V(detail::toString(llvm::format("'\\x%02" PRIx64 "'", Val)));
- else if (Val <= 0xFFFF)
- V(detail::toString(llvm::format("'\\u%04" PRIx64 "'", Val)));
- else
- V(detail::toString(llvm::format("'\\U%08" PRIx64 "'", Val)));
+ LLVM_QUICK_EXIT_NONE(V("'"));
+ LLVM_QUICK_EXIT_NONE(V(Twine((char)Val).str()));
+ LLVM_QUICK_EXIT_NONE(V("'"));
+ } else if (Val < 256) {
+ LLVM_QUICK_EXIT_NONE(V(detail::toString(llvm::format("'\\x%02" PRIx64 "'", Val))));
+ } else if (Val <= 0xFFFF) {
+ LLVM_QUICK_EXIT_NONE(
+ V(detail::toString(llvm::format("'\\u%04" PRIx64 "'", Val))));
+ } else {
+ LLVM_QUICK_EXIT_NONE(
+ V(detail::toString(llvm::format("'\\U%08" PRIx64 "'", Val))));
+ }
}
}
continue;
@@ -568,19 +600,19 @@ bool DWARFTypePrinter<DieType, Visitor>::appendTemplateParameters(DieType D,
toString(C.find(dwarf::DW_AT_GNU_template_name), nullptr);
assert(RawName);
StringRef Name = RawName;
- Sep();
- V(Name);
+ LLVM_QUICK_EXIT_NONE(Sep());
+ LLVM_QUICK_EXIT_NONE(V(Name));
continue;
}
if (C.getTag() != dwarf::DW_TAG_template_type_parameter)
continue;
auto TypeAttr = C.find(dwarf::DW_AT_type);
- Sep();
+ LLVM_QUICK_EXIT_NONE(Sep());
appendQualifiedName(TypeAttr ? detail::resolveReferencedType(C, *TypeAttr)
: DieType());
}
if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {
- V("<");
+ LLVM_QUICK_EXIT_NONE(V("<"));
EndedWithTemplate = false;
}
return IsTemplate;
@@ -602,19 +634,21 @@ void DWARFTypePrinter<DieType, Visitor>::decomposeConstVolatile(DieType &N, DieT
}
}
template <typename DieType, typename Visitor>
-void DWARFTypePrinter<DieType, Visitor>::appendConstVolatileQualifierAfter(DieType N) {
+bool DWARFTypePrinter<DieType, Visitor>::appendConstVolatileQualifierAfter(DieType N) {
DieType C;
DieType V;
DieType T;
decomposeConstVolatile(N, T, C, V);
- if (T && T.getTag() == dwarf::DW_TAG_subroutine_type)
- appendSubroutineNameAfter(T, detail::resolveReferencedType(T), false, C.isValid(),
- V.isValid());
- else
- appendUnqualifiedNameAfter(T, detail::resolveReferencedType(T));
+ if (T && T.getTag() == dwarf::DW_TAG_subroutine_type) {
+ LLVM_QUICK_EXIT(appendSubroutineNameAfter(T, detail::resolveReferencedType(T), false, C.isValid(),
+ V.isValid()));
+ } else {
+ LLVM_QUICK_EXIT(appendUnqualifiedNameAfter(T, detail::resolveReferencedType(T)));
+ }
+ return true;
}
template <typename DieType, typename Visitor>
-void DWARFTypePrinter<DieType, Visitor>::appendConstVolatileQualifierBefore(DieType N) {
+bool DWARFTypePrinter<DieType, Visitor>::appendConstVolatileQualifierBefore(DieType N) {
DieType C;
DieType Vol;
DieType T;
@@ -628,44 +662,52 @@ void DWARFTypePrinter<DieType, Visitor>::appendConstVolatileQualifierBefore(DieT
A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
!Subroutine;
if (Leading) {
- if (C)
- V("const ");
- if (Vol)
- V("volatile ");
+ if (C) {
+ LLVM_QUICK_EXIT(V("const "));
+ }
+ if (Vol) {
+ LLVM_QUICK_EXIT(V("volatile "));
+ }
}
appendQualifiedNameBefore(T);
if (!Leading && !Subroutine) {
Word = true;
- if (C)
- V("const");
+ if (C) {
+ LLVM_QUICK_EXIT(V("const"));
+ }
if (Vol) {
- if (C)
- V(" ");
- V("volatile");
+ if (C) {
+ LLVM_QUICK_EXIT(V(" "));
+ }
+ LLVM_QUICK_EXIT(V("volatile"));
}
}
+ return true;
}
template <typename DieType, typename Visitor>
-void DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedName(
+bool DWARFTypePrinter<DieType, Visitor>::appendUnqualifiedName(
DieType D, std::string *OriginalFullName) {
// FIXME: We should have pretty printers per language. Currently we print
// everything as if it was C++ and fall back to the TAG type name.
- DieType Inner = appendUnqualifiedNameBefore(D, OriginalFullName);
- appendUnqualifiedNameAfter(D, Inner);
+ std::optional<DieType> Inner =
+ appendUnqualifiedNameBefore(D, OriginalFullName);
+ LLVM_QUICK_EXIT(Inner);
+ LLVM_QUICK_EXIT(appendUnqualifiedNameAfter(D, *Inner));
+ return true;
}
template <typename DieType, typename Visitor>
-void DWARFTypePrinter<DieType, Visitor>::appendSubroutineNameAfter(
+bool DWARFTypePrinter<DieType, Visitor>::appendSubroutineNameAfter(
DieType D, DieType Inner, bool SkipFirstParamIfArtificial, bool Const,
bool Volatile) {
DieType FirstParamIfArtificial;
- V("(");
+ LLVM_QUICK_EXIT(V("("));
EndedWithTemplate = false;
bool First = true;
bool RealFirst = true;
for (DieType P : D) {
if (P.getTag() != dwarf::DW_TAG_formal_parameter &&
P.getTag() != dwarf::DW_TAG_unspecified_parameters)
- return;
+ return true;
DieType T = detail::resolveReferencedType(P);
if (SkipFirstParamIfArtificial && RealFirst && P.find(dwarf::DW_AT_artificial)) {
FirstParamIfArtificial = T;
@@ -673,16 +715,17 @@ void DWARFTypePrinter<DieType, Visitor>::appendSubroutineNameAfter(
continue;
}
if (!First) {
- V(", ");
+ LLVM_QUICK_EXIT(V(", "));
}
First = false;
- if (P.getTag() == dwarf::DW_TAG_unspecified_parameters)
- V("...");
- else
- appendQualifiedName(T);
+ if (P.getTag() == dwarf::DW_TAG_unspecified_parameters) {
+ LLVM_QUICK_EXIT(V("..."));
+ } else {
+ LLVM_QUICK_EXIT(appendQualifiedName(T));
+ }
}
EndedWithTemplate = false;
- V(")");
+ LLVM_QUICK_EXIT(V(")"));
if (FirstParamIfArtificial) {
if (DieType P = FirstParamIfArtificial) {
if (P.getTag() == dwarf::DW_TAG_pointer_type) {
@@ -704,35 +747,35 @@ void DWARFTypePrinter<DieType, Visitor>::appendSubroutineNameAfter(
if (auto CC = D.find(dwarf::DW_AT_calling_convention)) {
switch (*CC->getAsUnsignedConstant()) {
case dwarf::CallingConvention::DW_CC_BORLAND_stdcall:
- V(" __attribute__((stdcall))");
+ LLVM_QUICK_EXIT(V(" __attribute__((stdcall))"));
break;
case dwarf::CallingConvention::DW_CC_BORLAND_msfastcall:
- V(" __attribute__((fastcall))");
+ LLVM_QUICK_EXIT(V(" __attribute__((fastcall))"));
break;
case dwarf::CallingConvention::DW_CC_BORLAND_thiscall:
- V(" __attribute__((thiscall))");
+ LLVM_QUICK_EXIT(V(" __attribute__((thiscall))"));
break;
case dwarf::CallingConvention::DW_CC_LLVM_vectorcall:
- V(" __attribute__((vectorcall))");
+ LLVM_QUICK_EXIT(V(" __attribute__((vectorcall))"));
break;
case dwarf::CallingConvention::DW_CC_BORLAND_pascal:
- V(" __attribute__((pascal))");
+ LLVM_QUICK_EXIT(V(" __attribute__((pascal))"));
break;
case dwarf::CallingConvention::DW_CC_LLVM_Win64:
- V(" __attribute__((ms_abi))");
+ LLVM_QUICK_EXIT(V(" __attribute__((ms_abi))"));
break;
case dwarf::CallingConvention::DW_CC_LLVM_X86_64SysV:
- V(" __attribute__((sysv_abi))");
+ LLVM_QUICK_EXIT(V(" __attribute__((sysv_abi))"));
break;
case dwarf::CallingConvention::DW_CC_LLVM_AAPCS:
// AArch64VectorCall missing?
- V(" __attribute__((pcs(\"aapcs\")))");
+ LLVM_QUICK_EXIT(V(" __attribute__((pcs(\"aapcs\")))"));
break;
case dwarf::CallingConvention::DW_CC_LLVM_AAPCS_VFP:
- V(" __attribute__((pcs(\"aapcs-vfp\")))");
+ LLVM_QUICK_EXIT(V(" __attribute__((pcs(\"aapcs-vfp\")))"));
break;
case dwarf::CallingConvention::DW_CC_LLVM_IntelOclBicc:
- V(" __attribute__((intel_ocl_bicc))");
+ LLVM_QUICK_EXIT(V(" __attribute__((intel_ocl_bicc))"));
break;
case dwarf::CallingConvention::DW_CC_LLVM_SpirFunction:
case dwarf::CallingConvention::DW_CC_LLVM_OpenCLKernel:
@@ -744,55 +787,66 @@ void DWARFTypePrinter<DieType, Visitor>::appendSubroutineNameAfter(
break;
case dwarf::CallingConvention::DW_CC_LLVM_Swift:
// SwiftAsync missing
- V(" __attribute__((swiftcall))");
+ LLVM_QUICK_EXIT(V(" __attribute__((swiftcall))"));
break;
case dwarf::CallingConvention::DW_CC_LLVM_PreserveMost:
- V(" __attribute__((preserve_most))");
+ LLVM_QUICK_EXIT(V(" __attribute__((preserve_most))"));
break;
case dwarf::CallingConvention::DW_CC_LLVM_PreserveAll:
- V(" __attribute__((preserve_all))");
+ LLVM_QUICK_EXIT(V(" __attribute__((preserve_all))"));
break;
case dwarf::CallingConvention::DW_CC_LLVM_PreserveNone:
- V(" __attribute__((preserve_none))");
+ LLVM_QUICK_EXIT(V(" __attribute__((preserve_none))"));
break;
case dwarf::CallingConvention::DW_CC_LLVM_X86RegCall:
- V(" __attribute__((regcall))");
+ LLVM_QUICK_EXIT(V(" __attribute__((regcall))"));
break;
case dwarf::CallingConvention::DW_CC_LLVM_M68kRTD:
- V(" __attribute__((m68k_rtd))");
+ LLVM_QUICK_EXIT(V(" __attribute__((m68k_rtd))"));
break;
}
}
- if (Const)
- V(" const");
- if (Volatile)
- V(" volatile");
- if (D.find(dwarf::DW_AT_reference))
- V(" &");
- if (D.find(dwarf::DW_AT_rvalue_reference))
- V(" &&");
+ if (Const) {
+ LLVM_QUICK_EXIT(V(" const"));
+ }
+ if (Volatile) {
+ LLVM_QUICK_EXIT(V(" volatile"));
+ }
+ if (D.find(dwarf::DW_AT_reference)) {
+ LLVM_QUICK_EXIT(V(" &"));
+ }
+ if (D.find(dwarf::DW_AT_rvalue_reference)) {
+ LLVM_QUICK_EXIT(V(" &&"));
+ }
- appendUnqualifiedNameAfter(Inner, detail::resolveReferencedType(Inner));
+ LLVM_QUICK_EXIT(
+ appendUnqualifiedNameAfter(Inner, detail::resolveReferencedType(Inner)));
+ return true;
}
template <typename DieType, typename Visitor>
-void DWARFTypePrinter<DieType, Visitor>::appendScopes(DieType D) {
+bool DWARFTypePrinter<DieType, Visitor>::appendScopes(DieType D) {
if (D.getTag() == dwarf::DW_TAG_compile_unit)
- return;
+ return true;
if (D.getTag() == dwarf::DW_TAG_type_unit)
- return;
+ return true;
if (D.getTag() == dwarf::DW_TAG_skeleton_unit)
- return;
+ return true;
if (D.getTag() == dwarf::DW_TAG_subprogram)
- return;
+ return true;
if (D.getTag() == dwarf::DW_TAG_lexical_block)
- return;
+ return true;
//D = D.resolveTypeUnitReference();
- if (DieType P = D.getParent())
- appendScopes(P);
- appendUnqualifiedName(D);
- V("::");
+ if (DieType P = D.getParent()) {
+ LLVM_QUICK_EXIT(appendScopes(P));
+ }
+ LLVM_QUICK_EXIT(appendUnqualifiedName(D));
+ LLVM_QUICK_EXIT(V("::"));
+ return true;
}
} // namespace llvm
+#undef LLVM_QUICK_EXIT
+#undef LLVM_QUICK_EXIT_NONE
+
#endif // LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H
More information about the lldb-commits
mailing list