//===-- Materializer.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Expression/Materializer.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/ValueObject/ValueObjectConstResult.h"
#include "lldb/ValueObject/ValueObjectVariable.h"
#include "lldb/lldb-forward.h"

#include <memory>
#include <optional>

using namespace lldb_private;

// FIXME: these should be retrieved from the target
//        instead of being hard-coded. Currently we
//        assume that persistent vars are materialized
//        as references, and thus pick the size of a
//        64-bit pointer.
static constexpr uint32_t g_default_var_alignment = 8;
static constexpr uint32_t g_default_var_byte_size = 8;

uint32_t Materializer::AddStructMember(Entity &entity) {
  uint32_t size = entity.GetSize();
  uint32_t alignment = entity.GetAlignment();

  uint32_t ret;

  if (m_current_offset == 0)
    m_struct_alignment = alignment;

  if (m_current_offset % alignment)
    m_current_offset += (alignment - (m_current_offset % alignment));

  ret = m_current_offset;

  m_current_offset += size;

  return ret;
}

class EntityPersistentVariable : public Materializer::Entity {
public:
  EntityPersistentVariable(lldb::ExpressionVariableSP &persistent_variable_sp,
                           Materializer::PersistentVariableDelegate *delegate)
      : Entity(), m_persistent_variable_sp(persistent_variable_sp),
        m_delegate(delegate) {
    // Hard-coding to maximum size of a pointer since persistent variables are
    // materialized by reference
    m_size = g_default_var_byte_size;
    m_alignment = g_default_var_alignment;
  }

  void MakeAllocation(IRMemoryMap &map, Status &err) {
    Log *log = GetLog(LLDBLog::Expressions);

    // Allocate a spare memory area to store the persistent variable's
    // contents.

    const bool zero_memory = false;
    IRMemoryMap::AllocationPolicy used_policy;
    const uint64_t malloc_size =
        llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
            .value_or(0);
    auto address_or_error = map.Malloc(
        malloc_size, 8, lldb::ePermissionsReadable | lldb::ePermissionsWritable,
        IRMemoryMap::eAllocationPolicyMirror, zero_memory, &used_policy);
    if (!address_or_error) {
      err = Status::FromErrorStringWithFormat(
          "couldn't allocate a memory area to store %s: %s",
          m_persistent_variable_sp->GetName().GetCString(),
          toString(address_or_error.takeError()).c_str());
      return;
    }
    lldb::addr_t mem = *address_or_error;

    LLDB_LOGF(
        log, "Allocated 0x%" PRIx64 "bytes for %s (0x%" PRIx64 ") successfully",
        malloc_size, m_persistent_variable_sp->GetName().GetCString(), mem);

    // Put the location of the spare memory into the live data of the
    // ValueObject.

    m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create(
        map.GetBestExecutionContextScope(),
        m_persistent_variable_sp->GetCompilerType(),
        m_persistent_variable_sp->GetName(), mem, eAddressTypeLoad,
        map.GetAddressByteSize());

    if (used_policy == IRMemoryMap::eAllocationPolicyMirror) {
      if (m_persistent_variable_sp->m_flags &
          ExpressionVariable::EVKeepInTarget) {
        // Clear the flag if the variable will never be deallocated.
        Status leak_error;
        map.Leak(mem, leak_error);
        m_persistent_variable_sp->m_flags &=
            ~ExpressionVariable::EVNeedsAllocation;
      }
    } else {
      // If we cannot allocate memory in the process,
      // - clear the 'EVKeepInTarget' flag to ensure that 'm_live_sp' is reset
      //   during dematerialization,
      m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVKeepInTarget;
      // - set the 'EVNeedsFreezeDry' flag so that the value is copied to
      //   'm_frozen_sp' during dematerialization.
      m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsFreezeDry;
    }

    // Write the contents of the variable to the area.

    Status write_error;

    map.WriteMemory(
        mem, m_persistent_variable_sp->GetValueBytes(),
        llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
            .value_or(0),
        write_error);

    if (!write_error.Success()) {
      err = Status::FromErrorStringWithFormatv(
          "couldn't write {0} to the target: {1}",
          m_persistent_variable_sp->GetName(), write_error.AsCString());
      return;
    }
  }

  void DestroyAllocation(IRMemoryMap &map, Status &err) {
    Status deallocate_error;

    lldb::ValueObjectSP live_valobj_sp =
        m_persistent_variable_sp->GetLiveObject();
    map.Free((lldb::addr_t)live_valobj_sp->GetValue().GetScalar().ULongLong(),
             deallocate_error);

    live_valobj_sp.reset();

    if (!deallocate_error.Success()) {
      err = Status::FromErrorStringWithFormat(
          "couldn't deallocate memory for %s: %s",
          m_persistent_variable_sp->GetName().GetCString(),
          deallocate_error.AsCString());
    }
  }

