//===-- 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;
    auto address_or_error = map.Malloc(
        llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
            .value_or(0),
        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 %s (0x%" PRIx64 ") successfully",
              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;

    map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue()
                 .GetScalar()
                 .ULongLong(),
             deallocate_error);

    m_persistent_variable_sp->m_live_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;
    }

    if ((m_persistent_variable_sp->m_flags &
             ExpressionVariable::EVIsProgramReference &&
         m_persistent_variable_sp->m_live_sp) ||
        m_persistent_variable_sp->m_flags &
            ExpressionVariable::EVIsLLDBAllocated) {
      Status write_error;

      map.WriteScalarToMemory(
          load_addr,
          m_persistent_variable_sp->m_live_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);
    }

    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 &&
          !m_persistent_variable_sp->m_live_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.get()->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;
        }
      }

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

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

      if (m_persistent_variable_sp->m_live_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.Printf("Pointer:\n");

      DataBufferHeap data(m_size, 0);

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

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

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

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

      lldb::addr_t target_address;

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

      if (!err.Success()) {
        dump_stream.Printf("  <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.Printf("  <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 {0} to memory: "
            "{0}",
            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.Printf("Pointer:\n");

      DataBufferHeap data(m_size, 0);

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

      if (!err.Success()) {
        dump_stream.Printf("  <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.Printf("Points to process memory:\n");
    } else {
      dump_stream.Printf("Temporary allocation:\n");
    }

    if (ptr == LLDB_INVALID_ADDRESS) {
      dump_stream.Printf("  <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.Printf("  <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.Printf("Pointer:\n");

      DataBufferHeap data(m_size, 0);

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

      if (!err.Success()) {
        dump_stream.Printf("  <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.Printf("Points to process memory:\n");
    } else {
      dump_stream.Printf("Temporary allocation:\n");
    }

    if (ptr == LLDB_INVALID_ADDRESS) {
      dump_stream.Printf("  <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.Printf("  <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}, 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.Printf("Pointer:\n");

      DataBufferHeap data(m_size, 0);

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

      if (!err.Success()) {
        dump_stream.Printf("  <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.Printf("Value:\n");

      DataBufferHeap data(m_size, 0);

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

      if (!err.Success()) {
        dump_stream.Printf("  <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;
