//===-- Materializer.cpp ----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Expression/Materializer.h"
#include "lldb/Symbol/ClangASTContext.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"

using namespace lldb_private;

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

void
Materializer::Entity::SetSizeAndAlignmentFromType (CompilerType &type)
{
    m_size = type.GetByteSize(nullptr);
    
    uint32_t bit_alignment = type.GetTypeBitAlign();
    
    if (bit_alignment % 8)
    {
        bit_alignment += 8;
        bit_alignment &= ~((uint32_t)0x111u);
    }
    
    m_alignment = bit_alignment / 8;
}

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 = 8;
        m_alignment = 8;
    }
    
    void MakeAllocation (IRMemoryMap &map, Error &err)
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

        // Allocate a spare memory area to store the persistent variable's contents.
        
        Error allocate_error;
        const bool zero_memory = false;
        
        lldb::addr_t mem = map.Malloc(m_persistent_variable_sp->GetByteSize(),
                                      8,
                                      lldb::ePermissionsReadable | lldb::ePermissionsWritable,
                                      IRMemoryMap::eAllocationPolicyMirror,
                                      zero_memory,
                                      allocate_error);
        
        if (!allocate_error.Success())
        {
            err.SetErrorStringWithFormat("couldn't allocate a memory area to store %s: %s", m_persistent_variable_sp->GetName().GetCString(), allocate_error.AsCString());
            return;
        }
        
        if (log)
            log->Printf("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());
        
        // Clear the flag if the variable will never be deallocated.
        
        if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget)
        {
            Error leak_error;
            map.Leak(mem, leak_error);
            m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVNeedsAllocation;
        }
        
        // Write the contents of the variable to the area.
        
        Error write_error;
        
        map.WriteMemory (mem,
                         m_persistent_variable_sp->GetValueBytes(),
                         m_persistent_variable_sp->GetByteSize(),
                         write_error);
        
        if (!write_error.Success())
        {
            err.SetErrorStringWithFormat ("couldn't write %s to the target: %s", m_persistent_variable_sp->GetName().AsCString(),
                                          write_error.AsCString());
            return;
        }
    }
    
    void DestroyAllocation (IRMemoryMap &map, Error &err)
    {
        Error 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.SetErrorStringWithFormat ("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,
                     Error &err) override
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

        const lldb::addr_t load_addr = process_address + m_offset;
    
        if (log)
        {
            log->Printf("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)
        {
            Error write_error;
                        
            map.WriteScalarToMemory(load_addr,
                                    m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(),
                                    map.GetAddressByteSize(),
                                    write_error);
            
            if (!write_error.Success())
            {
                err.SetErrorStringWithFormat("couldn't write the location of %s to memory: %s", m_persistent_variable_sp->GetName().AsCString(), write_error.AsCString());
            }
        }
        else
        {
            err.SetErrorStringWithFormat("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,
                       Error &err) override
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
        
        const lldb::addr_t load_addr = process_address + m_offset;

        if (log)
        {
            log->Printf("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;
                Error read_error;
                
                map.ReadPointerFromMemory(&location, load_addr, read_error);
                                
                if (!read_error.Success())
                {
                    err.SetErrorStringWithFormat("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,
                                                                                      m_persistent_variable_sp->GetByteSize());
                
                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.SetErrorStringWithFormat("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.SetErrorStringWithFormat("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)
            {                
                if (log)
                    log->Printf("Dematerializing %s from 0x%" PRIx64 " (size = %llu)", m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem, (unsigned long long)m_persistent_variable_sp->GetByteSize());
                
                // Read the contents of the spare memory area
                
                m_persistent_variable_sp->ValueUpdated ();
                
                Error read_error;
                
                map.ReadMemory(m_persistent_variable_sp->GetValueBytes(),
                               mem,
                               m_persistent_variable_sp->GetByteSize(),
                               read_error);
                
                if (!read_error.Success())
                {
                    err.SetErrorStringWithFormat ("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.SetErrorStringWithFormat("no dematerialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString());
            return;
        }
        
        lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess();
        if (!process_sp ||
            !process_sp->CanJIT())
        {
            // Allocations are not persistent so persistent variables cannot stay materialized.
            
            m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsAllocation;

            DestroyAllocation(map, err);
            if (!err.Success())
                return;
        }
        else 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;
        
        Error 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
            {
                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
                
                extractor.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 (m_persistent_variable_sp->GetByteSize(), 0);
            
                map.ReadMemory(data.GetBytes(), target_address, m_persistent_variable_sp->GetByteSize(), err);
                
                if (!err.Success())
                {
                    dump_stream.Printf("  <could not be read>\n");
                }
                else
                {
                    DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
                    
                    extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, target_address);
                    
                    dump_stream.PutChar('\n');
                }
            }
        }
        
        log->PutCString(dump_stream.GetData());
    }
    
    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,
                                     Error &err)
{
    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
    iter->reset (new EntityPersistentVariable (persistent_variable_sp, delegate));
    uint32_t ret = AddStructMember(**iter);
    (*iter)->SetOffset(ret);
    return ret;
}

class EntityVariable : public Materializer::Entity
{
public:
    EntityVariable (lldb::VariableSP &variable_sp) :
        Entity(),
        m_variable_sp(variable_sp),
        m_is_reference(false),
        m_temporary_allocation(LLDB_INVALID_ADDRESS),
        m_temporary_allocation_size(0)
    {
        // Hard-coding to maximum size of a pointer since all variables are materialized by reference
        m_size = 8;
        m_alignment = 8;
        m_is_reference = m_variable_sp->GetType()->GetForwardCompilerType ().IsReferenceType();
    }
    
    void Materialize(lldb::StackFrameSP &frame_sp,
                     IRMemoryMap &map,
                     lldb::addr_t process_address,
                     Error &err) override
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
        
        const lldb::addr_t load_addr = process_address + m_offset;
        if (log)
        {
            log->Printf("EntityVariable::Materialize [address = 0x%" PRIx64 ", m_variable_sp = %s]",
                        (uint64_t)load_addr,
                        m_variable_sp->GetName().AsCString());
        }
        
        ExecutionContextScope *scope = frame_sp.get();
        
        if (!scope)
            scope = map.GetBestExecutionContextScope();
        
        lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp);
        
        if (!valobj_sp)
        {
            err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString());
            return;
        }
        
        Error valobj_error = valobj_sp->GetError();
        
        if (valobj_error.Fail())
        {
            err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s", m_variable_sp->GetName().AsCString(), valobj_error.AsCString());
            return;
        }
        
        if (m_is_reference)
        {
            DataExtractor valobj_extractor;
            Error extract_error;
            valobj_sp->GetData(valobj_extractor, extract_error);
            
            if (!extract_error.Success())
            {
                err.SetErrorStringWithFormat("couldn't read contents of reference variable %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString());
                return;
            }
            
            lldb::offset_t offset = 0;
            lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset);
            
            Error write_error;
            map.WritePointerToMemory(load_addr, reference_addr, write_error);
            
            if (!write_error.Success())
            {
                err.SetErrorStringWithFormat("couldn't write the contents of reference variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
                return;
            }
        }
        else
        {
            AddressType address_type = eAddressTypeInvalid;
            const bool scalar_is_load_address = false;
            lldb::addr_t addr_of_valobj = valobj_sp->GetAddressOf(scalar_is_load_address, &address_type);
            if (addr_of_valobj != LLDB_INVALID_ADDRESS)
            {
                Error write_error;
                map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);
                
                if (!write_error.Success())
                {
                    err.SetErrorStringWithFormat("couldn't write the address of variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
                    return;
                }
            }
            else
            {
                DataExtractor data;
                Error extract_error;
                valobj_sp->GetData(data, extract_error);
                if (!extract_error.Success())
                {
                    err.SetErrorStringWithFormat("couldn't get the value of %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString());
                    return;
                }
                    
                if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
                {
                    err.SetErrorStringWithFormat("trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString());
                    return;
                }
                
                if (data.GetByteSize() != m_variable_sp->GetType()->GetByteSize())
                {
                    if (data.GetByteSize() == 0 && m_variable_sp->LocationExpression().IsValid() == false)
                    {
                        err.SetErrorStringWithFormat("the variable '%s' has no location, it may have been optimized out", m_variable_sp->GetName().AsCString());
                    }
                    else
                    {
                        err.SetErrorStringWithFormat("size of variable %s (%" PRIu64 ") disagrees with the ValueObject's size (%" PRIu64 ")",
                                                     m_variable_sp->GetName().AsCString(),
                                                     m_variable_sp->GetType()->GetByteSize(),
                                                     data.GetByteSize());
                    }
                    return;
                }
                
                size_t bit_align = m_variable_sp->GetType()->GetLayoutCompilerType ().GetTypeBitAlign();
                size_t byte_align = (bit_align + 7) / 8;
                
                if (!byte_align)
                    byte_align = 1;
                
                Error alloc_error;
                const bool zero_memory = false;

                m_temporary_allocation = map.Malloc(data.GetByteSize(),
                                                    byte_align,
                                                    lldb::ePermissionsReadable | lldb::ePermissionsWritable,
                                                    IRMemoryMap::eAllocationPolicyMirror,
                                                    zero_memory,
                                                    alloc_error);
                
                m_temporary_allocation_size = data.GetByteSize();
                
                m_original_data.reset(new DataBufferHeap(data.GetDataStart(), data.GetByteSize()));
                
                if (!alloc_error.Success())
                {
                    err.SetErrorStringWithFormat("couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString());
                    return;
                }
                
                Error write_error;
                
                map.WriteMemory(m_temporary_allocation, data.GetDataStart(), data.GetByteSize(), write_error);
                
                if (!write_error.Success())
                {
                    err.SetErrorStringWithFormat("couldn't write to the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
                    return;
                }
                
                Error pointer_write_error;
                
                map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error);
                
                if (!pointer_write_error.Success())
                {
                    err.SetErrorStringWithFormat("couldn't write the address of the temporary region for %s: %s", m_variable_sp->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,
                       Error &err) override
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

        const lldb::addr_t load_addr = process_address + m_offset;
        if (log)
        {
            log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64 ", m_variable_sp = %s]",
                        (uint64_t)load_addr,
                        m_variable_sp->GetName().AsCString());
        }
        
        if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
        {
            ExecutionContextScope *scope = frame_sp.get();
            
            if (!scope)
                scope = map.GetBestExecutionContextScope();
            
            lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp);
            
            if (!valobj_sp)
            {
                err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString());
                return;
            }
            
            lldb_private::DataExtractor data;
            
            Error extract_error;
            
            map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(), extract_error);
            
            if (!extract_error.Success())
            {
                err.SetErrorStringWithFormat("couldn't get the data for variable %s", m_variable_sp->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;
                }
            }
            
            Error set_error;
            
            if (actually_write)
            {
                valobj_sp->SetData(data, set_error);
                
                if (!set_error.Success())
                {
                    err.SetErrorStringWithFormat("couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString());
                    return;
                }
            }
            
            Error free_error;
            
            map.Free(m_temporary_allocation, free_error);
            
            if (!free_error.Success())
            {
                err.SetErrorStringWithFormat("couldn't free the temporary region for %s: %s", m_variable_sp->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);
        
        Error 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());
                
                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
                
                lldb::offset_t offset;
                
                ptr = extractor.GetPointer(&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
            {
                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
                
                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
                
                dump_stream.PutChar('\n');
            }
        }
        
        log->PutCString(dump_stream.GetData());
    }
    
    void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
    {
        if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
        {
            Error free_error;
            
            map.Free(m_temporary_allocation, free_error);
            
            m_temporary_allocation = LLDB_INVALID_ADDRESS;
            m_temporary_allocation_size = 0;
        }

    }

private:
    lldb::VariableSP    m_variable_sp;
    bool                m_is_reference;
    lldb::addr_t        m_temporary_allocation;
    size_t              m_temporary_allocation_size;
    lldb::DataBufferSP  m_original_data;
};

uint32_t
Materializer::AddVariable (lldb::VariableSP &variable_sp, Error &err)
{
    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
    iter->reset (new EntityVariable (variable_sp));
    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_temporary_allocation(LLDB_INVALID_ADDRESS),
        m_temporary_allocation_size(0),
        m_delegate(delegate)
    {
        // Hard-coding to maximum size of a pointer since all results are materialized by reference
        m_size = 8;
        m_alignment = 8;
    }
    
    void Materialize(lldb::StackFrameSP &frame_sp,
                     IRMemoryMap &map,
                     lldb::addr_t process_address,
                     Error &err) override
    {
        if (!m_is_program_reference)
        {
            if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
            {
                err.SetErrorString("Trying to create a temporary region for the result but one exists");
                return;
            }
            
            const lldb::addr_t load_addr = process_address + m_offset;

            size_t byte_size = m_type.GetByteSize(nullptr);
            size_t bit_align = m_type.GetTypeBitAlign();
            size_t byte_align = (bit_align + 7) / 8;
            
            if (!byte_align)
                byte_align = 1;
            
            Error alloc_error;
            const bool zero_memory = true;

            m_temporary_allocation = map.Malloc(byte_size,
                                                byte_align,
                                                lldb::ePermissionsReadable | lldb::ePermissionsWritable,
                                                IRMemoryMap::eAllocationPolicyMirror,
                                                zero_memory,
                                                alloc_error);
            m_temporary_allocation_size = byte_size;
            
            if (!alloc_error.Success())
            {
                err.SetErrorStringWithFormat("couldn't allocate a temporary region for the result: %s", alloc_error.AsCString());
                return;
            }
                        
            Error pointer_write_error;
            
            map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error);
            
            if (!pointer_write_error.Success())
            {
                err.SetErrorStringWithFormat("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,
                       Error &err) override
    {
        err.Clear();
        
        ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
        
        if (!exe_scope)
        {
            err.SetErrorString("Couldn't dematerialize a result variable: invalid execution context scope");
            return;
        }
        
        lldb::addr_t address;
        Error read_error;
        const lldb::addr_t load_addr = process_address + m_offset;
        
        map.ReadPointerFromMemory (&address, load_addr, read_error);
        
        if (!read_error.Success())
        {
            err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its address");
            return;
        }
        
        lldb::TargetSP target_sp = exe_scope->CalculateTarget();
        
        if (!target_sp)
        {
            err.SetErrorString("Couldn't dematerialize a result variable: no target");
            return;
        }
        
        Error type_system_error;
        TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(&type_system_error, m_type.GetMinimumLanguage());
        
        if (!type_system)
        {
            err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: couldn't get the corresponding type system: %s", type_system_error.AsCString());
            return;
        }
        
        PersistentExpressionState *persistent_state = type_system->GetPersistentExpressionState();
        
        if (!persistent_state)
        {
            err.SetErrorString("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.SetErrorStringWithFormat("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 && process_sp && process_sp->CanJIT() && !(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 = ret->GetByteSize();
        uint8_t *pvar_data = ret->GetValueBytes();
                
        map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);
        
        if (!read_error.Success())
        {
            err.SetErrorString("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)
            {
                Error free_error;
                map.Free(m_temporary_allocation, free_error);
            }
        }
        else
        {
            ret->m_flags |= 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);
        
        Error 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());
                
                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
                
                lldb::offset_t offset;
                
                ptr = extractor.GetPointer(&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
            {
                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
                
                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
                
                dump_stream.PutChar('\n');
            }
        }
        
        log->PutCString(dump_stream.GetData());
    }
    
    void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
    {
        if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS)
        {
            Error free_error;
            
            map.Free(m_temporary_allocation, free_error);
        }
        
        m_temporary_allocation = LLDB_INVALID_ADDRESS;
        m_temporary_allocation_size = 0;
    }

private:
    CompilerType    m_type;
    bool            m_is_program_reference;
    bool            m_keep_in_memory;
    
    lldb::addr_t    m_temporary_allocation;
    size_t          m_temporary_allocation_size;
    Materializer::PersistentVariableDelegate *m_delegate;
};

uint32_t
Materializer::AddResultVariable (const CompilerType &type,
                                 bool is_program_reference,
                                 bool keep_in_memory,
                                 PersistentVariableDelegate *delegate,
                                 Error &err)
{
    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
    iter->reset (new 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 = 8;
        m_alignment = 8;
    }
    
    void Materialize(lldb::StackFrameSP &frame_sp,
                     IRMemoryMap &map,
                     lldb::addr_t process_address,
                     Error &err) override
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

        const lldb::addr_t load_addr = process_address + m_offset;

        if (log)
        {
            log->Printf("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 = map.GetBestExecutionContextScope();
        
        lldb::TargetSP target_sp;
        
        if (exe_scope)
            target_sp = map.GetBestExecutionContextScope()->CalculateTarget();
        
        if (!target_sp)
        {
            err.SetErrorStringWithFormat("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();
        
        Error pointer_write_error;
        
        map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);
        
        if (!pointer_write_error.Success())
        {
            err.SetErrorStringWithFormat("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,
                       Error &err) override
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

        const lldb::addr_t load_addr = process_address + m_offset;

        if (log)
        {
            log->Printf("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;
        
        Error 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
            {
                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
                
                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
                
                dump_stream.PutChar('\n');
            }
        }
        
        log->PutCString(dump_stream.GetData());
    }
    
    void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
    {
    }

private:
    Symbol m_symbol;
};

uint32_t
Materializer::AddSymbol (const Symbol &symbol_sp, Error &err)
{
    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
    iter->reset (new 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,
                     Error &err) override
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
        
        const lldb::addr_t load_addr = process_address + m_offset;

        if (log)
        {
            log->Printf("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.SetErrorStringWithFormat("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.SetErrorStringWithFormat("couldn't read the value of register %s", m_register_info.name);
            return;
        }
        
        DataExtractor register_data;
        
        if (!reg_value.GetData(register_data))
        {
            err.SetErrorStringWithFormat("couldn't get the data for register %s", m_register_info.name);
            return;
        }
        
        if (register_data.GetByteSize() != m_register_info.byte_size)
        {
            err.SetErrorStringWithFormat("data for register %s had size %llu but we expected %llu", m_register_info.name, (unsigned long long)register_data.GetByteSize(), (unsigned long long)m_register_info.byte_size);
            return;
        }
        
        m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(), register_data.GetByteSize()));
        
        Error write_error;
        
        map.WriteMemory(load_addr, register_data.GetDataStart(), register_data.GetByteSize(), write_error);
        
        if (!write_error.Success())
        {
            err.SetErrorStringWithFormat("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,
                       Error &err) override
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
        
        const lldb::addr_t load_addr = process_address + m_offset;

        if (log)
        {
            log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64 ", m_register_info = %s]",
                        (uint64_t)load_addr,
                        m_register_info.name);
        }
        
        Error extract_error;
        
        DataExtractor register_data;
        
        if (!frame_sp.get())
        {
            err.SetErrorStringWithFormat("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.SetErrorStringWithFormat("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 (const_cast<uint8_t*>(register_data.GetDataStart()), register_data.GetByteSize(), register_data.GetByteOrder());
        
        if (!reg_context_sp->WriteRegister(&m_register_info, register_value))
        {
            err.SetErrorStringWithFormat("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;
        
        Error 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
            {
                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
                
                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
                
                dump_stream.PutChar('\n');
            }
        }
        
        log->PutCString(dump_stream.GetData());
    }
    
    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, Error &err)
{
    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
    iter->reset (new EntityRegister (register_info));
    uint32_t ret = AddStructMember(**iter);
    (*iter)->SetOffset(ret);
    return ret;
}

Materializer::Materializer () :
    m_dematerializer_wp(),
    m_current_offset(0),
    m_struct_alignment(8)
{
}

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, Error &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.SetErrorToGenericError();
        error.SetErrorString("Couldn't materialize: already materialized");
    }

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

    if (!exe_scope)
    {
        error.SetErrorToGenericError();
        error.SetErrorString("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 = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
    {
        log->Printf("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 (Error &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 = m_map->GetBestExecutionContextScope();

    if (!IsValid())
    {
        error.SetErrorToGenericError();
        error.SetErrorString("Couldn't dematerialize: invalid dematerializer");
    }

    if (!exe_scope)
    {
        error.SetErrorToGenericError();
        error.SetErrorString("Couldn't dematerialize: target is gone");
    }
    else
    {
        if (Log *log =lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
        {
            log->Printf("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;
