Skip to content

Commit a7fe34b

Browse files
committed
[lldb/SwiftUserExpression] Simplify ScanContext logic
- Remove redundant null checks - Add missing logging information - Avoid re-computing the type of self and its type flags
1 parent ceacb48 commit a7fe34b

File tree

2 files changed

+128
-124
lines changed

2 files changed

+128
-124
lines changed

lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.cpp

Lines changed: 127 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -94,177 +94,181 @@ static CompilerType GetConcreteType(ExecutionContext &exe_ctx,
9494
return type;
9595
}
9696

97+
/// Determine whether we have a Swift language symbol context. This handles
98+
/// some special cases, such as when the expression language is unknown, or
99+
/// when we have to guess from a mangled name.
100+
static bool isSwiftLanguageSymbolContext(const SwiftUserExpression &expr,
101+
const SymbolContext &sym_ctx) {
102+
if (sym_ctx.comp_unit && (expr.Language() == lldb::eLanguageTypeUnknown ||
103+
expr.Language() == lldb::eLanguageTypeSwift)) {
104+
if (sym_ctx.comp_unit->GetLanguage() == lldb::eLanguageTypeSwift ||
105+
sym_ctx.comp_unit->GetLanguage() == lldb::eLanguageTypePLI)
106+
return true;
107+
} else if (sym_ctx.symbol && expr.Language() == lldb::eLanguageTypeUnknown) {
108+
if (sym_ctx.symbol->GetMangled().GuessLanguage() ==
109+
lldb::eLanguageTypeSwift)
110+
return true;
111+
}
112+
return false;
113+
}
114+
115+
/// Information about `self` in a frame.
116+
struct SwiftSelfInfo {
117+
/// Whether `self` is a metatype (i.e. whether we're in a static method).
118+
bool is_metatype = false;
119+
120+
/// Adjusted type of `self`. If we're in a static method, this is an instance
121+
/// type.
122+
CompilerType type = {};
123+
124+
/// Underlying Swift type for the adjusted type of `self`.
125+
swift::TypeBase *swift_type = nullptr;
126+
127+
/// Type flags for the adjusted type of `self`.
128+
Flags type_flags = {};
129+
};
130+
131+
/// Find information about `self` in the frame.
132+
static llvm::Optional<SwiftSelfInfo>
133+
findSwiftSelf(StackFrame &frame, lldb::VariableSP self_var_sp) {
134+
SwiftSelfInfo info;
135+
136+
lldb::ValueObjectSP valobj_sp = frame.GetValueObjectForFrameVariable(
137+
self_var_sp, lldb::eDynamicDontRunTarget);
138+
139+
// 1) Try finding the type of `self` from its ValueObject.
140+
if (valobj_sp && valobj_sp->GetError().Success())
141+
info.type = valobj_sp->GetCompilerType();
142+
143+
// 2) If (1) fails, try finding the type of `self` from its Variable.
144+
if (!info.type.IsValid())
145+
if (Type *self_lldb_type = self_var_sp->GetType())
146+
info.type = self_var_sp->GetType()->GetForwardCompilerType();
147+
148+
// 3) If (1) and (2) fail, give up.
149+
if (!info.type.IsValid())
150+
return llvm::None;
151+
152+
// 4) If `self` is a metatype, get its instance type.
153+
if (Flags(info.type.GetTypeInfo())
154+
.AllSet(lldb::eTypeIsSwift | lldb::eTypeIsMetatype)) {
155+
info.type = TypeSystemSwift::GetInstanceType(info.type);
156+
info.is_metatype = true;
157+
}
158+
159+
// 5) If the adjusted type isn't equal to the type according to the runtime,
160+
// switch it to the latter type.
161+
info.swift_type = GetSwiftType(info.type).getPointer();
162+
if (info.swift_type && (info.swift_type != info.type.GetOpaqueQualType()))
163+
info.type = ToCompilerType(info.swift_type);
164+
165+
info.type_flags = Flags(info.type.GetTypeInfo());
166+
167+
if (!info.type.IsValid())
168+
return llvm::None;
169+
return info;
170+
}
171+
97172
void SwiftUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
98173
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
99-
100-
if (log)
101-
log->Printf("SwiftUserExpression::ScanContext()");
174+
LLDB_LOG(log, "SwiftUserExpression::ScanContext()");
102175

103176
m_target = exe_ctx.GetTargetPtr();
104-
105177
if (!m_target) {
106-
if (log)
107-
log->Printf(" [SUE::SC] Null target");
178+
LLDB_LOG(log, " [SUE::SC] Null target");
108179
return;
109180
}
110181

111182
StackFrame *frame = exe_ctx.GetFramePtr();
112183
if (!frame) {
113-
if (log)
114-
log->Printf(" [SUE::SC] Null stack frame");
184+
LLDB_LOG(log, " [SUE::SC] Null stack frame");
115185
return;
116186
}
117187

