//===-- SwiftLanguageRuntime.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 "lldb/Target/SwiftLanguageRuntime.h"

#include <string.h>

#include "llvm/Support/raw_ostream.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"

#include "swift/ABI/MetadataValues.h"
#include "swift/ABI/System.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Module.h"
#include "swift/AST/Types.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Demangling/Demangler.h"
#include "swift/Remote/MemoryReader.h"
#include "swift/RemoteAST/RemoteAST.h"

#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Utility/Status.h"
#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/DataFormatters/StringPrinter.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionValueBoolean.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/SwiftASTContext.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ProcessStructReader.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Target/ThreadPlanStepInRange.h"
#include "lldb/Target/ThreadPlanStepOverRange.h"

#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StringLexer.h"

// FIXME: we should not need this
#include "Plugins/Language/Swift/SwiftFormatters.h"

using namespace lldb;
using namespace lldb_private;

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
SwiftLanguageRuntime::~SwiftLanguageRuntime() {}

SwiftLanguageRuntime::SwiftLanguageRuntime(Process *process)
    : LanguageRuntime(process), m_negative_cache_mutex(),
      m_SwiftNativeNSErrorISA(), m_memory_reader_sp(), m_promises_map(),
      m_resolvers_map(), m_bridged_synthetics_map(), m_box_metadata_type() {
  SetupSwiftError();
  SetupExclusivity();
}

static llvm::Optional<lldb::addr_t>
FindSymbolForSwiftObject(Target &target, const ConstString &object,
                         const SymbolType sym_type) {
  llvm::Optional<lldb::addr_t> retval;

  SymbolContextList sc_list;
  if (target.GetImages().FindSymbolsWithNameAndType(object, sym_type,
                                                    sc_list)) {
    SymbolContext SwiftObject_Class;
    if (sc_list.GetSize() == 1 &&
        sc_list.GetContextAtIndex(0, SwiftObject_Class)) {
      if (SwiftObject_Class.symbol) {
        lldb::addr_t SwiftObject_class_addr =
            SwiftObject_Class.symbol->GetAddress().GetLoadAddress(&target);
        if (SwiftObject_class_addr &&
            SwiftObject_class_addr != LLDB_INVALID_ADDRESS)
          retval = SwiftObject_class_addr;
      }
    }
  }
  return retval;
}

AppleObjCRuntimeV2 *SwiftLanguageRuntime::GetObjCRuntime() {
  if (auto objc_runtime = GetProcess()->GetObjCLanguageRuntime()) {
    if (objc_runtime->GetPluginName() ==
        AppleObjCRuntimeV2::GetPluginNameStatic())
      return (AppleObjCRuntimeV2 *)objc_runtime;
  }
  return nullptr;
}

void SwiftLanguageRuntime::SetupSwiftError() {
  Target &target(m_process->GetTarget());

  if (m_SwiftNativeNSErrorISA.hasValue())
    return;

  ConstString g_SwiftNativeNSError("_SwiftNativeNSError");

  m_SwiftNativeNSErrorISA = FindSymbolForSwiftObject(
      target, g_SwiftNativeNSError, eSymbolTypeObjCClass);
}

void SwiftLanguageRuntime::SetupExclusivity() {
  Target &target(m_process->GetTarget());

  ConstString g_disableExclusivityChecking("_swift_disableExclusivityChecking");

  m_dynamic_exclusivity_flag_addr = FindSymbolForSwiftObject(
      target, g_disableExclusivityChecking, eSymbolTypeData);

  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));

  if (log)
    log->Printf("SwiftLanguageRuntime: _swift_disableExclusivityChecking = %llu",
                m_dynamic_exclusivity_flag_addr ?
                *m_dynamic_exclusivity_flag_addr : 0);
}


void SwiftLanguageRuntime::ModulesDidLoad(const ModuleList &module_list) {}

static bool GetObjectDescription_ResultVariable(Process *process, Stream &str,
                                                ValueObject &object) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));

  StreamString expr_string;
  expr_string.Printf("Swift._DebuggerSupport.stringForPrintObject(%s)",
                     object.GetName().GetCString());

  if (log)
    log->Printf("[GetObjectDescription_ResultVariable] expression: %s",
                expr_string.GetData());

  ValueObjectSP result_sp;
  EvaluateExpressionOptions eval_options;
  eval_options.SetLanguage(lldb::eLanguageTypeSwift);
  eval_options.SetResultIsInternal(true);
  eval_options.SetGenerateDebugInfo(true);
  auto eval_result = process->GetTarget().EvaluateExpression(
      expr_string.GetData(),
      process->GetThreadList().GetSelectedThread()->GetSelectedFrame().get(),
      result_sp, eval_options);

  if (log) {
    switch (eval_result) {
    case eExpressionCompleted:
      log->Printf("[GetObjectDescription_ResultVariable] eExpressionCompleted");
      break;
    case eExpressionSetupError:
      log->Printf(
          "[GetObjectDescription_ResultVariable] eExpressionSetupError");
      break;
    case eExpressionParseError:
      log->Printf(
          "[GetObjectDescription_ResultVariable] eExpressionParseError");
      break;
    case eExpressionDiscarded:
      log->Printf("[GetObjectDescription_ResultVariable] eExpressionDiscarded");
      break;
    case eExpressionInterrupted:
      log->Printf(
          "[GetObjectDescription_ResultVariable] eExpressionInterrupted");
      break;
    case eExpressionHitBreakpoint:
      log->Printf(
          "[GetObjectDescription_ResultVariable] eExpressionHitBreakpoint");
      break;
    case eExpressionTimedOut:
      log->Printf("[GetObjectDescription_ResultVariable] eExpressionTimedOut");
      break;
    case eExpressionResultUnavailable:
      log->Printf(
          "[GetObjectDescription_ResultVariable] eExpressionResultUnavailable");
      break;
    case eExpressionStoppedForDebug:
      log->Printf(
          "[GetObjectDescription_ResultVariable] eExpressionStoppedForDebug");
      break;
    }
  }

  // sanitize the result of the expression before moving forward
  if (!result_sp) {
    if (log)
      log->Printf("[GetObjectDescription_ResultVariable] expression generated "
                  "no result");
    return false;
  }
  if (result_sp->GetError().Fail()) {
    if (log)
      log->Printf("[GetObjectDescription_ResultVariable] expression generated "
                  "error: %s",
                  result_sp->GetError().AsCString());
    return false;
  }
  if (false == result_sp->GetCompilerType().IsValid()) {
    if (log)
      log->Printf("[GetObjectDescription_ResultVariable] expression generated "
                  "invalid type");
    return false;
  }

  lldb_private::formatters::StringPrinter::ReadStringAndDumpToStreamOptions
      dump_options;
  dump_options.SetEscapeNonPrintables(false).SetQuote('\0').SetPrefixToken(
      nullptr);
  if (lldb_private::formatters::swift::String_SummaryProvider(
          *result_sp.get(), str, TypeSummaryOptions()
                                     .SetLanguage(lldb::eLanguageTypeSwift)
                                     .SetCapping(eTypeSummaryUncapped),
          dump_options)) {
    if (log)
      log->Printf("[GetObjectDescription_ResultVariable] expression completed "
                  "successfully");
    return true;
  } else {
    if (log)
      log->Printf("[GetObjectDescription_ResultVariable] expression generated "
                  "invalid string data");
    return false;
  }
}

static bool GetObjectDescription_ObjectReference(Process *process, Stream &str,
                                                 ValueObject &object) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));

  StreamString expr_string;
  expr_string.Printf("Swift._DebuggerSupport.stringForPrintObject(Swift."
                     "unsafeBitCast(0x%" PRIx64 ", to: AnyObject.self))",
                     object.GetValueAsUnsigned(0));

  if (log)
    log->Printf("[GetObjectDescription_ObjectReference] expression: %s",
                expr_string.GetData());

  ValueObjectSP result_sp;
  EvaluateExpressionOptions eval_options;
  eval_options.SetLanguage(lldb::eLanguageTypeSwift);
  eval_options.SetResultIsInternal(true);
  eval_options.SetGenerateDebugInfo(true);
  auto eval_result = process->GetTarget().EvaluateExpression(
      expr_string.GetData(),
      process->GetThreadList().GetSelectedThread()->GetSelectedFrame().get(),
      result_sp, eval_options);

  if (log) {
    switch (eval_result) {
    case eExpressionCompleted:
      log->Printf(
          "[GetObjectDescription_ObjectReference] eExpressionCompleted");
      break;
    case eExpressionSetupError:
      log->Printf(
          "[GetObjectDescription_ObjectReference] eExpressionSetupError");
      break;
    case eExpressionParseError:
      log->Printf(
          "[GetObjectDescription_ObjectReference] eExpressionParseError");
      break;
    case eExpressionDiscarded:
      log->Printf(
          "[GetObjectDescription_ObjectReference] eExpressionDiscarded");
      break;
    case eExpressionInterrupted:
      log->Printf(
          "[GetObjectDescription_ObjectReference] eExpressionInterrupted");
      break;
    case eExpressionHitBreakpoint:
      log->Printf(
          "[GetObjectDescription_ObjectReference] eExpressionHitBreakpoint");
      break;
    case eExpressionTimedOut:
      log->Printf("[GetObjectDescription_ObjectReference] eExpressionTimedOut");
      break;
    case eExpressionResultUnavailable:
      log->Printf("[GetObjectDescription_ObjectReference] "
                  "eExpressionResultUnavailable");
      break;
    case eExpressionStoppedForDebug:
      log->Printf(
          "[GetObjectDescription_ObjectReference] eExpressionStoppedForDebug");
      break;
    }
  }

  // sanitize the result of the expression before moving forward
  if (!result_sp) {
    if (log)
      log->Printf("[GetObjectDescription_ObjectReference] expression generated "
                  "no result");
    return false;
  }
  if (result_sp->GetError().Fail()) {
    if (log)
      log->Printf("[GetObjectDescription_ObjectReference] expression generated "
                  "error: %s",
                  result_sp->GetError().AsCString());
    return false;
  }
  if (false == result_sp->GetCompilerType().IsValid()) {
    if (log)
      log->Printf("[GetObjectDescription_ObjectReference] expression generated "
                  "invalid type");
    return false;
  }

  lldb_private::formatters::StringPrinter::ReadStringAndDumpToStreamOptions
      dump_options;
  dump_options.SetEscapeNonPrintables(false).SetQuote('\0').SetPrefixToken(
      nullptr);
  if (lldb_private::formatters::swift::String_SummaryProvider(
          *result_sp.get(), str, TypeSummaryOptions()
                                     .SetLanguage(lldb::eLanguageTypeSwift)
                                     .SetCapping(eTypeSummaryUncapped),
          dump_options)) {
    if (log)
      log->Printf("[GetObjectDescription_ObjectReference] expression completed "
                  "successfully");
    return true;
  } else {
    if (log)
      log->Printf("[GetObjectDescription_ObjectReference] expression generated "
                  "invalid string data");
    return false;
  }
}

static bool GetObjectDescription_ObjectCopy(Process *process, Stream &str,
                                            ValueObject &object) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));

  ValueObjectSP static_sp(object.GetStaticValue());

  CompilerType static_type(static_sp->GetCompilerType());
  if (auto non_reference_type = static_type.GetNonReferenceType())
    static_type = non_reference_type;

  Status error;

  lldb::addr_t copy_location = process->AllocateMemory(
      static_type.GetByteStride(), ePermissionsReadable | ePermissionsWritable,
      error);
  if (copy_location == LLDB_INVALID_ADDRESS) {
    if (log)
      log->Printf("[GetObjectDescription_ObjectCopy] copy_location invalid");
    return false;
  }
  CleanUp cleanup(
      [process, copy_location] { process->DeallocateMemory(copy_location); });

  DataExtractor data_extractor;
  if (0 == static_sp->GetData(data_extractor, error)) {
    if (log)
      log->Printf("[GetObjectDescription_ObjectCopy] data extraction failed");
    return false;
  }

  if (0 ==
      process->WriteMemory(copy_location, data_extractor.GetDataStart(),
                           data_extractor.GetByteSize(), error)) {
    if (log)
      log->Printf("[GetObjectDescription_ObjectCopy] memory copy failed");
    return false;
  }

  StreamString expr_string;
  expr_string.Printf("Swift._DebuggerSupport.stringForPrintObject(Swift."
                     "UnsafePointer<%s>(bitPattern: 0x%" PRIx64 ")!.pointee)",
                     static_type.GetTypeName().GetCString(), copy_location);

  if (log)
    log->Printf("[GetObjectDescription_ObjectCopy] expression: %s",
                expr_string.GetData());

  ValueObjectSP result_sp;
  EvaluateExpressionOptions eval_options;
  eval_options.SetLanguage(lldb::eLanguageTypeSwift);
  eval_options.SetResultIsInternal(true);
  eval_options.SetGenerateDebugInfo(true);
  auto eval_result = process->GetTarget().EvaluateExpression(
      expr_string.GetData(),
      process->GetThreadList().GetSelectedThread()->GetSelectedFrame().get(),
      result_sp, eval_options);

  if (log) {
    switch (eval_result) {
    case eExpressionCompleted:
      log->Printf("[GetObjectDescription_ObjectCopy] eExpressionCompleted");
      break;
    case eExpressionSetupError:
      log->Printf("[GetObjectDescription_ObjectCopy] eExpressionSetupError");
      break;
    case eExpressionParseError:
      log->Printf("[GetObjectDescription_ObjectCopy] eExpressionParseError");
      break;
    case eExpressionDiscarded:
      log->Printf("[GetObjectDescription_ObjectCopy] eExpressionDiscarded");
      break;
    case eExpressionInterrupted:
      log->Printf("[GetObjectDescription_ObjectCopy] eExpressionInterrupted");
      break;
    case eExpressionHitBreakpoint:
      log->Printf("[GetObjectDescription_ObjectCopy] eExpressionHitBreakpoint");
      break;
    case eExpressionTimedOut:
      log->Printf("[GetObjectDescription_ObjectCopy] eExpressionTimedOut");
      break;
    case eExpressionResultUnavailable:
      log->Printf(
          "[GetObjectDescription_ObjectCopy] eExpressionResultUnavailable");
      break;
    case eExpressionStoppedForDebug:
      log->Printf(
          "[GetObjectDescription_ObjectCopy] eExpressionStoppedForDebug");
      break;
    }
  }

  // sanitize the result of the expression before moving forward
  if (!result_sp) {
    if (log)
      log->Printf(
          "[GetObjectDescription_ObjectCopy] expression generated no result");

    str.Printf("expression produced no result");
    return true;
  }
  if (result_sp->GetError().Fail()) {
    if (log)
      log->Printf(
          "[GetObjectDescription_ObjectCopy] expression generated error: %s",
          result_sp->GetError().AsCString());

    str.Printf("expression produced error: %s",
               result_sp->GetError().AsCString());
    return true;
  }
  if (false == result_sp->GetCompilerType().IsValid()) {
    if (log)
      log->Printf("[GetObjectDescription_ObjectCopy] expression generated "
                  "invalid type");

    str.Printf("expression produced invalid result type");
    return true;
  }

  lldb_private::formatters::StringPrinter::ReadStringAndDumpToStreamOptions
      dump_options;
  dump_options.SetEscapeNonPrintables(false).SetQuote('\0').SetPrefixToken(
      nullptr);
  if (lldb_private::formatters::swift::String_SummaryProvider(
          *result_sp.get(), str, TypeSummaryOptions()
                                     .SetLanguage(lldb::eLanguageTypeSwift)
                                     .SetCapping(eTypeSummaryUncapped),
          dump_options)) {
    if (log)
      log->Printf("[GetObjectDescription_ObjectCopy] expression completed "
                  "successfully");
  } else {
    if (log)
      log->Printf("[GetObjectDescription_ObjectCopy] expression generated "
                  "invalid string data");

    str.Printf("expression produced unprintable string");
  }
  return true;
}

static bool IsSwiftResultVariable(const ConstString &name) {
  if (name) {
    llvm::StringRef name_sr(name.GetStringRef());
    if (name_sr.size() > 2 &&
        (name_sr.startswith("$R") || name_sr.startswith("$E")) &&
        ::isdigit(name_sr[2]))
      return true;
  }
  return false;
}

static bool IsSwiftReferenceType(ValueObject &object) {
  CompilerType object_type(object.GetCompilerType());
  if (llvm::dyn_cast_or_null<SwiftASTContext>(object_type.GetTypeSystem())) {
    Flags type_flags(object_type.GetTypeInfo());
    if (type_flags.AllSet(eTypeIsClass | eTypeHasValue |
                          eTypeInstanceIsPointer))
      return true;
  }
  return false;
}

bool SwiftLanguageRuntime::GetObjectDescription(Stream &str,
                                                ValueObject &object) {
  if (object.IsUninitializedReference()) {
    str.Printf("<uninitialized>");
    return true;
  }

  if (::IsSwiftResultVariable(object.GetName())) {
    // if this thing is a Swift expression result variable, it has two
    // properties:
    // a) its name is something we can refer to in expressions for free
    // b) its type may be something we can't actually talk about in expressions
    // so, just use the result variable's name in the expression and be done
    // with it
    StreamString probe_stream;
    if (GetObjectDescription_ResultVariable(m_process, probe_stream, object)) {
      str.Printf("%s", probe_stream.GetData());
      return true;
    }
  } else if (::IsSwiftReferenceType(object)) {
    // if this is a Swift class, it has two properties:
    // a) we do not need its type name, AnyObject is just as good
    // b) its value is something we can directly use to refer to it
    // so, just use the ValueObject's pointer-value and be done with it
    StreamString probe_stream;
    if (GetObjectDescription_ObjectReference(m_process, probe_stream, object)) {
      str.Printf("%s", probe_stream.GetData());
      return true;
    }
  }

  // in general, don't try to use the name of the ValueObject as it might end up
  // referring to the wrong thing
  return GetObjectDescription_ObjectCopy(m_process, str, object);
}

bool SwiftLanguageRuntime::GetObjectDescription(
    Stream &str, Value &value, ExecutionContextScope *exe_scope) {
  // This is only interesting to do with a ValueObject for Swift
  return false;
}

bool SwiftLanguageRuntime::IsSwiftMangledName(const char *name) {
  return swift::Demangle::isSwiftSymbol(name);
}

std::string SwiftLanguageRuntime::DemangleSymbolAsString (const char *symbol,
                                                          bool simplified) {
  if (simplified) {
    swift::Demangle::DemangleOptions options(swift::Demangle::DemangleOptions::
                                             SimplifiedUIDemangleOptions());
    return swift::Demangle::demangleSymbolAsString(
        symbol, strlen(symbol), options);
  } else
    return swift::Demangle::demangleSymbolAsString(symbol, strlen(symbol));
}

