blob: c048adb522ad97efdb2e8a3662d6e104248da9ad [file]
//===-- SwiftExpressionParser.cpp -------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "SwiftExpressionParser.h"
#include "SwiftASTManipulator.h"
#include "SwiftREPLMaterializer.h"
#include "SwiftSILManipulator.h"
#include "SwiftUserExpression.h"
#include "Plugins/ExpressionParser/Swift/SwiftDiagnostic.h"
#include "Plugins/ExpressionParser/Swift/SwiftExpressionVariable.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/Expression.h"
#include "lldb/Expression/ExpressionSourceCode.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/SwiftLanguageRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.h"
#include "llvm-c/Analysis.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include "clang/Basic/Module.h"
#include "clang/Rewrite/Core/RewriteBuffer.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticConsumer.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/Module.h"
#include "swift/AST/ModuleLoader.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Basic/PrimarySpecificPaths.h"
#include "swift/Basic/SourceManager.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Parse/LocalContext.h"
#include "swift/Parse/PersistentParserState.h"
#include "swift/SIL/SILDebuggerClient.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "swift/Subsystems.h"
using namespace lldb_private;
SwiftExpressionParser::SwiftExpressionParser(
ExecutionContextScope *exe_scope, Expression &expr,
const EvaluateExpressionOptions &options)
: ExpressionParser(exe_scope, expr, options.GetGenerateDebugInfo()),
m_expr(expr), m_triple(), m_llvm_context(), m_module(),
m_execution_unit_sp(), m_swift_ast_context(NULL), m_sc(),
m_stack_frame_wp(), m_options(options) {
assert(expr.Language() == lldb::eLanguageTypeSwift);
// TODO This code is copied from ClangExpressionParser.cpp.
// Factor this out into common code.
lldb::TargetSP target_sp;
if (exe_scope) {
target_sp = exe_scope->CalculateTarget();
lldb::StackFrameSP stack_frame = exe_scope->CalculateStackFrame();
if (stack_frame) {
m_stack_frame_wp = stack_frame;
m_sc = stack_frame->GetSymbolContext(lldb::eSymbolContextEverything);
} else {
m_sc.target_sp = target_sp;
}
}
if (target_sp && target_sp->GetArchitecture().IsValid()) {
std::string triple = target_sp->GetArchitecture().GetTriple().str();
int dash_count = 0;
for (size_t i = 0; i < triple.size(); ++i) {
if (triple[i] == '-')
dash_count++;
if (dash_count == 3) {
triple.resize(i);
break;
}
}
m_triple = triple;
} else {
m_triple = llvm::sys::getDefaultTargetTriple();
}
if (target_sp) {
m_swift_ast_context = llvm::cast_or_null<SwiftASTContext>(
target_sp->GetScratchTypeSystemForLanguage(nullptr,
lldb::eLanguageTypeSwift));
}
}
static void DescribeFileUnit(Stream &s, swift::FileUnit *file_unit) {
s.PutCString("kind = ");
switch (file_unit->getKind()) {
default: { s.PutCString("<unknown>"); }
case swift::FileUnitKind::Source: {
s.PutCString("Source, ");
if (swift::SourceFile *source_file =
llvm::dyn_cast<swift::SourceFile>(file_unit)) {
s.Printf("filename = '%s', ", source_file->getFilename().str().c_str());
s.PutCString("source file kind = ");
switch (source_file->Kind) {
case swift::SourceFileKind::Library:
s.PutCString("Library");
case swift::SourceFileKind::Main:
s.PutCString("Main");
case swift::SourceFileKind::REPL:
s.PutCString("REPL");
case swift::SourceFileKind::SIL:
s.PutCString("SIL");
}
}
} break;
case swift::FileUnitKind::Builtin: {
s.PutCString("Builtin");
} break;
case swift::FileUnitKind::SerializedAST:
case swift::FileUnitKind::ClangModule: {
s.PutCString("SerializedAST, ");
swift::LoadedFile *loaded_file = llvm::cast<swift::LoadedFile>(file_unit);
s.Printf("filename = '%s'", loaded_file->getFilename().str().c_str());
} break;
};
}
// Gets the full module name from the module passed in.
static void GetNameFromModule(swift::ModuleDecl *module, std::string &result) {
result.clear();
if (module) {
const char *name = module->getName().get();
if (!name)
return;
result.append(name);
const clang::Module *clang_module = module->findUnderlyingClangModule();
// At present, there doesn't seem to be any way to get the full module path
// from the Swift side.
if (!clang_module)
return;
for (const clang::Module *cur_module = clang_module->Parent; cur_module;
cur_module = cur_module->Parent) {
if (!cur_module->Name.empty()) {
result.insert(0, 1, '.');
result.insert(0, cur_module->Name);
}
}
}
}
// Largely lifted from swift::performAutoImport, but serves our own nefarious
// purposes.
bool SwiftExpressionParser::PerformAutoImport(swift::SourceFile &source_file,
bool user_imports,
Status &error) {
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
const std::vector<ConstString> *cu_modules = nullptr;
CompileUnit *compile_unit = m_sc.comp_unit;
if (compile_unit)
cu_modules = &compile_unit->GetImportedModules();
llvm::SmallVector<swift::ModuleDecl::ImportedModule, 2> imported_modules;
llvm::SmallVector<std::pair<swift::ModuleDecl::ImportedModule,
swift::SourceFile::ImportOptions>,
2>
additional_imports;
source_file.getImportedModules(imported_modules,
swift::ModuleDecl::ImportFilter::All);
std::set<ConstString> loaded_modules;
auto load_one_module = [this, log, &loaded_modules, &imported_modules,
&additional_imports,
&error](const ConstString &module_name) {
error.Clear();
if (loaded_modules.count(module_name))
return true;
if (log)
log->Printf("[PerformAutoImport] Importing module %s",
module_name.AsCString());
loaded_modules.insert(module_name);
swift::ModuleDecl *swift_module = nullptr;
lldb::StackFrameSP this_frame_sp(m_stack_frame_wp.lock());
if (module_name == ConstString(m_swift_ast_context->GetClangImporter()
->getImportedHeaderModule()
->getName()
.str()))
swift_module =
m_swift_ast_context->GetClangImporter()->getImportedHeaderModule();
else if (this_frame_sp) {
lldb::ProcessSP process_sp(this_frame_sp->CalculateProcess());
if (process_sp)
swift_module = m_swift_ast_context->FindAndLoadModule(
module_name, *process_sp.get(), error);
} else
swift_module = m_swift_ast_context->GetModule(module_name, error);
if (!swift_module || !error.Success() ||
m_swift_ast_context->HasFatalErrors()) {
if (log)
log->Printf("[PerformAutoImport] Couldnt import module %s: %s",
module_name.AsCString(), error.AsCString());
if (!swift_module || m_swift_ast_context->HasFatalErrors()) {
return false;
}
}
if (log) {
log->Printf("Importing %s with source files:", module_name.AsCString());
for (swift::FileUnit *file_unit : swift_module->getFiles()) {
StreamString ss;
DescribeFileUnit(ss, file_unit);
log->Printf(" %s", ss.GetData());
}
}
additional_imports.push_back(std::make_pair(
std::make_pair(swift::ModuleDecl::AccessPathTy(), swift_module),
swift::SourceFile::ImportOptions()));
imported_modules.push_back(
std::make_pair(swift::ModuleDecl::AccessPathTy(), swift_module));
return true;
};
if (!user_imports) {
if (!load_one_module(ConstString("Swift")))
return false;
if (cu_modules) {
for (const ConstString &module_name : *cu_modules) {
if (!load_one_module(module_name))
return false;
}
}
} else {
llvm::SmallVector<swift::ModuleDecl::ImportedModule, 2> parsed_imports;
source_file.getImportedModules(parsed_imports,
swift::ModuleDecl::ImportFilter::All);
SwiftPersistentExpressionState *persistent_expression_state =
llvm::cast<SwiftPersistentExpressionState>(
m_sc.target_sp->GetPersistentExpressionStateForLanguage(
lldb::eLanguageTypeSwift));
for (auto module_pair : parsed_imports) {
swift::ModuleDecl *module = module_pair.second;
if (module) {
std::string module_name;
GetNameFromModule(module, module_name);
if (!module_name.empty()) {
ConstString module_const_str(module_name);
if (log)
log->Printf("[PerformAutoImport] Performing auto import on found "
"module: %s.\n",
module_name.c_str());
if (!load_one_module(module_const_str))
return false;
if (1 /* How do we tell we are in REPL or playground mode? */) {
persistent_expression_state->AddHandLoadedModule(module_const_str);
}
}
}
}
// Finally get the hand-loaded modules from the
// SwiftPersistentExpressionState and load them into this context:
if (!persistent_expression_state->RunOverHandLoadedModules(load_one_module))
return false;
}
source_file.addImports(additional_imports);
return true;
}
class VariableMetadataPersistent
: public SwiftASTManipulatorBase::VariableMetadata {
public:
VariableMetadataPersistent(lldb::ExpressionVariableSP &persistent_variable_sp)
: m_persistent_variable_sp(persistent_variable_sp) {}
static constexpr unsigned Type() { return 'Pers'; }
virtual unsigned GetType() { return Type(); }
lldb::ExpressionVariableSP m_persistent_variable_sp;
};
class VariableMetadataVariable
: public SwiftASTManipulatorBase::VariableMetadata {
public:
VariableMetadataVariable(lldb::VariableSP &variable_sp)
: m_variable_sp(variable_sp) {}
static constexpr unsigned Type() { return 'Vari'; }
virtual unsigned GetType() { return Type(); }
lldb::VariableSP m_variable_sp;
};
static CompilerType ImportType(SwiftASTContext &target_context,
CompilerType source_type) {
SwiftASTContext *swift_ast_ctx =
llvm::dyn_cast_or_null<SwiftASTContext>(source_type.GetTypeSystem());
if (swift_ast_ctx == nullptr)
return CompilerType();
if (swift_ast_ctx == &target_context)
return source_type;
Status error, mangled_error;
CompilerType target_type;
// First try to get the type by using the mangled name,
// That will save the mangling step ImportType would have to do:
ConstString type_name = source_type.GetTypeName();
ConstString mangled_counterpart;
bool found_counterpart = type_name.GetMangledCounterpart(mangled_counterpart);
if (found_counterpart)
target_type = target_context.GetTypeFromMangledTypename(
mangled_counterpart.GetCString(), mangled_error);
if (!target_type.IsValid())
target_type = target_context.ImportType(source_type, error);
return target_type;
}
namespace {
class LLDBNameLookup : public swift::SILDebuggerClient {
public:
LLDBNameLookup(SwiftExpressionParser &parser, swift::SourceFile &source_file,
SwiftExpressionParser::SILVariableMap &variable_map,
SymbolContext &sc)
: SILDebuggerClient(source_file.getASTContext()), m_parser(parser),
m_log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)),
m_source_file(source_file), m_variable_map(variable_map), m_sc(sc) {
source_file.getParentModule()->setDebugClient(this);
if (m_sc.target_sp) {
m_persistent_vars = llvm::cast<SwiftPersistentExpressionState>(
m_sc.target_sp->GetPersistentExpressionStateForLanguage(
lldb::eLanguageTypeSwift));
}
}
virtual ~LLDBNameLookup() {}
virtual bool shouldGlobalize(swift::Identifier Name, swift::DeclKind Kind) {
if (m_parser.GetOptions().GetREPLEnabled())
return true;
else {
// Extensions have to be globalized, there's no way to mark them as local
// to the function, since their
// name is the name of the thing being extended...
if (Kind == swift::DeclKind::Extension)
return true;
// Operators need to be parsed at the global scope regardless of name.
if (Kind == swift::DeclKind::Func && Name.isOperator())
return true;
const char *name_cstr = Name.get();
if (name_cstr && name_cstr[0] == '$') {
if (m_log)
m_log->Printf("[LLDBNameLookup::shouldGlobalize] Returning true to "
"globalizing %s",
name_cstr);
return true;
}
}
return false;
}
virtual void didGlobalize(swift::Decl *decl) {
swift::ValueDecl *value_decl = swift::dyn_cast<swift::ValueDecl>(decl);
if (value_decl) {
// It seems weird to be asking this again, but some DeclKinds must be
// moved to
// the source-file level to be legal. But we don't want to register them
// with
// lldb unless they are of the kind lldb explicitly wants to globalize.
if (shouldGlobalize(value_decl->getBaseName().getIdentifier(),
value_decl->getKind()))
m_staged_decls.AddDecl(value_decl, false, ConstString());
}
}
virtual bool lookupOverrides(swift::DeclBaseName Name, swift::DeclContext *DC,
swift::SourceLoc Loc, bool IsTypeLookup,
ResultVector &RV) {
static unsigned counter = 0;
unsigned count = counter++;
if (m_log) {
m_log->Printf("[LLDBNameLookup::lookupOverrides(%u)] Searching for %s",
count, Name.getIdentifier().get());
}
return false;
}
virtual bool lookupAdditions(swift::DeclBaseName Name, swift::DeclContext *DC,
swift::SourceLoc Loc, bool IsTypeLookup,
ResultVector &RV) {
static unsigned counter = 0;
unsigned count = counter++;
StringRef NameStr = Name.getIdentifier().str();
if (m_log) {
m_log->Printf("[LLDBNameLookup::lookupAdditions (%u)] Searching for %s",
count, Name.getIdentifier().str().str().c_str());
}
ConstString name_const_str(NameStr);
std::vector<swift::ValueDecl *> results;
// First look up the matching Decl's we've made in this compile, then pass
// that list to the
// persistent decls, which will only add decls it has that are NOT
// equivalent to the decls
// we made locally.
m_staged_decls.FindMatchingDecls(name_const_str, results);
// Next look up persistent decls matching this name. Then, if we are in the
// plain expression parser, and we
// aren't looking at a debugger variable, filter out persistent results of
// the same kind as one found by the
// ordinary lookup mechanism in the parser . The problem
// we are addressing here is the case where the user has entered the REPL
// while in an ordinary debugging session
// to play around. While there, e.g., they define a class that happens to
// have the same name as one in the
// program, then in some other context "expr" will call the class they've
// defined, not the one in the program
// itself would use. Plain "expr" should behave as much like code in the
// program would, so we want to favor
// entities of the same DeclKind & name from the program over ones defined
// in the REPL. For function decls we
// check the interface type and full name so we don't remove overloads that
// don't exist in the current scope.
//
// Note also, we only do this for the persistent decls. Anything in the
// "staged" list has been defined in this
// expr setting and so is more local than local.
bool skip_results_with_matching_kind =
!(m_parser.GetOptions().GetREPLEnabled() ||
m_parser.GetOptions().GetPlaygroundTransformEnabled() ||
(!NameStr.empty() && NameStr.front() == '$'));
size_t num_external_results = RV.size();
if (skip_results_with_matching_kind && num_external_results > 0) {
std::vector<swift::ValueDecl *> persistent_results;
m_persistent_vars->GetSwiftPersistentDecls(name_const_str,
persistent_results);
size_t num_persistent_results = persistent_results.size();
for (size_t idx = 0; idx < num_persistent_results; idx++) {
swift::ValueDecl *value_decl = persistent_results[idx];
if (!value_decl)
continue;
swift::DeclName value_decl_name = value_decl->getFullName();
swift::DeclKind value_decl_kind = value_decl->getKind();
swift::CanType value_interface_type =
value_decl->getInterfaceType()->getCanonicalType();
bool is_function = swift::isa<swift::AbstractFunctionDecl>(value_decl);
bool skip_it = false;
for (size_t rv_idx = 0; rv_idx < num_external_results; rv_idx++) {
if (swift::ValueDecl *rv_decl = RV[rv_idx].getValueDecl()) {
if (value_decl_kind == rv_decl->getKind()) {
if (is_function) {
swift::DeclName rv_full_name = rv_decl->getFullName();
if (rv_full_name.matchesRef(value_decl_name)) {
// If the full names match, make sure the interface types
// match:
if (rv_decl->getInterfaceType()->getCanonicalType() ==
value_interface_type)
skip_it = true;
}
} else {
skip_it = true;
}
if (skip_it)
break;
}
}
}
if (!skip_it)
results.push_back(value_decl);
}
} else {
m_persistent_vars->GetSwiftPersistentDecls(name_const_str, results);
}
for (size_t idx = 0; idx < results.size(); idx++) {
swift::ValueDecl *value_decl = results[idx];
assert(&DC->getASTContext() ==
&value_decl->getASTContext()); // no import required
RV.push_back(swift::LookupResultEntry(value_decl));
}
return results.size() > 0;
}
virtual swift::SILValue emitLValueForVariable(swift::VarDecl *var,
swift::SILBuilder &builder) {
SwiftSILManipulator manipulator(builder);
swift::Identifier variable_name = var->getName();
ConstString variable_const_string(variable_name.get());
SwiftExpressionParser::SILVariableMap::iterator vi =
m_variable_map.find(variable_const_string.AsCString());
if (vi == m_variable_map.end())
return swift::SILValue();
return manipulator.emitLValueForVariable(var, vi->second);
}
SwiftPersistentExpressionState::SwiftDeclMap &GetStagedDecls() {
return m_staged_decls;
}
virtual swift::Identifier getPreferredPrivateDiscriminator() {
if (m_sc.comp_unit) {
if (lldb_private::Module *module = m_sc.module_sp.get()) {
if (lldb_private::SymbolVendor *symbol_vendor =
module->GetSymbolVendor()) {
std::string private_discriminator_string;
if (symbol_vendor->GetCompileOption("-private-discriminator",
private_discriminator_string,
m_sc.comp_unit)) {
return m_source_file.getASTContext().getIdentifier(
private_discriminator_string);
}
}
}
}
return swift::Identifier();
}
private:
SwiftExpressionParser &m_parser;
Log *m_log;
swift::SourceFile &m_source_file;
SwiftExpressionParser::SILVariableMap &m_variable_map;
SymbolContext m_sc;
SwiftPersistentExpressionState *m_persistent_vars = nullptr;
SwiftPersistentExpressionState::SwiftDeclMap
m_staged_decls; // We stage the decls we are globalize in this map.
// They will get copied over to the SwiftPersistentVariable
// store if the parse succeeds.
};
} // END Anonymous namespace
static void
AddRequiredAliases(Block *block, lldb::StackFrameSP &stack_frame_sp,
SwiftASTContext &swift_ast_context,
SwiftASTManipulator &manipulator,
const Expression::SwiftGenericInfo &generic_info) {
// First, emit the typealias for "$__lldb_context"
do {
if (!block)
break;
Function *function = block->CalculateSymbolContextFunction();
if (!function)
break;
constexpr bool can_create = true;
Block &function_block(function->GetBlock(can_create));
lldb::VariableListSP variable_list_sp(
function_block.GetBlockVariableList(true));
if (!variable_list_sp)
break;
lldb::VariableSP self_var_sp(
variable_list_sp->FindVariable(ConstString("self")));
if (!self_var_sp)
break;
CompilerType self_type;
if (stack_frame_sp) {
lldb::ValueObjectSP valobj_sp =
stack_frame_sp->GetValueObjectForFrameVariable(
self_var_sp, lldb::eNoDynamicValues);
if (valobj_sp)
self_type = valobj_sp->GetCompilerType();
}
if (!self_type.IsValid()) {
if (Type *type = self_var_sp->GetType()) {
self_type = type->GetForwardCompilerType();
}
}
if (!self_type.IsValid() ||
!llvm::isa<SwiftASTContext>(self_type.GetTypeSystem()))
break;
// Import before getting the unbound version, because the unbound version
// may not be in the mangled name map
CompilerType imported_self_type = ImportType(swift_ast_context, self_type);
if (!imported_self_type.IsValid())
break;
// This might be a referenced type, in which case we really want to extend
// the referent:
imported_self_type =
llvm::cast<SwiftASTContext>(imported_self_type.GetTypeSystem())
->GetReferentType(imported_self_type);
// If we are extending a generic class it's going to be a metatype, and we
// have to grab the instance type:
imported_self_type =
llvm::cast<SwiftASTContext>(imported_self_type.GetTypeSystem())
->GetInstanceType(imported_self_type.GetOpaqueQualType());
Flags imported_self_type_flags(imported_self_type.GetTypeInfo());
// If 'self' is the Self archetype, resolve it to the actual metatype it is
if (SwiftASTContext::IsSelfArchetypeType(imported_self_type)) {
SwiftLanguageRuntime *swift_runtime =
stack_frame_sp->GetThread()->GetProcess()->GetSwiftLanguageRuntime();
if (CompilerType concrete_self_type = swift_runtime->GetConcreteType(
stack_frame_sp.get(), ConstString("Self"))) {
if (SwiftASTContext *concrete_self_type_ast_ctx =
llvm::dyn_cast_or_null<SwiftASTContext>(
concrete_self_type.GetTypeSystem())) {
imported_self_type = concrete_self_type_ast_ctx->CreateMetatypeType(
concrete_self_type);
imported_self_type_flags.Reset(imported_self_type.GetTypeInfo());
imported_self_type =
ImportType(swift_ast_context, imported_self_type);
if (imported_self_type_flags.AllSet(lldb::eTypeIsSwift |
lldb::eTypeIsMetatype)) {
imported_self_type = imported_self_type.GetInstanceType();
}
}
}
}
// Get the instance type:
if (imported_self_type_flags.AllSet(lldb::eTypeIsSwift |
lldb::eTypeIsMetatype)) {
imported_self_type = imported_self_type.GetInstanceType();
imported_self_type_flags.Reset(imported_self_type.GetTypeInfo());
}
swift::Type object_type =
swift::Type((swift::TypeBase *)(imported_self_type.GetOpaqueQualType()))
->getWithoutSpecifierType();
if (object_type.getPointer() &&
(object_type.getPointer() != imported_self_type.GetOpaqueQualType()))
imported_self_type = CompilerType(imported_self_type.GetTypeSystem(),
object_type.getPointer());
// If the type of 'self' is a bound generic type, get the unbound version
bool is_generic = imported_self_type_flags.AllSet(lldb::eTypeIsSwift |
lldb::eTypeIsGeneric);
bool is_bound = imported_self_type_flags.AllSet(lldb::eTypeIsSwift |
lldb::eTypeIsBound);
if (is_generic) {
if (is_bound)
imported_self_type = imported_self_type.GetUnboundType();
}
// if 'self' is a weak storage type, it must be an optional. Look through
// it and unpack the argument of "optional".
if (swift::WeakStorageType *weak_storage_type =
((swift::TypeBase *)imported_self_type.GetOpaqueQualType())
->getAs<swift::WeakStorageType>()) {
swift::Type referent_type = weak_storage_type->getReferentType();
swift::BoundGenericEnumType *optional_type =
referent_type->getAs<swift::BoundGenericEnumType>();
if (!optional_type) {
break;
}
swift::Type first_arg_type = optional_type->getGenericArgs()[0];
swift::ClassType *self_class_type =
first_arg_type->getAs<swift::ClassType>();
if (!self_class_type) {
break;
}
imported_self_type =
CompilerType(imported_self_type.GetTypeSystem(), self_class_type);
}
imported_self_type_flags.Reset(imported_self_type.GetTypeInfo());
if (imported_self_type_flags.AllClear(lldb::eTypeIsArchetype)) {
swift::ValueDecl *type_alias_decl = nullptr;
type_alias_decl = manipulator.MakeGlobalTypealias(
swift_ast_context.GetASTContext()->getIdentifier("$__lldb_context"),
imported_self_type);
if (!type_alias_decl) {
Log *log(
lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
if (log)
log->Printf("SEP:AddRequiredAliases: Failed to make the "
"$__lldb_context typealias.");
}
} else {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
if (log)
log->Printf("SEP:AddRequiredAliases: Failed to resolve the self "
"archetype - could not make the $__lldb_context "
"typealias.");
}
} while (0);
// Emit the typedefs
for (const Expression::SwiftGenericInfo::Binding &binding :
generic_info.function_bindings) {
CompilerType bound_type = binding.type;
if (!llvm::isa<SwiftASTContext>(bound_type.GetTypeSystem()))
continue;
CompilerType imported_bound_type =
ImportType(swift_ast_context, bound_type);
if (!imported_bound_type.IsValid())
continue;
std::string alias_name("$__lldb_typeof_generic_");
alias_name.append(binding.name);
swift::ValueDecl *type_alias_decl = manipulator.MakeGlobalTypealias(
swift_ast_context.GetASTContext()->getIdentifier(alias_name),
imported_bound_type);
if (!type_alias_decl)
continue;
}
}
static void CountLocals(
SymbolContext &sc, lldb::StackFrameSP &stack_frame_sp,
SwiftASTContext &ast_context,
llvm::SmallVectorImpl<SwiftASTManipulator::VariableInfo> &local_variables) {
std::set<ConstString> counted_names; // avoids shadowing
if (!sc.block && !sc.function)
return;
Block *block = sc.block;
Block *top_block = block->GetContainingInlinedBlock();
if (!top_block)
top_block = &sc.function->GetBlock(true);
static ConstString s_self_name("self");
SwiftLanguageRuntime *language_runtime = nullptr;
ExecutionContextScope *scope = nullptr;
if (stack_frame_sp) {
language_runtime =
stack_frame_sp->GetThread()->GetProcess()->GetSwiftLanguageRuntime();
scope = stack_frame_sp.get();
}
// The module scoped variables are stored at the CompUnit level, so after we
// go through the current context,
// then we have to take one more pass through the variables in the CompUnit.
bool handling_globals = false;
while (true) {
VariableList variables;
if (!handling_globals) {
constexpr bool can_create = true;
constexpr bool get_parent_variables = false;
constexpr bool stop_if_block_is_inlined_function = true;
block->AppendVariables(can_create, get_parent_variables,
stop_if_block_is_inlined_function,
[](Variable *) { return true; }, &variables);
} else {
if (sc.comp_unit) {
lldb::VariableListSP globals_sp = sc.comp_unit->GetVariableList(true);
if (globals_sp)
variables.AddVariables(globals_sp.get());
}
}
for (size_t vi = 0, ve = variables.GetSize(); vi != ve; ++vi) {
lldb::VariableSP variable_sp(variables.GetVariableAtIndex(vi));
const ConstString &name(variable_sp->GetName());
const char *name_cstring = variable_sp->GetName().GetCString();
if (name.IsEmpty())
continue;
if (counted_names.count(name))
continue;
CompilerType var_type;
if (stack_frame_sp) {
lldb::ValueObjectSP valobj_sp =
stack_frame_sp->GetValueObjectForFrameVariable(
variable_sp, lldb::eNoDynamicValues);
if (!valobj_sp || valobj_sp->GetError().Fail()) {
// Ignore the variable if we couldn't find its corresponding value
// object.
// TODO if the expression tries to use an ignored variable, produce a
// sensible error.
continue;
} else {
var_type = valobj_sp->GetCompilerType();
}
if (var_type.IsValid() && !SwiftASTContext::IsFullyRealized(var_type)) {
lldb::ValueObjectSP dynamic_valobj_sp =
valobj_sp->GetDynamicValue(lldb::eDynamicDontRunTarget);
if (!dynamic_valobj_sp || dynamic_valobj_sp->GetError().Fail()) {
continue;
}
}
}
if (!var_type.IsValid()) {
Type *var_lldb_type = variable_sp->GetType();
if (var_lldb_type)
var_type = var_lldb_type->GetFullCompilerType();
}
if (!var_type.IsValid())
continue;
if (!llvm::isa<SwiftASTContext>(var_type.GetTypeSystem()))
continue;
Status error;
CompilerType target_type = ast_context.ImportType(var_type, error);
// If the import failed, give up
if (!target_type.IsValid())
continue;
// Make sure to resolve all archetypes in the variable type.
if (language_runtime && stack_frame_sp)
target_type = language_runtime->DoArchetypeBindingForType(
*stack_frame_sp, target_type);
// If we couldn't fully realize the type, then we aren't going to get very
// far making a local out of it,
// so discard it here.
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TYPES |
LIBLLDB_LOG_EXPRESSIONS));
if (!SwiftASTContext::IsFullyRealized(target_type)) {
if (log) {
log->Printf("Discarding local %s because we couldn't fully realize "
"it, our best attempt was: %s.",
name_cstring,
target_type.GetTypeName().AsCString("<unknown>"));
}
continue;
}
SwiftASTManipulatorBase::VariableMetadataSP metadata_sp(
new VariableMetadataVariable(variable_sp));
const char *overridden_name = name_cstring;
if (name == s_self_name) {
overridden_name = ConstString("$__lldb_injected_self").AsCString();
if (log) {
swift::TypeBase *swift_type =
(swift::TypeBase *)target_type.GetOpaqueQualType();
if (swift_type) {
std::string s;
llvm::raw_string_ostream ss(s);
swift_type->dump(ss);
ss.flush();
log->Printf("Adding injected self: type (%p) context(%p) is: %s",
swift_type, ast_context.GetASTContext(), s.c_str());
}
}
}
SwiftASTManipulator::VariableInfo variable_info(
target_type,
ast_context.GetASTContext()->getIdentifier(overridden_name),
metadata_sp,
swift::VarDecl::Specifier::Var);
local_variables.push_back(variable_info);
counted_names.insert(name);
}
if (handling_globals) {
// Okay, now we're done...
break;
} else if (block == top_block) {
// Now add the containing module block, that's what holds the module
// globals:
handling_globals = true;
} else
block = block->GetParent();
}
}
static void ResolveSpecialNames(
SymbolContext &sc, SwiftASTContext &ast_context,
llvm::SmallVectorImpl<swift::Identifier> &special_names,
llvm::SmallVectorImpl<SwiftASTManipulator::VariableInfo> &local_variables) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
if (!sc.target_sp)
return;
SwiftPersistentExpressionState *persistent_state =
llvm::cast<SwiftPersistentExpressionState>(
sc.target_sp->GetPersistentExpressionStateForLanguage(
lldb::eLanguageTypeSwift));
std::set<ConstString> resolved_names;
for (swift::Identifier &name : special_names) {
ConstString name_cs = ConstString(name.str());
if (resolved_names.count(name_cs))
continue;
resolved_names.insert(name_cs);
if (log)
log->Printf("Resolving special name %s", name_cs.AsCString());
lldb::ExpressionVariableSP expr_var_sp =
persistent_state->GetVariable(name_cs);
if (!expr_var_sp)
continue;
CompilerType var_type = expr_var_sp->GetCompilerType();
if (!var_type.IsValid())
continue;
if (!llvm::isa<SwiftASTContext>(var_type.GetTypeSystem()))
continue;
CompilerType target_type;
Status error;
target_type = ast_context.ImportType(var_type, error);
if (!target_type)
continue;
SwiftASTManipulatorBase::VariableMetadataSP metadata_sp(
new VariableMetadataPersistent(expr_var_sp));
auto specifier = llvm::cast<SwiftExpressionVariable>(expr_var_sp.get())
->GetIsModifiable()
? swift::VarDecl::Specifier::Var
: swift::VarDecl::Specifier::Let;
SwiftASTManipulator::VariableInfo variable_info(
target_type, ast_context.GetASTContext()->getIdentifier(name.str()),
metadata_sp, specifier);
local_variables.push_back(variable_info);
}
}
//----------------------------------------------------------------------
// Diagnostics are part of the ShintASTContext and we must enable and
// disable colorization manually in the ShintASTContext. We need to
// ensure that if we modify the setting that we restore it to what it
// was. This class helps us to do that without having to intrument all
// returns from a function, like in SwiftExpressionParser::Parse(...).
//----------------------------------------------------------------------
class SetColorize {
public:
SetColorize(SwiftASTContext *swift_ast, bool colorize)
: m_swift_ast(swift_ast),
m_saved_colorize(swift_ast->SetColorizeDiagnostics(colorize)) {}
~SetColorize() { m_swift_ast->SetColorizeDiagnostics(m_saved_colorize); }
protected:
SwiftASTContext *m_swift_ast;
const bool m_saved_colorize;
};
unsigned SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
uint32_t first_line, uint32_t last_line,
uint32_t line_offset) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
// In the case of playgrounds, we turn all rewriting functionality off.
const bool repl = m_options.GetREPLEnabled();
const bool playground = m_options.GetPlaygroundTransformEnabled();
if (!m_swift_ast_context) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
"No AST context to parse into. Please parse with a target.\n");
return 1;
}
// Lazily get the clang importer if we can to make sure it exists in case we
// need it
if (!m_swift_ast_context->GetClangImporter()) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
"Swift expressions require OS X 10.10 / iOS 8 SDKs or later.\n");
return 1;
}
if (m_swift_ast_context->HasFatalErrors()) {
diagnostic_manager.PutString(eDiagnosticSeverityError,
"The AST context is in a fatal error state.");
return 1;
}
swift::ASTContext *ast_context = m_swift_ast_context->GetASTContext();
if (!ast_context) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
"Couldn't initialize the AST context. Please check your settings.");
return 1;
}
if (m_swift_ast_context->HasFatalErrors()) {
diagnostic_manager.PutString(eDiagnosticSeverityError,
"The AST context is in a fatal error state.");
return 1;
}
// If we are using the playground, hand import the necessary modules.
// FIXME: We won't have to do this once the playground adds import statements
// for the things it needs itself.
if (playground) {
SwiftPersistentExpressionState *persistent_state =
llvm::cast<SwiftPersistentExpressionState>(
m_sc.target_sp->GetPersistentExpressionStateForLanguage(
lldb::eLanguageTypeSwift));
persistent_state->AddHandLoadedModule(ConstString("Swift"));
}
// TODO find a way to get contraint-solver output sent to a stream so we can
// log it
// m_swift_ast_context->GetLanguageOptions().DebugConstraintSolver = true;
m_swift_ast_context->ClearDiagnostics();
// Make a class that will set/restore the colorize setting in the
// SwiftASTContext for us
// SetColorize colorize(m_swift_ast_context,
// stream.GetFlags().Test(Stream::eANSIColor));
m_swift_ast_context->GetLanguageOptions().DebuggerSupport = true;
m_swift_ast_context->GetLanguageOptions().EnableDollarIdentifiers =
true; // No longer part of debugger support, set it separately.
m_swift_ast_context->GetLanguageOptions().EnableAccessControl =
(repl || playground);
m_swift_ast_context->GetLanguageOptions().EnableTargetOSChecking = false;
{
lldb::StackFrameSP this_frame_sp(m_stack_frame_wp.lock());
if (this_frame_sp) {
lldb::ProcessSP process_sp(this_frame_sp->CalculateProcess());
if (process_sp) {
Status error;
if (!process_sp->GetObjCLanguageRuntime()) {
m_swift_ast_context->GetLanguageOptions().EnableObjCInterop = false;
}
}
}
}
if (repl || playground) {
m_swift_ast_context->GetLanguageOptions().Playground = true;
m_swift_ast_context->GetIRGenOptions().Playground = true;
} else {
m_swift_ast_context->GetLanguageOptions().Playground = true;
m_swift_ast_context->GetIRGenOptions().Playground = false;
}
// For the expression parser and REPL we want to relax the requirement that
// you put "try" in
// front of every expression that might throw.
if (!playground) {
m_swift_ast_context->GetLanguageOptions().EnableThrowWithoutTry = true;
}
m_swift_ast_context->GetIRGenOptions().OptMode
= swift::OptimizationMode::NoOptimization;
m_swift_ast_context->GetIRGenOptions().Verify =
false; // normally we'd like to verify, but unfortunately the verifier's
// error mode is abort().
bool created_main_file = false;
unsigned buffer_id = 0;
const bool generate_debug_info = m_options.GetGenerateDebugInfo();
m_swift_ast_context->SetGenerateDebugInfo(
generate_debug_info ? swift::IRGenDebugInfoKind::Normal
: swift::IRGenDebugInfoKind::None);
swift::IRGenOptions &ir_gen_options = m_swift_ast_context->GetIRGenOptions();
std::string mainInputFilename;
if (generate_debug_info) {
std::string temp_source_path;
if (ExpressionSourceCode::SaveExpressionTextToTempFile(
m_expr.Text(), m_options, temp_source_path)) {
auto error_or_buffer_ap =
llvm::MemoryBuffer::getFile(temp_source_path.c_str());
if (error_or_buffer_ap.getError() == std::error_condition()) {
buffer_id = m_swift_ast_context->GetSourceManager().addNewSourceBuffer(
std::move(error_or_buffer_ap.get()));
mainInputFilename = temp_source_path;
llvm::SmallString<256> source_dir(temp_source_path);
llvm::sys::path::remove_filename(source_dir);
ir_gen_options.DebugCompilationDir = source_dir.str();
created_main_file = true;
}
}
}
if (!created_main_file) {
const char *filename = repl ? "<REPL>" : "<EXPR>";
mainInputFilename = filename;
std::unique_ptr<llvm::MemoryBuffer> expr_buffer(
llvm::MemoryBuffer::getMemBufferCopy(m_expr.Text(), filename));
buffer_id = m_swift_ast_context->GetSourceManager().addNewSourceBuffer(
std::move(expr_buffer));
}
char expr_name_buf[32];
snprintf(expr_name_buf, sizeof(expr_name_buf), "__lldb_expr_%u",
m_options.GetExpressionNumber());
swift::Identifier module_id(ast_context->getIdentifier(expr_name_buf));
swift::ModuleDecl *module = swift::ModuleDecl::create(module_id, *ast_context);
const swift::SourceFile::ImplicitModuleImportKind implicit_import_kind =
swift::SourceFile::ImplicitModuleImportKind::Stdlib;
m_swift_ast_context->GetCompilerInvocation().getFrontendOptions().ModuleName =
expr_name_buf;
m_swift_ast_context->GetCompilerInvocation().getIRGenOptions().ModuleName =
expr_name_buf;
swift::SourceFileKind source_file_kind = swift::SourceFileKind::Library;
if (playground || repl) {
source_file_kind = swift::SourceFileKind::Main;
}
swift::SourceFile *source_file = new (*ast_context) swift::SourceFile(
*module, source_file_kind, buffer_id, implicit_import_kind,
/*Keep tokens*/false);
module->addFile(*source_file);
bool done = false;
SILVariableMap variable_map;
LLDBNameLookup *external_lookup =
new LLDBNameLookup(*this, *source_file, variable_map, m_sc);
// FIXME: This call is here just so that the we keep the DebuggerClients alive
// as long as the Module we are not
// inserting them in.
m_swift_ast_context->AddDebuggerClient(external_lookup);
swift::PersistentParserState persistent_state;
while (!done) {
swift::parseIntoSourceFile(*source_file, buffer_id, &done, nullptr,
&persistent_state);
if (m_swift_ast_context->HasErrors()) {
m_swift_ast_context->PrintDiagnostics(diagnostic_manager, buffer_id,
first_line, last_line, line_offset);
return 1;
}
}
// This currently crashes with Assertion failed: (BufferID != -1), function
// findBufferContainingLoc, file
// llvm/tools/swift/include/swift/Basic/SourceManager.h, line 92.
// if (log)
// {
// std::string s;
// llvm::raw_string_ostream ss(s);
// source_file->dump(ss);
// ss.flush();
//
// log->Printf("Source file after parsing:");
// log->PutCString(s.c_str());
// }
if (!done) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
"Parse did not consume the whole expression.");
return 1;
}
std::unique_ptr<SwiftASTManipulator> code_manipulator;
if (!playground) {
code_manipulator.reset(new SwiftASTManipulator(*source_file, repl));
code_manipulator->RewriteResult();
}
Status auto_import_error;
if (!PerformAutoImport(*source_file, false, auto_import_error)) {
diagnostic_manager.Printf(eDiagnosticSeverityError, "in auto-import:\n%s",
auto_import_error.AsCString());
return 1;
}
// Swift Modules that rely on shared libraries (not frameworks) don't record
// the link information in the
// swiftmodule file, so we can't really make them work without outside
// information. However, in the REPL you can
// added -L & -l options to the initial compiler startup, and we should dlopen
// anything that's been stuffed
// on there and hope it will be useful later on.
if (repl) {
lldb::StackFrameSP this_frame_sp(m_stack_frame_wp.lock());
if (this_frame_sp) {
lldb::ProcessSP process_sp(this_frame_sp->CalculateProcess());
if (process_sp) {
Status error;
m_swift_ast_context->LoadExtraDylibs(*process_sp.get(), error);
}
}
}
if (!playground && !repl) {
lldb::StackFrameSP stack_frame_sp = m_stack_frame_wp.lock();
bool local_context_is_swift = true;
if (m_sc.block) {
Function *function = m_sc.block->CalculateSymbolContextFunction();
if (function && function->GetLanguage() != lldb::eLanguageTypeSwift)
local_context_is_swift = false;
}
llvm::SmallVector<SwiftASTManipulator::VariableInfo, 5> local_variables;
if (local_context_is_swift) {
AddRequiredAliases(m_sc.block, stack_frame_sp, *m_swift_ast_context,
*code_manipulator, m_expr.GetSwiftGenericInfo());
// Register all local variables so that lookups to them resolve
CountLocals(m_sc, stack_frame_sp, *m_swift_ast_context, local_variables);
}
// Register all magic variables
llvm::SmallVector<swift::Identifier, 2> special_names;
llvm::StringRef persistent_var_prefix;
if (!repl)
persistent_var_prefix = "$";
code_manipulator->FindSpecialNames(special_names, persistent_var_prefix);
ResolveSpecialNames(m_sc, *m_swift_ast_context, special_names,
local_variables);
code_manipulator->AddExternalVariables(local_variables);
// This currently crashes with Assertion failed: (BufferID != -1), function
// findBufferContainingLoc, file
// llvm/tools/swift/include/swift/Basic/SourceManager.h, line 92.
// if (log)
// {
// std::string s;
// llvm::raw_string_ostream ss(s);
// source_file->dump(ss);
// ss.flush();
//
// log->Printf("Source file after code manipulation:");
// log->PutCString(s.c_str());
// }
stack_frame_sp.reset();
}
swift::performNameBinding(*source_file);
if (m_swift_ast_context->HasErrors()) {
m_swift_ast_context->PrintDiagnostics(diagnostic_manager, buffer_id,
first_line, last_line, line_offset);
return 1;
}
// Do the auto-importing after Name Binding, that's when the Imports for the
// source file are figured out.
{
std::lock_guard<std::recursive_mutex> global_context_locker(
IRExecutionUnit::GetLLVMGlobalContextMutex());
Status auto_import_error;
if (!PerformAutoImport(*source_file, true, auto_import_error)) {
diagnostic_manager.Printf(eDiagnosticSeverityError, "in auto-import:\n%s",
auto_import_error.AsCString());
return 1;
}
}
swift::TopLevelContext top_level_context; // not persistent because we're
// building source files one at a
// time
swift::OptionSet<swift::TypeCheckingFlags> type_checking_options;
swift::performTypeChecking(*source_file, top_level_context,
type_checking_options);
if (m_swift_ast_context->HasErrors()) {
m_swift_ast_context->PrintDiagnostics(diagnostic_manager, buffer_id,
first_line, last_line, line_offset);
return 1;
}
if (log) {
std::string s;
llvm::raw_string_ostream ss(s);
source_file->dump(ss);
ss.flush();
log->Printf("Source file after type checking:");
log->PutCString(s.c_str());
}
if (repl) {
code_manipulator->MakeDeclarationsPublic();
}
Status error;
if (!playground) {
code_manipulator->FixupResultAfterTypeChecking(error);
if (!error.Success()) {
diagnostic_manager.PutString(eDiagnosticSeverityError,
error.AsCString());
return 1;
}
} else {
swift::performPlaygroundTransform(*source_file, true);
swift::typeCheckExternalDefinitions(*source_file);
}
// I think we now have to do the name binding and type checking again, but
// there should be only the result
// variable to bind up at this point.
if (log) {
std::string s;
llvm::raw_string_ostream ss(s);
source_file->dump(ss);
ss.flush();
log->Printf("Source file after FixupResult:");
log->PutCString(s.c_str());
}
if (m_sc.target_sp && !playground) {
if (!code_manipulator->CheckPatternBindings()) // Do this first, so we don't
// pollute the persistent
// variable namespace
{
m_swift_ast_context->PrintDiagnostics(diagnostic_manager, buffer_id,
first_line, last_line, line_offset);
return 1;
}
Status error;
SwiftASTContext *scratch_ast_context =
m_sc.target_sp->GetScratchSwiftASTContext(error);
if (scratch_ast_context) {
SwiftPersistentExpressionState *persistent_state =
llvm::dyn_cast<SwiftPersistentExpressionState>(
scratch_ast_context->GetPersistentExpressionState());
llvm::SmallVector<size_t, 1> declaration_indexes;
code_manipulator->FindVariableDeclarations(declaration_indexes, repl);
for (size_t declaration_index : declaration_indexes) {
SwiftASTManipulator::VariableInfo &variable_info =
code_manipulator->GetVariableInfo()[declaration_index];
CompilerType imported_type =
ImportType(*scratch_ast_context, variable_info.GetType());
if (imported_type) {
lldb::ExpressionVariableSP persistent_variable =
persistent_state->AddNewlyConstructedVariable(
new SwiftExpressionVariable(
m_sc.target_sp.get(),
ConstString(variable_info.GetName().str()), imported_type,
m_sc.target_sp->GetArchitecture().GetByteOrder(),
m_sc.target_sp->GetArchitecture().GetAddressByteSize()));
if (repl) {
persistent_variable->m_flags |= ExpressionVariable::EVKeepInTarget;
persistent_variable->m_flags |=
ExpressionVariable::EVIsProgramReference;
} else {
persistent_variable->m_flags |=
ExpressionVariable::EVNeedsAllocation;
persistent_variable->m_flags |= ExpressionVariable::EVKeepInTarget;
llvm::cast<SwiftExpressionVariable>(persistent_variable.get())
->m_swift_flags |= SwiftExpressionVariable::EVSNeedsInit;
}
swift::VarDecl *decl = variable_info.GetDecl();
if (decl) {
if (decl->isLet()) {
llvm::cast<SwiftExpressionVariable>(persistent_variable.get())
->SetIsModifiable(false);
}
if (decl->getStorageKind() ==
swift::VarDecl::StorageKindTy::Computed) {
llvm::cast<SwiftExpressionVariable>(persistent_variable.get())
->SetIsComputed(true);
}
}
variable_info.m_metadata.reset(
new VariableMetadataPersistent(persistent_variable));
persistent_state->RegisterSwiftPersistentDecl(decl);
}
}
if (repl) {
llvm::SmallVector<swift::ValueDecl *, 1> non_variables;
code_manipulator->FindNonVariableDeclarations(non_variables);
for (swift::ValueDecl *decl : non_variables) {
persistent_state->RegisterSwiftPersistentDecl(decl);
}
}
}
}
if (!playground && !repl) {
code_manipulator->FixCaptures();
// This currently crashes with Assertion failed: (BufferID != -1), function
// findBufferContainingLoc, file
// llvm/tools/swift/include/swift/Basic/SourceManager.h, line 92.
// if (log)
// {
// std::string s;
// llvm::raw_string_ostream ss(s);
// source_file->dump(ss);
// ss.flush();
//
// log->Printf("Source file after capture fixing:");
// log->PutCString(s.c_str());
// }
if (log) {
log->Printf("Variables:");
for (const SwiftASTManipulatorBase::VariableInfo &variable :
code_manipulator->GetVariableInfo()) {
StreamString ss;
variable.Print(ss);
log->Printf(" %s", ss.GetData());
}
}
}
Materializer *materializer = m_expr.GetMaterializer();
if (materializer && !playground) {
for (SwiftASTManipulatorBase::VariableInfo &variable :
code_manipulator->GetVariableInfo()) {
uint64_t offset = 0;
bool needs_init = false;
bool is_result =
variable
.MetadataIs<SwiftASTManipulatorBase::VariableMetadataResult>();
bool is_error =
variable.MetadataIs<SwiftASTManipulatorBase::VariableMetadataError>();
SwiftUserExpression *user_expression = static_cast<SwiftUserExpression *>(
&m_expr); // this is the only thing that has a materializer
if (is_result || is_error) {
needs_init = true;
Status error;
if (repl) {
if (swift::TypeBase *swift_type =
(swift::TypeBase *)variable.GetType().GetOpaqueQualType()) {
if (!swift_type->getCanonicalType()->isVoid()) {
if (is_result)
offset = llvm::cast<SwiftREPLMaterializer>(materializer)
->AddREPLResultVariable(
variable.GetType(), variable.GetDecl(),
&user_expression->GetResultDelegate(), error);
else
offset = llvm::cast<SwiftREPLMaterializer>(materializer)
->AddREPLResultVariable(
variable.GetType(), variable.GetDecl(),
&user_expression->GetErrorDelegate(), error);
}
}
} else {
CompilerType actual_type(variable.GetType());
if (Flags(actual_type.GetTypeInfo())
.AllSet(lldb::eTypeIsSwift | lldb::eTypeIsArchetype)) {
lldb::StackFrameSP stack_frame_sp = m_stack_frame_wp.lock();
if (stack_frame_sp && stack_frame_sp->GetThread() &&
stack_frame_sp->GetThread()->GetProcess()) {
SwiftLanguageRuntime *swift_runtime =
stack_frame_sp->GetThread()
->GetProcess()
->GetSwiftLanguageRuntime();
if (swift_runtime) {
actual_type = swift_runtime->GetConcreteType(
stack_frame_sp.get(), actual_type.GetTypeName());
if (actual_type.IsValid())
variable.SetType(actual_type);
else
actual_type = variable.GetType();
}
}
}
swift::Type actual_swift_type =
swift::Type((swift::TypeBase *)actual_type.GetOpaqueQualType());
swift::Type fixed_type = code_manipulator->FixupResultType(
actual_swift_type, user_expression->GetLanguageFlags());
if (!fixed_type.isNull()) {
actual_type = CompilerType(actual_type.GetTypeSystem(),
fixed_type.getPointer());
variable.SetType(actual_type);
}
if (is_result)
offset = materializer->AddResultVariable(
actual_type, false, true, &user_expression->GetResultDelegate(),
error);
else
offset = materializer->AddResultVariable(
actual_type, false, true, &user_expression->GetErrorDelegate(),
error);
}
if (!error.Success()) {
diagnostic_manager.Printf(eDiagnosticSeverityError,
"couldn't add %s variable to struct: %s.\n",
is_result ? "result" : "error",
error.AsCString());
return 1;
}
if (log)
log->Printf("Added %s variable to struct at offset %llu",
is_result ? "result" : "error",
(unsigned long long)offset);
} else if (variable.MetadataIs<VariableMetadataVariable>()) {
Status error;
VariableMetadataVariable *variable_metadata =
static_cast<VariableMetadataVariable *>(variable.m_metadata.get());
offset =
materializer->AddVariable(variable_metadata->m_variable_sp, error);
if (!error.Success()) {
diagnostic_manager.Printf(eDiagnosticSeverityError,
"couldn't add variable to struct: %s.\n",
error.AsCString());
return 1;
}
if (log)
log->Printf("Added variable %s to struct at offset %llu",
variable_metadata->m_variable_sp->GetName().AsCString(),
(unsigned long long)offset);
} else if (variable.MetadataIs<VariableMetadataPersistent>()) {
VariableMetadataPersistent *variable_metadata =
static_cast<VariableMetadataPersistent *>(
variable.m_metadata.get());
needs_init = llvm::cast<SwiftExpressionVariable>(
variable_metadata->m_persistent_variable_sp.get())
->m_swift_flags &
SwiftExpressionVariable::EVSNeedsInit;
Status error;
offset = materializer->AddPersistentVariable(
variable_metadata->m_persistent_variable_sp,
&user_expression->GetPersistentVariableDelegate(), error);
if (!error.Success()) {
diagnostic_manager.Printf(eDiagnosticSeverityError,
"couldn't add variable to struct: %s.\n",
error.AsCString());
return 1;
}
if (log)
log->Printf("Added persistent variable %s with flags 0x%llx to "
"struct at offset %llu",
variable_metadata->m_persistent_variable_sp->GetName()
.AsCString(),
(unsigned long long)
variable_metadata->m_persistent_variable_sp->m_flags,
(unsigned long long)offset);
}
variable_map[ConstString(variable.GetName().get()).GetCString()] =
SILVariableInfo(variable.GetType(), offset, needs_init);
}
}
std::unique_ptr<swift::SILModule> sil_module(swift::performSILGeneration(
*source_file, m_swift_ast_context->GetSILOptions()));
if (log) {
std::string s;
llvm::raw_string_ostream ss(s);
const bool verbose = false;
sil_module->print(ss, verbose, module);
ss.flush();
log->Printf("SIL module before linking:");
log->PutCString(s.c_str());
}
swift::performSILLinking(sil_module.get());
if (m_swift_ast_context->HasErrors()) {
m_swift_ast_context->PrintDiagnostics(diagnostic_manager, buffer_id,
first_line, last_line, line_offset);
return 1;
}
if (log) {
std::string s;
llvm::raw_string_ostream ss(s);
const bool verbose = false;
sil_module->print(ss, verbose, module);
ss.flush();
log->Printf("Generated SIL module:");
log->PutCString(s.c_str());
}
runSILDiagnosticPasses(*sil_module);
if (log) {
std::string s;
llvm::raw_string_ostream ss(s);
const bool verbose = false;
sil_module->print(ss, verbose, module);
ss.flush();
log->Printf("SIL module after diagnostic passes:");
log->PutCString(s.c_str());
}
if (m_swift_ast_context->HasErrors()) {
m_swift_ast_context->PrintDiagnostics(diagnostic_manager, buffer_id,
first_line, last_line, line_offset);
return 1;
}
{
std::lock_guard<std::recursive_mutex> global_context_locker(
IRExecutionUnit::GetLLVMGlobalContextMutex());
m_module = swift::performIRGeneration(
m_swift_ast_context->GetIRGenOptions(), module, std::move(sil_module),
"lldb_module", swift::PrimarySpecificPaths("", mainInputFilename),
SwiftASTContext::GetGlobalLLVMContext(), llvm::ArrayRef<std::string>());
}
if (m_swift_ast_context->HasErrors()) {
m_swift_ast_context->PrintDiagnostics(diagnostic_manager, buffer_id,
first_line, last_line, line_offset);
return 1;
}
if (!m_module) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
"Couldn't IRGen expression, no additional error");
return 1;
}
if (log) {
std::string s;
llvm::raw_string_ostream ss(s);
m_module->print(ss, NULL);
ss.flush();
log->Printf("Generated IR module:");
log->PutCString(s.c_str());
}
{
std::lock_guard<std::recursive_mutex> global_context_locker(
IRExecutionUnit::GetLLVMGlobalContextMutex());
LLVMVerifyModule((LLVMOpaqueModule *)m_module.get(), LLVMReturnStatusAction,
nullptr);
}
bool fail = m_swift_ast_context->HasErrors();
if (!fail) {
// The Parse succeeded! Now put this module into the context's list of
// loaded modules,
// and copy the Decls that were globalized as part of the parse from the
// staging area in the
// external lookup object into the SwiftPersistentExpressionState.
ast_context->LoadedModules.insert(std::make_pair(module_id, module));
if (m_swift_ast_context)
m_swift_ast_context->CacheModule(module);
if (m_sc.target_sp) {
SwiftPersistentExpressionState *persistent_state =
llvm::cast<SwiftPersistentExpressionState>(
m_sc.target_sp->GetPersistentExpressionStateForLanguage(
lldb::eLanguageTypeSwift));
persistent_state->CopyInSwiftPersistentDecls(
external_lookup->GetStagedDecls());
}
}
return fail ? 1 : 0;
}
static bool FindFunctionInModule(ConstString &mangled_name,
llvm::Module *module, const char *orig_name,
bool exact) {
swift::Demangle::Context demangle_ctx;
for (llvm::Module::iterator fi = module->getFunctionList().begin(),
fe = module->getFunctionList().end();
fi != fe; ++fi) {
if (exact) {
if (!fi->getName().str().compare(orig_name)) {
mangled_name.SetCString(fi->getName().str().c_str());
return true;
}
} else {
if (fi->getName().str().find(orig_name) != std::string::npos) {
mangled_name.SetCString(fi->getName().str().c_str());
return true;
}
// The new demangling is cannier about compression, so the name may
// not be in the mangled name plain. Let's demangle it and see if we
// can find it in the demangled nodes.
demangle_ctx.clear();
swift::Demangle::NodePointer node_ptr = demangle_ctx.demangleSymbolAsNode(fi->getName());
if (node_ptr)
{
if (node_ptr->getKind() != swift::Demangle::Node::Kind::Global)
continue;
if (node_ptr->getNumChildren() != 1)
continue;
node_ptr = node_ptr->getFirstChild();
if (node_ptr->getKind() != swift::Demangle::Node::Kind::Function)
continue;
size_t num_children = node_ptr->getNumChildren();
for (size_t i = 0; i < num_children; i++)
{
swift::Demangle::NodePointer child_ptr = node_ptr->getChild(i);
if (child_ptr->getKind() == swift::Demangle::Node::Kind::Identifier) {
if (!child_ptr->hasText())
continue;
if(child_ptr->getText().contains(orig_name))
{
mangled_name.SetCString(fi->getName().str().c_str());
return true;
}
}
}
}
}
}
return false;
}
Status SwiftExpressionParser::PrepareForExecution(
lldb::addr_t &func_addr, lldb::addr_t &func_end,
lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx,
bool &can_interpret, ExecutionPolicy execution_policy) {
Status err;
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
if (!m_module) {
err.SetErrorString("Can't prepare a NULL module for execution");
return err;
}
const char *orig_name = nullptr;
bool exact = false;
if (m_options.GetPlaygroundTransformEnabled() || m_options.GetREPLEnabled()) {
orig_name = "main";
exact = true;
} else {
orig_name = "$__lldb_expr";
}
ConstString function_name;
if (!FindFunctionInModule(function_name, m_module.get(), orig_name, exact)) {
err.SetErrorToGenericError();
err.SetErrorStringWithFormat("Couldn't find %s() in the module", orig_name);
return err;
} else {
if (log)
log->Printf("Found function %s for %s", function_name.AsCString(),
"$__lldb_expr");
}
// Retrieve an appropriate symbol context.
SymbolContext sc;
if (lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP()) {
sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
} else if (lldb::TargetSP target_sp = exe_ctx.GetTargetSP()) {
sc.target_sp = target_sp;
}
std::vector<std::string> features;
std::unique_ptr<llvm::LLVMContext> llvm_context_up;
m_execution_unit_sp.reset(
new IRExecutionUnit(llvm_context_up,
m_module, // handed off here
function_name, exe_ctx.GetTargetSP(), sc, features));
// TODO figure out some way to work ClangExpressionDeclMap into this or do the
// equivalent
// for Swift
m_execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
execution_unit_sp = m_execution_unit_sp;
m_execution_unit_sp.reset();
return err;
}
bool SwiftExpressionParser::RewriteExpression(
DiagnosticManager &diagnostic_manager) {
// There isn't a Swift equivalent to clang::Rewriter, so we'll just use
// that...
if (!m_swift_ast_context)
return false;
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
swift::SourceManager &source_manager =
m_swift_ast_context->GetSourceManager();
const DiagnosticList &diagnostics = diagnostic_manager.Diagnostics();
size_t num_diags = diagnostics.size();
if (num_diags == 0)
return false;
clang::RewriteBuffer rewrite_buf;
llvm::StringRef text_ref(m_expr.Text());
rewrite_buf.Initialize(text_ref);
for (const Diagnostic *diag : diagnostic_manager.Diagnostics()) {
const SwiftDiagnostic *diagnostic = llvm::dyn_cast<SwiftDiagnostic>(diag);
if (!(diagnostic && diagnostic->HasFixIts()))
continue;
const SwiftDiagnostic::FixItList &fixits = diagnostic->FixIts();
std::vector<swift::CharSourceRange> source_ranges;
for (const swift::DiagnosticInfo::FixIt &fixit : fixits) {
const swift::CharSourceRange &range = fixit.getRange();
swift::SourceLoc start_loc = range.getStart();
if (!start_loc.isValid()) {
// getLocOffsetInBuffer will assert if you pass it an invalid location,
// so we have to check that first.
if (log)
log->Printf(
"SwiftExpressionParser::RewriteExpression: ignoring fixit since "
"it contains an invalid source location: %s.",
range.str().str().c_str());
return false;
}
// ReplaceText can't handle replacing the same source range more than
// once, so we have to check that
// before we proceed:
if (std::find(source_ranges.begin(), source_ranges.end(), range) !=
source_ranges.end()) {
if (log)
log->Printf(
"SwiftExpressionParser::RewriteExpression: ignoring fix-it since "
"source range appears twice: %s.\n",
range.str().str().c_str());
return false;
} else
source_ranges.push_back(range);
// ReplaceText will either assert or crash if the start_loc isn't inside
// the buffer it is said to
// reside in. That shouldn't happen, but it doesn't hurt to check before
// we call ReplaceText.
auto *Buffer = source_manager.getLLVMSourceMgr().getMemoryBuffer(
diagnostic->GetBufferID());
if (!(start_loc.getOpaquePointerValue() >= Buffer->getBuffer().begin() &&
start_loc.getOpaquePointerValue() <= Buffer->getBuffer().end())) {
if (log)
log->Printf(
"SwiftExpressionParser::RewriteExpression: ignoring fixit since "
"it contains a source location not in the specified buffer: %s.",
range.str().str().c_str());
}
unsigned offset = source_manager.getLocOffsetInBuffer(
range.getStart(), diagnostic->GetBufferID());
rewrite_buf.ReplaceText(offset, range.getByteLength(), fixit.getText());
}
}
std::string fixed_expression;
llvm::raw_string_ostream out_stream(fixed_expression);
rewrite_buf.write(out_stream);
out_stream.flush();
diagnostic_manager.SetFixedExpression(fixed_expression);
return true;
}