118188
SymbolContext sym_ctx = frame->GetSymbolContext(
119189
lldb::eSymbolContextFunction | lldb::eSymbolContextBlock |
120190
lldb::eSymbolContextCompUnit | lldb::eSymbolContextSymbol);
121-
122-
// This stage of the scan is only for Swift, but when we are going
123-
// to do Swift evaluation we need to do this scan.
124-
// So be sure to cover both cases:
125-
// 1) When the language is eLanguageTypeUnknown, to determine if this IS Swift
126-
// 2) When the language is explicitly set to eLanguageTypeSwift.
127-
bool frame_is_swift = false;
128-
129-
if (sym_ctx.comp_unit && (m_language == lldb::eLanguageTypeUnknown ||
130-
m_language == lldb::eLanguageTypeSwift)) {
131-
if (sym_ctx.comp_unit->GetLanguage() == lldb::eLanguageTypeSwift ||
132-
sym_ctx.comp_unit->GetLanguage() == lldb::eLanguageTypePLI)
133-
frame_is_swift = true;
134-
} else if (sym_ctx.symbol && m_language == lldb::eLanguageTypeUnknown) {
135-
if (sym_ctx.symbol->GetMangled().GuessLanguage() ==
136-
lldb::eLanguageTypeSwift)
137-
frame_is_swift = true;
191+
bool frame_is_swift = isSwiftLanguageSymbolContext(*this, sym_ctx);
192+
if (!frame_is_swift) {
193+
LLDB_LOG(log, " [SUE::SC] Frame is not swift-y");
194+
return;
138195
}
139196

140-
if (!frame_is_swift)
197+
// Make sure the target's SwiftASTContext has been setup before doing any
198+
// Swift name lookups.
199+
auto swift_ast_ctx = m_target->GetScratchSwiftASTContext(err, *frame);
200+
if (!swift_ast_ctx) {
201+
LLDB_LOG(log, " [SUE::SC] NULL Swift AST Context");
141202
return;
203+
}
142204

143-
m_is_class = false;
144-
m_needs_object_ptr = false;
145-
146-
// Make sure the target's SwiftASTContext has been setup before
147-
// doing any Swift name lookups.
148-
if (m_target) {
149-
auto swift_ast_ctx = m_target->GetScratchSwiftASTContext(err, *frame);
150-
if (!swift_ast_ctx) {
151-
if (log)
152-
log->Printf(" [SUE::SC] NULL Swift AST Context");
153-
return;
154-
}
155-
156-
if (!swift_ast_ctx->GetClangImporter()) {
157-
if (log)
158-
log->Printf(" [SUE::SC] Swift AST Context has no Clang importer");
159-
return;
160-
}
205+
if (!swift_ast_ctx->GetClangImporter()) {
206+
LLDB_LOG(log, " [SUE::SC] Swift AST Context has no Clang importer");
207+
return;
208+
}
161209

162-
if (swift_ast_ctx->HasFatalErrors()) {
163-
if (log)
164-
log->Printf(" [SUE::SC] Swift AST Context has fatal errors");
165-
return;
166-
}
210+
if (swift_ast_ctx->HasFatalErrors()) {
211+
LLDB_LOG(log, " [SUE::SC] Swift AST Context has fatal errors");
212+
return;
167213
}
168214

169-
if (log)
170-
log->Printf(" [SUE::SC] Compilation unit is swift");
215+
LLDB_LOG(log, " [SUE::SC] Compilation unit is swift");
171216

172217
Block *function_block = sym_ctx.GetFunctionBlock();
173-
if (!function_block)
218+
if (!function_block) {
219+
LLDB_LOG(log, " [SUE::SC] No function block");
174220
return;
221+
}
175222

176223
lldb::VariableListSP variable_list_sp(
177224
function_block->GetBlockVariableList(true));
178-
179-
if (!variable_list_sp)
225+
if (!variable_list_sp) {
226+
LLDB_LOG(log, " [SUE::SC] No block variable list");
180227
return;
228+
}
181229

182230
lldb::VariableSP self_var_sp(
183231
variable_list_sp->FindVariable(ConstString("self")));
184-
185-
if (!self_var_sp || !SwiftLanguageRuntime::IsSelf(*self_var_sp))
232+
if (!self_var_sp || !SwiftLanguageRuntime::IsSelf(*self_var_sp)) {
233+
LLDB_LOG(log, " [SUE::SC] No valid `self` variable");
186234
return;
187-
188-
CompilerType self_type;
189-
if (lldb::StackFrameSP stack_frame_sp = exe_ctx.GetFrameSP()) {
190-
// If we have a self variable, but it has no location at
191-
// the current PC, then we can't use it. Set the self var
192-
// back to empty and we'll just pretend we are in a
193-
// regular frame, which is really the best we can do.
194-
if (!self_var_sp->LocationIsValidForFrame(stack_frame_sp.get()))
195-
return;
196-
197-
lldb::ValueObjectSP valobj_sp =
198-
stack_frame_sp->GetValueObjectForFrameVariable(
199-
self_var_sp, lldb::eDynamicDontRunTarget);
200-
201-
if (valobj_sp && valobj_sp->GetError().Success())
202-
self_type = valobj_sp->GetCompilerType();
203235
}
204236

205-
if (!self_type.IsValid()) {
206-
Type *self_lldb_type = self_var_sp->GetType();
207-
208-
if (self_lldb_type)
209-
self_type = self_var_sp->GetType()->GetForwardCompilerType();
237+
// If we have a self variable, but it has no location at the current PC, then
238+
// we can't use it. Set the self var back to empty and we'll just pretend we
239+
// are in a regular frame, which is really the best we can do.
240+
if (!self_var_sp->LocationIsValidForFrame(frame)) {
241+
LLDB_LOG(log, " [SUE::SC] `self` variable location not valid for frame");
242+
return;
210243
}
211244

212-
if (!self_type.IsValid()) {
213-
// If the self_type is invalid at this point, reset it.
214-
// Code below the phony do/while will assume the existence
215-
// of this var means something, but it is useless in this
216-
// condition.
245+
auto maybe_self_info = findSwiftSelf(*frame, self_var_sp);
246+
if (!maybe_self_info) {
247+
LLDB_LOG(log, " [SUE::SC] Could not determine info about `self`");
217248
return;
218249
}
219250

220-
// Check to see if we are in a class func of a class (or
221-
// static func of a struct) and adjust our self_type to
222-
// point to the instance type.
223-
m_needs_object_ptr = true;
251+
// Check to see if we are in a class func of a class (or static func of a
252+
// struct) and adjust our type to point to the instance type.
253+
SwiftSelfInfo info = *maybe_self_info;
224254

225-
Flags self_type_flags(self_type.GetTypeInfo());
255+
m_in_static_method = info.is_metatype;
226256

227-
if (self_type_flags.AllSet(lldb::eTypeIsSwift | lldb::eTypeIsMetatype)) {
228-
self_type = TypeSystemSwift::GetInstanceType(self_type);
229-
self_type_flags = self_type.GetTypeInfo();
230-
if (self_type_flags.Test(lldb::eTypeIsClass))
231-
m_is_class = true;
232-
m_in_static_method = true;
233-
}
234-
235-
if (self_type_flags.AllSet(lldb::eTypeIsSwift |
236-
lldb::eTypeInstanceIsPointer)) {
237-
if (self_type_flags.Test(lldb::eTypeIsClass))
238-
m_is_class = true;
239-
}
240-
241-
swift::Type object_type = GetSwiftType(self_type);
242-
if (object_type.getPointer() &&
243-
(object_type.getPointer() != self_type.GetOpaqueQualType()))
244-
self_type = ToCompilerType(object_type.getPointer());
257+
if (info.type_flags.AllSet(lldb::eTypeIsSwift | lldb::eTypeInstanceIsPointer))
258+
m_is_class |= info.type_flags.Test(lldb::eTypeIsClass);
245259

246260
// Handle weak self.
247-
if (auto *ref_type = llvm::dyn_cast_or_null<swift::ReferenceStorageType>(
248-
GetSwiftType(self_type).getPointer())) {
249-
if (ref_type->getOwnership() == swift::ReferenceOwnership::Weak) {
250-
m_is_class = true;
251-
m_is_weak_self = true;
252-
}
261+
auto *ref_type =
262+
llvm::dyn_cast_or_null<swift::ReferenceStorageType>(info.swift_type);
263+
if (ref_type && ref_type->getOwnership() == swift::ReferenceOwnership::Weak) {
264+
m_is_class = true;
265+
m_is_weak_self = true;
253266
}
254267

255-
if (Flags(self_type.GetTypeInfo())
256-
.AllSet(lldb::eTypeIsSwift | lldb::eTypeIsStructUnion |
257-
lldb::eTypeIsGeneric) &&
258-
self_type_flags.AllSet(lldb::eTypeIsSwift | lldb::eTypeIsReference |
259-
lldb::eTypeHasValue)) {
260-
// We can't extend generic structs when "self" is mutating at the
261-
// moment.
262-
m_needs_object_ptr = false;
263-
}
268+
m_needs_object_ptr = !m_in_static_method;
264269

265-
if (log)
266-
log->Printf(" [SUE::SC] Containing class name: %s",
267-
self_type.GetTypeName().AsCString());
270+
LLDB_LOGF(log, " [SUE::SC] Containing class name: %s",
271+
info.type.GetTypeName().AsCString());
268272
}
269273

270274
static SwiftPersistentExpressionState *

lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class SwiftExpressionParser;
3636
/// LLDB uses expressions for various purposes, notably to call functions
3737
/// and as a backend for the expr command. SwiftUserExpression encapsulates
3838
/// the objects needed to parse and interpret or JIT an expression. It
39-
/// uses the Clang parser to produce LLVM IR from the expression.
39+
/// uses the Swift parser to produce LLVM IR from the expression.
4040
//----------------------------------------------------------------------
4141
class SwiftUserExpression : public LLVMUserExpression {
4242
// LLVM RTTI support

0 commit comments

Comments
 (0)