std::string SwiftLanguageRuntime::DemangleSymbolAsString (const ConstString &symbol,
                                                          bool simplified) {
  if (simplified) {
    swift::Demangle::DemangleOptions options(swift::Demangle::DemangleOptions::
                                             SimplifiedUIDemangleOptions());
    return swift::Demangle::demangleSymbolAsString(
        symbol.GetStringRef(), options);
  } else
    return swift::Demangle::demangleSymbolAsString(symbol.GetStringRef());
}

bool SwiftLanguageRuntime::IsSwiftClassName(const char *name)
{
  return swift::Demangle::isClass(name);
}

const std::string SwiftLanguageRuntime::GetCurrentMangledName(const char *mangled_name)
{
#ifndef USE_NEW_MANGLING
  return std::string(mangled_name);
#else
  //FIXME: Check if we need to cache these lookups...
  swift::Demangle::Context demangle_ctx;
  swift::Demangle::NodePointer node_ptr = demangle_ctx.demangleSymbolAsNode(mangled_name);
  if (!node_ptr)
  {
    // Sometimes this gets passed the prefix of a name, in which case we
    // won't be able to demangle it.  In that case return what was passed in.
    printf ("Couldn't get mangled name for %s.\n", mangled_name);
    return mangled_name;
  }
  else
    return swift::Demangle::mangleNode(node_ptr);
#endif
}

void SwiftLanguageRuntime::MethodName::Clear() {
  m_full.Clear();
  m_basename = llvm::StringRef();
  m_context = llvm::StringRef();
  m_arguments = llvm::StringRef();
  m_qualifiers = llvm::StringRef();
  m_template_args = llvm::StringRef();
  m_metatype_ref = llvm::StringRef();
  m_return_type = llvm::StringRef();
  m_type = eTypeInvalid;
  m_parsed = false;
  m_parse_error = false;
}

static bool StringHasAllOf(const llvm::StringRef &s, const char *which) {
  for (const char *c = which; *c != 0; c++) {
    if (s.find(*c) == llvm::StringRef::npos)
      return false;
  }
  return true;
}

static bool StringHasAnyOf(const llvm::StringRef &s,
                           std::initializer_list<const char *> which,
                           size_t &where) {
  for (const char *item : which) {
    size_t where_item = s.find(item);
    if (where_item != llvm::StringRef::npos) {
      where = where_item;
      return true;
    }
  }
  where = llvm::StringRef::npos;
  return false;
}

bool StringHasAnyOf(const llvm::StringRef &s, const char *which,
                    size_t &where) {
  for (const char *c = which; *c != 0; c++) {
    size_t where_item = s.find(*c);
    if (where_item != llvm::StringRef::npos) {
      where = where_item;
      return true;
    }
  }
  where = llvm::StringRef::npos;
  return false;
}

static bool UnpackTerminatedSubstring(const llvm::StringRef &s,
                                      const char start, const char stop,
                                      llvm::StringRef &dest) {
  size_t pos_of_start = s.find(start);
  if (pos_of_start == llvm::StringRef::npos)
    return false;
  size_t pos_of_stop = s.rfind(stop);
  if (pos_of_stop == llvm::StringRef::npos)
    return false;
  size_t token_count = 1;
  size_t idx = pos_of_start + 1;
  while (idx < s.size()) {
    if (s[idx] == start)
      ++token_count;
    if (s[idx] == stop) {
      if (token_count == 1) {
        dest = s.slice(pos_of_start, idx + 1);
        return true;
      }
    }
    idx++;
  }
  return false;
}

static bool UnpackQualifiedName(const llvm::StringRef &s, llvm::StringRef &decl,
                                llvm::StringRef &basename, bool &was_operator) {
  size_t pos_of_dot = s.rfind('.');
  if (pos_of_dot == llvm::StringRef::npos)
    return false;
  decl = s.substr(0, pos_of_dot);
  basename = s.substr(pos_of_dot + 1);
  size_t idx_of_operator;
  was_operator = StringHasAnyOf(basename, {"@infix", "@prefix", "@postfix"},
                                idx_of_operator);
  if (was_operator)
    basename = basename.substr(0, idx_of_operator - 1);
  return !decl.empty() && !basename.empty();
}

static bool ParseLocalDeclName(const swift::Demangle::NodePointer &node,
                               StreamString &identifier,
                               swift::Demangle::Node::Kind &parent_kind,
                               swift::Demangle::Node::Kind &kind) {
  swift::Demangle::Node::iterator end = node->end();
  for (swift::Demangle::Node::iterator pos = node->begin(); pos != end; ++pos) {
    swift::Demangle::NodePointer child = *pos;

    swift::Demangle::Node::Kind child_kind = child->getKind();
    switch (child_kind) {
    case swift::Demangle::Node::Kind::Number:
      break;

    default:
      if (child->hasText()) {
        identifier.PutCString(child->getText());
        return true;
      }
      break;
    }
  }
  return false;
}

static bool ParseFunction(const swift::Demangle::NodePointer &node,
                          StreamString &identifier,
                          swift::Demangle::Node::Kind &parent_kind,
                          swift::Demangle::Node::Kind &kind) {
  swift::Demangle::Node::iterator end = node->end();
  swift::Demangle::Node::iterator pos = node->begin();
  // First child is the function's scope
  parent_kind = (*pos)->getKind();
  ++pos;
  // Second child is either the type (no identifier)
  if (pos != end) {
    switch ((*pos)->getKind()) {
    case swift::Demangle::Node::Kind::Type:
      break;

    case swift::Demangle::Node::Kind::LocalDeclName:
      if (ParseLocalDeclName(*pos, identifier, parent_kind, kind))
        return true;
      else
        return false;
      break;

    default:
    case swift::Demangle::Node::Kind::InfixOperator:
    case swift::Demangle::Node::Kind::PostfixOperator:
    case swift::Demangle::Node::Kind::PrefixOperator:
    case swift::Demangle::Node::Kind::Identifier:
      if ((*pos)->hasText())
        identifier.PutCString((*pos)->getText());
      return true;
    }
  }
  return false;
}

static bool ParseGlobal(const swift::Demangle::NodePointer &node,
                        StreamString &identifier,
                        swift::Demangle::Node::Kind &parent_kind,
                        swift::Demangle::Node::Kind &kind) {
  swift::Demangle::Node::iterator end = node->end();
  for (swift::Demangle::Node::iterator pos = node->begin(); pos != end; ++pos) {
    swift::Demangle::NodePointer child = *pos;
    if (child) {
      kind = child->getKind();
      switch (child->getKind()) {
      case swift::Demangle::Node::Kind::Allocator:
        identifier.PutCString("__allocating_init");
        ParseFunction(child, identifier, parent_kind, kind);
        return true;

      case swift::Demangle::Node::Kind::Constructor:
        identifier.PutCString("init");
        ParseFunction(child, identifier, parent_kind, kind);
        return true;

      case swift::Demangle::Node::Kind::Deallocator:
        identifier.PutCString("__deallocating_deinit");
        ParseFunction(child, identifier, parent_kind, kind);
        return true;

      case swift::Demangle::Node::Kind::Destructor:
        identifier.PutCString("deinit");
        ParseFunction(child, identifier, parent_kind, kind);
        return true;

      case swift::Demangle::Node::Kind::Getter:
      case swift::Demangle::Node::Kind::Setter:
      case swift::Demangle::Node::Kind::Function:
        return ParseFunction(child, identifier, parent_kind, kind);

      // Ignore these, they decorate a function at the same level, but don't
      // contain any text
      case swift::Demangle::Node::Kind::ObjCAttribute:
        break;

      default:
        return false;
      }
    }
  }
  return false;
}

bool SwiftLanguageRuntime::MethodName::ExtractFunctionBasenameFromMangled(
    const ConstString &mangled, ConstString &basename, bool &is_method) {
  bool success = false;
  swift::Demangle::Node::Kind kind = swift::Demangle::Node::Kind::Global;
  swift::Demangle::Node::Kind parent_kind = swift::Demangle::Node::Kind::Global;
  if (mangled) {
    const char *mangled_cstr = mangled.GetCString();
    const size_t mangled_cstr_len = mangled.GetLength();

    if (mangled_cstr_len > 3) {
      llvm::StringRef mangled_ref(mangled_cstr, mangled_cstr_len);

      // Only demangle swift functions
      // This is a no-op right now for the new mangling, because you
      // have to demangle the whole name to figure this out anyway.
      // I'm leaving the test here in case we actually need to do this
      // only to functions.
      swift::Demangle::Context demangle_ctx;
      swift::Demangle::NodePointer node =
          demangle_ctx.demangleSymbolAsNode(mangled_ref);
      StreamString identifier;
      if (node) {
        switch (node->getKind()) {
        case swift::Demangle::Node::Kind::Global:
          success = ParseGlobal(node, identifier, parent_kind, kind);
          break;

        default:
          break;
        }

        if (!identifier.GetString().empty()) {
          basename = ConstString(identifier.GetString());
        }
      }
    }
  }
  if (success) {
    switch (kind) {
    case swift::Demangle::Node::Kind::Allocator:
    case swift::Demangle::Node::Kind::Constructor:
    case swift::Demangle::Node::Kind::Deallocator:
    case swift::Demangle::Node::Kind::Destructor:
      is_method = true;
      break;

    case swift::Demangle::Node::Kind::Getter:
    case swift::Demangle::Node::Kind::Setter:
      // don't handle getters and setters right now...
      return false;

    case swift::Demangle::Node::Kind::Function:
      switch (parent_kind) {
      case swift::Demangle::Node::Kind::BoundGenericClass:
      case swift::Demangle::Node::Kind::BoundGenericEnum:
      case swift::Demangle::Node::Kind::BoundGenericStructure:
      case swift::Demangle::Node::Kind::Class:
      case swift::Demangle::Node::Kind::Enum:
      case swift::Demangle::Node::Kind::Structure:
        is_method = true;
        break;

      default:
        break;
      }
      break;

    default:
      break;
    }
  }
  return success;
}

void SwiftLanguageRuntime::MethodName::Parse() {
  if (!m_parsed && m_full) {
    //        ConstString mangled;
    //        m_full.GetMangledCounterpart(mangled);
    //        printf ("\n   parsing = '%s'\n", m_full.GetCString());
    //        if (mangled)
    //            printf ("   mangled = '%s'\n", mangled.GetCString());
    m_parse_error = false;
    m_parsed = true;
    llvm::StringRef full(m_full.GetCString());
    bool was_operator = false;

    if (full.find("::") != llvm::StringRef::npos) {
      // :: is not an allowed operator in Swift (func ::(...) { fails to
      // compile)
      // but it's a very legitimate token in C++ - as a defense, reject anything
      // with a :: in it as invalid Swift
      m_parse_error = true;
      return;
    }

    if (StringHasAllOf(full, ".:()")) {
      const size_t open_paren = full.find(" (");
      llvm::StringRef funcname = full.substr(0, open_paren);
      UnpackQualifiedName(funcname, m_context, m_basename, was_operator);
      if (was_operator)
        m_type = eTypeOperator;
      // check for obvious constructor/destructor cases
      else if (m_basename.equals("__deallocating_destructor"))
        m_type = eTypeDeallocator;
      else if (m_basename.equals("__allocating_constructor"))
        m_type = eTypeAllocator;
      else if (m_basename.equals("init"))
        m_type = eTypeConstructor;
      else if (m_basename.equals("destructor"))
        m_type = eTypeDestructor;
      else
        m_type = eTypeUnknownMethod;

      const size_t idx_of_colon =
          full.find(':', open_paren == llvm::StringRef::npos ? 0 : open_paren);
      full = full.substr(idx_of_colon + 2);
      if (full.empty())
        return;
      if (full[0] == '<') {
        if (UnpackTerminatedSubstring(full, '<', '>', m_template_args)) {
          full = full.substr(m_template_args.size());
        } else {
          m_parse_error = true;
          return;
        }
      }
      if (full.empty())
        return;
      if (full[0] == '(') {
        if (UnpackTerminatedSubstring(full, '(', ')', m_metatype_ref)) {
          full = full.substr(m_template_args.size());
          if (full[0] == '<') {
            if (UnpackTerminatedSubstring(full, '<', '>', m_template_args)) {
              full = full.substr(m_template_args.size());
            } else {
              m_parse_error = true;
              return;
            }
          }
        } else {
          m_parse_error = true;
          return;
        }
      }
      if (full.empty())
        return;
      if (full[0] == '(') {
        if (UnpackTerminatedSubstring(full, '(', ')', m_arguments)) {
          full = full.substr(m_template_args.size());
        } else {
          m_parse_error = true;
          return;
        }
      }
      if (full.empty())
        return;
      size_t idx_of_ret = full.find("->");
      if (idx_of_ret == llvm::StringRef::npos) {
        full = full.substr(idx_of_ret);
        if (full.empty()) {
          m_parse_error = true;
          return;
        }
        if (full[0] == ' ')
          full = full.substr(1);
        m_return_type = full;
      }
    } else if (full.find('.') != llvm::StringRef::npos) {
      // this is probably just a full name (module.type.func)
      UnpackQualifiedName(full, m_context, m_basename, was_operator);
      if (was_operator)
        m_type = eTypeOperator;
      else
        m_type = eTypeUnknownMethod;
    } else {
      // this is most probably just a basename
      m_basename = full;
      m_type = eTypeUnknownMethod;
    }
  }
}

llvm::StringRef SwiftLanguageRuntime::MethodName::GetBasename() {
  if (!m_parsed)
    Parse();
  return m_basename;
}

const CompilerType &SwiftLanguageRuntime::GetBoxMetadataType() {
  if (m_box_metadata_type.IsValid())
    return m_box_metadata_type;

  static ConstString g_type_name("__lldb_autogen_boxmetadata");
  const bool is_packed = false;
  if (ClangASTContext *ast_ctx =
          GetProcess()->GetTarget().GetScratchClangASTContext()) {
    CompilerType voidstar =
        ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
    CompilerType uint32 = ClangASTContext::GetIntTypeFromBitSize(
        ast_ctx->getASTContext(), 32, false);

    m_box_metadata_type = ast_ctx->GetOrCreateStructForIdentifier(
        g_type_name, {{"kind", voidstar}, {"offset", uint32}}, is_packed);
  }

  return m_box_metadata_type;
}

std::shared_ptr<swift::remote::MemoryReader>
SwiftLanguageRuntime::GetMemoryReader() {
  class MemoryReader : public swift::remote::MemoryReader {
  public:
    MemoryReader(Process *p, size_t max_read_amount = 50 * 1024)
        : m_process(p) {
      lldbassert(m_process && "MemoryReader requires a valid Process");
      m_max_read_amount = max_read_amount;
    }

    virtual ~MemoryReader() = default;

    uint8_t getPointerSize() override {
      return m_process->GetAddressByteSize();
    }

    uint8_t getSizeSize() override {
      return getPointerSize(); // FIXME: sizeof(size_t)
    }

    swift::remote::RemoteAddress
    getSymbolAddress(const std::string &name) override {
      Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));

      if (name.empty())
        return swift::remote::RemoteAddress(nullptr);

      if (log)
        log->Printf("[MemoryReader] asked to retrieve address of symbol %s",
                    name.c_str());

      ConstString name_cs(name.c_str(), name.size());
      SymbolContextList sc_list;
      if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(
              name_cs, lldb::eSymbolTypeAny, sc_list)) {
        SymbolContext sym_ctx;
        // Remove undefined symbols from the list:
        size_t num_sc_matches = sc_list.GetSize();
        if (num_sc_matches > 1) {
          SymbolContextList tmp_sc_list(sc_list);
          sc_list.Clear();
          for (size_t idx = 0; idx < num_sc_matches; idx++) {
            tmp_sc_list.GetContextAtIndex(idx, sym_ctx);
            if (sym_ctx.symbol &&
                sym_ctx.symbol->GetType() != lldb::eSymbolTypeUndefined) {
                sc_list.Append(sym_ctx);
            }
          }
        }
        if (sc_list.GetSize() == 1 && sc_list.GetContextAtIndex(0, sym_ctx)) {
          if (sym_ctx.symbol) {
            auto load_addr =
                sym_ctx.symbol->GetLoadAddress(&m_process->GetTarget());
            if (log)
              log->Printf("[MemoryReader] symbol resolved to 0x%" PRIx64,
                          load_addr);
            return swift::remote::RemoteAddress(load_addr);
          }
        }
      }

      if (log)
        log->Printf("[MemoryReader] symbol resolution failed");
      return swift::remote::RemoteAddress(nullptr);
    }

    bool readBytes(swift::remote::RemoteAddress address, uint8_t *dest,
                   uint64_t size) override {
      Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));

      if (log)
        log->Printf("[MemoryReader] asked to read %" PRIu64
                    " bytes at address 0x%" PRIx64,
                    size, address.getAddressData());

      if (size > m_max_read_amount) {
        if (log)
          log->Printf(
              "[MemoryReader] memory read exceeds maximum allowed size");
        return false;
      }

      Target &target(m_process->GetTarget());
      Address addr(address.getAddressData());
      Status error;
      if (size > target.ReadMemory(addr, false, dest, size, error)) {
        if (log)
          log->Printf(
              "[MemoryReader] memory read returned fewer bytes than asked for");
        return false;
      }
      if (error.Fail()) {
        if (log)
          log->Printf("[MemoryReader] memory read returned error: %s",
                      error.AsCString());
        return false;
      }

      if (log) {
        StreamString stream;
        for (uint64_t i = 0; i < size; i++) {
          stream.PutHex8(dest[i]);
          stream.PutChar(' ');
        }
        log->Printf("[MemoryReader] memory read returned data: %s",
                    stream.GetData());
      }

      return true;
    }

    bool readString(swift::remote::RemoteAddress address,
                    std::string &dest) override {
      Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));

      if (log)
        log->Printf(
            "[MemoryReader] asked to read string data at address 0x%" PRIx64,
            address.getAddressData());

      std::vector<char> storage(m_max_read_amount, 0);
      Target &target(m_process->GetTarget());
      Address addr(address.getAddressData());
      Status error;
      target.ReadCStringFromMemory(addr, &storage[0], storage.size(), error);
      if (error.Success()) {
        dest.assign(&storage[0]);
        if (log)
          log->Printf("[MemoryReader] memory read returned data: %s",
                      dest.c_str());
        return true;
      } else {
        if (log)
          log->Printf("[MemoryReader] memory read returned error: %s",
                      error.AsCString());
        return false;
      }
    }

  private:
    Process *m_process;
    size_t m_max_read_amount;
  };

  if (!m_memory_reader_sp)
    m_memory_reader_sp.reset(new MemoryReader(GetProcess()));

  return m_memory_reader_sp;
}

SwiftASTContext *SwiftLanguageRuntime::GetScratchSwiftASTContext() {
  Status error;
  return m_process->GetTarget().GetScratchSwiftASTContext(error);
}

