Skip to content

Commit 6429041

Browse files
authored
Merge pull request #1180 from vedantk/simplify-sue
[lldb/SwiftUserExpression] Simplify ScanContext logic
2 parents 35f9c84 + 84ddfbe commit 6429041

File tree

4 files changed

+131
-126
lines changed

4 files changed

+131
-126
lines changed

lldb/include/lldb/Expression/Expression.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ class Expression {
5151

5252
/// Return the language that should be used when parsing. To use the
5353
/// default, return eLanguageTypeUnknown.
54-
virtual lldb::LanguageType Language() { return lldb::eLanguageTypeUnknown; }
54+
virtual lldb::LanguageType Language() const {
55+
return lldb::eLanguageTypeUnknown;
56+
}
5557

5658
/// Return the Materializer that the parser should use when registering
5759
/// external values.

lldb/include/lldb/Expression/UserExpression.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ class UserExpression : public Expression {
194194

195195
/// Return the language that should be used when parsing. To use the
196196
/// default, return eLanguageTypeUnknown.
197-
lldb::LanguageType Language() override { return m_language; }
197+
lldb::LanguageType Language() const override { return m_language; }
198198

199199
/// Return the desired result type of the function, or eResultTypeAny if
200200
/// indifferent.

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

Lines changed: 126 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -94,177 +94,180 @@ 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+
return true;
106+
} else if (sym_ctx.symbol && expr.Language() == lldb::eLanguageTypeUnknown) {
107+
if (sym_ctx.symbol->GetMangled().GuessLanguage() ==
108+
lldb::eLanguageTypeSwift)
109+
return true;
110+
}
111+
return false;
112+
}
113+
114+
/// Information about `self` in a frame.
115+
struct SwiftSelfInfo {
116+
/// Whether `self` is a metatype (i.e. whether we're in a static method).
117+
bool is_metatype = false;
118+
119+
/// Adjusted type of `self`. If we're in a static method, this is an instance
120+
/// type.
121+
CompilerType type = {};
122+
123+
/// Underlying Swift type for the adjusted type of `self`.
124+
swift::TypeBase *swift_type = nullptr;
125+
126+
/// Type flags for the adjusted type of `self`.
127+
Flags type_flags = {};
128+
};
129+
130+
/// Find information about `self` in the frame.
131+
static llvm::Optional<SwiftSelfInfo>
132+
findSwiftSelf(StackFrame &frame, lldb::VariableSP self_var_sp) {
133+
SwiftSelfInfo info;
134+
135+
lldb::ValueObjectSP valobj_sp = frame.GetValueObjectForFrameVariable(
136+
self_var_sp, lldb::eDynamicDontRunTarget);
137+
138+
// 1) Try finding the type of `self` from its ValueObject.
139+
if (valobj_sp && valobj_sp->GetError().Success())
140+
info.type = valobj_sp->GetCompilerType();
141+
142+
// 2) If (1) fails, try finding the type of `self` from its Variable.
143+
if (!info.type.IsValid())
144+
if (Type *self_lldb_type = self_var_sp->GetType())
145+
info.type = self_var_sp->GetType()->GetForwardCompilerType();
146+
147+
// 3) If (1) and (2) fail, give up.
148+
if (!info.type.IsValid())
149+
return llvm::None;
150+
151+
// 4) If `self` is a metatype, get its instance type.
152+
if (Flags(info.type.GetTypeInfo())
153+
.AllSet(lldb::eTypeIsSwift | lldb::eTypeIsMetatype)) {
154+
info.type = TypeSystemSwift::GetInstanceType(info.type);
155+
info.is_metatype = true;
156+
}
157+
158+
// 5) If the adjusted type isn't equal to the type according to the runtime,
159+
// switch it to the latter type.
160+
info.swift_type = GetSwiftType(info.type).getPointer();
161+
if (info.swift_type && (info.swift_type != info.type.GetOpaqueQualType()))
162+
info.type = ToCompilerType(info.swift_type);
163+
164+
info.type_flags = Flags(info.type.GetTypeInfo());
165+
166+
if (!info.type.IsValid())
167+
return llvm::None;
168+
return info;
169+
}
170+
97171
void SwiftUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
98172
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
99-
100-
if (log)
101-
log->Printf("SwiftUserExpression::ScanContext()");
173+
LLDB_LOG(log, "SwiftUserExpression::ScanContext()");
102174