  void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                   lldb::addr_t process_address, Status &err) override {
    Log *log = GetLog(LLDBLog::Expressions);

    const lldb::addr_t load_addr = process_address + m_offset;

    LLDB_LOG(log,
             "EntityPersistentVariable::Materialize [address = {0:x}, m_name = "
             "{1}, m_flags = {2:x}]",
             (uint64_t)load_addr, m_persistent_variable_sp->GetName(),
             m_persistent_variable_sp->m_flags);

    if (m_persistent_variable_sp->m_flags &
        ExpressionVariable::EVNeedsAllocation) {
      MakeAllocation(map, err);
      m_persistent_variable_sp->m_flags |=
          ExpressionVariable::EVIsLLDBAllocated;

      if (!err.Success())
        return;
    }

    lldb::ValueObjectSP live_valobj_sp =
        m_persistent_variable_sp->GetLiveObject();
    if ((m_persistent_variable_sp->m_flags &
             ExpressionVariable::EVIsProgramReference &&
         live_valobj_sp) ||
        m_persistent_variable_sp->m_flags &
            ExpressionVariable::EVIsLLDBAllocated) {
      Status write_error;

      map.WriteScalarToMemory(load_addr, live_valobj_sp->GetValue().GetScalar(),
                              map.GetAddressByteSize(), write_error);

      if (!write_error.Success()) {
        err = Status::FromErrorStringWithFormatv(
            "couldn't write the location of {0} to memory: {1}",
            m_persistent_variable_sp->GetName(), write_error.AsCString());
      }
    } else {
      err = Status::FromErrorStringWithFormatv(
          "no materialization happened for persistent variable {0}",
          m_persistent_variable_sp->GetName());
      return;
    }
  }

  void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                     lldb::addr_t process_address, lldb::addr_t frame_top,
                     lldb::addr_t frame_bottom, Status &err) override {
    Log *log = GetLog(LLDBLog::Expressions);

    const lldb::addr_t load_addr = process_address + m_offset;

    LLDB_LOG(log,
             "EntityPersistentVariable::Dematerialize [address = {0:x}, m_name "
             "= {1}, m_flags = {2}]",
             (uint64_t)process_address + m_offset,
             m_persistent_variable_sp->GetName(),
             m_persistent_variable_sp->m_flags);

    if (m_delegate) {
      m_delegate->DidDematerialize(m_persistent_variable_sp);
    }

    lldb::ValueObjectSP live_valobj_sp =
        m_persistent_variable_sp->GetLiveObject();
    if ((m_persistent_variable_sp->m_flags &
         ExpressionVariable::EVIsLLDBAllocated) ||
        (m_persistent_variable_sp->m_flags &
         ExpressionVariable::EVIsProgramReference)) {
      if (m_persistent_variable_sp->m_flags &
              ExpressionVariable::EVIsProgramReference &&
          !live_valobj_sp) {
        // If the reference comes from the program, then the
        // ClangExpressionVariable's live variable data hasn't been set up yet.
        // Do this now.

        lldb::addr_t location;
        Status read_error;

        map.ReadPointerFromMemory(&location, load_addr, read_error);

        if (!read_error.Success()) {
          err = Status::FromErrorStringWithFormat(
              "couldn't read the address of program-allocated variable %s: %s",
              m_persistent_variable_sp->GetName().GetCString(),
              read_error.AsCString());
          return;
        }

        m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create(
            map.GetBestExecutionContextScope(),
            m_persistent_variable_sp->GetCompilerType(),
            m_persistent_variable_sp->GetName(), location, eAddressTypeLoad,
            llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
                .value_or(0));

        if (frame_top != LLDB_INVALID_ADDRESS &&
            frame_bottom != LLDB_INVALID_ADDRESS && location >= frame_bottom &&
            location <= frame_top) {
          // If the variable is resident in the stack frame created by the
          // expression, then it cannot be relied upon to stay around.  We
          // treat it as needing reallocation.
          m_persistent_variable_sp->m_flags |=
              ExpressionVariable::EVIsLLDBAllocated;
          m_persistent_variable_sp->m_flags |=
              ExpressionVariable::EVNeedsAllocation;
          m_persistent_variable_sp->m_flags |=
              ExpressionVariable::EVNeedsFreezeDry;
          m_persistent_variable_sp->m_flags &=
              ~ExpressionVariable::EVIsProgramReference;
        }
      }

      if (!live_valobj_sp) {
        err = Status::FromErrorStringWithFormat(
            "couldn't find the memory area used to store %s",
            m_persistent_variable_sp->GetName().GetCString());
        return;
      }

      lldb::addr_t mem = live_valobj_sp->GetValue().GetScalar().ULongLong();

      if (live_valobj_sp->GetValue().GetValueAddressType() !=
          eAddressTypeLoad) {
        err = Status::FromErrorStringWithFormat(
            "the address of the memory area for %s is in an incorrect format",
            m_persistent_variable_sp->GetName().GetCString());
        return;
      }

      if (m_persistent_variable_sp->m_flags &
              ExpressionVariable::EVNeedsFreezeDry ||
          m_persistent_variable_sp->m_flags &
              ExpressionVariable::EVKeepInTarget) {
        LLDB_LOGF(log, "Dematerializing %s from 0x%" PRIx64 " (size = %llu)",
                  m_persistent_variable_sp->GetName().GetCString(),
                  (uint64_t)mem,
                  (unsigned long long)llvm::expectedToOptional(
                      m_persistent_variable_sp->GetByteSize())
                      .value_or(0));

        // Read the contents of the spare memory area

        m_persistent_variable_sp->ValueUpdated();

        Status read_error;

        map.ReadMemory(
            m_persistent_variable_sp->GetValueBytes(), mem,
            llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
                .value_or(0),
            read_error);

        if (!read_error.Success()) {
          err = Status::FromErrorStringWithFormat(
              "couldn't read the contents of %s from memory: %s",
              m_persistent_variable_sp->GetName().GetCString(),
              read_error.AsCString());
          return;
        }
        m_persistent_variable_sp->m_flags &=
            ~ExpressionVariable::EVNeedsFreezeDry;
      }
    } else {
      err = Status::FromErrorStringWithFormatv(
          "no dematerialization happened for persistent variable {0}",
          m_persistent_variable_sp->GetName());
      return;
    }

    if (m_persistent_variable_sp->m_flags &
            ExpressionVariable::EVNeedsAllocation &&
        !(m_persistent_variable_sp->m_flags &
          ExpressionVariable::EVKeepInTarget)) {
      DestroyAllocation(map, err);
      if (!err.Success())
        return;
    }
  }

  void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
                 Log *log) override {
    StreamString dump_stream;

    Status err;

    const lldb::addr_t load_addr = process_address + m_offset;

    dump_stream.Format("{0:x}: EntityPersistentVariable ({1})\n", load_addr,
                       m_persistent_variable_sp->GetName());

    {
      dump_stream.PutCString("Pointer:\n");

      DataBufferHeap data(m_size, 0);

      map.ReadMemory(data.GetBytes(), load_addr, m_size, err);

      if (!err.Success()) {
        dump_stream.PutCString("  <could not be read>\n");
      } else {
        DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
                     load_addr);

        dump_stream.PutChar('\n');
      }
    }

    {
      dump_stream.PutCString("Target:\n");

      lldb::addr_t target_address;

      map.ReadPointerFromMemory(&target_address, load_addr, err);

      if (!err.Success()) {
        dump_stream.PutCString("  <could not be read>\n");
      } else {
        DataBufferHeap data(
            llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
                .value_or(0),
            0);

        map.ReadMemory(
            data.GetBytes(), target_address,
            llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
                .value_or(0),
            err);

        if (!err.Success()) {
          dump_stream.PutCString("  <could not be read>\n");
        } else {
          DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
                       target_address);

          dump_stream.PutChar('\n');
        }
      }
    }

    log->PutString(dump_stream.GetString());
  }

  void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}