SwiftLanguageRuntime::MemberVariableOffsetResolver::
    MemberVariableOffsetResolver(swift::ASTContext *ast_ctx,
                                 SwiftLanguageRuntime *runtime,
                                 swift::TypeBase *type)
    : m_swift_ast(ast_ctx), m_swift_runtime(runtime), m_offsets() {
  lldbassert(m_swift_ast &&
             "MemberVariableOffsetResolver requires a swift::ASTContext");
  lldbassert(m_swift_runtime &&
             "MemberVariableOffsetResolver requires a SwiftLanguageRuntime");
  lldbassert(type && "MemberVariableOffsetResolver requires a swift::Type");
  m_swift_type = type;
  m_remote_ast.reset(new swift::remoteAST::RemoteASTContext(
      *ast_ctx, m_swift_runtime->GetMemoryReader()));
}

llvm::Optional<uint64_t>
SwiftLanguageRuntime::MemberVariableOffsetResolver::ResolveOffset(
    ValueObject *valobj, ConstString ivar_name, Status *error) {
  if (error)
    error->Clear();

  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));

  if (log)
    log->Printf(
        "[MemberVariableOffsetResolver] asked to resolve offset for ivar %s",
        ivar_name.AsCString());

  auto iter = m_offsets.find(ivar_name.AsCString()), end = m_offsets.end();
  if (iter != end)
    return iter->second;

  auto optmeta = swift::remote::RemoteAddress(nullptr);

  const swift::TypeKind type_kind = m_swift_type->getKind();
  switch (type_kind) {
  case swift::TypeKind::Class:
  case swift::TypeKind::BoundGenericClass: {
    if (log)
      log->Printf("[MemberVariableOffsetResolver] type is a class - trying to "
                  "get metadata for valueobject %s",
                  (valobj ? valobj->GetName().AsCString() : "<null>"));
    // retrieve the metadata for class types as this is where we get the maximum
    // benefit
    if (valobj) {
      lldb::addr_t value = valobj->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
      if (value == 0 || value == LLDB_INVALID_ADDRESS)
        break;
      Status error;
      lldb::addr_t meta_ptr =
          m_swift_runtime->GetProcess()->ReadPointerFromMemory(value, error);
      if (error.Fail() || meta_ptr == 0 || meta_ptr == LLDB_INVALID_ADDRESS)
        break;
      if (auto objc_runtime = m_swift_runtime->GetObjCRuntime()) {
        if (objc_runtime->GetRuntimeVersion() ==
            ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V2) {
          meta_ptr =
              ((AppleObjCRuntimeV2 *)objc_runtime)->GetPointerISA(meta_ptr);
        }
      }
      optmeta = swift::remote::RemoteAddress(meta_ptr);
    }
    if (log)
      log->Printf("[MemberVariableOffsetResolver] optmeta = 0x%" PRIx64,
                  optmeta.getAddressData());
  } break;
  default: {
    if (log)
      log->Printf("[MemberVariableOffsetResolver] type is not a class - no "
                  "metadata needed");
  } break;
  }

  swift::remoteAST::Result<uint64_t> result = m_remote_ast->getOffsetOfMember(
      m_swift_type, optmeta, ivar_name.GetStringRef());
  if (result) {
    if (log)
      log->Printf("[MemberVariableOffsetResolver] offset discovered = %" PRIu64,
                  (uint64_t)result.getValue());
    m_offsets.emplace(ivar_name.AsCString(), result.getValue());
    return result.getValue();
  } else {
    const auto &failure = result.getFailure();
    if (error)
      error->SetErrorStringWithFormat("error in resolving type offset: %s",
                                      failure.render().c_str());
    if (log)
      log->Printf("[MemberVariableOffsetResolver] failure: %s",
                  failure.render().c_str());
    return llvm::Optional<uint64_t>();
  }
}

SwiftLanguageRuntime::MetadataPromise::MetadataPromise(
    swift::ASTContext *ast_ctx, SwiftLanguageRuntime *runtime,
    lldb::addr_t location)
    : m_swift_ast(ast_ctx), m_swift_runtime(runtime),
      m_metadata_location(location) {
  lldbassert(m_swift_ast && "MetadataPromise requires a swift::ASTContext");
  lldbassert(m_swift_runtime &&
             "MetadataPromise requires a SwiftLanguageRuntime");
  m_remote_ast.reset(new swift::remoteAST::RemoteASTContext(
      *ast_ctx, m_swift_runtime->GetMemoryReader()));
}

CompilerType
SwiftLanguageRuntime::MetadataPromise::FulfillTypePromise(Status *error) {
  if (error)
    error->Clear();

  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));

  if (log)
    log->Printf("[MetadataPromise] asked to fulfill type promise at location "
                "0x%" PRIx64,
                m_metadata_location);

  if (m_compiler_type.hasValue())
    return m_compiler_type.getValue();

  swift::remoteAST::Result<swift::Type> result =
      m_remote_ast->getTypeForRemoteTypeMetadata(
          swift::remote::RemoteAddress(m_metadata_location));

  if (result) {
    m_compiler_type = CompilerType(m_swift_ast, result.getValue().getPointer());
    if (log)
      log->Printf("[MetadataPromise] result is type %s",
                  m_compiler_type->GetTypeName().AsCString());
    return m_compiler_type.getValue();
  } else {
    const auto &failure = result.getFailure();
    if (error)
      error->SetErrorStringWithFormat("error in resolving type: %s",
                                      failure.render().c_str());
    if (log)
      log->Printf("[MetadataPromise] failure: %s", failure.render().c_str());
    return (m_compiler_type = CompilerType()).getValue();
  }
}

llvm::Optional<swift::MetadataKind>
SwiftLanguageRuntime::MetadataPromise::FulfillKindPromise(Status *error) {
  if (error)
    error->Clear();

  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));

  if (log)
    log->Printf("[MetadataPromise] asked to fulfill kind promise at location "
                "0x%" PRIx64,
                m_metadata_location);

  if (m_metadata_kind.hasValue())
    return m_metadata_kind;

  swift::remoteAST::Result<swift::MetadataKind> result =
      m_remote_ast->getKindForRemoteTypeMetadata(
          swift::remote::RemoteAddress(m_metadata_location));

  if (result) {
    m_metadata_kind = result.getValue();
    if (log)
      log->Printf("[MetadataPromise] result is kind %u", result.getValue());
    return m_metadata_kind;
  } else {
    const auto &failure = result.getFailure();
    if (error)
      error->SetErrorStringWithFormat("error in resolving type: %s",
                                      failure.render().c_str());
    if (log)
      log->Printf("[MetadataPromise] failure: %s", failure.render().c_str());
    return m_metadata_kind;
  }
}

bool SwiftLanguageRuntime::MetadataPromise::IsStaticallyDetermined() {
  if (llvm::Optional<swift::MetadataKind> kind_promise = FulfillKindPromise()) {
    switch (kind_promise.getValue()) {
    case swift::MetadataKind::Class:
    case swift::MetadataKind::Existential:
    case swift::MetadataKind::ObjCClassWrapper:
      return false;
    default:
      return true;
    }
  }

  return true;
}

static inline swift::Type GetSwiftType(const CompilerType &type) {
  return swift::Type(
      reinterpret_cast<swift::TypeBase *>(type.GetOpaqueQualType()));
}

SwiftLanguageRuntime::MetadataPromiseSP
SwiftLanguageRuntime::GetMetadataPromise(lldb::addr_t addr,
                                         SwiftASTContext *swift_ast_ctx) {
  if (!swift_ast_ctx)
    swift_ast_ctx = GetScratchSwiftASTContext();

  if (!swift_ast_ctx || swift_ast_ctx->HasFatalErrors())
    return nullptr;

  if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
    return nullptr;

  if (auto objc_runtime = GetObjCRuntime()) {
    if (objc_runtime->GetRuntimeVersion() ==
        ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V2) {
      addr = ((AppleObjCRuntimeV2 *)objc_runtime)->GetPointerISA(addr);
    }
  }

  typename decltype(m_promises_map)::key_type key{
      swift_ast_ctx->GetASTContext(), addr};

  auto iter = m_promises_map.find(key), end = m_promises_map.end();
  if (iter != end)
    return iter->second;

  MetadataPromiseSP promise_sp(
      new MetadataPromise(std::get<0>(key), this, std::get<1>(key)));
  m_promises_map.emplace(key, promise_sp);
  return promise_sp;
}

SwiftLanguageRuntime::MemberVariableOffsetResolverSP
SwiftLanguageRuntime::GetMemberVariableOffsetResolver(
    CompilerType compiler_type) {
  if (!compiler_type.IsValid())
    return nullptr;

  SwiftASTContext *swift_ast_ctx =
      llvm::dyn_cast_or_null<SwiftASTContext>(compiler_type.GetTypeSystem());
  if (!swift_ast_ctx || swift_ast_ctx->HasFatalErrors())
    return nullptr;

  swift::TypeBase *swift_type = reinterpret_cast<swift::TypeBase *>(
      compiler_type.GetCanonicalType().GetOpaqueQualType());

  typename decltype(m_resolvers_map)::key_type key{
      swift_ast_ctx->GetASTContext(), swift_type};

  auto iter = m_resolvers_map.find(key), end = m_resolvers_map.end();
  if (iter != end)
    return iter->second;

  MemberVariableOffsetResolverSP resolver_sp(new MemberVariableOffsetResolver(
      std::get<0>(key), this, std::get<1>(key)));
  m_resolvers_map.emplace(key, resolver_sp);
  return resolver_sp;
}

static size_t BaseClassDepth(ValueObject &in_value) {
  ValueObject *ptr = &in_value;
  size_t depth = 0;
  while (ptr->IsBaseClass()) {
    depth++;
    ptr = ptr->GetParent();
  }
  return depth;
}

bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_Class(
    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
    TypeAndOrName &class_type_or_name, Address &address) {
  CompilerType value_type(in_value.GetCompilerType());

  AddressType address_type;
  lldb::addr_t class_metadata_ptr = in_value.GetPointerValue(&address_type);
  if (auto objc_runtime = GetObjCRuntime()) {
    if (objc_runtime->IsTaggedPointer(class_metadata_ptr)) {
      Value::ValueType value_type;
      return objc_runtime->GetDynamicTypeAndAddress(
          in_value, use_dynamic, class_type_or_name, address, value_type,
          /* allow_swift = */ true);
    }
  }
  if (class_metadata_ptr == LLDB_INVALID_ADDRESS || class_metadata_ptr == 0)
    return false;
  address.SetRawAddress(class_metadata_ptr);

  size_t base_depth = BaseClassDepth(in_value);

  lldb::addr_t class_instance_location;
  if (in_value.IsBaseClass())
    class_instance_location = in_value.GetPointerValue();
  else
    class_instance_location = in_value.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
  if (class_instance_location == LLDB_INVALID_ADDRESS)
    return false;
  Status error;
  lldb::addr_t class_metadata_location =
      m_process->ReadPointerFromMemory(class_instance_location, error);
  if (error.Fail() || class_metadata_location == 0 ||
      class_metadata_location == LLDB_INVALID_ADDRESS)
    return false;

  SwiftASTContext *swift_ast_ctx = llvm::dyn_cast_or_null<SwiftASTContext>(
      in_value.GetCompilerType().GetTypeSystem());

  MetadataPromiseSP promise_sp(
      GetMetadataPromise(class_metadata_location, swift_ast_ctx));
  if (!promise_sp)
    return false;

  CompilerType class_type(promise_sp->FulfillTypePromise());
  if (!class_type)
    return false;

  while (base_depth > 0) {
    class_type = class_type.GetDirectBaseClassAtIndex(0, nullptr);
    assert(class_type && "failed to get base class");
    base_depth--;
  }

  class_type_or_name.SetCompilerType(class_type);

  if (error.Fail())
    return false;

  return class_type_or_name.GetCompilerType().IsValid();
}

SwiftLanguageRuntime::SwiftErrorDescriptor::SwiftErrorDescriptor()
    : m_kind(Kind::eNotAnError) {}

bool SwiftLanguageRuntime::IsValidErrorValue(
    ValueObject &in_value, SwiftErrorDescriptor *out_error_descriptor) {
  // see GetDynamicTypeAndAddress_ErrorType for details

  CompilerType var_type(in_value.GetStaticValue()->GetCompilerType());
  SwiftASTContext::ProtocolInfo protocol_info;
  if (!SwiftASTContext::GetProtocolTypeInfo(var_type, protocol_info))
    return false;
  if (!protocol_info.m_is_errortype)
    return false;

  static ConstString g_instance_type_child_name("instance_type");
  ValueObjectSP instance_type_sp(
      in_value.GetStaticValue()->GetChildMemberWithName(
          g_instance_type_child_name, true));
  if (!instance_type_sp)
    return false;
  lldb::addr_t metadata_location = instance_type_sp->GetValueAsUnsigned(0);
  if (metadata_location == 0 || metadata_location == LLDB_INVALID_ADDRESS)
    return false;

  SetupSwiftError();
  if (m_SwiftNativeNSErrorISA.hasValue()) {
    if (auto objc_runtime = GetObjCRuntime()) {
      if (auto descriptor =
              objc_runtime->GetClassDescriptor(*instance_type_sp)) {
        if (descriptor->GetISA() != m_SwiftNativeNSErrorISA.getValue()) {
          // not a _SwiftNativeNSError - but statically typed as ErrorType
          // return true here
          if (out_error_descriptor) {
            *out_error_descriptor = SwiftErrorDescriptor();
            out_error_descriptor->m_kind = SwiftErrorDescriptor::Kind::eBridged;
            out_error_descriptor->m_bridged.instance_ptr_value =
                instance_type_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
          }
          return true;
        }
      }
    }
  }

  if (GetObjCRuntime()) {
    // this is a swift native error but it can be bridged to ObjC
    // so it needs to be layout compatible

    size_t ptr_size = m_process->GetAddressByteSize();
    size_t metadata_offset =
        ptr_size + 4 + (ptr_size == 8 ? 4 : 0);        // CFRuntimeBase
    metadata_offset += ptr_size + ptr_size + ptr_size; // CFIndex + 2*CFRef

    metadata_location += metadata_offset;
    Status error;
    lldb::addr_t metadata_ptr_value =
        m_process->ReadPointerFromMemory(metadata_location, error);
    if (metadata_ptr_value == 0 || metadata_ptr_value == LLDB_INVALID_ADDRESS ||
        error.Fail())
      return false;

    if (out_error_descriptor) {
      *out_error_descriptor = SwiftErrorDescriptor();
      out_error_descriptor->m_kind =
          SwiftErrorDescriptor::Kind::eSwiftBridgeableNative;
      out_error_descriptor->m_bridgeable_native.metadata_location =
          metadata_location;
      out_error_descriptor->m_bridgeable_native.metadata_ptr_value =
          metadata_ptr_value;
    }
  } else {
    // this is a swift native error and it has no way to be bridged to ObjC
    // so it adopts a more compact layout

    Status error;

    size_t ptr_size = m_process->GetAddressByteSize();
    size_t metadata_offset = 2 * ptr_size;
    metadata_location += metadata_offset;
    lldb::addr_t metadata_ptr_value =
        m_process->ReadPointerFromMemory(metadata_location, error);
    if (metadata_ptr_value == 0 || metadata_ptr_value == LLDB_INVALID_ADDRESS ||
        error.Fail())
      return false;

    lldb::addr_t witness_table_location = metadata_location + ptr_size;
    lldb::addr_t witness_table_ptr_value =
        m_process->ReadPointerFromMemory(witness_table_location, error);
    if (witness_table_ptr_value == 0 ||
        witness_table_ptr_value == LLDB_INVALID_ADDRESS || error.Fail())
      return false;

    lldb::addr_t payload_location = witness_table_location + ptr_size;

    if (out_error_descriptor) {
      *out_error_descriptor = SwiftErrorDescriptor();
      out_error_descriptor->m_kind =
          SwiftErrorDescriptor::Kind::eSwiftPureNative;
      out_error_descriptor->m_pure_native.metadata_location =
          metadata_ptr_value;
      out_error_descriptor->m_pure_native.witness_table_location =
          witness_table_ptr_value;
      out_error_descriptor->m_pure_native.payload_ptr = payload_location;
    }
  }

  return true;
}

bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_ErrorType(
    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
    TypeAndOrName &class_type_or_name, Address &address) {
  // layout of error type
  // pointer to -------> SwiftError {
  // --------------
  // CFRuntimeBase
  // CFIndex
  // CFStringRef
  // CFDictionaryRef
  // --------------
  // Metadata
  // WitnessTable
  // hashable Metadata
  // hashable WitnessTable
  // --------------
  // tail allocated actual object data *
  // }
  // * for a struct, it's the inline data
  // * for a class, it's the inline pointer-to-the-data (aka, the swift class
  // instance)
  SwiftErrorDescriptor error_descriptor;
  if (!IsValidErrorValue(in_value, &error_descriptor))
    return false;

  Status error;
  CompilerType var_type(in_value.GetStaticValue()->GetCompilerType());
  size_t ptr_size = m_process->GetAddressByteSize();
  SwiftASTContext *swift_ast_ctx =
      llvm::dyn_cast_or_null<SwiftASTContext>(var_type.GetTypeSystem());
  if (!swift_ast_ctx)
    return false;

  switch (error_descriptor.m_kind) {
  case SwiftErrorDescriptor::Kind::eNotAnError:
    return false;
  case SwiftErrorDescriptor::Kind::eSwiftBridgeableNative: {
    MetadataPromiseSP promise_sp(GetMetadataPromise(
        error_descriptor.m_bridgeable_native.metadata_ptr_value,
        swift_ast_ctx));
    if (!promise_sp)
      return false;
    error_descriptor.m_bridgeable_native.metadata_location += 4 * ptr_size;
    if (!promise_sp->IsStaticallyDetermined()) {
      // figure out the actual dynamic type via the metadata at the "isa"
      // pointer
      error_descriptor.m_bridgeable_native.metadata_location =
          m_process->ReadPointerFromMemory(
              error_descriptor.m_bridgeable_native.metadata_location, error);
      if (error_descriptor.m_bridgeable_native.metadata_location == 0 ||
          error_descriptor.m_bridgeable_native.metadata_location ==
              LLDB_INVALID_ADDRESS ||
          error.Fail())
        return false;
      error_descriptor.m_bridgeable_native.metadata_ptr_value =
          m_process->ReadPointerFromMemory(
              error_descriptor.m_bridgeable_native.metadata_location, error);
      if (error_descriptor.m_bridgeable_native.metadata_ptr_value == 0 ||
          error_descriptor.m_bridgeable_native.metadata_ptr_value ==
              LLDB_INVALID_ADDRESS ||
          error.Fail())
        return false;
      promise_sp = GetMetadataPromise(
          error_descriptor.m_bridgeable_native.metadata_ptr_value,
          swift_ast_ctx);
      if (!promise_sp || !promise_sp->FulfillTypePromise()) {
        // this could still be a random ObjC object
        if (auto objc_runtime = GetObjCRuntime()) {
          DataExtractor extractor(
              &error_descriptor.m_bridgeable_native.metadata_location,
              sizeof(error_descriptor.m_bridgeable_native.metadata_location),
              GetProcess()->GetByteOrder(), GetProcess()->GetAddressByteSize());
          ExecutionContext exe_ctx(GetProcess());
          auto scratch_ast =
              GetProcess()->GetTarget().GetScratchClangASTContext();
          if (scratch_ast) {
            auto valobj_sp = ValueObject::CreateValueObjectFromData(
                in_value.GetName().AsCString(), extractor, exe_ctx,
                scratch_ast->GetBasicType(eBasicTypeObjCID));
            if (valobj_sp) {
              Value::ValueType value_type;
              if (objc_runtime->GetDynamicTypeAndAddress(
                      *valobj_sp, use_dynamic, class_type_or_name, address,
                      value_type)) {
                address.SetLoadAddress(
                    error_descriptor.m_bridgeable_native.metadata_location,
                    &GetProcess()->GetTarget());
                if (!class_type_or_name.GetCompilerType().IsPointerType()) {
                  // the language runtimes do not return pointer-to-types when
                  // doing dynamic type resolution
                  // what usually happens is that the static type has
                  // pointer-like traits that ValueObjectDynamic
                  // then preserves in the dynamic value - since the static type
                  // here is a Swift protocol object
                  // the dynamic type won't know to pointerize. But we truly
                  // need an ObjCObjectPointer here or else
                  // type printing WILL be confused. Hence, make the pointer
                  // type ourselves if we didn't get one already
                  class_type_or_name.SetCompilerType(
                      class_type_or_name.GetCompilerType().GetPointerType());
                }
                return true;
              }
            }
          }
        }

        return false;
      }
    }

    if (!promise_sp)
      return false;
    address.SetLoadAddress(
        error_descriptor.m_bridgeable_native.metadata_location,
        &m_process->GetTarget());
    CompilerType metadata_type(promise_sp->FulfillTypePromise());
    if (metadata_type.IsValid() && error.Success()) {
      class_type_or_name.SetCompilerType(metadata_type);
      return true;
    }
  } break;
  case SwiftErrorDescriptor::Kind::eBridged: {
    if (error_descriptor.m_bridged.instance_ptr_value != 0 &&
        error_descriptor.m_bridged.instance_ptr_value != LLDB_INVALID_ADDRESS) {
      Status error_type_lookup_error;
      if (CompilerType error_type =
              swift_ast_ctx->GetNSErrorType(error_type_lookup_error)) {
        class_type_or_name.SetCompilerType(error_type);
        address.SetRawAddress(error_descriptor.m_bridged.instance_ptr_value);
        return true;
      }
    }
  } break;
  case SwiftErrorDescriptor::Kind::eSwiftPureNative: {
    Status error;
    if (MetadataPromiseSP promise_sp = GetMetadataPromise(
            error_descriptor.m_pure_native.metadata_location, swift_ast_ctx)) {
      if (promise_sp->IsStaticallyDetermined()) {
        if (CompilerType compiler_type = promise_sp->FulfillTypePromise()) {
          class_type_or_name.SetCompilerType(compiler_type);
          address.SetRawAddress(error_descriptor.m_pure_native.payload_ptr);
          return true;
        }
      } else {
        error_descriptor.m_pure_native.metadata_location =
            m_process->ReadPointerFromMemory(
                error_descriptor.m_pure_native.payload_ptr, error);
        if (error_descriptor.m_pure_native.metadata_location == 0 ||
            error_descriptor.m_pure_native.metadata_location ==
                LLDB_INVALID_ADDRESS ||
            error.Fail())
          return false;
        error_descriptor.m_pure_native.payload_ptr =
            error_descriptor.m_pure_native.metadata_location;
        error_descriptor.m_pure_native.metadata_location =
            m_process->ReadPointerFromMemory(
                error_descriptor.m_pure_native.payload_ptr, error);
        if (MetadataPromiseSP promise_sp = GetMetadataPromise(
                error_descriptor.m_pure_native.metadata_location,
                swift_ast_ctx)) {
          if (CompilerType compiler_type = promise_sp->FulfillTypePromise()) {
            class_type_or_name.SetCompilerType(compiler_type);
            address.SetRawAddress(error_descriptor.m_pure_native.payload_ptr);
            return true;
          }
        }
      }
    }
  } break;
  }

  return false;
}

bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_Protocol(
    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
    TypeAndOrName &class_type_or_name, Address &address) {
  CompilerType var_type(in_value.GetCompilerType());
  SwiftASTContext::ProtocolInfo protocol_info;
  if (!SwiftASTContext::GetProtocolTypeInfo(var_type, protocol_info))
    return false;

  if (protocol_info.m_is_errortype)
    return GetDynamicTypeAndAddress_ErrorType(in_value, use_dynamic,
                                              class_type_or_name, address);

  MetadataPromiseSP promise_sp;
  static ConstString g_instance_type_child_name("instance_type");
  ValueObjectSP instance_type_sp(
      in_value.GetStaticValue()->GetChildMemberWithName(
          g_instance_type_child_name, true));
  if (!instance_type_sp)
    return false;
  ValueObjectSP payload0_sp(
      in_value.GetStaticValue()->GetChildAtIndex(0, true));
  if (!payload0_sp)
    return false;
  // @objc protocols are automatically class-only, and there is no
  // static/dynamic to deal with
  bool is_class = protocol_info.m_is_objc || protocol_info.m_is_class_only ||
                  protocol_info.m_is_anyobject;
  if (!is_class) {
    promise_sp = GetMetadataPromise(instance_type_sp->GetValueAsUnsigned(0));
    if (!promise_sp)
      return false;
    if (promise_sp->FulfillKindPromise().hasValue() &&
        promise_sp->FulfillKindPromise().getValue() ==
            swift::MetadataKind::Class)
      is_class = true;
  }
  if (is_class) {
    if (GetDynamicTypeAndAddress_Class(*payload0_sp, use_dynamic,
                                       class_type_or_name, address))
      return true;

    // only for @objc protocols, try to fallback to the ObjC runtime as a source
    // of type information
    // this is not exactly a great solution and we need to be careful with how
    // we use the results of this
    // computation, but assuming some care, at least data formatters will work
    if (!protocol_info.m_is_objc)
      return false;
    auto objc_runtime = GetObjCRuntime();
    if (!objc_runtime)
      return false;
    auto descriptor_sp = objc_runtime->GetClassDescriptor(*payload0_sp);
    if (!descriptor_sp)
      return false;
    std::vector<clang::NamedDecl *> decls;
    DeclVendor *vendor = objc_runtime->GetDeclVendor();
    if (!vendor)
      return false;
    vendor->FindDecls(descriptor_sp->GetClassName(), true, 1, decls);
    if (decls.size() == 0)
      return false;
    CompilerType type = ClangASTContext::GetTypeForDecl(decls[0]);
    if (!type.IsValid())
      return false;

    lldb::addr_t class_metadata_ptr = payload0_sp->GetAddressOf();
    if (class_metadata_ptr == LLDB_INVALID_ADDRESS || class_metadata_ptr == 0)
      return false;
    address.SetRawAddress(class_metadata_ptr);

    class_type_or_name.SetCompilerType(type.GetPointerType());
    return class_type_or_name.GetCompilerType().IsValid();
  }

  if (promise_sp->FulfillKindPromise().hasValue() &&
      (promise_sp->FulfillKindPromise().getValue() ==
           swift::MetadataKind::Struct ||
       promise_sp->FulfillKindPromise().getValue() ==
           swift::MetadataKind::Enum ||
       promise_sp->FulfillKindPromise().getValue() ==
           swift::MetadataKind::Tuple)) {
    Status error;
    class_type_or_name.SetCompilerType(promise_sp->FulfillTypePromise());
    if (error.Fail())
      return false;
    // the choices made here affect dynamic type resolution
    // for an inline protocol object, e.g.:
    // (P) $R1 = {
    //     (Builtin.RawPointer) payload_data_0 = 0x0000000000000001
    //     (Builtin.RawPointer) payload_data_1 = 0x0000000000000002
    //     (Builtin.RawPointer) payload_data_2 = 0x0000000000000000
    //     (Builtin.RawPointer) instance_type = 0x000000010054c2f8
    //     (Builtin.RawPointer) protocol_witness_0 = 0x000000010054c100
    // }
    // pick &payload_data_0
    // for a pointed-to protocol object, e.g.:
    // (Q) $R2 = {
    //     (Builtin.RawPointer) payload_data_0 = 0x00000001006079b0
    //     (Builtin.RawPointer) payload_data_1 = 0x0000000000000000
    //     (Builtin.RawPointer) payload_data_2 = 0x0000000000000000
    //     (Builtin.RawPointer) instance_type = 0x000000010054c648
    //     (Builtin.RawPointer) protocol_witness_0 = 0x000000010054c7b0
    // }
    // pick the value of payload_data_0
    switch (SwiftASTContext::GetAllocationStrategy(
        class_type_or_name.GetCompilerType())) {
    case SwiftASTContext::TypeAllocationStrategy::eInline:
      // FIXME: we should not have to do this - but we are getting confused
      // w.r.t.
      // frozen-dried vs. live versions of objects, so hack around it for now
      if (in_value.GetValue().GetValueAddressType() == eAddressTypeHost)
        address.SetRawAddress(in_value.GetValue().GetScalar().ULongLong());
      else
        address.SetRawAddress(in_value.GetAddressOf());
      return true;
    case SwiftASTContext::TypeAllocationStrategy::ePointer:
      address.SetRawAddress(payload0_sp->GetValueAsUnsigned(0));
      return true;
    default:
      // TODO we don't know how to deal with the dynamic case quite yet
      return false;
    }
  }
  return false;
}

bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_Promise(
    ValueObject &in_value, MetadataPromiseSP promise_sp,
    lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name,
    Address &address) {
  if (!promise_sp)
    return false;

  CompilerType var_type(in_value.GetCompilerType());
  Status error;

  if (!promise_sp->FulfillKindPromise())
    return false;

  switch (promise_sp->FulfillKindPromise().getValue()) {
  case swift::MetadataKind::Class: {
    CompilerType dyn_type(promise_sp->FulfillTypePromise());
    if (!dyn_type.IsValid())
      return false;
    class_type_or_name.SetCompilerType(dyn_type);
    lldb::addr_t val_ptr_addr = in_value.GetPointerValue();
    val_ptr_addr = GetProcess()->ReadPointerFromMemory(val_ptr_addr, error);
    address.SetLoadAddress(val_ptr_addr, &m_process->GetTarget());
    return true;
  } break;
  case swift::MetadataKind::Struct:
  case swift::MetadataKind::Tuple: {
    CompilerType dyn_type(promise_sp->FulfillTypePromise());
    if (!dyn_type.IsValid())
      return false;
    class_type_or_name.SetCompilerType(dyn_type);
    lldb::addr_t val_ptr_addr = in_value.GetPointerValue();
    address.SetLoadAddress(val_ptr_addr, &m_process->GetTarget());
    return true;
  } break;
  case swift::MetadataKind::Enum: {
    CompilerType dyn_type(promise_sp->FulfillTypePromise());
    if (!dyn_type.IsValid())
      return false;
    class_type_or_name.SetCompilerType(dyn_type);
    lldb::addr_t val_ptr_addr = in_value.GetPointerValue();
    {
      auto swift_type = GetSwiftType(dyn_type);
      if (swift_type->getOptionalObjectType())
        val_ptr_addr = GetProcess()->ReadPointerFromMemory(val_ptr_addr, error);
    }
    address.SetLoadAddress(val_ptr_addr, &m_process->GetTarget());
    return true;
  } break;
  case swift::MetadataKind::Existential: {
    SwiftASTContext *swift_ast_ctx =
        llvm::dyn_cast_or_null<SwiftASTContext>(var_type.GetTypeSystem());

    CompilerType protocol_type(promise_sp->FulfillTypePromise());
    if (swift_ast_ctx->IsErrorType(protocol_type)) {
      if (swift_ast_ctx) {
        Status error;
        // the offset
        size_t ptr_size = m_process->GetAddressByteSize();
        size_t metadata_offset = ptr_size + 4 + (ptr_size == 8 ? 4 : 0);
        metadata_offset += ptr_size + ptr_size + ptr_size;
        lldb::addr_t archetype_ptr_value = in_value.GetValueAsUnsigned(0);
        lldb::addr_t base_errortype_ptr =
            m_process->ReadPointerFromMemory(archetype_ptr_value, error);
        lldb::addr_t static_metadata_ptrptr =
            base_errortype_ptr + metadata_offset;
        lldb::addr_t static_metadata_ptr =
            m_process->ReadPointerFromMemory(static_metadata_ptrptr, error);
        MetadataPromiseSP promise_sp(
            GetMetadataPromise(static_metadata_ptr, swift_ast_ctx));
        if (promise_sp) {
          lldb::addr_t load_addr = static_metadata_ptrptr + 2 * ptr_size;
          if (promise_sp->FulfillKindPromise() &&
              promise_sp->FulfillKindPromise().getValue() ==
                  swift::MetadataKind::Class) {
            load_addr = m_process->ReadPointerFromMemory(load_addr, error);
            lldb::addr_t dynamic_metadata_location =
                m_process->ReadPointerFromMemory(load_addr, error);
            promise_sp =
                GetMetadataPromise(dynamic_metadata_location, swift_ast_ctx);
          }
          CompilerType clang_type(promise_sp->FulfillTypePromise());
          if (clang_type.IsValid() && load_addr != 0 &&
              load_addr != LLDB_INVALID_ADDRESS) {
            class_type_or_name.SetCompilerType(clang_type);
            address.SetLoadAddress(load_addr, &m_process->GetTarget());
            return true;
          }
        }
      }
    } else {
      Status error;
      lldb::addr_t ptr_to_instance_type = in_value.GetValueAsUnsigned(0) +
                                          (3 * m_process->GetAddressByteSize());
      lldb::addr_t metadata_of_impl_addr =
          m_process->ReadPointerFromMemory(ptr_to_instance_type, error);
      if (error.Fail() || metadata_of_impl_addr == 0 ||
          metadata_of_impl_addr == LLDB_INVALID_ADDRESS)
        return false;
      MetadataPromiseSP promise_of_impl_sp(
          GetMetadataPromise(metadata_of_impl_addr, swift_ast_ctx));
      if (GetDynamicTypeAndAddress_Promise(in_value, promise_of_impl_sp,
                                           use_dynamic, class_type_or_name,
                                           address)) {
        lldb::addr_t load_addr = in_value.GetValueAsUnsigned(0);
        if (promise_of_impl_sp->FulfillKindPromise() &&
            promise_of_impl_sp->FulfillKindPromise().getValue() ==
                swift::MetadataKind::Class) {
          load_addr = m_process->ReadPointerFromMemory(load_addr, error);
          if (error.Fail() || load_addr == 0 ||
              load_addr == LLDB_INVALID_ADDRESS)
            return false;
        } else if (promise_of_impl_sp->FulfillKindPromise() &&
                   (promise_of_impl_sp->FulfillKindPromise().getValue() ==
                        swift::MetadataKind::Enum ||
                    promise_of_impl_sp->FulfillKindPromise().getValue() ==
                        swift::MetadataKind::Struct)) {
        } else
          lldbassert(false && "class, enum and struct are the only protocol "
                              "implementor types I know about");
        address.SetLoadAddress(load_addr, &m_process->GetTarget());
        return true;
      }
    }
  } break;
  default:
    break;
  }

  return false;
}

SwiftLanguageRuntime::MetadataPromiseSP
SwiftLanguageRuntime::GetPromiseForTypeNameAndFrame(const char *type_name,
                                                    StackFrame *frame) {
  if (!frame || !type_name || !type_name[0])
    return nullptr;

  SwiftASTContext *swift_ast_ctx = nullptr;
  const SymbolContext &sc(frame->GetSymbolContext(eSymbolContextFunction));
  if (sc.function)
    swift_ast_ctx = llvm::dyn_cast_or_null<SwiftASTContext>(
        sc.function->GetCompilerType().GetTypeSystem());

  StreamString type_metadata_ptr_var_name;
  type_metadata_ptr_var_name.Printf("$swift.type.%s", type_name);
  VariableList *var_list = frame->GetVariableList(false);
  if (!var_list)
    return nullptr;

  VariableSP var_sp(var_list->FindVariable(
      ConstString(type_metadata_ptr_var_name.GetData())));
  if (!var_sp)
    return nullptr;

  ValueObjectSP metadata_ptr_var_sp(
      frame->GetValueObjectForFrameVariable(var_sp, lldb::eNoDynamicValues));
  if (!metadata_ptr_var_sp ||
      metadata_ptr_var_sp->UpdateValueIfNeeded() == false)
    return nullptr;

  lldb::addr_t metadata_location(metadata_ptr_var_sp->GetValueAsUnsigned(0));
  if (metadata_location == 0 || metadata_location == LLDB_INVALID_ADDRESS)
    return nullptr;

  return GetMetadataPromise(metadata_location, swift_ast_ctx);
}

CompilerType
SwiftLanguageRuntime::DoArchetypeBindingForType(StackFrame &stack_frame,
                                                CompilerType base_type) {
  SwiftASTContext *ast_context =
      llvm::dyn_cast_or_null<SwiftASTContext>(base_type.GetTypeSystem());
  lldbassert(ast_context && "null AST Context");
  if (!ast_context)
    return base_type;
  if (base_type.GetTypeInfo() & lldb::eTypeIsSwift) {
    swift::Type target_swift_type(GetSwiftType(base_type));

    target_swift_type = target_swift_type.transform(
        [this, &stack_frame,
         ast_context](swift::Type candidate_type) -> swift::Type {
          if (swift::ArchetypeType *candidate_archetype =
                  llvm::dyn_cast_or_null<swift::ArchetypeType>(
                      candidate_type.getPointer())) {
            ConstString candidate_name(candidate_archetype->getFullName());

            CompilerType concrete_type = this->GetConcreteType(
                &stack_frame, candidate_name);
            Status import_error;
            CompilerType target_concrete_type =
                ast_context->ImportType(concrete_type, import_error);

            if (target_concrete_type.IsValid())
              return swift::Type(GetSwiftType(target_concrete_type));
            else
              return candidate_type;
          } else
            return candidate_type;
        });

    return CompilerType(ast_context->GetASTContext(),
                        target_swift_type.getPointer());
  }
  return base_type;
}

bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_Archetype(
    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
    TypeAndOrName &class_type_or_name, Address &address) {
  const char *type_name(in_value.GetTypeName().GetCString());
  StackFrame *frame(in_value.GetFrameSP().get());
  MetadataPromiseSP promise_sp(GetPromiseForTypeNameAndFrame(type_name, frame));
  if (!promise_sp)
    return false;
  if (!GetDynamicTypeAndAddress_Promise(in_value, promise_sp, use_dynamic,
                                        class_type_or_name, address))
    return false;
  if (promise_sp->FulfillKindPromise() &&
      promise_sp->FulfillKindPromise().getValue() ==
          swift::MetadataKind::Class) {
    // when an archetype represents a class, it will represent the static type
    // of the class
    // but the dynamic type might be different
    Status error;
    lldb::addr_t addr_of_meta = address.GetLoadAddress(&m_process->GetTarget());
    addr_of_meta = m_process->ReadPointerFromMemory(addr_of_meta, error);
    if (addr_of_meta == LLDB_INVALID_ADDRESS || addr_of_meta == 0 ||
        error.Fail())
      return true; // my gut says we should fail here, but we seemed to be on a
                   // good track before..
    MetadataPromiseSP actual_type_promise(GetMetadataPromise(addr_of_meta));
    if (actual_type_promise && actual_type_promise.get() != promise_sp.get()) {
      CompilerType static_type(class_type_or_name.GetCompilerType());
      class_type_or_name.SetCompilerType(
          actual_type_promise->FulfillTypePromise());
      if (error.Fail() ||
          class_type_or_name.GetCompilerType().IsValid() == false)
        class_type_or_name.SetCompilerType(static_type);
    }
  }
  return true;
}

bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_Tuple(
    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
    TypeAndOrName &class_type_or_name, Address &address) {
  std::vector<CompilerType> dyn_types;

  for (size_t idx = 0; idx < in_value.GetNumChildren(); idx++) {
    ValueObjectSP child_sp(in_value.GetChildAtIndex(idx, true));
    TypeAndOrName type_and_or_name;
    Address address;
    Value::ValueType value_type;
    if (GetDynamicTypeAndAddress(*child_sp.get(), use_dynamic, type_and_or_name,
                                 address, value_type) == false)
      dyn_types.push_back(child_sp->GetCompilerType());
    else
      dyn_types.push_back(type_and_or_name.GetCompilerType());
  }

  SwiftASTContext *swift_ast_ctx = llvm::dyn_cast_or_null<SwiftASTContext>(
      in_value.GetCompilerType().GetTypeSystem());

  CompilerType dyn_tuple_type(swift_ast_ctx->CreateTupleType(dyn_types));

  class_type_or_name.SetCompilerType(dyn_tuple_type);
  lldb::addr_t tuple_address = in_value.GetPointerValue();
  Status error;
  tuple_address = m_process->ReadPointerFromMemory(tuple_address, error);
  if (error.Fail() || tuple_address == 0 ||
      tuple_address == LLDB_INVALID_ADDRESS)
    return false;

  address.SetLoadAddress(tuple_address, in_value.GetTargetSP().get());

  return true;
}

bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_Struct(
    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
    TypeAndOrName &class_type_or_name, Address &address) {
  // struct can't inherit from each other, but they can be generic, in which
  // case
  // we need to turn MyStruct<U> into MyStruct<$swift.type.U>
  std::vector<CompilerType> generic_args;

  lldb_private::StackFrame *frame =
      in_value.GetExecutionContextRef().GetFrameSP().get();

  if (!frame)
    return false;

  // this will be a BoundGenericStruct, bound to archetypes
  CompilerType struct_type(in_value.GetCompilerType());
  CompilerType resolved_type(DoArchetypeBindingForType(*frame, struct_type));
  if (!resolved_type)
    return false;

  class_type_or_name.SetCompilerType(resolved_type);

  lldb::addr_t struct_address = in_value.GetPointerValue();
  if (0 == struct_address || LLDB_INVALID_ADDRESS == struct_address)
    struct_address = in_value.GetAddressOf(true, nullptr);
  if (0 == struct_address || LLDB_INVALID_ADDRESS == struct_address) {
    if (false == SwiftASTContext::IsPossibleZeroSizeType(
                     class_type_or_name.GetCompilerType()))
      return false;
  }

  address.SetLoadAddress(struct_address, in_value.GetTargetSP().get());
  return true;
}

bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_Enum(
    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
    TypeAndOrName &class_type_or_name, Address &address) {
  // enums can't inherit from each other, but they can be generic, in which case
  // we need to turn MyEnum<U> into MyEnum<$swift.type.U>
  std::vector<CompilerType> generic_args;

  lldb_private::StackFrame *frame =
      in_value.GetExecutionContextRef().GetFrameSP().get();

  if (!frame)
    return false;

  // this will be a BoundGenericEnum, bound to archetypes
  CompilerType enum_type(in_value.GetCompilerType());
  CompilerType resolved_type(DoArchetypeBindingForType(*frame, enum_type));
  if (!resolved_type)
    return false;

  class_type_or_name.SetCompilerType(resolved_type);

  lldb::addr_t enum_address = in_value.GetPointerValue();
  if (0 == enum_address || LLDB_INVALID_ADDRESS == enum_address)
    enum_address = in_value.GetAddressOf(true, nullptr);
  if (0 == enum_address || LLDB_INVALID_ADDRESS == enum_address) {
    if (false == SwiftASTContext::IsPossibleZeroSizeType(
                     class_type_or_name.GetCompilerType()))
      return false;
  }

  address.SetLoadAddress(enum_address, in_value.GetTargetSP().get());
  return true;
}

bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_IndirectEnumCase(
    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
    TypeAndOrName &class_type_or_name, Address &address) {
  static ConstString g_offset("offset");

  DataExtractor data;
  Status error;
  if (in_value.GetParent() && in_value.GetParent()->GetData(data, error) &&
      error.Success()) {
    bool has_payload;
    bool is_indirect;
    CompilerType payload_type;
    if (SwiftASTContext::GetSelectedEnumCase(
            in_value.GetParent()->GetCompilerType(), data, nullptr,
            &has_payload, &payload_type, &is_indirect)) {
      if (has_payload && is_indirect && payload_type)
        class_type_or_name.SetCompilerType(payload_type);
      lldb::addr_t box_addr = in_value.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
      if (box_addr != LLDB_INVALID_ADDRESS) {
        box_addr = MaskMaybeBridgedPointer(box_addr);
        lldb::addr_t box_location =
            m_process->ReadPointerFromMemory(box_addr, error);
        if (box_location != LLDB_INVALID_ADDRESS) {
          box_location = MaskMaybeBridgedPointer(box_location);
          ProcessStructReader reader(m_process, box_location,
                                     GetBoxMetadataType());
          uint32_t offset = reader.GetField<uint32_t>(g_offset);
          lldb::addr_t box_value = box_addr + offset;

          // try to read one byte at the box value
          m_process->ReadUnsignedIntegerFromMemory(box_value, 1, 0, error);
          if (error
                  .Fail()) // and if that fails, then we're off in no man's land
            return false;

          Flags type_info(payload_type.GetTypeInfo());
          if (type_info.AllSet(eTypeIsSwift | eTypeIsClass)) {
            lldb::addr_t old_box_value = box_value;
            box_value = m_process->ReadPointerFromMemory(box_value, error);
            if (box_value != LLDB_INVALID_ADDRESS) {
              DataExtractor data(&box_value, m_process->GetAddressByteSize(),
                                 m_process->GetByteOrder(),
                                 m_process->GetAddressByteSize());
              ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromData(
                  "_", data, *m_process, payload_type));
              if (valobj_sp) {
                Value::ValueType value_type;
                if (GetDynamicTypeAndAddress(*valobj_sp, use_dynamic,
                                             class_type_or_name, address,
                                             value_type)) {
                  address.SetRawAddress(old_box_value);
                  return true;
                }
              }
            }
          } else if (type_info.AllSet(eTypeIsSwift | eTypeIsProtocol)) {
            SwiftASTContext::ProtocolInfo protocol_info;
            if (SwiftASTContext::GetProtocolTypeInfo(payload_type,
                                                     protocol_info)) {
              auto ptr_size = m_process->GetAddressByteSize();
              std::vector<uint8_t> buffer(
                  ptr_size * protocol_info.m_num_storage_words, 0);
              for (uint32_t idx = 0; idx < protocol_info.m_num_storage_words;
                   idx++) {
                lldb::addr_t word = m_process->ReadUnsignedIntegerFromMemory(
                    box_value + idx * ptr_size, ptr_size, 0, error);
                if (error.Fail())
                  return false;
                memcpy(&buffer[idx * ptr_size], &word, ptr_size);
              }
              DataExtractor data(&buffer[0], buffer.size(),
                                 m_process->GetByteOrder(),
                                 m_process->GetAddressByteSize());
              ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromData(
                  "_", data, *m_process, payload_type));
              if (valobj_sp) {
                Value::ValueType value_type;
                if (GetDynamicTypeAndAddress(*valobj_sp, use_dynamic,
                                             class_type_or_name, address,
                                             value_type)) {
                  address.SetRawAddress(box_value);
                  return true;
                }
              }
            }
          } else {
            // this is most likely a statically known type
            address.SetLoadAddress(box_value, &m_process->GetTarget());
            return true;
          }
        }
      }
    }
  }
  return false;
}

// Dynamic type resolution tends to want to generate scalar data - but there are
// caveats
// Per original comment here
// "Our address is the location of the dynamic type stored in memory.  It isn't
// a load address,
//  because we aren't pointing to the LOCATION that stores the pointer to us,
//  we're pointing to us..."
// See inlined comments for exceptions to this general rule.
Value::ValueType SwiftLanguageRuntime::GetValueType(
    Value::ValueType static_value_type, const CompilerType &static_type,
    const CompilerType &dynamic_type, bool is_indirect_enum_case) {
  Flags static_type_flags(static_type.GetTypeInfo());
  Flags dynamic_type_flags(dynamic_type.GetTypeInfo());

  if (dynamic_type_flags.AllSet(eTypeIsSwift)) {
    // for a protocol object where does the dynamic data live if the target
    // object is a struct? (for a class, it's easy)
    if (static_type_flags.AllSet(eTypeIsSwift | eTypeIsProtocol) &&
        dynamic_type_flags.AnySet(eTypeIsStructUnion | eTypeIsEnumeration)) {
      SwiftASTContext *swift_ast_ctx =
          llvm::dyn_cast_or_null<SwiftASTContext>(static_type.GetTypeSystem());

      if (swift_ast_ctx && swift_ast_ctx->IsErrorType(static_type)) {
        // ErrorType values are always a pointer
        return Value::eValueTypeLoadAddress;
      }

      switch (SwiftASTContext::GetAllocationStrategy(dynamic_type)) {
      case SwiftASTContext::TypeAllocationStrategy::eDynamic:
      case SwiftASTContext::TypeAllocationStrategy::eUnknown:
        break;
      case SwiftASTContext::TypeAllocationStrategy::eInline: // inline data;
                                                             // same as the
                                                             // static data
        return static_value_type;
      case SwiftASTContext::TypeAllocationStrategy::ePointer: // pointed-to; in
                                                              // the target
        return Value::eValueTypeLoadAddress;
      }
    }
    if (static_type_flags.AllSet(eTypeIsSwift | eTypeIsArchetype)) {
      // if I am handling a non-pointer Swift type obtained from an archetype,
      // then the runtime vends the location
      // of the object, not the object per se (since the object is not a pointer
      // itself, this is way easier to achieve)
      // hence, it's a load address, not a scalar containing a pointer as for
      // ObjC classes
      if (dynamic_type_flags.AllClear(eTypeIsPointer | eTypeIsReference |
                                      eTypeInstanceIsPointer))
        return Value::eValueTypeLoadAddress;
    }

    if (static_type_flags.AllSet(eTypeIsSwift | eTypeIsPointer) &&
        static_type_flags.AllClear(eTypeIsArchetype)) {
      if (is_indirect_enum_case || static_type_flags.AllClear(eTypeIsBuiltIn))
        return Value::eValueTypeLoadAddress;
    }
  }

  if (static_type_flags.AllSet(eTypeIsSwift) &&
      dynamic_type_flags.AllSet(eTypeIsSwift) &&
      dynamic_type_flags.AllClear(eTypeIsPointer | eTypeInstanceIsPointer))
    return static_value_type;
  else
    return Value::eValueTypeScalar;
}

static bool IsIndirectEnumCase(ValueObject &valobj) {
  return (valobj.GetLanguageFlags() &
          SwiftASTContext::LanguageFlags::eIsIndirectEnumCase) ==
         SwiftASTContext::LanguageFlags::eIsIndirectEnumCase;
}

bool SwiftLanguageRuntime::GetDynamicTypeAndAddress(
    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
    TypeAndOrName &class_type_or_name, Address &address,
    Value::ValueType &value_type) {
  class_type_or_name.Clear();

  if (SwiftASTContext *swift_ast = llvm::dyn_cast_or_null<SwiftASTContext>(
          in_value.GetCompilerType().GetTypeSystem())) {
    if (swift_ast->HasFatalErrors() || !swift_ast->GetClangImporter()) {
      return false;
    }
  } else {
    return false;
  }

  if (use_dynamic == lldb::eNoDynamicValues || !CouldHaveDynamicValue(in_value))
    return false;

  bool success = false;
  const bool is_indirect_enum_case = IsIndirectEnumCase(in_value);

  if (is_indirect_enum_case)
    success = GetDynamicTypeAndAddress_IndirectEnumCase(
        in_value, use_dynamic, class_type_or_name, address);
  else {
    CompilerType var_type(in_value.GetCompilerType());
    Flags type_info(var_type.GetTypeInfo());
    if (type_info.AnySet(eTypeIsSwift)) {
      if (type_info.AnySet(eTypeIsClass))
        success = GetDynamicTypeAndAddress_Class(in_value, use_dynamic,
                                                 class_type_or_name, address);
      else if (type_info.AnySet(eTypeIsEnumeration))
        success = GetDynamicTypeAndAddress_Enum(in_value, use_dynamic,
                                                class_type_or_name, address);
      else if (type_info.AnySet(eTypeIsProtocol))
        success = GetDynamicTypeAndAddress_Protocol(
            in_value, use_dynamic, class_type_or_name, address);
      else if (type_info.AnySet(eTypeIsArchetype))
        success = GetDynamicTypeAndAddress_Archetype(
            in_value, use_dynamic, class_type_or_name, address);
      else if (type_info.AnySet(eTypeIsTuple))
        success = GetDynamicTypeAndAddress_Tuple(in_value, use_dynamic,
                                                 class_type_or_name, address);
      else if (type_info.AnySet(eTypeIsStructUnion))
        success = GetDynamicTypeAndAddress_Struct(in_value, use_dynamic,
                                                  class_type_or_name, address);
      else if (type_info.AllSet(eTypeIsBuiltIn | eTypeIsPointer |
                                eTypeHasValue))
        success = GetDynamicTypeAndAddress_Class(in_value, use_dynamic,
                                                 class_type_or_name, address);
    }
  }

  if (success) {
    value_type = GetValueType(
        in_value.GetValue().GetValueType(), in_value.GetCompilerType(),
        class_type_or_name.GetCompilerType(), is_indirect_enum_case);
  }
  return success;
}

TypeAndOrName
SwiftLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
                                       ValueObject &static_value) {
  TypeAndOrName ret(type_and_or_name);
  bool should_be_made_into_ref = false;
  bool should_be_made_into_ptr = false;
  Flags type_flags(static_value.GetCompilerType().GetTypeInfo());
  Flags type_andor_name_flags(type_and_or_name.GetCompilerType().GetTypeInfo());

  // if the static type is a pointer or reference, so should the dynamic type
  // caveat: if the static type is a Swift class instance, the dynamic type
  // could either be a Swift type (no need to change anything), or an ObjC type
  // in which case it needs to be made into a pointer
  if (type_flags.AnySet(eTypeIsPointer))
    should_be_made_into_ptr =
        (type_flags.AllClear(eTypeIsArchetype | eTypeIsBuiltIn) &&
         !IsIndirectEnumCase(static_value));
  else if (type_flags.AnySet(eTypeInstanceIsPointer))
    should_be_made_into_ptr = !type_andor_name_flags.AllSet(eTypeIsSwift);
  else if (type_flags.AnySet(eTypeIsReference))
    should_be_made_into_ref = true;
  else if (type_flags.AllSet(eTypeIsSwift | eTypeIsProtocol))
    should_be_made_into_ptr =
        type_and_or_name.GetCompilerType().IsRuntimeGeneratedType() &&
        !type_and_or_name.GetCompilerType().IsPointerType();

  if (type_and_or_name.HasType()) {
    // The type will always be the type of the dynamic object.  If our parent's
    // type was a pointer,
    // then our type should be a pointer to the type of the dynamic object.  If
    // a reference, then the original type
    // should be okay...
    CompilerType orig_type = type_and_or_name.GetCompilerType();
    CompilerType corrected_type = orig_type;
    if (should_be_made_into_ptr)
      corrected_type = orig_type.GetPointerType();
    else if (should_be_made_into_ref)
      corrected_type = orig_type.GetLValueReferenceType();
    ret.SetCompilerType(corrected_type);
  } else /*if (m_dynamic_type_info.HasName())*/
  {
    // If we are here we need to adjust our dynamic type name to include the
    // correct & or * symbol
    std::string corrected_name(type_and_or_name.GetName().GetCString());
    if (should_be_made_into_ptr)
      corrected_name.append(" *");
    else if (should_be_made_into_ref)
      corrected_name.append(" &");
    // the parent type should be a correctly pointer'ed or referenc'ed type
    ret.SetCompilerType(static_value.GetCompilerType());
    ret.SetName(corrected_name.c_str());
  }
  return ret;
}

bool SwiftLanguageRuntime::IsRuntimeSupportValue(ValueObject &valobj) {
  static llvm::StringRef g_dollar_swift_type("$swift.type.");
  ConstString valobj_name(valobj.GetName());
  llvm::StringRef valobj_name_sr(valobj_name.GetStringRef());
  if (valobj_name_sr.startswith(g_dollar_swift_type))
    return true;
  static llvm::StringRef g_globalinit("globalinit_");
  static ConstString g_builtin_word("Builtin.Word");
  static ConstString g__argc("_argc");
  static ConstString g__unsafeArgv("_unsafeArgv");
  static ConstString g_dollar_error("$error");
  static ConstString g_tmp_closure("$tmpClosure");

  ConstString valobj_type_name(valobj.GetTypeName());
  if (valobj_name_sr.startswith(g_globalinit) &&
      valobj_type_name == g_builtin_word)
    return true;
  if (valobj_name == g__argc || valobj_name == g__unsafeArgv ||
      valobj_name == g_dollar_error || valobj_name == g_tmp_closure)
    return true;
  return false;
}

