//===-- 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::FromErrorStringWithFormat(
          "couldn't write %s to the target: %s",
          m_persistent_variable_sp->GetName().AsCString(),
          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_LOGF(log,
              "EntityPersistentVariable::Materialize [address = 0x%" PRIx64
              ", m_name = %s, m_flags = 0x%hx]",
              (uint64_t)load_addr,
              m_persistent_variable_sp->GetName().AsCString(),
              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::FromErrorStringWithFormat(
            "couldn't write the location of %s to memory: %s",
            m_persistent_variable_sp->GetName().AsCString(),
            write_error.AsCString());
      }
    } else {
      err = Status::FromErrorStringWithFormat(
          "no materialization happened for persistent variable %s",
          m_persistent_variable_sp->GetName().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,
              "EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64
              ", m_name = %s, m_flags = 0x%hx]",
              (uint64_t)process_address + m_offset,
              m_persistent_variable_sp->GetName().AsCString(),
              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::FromErrorStringWithFormat(
          "no dematerialization happened for persistent variable %s",
          m_persistent_variable_sp->GetName().AsCString());
      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.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n",
                       load_addr,
                       m_persistent_variable_sp->GetName().AsCString());

    {
      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::FromErrorStringWithFormat(
          "couldn't get a value object for variable %s", GetName().AsCString());
      return;
    }

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

    if (valobj_error.Fail()) {
      err = Status::FromErrorStringWithFormat(
          "couldn't get the value of variable %s: %s", GetName().AsCString(),
          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::FromErrorStringWithFormat(
            "couldn't read contents of reference variable %s: %s",
            GetName().AsCString(), 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::FromErrorStringWithFormat(
            "couldn't write the contents of reference "
            "variable %s to memory: %s",
            GetName().AsCString(), 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::FromErrorStringWithFormat(
              "couldn't write the address of variable %s to memory: %s",
              GetName().AsCString(), write_error.AsCString());
          return;
        }
      } else {
        DataExtractor data;
        Status extract_error;
        valobj_sp->GetData(data, extract_error);
        if (!extract_error.Success()) {
          err = Status::FromErrorStringWithFormat(
              "couldn't get the value of %s: %s", GetName().AsCString(),
              extract_error.AsCString());
          return;
        }

        if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
          err = Status::FromErrorStringWithFormat(
              "trying to create a temporary region for %s but one exists",
              GetName().AsCString());
          return;
        }

        if (data.GetByteSize() <
            llvm::expectedToOptional(GetByteSize(scope)).value_or(0)) {
          if (data.GetByteSize() == 0 && !LocationExpressionIsValid()) {
            err = Status::FromErrorStringWithFormat(
                "the variable '%s' has no location, "
                "it may have been optimized out",
                GetName().AsCString());
          } else {
            err = Status::FromErrorStringWithFormat(
                "size of variable %s (%" PRIu64
                ") is larger than the ValueObject's size (%" PRIu64 ")",
                GetName().AsCString(),
                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::FromErrorStringWithFormat(
              "can't get the type alignment for %s", GetName().AsCString());
          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::FromErrorStringWithFormat(
              "couldn't allocate a temporary region for %s: %s",
              GetName().AsCString(),
              toString(address_or_error.takeError()).c_str());
          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::FromErrorStringWithFormat(
              "couldn't write to the temporary region for %s: %s",
              GetName().AsCString(), 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::FromErrorStringWithFormat(
              "couldn't write the address of the temporary region for %s: %s",
              GetName().AsCString(), 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_LOGF(log,
              "EntityVariable::Dematerialize [address = 0x%" PRIx64
              ", m_variable_sp = %s]",
              (uint64_t)load_addr, GetName().AsCString());

    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::FromErrorStringWithFormat(
            "couldn't get a value object for variable %s",
            GetName().AsCString());
        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::FromErrorStringWithFormat(
            "couldn't get the data for variable %s", GetName().AsCString());
        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::FromErrorStringWithFormat(
              "couldn't write the new contents of %s back into the variable",
              GetName().AsCString());
          return;
        }
      }

      Status free_error;

      map.Free(m_temporary_allocation, free_error);

      if (!free_error.Success()) {
        err = Status::FromErrorStringWithFormat(
            "couldn't free the temporary region for %s: %s",
            GetName().AsCString(), 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::FromErrorStringWithFormat(
            "can't get the alignment of type  \"%s\"",
            m_type.GetTypeName().AsCString());
        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::FromErrorStringWithFormat(
          "couldn't dematerialize a result variable: "
          "failed to make persistent variable %s",
          name.AsCString());
      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_LOGF(log,
              "EntitySymbol::Materialize [address = 0x%" PRIx64
              ", m_symbol = %s]",
              (uint64_t)load_addr, m_symbol.GetName().AsCString());

    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::FromErrorStringWithFormat(
          "couldn't resolve symbol %s because there is no target",
          m_symbol.GetName().AsCString());
      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::FromErrorStringWithFormat(
          "couldn't write the address of symbol %s: %s",
          m_symbol.GetName().AsCString(), 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_LOGF(log,
              "EntitySymbol::Dematerialize [address = 0x%" PRIx64
              ", m_symbol = %s]",
              (uint64_t)load_addr, m_symbol.GetName().AsCString());

    // 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.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr,
                       m_symbol.GetName().AsCString());

    {
      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;