private:
  lldb::ExpressionVariableSP m_persistent_variable_sp;
  Materializer::PersistentVariableDelegate *m_delegate;
};

uint32_t Materializer::AddPersistentVariable(
    lldb::ExpressionVariableSP &persistent_variable_sp,
    PersistentVariableDelegate *delegate, Status &err) {
  EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
  *iter = std::make_unique<EntityPersistentVariable>(persistent_variable_sp,
                                                     delegate);
  uint32_t ret = AddStructMember(**iter);
  (*iter)->SetOffset(ret);
  return ret;
}

/// Base class for materialization of Variables and ValueObjects.
///
/// Subclasses specify how to obtain the Value which is to be
/// materialized.
class EntityVariableBase : public Materializer::Entity {
public:
  virtual ~EntityVariableBase() = default;

  EntityVariableBase() {
    // Hard-coding to maximum size of a pointer since all variables are
    // materialized by reference
    m_size = g_default_var_byte_size;
    m_alignment = g_default_var_alignment;
  }

  void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                   lldb::addr_t process_address, Status &err) override {
    Log *log = GetLog(LLDBLog::Expressions);

    const lldb::addr_t load_addr = process_address + m_offset;
    LLDB_LOGF(log,
              "EntityVariable::Materialize [address = 0x%" PRIx64
              ", m_variable_sp = %s]",
              (uint64_t)load_addr, GetName().GetCString());

    ExecutionContextScope *scope = frame_sp.get();

    if (!scope)
      scope = map.GetBestExecutionContextScope();

    lldb::ValueObjectSP valobj_sp = SetupValueObject(scope);

    if (!valobj_sp) {
      err = Status::FromErrorStringWithFormatv(
          "couldn't get a value object for variable {0}", GetName());
      return;
    }

    Status valobj_error = valobj_sp->GetError().Clone();

    if (valobj_error.Fail()) {
      err = Status::FromErrorStringWithFormatv(
          "couldn't get the value of variable {0}: {1}", GetName(),
          valobj_error.AsCString());
      return;
    }

    if (m_is_reference) {
      DataExtractor valobj_extractor;
      Status extract_error;
      valobj_sp->GetData(valobj_extractor, extract_error);

      if (!extract_error.Success()) {
        err = Status::FromErrorStringWithFormatv(
            "couldn't read contents of reference variable {0}: {1}", GetName(),
            extract_error.AsCString());
        return;
      }

      lldb::offset_t offset = 0;
      lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset);

      Status write_error;
      map.WritePointerToMemory(load_addr, reference_addr, write_error);

      if (!write_error.Success()) {
        err = Status::FromErrorStringWithFormatv(
            "couldn't write the contents of reference variable {} to memory: "
            "{}",
            GetName(), write_error.AsCString());
        return;
      }
    } else {
      lldb::addr_t addr_of_valobj =
          valobj_sp->GetAddressOf(/*scalar_is_load_address=*/false).address;
      if (addr_of_valobj != LLDB_INVALID_ADDRESS) {
        Status write_error;
        map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);

        if (!write_error.Success()) {
          err = Status::FromErrorStringWithFormatv(
              "couldn't write the address of variable {0} to memory: {1}",
              GetName(), write_error.AsCString());
          return;
        }
      } else {
        DataExtractor data;
        Status extract_error;
        valobj_sp->GetData(data, extract_error);
        if (!extract_error.Success()) {
          err = Status::FromErrorStringWithFormatv(
              "couldn't get the value of {0}: {1}", GetName(),
              extract_error.AsCString());
          return;
        }

        if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
          err = Status::FromErrorStringWithFormatv(
              "trying to create a temporary region for {0} but one exists",
              GetName());
          return;
        }

        if (data.GetByteSize() <
            llvm::expectedToOptional(GetByteSize(scope)).value_or(0)) {
          if (data.GetByteSize() == 0 && !LocationExpressionIsValid()) {
            err = Status::FromErrorStringWithFormatv(
                "the variable '{0}' has no location, "
                "it may have been optimized out",
                GetName());
          } else {
            err = Status::FromErrorStringWithFormatv(
                "size of variable {0} ({1}) is larger than the ValueObject's "
                "size ({2})",
                GetName(),
                llvm::expectedToOptional(GetByteSize(scope)).value_or(0),
                data.GetByteSize());
          }
          return;
        }

        std::optional<size_t> opt_bit_align = GetTypeBitAlign(scope);
        if (!opt_bit_align) {
          err = Status::FromErrorStringWithFormatv(
              "can't get the type alignment for {0}", GetName());
          return;
        }

        size_t byte_align = (*opt_bit_align + 7) / 8;

        const bool zero_memory = false;
        if (auto address_or_error = map.Malloc(
                data.GetByteSize(), byte_align,
                lldb::ePermissionsReadable | lldb::ePermissionsWritable,
                IRMemoryMap::eAllocationPolicyMirror, zero_memory)) {
          m_temporary_allocation = *address_or_error;
        } else {
          err = Status::FromErrorStringWithFormatv(
              "couldn't allocate a temporary region for {0}: {1}", GetName(),
              toString(address_or_error.takeError()));
          return;
        }

        m_temporary_allocation_size = data.GetByteSize();

        m_original_data = std::make_shared<DataBufferHeap>(data.GetDataStart(),
                                                           data.GetByteSize());

        Status write_error;

        map.WriteMemory(m_temporary_allocation, data.GetDataStart(),
                        data.GetByteSize(), write_error);

        if (!write_error.Success()) {
          err = Status::FromErrorStringWithFormatv(
              "couldn't write to the temporary region for {0}: {1}", GetName(),
              write_error.AsCString());
          return;
        }

        Status pointer_write_error;

        map.WritePointerToMemory(load_addr, m_temporary_allocation,
                                 pointer_write_error);

        if (!pointer_write_error.Success()) {
          err = Status::FromErrorStringWithFormatv(
              "couldn't write the address of the temporary region for {0}: {1}",
              GetName(), pointer_write_error.AsCString());
        }
      }
    }
  }

  void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                     lldb::addr_t process_address, lldb::addr_t frame_top,
                     lldb::addr_t frame_bottom, Status &err) override {
    Log *log = GetLog(LLDBLog::Expressions);

    const lldb::addr_t load_addr = process_address + m_offset;
    LLDB_LOG(
        log,
        "EntityVariable::Dematerialize [address = {0:x}, m_variable_sp = {1}]",
        (uint64_t)load_addr, GetName());

    if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
      ExecutionContextScope *scope = frame_sp.get();

      if (!scope)
        scope = map.GetBestExecutionContextScope();

      lldb::ValueObjectSP valobj_sp = SetupValueObject(scope);

      if (!valobj_sp) {
        err = Status::FromErrorStringWithFormatv(
            "couldn't get a value object for variable {0}", GetName());
        return;
      }

      lldb_private::DataExtractor data;

      Status extract_error;

      map.GetMemoryData(
          data, m_temporary_allocation,
          llvm::expectedToOptional(valobj_sp->GetByteSize()).value_or(0),
          extract_error);

      if (!extract_error.Success()) {
        err = Status::FromErrorStringWithFormatv(
            "couldn't get the data for variable {0}", GetName());
        return;
      }

      bool actually_write = true;

      if (m_original_data) {
        if ((data.GetByteSize() == m_original_data->GetByteSize()) &&
            !memcmp(m_original_data->GetBytes(), data.GetDataStart(),
                    data.GetByteSize())) {
          actually_write = false;
        }
      }

      Status set_error;

      if (actually_write) {
        valobj_sp->SetData(data, set_error);

        if (!set_error.Success()) {
          err = Status::FromErrorStringWithFormatv(
              "couldn't write the new contents of {0} back into the variable",
              GetName());
          return;
        }
      }

      Status free_error;

      map.Free(m_temporary_allocation, free_error);

      if (!free_error.Success()) {
        err = Status::FromErrorStringWithFormatv(
            "couldn't free the temporary region for {0}: {1}", GetName(),
            free_error.AsCString());
        return;
      }

      m_original_data.reset();
      m_temporary_allocation = LLDB_INVALID_ADDRESS;
      m_temporary_allocation_size = 0;
    }
  }

  void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
                 Log *log) override {
    StreamString dump_stream;

    const lldb::addr_t load_addr = process_address + m_offset;
    dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr);

    Status err;

    lldb::addr_t ptr = LLDB_INVALID_ADDRESS;

    {
      dump_stream.PutCString("Pointer:\n");

      DataBufferHeap data(m_size, 0);

      map.ReadMemory(data.GetBytes(), load_addr, m_size, err);

      if (!err.Success()) {
        dump_stream.PutCString("  <could not be read>\n");
      } else {
        DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
                                map.GetByteOrder(), map.GetAddressByteSize());

        DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
                     load_addr);

        lldb::offset_t offset = 0;

        ptr = extractor.GetAddress(&offset);

        dump_stream.PutChar('\n');
      }
    }

    if (m_temporary_allocation == LLDB_INVALID_ADDRESS) {
      dump_stream.PutCString("Points to process memory:\n");
    } else {
      dump_stream.PutCString("Temporary allocation:\n");
    }

    if (ptr == LLDB_INVALID_ADDRESS) {
      dump_stream.PutCString("  <could not be be found>\n");
    } else {
      DataBufferHeap data(m_temporary_allocation_size, 0);

      map.ReadMemory(data.GetBytes(), m_temporary_allocation,
                     m_temporary_allocation_size, err);

      if (!err.Success()) {
        dump_stream.PutCString("  <could not be read>\n");
      } else {
        DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
                     load_addr);

        dump_stream.PutChar('\n');
      }
    }

    log->PutString(dump_stream.GetString());
  }

  void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
    if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
      Status free_error;

      map.Free(m_temporary_allocation, free_error);

      m_temporary_allocation = LLDB_INVALID_ADDRESS;
      m_temporary_allocation_size = 0;
    }
  }