bool SwiftLanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
  // if (in_value.IsDynamic())
  //    return false;
  if (IsIndirectEnumCase(in_value))
    return true;
  CompilerType var_type(in_value.GetCompilerType());
  Flags var_type_flags(var_type.GetTypeInfo());
  if (var_type_flags.AllSet(eTypeIsSwift | eTypeInstanceIsPointer)) {
    // Swift class instances are actually pointers, but base class instances
    // are inlined at offset 0 in the class data. If we just let base classes
    // be dynamic, it would cause an infinite recursion. So we would usually
    // disable it
    // But if the base class is a generic type we still need to bind it, and
    // that is
    // a good job for dynamic types to perform
    if (in_value.IsBaseClass()) {
      CompilerType base_type(in_value.GetCompilerType());
      if (SwiftASTContext::IsFullyRealized(base_type))
        return false;
    }
    return true;
  }
  return var_type.IsPossibleDynamicType(nullptr, false, false, true);
}

CompilerType
SwiftLanguageRuntime::GetConcreteType(ExecutionContextScope *exe_scope,
                                      ConstString abstract_type_name) {
  if (!exe_scope)
    return CompilerType();

  StackFrame *frame(exe_scope->CalculateStackFrame().get());
  if (!frame)
    return CompilerType();

  MetadataPromiseSP promise_sp(
      GetPromiseForTypeNameAndFrame(abstract_type_name.GetCString(), frame));
  if (!promise_sp)
    return CompilerType();

  return promise_sp->FulfillTypePromise();
}

namespace {

enum class ThunkKind
{
  Unknown = 0,
  AllocatingInit,
  PartialApply,
  ObjCAttribute,
  Reabstraction,
  ProtocolConformance,
};

enum class ThunkAction
{
  Unknown = 0,
  GetThunkTarget,
  StepIntoConformance,
  StepThrough
};

}

static ThunkKind
GetThunkKind(llvm::StringRef symbol_name)
{
  swift::Demangle::Node::Kind kind;
  swift::Demangle::Context demangle_ctx;
  if (!demangle_ctx.isThunkSymbol(symbol_name))
    return ThunkKind::Unknown;

  swift::Demangle::NodePointer nodes = demangle_ctx.demangleSymbolAsNode(symbol_name);
  size_t num_global_children = nodes->getNumChildren();
  if (num_global_children == 0)
    return ThunkKind::Unknown;

  if (nodes->getKind() != swift::Demangle::Node::Kind::Global)
    return ThunkKind::Unknown;
  if (nodes->getNumChildren() == 0)
    return ThunkKind::Unknown;

  swift::Demangle::NodePointer node_ptr = nodes->getFirstChild();
  kind = node_ptr->getKind();
  switch (kind)
  {
  case swift::Demangle::Node::Kind::ObjCAttribute:
        return ThunkKind::ObjCAttribute;
    break;
  case swift::Demangle::Node::Kind::ProtocolWitness:
    if (node_ptr->getNumChildren() == 0)
      return ThunkKind::Unknown;
    if (node_ptr->getFirstChild()->getKind() 
           == swift::Demangle::Node::Kind::ProtocolConformance)
      return ThunkKind::ProtocolConformance;
    break;
  case swift::Demangle::Node::Kind::ReabstractionThunkHelper:
    return ThunkKind::Reabstraction;
  case swift::Demangle::Node::Kind::PartialApplyForwarder:
    return ThunkKind::PartialApply;
  case swift::Demangle::Node::Kind::Allocator:
    if (node_ptr->getNumChildren() == 0)
      return ThunkKind::Unknown;
    if (node_ptr->getFirstChild()->getKind() 
           == swift::Demangle::Node::Kind::Class)
      return ThunkKind::AllocatingInit;
    break;
  default:
    break;
  }

  return ThunkKind::Unknown;
}
static const char *GetThunkKindName (ThunkKind kind)
{
  switch (kind)
  {
    case ThunkKind::Unknown:
      return "Unknown";
    case ThunkKind::AllocatingInit:
      return "StepThrough";
    case ThunkKind::PartialApply:
      return "GetThunkTarget";
    case ThunkKind::ObjCAttribute:
      return "GetThunkTarget";
    case ThunkKind::Reabstraction:
      return "GetThunkTarget";
    case ThunkKind::ProtocolConformance:
      return "StepIntoConformance";
  }
}

static ThunkAction
GetThunkAction (ThunkKind kind)
{
    switch (kind)
    {
      case ThunkKind::Unknown:
        return ThunkAction::Unknown;
      case ThunkKind::AllocatingInit:
        return ThunkAction::StepThrough;
      case ThunkKind::PartialApply:
        return ThunkAction::GetThunkTarget;
      case ThunkKind::ObjCAttribute:
        return ThunkAction::GetThunkTarget;
      case ThunkKind::Reabstraction:
        return ThunkAction::StepThrough;
      case ThunkKind::ProtocolConformance:
        return ThunkAction::StepIntoConformance;
    }
}

bool SwiftLanguageRuntime::GetTargetOfPartialApply(SymbolContext &curr_sc,
                                                   ConstString &apply_name,
                                                   SymbolContext &sc) {
  if (!curr_sc.module_sp)
    return false;
    
  SymbolContextList sc_list;
  swift::Demangle::Context demangle_ctx;
  // Make sure this is a partial apply:
  
  std::string apply_target = demangle_ctx.getThunkTarget(apply_name.GetStringRef());
  if (!apply_target.empty()) {
    size_t num_symbols = curr_sc.module_sp->FindFunctions(
        ConstString(apply_target), NULL, eFunctionNameTypeFull, true, false, false, sc_list);
    if (num_symbols == 0)
      return false;
      
    CompileUnit *curr_cu = curr_sc.comp_unit;

    size_t num_found = 0;
    for (size_t i = 0; i < num_symbols; i++) {
      SymbolContext tmp_sc;
      if (sc_list.GetContextAtIndex(i, tmp_sc)) {
        if (tmp_sc.comp_unit && curr_cu && tmp_sc.comp_unit == curr_cu) {
          sc = tmp_sc;
          num_found++;
        } else if (curr_sc.module_sp == tmp_sc.module_sp) {
          sc = tmp_sc;
          num_found++;
        }
      }
    }
    if (num_found == 1)
      return true;
    else {
      sc.Clear(false);
      return false;
    }
  } else {
    return false;
  }
}

bool SwiftLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) {

  llvm::StringRef symbol_name = symbol.GetMangled().GetMangledName().GetStringRef();
  if (symbol_name.empty())
    return false;

  swift::Demangle::Context demangle_ctx;
  return demangle_ctx.isThunkSymbol(symbol_name);
}

lldb::ThreadPlanSP
SwiftLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread,
                                                   bool stop_others) {
  // Here are the trampolines we have at present.
  // 1) The thunks from protocol invocations to the call in the actual object
  // implementing the protocol.
  // 2) Thunks for going from Swift ObjC classes to their actual method
  // invocations
  // 3) Thunks that retain captured objects in closure invocations.

  ThreadPlanSP new_thread_plan_sp;

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
  StackFrameSP stack_sp = thread.GetStackFrameAtIndex(0);
  if (!stack_sp)
    return new_thread_plan_sp;

  SymbolContext sc = stack_sp->GetSymbolContext(eSymbolContextEverything);
  Symbol *symbol = sc.symbol;

  // Note, I don't really need to consult IsSymbolARuntimeThunk here, but it
  // is fast to do and
  // keeps this list and the one in IsSymbolARuntimeThunk in sync.
  if (!symbol || !IsSymbolARuntimeThunk(*symbol))
      return new_thread_plan_sp;
      
  // Only do this if you are at the beginning of the thunk function:
  lldb::addr_t cur_addr = thread.GetRegisterContext()->GetPC();
  lldb::addr_t symbol_addr = symbol->GetAddress().GetLoadAddress(
      &thread.GetProcess()->GetTarget());

  if (symbol_addr != cur_addr)
    return new_thread_plan_sp;

  Address target_address;
  ConstString symbol_mangled_name = symbol->GetMangled().GetMangledName();
  const char *symbol_name = symbol_mangled_name.AsCString();
  
  ThunkKind thunk_kind = GetThunkKind(symbol_mangled_name.GetStringRef());
  ThunkAction thunk_action = GetThunkAction(thunk_kind);
  

  switch (thunk_action)
  {
    case ThunkAction::Unknown:
      return new_thread_plan_sp;
    case ThunkAction::GetThunkTarget:
    {
      swift::Demangle::Context demangle_ctx;
      std::string thunk_target = demangle_ctx.getThunkTarget(symbol_name);
      if (thunk_target.empty())
      {
        if (log)
          log->Printf("Stepped to thunk \"%s\" (kind: %s) but could not "
                      "find the thunk target. ",
                      symbol_name,
                      GetThunkKindName(thunk_kind));
        return new_thread_plan_sp;
      }
      if (log)
        log->Printf("Stepped to thunk \"%s\" (kind: %s) stepping to target: \"%s\".",
                    symbol_name, GetThunkKindName(thunk_kind), thunk_target.c_str());

      ModuleList modules = thread.GetProcess()->GetTarget().GetImages();
      SymbolContextList sc_list;
      modules.FindFunctionSymbols(ConstString(thunk_target),
                                    eFunctionNameTypeFull, sc_list);
      if (sc_list.GetSize() == 1) {
        SymbolContext sc;
        sc_list.GetContextAtIndex(0, sc);

        if (sc.symbol)
          target_address = sc.symbol->GetAddress();
      }
    }
    break;
    case ThunkAction::StepIntoConformance:
    {
      // The TTW symbols encode the protocol conformance requirements and it
      // is possible to go to
      // the AST and get it to replay the logic that it used to determine
      // what to dispatch to.
      // But that ties us too closely to the logic of the compiler, and
      // these thunks are quite
      // simple, they just do a little retaining, and then call the correct
      // function.
      // So for simplicity's sake, I'm just going to get the base name of
      // the function
      // this protocol thunk is preparing to call, then step into through
      // the thunk, stopping if I end up
      // in a frame with that function name.

      swift::Demangle::Context demangle_ctx;
      swift::Demangle::NodePointer demangled_nodes =
          demangle_ctx.demangleSymbolAsNode(symbol_mangled_name.GetStringRef());

      // Now find the ProtocolWitness node in the demangled result.

      swift::Demangle::NodePointer witness_node = demangled_nodes;
      bool found_witness_node = false;
      while (witness_node) {
        if (witness_node->getKind() ==
            swift::Demangle::Node::Kind::ProtocolWitness) {
          found_witness_node = true;
          break;
        }
        witness_node = witness_node->getFirstChild();
      }
      if (!found_witness_node) {
        if (log)
          log->Printf("Stepped into witness thunk \"%s\" but could not "
                      "find the ProtocolWitness node in the demangled "
                      "nodes.",
                      symbol_name);
        return new_thread_plan_sp;
      }

      size_t num_children = witness_node->getNumChildren();
      if (num_children < 2) {
        if (log)
          log->Printf("Stepped into witness thunk \"%s\" but the "
                      "ProtocolWitness node doesn't have enough nodes.",
                      symbol_name);
        return new_thread_plan_sp;
      }

      swift::Demangle::NodePointer function_node =
          witness_node->getChild(1);
      if (function_node == nullptr ||
          function_node->getKind() !=
              swift::Demangle::Node::Kind::Function) {
        if (log)
          log->Printf("Stepped into witness thunk \"%s\" but could not "
                      "find the function in the ProtocolWitness node.",
                      symbol_name);
        return new_thread_plan_sp;
      }

      // Okay, now find the name of this function.
      num_children = function_node->getNumChildren();
      swift::Demangle::NodePointer name_node(nullptr);
      for (size_t i = 0; i < num_children; i++) {
        if (function_node->getChild(i)->getKind() ==
            swift::Demangle::Node::Kind::Identifier) {
          name_node = function_node->getChild(i);
          break;
        }
      }

      if (!name_node) {
        if (log)
          log->Printf("Stepped into witness thunk \"%s\" but could not "
                      "find the Function name in the function node.",
                      symbol_name);
        return new_thread_plan_sp;
      }

      std::string function_name(name_node->getText());
      if (function_name.empty()) {
        if (log)
          log->Printf("Stepped into witness thunk \"%s\" but the Function "
                      "name was empty.",
                      symbol_name);
        return new_thread_plan_sp;
      }

      // We have to get the address range of the thunk symbol, and make a
      // "step through range stepping in"
      AddressRange sym_addr_range(sc.symbol->GetAddress(),
                                  sc.symbol->GetByteSize());
      new_thread_plan_sp.reset(new ThreadPlanStepInRange(
          thread, sym_addr_range, sc, function_name.c_str(),
          eOnlyDuringStepping, eLazyBoolNo, eLazyBoolNo));
      return new_thread_plan_sp;

    }
    break;
    case ThunkAction::StepThrough:
    {
      if (log)
        log->Printf("Stepping through thunk: %s kind: %s",
                    symbol_name, GetThunkKindName(thunk_kind));
      AddressRange sym_addr_range(sc.symbol->GetAddress(),
                                  sc.symbol->GetByteSize());
      new_thread_plan_sp.reset(new ThreadPlanStepInRange(
          thread, sym_addr_range, sc, nullptr, eOnlyDuringStepping,
          eLazyBoolNo, eLazyBoolNo));
      return new_thread_plan_sp;
    }
    break;
  }
    
  if (target_address.IsValid()) {
    new_thread_plan_sp.reset(
        new ThreadPlanRunToAddress(thread, target_address, stop_others));
  }

  return new_thread_plan_sp;
}

void SwiftLanguageRuntime::FindFunctionPointersInCall(
    StackFrame &frame, std::vector<Address> &addresses, bool debug_only,
    bool resolve_thunks) {
  // Extract the mangled name from the stack frame, and realize the function
  // type in the Target's SwiftASTContext.
  // Then walk the arguments looking for function pointers.  If we find one in
  // the FIRST argument, we can fetch
  // the pointer value and return that.
  // FIXME: when we can ask swift/llvm for the location of function arguments,
  // then we can do this for all the
  // function pointer arguments we find.

  SymbolContext sc = frame.GetSymbolContext(eSymbolContextSymbol);
  if (sc.symbol) {
    Mangled mangled_name = sc.symbol->GetMangled();
    if (mangled_name.GuessLanguage() == lldb::eLanguageTypeSwift) {
      Status error;
      Target &target = frame.GetThread()->GetProcess()->GetTarget();
      SwiftASTContext *swift_ast = target.GetScratchSwiftASTContext(error);
      if (swift_ast) {
        CompilerType function_type = swift_ast->GetTypeFromMangledTypename(
            mangled_name.GetMangledName().AsCString(), error);
        if (error.Success()) {
          if (function_type.IsFunctionType()) {
            // FIXME: For now we only check the first argument since we don't
            // know how to find the values
            // of arguments further in the argument list.
            // int num_arguments = function_type.GetFunctionArgumentCount();
            // for (int i = 0; i < num_arguments; i++)

            for (int i = 0; i < 1; i++) {
              CompilerType argument_type =
                  function_type.GetFunctionArgumentTypeAtIndex(i);
              if (argument_type.IsFunctionPointerType()) {
                // We found a function pointer argument.  Try to track down its
                // value.  This is a hack
                // for now, we really should ask swift/llvm how to find the
                // argument(s) given the
                // Swift decl for this function, and then look those up in the
                // frame.

                ABISP abi_sp(frame.GetThread()->GetProcess()->GetABI());
                ValueList argument_values;
                Value input_value;
                CompilerType clang_void_ptr_type =
                    target.GetScratchClangASTContext()
                        ->GetBasicType(eBasicTypeVoid)
                        .GetPointerType();

                input_value.SetValueType(Value::eValueTypeScalar);
                input_value.SetCompilerType(clang_void_ptr_type);
                argument_values.PushValue(input_value);

                bool success = abi_sp->GetArgumentValues(
                    *(frame.GetThread().get()), argument_values);
                if (success) {
                  // Now get a pointer value from the zeroth argument.
                  Status error;
                  DataExtractor data;
                  ExecutionContext exe_ctx;
                  frame.CalculateExecutionContext(exe_ctx);
                  error = argument_values.GetValueAtIndex(0)->GetValueAsData(
                      &exe_ctx, data, 0, NULL);
                  lldb::offset_t offset = 0;
                  lldb::addr_t fn_ptr_addr = data.GetPointer(&offset);
                  Address fn_ptr_address;
                  fn_ptr_address.SetLoadAddress(fn_ptr_addr, &target);
                  // Now check to see if this has debug info:
                  bool add_it = true;

                  if (resolve_thunks) {
                    SymbolContext sc;
                    fn_ptr_address.CalculateSymbolContext(
                        &sc, eSymbolContextEverything);
                    if (sc.comp_unit && sc.symbol) {
                      ConstString symbol_name =
                          sc.symbol->GetMangled().GetMangledName();
                      if (symbol_name) {
                        SymbolContext target_context;
                        if (GetTargetOfPartialApply(sc, symbol_name,
                                                    target_context)) {
                          if (target_context.symbol)
                            fn_ptr_address =
                                target_context.symbol->GetAddress();
                          else if (target_context.function)
                            fn_ptr_address =
                                target_context.function->GetAddressRange()
                                    .GetBaseAddress();
                        }
                      }
                    }
                  }

                  if (debug_only) {
                    LineEntry line_entry;
                    fn_ptr_address.CalculateSymbolContextLineEntry(line_entry);
                    if (!line_entry.IsValid())
                      add_it = false;
                  }
                  if (add_it)
                    addresses.push_back(fn_ptr_address);
                }
              }
            }
          }
        }
      }
    }
  }
}

//------------------------------------------------------------------
// Exception breakpoint Precondition class for Swift:
//------------------------------------------------------------------
void SwiftLanguageRuntime::SwiftExceptionPrecondition::AddTypeName(
    const char *class_name) {
  m_type_names.insert(class_name);
}

void SwiftLanguageRuntime::SwiftExceptionPrecondition::AddEnumSpec(
    const char *enum_name, const char *element_name) {
  std::unordered_map<std::string, std::vector<std::string>>::value_type
      new_value(enum_name, std::vector<std::string>());
  auto result = m_enum_spec.emplace(new_value);
  result.first->second.push_back(element_name);
}

SwiftLanguageRuntime::SwiftExceptionPrecondition::SwiftExceptionPrecondition() {
}

