[Lldb-commits] [lldb] [LLDB] Add `ScalarLiteralNode` and literal parsing in DIL (PR #152308)
Pavel Labath via lldb-commits
lldb-commits at lists.llvm.org
Fri Aug 15 02:40:46 PDT 2025
================
@@ -402,4 +404,122 @@ Interpreter::Visit(const BitFieldExtractionNode *node) {
return child_valobj_sp;
}
+static lldb::TypeSystemSP GetTypeSystemFromCU(std::shared_ptr<StackFrame> ctx) {
+ SymbolContext symbol_context =
+ ctx->GetSymbolContext(lldb::eSymbolContextCompUnit);
+ lldb::LanguageType language = symbol_context.comp_unit->GetLanguage();
+
+ symbol_context = ctx->GetSymbolContext(lldb::eSymbolContextModule);
+ llvm::Expected<lldb::TypeSystemSP> type_system =
+ symbol_context.module_sp->GetTypeSystemForLanguage(language);
+
+ if (type_system)
+ return *type_system;
+
+ return lldb::TypeSystemSP();
+}
+
+static CompilerType GetBasicType(lldb::TypeSystemSP type_system,
+ lldb::BasicType basic_type) {
+ if (type_system)
+ if (auto compiler_type = type_system.get()->GetBasicTypeFromAST(basic_type))
+ return compiler_type;
+
+ CompilerType empty_type;
+ return empty_type;
+}
+
+llvm::Expected<CompilerType>
+Interpreter::PickIntegerType(lldb::TypeSystemSP type_system,
+ std::shared_ptr<ExecutionContextScope> ctx,
+ const IntegerLiteralNode *literal) {
+ // Binary, Octal, Hexadecimal and literals with a U suffix are allowed to be
+ // an unsigned integer.
+ bool unsigned_is_allowed = literal->IsUnsigned() || literal->GetRadix() != 10;
+
+ // Try int/unsigned int.
+ uint64_t int_byte_size = 0;
+ if (auto temp =
+ GetBasicType(type_system, lldb::eBasicTypeInt).GetByteSize(ctx.get()))
+ int_byte_size = *temp;
+ unsigned int_size = int_byte_size * CHAR_BIT;
+ llvm::APInt apint = literal->GetValue();
+ if (!literal->IsLong() && !literal->IsLongLong() && apint.isIntN(int_size)) {
+ if (!literal->IsUnsigned() && apint.isIntN(int_size - 1))
+ return GetBasicType(type_system, lldb::eBasicTypeInt);
+ if (unsigned_is_allowed)
+ return GetBasicType(type_system, lldb::eBasicTypeUnsignedInt);
+ }
+ // Try long/unsigned long.
+ uint64_t long_byte_size = 0;
+ if (auto temp = GetBasicType(type_system, lldb::eBasicTypeLong)
+ .GetByteSize(ctx.get()))
+ long_byte_size = *temp;
+ unsigned long_size = long_byte_size * CHAR_BIT;
+ if (!literal->IsLongLong() && apint.isIntN(long_size)) {
+ if (!literal->IsUnsigned() && apint.isIntN(long_size - 1))
+ return GetBasicType(type_system, lldb::eBasicTypeLong);
+ if (unsigned_is_allowed)
+ return GetBasicType(type_system, lldb::eBasicTypeUnsignedLong);
+ }
+ // Try long long/unsigned long long.
+ uint64_t long_long_byte_size = 0;
+ if (auto temp = GetBasicType(type_system, lldb::eBasicTypeLongLong)
+ .GetByteSize(ctx.get()))
+ long_long_byte_size = *temp;
+ unsigned long_long_size = long_long_byte_size * CHAR_BIT;
+ if (apint.isIntN(long_long_size)) {
+ if (!literal->IsUnsigned() && apint.isIntN(long_long_size - 1))
+ return GetBasicType(type_system, lldb::eBasicTypeLongLong);
+ // If we still couldn't decide a type, we probably have something that
+ // does not fit in a signed long long, but has no U suffix. Also known as:
+ //
+ // warning: integer literal is too large to be represented in a signed
+ // integer type, interpreting as unsigned [-Wimplicitly-unsigned-literal]
+ //
+ return GetBasicType(type_system, lldb::eBasicTypeUnsignedLongLong);
----------------
labath wrote:
I'm afraid I don't see the difference, and I've spent a lot of time looking at this function.
Here's my attempt at an equivalent version. I think it should be equivalent, but if it's not, then maybe that means we should make the differences more prominent.
```
SmallVector<std::pair<BasicType, BasicType>, 3> candidates;
if (literal->GetTypeSuffix() <= IntegerTypeSuffix::None)
candidates.emplace_back(eBasicTypeInt, unsigned_is_allowed ? eBasicTypeUInt : eBasicTypeInvalid);
if (literal->GetTypeSuffix() <= IntegerTypeSuffix::Long)
candidates.emplace_back(eBasicTypeLong, unsigned_is_allowed ? eBasicTypeULong : eBasicTypeInvalid);
candidates.emplace_back(eBasicTypeLongLong, eBasicTypeULLong);
for (auto [signed_, unsigned_] : candidates) {
CompilerType signed_type = type_system->GetBasicTypeFromAST(signed_);
if (!signed_type)
continue;
llvm::Expected<uint64_t> size = signed_type.GetBitSize(ctx.get());
if (!size) return size.takeError();
if (!literal.IsUnsigned() && apint.isIntN(*size-1))
return signed_type;
if (unsigned_ != eBasicTypeInvalid && apint.isIntN(*size))
return type_system->GetBasicTypeFromAST(unsigned_)
}
return llvm::make_error(...);
```
A small difference is that this continues if it can't find (e.g.) the int type. I think this is fine -- if somehow we do end up with a type system that does not have an int type, then it makes sense to try the next larger one.
https://github.com/llvm/llvm-project/pull/152308
More information about the lldb-commits
mailing list