private:
  virtual ConstString GetName() const = 0;

  /// Creates and returns ValueObject tied to this variable
  /// and prepares Entity for materialization.
  ///
  /// Called each time the Materializer (de)materializes a
  /// variable. We re-create the ValueObject based on the
  /// current ExecutionContextScope since clients such as
  /// conditional breakpoints may materialize the same
  /// EntityVariable multiple times with different frames.
  ///
  /// Each subsequent use of the EntityVariableBase interface
  /// will query the newly created ValueObject until this
  /// function is called again.
  virtual lldb::ValueObjectSP
  SetupValueObject(ExecutionContextScope *scope) = 0;

  /// Returns size in bytes of the type associated with this variable
  ///
  /// \returns On success, returns byte size of the type associated
  ///          with this variable. Returns std::nullopt otherwise.
  virtual llvm::Expected<uint64_t>
  GetByteSize(ExecutionContextScope *scope) const = 0;

  /// Returns 'true' if the location expression associated with this variable
  /// is valid.
  virtual bool LocationExpressionIsValid() const = 0;

  /// Returns alignment of the type associated with this variable in bits.
  ///
  /// \returns On success, returns alignment in bits for the type associated
  ///          with this variable. Returns std::nullopt otherwise.
  virtual std::optional<size_t>
  GetTypeBitAlign(ExecutionContextScope *scope) const = 0;