ValueObjectSP
SwiftLanguageRuntime::CalculateErrorValueObjectFromValue(
    Value &value, ConstString name, bool persistent)
{
  ValueObjectSP error_valobj_sp;
  Status error;
  SwiftASTContext *ast_context =
      m_process->GetTarget().GetScratchSwiftASTContext(error);
  if (!ast_context || error.Fail())
    return error_valobj_sp;

  CompilerType swift_error_proto_type = ast_context->GetErrorType();
  value.SetCompilerType(swift_error_proto_type);
  
  error_valobj_sp = ValueObjectConstResult::Create(
      m_process, value, name);
  
  if (error_valobj_sp && error_valobj_sp->GetError().Success()) {
    error_valobj_sp = error_valobj_sp->GetQualifiedRepresentationIfAvailable(
        lldb::eDynamicCanRunTarget, true);
    if (!IsValidErrorValue(*(error_valobj_sp.get()))) {
      error_valobj_sp.reset();
    }
  }

  if (persistent && error_valobj_sp) {
    PersistentExpressionState *persistent_state =
        m_process->GetTarget().GetPersistentExpressionStateForLanguage(
            eLanguageTypeSwift);

    ConstString persistent_variable_name(
        persistent_state->GetNextPersistentVariableName(true));

    lldb::ValueObjectSP const_valobj_sp;

    // Check in case our value is already a constant value
    if (error_valobj_sp->GetIsConstant()) {
      const_valobj_sp = error_valobj_sp;
      const_valobj_sp->SetName(persistent_variable_name);
    } else
      const_valobj_sp =
          error_valobj_sp->CreateConstantValue(persistent_variable_name);

    lldb::ValueObjectSP live_valobj_sp = error_valobj_sp;

    error_valobj_sp = const_valobj_sp;

    ExpressionVariableSP clang_expr_variable_sp(
        persistent_state->CreatePersistentVariable(error_valobj_sp));
    clang_expr_variable_sp->m_live_sp = live_valobj_sp;
    clang_expr_variable_sp->m_flags |=
        ClangExpressionVariable::EVIsProgramReference;

    error_valobj_sp = clang_expr_variable_sp->GetValueObject();
  }
  return error_valobj_sp;
}

ValueObjectSP SwiftLanguageRuntime::CalculateErrorValueFromFirstArgument(
    StackFrameSP frame_sp, ConstString variable_name) {
  ProcessSP process_sp(frame_sp->GetThread()->GetProcess());
  ABISP abi_sp(process_sp->GetABI());
  ValueList argument_values;
  Value input_value;
  Status error;
  Target *target = frame_sp->CalculateTarget().get();
  ValueObjectSP error_valobj_sp;

  ClangASTContext *clang_ast_context = target->GetScratchClangASTContext();
  CompilerType clang_void_ptr_type =
      clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();

  input_value.SetValueType(Value::eValueTypeScalar);
  input_value.SetCompilerType(clang_void_ptr_type);
  argument_values.PushValue(input_value);

  bool success = abi_sp->GetArgumentValues(*(frame_sp->GetThread().get()),
                                           argument_values);
  if (success) {
    ExecutionContext exe_ctx;
    frame_sp->CalculateExecutionContext(exe_ctx);
    DataExtractor data;

    SwiftASTContext *ast_context = target->GetScratchSwiftASTContext(error);
    if (!ast_context || error.Fail())
      return error_valobj_sp;

    CompilerType swift_error_proto_type = ast_context->GetErrorType();
    if (swift_error_proto_type.IsValid()) {
      Value *arg0 = argument_values.GetValueAtIndex(0);
      Status extract_error = arg0->GetValueAsData(&exe_ctx, data, 0, nullptr);
      if (extract_error.Success()) {
        error_valobj_sp = ValueObjectConstResult::Create(
            frame_sp.get(), swift_error_proto_type, variable_name, data);
        if (error_valobj_sp->GetError().Fail()) {
          // If we couldn't make the error ValueObject, then we will always
          // stop.
          // FIXME: Some logging here would be good.
          return error_valobj_sp;
        }

        error_valobj_sp =
            error_valobj_sp->GetQualifiedRepresentationIfAvailable(
                lldb::eDynamicCanRunTarget, true);
      }
    }
  }
  return error_valobj_sp;
}

void SwiftLanguageRuntime::RegisterGlobalError(Target &target, ConstString name,
                                               lldb::addr_t addr) {
  Status ast_context_error;
  SwiftASTContext *ast_context =
      target.GetScratchSwiftASTContext(ast_context_error);

  if (ast_context_error.Success() && ast_context &&
      !ast_context->HasFatalErrors()) {
    SwiftPersistentExpressionState *persistent_state =
        llvm::cast<SwiftPersistentExpressionState>(
            target.GetPersistentExpressionStateForLanguage(
                lldb::eLanguageTypeSwift));

    std::string module_name = "$__lldb_module_for_";
    module_name.append(&name.GetCString()[1]);

    Status module_creation_error;
    swift::ModuleDecl *module_decl = ast_context->CreateModule(
        ConstString(module_name), module_creation_error);

    if (module_creation_error.Success() && module_decl) {
      const bool is_static = false;
      const auto specifier = swift::VarDecl::Specifier::Let;
      const bool is_capture_list = false;

      swift::VarDecl *var_decl = new (*ast_context->GetASTContext())
          swift::VarDecl(is_static, specifier, is_capture_list, swift::SourceLoc(),
                         ast_context->GetIdentifier(name.GetCString()),
                         GetSwiftType(ast_context->GetErrorType()),
                         module_decl);
      var_decl->setInterfaceType(var_decl->getType());
      var_decl->setDebuggerVar(true);

      persistent_state->RegisterSwiftPersistentDecl(var_decl);

      ConstString mangled_name;

      {
        swift::Mangle::ASTMangler mangler(true);
        mangled_name = ConstString(mangler.mangleGlobalVariableFull(var_decl));
      }

      lldb::addr_t symbol_addr;

      {
        ProcessSP process_sp(target.GetProcessSP());
        Status alloc_error;

        symbol_addr = process_sp->AllocateMemory(
            process_sp->GetAddressByteSize(),
            lldb::ePermissionsWritable | lldb::ePermissionsReadable,
            alloc_error);

        if (alloc_error.Success() && symbol_addr != LLDB_INVALID_ADDRESS) {
          Status write_error;
          process_sp->WritePointerToMemory(symbol_addr, addr, write_error);

          if (write_error.Success()) {
            persistent_state->RegisterSymbol(mangled_name, symbol_addr);
          }
        }
      }
    }
  }
}

bool SwiftLanguageRuntime::SwiftExceptionPrecondition::EvaluatePrecondition(
    StoppointCallbackContext &context) {
  if (!m_type_names.empty()) {
    StackFrameSP frame_sp = context.exe_ctx_ref.GetFrameSP();
    if (!frame_sp)
      return true;

    ValueObjectSP error_valobj_sp = CalculateErrorValueFromFirstArgument(
        frame_sp, ConstString("__swift_error_var"));
    if (!error_valobj_sp || error_valobj_sp->GetError().Fail())
      return true;

    // This shouldn't fail, since at worst it will return me the object I just
    // successfully got.
    std::string full_error_name(
        error_valobj_sp->GetCompilerType().GetTypeName().AsCString());
    size_t last_dot_pos = full_error_name.rfind('.');
    std::string type_name_base;
    if (last_dot_pos == std::string::npos)
      type_name_base = full_error_name;
    else {
      if (last_dot_pos + 1 <= full_error_name.size())
        type_name_base =
            full_error_name.substr(last_dot_pos + 1, full_error_name.size());
    }

    // The type name will be the module and then the type.  If the match name
    // has a dot, we require a complete
    // match against the type, if the type name has no dot, we match it against
    // the base.

    for (std::string name : m_type_names) {
      if (name.rfind('.') != std::string::npos) {
        if (name == full_error_name)
          return true;
      } else {
        if (name == type_name_base)
          return true;
      }
    }
    return false;
  }
  return true;
}

void SwiftLanguageRuntime::SwiftExceptionPrecondition::GetDescription(
    Stream &stream, lldb::DescriptionLevel level) {
  if (level == eDescriptionLevelFull || level == eDescriptionLevelVerbose) {
    if (m_type_names.size() > 0) {
      stream.Printf("\nType Filters:");
      for (std::string name : m_type_names) {
        stream.Printf(" %s", name.c_str());
      }
      stream.Printf("\n");
    }
  }
}

Status SwiftLanguageRuntime::SwiftExceptionPrecondition::ConfigurePrecondition(
    Args &args) {
  Status error;
  std::vector<std::string> object_typenames;
  args.GetOptionValuesAsStrings("exception-typename", object_typenames);
  for (auto type_name : object_typenames)
    AddTypeName(type_name.c_str());
  return error;
}

void SwiftLanguageRuntime::AddToLibraryNegativeCache(const char *library_name) {
  std::lock_guard<std::mutex> locker(m_negative_cache_mutex);
  m_library_negative_cache.insert(library_name);
}

bool SwiftLanguageRuntime::IsInLibraryNegativeCache(const char *library_name) {
  std::lock_guard<std::mutex> locker(m_negative_cache_mutex);
  return m_library_negative_cache.count(library_name) == 1;
}

lldb::addr_t
SwiftLanguageRuntime::MaskMaybeBridgedPointer(lldb::addr_t addr,
                                              lldb::addr_t *masked_bits) {
  if (!m_process)
    return addr;
  const ArchSpec &arch_spec(m_process->GetTarget().GetArchitecture());
  ArchSpec::Core core_kind = arch_spec.GetCore();
  bool is_arm = false;
  bool is_intel = false;
  bool is_32 = false;
  bool is_64 = false;
  if (core_kind == ArchSpec::Core::eCore_arm_arm64) {
    is_arm = is_64 = true;
  } else if (core_kind >= ArchSpec::Core::kCore_arm_first &&
             core_kind <= ArchSpec::Core::kCore_arm_last) {
    is_arm = true;
  } else if (core_kind >= ArchSpec::Core::kCore_x86_64_first &&
             core_kind <= ArchSpec::Core::kCore_x86_64_last) {
    is_intel = true;
  } else if (core_kind >= ArchSpec::Core::kCore_x86_32_first &&
             core_kind <= ArchSpec::Core::kCore_x86_32_last) {
    is_intel = true;
  } else {
    // this is a really random CPU core to be running on - just get out fast
    return addr;
  }

  switch (arch_spec.GetAddressByteSize()) {
  case 4:
    is_32 = true;
    break;
  case 8:
    is_64 = true;
    break;
  default:
    // this is a really random pointer size to be running on - just get out fast
    return addr;
  }

  lldb::addr_t mask = 0;

  if (is_arm && is_64)
    mask = SWIFT_ABI_ARM64_SWIFT_SPARE_BITS_MASK;

  if (is_arm && is_32)
    mask = SWIFT_ABI_ARM_SWIFT_SPARE_BITS_MASK;

  if (is_intel && is_64)
    mask = SWIFT_ABI_X86_64_SWIFT_SPARE_BITS_MASK;

  if (is_intel && is_32)
    mask = SWIFT_ABI_I386_SWIFT_SPARE_BITS_MASK;

  if (masked_bits)
    *masked_bits = addr & mask;
  return addr & ~mask;
}

lldb::addr_t
SwiftLanguageRuntime::MaybeMaskNonTrivialReferencePointer(
    lldb::addr_t addr,
    SwiftASTContext::NonTriviallyManagedReferenceStrategy strategy) {

  if (addr == 0)
    return addr;

  AppleObjCRuntime *objc_runtime = GetObjCRuntime();
  
  if (objc_runtime) {
    // tagged pointers don't perform any masking
    if (objc_runtime->IsTaggedPointer(addr))
      return addr;
  }

  if (!m_process)
    return addr;
  const ArchSpec &arch_spec(m_process->GetTarget().GetArchitecture());
  ArchSpec::Core core_kind = arch_spec.GetCore();
  bool is_arm = false;
  bool is_intel = false;
  bool is_32 = false;
  bool is_64 = false;
  if (core_kind == ArchSpec::Core::eCore_arm_arm64) {
    is_arm = is_64 = true;
  } else if (core_kind >= ArchSpec::Core::kCore_arm_first &&
             core_kind <= ArchSpec::Core::kCore_arm_last) {
    is_arm = true;
  } else if (core_kind >= ArchSpec::Core::kCore_x86_64_first &&
             core_kind <= ArchSpec::Core::kCore_x86_64_last) {
    is_intel = true;
  } else if (core_kind >= ArchSpec::Core::kCore_x86_32_first &&
             core_kind <= ArchSpec::Core::kCore_x86_32_last) {
    is_intel = true;
  } else {
    // this is a really random CPU core to be running on - just get out fast
    return addr;
  }

  switch (arch_spec.GetAddressByteSize()) {
  case 4:
    is_32 = true;
    break;
  case 8:
    is_64 = true;
    break;
  default:
    // this is a really random pointer size to be running on - just get out fast
    return addr;
  }

  lldb::addr_t mask = 0;

  if (strategy == SwiftASTContext::NonTriviallyManagedReferenceStrategy::eWeak) {
    bool is_indirect = true;
    
    // On non-objc platforms, the weak reference pointer always pointed to a
    // runtime structure.
    // For ObjC platforms, the masked value determines whether it is indirect.
    
    uint32_t value = 0;
    
    if (objc_runtime)
    {
    
      if (is_intel) {
        if (is_64) {
          mask = SWIFT_ABI_X86_64_OBJC_WEAK_REFERENCE_MARKER_MASK;
          value = SWIFT_ABI_X86_64_OBJC_WEAK_REFERENCE_MARKER_VALUE;
        } else {
          mask = SWIFT_ABI_I386_OBJC_WEAK_REFERENCE_MARKER_MASK;
          value = SWIFT_ABI_I386_OBJC_WEAK_REFERENCE_MARKER_VALUE;
        }
      } else if (is_arm) {
        if (is_64) {
            mask = SWIFT_ABI_ARM64_OBJC_WEAK_REFERENCE_MARKER_MASK;
            value = SWIFT_ABI_ARM64_OBJC_WEAK_REFERENCE_MARKER_VALUE;
        } else {
            mask = SWIFT_ABI_ARM_OBJC_WEAK_REFERENCE_MARKER_MASK;
            value = SWIFT_ABI_ARM_OBJC_WEAK_REFERENCE_MARKER_VALUE;
        }
      }
    } else {
        // This name is a little confusing. The "DEFAULT" marking in System.h
        // is supposed to mean: the value for non-ObjC platforms.  So
        // DEFAULT_OBJC here actually means "non-ObjC".
        mask = SWIFT_ABI_DEFAULT_OBJC_WEAK_REFERENCE_MARKER_MASK;
        value = SWIFT_ABI_DEFAULT_OBJC_WEAK_REFERENCE_MARKER_VALUE;
    }
    
    is_indirect = ((addr & mask) == value);
    
    if (!is_indirect)
      return addr;
    
    // The masked value of address is a pointer to the runtime structure.
    // The first field of the structure is the actual pointer.
    Process *process = GetProcess();
    Status error;
    
    lldb::addr_t masked_addr = addr & ~mask;
    lldb::addr_t isa_addr = process->ReadPointerFromMemory(masked_addr, error);
    if (error.Fail())
    {
        // FIXME: do some logging here.
        return addr;
    }
    return isa_addr;
    
      
  } else {
    if (is_arm && is_64)
      mask = SWIFT_ABI_ARM64_OBJC_NUM_RESERVED_LOW_BITS;
    else if (is_intel && is_64)
      mask = SWIFT_ABI_X86_64_OBJC_NUM_RESERVED_LOW_BITS;
    else
      mask = SWIFT_ABI_DEFAULT_OBJC_NUM_RESERVED_LOW_BITS;

    mask = (1 << mask) | (1 << (mask + 1));

    return addr & ~mask;
  }
  
  return addr;
}

ConstString SwiftLanguageRuntime::GetErrorBackstopName() {
  return ConstString("swift_errorInMain");
}

ConstString SwiftLanguageRuntime::GetStandardLibraryBaseName() {
  static ConstString g_swiftCore("swiftCore");
  return g_swiftCore;
}

ConstString SwiftLanguageRuntime::GetStandardLibraryName() {
  PlatformSP platform_sp(m_process->GetTarget().GetPlatform());
  if (platform_sp)
    return platform_sp->GetFullNameForDylib(GetStandardLibraryBaseName());
  return GetStandardLibraryBaseName();
}

bool SwiftLanguageRuntime::GetReferenceCounts(ValueObject &valobj,
                                              size_t &strong, size_t &weak) {
  CompilerType compiler_type(valobj.GetCompilerType());
  Flags type_flags(compiler_type.GetTypeInfo());
  if (llvm::isa<SwiftASTContext>(compiler_type.GetTypeSystem()) &&
      type_flags.AllSet(eTypeInstanceIsPointer)) {
    lldb::addr_t ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
    if (ptr_value == LLDB_INVALID_ADDRESS)
      return false;
    ptr_value += GetProcess()->GetAddressByteSize();
    Status error;
    strong =
        GetProcess()->ReadUnsignedIntegerFromMemory(ptr_value, 4, 0, error) >>
        2;
    if (error.Fail())
      return false;
    weak = GetProcess()->ReadUnsignedIntegerFromMemory(ptr_value + 4, 4, 0,
                                                       error) >>
           2;
    if (error.Fail())
      return false;
    return true;
  }
  return false;
}

class ProjectionSyntheticChildren : public SyntheticChildren {
public:
  struct FieldProjection {
    ConstString name;
    CompilerType type;
    int32_t byte_offset;

    FieldProjection(CompilerType parent_type, ExecutionContext *exe_ctx,
                    size_t idx) {
      const bool transparent_pointers = false;
      const bool omit_empty_base_classes = true;
      const bool ignore_array_bounds = false;
      bool child_is_base_class = false;
      bool child_is_deref_of_parent = false;
      std::string child_name;

      uint32_t child_byte_size;
      uint32_t child_bitfield_bit_size;
      uint32_t child_bitfield_bit_offset;
      uint64_t language_flags;

      type = parent_type.GetChildCompilerTypeAtIndex(
          exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
          ignore_array_bounds, child_name, child_byte_size, byte_offset,
          child_bitfield_bit_size, child_bitfield_bit_offset,
          child_is_base_class, child_is_deref_of_parent, nullptr,
          language_flags);

      if (child_is_base_class)
        type.Clear(); // invalidate - base classes are dealt with outside of the
                      // projection
      else
        name.SetCStringWithLength(child_name.c_str(), child_name.size());
    }

    bool IsValid() { return !name.IsEmpty() && type.IsValid(); }

    explicit operator bool() { return IsValid(); }
  };

  struct TypeProjection {
    std::vector<FieldProjection> field_projections;
    ConstString type_name;
  };

  typedef std::unique_ptr<TypeProjection> TypeProjectionUP;

  bool IsScripted() { return false; }

  std::string GetDescription() { return "projection synthetic children"; }

