Skip to content

Commit 82da129

Browse files
authored
Merge pull request #5264 from augusto2112/refactor-add-external-variables
[lldb] [NFC] Refactor SwiftASTManipulator::AddExternalVariables
2 parents d0986a4 + 2007ad3 commit 82da129

File tree

2 files changed

+144
-121
lines changed

2 files changed

+144
-121
lines changed

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

Lines changed: 135 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,117 @@ GetPatternBindingForVarDecl(swift::VarDecl *var_decl,
10091009
return pattern_binding;
10101010
}
10111011

1012+
swift::FuncDecl *SwiftASTManipulator::GetFunctionToInjectVariableInto(
1013+
const SwiftASTManipulator::VariableInfo &variable, bool is_self) const {
1014+
// The only variable that we inject in the wrapper is self, so we can
1015+
// call the function declared in the type extension.
1016+
return is_self ? m_wrapper_decl : m_function_decl;
1017+
}
1018+
1019+
llvm::Optional<swift::Type> SwiftASTManipulator::GetSwiftTypeForVariable(
1020+
const SwiftASTManipulator::VariableInfo &variable, bool is_self) const {
1021+
auto *type_system_swift =
1022+
llvm::dyn_cast_or_null<TypeSystemSwift>(variable.m_type.GetTypeSystem());
1023+
1024+
if (!type_system_swift)
1025+
return {};
1026+
1027+
// This might be a referenced type, which will confuse the type checker.
1028+
// The access pattern for these types is the same as for the referent
1029+
// type, so it is fine to just strip it off.
1030+
CompilerType referent_type =
1031+
type_system_swift->GetReferentType(variable.m_type.GetOpaqueQualType());
1032+
1033+
swift::Type swift_type = GetSwiftType(referent_type);
1034+
if (!swift_type)
1035+
return {};
1036+
1037+
// One tricky bit here is that this var may be an argument to the
1038+
// function whose context we are emulating, and that argument might be
1039+
// of "inout" type. We need to strip the inout off the type or the
1040+
// initial parse will fail. Fortunately, the variable access goes the
1041+
// same regardless of whether it is inout or not, so we don't have to do
1042+
// anything more to get this to work.
1043+
swift_type = swift_type->getWithoutSpecifierType();
1044+
1045+
if (is_self) {
1046+
// Another tricky bit is that the Metatype types we get have the
1047+
// "Representation" already attached (i.e.
1048+
// "@thick", "@thin".) But the representation is a SIL level thing,
1049+
// and if it is attached to types that we hand the parser, it throws a
1050+
// verifier error & aborts. So we strip it off here:
1051+
swift::MetatypeType *metatype_type =
1052+
llvm::dyn_cast<swift::MetatypeType>(swift_type.getPointer());
1053+
if (metatype_type) {
1054+
swift_type = swift::Type(
1055+
swift::MetatypeType::get(metatype_type->getInstanceType()));
1056+
}
1057+
}
1058+
1059+
if (swift_type->hasArchetype())
1060+
swift_type = swift_type->mapTypeOutOfContext();
1061+
1062+
return {swift_type};
1063+
}
1064+
1065+
swift::VarDecl *SwiftASTManipulator::GetVarDeclForVariableInFunction(
1066+
const SwiftASTManipulator::VariableInfo &variable, bool is_self,
1067+
swift::FuncDecl *containing_function) {
1068+
const auto maybe_swift_type = GetSwiftTypeForVariable(variable, is_self);
1069+
1070+
if (!maybe_swift_type)
1071+
return {};
1072+
1073+
const auto &swift_type = *maybe_swift_type;
1074+
1075+
const swift::SourceLoc loc = containing_function->getBody()->getLBraceLoc();
1076+
const swift::Identifier name = variable.GetName();
1077+
// We may need to mutate the self variable later, so hardcode it to a var
1078+
// in that case.
1079+
const auto introducer =
1080+
is_self ? swift::VarDecl::Introducer::Var : variable.GetVarIntroducer();
1081+
1082+
const swift::ASTContext &ast_context = m_source_file.getASTContext();
1083+
swift::VarDecl *redirected_var_decl = new (ast_context) swift::VarDecl(
1084+
/*is_staic*/ false, introducer, loc, name, containing_function);
1085+
1086+
redirected_var_decl->setInterfaceType(swift_type);
1087+
redirected_var_decl->setDebuggerVar(true);
1088+
redirected_var_decl->setImplicit(true);
1089+
1090+
// This avoids having local variables filtered out by
1091+
// swift::namelookup::filterForDiscriminator().
1092+
redirected_var_decl->overwriteAccess(swift::AccessLevel::Public);
1093+
1094+
if (swift_type->getAs<swift::WeakStorageType>()) {
1095+
redirected_var_decl->getAttrs().add(
1096+
new (ast_context) swift::ReferenceOwnershipAttr(
1097+
swift::SourceRange(), swift::ReferenceOwnership::Weak));
1098+
}
1099+
1100+
return redirected_var_decl;
1101+
}
1102+
1103+
/// Adds the new nodes to the beginning of the function.
1104+
static void AddNodesToBeginningFunction(
1105+
swift::FuncDecl *function,
1106+
const llvm::SmallVectorImpl<swift::ASTNode> &new_nodes,
1107+
swift::ASTContext &ast_context) {
1108+
swift::BraceStmt *body = function->getBody();
1109+
llvm::ArrayRef<swift::ASTNode> current_elements = body->getElements();
1110+
1111+
llvm::SmallVector<swift::ASTNode, 3> new_elements(current_elements.begin(),
1112+
current_elements.end());
1113+
1114+
// Make sure to add the new nodes at the beginning of the function.
1115+
new_elements.insert(new_elements.begin(), new_nodes.begin(), new_nodes.end());
1116+
auto *new_function_body = swift::BraceStmt::create(
1117+
ast_context, body->getLBraceLoc(), ast_context.AllocateCopy(new_elements),
1118+
body->getRBraceLoc());
1119+
1120+
function->setBody(new_function_body, function->getBodyKind());
1121+
}
1122+
10121123
bool SwiftASTManipulator::AddExternalVariables(
10131124
llvm::MutableArrayRef<VariableInfo> variables) {
10141125
if (!IsValid())
@@ -1043,7 +1154,7 @@ bool SwiftASTManipulator::AddExternalVariables(
10431154

10441155
swift::VarDecl *redirected_var_decl = new (ast_context)
10451156
swift::VarDecl(is_static, introducer, loc, name,
1046-
&m_source_file);
1157+
&m_source_file);
10471158
redirected_var_decl->setInterfaceType(var_type);
10481159
redirected_var_decl->setTopLevelGlobal(true);
10491160

@@ -1085,127 +1196,29 @@ bool SwiftASTManipulator::AddExternalVariables(
10851196

10861197
m_variables.push_back(variable);
10871198
} else {
1088-
swift::BraceStmt *body = m_function_decl->getBody();
1089-
llvm::ArrayRef<swift::ASTNode> body_elements = body->getElements();
1090-
1091-
llvm::SmallVector<swift::ASTNode, 3> elements(body_elements.begin(),
1092-
body_elements.end());
1093-
llvm::SmallVectorImpl<swift::ASTNode>::iterator element_iterator =
1094-
elements.begin();
1095-
const bool is_static = false;
1199+
// The new nodes that should be added to each function.
1200+
std::unordered_map<swift::FuncDecl *, llvm::SmallVector<swift::ASTNode, 3>>
1201+
injected_nodes;
10961202

10971203
for (SwiftASTManipulator::VariableInfo &variable : variables) {
1098-
swift::SourceLoc loc = m_function_decl->getBody()->getLBraceLoc();
1099-
swift::FuncDecl *containing_function = m_function_decl;
1100-
swift::Identifier name = variable.m_name;
1101-
auto introducer = variable.GetVarIntroducer();
1102-
11031204
bool is_self = !variable.m_name.str().compare("$__lldb_injected_self");
1104-
1105-
if (is_self) {
1106-
if (!m_wrapper_decl)
1107-
continue;
1108-
1109-
// We need to mutate the $__lldb_wrapped_expr_%d member of self later.
1110-
introducer = swift::VarDecl::Introducer::Var;
1111-
loc = m_wrapper_decl->getBody()->getLBraceLoc();
1112-
containing_function = m_wrapper_decl;
1113-
}
1114-
1115-
// This might be a referenced type, which will confuse the type checker.
1116-
// The access pattern for these types is the same as for the referent
1117-
// type, so it is fine to
1118-
// just strip it off.
1119-
auto *swift_ast_ctx = llvm::dyn_cast_or_null<TypeSystemSwift>(
1120-
variable.m_type.GetTypeSystem());
1121-
1122-
CompilerType referent_type;
1123-
if (swift_ast_ctx)
1124-
referent_type =
1125-
swift_ast_ctx->GetReferentType(variable.m_type.GetOpaqueQualType());
1126-
if (!referent_type)
1127-
continue;
1128-
1129-
swift::Type swift_referent_type = GetSwiftType(referent_type);
1130-
if (!swift_referent_type)
1205+
swift::FuncDecl *containing_function =
1206+
GetFunctionToInjectVariableInto(variable, is_self);
1207+
assert(containing_function && "No function to inject variable into!");
1208+
if (!containing_function)
11311209
continue;
1132-
1133-
// One tricky bit here is that this var may be an argument to the function
1134-
// whose context we are
1135-
// emulating, and that argument might be of "inout" type. We need to
1136-
// strip the inout off the type
1137-
// or the initial parse will fail. Fortunately, the variable access goes
1138-
// the same regardless of whether
1139-
// it is inout or not, so we don't have to do anything more to get this to
1140-
// work.
1141-
swift::Type var_type =
1142-
swift_referent_type->getWithoutSpecifierType();
1143-
if (is_self) {
1144-
// Another tricky bit is that the Metatype types we get have the
1145-
// "Representation" already attached (i.e.
1146-
// "@thick", "@thin".) But the representation is a SIL level thing, and
1147-
// if it is attached to types that
1148-
// we hand the parser, it throws a verifier error & aborts. So we strip
1149-
// it off here:
1150-
swift::MetatypeType *metatype_type =
1151-
llvm::dyn_cast<swift::MetatypeType>(var_type.getPointer());
1152-
if (metatype_type) {
1153-
var_type = swift::Type(
1154-
swift::MetatypeType::get(metatype_type->getInstanceType()));
1155-
}
1156-
}
1157-
1158-
swift::VarDecl *redirected_var_decl = new (ast_context) swift::VarDecl(
1159-
is_static, introducer, loc, name,
1160-
containing_function);
1161-
auto interface_type = var_type;
1162-
if (interface_type->hasArchetype())
1163-
interface_type = interface_type->mapTypeOutOfContext();
1164-
redirected_var_decl->setInterfaceType(interface_type);
1165-
redirected_var_decl->setDebuggerVar(true);
1166-
redirected_var_decl->setImplicit(true);
1167-
// This avoids having local variables filtered out by
1168-
// swift::namelookup::filterForDiscriminator().
1169-
redirected_var_decl->overwriteAccess(swift::AccessLevel::Public);
11701210

1211+
swift::VarDecl *redirected_var_decl = GetVarDeclForVariableInFunction(
1212+
variable, is_self, containing_function);
11711213
swift::PatternBindingDecl *pattern_binding =
11721214
GetPatternBindingForVarDecl(redirected_var_decl, containing_function);
11731215

1174-
if (var_type->getAs<swift::WeakStorageType>()) {
1175-
redirected_var_decl->getAttrs().add(
1176-
new (ast_context) swift::ReferenceOwnershipAttr(
1177-
swift::SourceRange(), swift::ReferenceOwnership::Weak));
1178-
}
1179-
1180-
if (is_self) {
1181-
// we need to inject into the wrapper
1182-
1183-
swift::BraceStmt *wrapper_body = m_wrapper_decl->getBody();
1184-
llvm::ArrayRef<swift::ASTNode> wrapper_elements =
1185-
wrapper_body->getElements();
1186-
1187-
llvm::SmallVector<swift::ASTNode, 3> wrapper_elements_copy(
1188-
wrapper_elements.begin(), wrapper_elements.end());
1189-
llvm::SmallVectorImpl<swift::ASTNode>::iterator
1190-
wrapper_element_iterator = wrapper_elements_copy.begin();
1191-
1192-
wrapper_element_iterator = wrapper_elements_copy.insert(
1193-
wrapper_element_iterator, swift::ASTNode(pattern_binding));
1194-
wrapper_element_iterator = wrapper_elements_copy.insert(
1195-
wrapper_element_iterator, swift::ASTNode(redirected_var_decl));
1196-
1197-
auto *new_wrapper_body = swift::BraceStmt::create(
1198-
ast_context, wrapper_body->getLBraceLoc(),
1199-
ast_context.AllocateCopy(wrapper_elements_copy),
1200-
wrapper_body->getRBraceLoc());
1201-
m_wrapper_decl->setBody(new_wrapper_body,
1202-
m_wrapper_decl->getBodyKind());
1203-
} else {
1204-
element_iterator =
1205-
elements.insert(element_iterator, swift::ASTNode(pattern_binding));
1206-
element_iterator = elements.insert(element_iterator,
1207-
swift::ASTNode(redirected_var_decl));
1208-
}
1216+
// Push the var decl and pattern binding so we add them to the function
1217+
// later.
1218+
injected_nodes[containing_function].push_back(
1219+
swift::ASTNode(pattern_binding));
1220+
injected_nodes[containing_function].push_back(
1221+
swift::ASTNode(redirected_var_decl));
12091222

12101223
variable.m_decl = redirected_var_decl;
12111224

@@ -1215,18 +1228,19 @@ bool SwiftASTManipulator::AddExternalVariables(
12151228
variable.m_decl->dump(ss);
12161229
ss.flush();
12171230

1218-
log->Printf(
1219-
"[SwiftASTManipulator::AddExternalVariables] Injected variable %s",
1220-
s.c_str());
1231+
log->Printf("[SwiftASTManipulator::AddExternalVariables] Injected "
1232+
"variable %s",
1233+
s.c_str());
12211234
}
12221235

12231236
m_variables.push_back(variable);
12241237
}
12251238

1226-
auto *new_function_body = swift::BraceStmt::create(
1227-
ast_context, body->getLBraceLoc(), ast_context.AllocateCopy(elements),
1228-
body->getRBraceLoc());
1229-
m_function_decl->setBody(new_function_body, m_function_decl->getBodyKind());
1239+
for (auto &pair : injected_nodes) {
1240+
auto *containing_function = pair.first;
1241+
auto &new_nodes = pair.second;
1242+
AddNodesToBeginningFunction(containing_function, new_nodes, ast_context);
1243+
}
12301244
}
12311245

12321246
return true;

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,15 @@ class SwiftASTManipulator : public SwiftASTManipulatorBase {
155155
CompilerType &type,
156156
VariableMetadataSP &metadata_sp);
157157

158+
swift::FuncDecl *GetFunctionToInjectVariableInto(
159+
const SwiftASTManipulator::VariableInfo &variable, bool is_self) const;
160+
swift::VarDecl *GetVarDeclForVariableInFunction(
161+
const SwiftASTManipulator::VariableInfo &variable, bool is_self,
162+
swift::FuncDecl *containing_function);
163+
llvm::Optional<swift::Type>
164+
GetSwiftTypeForVariable(
165+
const SwiftASTManipulator::VariableInfo &variable, bool is_self) const;
166+
158167
bool AddExternalVariables(llvm::MutableArrayRef<VariableInfo> variables);
159168

160169
bool RewriteResult();

0 commit comments

Comments
 (0)