Skip to content

Commit d5927a6

Browse files
authored
[LLDB] Add unary plus and minus to DIL (#155617)
This patch adds unary nodes plus and minus, introduces unary type conversions, and adds integral promotion to the type system.
1 parent 83765f4 commit d5927a6

File tree

16 files changed

+427
-59
lines changed

16 files changed

+427
-59
lines changed

lldb/docs/dil-expr-lang.ebnf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ expression = unary_expression ;
88
unary_expression = postfix_expression
99
| unary_operator expression ;
1010
11-
unary_operator = "*" | "&" ;
11+
unary_operator = "*" | "&" | "+" | "-";
1212
1313
postfix_expression = primary_expression
1414
| postfix_expression "[" integer_literal "]"

lldb/include/lldb/Symbol/TypeSystem.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,18 @@ class TypeSystem : public PluginInterface,
411411
GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx,
412412
bool expand_pack);
413413

414+
// DIL
415+
416+
/// Checks if the type is eligible for integral promotion.
417+
virtual bool IsPromotableIntegerType(lldb::opaque_compiler_type_t type);
418+
419+
/// Perform integral promotion on a given type.
420+
/// This promotes eligible types (boolean, integers, unscoped enumerations)
421+
/// to a larger integer type according to type system rules.
422+
/// \returns Promoted type.
423+
virtual llvm::Expected<CompilerType>
424+
DoIntegralPromotion(CompilerType from, ExecutionContextScope *exe_scope);
425+
414426
// Dumping types
415427

416428
#ifndef NDEBUG

