-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[LLDB] Add type casting to DIL. #159500
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[LLDB] Add type casting to DIL. #159500
Changes from 2 commits
bbacb82
667b8ea
1646670
02e9571
fd3f8f5
77e940c
d13cda6
c2bc4f0
db42209
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ | |
#define LLDB_VALUEOBJECT_DILPARSER_H | ||
|
||
#include "lldb/Target/ExecutionContextScope.h" | ||
#include "lldb/Target/StackFrame.h" | ||
#include "lldb/Utility/DiagnosticsRendering.h" | ||
#include "lldb/Utility/Status.h" | ||
#include "lldb/ValueObject/DILAST.h" | ||
|
@@ -31,6 +32,9 @@ enum class ErrorCode : unsigned char { | |
kUnknown, | ||
}; | ||
|
||
llvm::Expected<lldb::TypeSystemSP> | ||
DILGetTypeSystemFromCU(std::shared_ptr<StackFrame> ctx); | ||
|
||
|
||
// The following is modeled on class OptionParseError. | ||
class DILDiagnosticError | ||
: public llvm::ErrorInfo<DILDiagnosticError, DiagnosticError> { | ||
|
@@ -55,6 +59,61 @@ class DILDiagnosticError | |
|
||
std::string message() const override { return m_detail.rendered; } | ||
}; | ||
/// TypeDeclaration builds information about the literal type definition as | ||
/// type is being parsed. It doesn't perform semantic analysis for non-basic | ||
/// types -- e.g. "char&&&" is a valid type declaration. | ||
/// NOTE: CV qualifiers are ignored. | ||
class TypeDeclaration { | ||
public: | ||
enum class TypeSpecifier { | ||
kBool, | ||
kChar, | ||
kDouble, | ||
kFloat, | ||
kInt, | ||
kLong, | ||
kLongDouble, | ||
kLongLong, | ||
kShort, | ||
kUnknown, | ||
kVoid, | ||
}; | ||
|
||
enum class SignSpecifier { | ||
kUnknown, | ||
kSigned, | ||
kUnsigned, | ||
}; | ||
|
||
bool IsEmpty() const { return !m_is_builtin && !m_is_user_type; } | ||
|
||
lldb::BasicType GetBasicType() const; | ||
|
||
public: | ||
// Indicates user-defined typename (e.g. "MyClass", "MyTmpl<int>"). | ||
std::string m_user_typename; | ||
|
||
// Basic type specifier ("void", "char", "intr", "float", "long long", etc.). | ||
TypeSpecifier m_type_specifier = TypeSpecifier::kUnknown; | ||
|
||
// Signedness specifier ("signed", "unsigned"). | ||
SignSpecifier m_sign_specifier = SignSpecifier::kUnknown; | ||
|
||
// Does the type declaration includes "int" specifier? | ||
// This is different than `type_specifier_` and is used to detect "int" | ||
// duplication for types that can be combined with "int" specifier (e.g. | ||
// "short int", "long int"). | ||
bool m_has_int_specifier = false; | ||
|
||
// Indicates whether there was an error during parsing. | ||
bool m_has_error = false; | ||
|
||
// Indicates whether this declaration describes a builtin type. | ||
bool m_is_builtin = false; | ||
|
||
// Indicates whether this declaration describes a user type. | ||
bool m_is_user_type = false; | ||
}; // class TypeDeclaration | ||
|
||
/// Pure recursive descent parser for C++ like expressions. | ||
/// EBNF grammar for the parser is described in lldb/docs/dil-expr-lang.ebnf | ||
|
@@ -101,6 +160,16 @@ class DILParser { | |
ASTNodeUP ParseFloatingPointLiteral(); | ||
ASTNodeUP ParseBooleanLiteral(); | ||
|
||
ASTNodeUP ParseCastExpression(); | ||
std::optional<CompilerType> ParseTypeId(bool must_be_type_id = false); | ||
void ParseTypeSpecifierSeq(TypeDeclaration *type_decl); | ||
bool ParseTypeSpecifier(TypeDeclaration *type_decl); | ||
std::string ParseTypeName(); | ||
CompilerType ResolveTypeDeclarators(CompilerType type, | ||
const std::vector<Token> &ptr_operators); | ||
bool IsSimpleTypeSpecifierKeyword(Token token) const; | ||
bool HandleSimpleTypeSpecifier(TypeDeclaration *type_decl); | ||
|
||
void BailOut(const std::string &error, uint32_t loc, uint16_t err_len); | ||
|
||
void Expect(Token::Kind kind); | ||
|
@@ -135,4 +204,66 @@ class DILParser { | |
|
||
} // namespace lldb_private::dil | ||
|
||
namespace llvm { | ||
template <> | ||
struct format_provider<lldb_private::dil::TypeDeclaration::TypeSpecifier> { | ||
static void format(const lldb_private::dil::TypeDeclaration::TypeSpecifier &t, | ||
raw_ostream &OS, llvm::StringRef Options) { | ||
switch (t) { | ||
case lldb_private::dil::TypeDeclaration::TypeSpecifier::kVoid: | ||
OS << "void"; | ||
break; | ||
case lldb_private::dil::TypeDeclaration::TypeSpecifier::kBool: | ||
OS << "bool"; | ||
break; | ||
case lldb_private::dil::TypeDeclaration::TypeSpecifier::kChar: | ||
OS << "char"; | ||
break; | ||
case lldb_private::dil::TypeDeclaration::TypeSpecifier::kInt: | ||
OS << "int"; | ||
break; | ||
case lldb_private::dil::TypeDeclaration::TypeSpecifier::kFloat: | ||
OS << "float"; | ||
break; | ||
case lldb_private::dil::TypeDeclaration::TypeSpecifier::kShort: | ||
OS << "short"; | ||
break; | ||
case lldb_private::dil::TypeDeclaration::TypeSpecifier::kLong: | ||
OS << "long"; | ||
break; | ||
case lldb_private::dil::TypeDeclaration::TypeSpecifier::kLongLong: | ||
OS << "long long"; | ||
break; | ||
case lldb_private::dil::TypeDeclaration::TypeSpecifier::kDouble: | ||
OS << "double"; | ||
break; | ||
case lldb_private::dil::TypeDeclaration::TypeSpecifier::kLongDouble: | ||
OS << "long double"; | ||
break; | ||
default: | ||
OS << "invalid type specifier"; | ||
break; | ||
} | ||
} | ||
}; | ||
|
||
template <> | ||
struct format_provider<lldb_private::dil::TypeDeclaration::SignSpecifier> { | ||
static void format(const lldb_private::dil::TypeDeclaration::SignSpecifier &t, | ||
raw_ostream &OS, llvm::StringRef Options) { | ||
switch (t) { | ||
case lldb_private::dil::TypeDeclaration::SignSpecifier::kSigned: | ||
OS << "signed"; | ||
break; | ||
case lldb_private::dil::TypeDeclaration::SignSpecifier::kUnsigned: | ||
OS << "unsigned"; | ||
break; | ||
default: | ||
OS << "invalid sign specifier"; | ||
break; | ||
} | ||
} | ||
}; | ||
} // namespace llvm | ||
|
||
#endif // LLDB_VALUEOBJECT_DILPARSER_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I have a problem with hardcoding C type names in the grammar itself. I believe this should be an identifier and it should be up to TypeSystem to recognize these. Is that feasible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is in fact the way the (updated) implementation works: Just expecting identifiers and using calls to LLDB's type system to determine if the name is for a builtin type or not. I just forgot to update the grammar here when I changed the implementation to work that way. I will update the grammar (thanks for catching this).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See DILParser::ParseBuiltinType, around line 396 of DILParser.cpp