blob: a989c2e3394b8eba2e6fc2c3416b7cd5c5e9e6c3 [file]
//===-- SwiftPersistentExpressionState.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 "SwiftPersistentExpressionState.h"
#include "SwiftExpressionVariable.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Core/Value.h"
#include "lldb/Symbol/SwiftASTContext.h" // Needed for llvm::isa<SwiftASTContext>(...)
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
#include "swift/AST/Decl.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Pattern.h"
#include "llvm/ADT/StringMap.h"
using namespace lldb;
using namespace lldb_private;
SwiftPersistentExpressionState::SwiftPersistentExpressionState()
: lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang),
m_next_persistent_variable_id(0), m_next_persistent_error_id(0) {}
ExpressionVariableSP SwiftPersistentExpressionState::CreatePersistentVariable(
const lldb::ValueObjectSP &valobj_sp) {
return AddNewlyConstructedVariable(new SwiftExpressionVariable(valobj_sp));
}
ExpressionVariableSP SwiftPersistentExpressionState::CreatePersistentVariable(
ExecutionContextScope *exe_scope, const ConstString &name,
const CompilerType &compiler_type, lldb::ByteOrder byte_order,
uint32_t addr_byte_size) {
return AddNewlyConstructedVariable(new SwiftExpressionVariable(
exe_scope, name, compiler_type, byte_order, addr_byte_size));
}
void SwiftPersistentExpressionState::RemovePersistentVariable(
lldb::ExpressionVariableSP variable) {
if (!variable)
return;
RemoveVariable(variable);
const char *name = variable->GetName().AsCString();
if (*name != '$')
return;
name++;
bool is_error = false;
switch (*name) {
case 'R':
break;
case 'E':
is_error = true;
break;
default:
return;
}
name++;
uint32_t value = strtoul(name, NULL, 0);
if (is_error) {
if (value == m_next_persistent_error_id - 1)
m_next_persistent_error_id--;
} else {
if (value == m_next_persistent_variable_id - 1)
m_next_persistent_variable_id--;
}
}
ConstString
SwiftPersistentExpressionState::GetNextPersistentVariableName(bool is_error) {
char name_cstr[256];
const char *prefix = nullptr;
if (is_error)
prefix = "$E";
else
prefix = "$R";
::snprintf(name_cstr, sizeof(name_cstr), "%s%u", prefix,
is_error ? m_next_persistent_error_id++
: m_next_persistent_variable_id++);
ConstString name(name_cstr);
return name;
}
bool SwiftPersistentExpressionState::SwiftDeclMap::DeclsAreEquivalent(
swift::Decl *lhs_decl, swift::Decl *rhs_decl) {
swift::DeclKind lhs_kind = lhs_decl->getKind();
swift::DeclKind rhs_kind = rhs_decl->getKind();
if (lhs_kind != rhs_kind)
return false;
bool equivalent = false;
switch (lhs_kind) {
// All the decls that define types of things should only allow one
// instance, so in this case, erase what is there, and copy in the new
// version.
case swift::DeclKind::Class:
case swift::DeclKind::Struct:
case swift::DeclKind::Enum:
case swift::DeclKind::TypeAlias:
case swift::DeclKind::Protocol:
equivalent = true;
break;
// For functions, we check that the signature is the same, and only replace it
// if it
// is, otherwise we just add it.
case swift::DeclKind::Func: {
swift::FuncDecl *lhs_func_decl = llvm::cast<swift::FuncDecl>(lhs_decl);
swift::FuncDecl *rhs_func_decl = llvm::cast<swift::FuncDecl>(rhs_decl);
// Okay, they have the same number of arguments, are they of the same type?
auto lhs_patterns = lhs_func_decl->getParameterLists();
auto rhs_patterns = rhs_func_decl->getParameterLists();
size_t num_patterns = lhs_patterns.size();
bool body_params_equal = true;
if (num_patterns == rhs_patterns.size()) {
auto &context = lhs_func_decl->getASTContext();
for (int idx = 0; idx < num_patterns; idx++) {
auto *lhs_param = lhs_patterns[idx];
auto *rhs_param = rhs_patterns[idx];
auto lhs_type = lhs_param->getInterfaceType(context);
auto rhs_type = rhs_param->getInterfaceType(context);
if (!lhs_type->isEqual(rhs_type)) {
body_params_equal = false;
break;
}
}
if (body_params_equal) {
// The bodies look the same, now try the return values:
auto lhs_result_type = lhs_func_decl->getResultInterfaceType();
auto rhs_result_type = rhs_func_decl->getResultInterfaceType();
if (lhs_result_type->isEqual(rhs_result_type)) {
equivalent = true;
}
}
}
} break;
// Not really sure how to compare operators, so we just do last one wins...
case swift::DeclKind::InfixOperator:
case swift::DeclKind::PrefixOperator:
case swift::DeclKind::PostfixOperator:
equivalent = true;
break;
default:
equivalent = true;
break;
}
return equivalent;
}
void SwiftPersistentExpressionState::SwiftDeclMap::AddDecl(
swift::ValueDecl *value_decl, bool check_existing,
const ConstString &alias) {
std::string name_str;
if (alias.IsEmpty()) {
name_str = (value_decl->getBaseName().getIdentifier().str());
} else {
name_str.assign(alias.GetCString());
}
if (!check_existing) {
m_swift_decls.insert(std::make_pair(name_str, value_decl));
return;
}
SwiftDeclMapTy::iterator map_end = m_swift_decls.end();
std::pair<SwiftDeclMapTy::iterator, SwiftDeclMapTy::iterator> found_range =
m_swift_decls.equal_range(name_str);
if (found_range.first == map_end) {
m_swift_decls.insert(std::make_pair(name_str, value_decl));
return;
} else {
SwiftDeclMapTy::iterator cur_item;
bool done = false;
for (cur_item = found_range.first; !done && cur_item != found_range.second;
cur_item++) {
swift::ValueDecl *cur_decl = (*cur_item).second;
if (DeclsAreEquivalent(cur_decl, value_decl)) {
m_swift_decls.erase(cur_item);
break;
}
}
m_swift_decls.insert(std::make_pair(name_str, value_decl));
}
}
bool SwiftPersistentExpressionState::SwiftDeclMap::FindMatchingDecls(
const ConstString &name, std::vector<swift::ValueDecl *> &matches) {
std::vector<swift::ValueDecl *> found_elements;
size_t start_num_items = matches.size();
std::string name_str(name.AsCString());
std::pair<SwiftDeclMapTy::iterator, SwiftDeclMapTy::iterator> found_range =
m_swift_decls.equal_range(name_str);
for (SwiftDeclMapTy::iterator cur_item = found_range.first;
cur_item != found_range.second; cur_item++) {
bool add_it = true;
swift::ValueDecl *cur_decl = (*cur_item).second;
for (size_t idx = 0; idx < start_num_items; idx++) {
if (DeclsAreEquivalent(matches[idx], cur_decl)) {
add_it = false;
break;
}
}
if (add_it)
matches.push_back((*cur_item).second);
}
return start_num_items != matches.size();
}
void SwiftPersistentExpressionState::SwiftDeclMap::CopyDeclsTo(
SwiftPersistentExpressionState::SwiftDeclMap &target_map) {
for (auto elem : m_swift_decls)
target_map.AddDecl(elem.second, true, ConstString());
}
void SwiftPersistentExpressionState::RegisterSwiftPersistentDecl(
swift::ValueDecl *value_decl) {
m_swift_persistent_decls.AddDecl(value_decl, true, ConstString());
}
void SwiftPersistentExpressionState::RegisterSwiftPersistentDeclAlias(
swift::ValueDecl *value_decl, const ConstString &name) {
m_swift_persistent_decls.AddDecl(value_decl, true, name);
}
void SwiftPersistentExpressionState::CopyInSwiftPersistentDecls(
SwiftPersistentExpressionState::SwiftDeclMap &target_map) {
target_map.CopyDeclsTo(m_swift_persistent_decls);
}
bool SwiftPersistentExpressionState::GetSwiftPersistentDecls(
const ConstString &name, std::vector<swift::ValueDecl *> &matches) {
return m_swift_persistent_decls.FindMatchingDecls(name, matches);
}