protected:
  bool m_is_reference = false;
  lldb::addr_t m_temporary_allocation = LLDB_INVALID_ADDRESS;
  size_t m_temporary_allocation_size = 0;
  lldb::DataBufferSP m_original_data;
};

/// Represents an Entity constructed from a VariableSP.
///
/// This class is used for materialization of variables for which
/// the user has a VariableSP on hand. The ValueObject is then
/// derived from the associated DWARF location expression when needed
/// by the Materializer.
class EntityVariable : public EntityVariableBase {
public:
  EntityVariable(lldb::VariableSP &variable_sp) : m_variable_sp(variable_sp) {
    m_is_reference =
        m_variable_sp->GetType()->GetForwardCompilerType().IsReferenceType();
  }

  ConstString GetName() const override { return m_variable_sp->GetName(); }

  lldb::ValueObjectSP SetupValueObject(ExecutionContextScope *scope) override {
    assert(m_variable_sp != nullptr);
    return ValueObjectVariable::Create(scope, m_variable_sp);
  }

  llvm::Expected<uint64_t>
  GetByteSize(ExecutionContextScope *scope) const override {
    return m_variable_sp->GetType()->GetByteSize(scope);
  }

  bool LocationExpressionIsValid() const override {
    return m_variable_sp->LocationExpressionList().IsValid();
  }

  std::optional<size_t>
  GetTypeBitAlign(ExecutionContextScope *scope) const override {
    return m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign(
        scope);
  }

private:
  lldb::VariableSP m_variable_sp; ///< Variable that this entity is based on.
};

/// Represents an Entity constructed from a VariableSP.
///
/// This class is used for materialization of variables for
/// which the user does not have a VariableSP available (e.g.,
/// when materializing ivars).
class EntityValueObject : public EntityVariableBase {
public:
  EntityValueObject(ConstString name, ValueObjectProviderTy provider)
      : m_name(name), m_valobj_provider(std::move(provider)) {
    assert(m_valobj_provider);
  }

  ConstString GetName() const override { return m_name; }

  lldb::ValueObjectSP SetupValueObject(ExecutionContextScope *scope) override {
    m_valobj_sp =
        m_valobj_provider(GetName(), scope->CalculateStackFrame().get());

    if (m_valobj_sp)
      m_is_reference = m_valobj_sp->GetCompilerType().IsReferenceType();

    return m_valobj_sp;
  }

  llvm::Expected<uint64_t>
  GetByteSize(ExecutionContextScope *scope) const override {
    if (m_valobj_sp)
      return m_valobj_sp->GetCompilerType().GetByteSize(scope);

    return llvm::createStringError("no value object");
  }

  bool LocationExpressionIsValid() const override {
    if (m_valobj_sp)
      return m_valobj_sp->GetError().Success();

    return false;
  }

  std::optional<size_t>
  GetTypeBitAlign(ExecutionContextScope *scope) const override {
    if (m_valobj_sp)
      return m_valobj_sp->GetCompilerType().GetTypeBitAlign(scope);

    return {};
  }

private:
  ConstString m_name;
  lldb::ValueObjectSP m_valobj_sp;
  ValueObjectProviderTy m_valobj_provider;
};

uint32_t Materializer::AddVariable(lldb::VariableSP &variable_sp, Status &err) {
  EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
  *iter = std::make_unique<EntityVariable>(variable_sp);
  uint32_t ret = AddStructMember(**iter);
  (*iter)->SetOffset(ret);
  return ret;
}

uint32_t Materializer::AddValueObject(ConstString name,
                                      ValueObjectProviderTy valobj_provider,
                                      Status &err) {
  assert(valobj_provider);
  EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
  *iter = std::make_unique<EntityValueObject>(name, std::move(valobj_provider));
  uint32_t ret = AddStructMember(**iter);
  (*iter)->SetOffset(ret);
  return ret;
}

class EntityResultVariable : public Materializer::Entity {
public:
  EntityResultVariable(const CompilerType &type, bool is_program_reference,
                       bool keep_in_memory,
                       Materializer::PersistentVariableDelegate *delegate)
      : Entity(), m_type(type), m_is_program_reference(is_program_reference),
        m_keep_in_memory(keep_in_memory), m_delegate(delegate) {
    // Hard-coding to maximum size of a pointer since all results are
    // materialized by reference
    m_size = g_default_var_byte_size;
    m_alignment = g_default_var_alignment;
  }