lldb/include/lldb/ValueObject/DILAST.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ enum class NodeKind {
3333
enum class UnaryOpKind {
3434
AddrOf, // "&"
3535
Deref, // "*"
36+
Minus, // "-"
37+
Plus, // "+"
3638
};
3739

3840
/// Forward declaration, for use in DIL AST nodes. Definition is at the very

lldb/include/lldb/ValueObject/DILEval.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ class Interpreter : Visitor {
6161
llvm::Expected<lldb::ValueObjectSP>
6262
Visit(const BooleanLiteralNode *node) override;
6363

64+
/// Perform usual unary conversions on a value. At the moment this
65+
/// includes array-to-pointer and integral promotion for eligible types.
66+
llvm::Expected<lldb::ValueObjectSP>
67+
UnaryConversion(lldb::ValueObjectSP valobj, uint32_t location);
6468
llvm::Expected<CompilerType>
6569
PickIntegerType(lldb::TypeSystemSP type_system,
6670
std::shared_ptr<ExecutionContextScope> ctx,

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7346,6 +7346,102 @@ CompilerType TypeSystemClang::GetTypeForFormatters(void *type) {
73467346
return CompilerType();
73477347
}
73487348

7349+
bool TypeSystemClang::IsPromotableIntegerType(
7350+
lldb::opaque_compiler_type_t type) {
7351+
// Unscoped enums are always considered as promotable, even if their
7352+
// underlying type does not need to be promoted (e.g. "int").
7353+
bool is_signed = false;
7354+
bool isUnscopedEnumerationType =
7355+
IsEnumerationType(type, is_signed) && !IsScopedEnumerationType(type);
7356+
if (isUnscopedEnumerationType)
7357+
return true;
7358+
7359+
switch (GetBasicTypeEnumeration(type)) {
7360+
case lldb::eBasicTypeBool:
7361+
case lldb::eBasicTypeChar:
7362+
case lldb::eBasicTypeSignedChar:
7363+
case lldb::eBasicTypeUnsignedChar:
7364+
case lldb::eBasicTypeShort:
7365+
case lldb::eBasicTypeUnsignedShort:
7366+
case lldb::eBasicTypeWChar:
7367+
case lldb::eBasicTypeSignedWChar:
7368+
case lldb::eBasicTypeUnsignedWChar:
7369+
case lldb::eBasicTypeChar16:
7370+
case lldb::eBasicTypeChar32:
7371+
return true;
7372+
7373+
default:
7374+
return false;
7375+
}
7376+
7377+
llvm_unreachable("All cases handled above.");
7378+
}
7379+
7380+
llvm::Expected<CompilerType>
7381+
TypeSystemClang::DoIntegralPromotion(CompilerType from,
7382+
ExecutionContextScope *exe_scope) {
7383+
if (!from.IsInteger() && !from.IsUnscopedEnumerationType())
7384+
return from;
7385+
7386+
if (!from.IsPromotableIntegerType())
7387+
return from;
7388+
7389+
if (from.IsUnscopedEnumerationType()) {
7390+
EnumDecl *enum_decl = GetAsEnumDecl(from);
7391+
CompilerType promotion_type = GetType(enum_decl->getPromotionType());
7392+
return DoIntegralPromotion(promotion_type, exe_scope);
7393+
}
7394+
7395+
lldb::BasicType builtin_type =
7396+
from.GetCanonicalType().GetBasicTypeEnumeration();
7397+
uint64_t from_size = 0;
7398+
if (builtin_type == lldb::eBasicTypeWChar ||
7399+
builtin_type == lldb::eBasicTypeSignedWChar ||
7400+
builtin_type == lldb::eBasicTypeUnsignedWChar ||
7401+
builtin_type == lldb::eBasicTypeChar16 ||
7402+
builtin_type == lldb::eBasicTypeChar32) {
7403+
// Find the type that can hold the entire range of values for our type.
7404+
bool is_signed = from.IsSigned();
7405+
llvm::Expected<uint64_t> from_size = from.GetByteSize(exe_scope);
7406+
if (!from_size)
7407+
return from_size.takeError();
7408+
CompilerType promote_types[] = {
7409+
GetBasicTypeFromAST(lldb::eBasicTypeInt),
7410+
GetBasicTypeFromAST(lldb::eBasicTypeUnsignedInt),
7411+
GetBasicTypeFromAST(lldb::eBasicTypeLong),
7412+
GetBasicTypeFromAST(lldb::eBasicTypeUnsignedLong),
7413+
GetBasicTypeFromAST(lldb::eBasicTypeLongLong),
7414+
GetBasicTypeFromAST(lldb::eBasicTypeUnsignedLongLong),
7415+
};
7416+
for (CompilerType &type : promote_types) {
7417+
llvm::Expected<uint64_t> byte_size = type.GetByteSize(exe_scope);
7418+
if (!byte_size)
7419+
return byte_size.takeError();
7420+
if (*from_size < *byte_size ||
7421+
(*from_size == *byte_size && is_signed == type.IsSigned())) {
7422+
return type;
7423+
}
7424+
}
7425+
llvm_unreachable("char type should fit into long long");
7426+
}
7427+
7428+
// Here we can promote only to "int" or "unsigned int".
7429+
CompilerType int_type = GetBasicTypeFromAST(lldb::eBasicTypeInt);
7430+
llvm::Expected<uint64_t> int_byte_size = int_type.GetByteSize(exe_scope);
7431+
if (!int_byte_size)
7432+
return int_byte_size.takeError();
7433+
7434+
// Signed integer types can be safely promoted to "int".
7435+
if (from.IsSigned()) {
7436+
return int_type;
7437+
}
7438+
// Unsigned integer types are promoted to "unsigned int" if "int" cannot hold
7439+
// their entire value range.
7440+
return (from_size == *int_byte_size)
7441+
? GetBasicTypeFromAST(lldb::eBasicTypeUnsignedInt)
7442+
: int_type;
7443+
}
7444+
73497445
clang::EnumDecl *TypeSystemClang::GetAsEnumDecl(const CompilerType &type) {
73507446
const clang::EnumType *enutype =
73517447
llvm::dyn_cast<clang::EnumType>(ClangUtil::GetCanonicalQualType(type));

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,14 @@ class TypeSystemClang : public TypeSystem {
938938

939939
CompilerType GetTypeForFormatters(void *type) override;
940940

941+
// DIL
942+
943+
bool IsPromotableIntegerType(lldb::opaque_compiler_type_t type) override;
944+
945+
llvm::Expected<CompilerType>
946+
DoIntegralPromotion(CompilerType from,
947+
ExecutionContextScope *exe_scope) override;
948+
941949
#define LLDB_INVALID_DECL_LEVEL UINT32_MAX
942950
// LLDB_INVALID_DECL_LEVEL is returned by CountDeclLevels if child_decl_ctx
943951
// could not be found in decl_ctx.

lldb/source/Symbol/CompilerType.cpp

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -370,30 +370,10 @@ bool CompilerType::IsScalarOrUnscopedEnumerationType() const {
370370
}
371371

372372
bool CompilerType::IsPromotableIntegerType() const {
373-
// Unscoped enums are always considered as promotable, even if their
374-
// underlying type does not need to be promoted (e.g. "int").
375-
if (IsUnscopedEnumerationType())
376-
return true;
377-
378-
switch (GetBasicTypeEnumeration()) {
379-
case lldb::eBasicTypeBool:
380-
case lldb::eBasicTypeChar:
381-
case lldb::eBasicTypeSignedChar:
382-
case lldb::eBasicTypeUnsignedChar:
383-
case lldb::eBasicTypeShort:
384-
case lldb::eBasicTypeUnsignedShort:
385-
case lldb::eBasicTypeWChar:
386-
case lldb::eBasicTypeSignedWChar:
387-
case lldb::eBasicTypeUnsignedWChar:
388-
case lldb::eBasicTypeChar16:
389-
case lldb::eBasicTypeChar32:
390-
return true;
391-
392-
default:
393-
return false;
394-
}
395-
396-
llvm_unreachable("All cases handled above.");
373+
if (IsValid())
374+
if (auto type_system_sp = GetTypeSystem())
375+
return type_system_sp->IsPromotableIntegerType(m_type);
376+
return false;
397377
}
398378

399379
bool CompilerType::IsPointerToVoid() const {

lldb/source/Symbol/TypeSystem.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,17 @@ CompilerType TypeSystem::GetTypeForFormatters(void *type) {
123123
return CompilerType(weak_from_this(), type);
124124
}
125125

126+
bool TypeSystem::IsPromotableIntegerType(lldb::opaque_compiler_type_t type) {
127+
return false;
128+
}
129+
130+
llvm::Expected<CompilerType>
131+
TypeSystem::DoIntegralPromotion(CompilerType from,
132+
ExecutionContextScope *exe_scope) {
133+
return llvm::createStringError(
134+
"Integral promotion is not implemented for this TypeSystem");
135+
}
136+
126137
bool TypeSystem::IsTemplateType(lldb::opaque_compiler_type_t type) {
127138
return false;
128139
}

0 commit comments

Comments
 (0)