103175
m_target = exe_ctx.GetTargetPtr();
104-
105176
if (!m_target) {
106-
if (log)
107-
log->Printf(" [SUE::SC] Null target");
177+
LLDB_LOG(log, " [SUE::SC] Null target");
108178
return;
109179
}
110180

111181
StackFrame *frame = exe_ctx.GetFramePtr();
112182
if (!frame) {
113-
if (log)
114-
log->Printf(" [SUE::SC] Null stack frame");
183+
LLDB_LOG(log, " [SUE::SC] Null stack frame");
115184
return;
116185
}
117186

118187
SymbolContext sym_ctx = frame->GetSymbolContext(
119188
lldb::eSymbolContextFunction | lldb::eSymbolContextBlock |
120189
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;
190+
bool frame_is_swift = isSwiftLanguageSymbolContext(*this, sym_ctx);
191+
if (!frame_is_swift) {
192+
LLDB_LOG(log, " [SUE::SC] Frame is not swift-y");
193+
return;
138194
}
139195

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

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-
}
204+
if (!swift_ast_ctx->GetClangImporter()) {
205+
LLDB_LOG(log, " [SUE::SC] Swift AST Context has no Clang importer");
206+
return;
207+
}
161208

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

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

172216
Block *function_block = sym_ctx.GetFunctionBlock();
173-
if (!function_block)
217+
if (!function_block) {
218+
LLDB_LOG(log, " [SUE::SC] No function block");
174219
return;
220+
}
175221

176222
lldb::VariableListSP variable_list_sp(
177223
function_block->GetBlockVariableList(true));
178-
179-
if (!variable_list_sp)
224+
if (!variable_list_sp) {
225+
LLDB_LOG(log, " [SUE::SC] No block variable list");
180226
return;
227+
}
181228

182229
lldb::VariableSP self_var_sp(
183230
variable_list_sp->FindVariable(ConstString("self")));
184-
185-
if (!self_var_sp || !SwiftLanguageRuntime::IsSelf(*self_var_sp))
231+
if (!self_var_sp || !SwiftLanguageRuntime::IsSelf(*self_var_sp)) {
232+
LLDB_LOG(log, " [SUE::SC] No valid `self` variable");
186233
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();
203234
}
204235

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();
236+
// If we have a self variable, but it has no location at the current PC, then
237+
// we can't use it. Set the self var back to empty and we'll just pretend we
238+
// are in a regular frame, which is really the best we can do.
239+
if (!self_var_sp->LocationIsValidForFrame(frame)) {
240+
LLDB_LOG(log, " [SUE::SC] `self` variable location not valid for frame");
241+
return;
210242
}
211243

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.
244+
auto maybe_self_info = findSwiftSelf(*frame, self_var_sp);
245+
if (!maybe_self_info) {
246+
LLDB_LOG(log, " [SUE::SC] Could not determine info about `self`");
217247
return;
218248
}
219249

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;
250+
// Check to see if we are in a class func of a class (or static func of a
251+
// struct) and adjust our type to point to the instance type.
252+
SwiftSelfInfo info = *maybe_self_info;
224253

225-
Flags self_type_flags(self_type.GetTypeInfo());
254+
m_in_static_method = info.is_metatype;
226255

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());
256+
if (info.type_flags.AllSet(lldb::eTypeIsSwift | lldb::eTypeInstanceIsPointer))
257+
m_is_class |= info.type_flags.Test(lldb::eTypeIsClass);
245258

246259
// 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-
}
260+
auto *ref_type =
261+
llvm::dyn_cast_or_null<swift::ReferenceStorageType>(info.swift_type);
262+
if (ref_type && ref_type->getOwnership() == swift::ReferenceOwnership::Weak) {
263+
m_is_class = true;
264+
m_is_weak_self = true;
253265
}
254266

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-
}
267+
m_needs_object_ptr = !m_in_static_method;
264268

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

270273
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)