  void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                   lldb::addr_t process_address, Status &err) override {
    if (!m_is_program_reference) {
      if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
        err = Status::FromErrorString(
            "Trying to create a temporary region for the result "
            "but one exists");
        return;
      }

      const lldb::addr_t load_addr = process_address + m_offset;

      ExecutionContextScope *exe_scope = frame_sp.get();
      if (!exe_scope)
        exe_scope = map.GetBestExecutionContextScope();

      auto byte_size_or_err = m_type.GetByteSize(exe_scope);
      if (!byte_size_or_err) {
        err = Status::FromError(byte_size_or_err.takeError());
        return;
      }
      auto byte_size = *byte_size_or_err;

      std::optional<size_t> opt_bit_align = m_type.GetTypeBitAlign(exe_scope);
      if (!opt_bit_align) {
        err = Status::FromErrorStringWithFormatv(
            "can't get the alignment of type  \"{0}\"", m_type.GetTypeName());
        return;
      }

      size_t byte_align = (*opt_bit_align + 7) / 8;

      const bool zero_memory = true;
      if (auto address_or_error = map.Malloc(
              byte_size, byte_align,
              lldb::ePermissionsReadable | lldb::ePermissionsWritable,
              IRMemoryMap::eAllocationPolicyMirror, zero_memory)) {
        m_temporary_allocation = *address_or_error;
      } else {
        err = Status::FromErrorStringWithFormat(
            "couldn't allocate a temporary region for the result: %s",
            toString(address_or_error.takeError()).c_str());
        return;
      }

      m_temporary_allocation_size = byte_size;

      Status pointer_write_error;

      map.WritePointerToMemory(load_addr, m_temporary_allocation,
                               pointer_write_error);

      if (!pointer_write_error.Success()) {
        err = Status::FromErrorStringWithFormat(
            "couldn't write the address of the "
            "temporary region for the result: %s",
            pointer_write_error.AsCString());
      }
    }
  }

  void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                     lldb::addr_t process_address, lldb::addr_t frame_top,
                     lldb::addr_t frame_bottom, Status &err) override {
    err.Clear();

    ExecutionContextScope *exe_scope = frame_sp.get();
    if (!exe_scope)
      exe_scope = map.GetBestExecutionContextScope();

    if (!exe_scope) {
      err = Status::FromErrorString(
          "Couldn't dematerialize a result variable: invalid "
          "execution context scope");
      return;
    }

    lldb::addr_t address;
    Status read_error;
    const lldb::addr_t load_addr = process_address + m_offset;

    map.ReadPointerFromMemory(&address, load_addr, read_error);

    if (!read_error.Success()) {
      err = Status::FromErrorString(
          "Couldn't dematerialize a result variable: couldn't "
          "read its address");
      return;
    }

    lldb::TargetSP target_sp = exe_scope->CalculateTarget();

    if (!target_sp) {
      err = Status::FromErrorString(
          "Couldn't dematerialize a result variable: no target");
      return;
    }

    auto type_system_or_err =
        target_sp->GetScratchTypeSystemForLanguage(m_type.GetMinimumLanguage());

    if (auto error = type_system_or_err.takeError()) {
      err = Status::FromErrorStringWithFormat(
          "Couldn't dematerialize a result variable: "
          "couldn't get the corresponding type "
          "system: %s",
          llvm::toString(std::move(error)).c_str());
      return;
    }
    auto ts = *type_system_or_err;
    if (!ts) {
      err = Status::FromErrorStringWithFormat(
          "Couldn't dematerialize a result variable: "
          "couldn't corresponding type system is "
          "no longer live.");
      return;
    }
    PersistentExpressionState *persistent_state =
        ts->GetPersistentExpressionState();

    if (!persistent_state) {
      err = Status::FromErrorString(
          "Couldn't dematerialize a result variable: "
          "corresponding type system doesn't handle persistent "
          "variables");
      return;
    }

    ConstString name = m_delegate
                           ? m_delegate->GetName()
                           : persistent_state->GetNextPersistentVariableName();

    lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(
        exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize());

    if (!ret) {
      err = Status::FromErrorStringWithFormatv(
          "couldn't dematerialize a result variable: failed to make persistent "
          "variable {0}",
          name);
      return;
    }

    lldb::ProcessSP process_sp =
        map.GetBestExecutionContextScope()->CalculateProcess();

    if (m_delegate) {
      m_delegate->DidDematerialize(ret);
    }

    bool can_persist = m_is_program_reference &&
                       !(address >= frame_bottom && address < frame_top);

    if (can_persist && m_keep_in_memory) {
      ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name,
                                                      address, eAddressTypeLoad,
                                                      map.GetAddressByteSize());
    }

    ret->ValueUpdated();

    const size_t pvar_byte_size =
        llvm::expectedToOptional(ret->GetByteSize()).value_or(0);
    uint8_t *pvar_data = ret->GetValueBytes();

    map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);

    if (!read_error.Success()) {
      err = Status::FromErrorString(
          "Couldn't dematerialize a result variable: couldn't read its memory");
      return;
    }

    if (!can_persist || !m_keep_in_memory) {
      ret->m_flags |= ExpressionVariable::EVNeedsAllocation;

      if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
        Status free_error;
        map.Free(m_temporary_allocation, free_error);
      }
    } else {
      ret->m_flags |= m_is_program_reference
                          ? ExpressionVariable::EVIsProgramReference
                          : ExpressionVariable::EVIsLLDBAllocated;
    }

    m_temporary_allocation = LLDB_INVALID_ADDRESS;
    m_temporary_allocation_size = 0;
  }

  void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
                 Log *log) override {
    StreamString dump_stream;

    const lldb::addr_t load_addr = process_address + m_offset;

    dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr);

    Status err;

    lldb::addr_t ptr = LLDB_INVALID_ADDRESS;

    {
      dump_stream.PutCString("Pointer:\n");

      DataBufferHeap data(m_size, 0);

      map.ReadMemory(data.GetBytes(), load_addr, m_size, err);

      if (!err.Success()) {
        dump_stream.PutCString("  <could not be read>\n");
      } else {
        DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
                                map.GetByteOrder(), map.GetAddressByteSize());

        DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
                     load_addr);

        lldb::offset_t offset = 0;

        ptr = extractor.GetAddress(&offset);

        dump_stream.PutChar('\n');
      }
    }

    if (m_temporary_allocation == LLDB_INVALID_ADDRESS) {
      dump_stream.PutCString("Points to process memory:\n");
    } else {
      dump_stream.PutCString("Temporary allocation:\n");
    }

    if (ptr == LLDB_INVALID_ADDRESS) {
      dump_stream.PutCString("  <could not be be found>\n");
    } else {
      DataBufferHeap data(m_temporary_allocation_size, 0);

      map.ReadMemory(data.GetBytes(), m_temporary_allocation,
                     m_temporary_allocation_size, err);

      if (!err.Success()) {
        dump_stream.PutCString("  <could not be read>\n");
      } else {
        DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
                     load_addr);

        dump_stream.PutChar('\n');
      }
    }

    log->PutString(dump_stream.GetString());
  }

  void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
    if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) {
      Status free_error;

      map.Free(m_temporary_allocation, free_error);
    }

    m_temporary_allocation = LLDB_INVALID_ADDRESS;
    m_temporary_allocation_size = 0;
  }