  ProjectionSyntheticChildren(const Flags &flags, TypeProjectionUP &&projection)
      : SyntheticChildren(flags), m_projection(std::move(projection)) {}

protected:
  TypeProjectionUP m_projection;

  class ProjectionFrontEndProvider : public SyntheticChildrenFrontEnd {
  public:
    ProjectionFrontEndProvider(ValueObject &backend,
                               TypeProjectionUP &projection)
        : SyntheticChildrenFrontEnd(backend), m_num_bases(0),
          m_projection(projection.get()) {
      lldbassert(m_projection && "need a valid projection");
      CompilerType type(backend.GetCompilerType());
      m_num_bases = type.GetNumDirectBaseClasses();
    }

    size_t CalculateNumChildren() override {
      return m_projection->field_projections.size() + m_num_bases;
    }

    lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
      if (idx < m_num_bases) {
        if (ValueObjectSP base_object_sp =
                m_backend.GetChildAtIndex(idx, true)) {
          CompilerType base_type(base_object_sp->GetCompilerType());
          ConstString base_type_name(base_type.GetTypeName());
          if (base_type_name.IsEmpty() ||
              !SwiftLanguageRuntime::IsSwiftClassName(base_type_name.GetCString()))
            return base_object_sp;
          base_object_sp = m_backend.GetSyntheticBase(
              0, base_type, true,
              Mangled(base_type_name, true)
                  .GetDemangledName(lldb::eLanguageTypeSwift));
          return base_object_sp;
        } else
          return nullptr;
      }
      idx -= m_num_bases;
      if (idx < m_projection->field_projections.size()) {
        auto &projection(m_projection->field_projections.at(idx));
        return m_backend.GetSyntheticChildAtOffset(
            projection.byte_offset, projection.type, true, projection.name);
      }
      return nullptr;
    }

    size_t GetIndexOfChildWithName(const ConstString &name) override {
      for (size_t idx = 0; idx < m_projection->field_projections.size();
           idx++) {
        if (m_projection->field_projections.at(idx).name == name)
          return idx;
      }
      return UINT32_MAX;
    }

    bool Update() override { return false; }

    bool MightHaveChildren() override { return true; }

    ConstString GetSyntheticTypeName() override {
      return m_projection->type_name;
    }

  private:
    size_t m_num_bases;
    TypeProjectionUP::element_type *m_projection;
  };

public:
  SyntheticChildrenFrontEnd::AutoPointer GetFrontEnd(ValueObject &backend) {
    return SyntheticChildrenFrontEnd::AutoPointer(
        new ProjectionFrontEndProvider(backend, m_projection));
  }
};

lldb::SyntheticChildrenSP
SwiftLanguageRuntime::GetBridgedSyntheticChildProvider(ValueObject &valobj) {
  const char *type_name(valobj.GetCompilerType().GetTypeName().AsCString());

  if (type_name && *type_name) {
    auto iter = m_bridged_synthetics_map.find(type_name),
         end = m_bridged_synthetics_map.end();
    if (iter != end)
      return iter->second;
  }

  ProjectionSyntheticChildren::TypeProjectionUP type_projection(
      new ProjectionSyntheticChildren::TypeProjectionUP::element_type());

  if (SwiftASTContext *swift_ast_ctx = GetScratchSwiftASTContext()) {
    Status error;
    CompilerType swift_type =
        swift_ast_ctx->GetTypeFromMangledTypename(type_name, error);

    if (swift_type.IsValid()) {
      ExecutionContext exe_ctx(GetProcess());
      bool any_projected = false;
      for (size_t idx = 0; idx < swift_type.GetNumChildren(true); idx++) {
        // if a projection fails, keep going - we have offsets here, so it
        // should be OK to skip some members
        if (auto projection = ProjectionSyntheticChildren::FieldProjection(
                swift_type, &exe_ctx, idx)) {
          any_projected = true;
          type_projection->field_projections.push_back(projection);
        }
      }

      if (any_projected) {
        type_projection->type_name = swift_type.GetDisplayTypeName();
        SyntheticChildrenSP synth_sp =
            SyntheticChildrenSP(new ProjectionSyntheticChildren(
                SyntheticChildren::Flags(), std::move(type_projection)));
        return (m_bridged_synthetics_map[type_name] = synth_sp);
      }
    }
  }

  return nullptr;
}

void SwiftLanguageRuntime::WillStartExecutingUserExpression() {
  std::lock_guard<std::mutex> lock(m_active_user_expr_mutex);
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));

  if (m_active_user_expr_count == 0 &&
      m_dynamic_exclusivity_flag_addr) {
    // We're executing the first user expression. Toggle the flag.
    Status error;
    TypeSystem *type_system =
      m_process->GetTarget().GetScratchTypeSystemForLanguage(
                                                      &error,
                                                      eLanguageTypeC_plus_plus);
    if (error.Fail()) {
      if (log)
        log->Printf("SwiftLanguageRuntime: Unable to get pointer to type "
                    "system: %s", error.AsCString());
      return;
    }
    ConstString BoolName("bool");
    size_t bool_size =
      type_system->GetBuiltinTypeByName(BoolName).GetByteSize(nullptr);

    Scalar original_value;
    m_process->ReadScalarIntegerFromMemory(*m_dynamic_exclusivity_flag_addr,
                                           bool_size, false, original_value,
                                           error);

    m_original_dynamic_exclusivity_flag_state = original_value.UInt() != 0;

    if (error.Fail()) {
      if (log)
        log->Printf("SwiftLanguageRuntime: Unable to read "
                    "disableExclusivityChecking flag state: %s",
                    error.AsCString());
    } else {
      Scalar new_value(1U);
      m_process->WriteScalarToMemory(*m_dynamic_exclusivity_flag_addr,
                                     new_value, bool_size, error);
      if (error.Fail()) {
        if (log)
          log->Printf("SwiftLanguageRuntime: Unable to set "
                      "disableExclusivityChecking flag state: %s",
                      error.AsCString());
      } else {
        if (log)
          log->Printf("SwiftLanguageRuntime: Changed "
                      "disableExclusivityChecking flag state from %u to 1",
                      m_original_dynamic_exclusivity_flag_state);
      }
    }
  }
  ++m_active_user_expr_count;

  if (log)
    log->Printf("SwiftLanguageRuntime: starting user expression. "
                "Number active: %u", m_active_user_expr_count);
}

void SwiftLanguageRuntime::DidFinishExecutingUserExpression() {
  std::lock_guard<std::mutex> lock(m_active_user_expr_mutex);
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));

  --m_active_user_expr_count;
  if (log)
    log->Printf("SwiftLanguageRuntime: finished user expression. "
                "Number active: %u", m_active_user_expr_count);

  if (m_active_user_expr_count == 0 &&
      m_dynamic_exclusivity_flag_addr) {
    Status error;
    TypeSystem *type_system =
      m_process->GetTarget().GetScratchTypeSystemForLanguage(
                                                      &error,
                                                      eLanguageTypeC_plus_plus);
    if (error.Fail()) {
      if (log)
        log->Printf("SwiftLanguageRuntime: Unable to get pointer to type "
                    "system: %s", error.AsCString());
      return;
    }
    ConstString BoolName("bool");
    size_t bool_size =
      type_system->GetBuiltinTypeByName(BoolName).GetByteSize(nullptr);

    Scalar original_value(m_original_dynamic_exclusivity_flag_state ? 1U : 0U);
    m_process->WriteScalarToMemory(*m_dynamic_exclusivity_flag_addr,
                                   original_value, bool_size, error);
    if (error.Fail()) {
      if (log)
        log->Printf("SwiftLanguageRuntime: Unable to reset "
                    "disableExclusivityChecking flag state: %s",
                    error.AsCString());
    } else {
      if (log)
        log->Printf("SwiftLanguageRuntime: Changed "
                    "disableExclusivityChecking flag state back to %u",
                    m_original_dynamic_exclusivity_flag_state);
    }
  }
}

llvm::Optional<Value> SwiftLanguageRuntime::GetErrorReturnLocationAfterReturn(
    lldb::StackFrameSP frame_sp)
{
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
  llvm::Optional<Value> error_val;

  llvm::StringRef error_reg_name;
  ArchSpec arch_spec(GetTargetRef().GetArchitecture());
  switch (arch_spec.GetMachine()) {
    case llvm::Triple::ArchType::arm:
      error_reg_name = "r6";
      break;
    case llvm::Triple::ArchType::aarch64:
      error_reg_name = "x19";
      break;
    case llvm::Triple::ArchType::x86_64:
      error_reg_name = "r12";
      break;
    default:
      break;
  }
  
  
  if (error_reg_name.empty())
      return error_val;
      
  RegisterContextSP reg_ctx = frame_sp->GetRegisterContext();
  const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(error_reg_name);
  lldbassert(reg_info && "didn't get the right register name for swift error register");
  if (!reg_info)
    return error_val;
  
  RegisterValue reg_value;
  if (!reg_ctx->ReadRegister(reg_info, reg_value))
  {
    // Do some logging here.
    return error_val;
  }
  
  lldb::addr_t error_addr = reg_value.GetAsUInt64();
  if (error_addr == 0)
    return error_val;

  Value val;
  if (reg_value.GetScalarValue(val.GetScalar())) {
    val.SetValueType(Value::eValueTypeScalar);
    val.SetContext(Value::eContextTypeRegisterInfo,
                     const_cast<RegisterInfo *>(reg_info));
    error_val = val;
  }
//  if (log)
//    log->Printf("Found return address: 0x%" PRIu64 " from register %s.",
//                return_addr,
//                error_reg_name.str().c_str());
  
  return error_val;
}

llvm::Optional<Value> SwiftLanguageRuntime::GetErrorReturnLocationBeforeReturn(
    lldb::StackFrameSP frame_sp, bool &need_to_check_after_return) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
  llvm::Optional<Value> error_val;
  
  if (!frame_sp)
  {
    need_to_check_after_return = false;
    return error_val;
  }
  
  // For Architectures where the error isn't returned in a register,
  // there's a magic variable that points to the value.  Check that first:
  
  ConstString error_location_name("$error");
  VariableListSP variables_sp = frame_sp->GetInScopeVariableList(false);
  VariableSP error_loc_var_sp = variables_sp->FindVariable(
      error_location_name, eValueTypeVariableArgument);
  if (error_loc_var_sp) {
    need_to_check_after_return = false;
    
    ValueObjectSP error_loc_val_sp = frame_sp->GetValueObjectForFrameVariable(
        error_loc_var_sp, eNoDynamicValues);
    if (error_loc_val_sp && error_loc_val_sp->GetError().Success())
      error_val = error_loc_val_sp->GetValue();

//    if (log)
//      log->Printf("Found return address: 0x%" PRIu64 " from error variable.", return_addr);
    return error_val;
  }
  
  // Otherwise, see if we know which register it lives in from the calling convention.
  // This should probably go in the ABI plugin not here, but the Swift ABI can change with
  // swiftlang versions and that would make it awkward in the ABI.
  
  Function *func = frame_sp->GetSymbolContext(eSymbolContextFunction).function;
  if (!func)
  {
    need_to_check_after_return = false;
    return error_val;
  }
  
  need_to_check_after_return = func->CanThrow();
  return error_val;

}

//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
LanguageRuntime *
SwiftLanguageRuntime::CreateInstance(Process *process,
                                     lldb::LanguageType language) {
  if (language == eLanguageTypeSwift)
    return new SwiftLanguageRuntime(process);
  else
    return NULL;
}

lldb::BreakpointResolverSP
SwiftLanguageRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp,
                                              bool throw_bp) {
  BreakpointResolverSP resolver_sp;

  if (throw_bp)
    resolver_sp.reset(new BreakpointResolverName(
        bkpt, "swift_willThrow", eFunctionNameTypeBase, eLanguageTypeUnknown,
        Breakpoint::Exact, 0, eLazyBoolNo));
  // FIXME: We don't do catch breakpoints for ObjC yet.
  // Should there be some way for the runtime to specify what it can do in this
  // regard?
  return resolver_sp;
}

static const char *
SwiftDemangleNodeKindToCString(const swift::Demangle::Node::Kind node_kind) {
#define NODE(e)                                                                \
  case swift::Demangle::Node::Kind::e:                                         \
    return #e;

  switch (node_kind) {
#include "swift/Demangling/DemangleNodes.def"
  }
  return "swift::Demangle::Node::Kind::???";
#undef NODE
}

static OptionDefinition g_swift_demangle_options[] = {
  // clang-format off
  {LLDB_OPT_SET_1, false, "expand", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Whether LLDB should print the demangled tree"},
  // clang-format on
};

class CommandObjectSwift_Demangle : public CommandObjectParsed {
public:
  CommandObjectSwift_Demangle(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "demangle",
                            "Demangle a Swift mangled name",
                            "language swift demangle"),
        m_options() {}

  ~CommandObjectSwift_Demangle() {}

  virtual Options *GetOptions() { return &m_options; }

  class CommandOptions : public Options {
  public:
    CommandOptions() : Options(), m_expand(false, false) {
      OptionParsingStarting(nullptr);
    }

    virtual ~CommandOptions() {}

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                                 ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;
      switch (short_option) {
      case 'e':
        m_expand.SetCurrentValue(true);
        break;

      default:
        error.SetErrorStringWithFormat("invalid short option character '%c'",
                                       short_option);
        break;
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_expand.Clear();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_swift_demangle_options);
    }

    // Options table: Required for subclasses of Options.

    OptionValueBoolean m_expand;
  };

protected:
  void PrintNode(swift::Demangle::NodePointer node_ptr, Stream &stream,
                 int depth = 0) {
    if (!node_ptr)
      return;

    std::string indent(2 * depth, ' ');

    stream.Printf("%s", indent.c_str());

    stream.Printf("kind=%s",
                  SwiftDemangleNodeKindToCString(node_ptr->getKind()));
    if (node_ptr->hasText()) {
      std::string Text = node_ptr->getText();
      stream.Printf(", text=\"%s\"", Text.c_str());
    }
    if (node_ptr->hasIndex())
      stream.Printf(", index=%" PRIu64, node_ptr->getIndex());

    stream.Printf("\n");

    for (auto &&child : *node_ptr) {
      PrintNode(child, stream, depth + 1);
    }
  }

  bool DoExecute(Args &command, CommandReturnObject &result) {
    for (size_t i = 0; i < command.GetArgumentCount(); i++) {
      const char *arg = command.GetArgumentAtIndex(i);
      if (arg && *arg) {
        swift::Demangle::Context demangle_ctx;
        auto node_ptr = demangle_ctx.demangleSymbolAsNode(llvm::StringRef(arg));
        if (node_ptr) {
          if (m_options.m_expand) {
            PrintNode(node_ptr, result.GetOutputStream());
          }
          result.GetOutputStream().Printf(
              "%s ---> %s\n", arg,
              swift::Demangle::nodeToString(node_ptr).c_str());
        }
      }
    }
    result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
    return true;
  }

  CommandOptions m_options;
};

class CommandObjectSwift_RefCount : public CommandObjectRaw {
public:
  CommandObjectSwift_RefCount(CommandInterpreter &interpreter)
      : CommandObjectRaw(interpreter, "refcount",
                         "Inspect the reference count data for a Swift object",
                         "language swift refcount",
                         eCommandProcessMustBePaused | eCommandRequiresFrame) {}

  ~CommandObjectSwift_RefCount() {}

  virtual Options *GetOptions() { return nullptr; }

protected:
  bool DoExecute(const char *command, CommandReturnObject &result) {
    ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
    StackFrameSP frame_sp(exe_ctx.GetFrameSP());
    EvaluateExpressionOptions options;
    options.SetLanguage(lldb::eLanguageTypeSwift);
    options.SetResultIsInternal(true);
    options.SetUseDynamic();
    ValueObjectSP result_valobj_sp;
    if (exe_ctx.GetTargetSP()->EvaluateExpression(command, frame_sp.get(),
                                                  result_valobj_sp) ==
        eExpressionCompleted) {
      if (result_valobj_sp) {
        if (result_valobj_sp->GetError().Fail()) {
          result.SetStatus(lldb::eReturnStatusFailed);
          result.AppendError(result_valobj_sp->GetError().AsCString());
          return false;
        }
        result_valobj_sp =
            result_valobj_sp->GetQualifiedRepresentationIfAvailable(
                lldb::eDynamicCanRunTarget, true);
        CompilerType result_type(result_valobj_sp->GetCompilerType());
        if (result_type.GetTypeInfo() & lldb::eTypeInstanceIsPointer) {
          size_t strong = 0, weak = 0;
          if (!exe_ctx.GetProcessSP()
                   ->GetSwiftLanguageRuntime()
                   ->GetReferenceCounts(*result_valobj_sp.get(), strong,
                                        weak)) {
            result.AppendError("refcount not available");
            result.SetStatus(lldb::eReturnStatusFailed);
            return false;
          } else {
            result.AppendMessageWithFormat(
                "refcount data: (strong = %zu, weak = %zu)\n", strong, weak);
            result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
            return true;
          }
        } else {
          result.AppendError("refcount only available for class types");
          result.SetStatus(lldb::eReturnStatusFailed);
          return false;
        }
      }
    }
    result.SetStatus(lldb::eReturnStatusFailed);
    if (result_valobj_sp && result_valobj_sp->GetError().Fail())
      result.AppendError(result_valobj_sp->GetError().AsCString());
    return false;
  }
};

class CommandObjectMultiwordSwift : public CommandObjectMultiword {
public:
  CommandObjectMultiwordSwift(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "swift",
            "A set of commands for operating on the Swift Language Runtime.",
            "swift <subcommand> [<subcommand-options>]") {
    LoadSubCommand("demangle", CommandObjectSP(new CommandObjectSwift_Demangle(
                                   interpreter)));
    LoadSubCommand("refcount", CommandObjectSP(new CommandObjectSwift_RefCount(
                                   interpreter)));
  }

  virtual ~CommandObjectMultiwordSwift() {}
};

void SwiftLanguageRuntime::Initialize() {
  PluginManager::RegisterPlugin(
      GetPluginNameStatic(), "Language runtime for the Swift language",
      CreateInstance,
      [](CommandInterpreter &interpreter) -> lldb::CommandObjectSP {
        return CommandObjectSP(new CommandObjectMultiwordSwift(interpreter));
      });
}

void SwiftLanguageRuntime::Terminate() {
  PluginManager::UnregisterPlugin(CreateInstance);
}

lldb_private::ConstString SwiftLanguageRuntime::GetPluginNameStatic() {
  static ConstString g_name("swift");
  return g_name;
}

//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
lldb_private::ConstString SwiftLanguageRuntime::GetPluginName() {
  return GetPluginNameStatic();
}

uint32_t SwiftLanguageRuntime::GetPluginVersion() { return 1; }