private:
  CompilerType m_type;
  /// This is used both to control whether this result entity can (and should)
  /// track the value in inferior memory, as well as to control whether LLDB
  /// needs to allocate memory for the variable during materialization.
  bool m_is_program_reference;
  bool m_keep_in_memory;

  lldb::addr_t m_temporary_allocation = LLDB_INVALID_ADDRESS;
  size_t m_temporary_allocation_size = 0;
  Materializer::PersistentVariableDelegate *m_delegate;
};

uint32_t Materializer::AddResultVariable(const CompilerType &type,
                                         bool is_program_reference,
                                         bool keep_in_memory,
                                         PersistentVariableDelegate *delegate,
                                         Status &err) {
  EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
  *iter = std::make_unique<EntityResultVariable>(type, is_program_reference,
                                                 keep_in_memory, delegate);
  uint32_t ret = AddStructMember(**iter);
  (*iter)->SetOffset(ret);
  return ret;
}

class EntitySymbol : public Materializer::Entity {
public:
  EntitySymbol(const Symbol &symbol) : Entity(), m_symbol(symbol) {
    // Hard-coding to maximum size of a symbol
    m_size = g_default_var_byte_size;
    m_alignment = g_default_var_alignment;
  }

  void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                   lldb::addr_t process_address, Status &err) override {
    Log *log = GetLog(LLDBLog::Expressions);

    const lldb::addr_t load_addr = process_address + m_offset;

    LLDB_LOG(log, "EntitySymbol::Materialize [address = {0:x}, m_symbol = {1}]",
             (uint64_t)load_addr, m_symbol.GetName());

    const Address sym_address = m_symbol.GetAddress();

    ExecutionContextScope *exe_scope = frame_sp.get();
    if (!exe_scope)
      exe_scope = map.GetBestExecutionContextScope();

    lldb::TargetSP target_sp;

    if (exe_scope)
      target_sp = map.GetBestExecutionContextScope()->CalculateTarget();

    if (!target_sp) {
      err = Status::FromErrorStringWithFormatv(
          "couldn't resolve symbol {0} because there is no target",
          m_symbol.GetName());
      return;
    }

    lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get());

    if (resolved_address == LLDB_INVALID_ADDRESS)
      resolved_address = sym_address.GetFileAddress();

    Status pointer_write_error;

    map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);

    if (!pointer_write_error.Success()) {
      err = Status::FromErrorStringWithFormatv(
          "couldn't write the address of symbol {0}: {1}", m_symbol.GetName(),
          pointer_write_error.AsCString());
      return;
    }
  }

  void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                     lldb::addr_t process_address, lldb::addr_t frame_top,
                     lldb::addr_t frame_bottom, Status &err) override {
    Log *log = GetLog(LLDBLog::Expressions);

    const lldb::addr_t load_addr = process_address + m_offset;

    LLDB_LOG(log,
             "EntitySymbol::Dematerialize [address = {0:x}, m_symbol = {1}]",
             (uint64_t)load_addr, m_symbol.GetName());

    // no work needs to be done
  }

  void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
                 Log *log) override {
    StreamString dump_stream;

    Status err;

    const lldb::addr_t load_addr = process_address + m_offset;

    dump_stream.Format("{0:x}: EntitySymbol ({1})\n", load_addr,
                       m_symbol.GetName());

    {
      dump_stream.PutCString("Pointer:\n");

      DataBufferHeap data(m_size, 0);

      map.ReadMemory(data.GetBytes(), load_addr, m_size, err);

      if (!err.Success()) {
        dump_stream.PutCString("  <could not be read>\n");
      } else {
        DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
                     load_addr);

        dump_stream.PutChar('\n');
      }
    }

    log->PutString(dump_stream.GetString());
  }

  void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}

private:
  Symbol m_symbol;
};

uint32_t Materializer::AddSymbol(const Symbol &symbol_sp, Status &err) {
  EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
  *iter = std::make_unique<EntitySymbol>(symbol_sp);
  uint32_t ret = AddStructMember(**iter);
  (*iter)->SetOffset(ret);
  return ret;
}

class EntityRegister : public Materializer::Entity {
public:
  EntityRegister(const RegisterInfo &register_info)
      : Entity(), m_register_info(register_info) {
    // Hard-coding alignment conservatively
    m_size = m_register_info.byte_size;
    m_alignment = m_register_info.byte_size;
  }

  void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                   lldb::addr_t process_address, Status &err) override {
    Log *log = GetLog(LLDBLog::Expressions);

    const lldb::addr_t load_addr = process_address + m_offset;

    LLDB_LOGF(log,
              "EntityRegister::Materialize [address = 0x%" PRIx64
              ", m_register_info = %s]",
              (uint64_t)load_addr, m_register_info.name);

    RegisterValue reg_value;

    if (!frame_sp.get()) {
      err = Status::FromErrorStringWithFormat(
          "couldn't materialize register %s without a stack frame",
          m_register_info.name);
      return;
    }

    lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();

    if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) {
      err = Status::FromErrorStringWithFormat(
          "couldn't read the value of register %s", m_register_info.name);
      return;
    }

    if (reg_value.GetByteSize() != m_register_info.byte_size) {
      err = Status::FromErrorStringWithFormat(
          "data for register %s had size %llu but we expected %llu",
          m_register_info.name, (unsigned long long)reg_value.GetByteSize(),
          (unsigned long long)m_register_info.byte_size);
      return;
    }

    lldb_private::DataBufferHeap buf(reg_value.GetByteSize(), 0);
    reg_value.GetAsMemoryData(m_register_info, buf.GetBytes(),
                              buf.GetByteSize(), map.GetByteOrder(), err);
    if (!err.Success())
      return;

    m_register_contents = std::make_shared<DataBufferHeap>(buf);

    Status write_error;

    map.WriteMemory(load_addr, buf.GetBytes(), reg_value.GetByteSize(),
                    write_error);

    if (!write_error.Success()) {
      err = Status::FromErrorStringWithFormat(
          "couldn't write the contents of register %s: %s",
          m_register_info.name, write_error.AsCString());
      return;
    }
  }

  void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                     lldb::addr_t process_address, lldb::addr_t frame_top,
                     lldb::addr_t frame_bottom, Status &err) override {
    Log *log = GetLog(LLDBLog::Expressions);

    const lldb::addr_t load_addr = process_address + m_offset;

    LLDB_LOGF(log,
              "EntityRegister::Dematerialize [address = 0x%" PRIx64
              ", m_register_info = %s]",
              (uint64_t)load_addr, m_register_info.name);

    Status extract_error;

    DataExtractor register_data;

    if (!frame_sp.get()) {
      err = Status::FromErrorStringWithFormat(
          "couldn't dematerialize register %s without a stack frame",
          m_register_info.name);
      return;
    }

    lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();

    map.GetMemoryData(register_data, load_addr, m_register_info.byte_size,
                      extract_error);

    if (!extract_error.Success()) {
      err = Status::FromErrorStringWithFormat(
          "couldn't get the data for register %s: %s", m_register_info.name,
          extract_error.AsCString());
      return;
    }

    if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(),
                register_data.GetByteSize())) {
      // No write required, and in particular we avoid errors if the register
      // wasn't writable

      m_register_contents.reset();
      return;
    }

    m_register_contents.reset();

    RegisterValue register_value(register_data.GetData(),
                                 register_data.GetByteOrder());

    if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) {
      err = Status::FromErrorStringWithFormat(
          "couldn't write the value of register %s", m_register_info.name);
      return;
    }
  }

  void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
                 Log *log) override {
    StreamString dump_stream;

    Status err;

    const lldb::addr_t load_addr = process_address + m_offset;

    dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr,
                       m_register_info.name);

    {
      dump_stream.PutCString("Value:\n");

      DataBufferHeap data(m_size, 0);

      map.ReadMemory(data.GetBytes(), load_addr, m_size, err);

      if (!err.Success()) {
        dump_stream.PutCString("  <could not be read>\n");
      } else {
        DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
                     load_addr);

        dump_stream.PutChar('\n');
      }
    }

    log->PutString(dump_stream.GetString());
  }

  void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}

private:
  RegisterInfo m_register_info;
  lldb::DataBufferSP m_register_contents;
};

uint32_t Materializer::AddRegister(const RegisterInfo &register_info,
                                   Status &err) {
  EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
  *iter = std::make_unique<EntityRegister>(register_info);
  uint32_t ret = AddStructMember(**iter);
  (*iter)->SetOffset(ret);
  return ret;
}

Materializer::~Materializer() {
  DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();

  if (dematerializer_sp)
    dematerializer_sp->Wipe();
}

Materializer::DematerializerSP
Materializer::Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                          lldb::addr_t process_address, Status &error) {
  ExecutionContextScope *exe_scope = frame_sp.get();
  if (!exe_scope)
    exe_scope = map.GetBestExecutionContextScope();

  DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();

  if (dematerializer_sp) {
    error =
        Status::FromErrorString("Couldn't materialize: already materialized");
  }

  DematerializerSP ret(
      new Dematerializer(*this, frame_sp, map, process_address));

  if (!exe_scope) {
    error =
        Status::FromErrorString("Couldn't materialize: target doesn't exist");
  }

  for (EntityUP &entity_up : m_entities) {
    entity_up->Materialize(frame_sp, map, process_address, error);

    if (!error.Success())
      return DematerializerSP();
  }

  if (Log *log = GetLog(LLDBLog::Expressions)) {
    LLDB_LOGF(
        log,
        "Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64
        ") materialized:",
        static_cast<void *>(frame_sp.get()), process_address);
    for (EntityUP &entity_up : m_entities)
      entity_up->DumpToLog(map, process_address, log);
  }

  m_dematerializer_wp = ret;

  return ret;
}

void Materializer::Dematerializer::Dematerialize(Status &error,
                                                 lldb::addr_t frame_bottom,
                                                 lldb::addr_t frame_top) {
  lldb::StackFrameSP frame_sp;

  lldb::ThreadSP thread_sp = m_thread_wp.lock();
  if (thread_sp)
    frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);

  ExecutionContextScope *exe_scope = frame_sp.get();
  if (!exe_scope)
    exe_scope = m_map->GetBestExecutionContextScope();

  if (!IsValid()) {
    error = Status::FromErrorString(
        "Couldn't dematerialize: invalid dematerializer");
  }

  if (!exe_scope) {
    error = Status::FromErrorString("Couldn't dematerialize: target is gone");
  } else {
    if (Log *log = GetLog(LLDBLog::Expressions)) {
      LLDB_LOGF(log,
                "Materializer::Dematerialize (frame_sp = %p, process_address "
                "= 0x%" PRIx64 ") about to dematerialize:",
                static_cast<void *>(frame_sp.get()), m_process_address);
      for (EntityUP &entity_up : m_materializer->m_entities)
        entity_up->DumpToLog(*m_map, m_process_address, log);
    }

    for (EntityUP &entity_up : m_materializer->m_entities) {
      entity_up->Dematerialize(frame_sp, *m_map, m_process_address, frame_top,
                               frame_bottom, error);

      if (!error.Success())
        break;
    }
  }

  Wipe();
}

void Materializer::Dematerializer::Wipe() {
  if (!IsValid())
    return;

  for (EntityUP &entity_up : m_materializer->m_entities) {
    entity_up->Wipe(*m_map, m_process_address);
  }

  m_materializer = nullptr;
  m_map = nullptr;
  m_process_address = LLDB_INVALID_ADDRESS;
}

Materializer::PersistentVariableDelegate::PersistentVariableDelegate() =
    default;
Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() =
    default;
