xref: /src/contrib/llvm-project/lldb/source/Expression/Materializer.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1cfca06d7SDimitry Andric //===-- Materializer.cpp --------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
914f1b3e8SDimitry Andric #include "lldb/Expression/Materializer.h"
1074a628f7SDimitry Andric #include "lldb/Core/DumpDataExtractor.h"
11f034231aSEd Maste #include "lldb/Core/ValueObjectConstResult.h"
12f034231aSEd Maste #include "lldb/Core/ValueObjectVariable.h"
13e81d9d49SDimitry Andric #include "lldb/Expression/ExpressionVariable.h"
14f034231aSEd Maste #include "lldb/Symbol/Symbol.h"
15f034231aSEd Maste #include "lldb/Symbol/Type.h"
16f034231aSEd Maste #include "lldb/Symbol/Variable.h"
17f034231aSEd Maste #include "lldb/Target/ExecutionContext.h"
18f034231aSEd Maste #include "lldb/Target/RegisterContext.h"
19f034231aSEd Maste #include "lldb/Target/StackFrame.h"
20f034231aSEd Maste #include "lldb/Target/Target.h"
21f034231aSEd Maste #include "lldb/Target/Thread.h"
22145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
2374a628f7SDimitry Andric #include "lldb/Utility/Log.h"
2494994d37SDimitry Andric #include "lldb/Utility/RegisterValue.h"
254b4fe385SDimitry Andric #include "lldb/lldb-forward.h"
26f034231aSEd Maste 
275f29bb8aSDimitry Andric #include <memory>
28e3b55780SDimitry Andric #include <optional>
295f29bb8aSDimitry Andric 
30f034231aSEd Maste using namespace lldb_private;
31f034231aSEd Maste 
324b4fe385SDimitry Andric // FIXME: these should be retrieved from the target
334b4fe385SDimitry Andric //        instead of being hard-coded. Currently we
344b4fe385SDimitry Andric //        assume that persistent vars are materialized
354b4fe385SDimitry Andric //        as references, and thus pick the size of a
364b4fe385SDimitry Andric //        64-bit pointer.
374b4fe385SDimitry Andric static constexpr uint32_t g_default_var_alignment = 8;
384b4fe385SDimitry Andric static constexpr uint32_t g_default_var_byte_size = 8;
394b4fe385SDimitry Andric 
AddStructMember(Entity & entity)4014f1b3e8SDimitry Andric uint32_t Materializer::AddStructMember(Entity &entity) {
41f034231aSEd Maste   uint32_t size = entity.GetSize();
42f034231aSEd Maste   uint32_t alignment = entity.GetAlignment();
43f034231aSEd Maste 
44f034231aSEd Maste   uint32_t ret;
45f034231aSEd Maste 
46f034231aSEd Maste   if (m_current_offset == 0)
47f034231aSEd Maste     m_struct_alignment = alignment;
48f034231aSEd Maste 
49f034231aSEd Maste   if (m_current_offset % alignment)
50f034231aSEd Maste     m_current_offset += (alignment - (m_current_offset % alignment));
51f034231aSEd Maste 
52f034231aSEd Maste   ret = m_current_offset;
53f034231aSEd Maste 
54f034231aSEd Maste   m_current_offset += size;
55f034231aSEd Maste 
56f034231aSEd Maste   return ret;
57f034231aSEd Maste }
58f034231aSEd Maste 
5914f1b3e8SDimitry Andric class EntityPersistentVariable : public Materializer::Entity {
60f034231aSEd Maste public:
EntityPersistentVariable(lldb::ExpressionVariableSP & persistent_variable_sp,Materializer::PersistentVariableDelegate * delegate)61e81d9d49SDimitry Andric   EntityPersistentVariable(lldb::ExpressionVariableSP &persistent_variable_sp,
6214f1b3e8SDimitry Andric                            Materializer::PersistentVariableDelegate *delegate)
6314f1b3e8SDimitry Andric       : Entity(), m_persistent_variable_sp(persistent_variable_sp),
6414f1b3e8SDimitry Andric         m_delegate(delegate) {
6514f1b3e8SDimitry Andric     // Hard-coding to maximum size of a pointer since persistent variables are
6614f1b3e8SDimitry Andric     // materialized by reference
674b4fe385SDimitry Andric     m_size = g_default_var_byte_size;
684b4fe385SDimitry Andric     m_alignment = g_default_var_alignment;
69f034231aSEd Maste   }
70f034231aSEd Maste 
MakeAllocation(IRMemoryMap & map,Status & err)71b76161e4SDimitry Andric   void MakeAllocation(IRMemoryMap &map, Status &err) {
72145449b1SDimitry Andric     Log *log = GetLog(LLDBLog::Expressions);
73f034231aSEd Maste 
74f73363f1SDimitry Andric     // Allocate a spare memory area to store the persistent variable's
75f73363f1SDimitry Andric     // contents.
76f034231aSEd Maste 
77b76161e4SDimitry Andric     Status allocate_error;
78e81d9d49SDimitry Andric     const bool zero_memory = false;
79f034231aSEd Maste 
8014f1b3e8SDimitry Andric     lldb::addr_t mem = map.Malloc(
81145449b1SDimitry Andric         m_persistent_variable_sp->GetByteSize().value_or(0), 8,
82f034231aSEd Maste         lldb::ePermissionsReadable | lldb::ePermissionsWritable,
8314f1b3e8SDimitry Andric         IRMemoryMap::eAllocationPolicyMirror, zero_memory, allocate_error);
84f034231aSEd Maste 
8514f1b3e8SDimitry Andric     if (!allocate_error.Success()) {
8614f1b3e8SDimitry Andric       err.SetErrorStringWithFormat(
8714f1b3e8SDimitry Andric           "couldn't allocate a memory area to store %s: %s",
8814f1b3e8SDimitry Andric           m_persistent_variable_sp->GetName().GetCString(),
8914f1b3e8SDimitry Andric           allocate_error.AsCString());
90f034231aSEd Maste       return;
91f034231aSEd Maste     }
92f034231aSEd Maste 
93ead24645SDimitry Andric     LLDB_LOGF(log, "Allocated %s (0x%" PRIx64 ") successfully",
9414f1b3e8SDimitry Andric               m_persistent_variable_sp->GetName().GetCString(), mem);
95f034231aSEd Maste 
9614f1b3e8SDimitry Andric     // Put the location of the spare memory into the live data of the
9714f1b3e8SDimitry Andric     // ValueObject.
98f034231aSEd Maste 
9914f1b3e8SDimitry Andric     m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create(
10014f1b3e8SDimitry Andric         map.GetBestExecutionContextScope(),
101e81d9d49SDimitry Andric         m_persistent_variable_sp->GetCompilerType(),
10214f1b3e8SDimitry Andric         m_persistent_variable_sp->GetName(), mem, eAddressTypeLoad,
103e81d9d49SDimitry Andric         map.GetAddressByteSize());
104f034231aSEd Maste 
105f034231aSEd Maste     // Clear the flag if the variable will never be deallocated.
106f034231aSEd Maste 
10714f1b3e8SDimitry Andric     if (m_persistent_variable_sp->m_flags &
10814f1b3e8SDimitry Andric         ExpressionVariable::EVKeepInTarget) {
109b76161e4SDimitry Andric       Status leak_error;
110f034231aSEd Maste       map.Leak(mem, leak_error);
11114f1b3e8SDimitry Andric       m_persistent_variable_sp->m_flags &=
11214f1b3e8SDimitry Andric           ~ExpressionVariable::EVNeedsAllocation;
113f034231aSEd Maste     }
114f034231aSEd Maste 
115f034231aSEd Maste     // Write the contents of the variable to the area.
116f034231aSEd Maste 
117b76161e4SDimitry Andric     Status write_error;
118f034231aSEd Maste 
11914f1b3e8SDimitry Andric     map.WriteMemory(mem, m_persistent_variable_sp->GetValueBytes(),
120145449b1SDimitry Andric                     m_persistent_variable_sp->GetByteSize().value_or(0),
121b60736ecSDimitry Andric                     write_error);
122f034231aSEd Maste 
12314f1b3e8SDimitry Andric     if (!write_error.Success()) {
12414f1b3e8SDimitry Andric       err.SetErrorStringWithFormat(
12514f1b3e8SDimitry Andric           "couldn't write %s to the target: %s",
12614f1b3e8SDimitry Andric           m_persistent_variable_sp->GetName().AsCString(),
127f034231aSEd Maste           write_error.AsCString());
128f034231aSEd Maste       return;
129f034231aSEd Maste     }
130f034231aSEd Maste   }
131f034231aSEd Maste 
DestroyAllocation(IRMemoryMap & map,Status & err)132b76161e4SDimitry Andric   void DestroyAllocation(IRMemoryMap &map, Status &err) {
133b76161e4SDimitry Andric     Status deallocate_error;
134f034231aSEd Maste 
13514f1b3e8SDimitry Andric     map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue()
13614f1b3e8SDimitry Andric                  .GetScalar()
13714f1b3e8SDimitry Andric                  .ULongLong(),
13814f1b3e8SDimitry Andric              deallocate_error);
139f034231aSEd Maste 
140f034231aSEd Maste     m_persistent_variable_sp->m_live_sp.reset();
141f034231aSEd Maste 
14214f1b3e8SDimitry Andric     if (!deallocate_error.Success()) {
14314f1b3e8SDimitry Andric       err.SetErrorStringWithFormat(
14414f1b3e8SDimitry Andric           "couldn't deallocate memory for %s: %s",
14514f1b3e8SDimitry Andric           m_persistent_variable_sp->GetName().GetCString(),
14614f1b3e8SDimitry Andric           deallocate_error.AsCString());
147f034231aSEd Maste     }
148f034231aSEd Maste   }
149f034231aSEd Maste 
Materialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,Status & err)15014f1b3e8SDimitry Andric   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
151b76161e4SDimitry Andric                    lldb::addr_t process_address, Status &err) override {
152145449b1SDimitry Andric     Log *log = GetLog(LLDBLog::Expressions);
153f034231aSEd Maste 
154f034231aSEd Maste     const lldb::addr_t load_addr = process_address + m_offset;
155f034231aSEd Maste 
15614f1b3e8SDimitry Andric     if (log) {
157ead24645SDimitry Andric       LLDB_LOGF(log,
158ead24645SDimitry Andric                 "EntityPersistentVariable::Materialize [address = 0x%" PRIx64
15914f1b3e8SDimitry Andric                 ", m_name = %s, m_flags = 0x%hx]",
160f034231aSEd Maste                 (uint64_t)load_addr,
161f034231aSEd Maste                 m_persistent_variable_sp->GetName().AsCString(),
162f034231aSEd Maste                 m_persistent_variable_sp->m_flags);
163f034231aSEd Maste     }
164f034231aSEd Maste 
16514f1b3e8SDimitry Andric     if (m_persistent_variable_sp->m_flags &
16614f1b3e8SDimitry Andric         ExpressionVariable::EVNeedsAllocation) {
167f034231aSEd Maste       MakeAllocation(map, err);
16814f1b3e8SDimitry Andric       m_persistent_variable_sp->m_flags |=
16914f1b3e8SDimitry Andric           ExpressionVariable::EVIsLLDBAllocated;
170f034231aSEd Maste 
171f034231aSEd Maste       if (!err.Success())
172f034231aSEd Maste         return;
173f034231aSEd Maste     }
174f034231aSEd Maste 
17514f1b3e8SDimitry Andric     if ((m_persistent_variable_sp->m_flags &
17614f1b3e8SDimitry Andric              ExpressionVariable::EVIsProgramReference &&
17714f1b3e8SDimitry Andric          m_persistent_variable_sp->m_live_sp) ||
17814f1b3e8SDimitry Andric         m_persistent_variable_sp->m_flags &
17914f1b3e8SDimitry Andric             ExpressionVariable::EVIsLLDBAllocated) {
180b76161e4SDimitry Andric       Status write_error;
181f034231aSEd Maste 
18214f1b3e8SDimitry Andric       map.WriteScalarToMemory(
18314f1b3e8SDimitry Andric           load_addr,
184f034231aSEd Maste           m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(),
18514f1b3e8SDimitry Andric           map.GetAddressByteSize(), write_error);
186f034231aSEd Maste 
18714f1b3e8SDimitry Andric       if (!write_error.Success()) {
18814f1b3e8SDimitry Andric         err.SetErrorStringWithFormat(
18914f1b3e8SDimitry Andric             "couldn't write the location of %s to memory: %s",
19014f1b3e8SDimitry Andric             m_persistent_variable_sp->GetName().AsCString(),
19114f1b3e8SDimitry Andric             write_error.AsCString());
192f034231aSEd Maste       }
19314f1b3e8SDimitry Andric     } else {
19414f1b3e8SDimitry Andric       err.SetErrorStringWithFormat(
19514f1b3e8SDimitry Andric           "no materialization happened for persistent variable %s",
19614f1b3e8SDimitry Andric           m_persistent_variable_sp->GetName().AsCString());
197f034231aSEd Maste       return;
198f034231aSEd Maste     }
199f034231aSEd Maste   }
200f034231aSEd Maste 
Dematerialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,lldb::addr_t frame_top,lldb::addr_t frame_bottom,Status & err)20114f1b3e8SDimitry Andric   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
20214f1b3e8SDimitry Andric                      lldb::addr_t process_address, lldb::addr_t frame_top,
203b76161e4SDimitry Andric                      lldb::addr_t frame_bottom, Status &err) override {
204145449b1SDimitry Andric     Log *log = GetLog(LLDBLog::Expressions);
205f034231aSEd Maste 
206f034231aSEd Maste     const lldb::addr_t load_addr = process_address + m_offset;
207f034231aSEd Maste 
20814f1b3e8SDimitry Andric     if (log) {
209ead24645SDimitry Andric       LLDB_LOGF(log,
21014f1b3e8SDimitry Andric                 "EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64
21114f1b3e8SDimitry Andric                 ", m_name = %s, m_flags = 0x%hx]",
212f034231aSEd Maste                 (uint64_t)process_address + m_offset,
213f034231aSEd Maste                 m_persistent_variable_sp->GetName().AsCString(),
214f034231aSEd Maste                 m_persistent_variable_sp->m_flags);
215f034231aSEd Maste     }
216f034231aSEd Maste 
21714f1b3e8SDimitry Andric     if (m_delegate) {
218e81d9d49SDimitry Andric       m_delegate->DidDematerialize(m_persistent_variable_sp);
219e81d9d49SDimitry Andric     }
220e81d9d49SDimitry Andric 
22114f1b3e8SDimitry Andric     if ((m_persistent_variable_sp->m_flags &
22214f1b3e8SDimitry Andric          ExpressionVariable::EVIsLLDBAllocated) ||
22314f1b3e8SDimitry Andric         (m_persistent_variable_sp->m_flags &
22414f1b3e8SDimitry Andric          ExpressionVariable::EVIsProgramReference)) {
22514f1b3e8SDimitry Andric       if (m_persistent_variable_sp->m_flags &
22614f1b3e8SDimitry Andric               ExpressionVariable::EVIsProgramReference &&
22714f1b3e8SDimitry Andric           !m_persistent_variable_sp->m_live_sp) {
22814f1b3e8SDimitry Andric         // If the reference comes from the program, then the
229f73363f1SDimitry Andric         // ClangExpressionVariable's live variable data hasn't been set up yet.
230f73363f1SDimitry Andric         // Do this now.
231f034231aSEd Maste 
232f034231aSEd Maste         lldb::addr_t location;
233b76161e4SDimitry Andric         Status read_error;
234f034231aSEd Maste 
235f034231aSEd Maste         map.ReadPointerFromMemory(&location, load_addr, read_error);
236f034231aSEd Maste 
23714f1b3e8SDimitry Andric         if (!read_error.Success()) {
23814f1b3e8SDimitry Andric           err.SetErrorStringWithFormat(
23914f1b3e8SDimitry Andric               "couldn't read the address of program-allocated variable %s: %s",
24014f1b3e8SDimitry Andric               m_persistent_variable_sp->GetName().GetCString(),
24114f1b3e8SDimitry Andric               read_error.AsCString());
242f034231aSEd Maste           return;
243f034231aSEd Maste         }
244f034231aSEd Maste 
24514f1b3e8SDimitry Andric         m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create(
24614f1b3e8SDimitry Andric             map.GetBestExecutionContextScope(),
247e81d9d49SDimitry Andric             m_persistent_variable_sp.get()->GetCompilerType(),
24814f1b3e8SDimitry Andric             m_persistent_variable_sp->GetName(), location, eAddressTypeLoad,
249145449b1SDimitry Andric             m_persistent_variable_sp->GetByteSize().value_or(0));
250f034231aSEd Maste 
251f034231aSEd Maste         if (frame_top != LLDB_INVALID_ADDRESS &&
25214f1b3e8SDimitry Andric             frame_bottom != LLDB_INVALID_ADDRESS && location >= frame_bottom &&
25314f1b3e8SDimitry Andric             location <= frame_top) {
25414f1b3e8SDimitry Andric           // If the variable is resident in the stack frame created by the
255f73363f1SDimitry Andric           // expression, then it cannot be relied upon to stay around.  We
256f73363f1SDimitry Andric           // treat it as needing reallocation.
25714f1b3e8SDimitry Andric           m_persistent_variable_sp->m_flags |=
25814f1b3e8SDimitry Andric               ExpressionVariable::EVIsLLDBAllocated;
25914f1b3e8SDimitry Andric           m_persistent_variable_sp->m_flags |=
26014f1b3e8SDimitry Andric               ExpressionVariable::EVNeedsAllocation;
26114f1b3e8SDimitry Andric           m_persistent_variable_sp->m_flags |=
26214f1b3e8SDimitry Andric               ExpressionVariable::EVNeedsFreezeDry;
26314f1b3e8SDimitry Andric           m_persistent_variable_sp->m_flags &=
26414f1b3e8SDimitry Andric               ~ExpressionVariable::EVIsProgramReference;
265f034231aSEd Maste         }
266f034231aSEd Maste       }
267f034231aSEd Maste 
26814f1b3e8SDimitry Andric       lldb::addr_t mem = m_persistent_variable_sp->m_live_sp->GetValue()
26914f1b3e8SDimitry Andric                              .GetScalar()
27014f1b3e8SDimitry Andric                              .ULongLong();
271f034231aSEd Maste 
27214f1b3e8SDimitry Andric       if (!m_persistent_variable_sp->m_live_sp) {
27314f1b3e8SDimitry Andric         err.SetErrorStringWithFormat(
27414f1b3e8SDimitry Andric             "couldn't find the memory area used to store %s",
27514f1b3e8SDimitry Andric             m_persistent_variable_sp->GetName().GetCString());
276f034231aSEd Maste         return;
277f034231aSEd Maste       }
278f034231aSEd Maste 
27914f1b3e8SDimitry Andric       if (m_persistent_variable_sp->m_live_sp->GetValue()
28014f1b3e8SDimitry Andric               .GetValueAddressType() != eAddressTypeLoad) {
28114f1b3e8SDimitry Andric         err.SetErrorStringWithFormat(
28214f1b3e8SDimitry Andric             "the address of the memory area for %s is in an incorrect format",
28314f1b3e8SDimitry Andric             m_persistent_variable_sp->GetName().GetCString());
284f034231aSEd Maste         return;
285f034231aSEd Maste       }
286f034231aSEd Maste 
28714f1b3e8SDimitry Andric       if (m_persistent_variable_sp->m_flags &
28814f1b3e8SDimitry Andric               ExpressionVariable::EVNeedsFreezeDry ||
28914f1b3e8SDimitry Andric           m_persistent_variable_sp->m_flags &
29014f1b3e8SDimitry Andric               ExpressionVariable::EVKeepInTarget) {
291ead24645SDimitry Andric         LLDB_LOGF(log, "Dematerializing %s from 0x%" PRIx64 " (size = %llu)",
292ead24645SDimitry Andric                   m_persistent_variable_sp->GetName().GetCString(),
293ead24645SDimitry Andric                   (uint64_t)mem,
294b60736ecSDimitry Andric                   (unsigned long long)m_persistent_variable_sp->GetByteSize()
295145449b1SDimitry Andric                       .value_or(0));
296f034231aSEd Maste 
297f034231aSEd Maste         // Read the contents of the spare memory area
298f034231aSEd Maste 
299f034231aSEd Maste         m_persistent_variable_sp->ValueUpdated();
300f034231aSEd Maste 
301b76161e4SDimitry Andric         Status read_error;
302f034231aSEd Maste 
30314f1b3e8SDimitry Andric         map.ReadMemory(m_persistent_variable_sp->GetValueBytes(), mem,
304145449b1SDimitry Andric                        m_persistent_variable_sp->GetByteSize().value_or(0),
305145449b1SDimitry Andric                        read_error);
306f034231aSEd Maste 
30714f1b3e8SDimitry Andric         if (!read_error.Success()) {
30814f1b3e8SDimitry Andric           err.SetErrorStringWithFormat(
30914f1b3e8SDimitry Andric               "couldn't read the contents of %s from memory: %s",
31014f1b3e8SDimitry Andric               m_persistent_variable_sp->GetName().GetCString(),
31114f1b3e8SDimitry Andric               read_error.AsCString());
312f034231aSEd Maste           return;
313f034231aSEd Maste         }
314f034231aSEd Maste 
31514f1b3e8SDimitry Andric         m_persistent_variable_sp->m_flags &=
31614f1b3e8SDimitry Andric             ~ExpressionVariable::EVNeedsFreezeDry;
317f034231aSEd Maste       }
31814f1b3e8SDimitry Andric     } else {
31914f1b3e8SDimitry Andric       err.SetErrorStringWithFormat(
32014f1b3e8SDimitry Andric           "no dematerialization happened for persistent variable %s",
32114f1b3e8SDimitry Andric           m_persistent_variable_sp->GetName().AsCString());
322f034231aSEd Maste       return;
323f034231aSEd Maste     }
324f034231aSEd Maste 
32514f1b3e8SDimitry Andric     lldb::ProcessSP process_sp =
32614f1b3e8SDimitry Andric         map.GetBestExecutionContextScope()->CalculateProcess();
32714f1b3e8SDimitry Andric     if (!process_sp || !process_sp->CanJIT()) {
32814f1b3e8SDimitry Andric       // Allocations are not persistent so persistent variables cannot stay
32914f1b3e8SDimitry Andric       // materialized.
330f034231aSEd Maste 
33114f1b3e8SDimitry Andric       m_persistent_variable_sp->m_flags |=
33214f1b3e8SDimitry Andric           ExpressionVariable::EVNeedsAllocation;
333f034231aSEd Maste 
334f034231aSEd Maste       DestroyAllocation(map, err);
335f034231aSEd Maste       if (!err.Success())
336f034231aSEd Maste         return;
33714f1b3e8SDimitry Andric     } else if (m_persistent_variable_sp->m_flags &
33814f1b3e8SDimitry Andric                    ExpressionVariable::EVNeedsAllocation &&
33914f1b3e8SDimitry Andric                !(m_persistent_variable_sp->m_flags &
34014f1b3e8SDimitry Andric                  ExpressionVariable::EVKeepInTarget)) {
341f034231aSEd Maste       DestroyAllocation(map, err);
342f034231aSEd Maste       if (!err.Success())
343f034231aSEd Maste         return;
344f034231aSEd Maste     }
345f034231aSEd Maste   }
346f034231aSEd Maste 
DumpToLog(IRMemoryMap & map,lldb::addr_t process_address,Log * log)34714f1b3e8SDimitry Andric   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
34814f1b3e8SDimitry Andric                  Log *log) override {
349f034231aSEd Maste     StreamString dump_stream;
350f034231aSEd Maste 
351b76161e4SDimitry Andric     Status err;
352f034231aSEd Maste 
353f034231aSEd Maste     const lldb::addr_t load_addr = process_address + m_offset;
354f034231aSEd Maste 
35514f1b3e8SDimitry Andric     dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n",
35614f1b3e8SDimitry Andric                        load_addr,
35714f1b3e8SDimitry Andric                        m_persistent_variable_sp->GetName().AsCString());
358f034231aSEd Maste 
359f034231aSEd Maste     {
360f034231aSEd Maste       dump_stream.Printf("Pointer:\n");
361f034231aSEd Maste 
362f034231aSEd Maste       DataBufferHeap data(m_size, 0);
363f034231aSEd Maste 
364f034231aSEd Maste       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
365f034231aSEd Maste 
36614f1b3e8SDimitry Andric       if (!err.Success()) {
367f034231aSEd Maste         dump_stream.Printf("  <could not be read>\n");
36814f1b3e8SDimitry Andric       } else {
36974a628f7SDimitry Andric         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
37074a628f7SDimitry Andric                      load_addr);
371f034231aSEd Maste 
372f034231aSEd Maste         dump_stream.PutChar('\n');
373f034231aSEd Maste       }
374f034231aSEd Maste     }
375f034231aSEd Maste 
376f034231aSEd Maste     {
377f034231aSEd Maste       dump_stream.Printf("Target:\n");
378f034231aSEd Maste 
379f034231aSEd Maste       lldb::addr_t target_address;
380f034231aSEd Maste 
381f034231aSEd Maste       map.ReadPointerFromMemory(&target_address, load_addr, err);
382f034231aSEd Maste 
38314f1b3e8SDimitry Andric       if (!err.Success()) {
384f034231aSEd Maste         dump_stream.Printf("  <could not be read>\n");
38514f1b3e8SDimitry Andric       } else {
386145449b1SDimitry Andric         DataBufferHeap data(m_persistent_variable_sp->GetByteSize().value_or(0),
387145449b1SDimitry Andric                             0);
388f034231aSEd Maste 
38914f1b3e8SDimitry Andric         map.ReadMemory(data.GetBytes(), target_address,
390145449b1SDimitry Andric                        m_persistent_variable_sp->GetByteSize().value_or(0),
391145449b1SDimitry Andric                        err);
392f034231aSEd Maste 
39314f1b3e8SDimitry Andric         if (!err.Success()) {
394f034231aSEd Maste           dump_stream.Printf("  <could not be read>\n");
39514f1b3e8SDimitry Andric         } else {
39674a628f7SDimitry Andric           DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
39774a628f7SDimitry Andric                        target_address);
398f034231aSEd Maste 
399f034231aSEd Maste           dump_stream.PutChar('\n');
400f034231aSEd Maste         }
401f034231aSEd Maste       }
402f034231aSEd Maste     }
403f034231aSEd Maste 
40414f1b3e8SDimitry Andric     log->PutString(dump_stream.GetString());
405f034231aSEd Maste   }
406f034231aSEd Maste 
Wipe(IRMemoryMap & map,lldb::addr_t process_address)40714f1b3e8SDimitry Andric   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
408e81d9d49SDimitry Andric 
409f034231aSEd Maste private:
410e81d9d49SDimitry Andric   lldb::ExpressionVariableSP m_persistent_variable_sp;
411e81d9d49SDimitry Andric   Materializer::PersistentVariableDelegate *m_delegate;
412f034231aSEd Maste };
413f034231aSEd Maste 
AddPersistentVariable(lldb::ExpressionVariableSP & persistent_variable_sp,PersistentVariableDelegate * delegate,Status & err)41414f1b3e8SDimitry Andric uint32_t Materializer::AddPersistentVariable(
41514f1b3e8SDimitry Andric     lldb::ExpressionVariableSP &persistent_variable_sp,
416b76161e4SDimitry Andric     PersistentVariableDelegate *delegate, Status &err) {
417f034231aSEd Maste   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
418cfca06d7SDimitry Andric   *iter = std::make_unique<EntityPersistentVariable>(persistent_variable_sp,
419cfca06d7SDimitry Andric                                                      delegate);
420f034231aSEd Maste   uint32_t ret = AddStructMember(**iter);
421f034231aSEd Maste   (*iter)->SetOffset(ret);
422f034231aSEd Maste   return ret;
423f034231aSEd Maste }
424f034231aSEd Maste 
4254b4fe385SDimitry Andric /// Base class for materialization of Variables and ValueObjects.
4264b4fe385SDimitry Andric ///
4274b4fe385SDimitry Andric /// Subclasses specify how to obtain the Value which is to be
4284b4fe385SDimitry Andric /// materialized.
4294b4fe385SDimitry Andric class EntityVariableBase : public Materializer::Entity {
430f034231aSEd Maste public:
4314b4fe385SDimitry Andric   virtual ~EntityVariableBase() = default;
4324b4fe385SDimitry Andric 
EntityVariableBase()4334b4fe385SDimitry Andric   EntityVariableBase() {
43414f1b3e8SDimitry Andric     // Hard-coding to maximum size of a pointer since all variables are
43514f1b3e8SDimitry Andric     // materialized by reference
4364b4fe385SDimitry Andric     m_size = g_default_var_byte_size;
4374b4fe385SDimitry Andric     m_alignment = g_default_var_alignment;
438f034231aSEd Maste   }
439f034231aSEd Maste 
Materialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,Status & err)44014f1b3e8SDimitry Andric   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
441b76161e4SDimitry Andric                    lldb::addr_t process_address, Status &err) override {
442145449b1SDimitry Andric     Log *log = GetLog(LLDBLog::Expressions);
443f034231aSEd Maste 
444f034231aSEd Maste     const lldb::addr_t load_addr = process_address + m_offset;
44514f1b3e8SDimitry Andric     if (log) {
446ead24645SDimitry Andric       LLDB_LOGF(log,
447ead24645SDimitry Andric                 "EntityVariable::Materialize [address = 0x%" PRIx64
44814f1b3e8SDimitry Andric                 ", m_variable_sp = %s]",
4494b4fe385SDimitry Andric                 (uint64_t)load_addr, GetName().GetCString());
450f034231aSEd Maste     }
451f034231aSEd Maste 
452f034231aSEd Maste     ExecutionContextScope *scope = frame_sp.get();
453f034231aSEd Maste 
454f034231aSEd Maste     if (!scope)
455f034231aSEd Maste       scope = map.GetBestExecutionContextScope();
456f034231aSEd Maste 
4574b4fe385SDimitry Andric     lldb::ValueObjectSP valobj_sp = SetupValueObject(scope);
458f034231aSEd Maste 
45914f1b3e8SDimitry Andric     if (!valobj_sp) {
46014f1b3e8SDimitry Andric       err.SetErrorStringWithFormat(
4614b4fe385SDimitry Andric           "couldn't get a value object for variable %s", GetName().AsCString());
462f034231aSEd Maste       return;
463f034231aSEd Maste     }
464f034231aSEd Maste 
465b76161e4SDimitry Andric     Status valobj_error = valobj_sp->GetError();
4660cac4ca3SEd Maste 
46714f1b3e8SDimitry Andric     if (valobj_error.Fail()) {
46814f1b3e8SDimitry Andric       err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s",
4694b4fe385SDimitry Andric                                    GetName().AsCString(),
47014f1b3e8SDimitry Andric                                    valobj_error.AsCString());
4710cac4ca3SEd Maste       return;
4720cac4ca3SEd Maste     }
4730cac4ca3SEd Maste 
47414f1b3e8SDimitry Andric     if (m_is_reference) {
475f034231aSEd Maste       DataExtractor valobj_extractor;
476b76161e4SDimitry Andric       Status extract_error;
4770cac4ca3SEd Maste       valobj_sp->GetData(valobj_extractor, extract_error);
4780cac4ca3SEd Maste 
47914f1b3e8SDimitry Andric       if (!extract_error.Success()) {
48014f1b3e8SDimitry Andric         err.SetErrorStringWithFormat(
48114f1b3e8SDimitry Andric             "couldn't read contents of reference variable %s: %s",
4824b4fe385SDimitry Andric             GetName().AsCString(), extract_error.AsCString());
4830cac4ca3SEd Maste         return;
4840cac4ca3SEd Maste       }
4850cac4ca3SEd Maste 
486f034231aSEd Maste       lldb::offset_t offset = 0;
487f034231aSEd Maste       lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset);
488f034231aSEd Maste 
489b76161e4SDimitry Andric       Status write_error;
490f034231aSEd Maste       map.WritePointerToMemory(load_addr, reference_addr, write_error);
491f034231aSEd Maste 
49214f1b3e8SDimitry Andric       if (!write_error.Success()) {
49314f1b3e8SDimitry Andric         err.SetErrorStringWithFormat("couldn't write the contents of reference "
49414f1b3e8SDimitry Andric                                      "variable %s to memory: %s",
4954b4fe385SDimitry Andric                                      GetName().AsCString(),
49614f1b3e8SDimitry Andric                                      write_error.AsCString());
497f034231aSEd Maste         return;
498f034231aSEd Maste       }
49914f1b3e8SDimitry Andric     } else {
500866dcdacSEd Maste       AddressType address_type = eAddressTypeInvalid;
501866dcdacSEd Maste       const bool scalar_is_load_address = false;
50214f1b3e8SDimitry Andric       lldb::addr_t addr_of_valobj =
50314f1b3e8SDimitry Andric           valobj_sp->GetAddressOf(scalar_is_load_address, &address_type);
50414f1b3e8SDimitry Andric       if (addr_of_valobj != LLDB_INVALID_ADDRESS) {
505b76161e4SDimitry Andric         Status write_error;
506f21a844fSEd Maste         map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);
507f034231aSEd Maste 
50814f1b3e8SDimitry Andric         if (!write_error.Success()) {
50914f1b3e8SDimitry Andric           err.SetErrorStringWithFormat(
51014f1b3e8SDimitry Andric               "couldn't write the address of variable %s to memory: %s",
5114b4fe385SDimitry Andric               GetName().AsCString(), write_error.AsCString());
512f034231aSEd Maste           return;
513f034231aSEd Maste         }
51414f1b3e8SDimitry Andric       } else {
515f034231aSEd Maste         DataExtractor data;
516b76161e4SDimitry Andric         Status extract_error;
5170cac4ca3SEd Maste         valobj_sp->GetData(data, extract_error);
51814f1b3e8SDimitry Andric         if (!extract_error.Success()) {
51914f1b3e8SDimitry Andric           err.SetErrorStringWithFormat("couldn't get the value of %s: %s",
5204b4fe385SDimitry Andric                                        GetName().AsCString(),
52114f1b3e8SDimitry Andric                                        extract_error.AsCString());
52214f1b3e8SDimitry Andric           return;
52314f1b3e8SDimitry Andric         }
52414f1b3e8SDimitry Andric 
52514f1b3e8SDimitry Andric         if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
52614f1b3e8SDimitry Andric           err.SetErrorStringWithFormat(
52714f1b3e8SDimitry Andric               "trying to create a temporary region for %s but one exists",
5284b4fe385SDimitry Andric               GetName().AsCString());
52914f1b3e8SDimitry Andric           return;
53014f1b3e8SDimitry Andric         }
53114f1b3e8SDimitry Andric 
5324b4fe385SDimitry Andric         if (data.GetByteSize() < GetByteSize(scope)) {
5334b4fe385SDimitry Andric           if (data.GetByteSize() == 0 && !LocationExpressionIsValid()) {
53414f1b3e8SDimitry Andric             err.SetErrorStringWithFormat("the variable '%s' has no location, "
53514f1b3e8SDimitry Andric                                          "it may have been optimized out",
5364b4fe385SDimitry Andric                                          GetName().AsCString());
53714f1b3e8SDimitry Andric           } else {
53814f1b3e8SDimitry Andric             err.SetErrorStringWithFormat(
53914f1b3e8SDimitry Andric                 "size of variable %s (%" PRIu64
54014f1b3e8SDimitry Andric                 ") is larger than the ValueObject's size (%" PRIu64 ")",
5414b4fe385SDimitry Andric                 GetName().AsCString(), GetByteSize(scope).value_or(0),
5425f29bb8aSDimitry Andric                 data.GetByteSize());
543f034231aSEd Maste           }
544f034231aSEd Maste           return;
545f034231aSEd Maste         }
546f034231aSEd Maste 
547e3b55780SDimitry Andric         std::optional<size_t> opt_bit_align = GetTypeBitAlign(scope);
548ead24645SDimitry Andric         if (!opt_bit_align) {
549ead24645SDimitry Andric           err.SetErrorStringWithFormat("can't get the type alignment for %s",
5504b4fe385SDimitry Andric                                        GetName().AsCString());
551ead24645SDimitry Andric           return;
552ead24645SDimitry Andric         }
553f034231aSEd Maste 
554ead24645SDimitry Andric         size_t byte_align = (*opt_bit_align + 7) / 8;
555866dcdacSEd Maste 
556b76161e4SDimitry Andric         Status alloc_error;
557e81d9d49SDimitry Andric         const bool zero_memory = false;
558f034231aSEd Maste 
55914f1b3e8SDimitry Andric         m_temporary_allocation = map.Malloc(
56014f1b3e8SDimitry Andric             data.GetByteSize(), byte_align,
561e81d9d49SDimitry Andric             lldb::ePermissionsReadable | lldb::ePermissionsWritable,
56214f1b3e8SDimitry Andric             IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error);
563e81d9d49SDimitry Andric 
564f034231aSEd Maste         m_temporary_allocation_size = data.GetByteSize();
565f034231aSEd Maste 
5665f29bb8aSDimitry Andric         m_original_data = std::make_shared<DataBufferHeap>(data.GetDataStart(),
5675f29bb8aSDimitry Andric                                                            data.GetByteSize());
5680cac4ca3SEd Maste 
56914f1b3e8SDimitry Andric         if (!alloc_error.Success()) {
57014f1b3e8SDimitry Andric           err.SetErrorStringWithFormat(
57114f1b3e8SDimitry Andric               "couldn't allocate a temporary region for %s: %s",
5724b4fe385SDimitry Andric               GetName().AsCString(), alloc_error.AsCString());
573f034231aSEd Maste           return;
574f034231aSEd Maste         }
575f034231aSEd Maste 
576b76161e4SDimitry Andric         Status write_error;
577f034231aSEd Maste 
57814f1b3e8SDimitry Andric         map.WriteMemory(m_temporary_allocation, data.GetDataStart(),
57914f1b3e8SDimitry Andric                         data.GetByteSize(), write_error);
580f034231aSEd Maste 
58114f1b3e8SDimitry Andric         if (!write_error.Success()) {
58214f1b3e8SDimitry Andric           err.SetErrorStringWithFormat(
58314f1b3e8SDimitry Andric               "couldn't write to the temporary region for %s: %s",
5844b4fe385SDimitry Andric               GetName().AsCString(), write_error.AsCString());
585f034231aSEd Maste           return;
586f034231aSEd Maste         }
587f034231aSEd Maste 
588b76161e4SDimitry Andric         Status pointer_write_error;
589f034231aSEd Maste 
59014f1b3e8SDimitry Andric         map.WritePointerToMemory(load_addr, m_temporary_allocation,
59114f1b3e8SDimitry Andric                                  pointer_write_error);
592f034231aSEd Maste 
59314f1b3e8SDimitry Andric         if (!pointer_write_error.Success()) {
59414f1b3e8SDimitry Andric           err.SetErrorStringWithFormat(
59514f1b3e8SDimitry Andric               "couldn't write the address of the temporary region for %s: %s",
5964b4fe385SDimitry Andric               GetName().AsCString(), pointer_write_error.AsCString());
597f034231aSEd Maste         }
598f034231aSEd Maste       }
599f034231aSEd Maste     }
600f034231aSEd Maste   }
601f034231aSEd Maste 
Dematerialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,lldb::addr_t frame_top,lldb::addr_t frame_bottom,Status & err)60214f1b3e8SDimitry Andric   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
60314f1b3e8SDimitry Andric                      lldb::addr_t process_address, lldb::addr_t frame_top,
604b76161e4SDimitry Andric                      lldb::addr_t frame_bottom, Status &err) override {
605145449b1SDimitry Andric     Log *log = GetLog(LLDBLog::Expressions);
606f034231aSEd Maste 
607f034231aSEd Maste     const lldb::addr_t load_addr = process_address + m_offset;
60814f1b3e8SDimitry Andric     if (log) {
609ead24645SDimitry Andric       LLDB_LOGF(log,
610ead24645SDimitry Andric                 "EntityVariable::Dematerialize [address = 0x%" PRIx64
61114f1b3e8SDimitry Andric                 ", m_variable_sp = %s]",
6124b4fe385SDimitry Andric                 (uint64_t)load_addr, GetName().AsCString());
613f034231aSEd Maste     }
614f034231aSEd Maste 
61514f1b3e8SDimitry Andric     if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
616f034231aSEd Maste       ExecutionContextScope *scope = frame_sp.get();
617f034231aSEd Maste 
618f034231aSEd Maste       if (!scope)
619f034231aSEd Maste         scope = map.GetBestExecutionContextScope();
620f034231aSEd Maste 
6214b4fe385SDimitry Andric       lldb::ValueObjectSP valobj_sp = SetupValueObject(scope);
622f034231aSEd Maste 
62314f1b3e8SDimitry Andric       if (!valobj_sp) {
62414f1b3e8SDimitry Andric         err.SetErrorStringWithFormat(
62514f1b3e8SDimitry Andric             "couldn't get a value object for variable %s",
6264b4fe385SDimitry Andric             GetName().AsCString());
627f034231aSEd Maste         return;
628f034231aSEd Maste       }
629f034231aSEd Maste 
630f034231aSEd Maste       lldb_private::DataExtractor data;
631f034231aSEd Maste 
632b76161e4SDimitry Andric       Status extract_error;
633f034231aSEd Maste 
634b60736ecSDimitry Andric       map.GetMemoryData(data, m_temporary_allocation,
635145449b1SDimitry Andric                         valobj_sp->GetByteSize().value_or(0), extract_error);
636f034231aSEd Maste 
63714f1b3e8SDimitry Andric       if (!extract_error.Success()) {
63814f1b3e8SDimitry Andric         err.SetErrorStringWithFormat("couldn't get the data for variable %s",
6394b4fe385SDimitry Andric                                      GetName().AsCString());
640f034231aSEd Maste         return;
641f034231aSEd Maste       }
642f034231aSEd Maste 
6430cac4ca3SEd Maste       bool actually_write = true;
6440cac4ca3SEd Maste 
64514f1b3e8SDimitry Andric       if (m_original_data) {
6460cac4ca3SEd Maste         if ((data.GetByteSize() == m_original_data->GetByteSize()) &&
64714f1b3e8SDimitry Andric             !memcmp(m_original_data->GetBytes(), data.GetDataStart(),
64814f1b3e8SDimitry Andric                     data.GetByteSize())) {
6490cac4ca3SEd Maste           actually_write = false;
6500cac4ca3SEd Maste         }
6510cac4ca3SEd Maste       }
6520cac4ca3SEd Maste 
653b76161e4SDimitry Andric       Status set_error;
654f034231aSEd Maste 
65514f1b3e8SDimitry Andric       if (actually_write) {
656f034231aSEd Maste         valobj_sp->SetData(data, set_error);
657f034231aSEd Maste 
65814f1b3e8SDimitry Andric         if (!set_error.Success()) {
65914f1b3e8SDimitry Andric           err.SetErrorStringWithFormat(
66014f1b3e8SDimitry Andric               "couldn't write the new contents of %s back into the variable",
6614b4fe385SDimitry Andric               GetName().AsCString());
662f034231aSEd Maste           return;
663f034231aSEd Maste         }
6640cac4ca3SEd Maste       }
665f034231aSEd Maste 
666b76161e4SDimitry Andric       Status free_error;
667f034231aSEd Maste 
668f034231aSEd Maste       map.Free(m_temporary_allocation, free_error);
669f034231aSEd Maste 
67014f1b3e8SDimitry Andric       if (!free_error.Success()) {
67114f1b3e8SDimitry Andric         err.SetErrorStringWithFormat(
67214f1b3e8SDimitry Andric             "couldn't free the temporary region for %s: %s",
6734b4fe385SDimitry Andric             GetName().AsCString(), free_error.AsCString());
674f034231aSEd Maste         return;
675f034231aSEd Maste       }
676f034231aSEd Maste 
6770cac4ca3SEd Maste       m_original_data.reset();
678f034231aSEd Maste       m_temporary_allocation = LLDB_INVALID_ADDRESS;
679f034231aSEd Maste       m_temporary_allocation_size = 0;
680f034231aSEd Maste     }
681f034231aSEd Maste   }
682f034231aSEd Maste 
DumpToLog(IRMemoryMap & map,lldb::addr_t process_address,Log * log)68314f1b3e8SDimitry Andric   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
68414f1b3e8SDimitry Andric                  Log *log) override {
685f034231aSEd Maste     StreamString dump_stream;
686f034231aSEd Maste 
687f034231aSEd Maste     const lldb::addr_t load_addr = process_address + m_offset;
688f034231aSEd Maste     dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr);
689f034231aSEd Maste 
690b76161e4SDimitry Andric     Status err;
691f034231aSEd Maste 
692f034231aSEd Maste     lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
693f034231aSEd Maste 
694f034231aSEd Maste     {
695f034231aSEd Maste       dump_stream.Printf("Pointer:\n");
696f034231aSEd Maste 
697f034231aSEd Maste       DataBufferHeap data(m_size, 0);
698f034231aSEd Maste 
699f034231aSEd Maste       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
700f034231aSEd Maste 
70114f1b3e8SDimitry Andric       if (!err.Success()) {
702f034231aSEd Maste         dump_stream.Printf("  <could not be read>\n");
70314f1b3e8SDimitry Andric       } else {
70414f1b3e8SDimitry Andric         DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
70514f1b3e8SDimitry Andric                                 map.GetByteOrder(), map.GetAddressByteSize());
706f034231aSEd Maste 
70774a628f7SDimitry Andric         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
70874a628f7SDimitry Andric                      load_addr);
709f034231aSEd Maste 
7106f8fc217SDimitry Andric         lldb::offset_t offset = 0;
711f034231aSEd Maste 
712cfca06d7SDimitry Andric         ptr = extractor.GetAddress(&offset);
713f034231aSEd Maste 
714f034231aSEd Maste         dump_stream.PutChar('\n');
715f034231aSEd Maste       }
716f034231aSEd Maste     }
717f034231aSEd Maste 
71814f1b3e8SDimitry Andric     if (m_temporary_allocation == LLDB_INVALID_ADDRESS) {
719f034231aSEd Maste       dump_stream.Printf("Points to process memory:\n");
72014f1b3e8SDimitry Andric     } else {
721f034231aSEd Maste       dump_stream.Printf("Temporary allocation:\n");
722f034231aSEd Maste     }
723f034231aSEd Maste 
72414f1b3e8SDimitry Andric     if (ptr == LLDB_INVALID_ADDRESS) {
725f034231aSEd Maste       dump_stream.Printf("  <could not be be found>\n");
72614f1b3e8SDimitry Andric     } else {
727f034231aSEd Maste       DataBufferHeap data(m_temporary_allocation_size, 0);
728f034231aSEd Maste 
72914f1b3e8SDimitry Andric       map.ReadMemory(data.GetBytes(), m_temporary_allocation,
73014f1b3e8SDimitry Andric                      m_temporary_allocation_size, err);
731f034231aSEd Maste 
73214f1b3e8SDimitry Andric       if (!err.Success()) {
733f034231aSEd Maste         dump_stream.Printf("  <could not be read>\n");
73414f1b3e8SDimitry Andric       } else {
73574a628f7SDimitry Andric         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
73674a628f7SDimitry Andric                      load_addr);
737f034231aSEd Maste 
738f034231aSEd Maste         dump_stream.PutChar('\n');
739f034231aSEd Maste       }
740f034231aSEd Maste     }
741f034231aSEd Maste 
74214f1b3e8SDimitry Andric     log->PutString(dump_stream.GetString());
743f034231aSEd Maste   }
744f034231aSEd Maste 
Wipe(IRMemoryMap & map,lldb::addr_t process_address)74514f1b3e8SDimitry Andric   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
74614f1b3e8SDimitry Andric     if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
747b76161e4SDimitry Andric       Status free_error;
748f034231aSEd Maste 
749f034231aSEd Maste       map.Free(m_temporary_allocation, free_error);
750f034231aSEd Maste 
751f034231aSEd Maste       m_temporary_allocation = LLDB_INVALID_ADDRESS;
752f034231aSEd Maste       m_temporary_allocation_size = 0;
753f034231aSEd Maste     }
754f034231aSEd Maste   }
755e81d9d49SDimitry Andric 
756f034231aSEd Maste private:
7574b4fe385SDimitry Andric   virtual ConstString GetName() const = 0;
7584b4fe385SDimitry Andric 
7594b4fe385SDimitry Andric   /// Creates and returns ValueObject tied to this variable
7604b4fe385SDimitry Andric   /// and prepares Entity for materialization.
7614b4fe385SDimitry Andric   ///
7624b4fe385SDimitry Andric   /// Called each time the Materializer (de)materializes a
7634b4fe385SDimitry Andric   /// variable. We re-create the ValueObject based on the
7644b4fe385SDimitry Andric   /// current ExecutionContextScope since clients such as
7654b4fe385SDimitry Andric   /// conditional breakpoints may materialize the same
7664b4fe385SDimitry Andric   /// EntityVariable multiple times with different frames.
7674b4fe385SDimitry Andric   ///
7684b4fe385SDimitry Andric   /// Each subsequent use of the EntityVariableBase interface
7694b4fe385SDimitry Andric   /// will query the newly created ValueObject until this
7704b4fe385SDimitry Andric   /// function is called again.
7714b4fe385SDimitry Andric   virtual lldb::ValueObjectSP
7724b4fe385SDimitry Andric   SetupValueObject(ExecutionContextScope *scope) = 0;
7734b4fe385SDimitry Andric 
7744b4fe385SDimitry Andric   /// Returns size in bytes of the type associated with this variable
7754b4fe385SDimitry Andric   ///
7764b4fe385SDimitry Andric   /// \returns On success, returns byte size of the type associated
777e3b55780SDimitry Andric   ///          with this variable. Returns std::nullopt otherwise.
778e3b55780SDimitry Andric   virtual std::optional<uint64_t>
7794b4fe385SDimitry Andric   GetByteSize(ExecutionContextScope *scope) const = 0;
7804b4fe385SDimitry Andric 
7814b4fe385SDimitry Andric   /// Returns 'true' if the location expression associated with this variable
7824b4fe385SDimitry Andric   /// is valid.
7834b4fe385SDimitry Andric   virtual bool LocationExpressionIsValid() const = 0;
7844b4fe385SDimitry Andric 
7854b4fe385SDimitry Andric   /// Returns alignment of the type associated with this variable in bits.
7864b4fe385SDimitry Andric   ///
7874b4fe385SDimitry Andric   /// \returns On success, returns alignment in bits for the type associated
788e3b55780SDimitry Andric   ///          with this variable. Returns std::nullopt otherwise.
789e3b55780SDimitry Andric   virtual std::optional<size_t>
7904b4fe385SDimitry Andric   GetTypeBitAlign(ExecutionContextScope *scope) const = 0;
7914b4fe385SDimitry Andric 
7924b4fe385SDimitry Andric protected:
793145449b1SDimitry Andric   bool m_is_reference = false;
794145449b1SDimitry Andric   lldb::addr_t m_temporary_allocation = LLDB_INVALID_ADDRESS;
795145449b1SDimitry Andric   size_t m_temporary_allocation_size = 0;
7960cac4ca3SEd Maste   lldb::DataBufferSP m_original_data;
797f034231aSEd Maste };
798f034231aSEd Maste 
7994b4fe385SDimitry Andric /// Represents an Entity constructed from a VariableSP.
8004b4fe385SDimitry Andric ///
8014b4fe385SDimitry Andric /// This class is used for materialization of variables for which
8024b4fe385SDimitry Andric /// the user has a VariableSP on hand. The ValueObject is then
8034b4fe385SDimitry Andric /// derived from the associated DWARF location expression when needed
8044b4fe385SDimitry Andric /// by the Materializer.
8054b4fe385SDimitry Andric class EntityVariable : public EntityVariableBase {
8064b4fe385SDimitry Andric public:
EntityVariable(lldb::VariableSP & variable_sp)8074b4fe385SDimitry Andric   EntityVariable(lldb::VariableSP &variable_sp) : m_variable_sp(variable_sp) {
8084b4fe385SDimitry Andric     m_is_reference =
8094b4fe385SDimitry Andric         m_variable_sp->GetType()->GetForwardCompilerType().IsReferenceType();
8104b4fe385SDimitry Andric   }
8114b4fe385SDimitry Andric 
GetName() const8124b4fe385SDimitry Andric   ConstString GetName() const override { return m_variable_sp->GetName(); }
8134b4fe385SDimitry Andric 
SetupValueObject(ExecutionContextScope * scope)8144b4fe385SDimitry Andric   lldb::ValueObjectSP SetupValueObject(ExecutionContextScope *scope) override {
8154b4fe385SDimitry Andric     assert(m_variable_sp != nullptr);
8164b4fe385SDimitry Andric     return ValueObjectVariable::Create(scope, m_variable_sp);
8174b4fe385SDimitry Andric   }
8184b4fe385SDimitry Andric 
819e3b55780SDimitry Andric   std::optional<uint64_t>
GetByteSize(ExecutionContextScope * scope) const8204b4fe385SDimitry Andric   GetByteSize(ExecutionContextScope *scope) const override {
8214b4fe385SDimitry Andric     return m_variable_sp->GetType()->GetByteSize(scope);
8224b4fe385SDimitry Andric   }
8234b4fe385SDimitry Andric 
LocationExpressionIsValid() const8244b4fe385SDimitry Andric   bool LocationExpressionIsValid() const override {
8254b4fe385SDimitry Andric     return m_variable_sp->LocationExpressionList().IsValid();
8264b4fe385SDimitry Andric   }
8274b4fe385SDimitry Andric 
828e3b55780SDimitry Andric   std::optional<size_t>
GetTypeBitAlign(ExecutionContextScope * scope) const8294b4fe385SDimitry Andric   GetTypeBitAlign(ExecutionContextScope *scope) const override {
8304b4fe385SDimitry Andric     return m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign(
8314b4fe385SDimitry Andric         scope);
8324b4fe385SDimitry Andric   }
8334b4fe385SDimitry Andric 
8344b4fe385SDimitry Andric private:
8354b4fe385SDimitry Andric   lldb::VariableSP m_variable_sp; ///< Variable that this entity is based on.
8364b4fe385SDimitry Andric };
8374b4fe385SDimitry Andric 
8384b4fe385SDimitry Andric /// Represents an Entity constructed from a VariableSP.
8394b4fe385SDimitry Andric ///
8404b4fe385SDimitry Andric /// This class is used for materialization of variables for
8414b4fe385SDimitry Andric /// which the user does not have a VariableSP available (e.g.,
8424b4fe385SDimitry Andric /// when materializing ivars).
8434b4fe385SDimitry Andric class EntityValueObject : public EntityVariableBase {
8444b4fe385SDimitry Andric public:
EntityValueObject(ConstString name,ValueObjectProviderTy provider)8454b4fe385SDimitry Andric   EntityValueObject(ConstString name, ValueObjectProviderTy provider)
8464b4fe385SDimitry Andric       : m_name(name), m_valobj_provider(std::move(provider)) {
8474b4fe385SDimitry Andric     assert(m_valobj_provider);
8484b4fe385SDimitry Andric   }
8494b4fe385SDimitry Andric 
GetName() const8504b4fe385SDimitry Andric   ConstString GetName() const override { return m_name; }
8514b4fe385SDimitry Andric 
SetupValueObject(ExecutionContextScope * scope)8524b4fe385SDimitry Andric   lldb::ValueObjectSP SetupValueObject(ExecutionContextScope *scope) override {
8534b4fe385SDimitry Andric     m_valobj_sp =
8544b4fe385SDimitry Andric         m_valobj_provider(GetName(), scope->CalculateStackFrame().get());
8554b4fe385SDimitry Andric 
8564b4fe385SDimitry Andric     if (m_valobj_sp)
8574b4fe385SDimitry Andric       m_is_reference = m_valobj_sp->GetCompilerType().IsReferenceType();
8584b4fe385SDimitry Andric 
8594b4fe385SDimitry Andric     return m_valobj_sp;
8604b4fe385SDimitry Andric   }
8614b4fe385SDimitry Andric 
862e3b55780SDimitry Andric   std::optional<uint64_t>
GetByteSize(ExecutionContextScope * scope) const8634b4fe385SDimitry Andric   GetByteSize(ExecutionContextScope *scope) const override {
8644b4fe385SDimitry Andric     if (m_valobj_sp)
8654b4fe385SDimitry Andric       return m_valobj_sp->GetCompilerType().GetByteSize(scope);
8664b4fe385SDimitry Andric 
8674b4fe385SDimitry Andric     return {};
8684b4fe385SDimitry Andric   }
8694b4fe385SDimitry Andric 
LocationExpressionIsValid() const8704b4fe385SDimitry Andric   bool LocationExpressionIsValid() const override {
8714b4fe385SDimitry Andric     if (m_valobj_sp)
8724b4fe385SDimitry Andric       return m_valobj_sp->GetError().Success();
8734b4fe385SDimitry Andric 
8744b4fe385SDimitry Andric     return false;
8754b4fe385SDimitry Andric   }
8764b4fe385SDimitry Andric 
877e3b55780SDimitry Andric   std::optional<size_t>
GetTypeBitAlign(ExecutionContextScope * scope) const8784b4fe385SDimitry Andric   GetTypeBitAlign(ExecutionContextScope *scope) const override {
8794b4fe385SDimitry Andric     if (m_valobj_sp)
8804b4fe385SDimitry Andric       return m_valobj_sp->GetCompilerType().GetTypeBitAlign(scope);
8814b4fe385SDimitry Andric 
8824b4fe385SDimitry Andric     return {};
8834b4fe385SDimitry Andric   }
8844b4fe385SDimitry Andric 
8854b4fe385SDimitry Andric private:
8864b4fe385SDimitry Andric   ConstString m_name;
8874b4fe385SDimitry Andric   lldb::ValueObjectSP m_valobj_sp;
8884b4fe385SDimitry Andric   ValueObjectProviderTy m_valobj_provider;
8894b4fe385SDimitry Andric };
8904b4fe385SDimitry Andric 
AddVariable(lldb::VariableSP & variable_sp,Status & err)891b76161e4SDimitry Andric uint32_t Materializer::AddVariable(lldb::VariableSP &variable_sp, Status &err) {
892f034231aSEd Maste   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
893cfca06d7SDimitry Andric   *iter = std::make_unique<EntityVariable>(variable_sp);
894f034231aSEd Maste   uint32_t ret = AddStructMember(**iter);
895f034231aSEd Maste   (*iter)->SetOffset(ret);
896f034231aSEd Maste   return ret;
897f034231aSEd Maste }
898f034231aSEd Maste 
AddValueObject(ConstString name,ValueObjectProviderTy valobj_provider,Status & err)8994b4fe385SDimitry Andric uint32_t Materializer::AddValueObject(ConstString name,
9004b4fe385SDimitry Andric                                       ValueObjectProviderTy valobj_provider,
9014b4fe385SDimitry Andric                                       Status &err) {
9024b4fe385SDimitry Andric   assert(valobj_provider);
9034b4fe385SDimitry Andric   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
9044b4fe385SDimitry Andric   *iter = std::make_unique<EntityValueObject>(name, std::move(valobj_provider));
9054b4fe385SDimitry Andric   uint32_t ret = AddStructMember(**iter);
9064b4fe385SDimitry Andric   (*iter)->SetOffset(ret);
9074b4fe385SDimitry Andric   return ret;
9084b4fe385SDimitry Andric }
9094b4fe385SDimitry Andric 
91014f1b3e8SDimitry Andric class EntityResultVariable : public Materializer::Entity {
911f034231aSEd Maste public:
EntityResultVariable(const CompilerType & type,bool is_program_reference,bool keep_in_memory,Materializer::PersistentVariableDelegate * delegate)91214f1b3e8SDimitry Andric   EntityResultVariable(const CompilerType &type, bool is_program_reference,
913e81d9d49SDimitry Andric                        bool keep_in_memory,
91414f1b3e8SDimitry Andric                        Materializer::PersistentVariableDelegate *delegate)
91514f1b3e8SDimitry Andric       : Entity(), m_type(type), m_is_program_reference(is_program_reference),
916145449b1SDimitry Andric         m_keep_in_memory(keep_in_memory), m_delegate(delegate) {
91714f1b3e8SDimitry Andric     // Hard-coding to maximum size of a pointer since all results are
91814f1b3e8SDimitry Andric     // materialized by reference
9194b4fe385SDimitry Andric     m_size = g_default_var_byte_size;
9204b4fe385SDimitry Andric     m_alignment = g_default_var_alignment;
921f034231aSEd Maste   }
922f034231aSEd Maste 
Materialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,Status & err)92314f1b3e8SDimitry Andric   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
924b76161e4SDimitry Andric                    lldb::addr_t process_address, Status &err) override {
92514f1b3e8SDimitry Andric     if (!m_is_program_reference) {
92614f1b3e8SDimitry Andric       if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
92714f1b3e8SDimitry Andric         err.SetErrorString("Trying to create a temporary region for the result "
92814f1b3e8SDimitry Andric                            "but one exists");
929f034231aSEd Maste         return;
930f034231aSEd Maste       }
931f034231aSEd Maste 
932f034231aSEd Maste       const lldb::addr_t load_addr = process_address + m_offset;
933f034231aSEd Maste 
934cfca06d7SDimitry Andric       ExecutionContextScope *exe_scope = frame_sp.get();
935cfca06d7SDimitry Andric       if (!exe_scope)
936cfca06d7SDimitry Andric         exe_scope = map.GetBestExecutionContextScope();
93714f1b3e8SDimitry Andric 
938e3b55780SDimitry Andric       std::optional<uint64_t> byte_size = m_type.GetByteSize(exe_scope);
93994994d37SDimitry Andric       if (!byte_size) {
940344a3780SDimitry Andric         err.SetErrorStringWithFormat("can't get size of type \"%s\"",
941344a3780SDimitry Andric                                      m_type.GetTypeName().AsCString());
94294994d37SDimitry Andric         return;
94394994d37SDimitry Andric       }
944f034231aSEd Maste 
945e3b55780SDimitry Andric       std::optional<size_t> opt_bit_align = m_type.GetTypeBitAlign(exe_scope);
946ead24645SDimitry Andric       if (!opt_bit_align) {
947344a3780SDimitry Andric         err.SetErrorStringWithFormat("can't get the alignment of type  \"%s\"",
948344a3780SDimitry Andric                                      m_type.GetTypeName().AsCString());
949ead24645SDimitry Andric         return;
950ead24645SDimitry Andric       }
951ead24645SDimitry Andric 
952ead24645SDimitry Andric       size_t byte_align = (*opt_bit_align + 7) / 8;
953866dcdacSEd Maste 
954b76161e4SDimitry Andric       Status alloc_error;
955e81d9d49SDimitry Andric       const bool zero_memory = true;
956f034231aSEd Maste 
95714f1b3e8SDimitry Andric       m_temporary_allocation = map.Malloc(
95894994d37SDimitry Andric           *byte_size, byte_align,
959e81d9d49SDimitry Andric           lldb::ePermissionsReadable | lldb::ePermissionsWritable,
96014f1b3e8SDimitry Andric           IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error);
96194994d37SDimitry Andric       m_temporary_allocation_size = *byte_size;
962f034231aSEd Maste 
96314f1b3e8SDimitry Andric       if (!alloc_error.Success()) {
96414f1b3e8SDimitry Andric         err.SetErrorStringWithFormat(
96514f1b3e8SDimitry Andric             "couldn't allocate a temporary region for the result: %s",
96614f1b3e8SDimitry Andric             alloc_error.AsCString());
967f034231aSEd Maste         return;
968f034231aSEd Maste       }
969f034231aSEd Maste 
970b76161e4SDimitry Andric       Status pointer_write_error;
971f034231aSEd Maste 
97214f1b3e8SDimitry Andric       map.WritePointerToMemory(load_addr, m_temporary_allocation,
97314f1b3e8SDimitry Andric                                pointer_write_error);
974f034231aSEd Maste 
97514f1b3e8SDimitry Andric       if (!pointer_write_error.Success()) {
97614f1b3e8SDimitry Andric         err.SetErrorStringWithFormat("couldn't write the address of the "
97714f1b3e8SDimitry Andric                                      "temporary region for the result: %s",
97814f1b3e8SDimitry Andric                                      pointer_write_error.AsCString());
979f034231aSEd Maste       }
980f034231aSEd Maste     }
981f034231aSEd Maste   }
982f034231aSEd Maste 
Dematerialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,lldb::addr_t frame_top,lldb::addr_t frame_bottom,Status & err)98314f1b3e8SDimitry Andric   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
98414f1b3e8SDimitry Andric                      lldb::addr_t process_address, lldb::addr_t frame_top,
985b76161e4SDimitry Andric                      lldb::addr_t frame_bottom, Status &err) override {
986f034231aSEd Maste     err.Clear();
987f034231aSEd Maste 
988cfca06d7SDimitry Andric     ExecutionContextScope *exe_scope = frame_sp.get();
989cfca06d7SDimitry Andric     if (!exe_scope)
990cfca06d7SDimitry Andric       exe_scope = map.GetBestExecutionContextScope();
991f034231aSEd Maste 
99214f1b3e8SDimitry Andric     if (!exe_scope) {
99314f1b3e8SDimitry Andric       err.SetErrorString("Couldn't dematerialize a result variable: invalid "
99414f1b3e8SDimitry Andric                          "execution context scope");
995f034231aSEd Maste       return;
996f034231aSEd Maste     }
997f034231aSEd Maste 
998f034231aSEd Maste     lldb::addr_t address;
999b76161e4SDimitry Andric     Status read_error;
1000f034231aSEd Maste     const lldb::addr_t load_addr = process_address + m_offset;
1001f034231aSEd Maste 
1002f034231aSEd Maste     map.ReadPointerFromMemory(&address, load_addr, read_error);
1003f034231aSEd Maste 
100414f1b3e8SDimitry Andric     if (!read_error.Success()) {
100514f1b3e8SDimitry Andric       err.SetErrorString("Couldn't dematerialize a result variable: couldn't "
100614f1b3e8SDimitry Andric                          "read its address");
1007f034231aSEd Maste       return;
1008f034231aSEd Maste     }
1009f034231aSEd Maste 
1010f034231aSEd Maste     lldb::TargetSP target_sp = exe_scope->CalculateTarget();
1011f034231aSEd Maste 
101214f1b3e8SDimitry Andric     if (!target_sp) {
1013f034231aSEd Maste       err.SetErrorString("Couldn't dematerialize a result variable: no target");
1014f034231aSEd Maste       return;
1015f034231aSEd Maste     }
1016f034231aSEd Maste 
1017ead24645SDimitry Andric     auto type_system_or_err =
1018ead24645SDimitry Andric         target_sp->GetScratchTypeSystemForLanguage(m_type.GetMinimumLanguage());
1019f034231aSEd Maste 
1020ead24645SDimitry Andric     if (auto error = type_system_or_err.takeError()) {
102114f1b3e8SDimitry Andric       err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: "
102214f1b3e8SDimitry Andric                                    "couldn't get the corresponding type "
102314f1b3e8SDimitry Andric                                    "system: %s",
1024ead24645SDimitry Andric                                    llvm::toString(std::move(error)).c_str());
1025e81d9d49SDimitry Andric       return;
1026e81d9d49SDimitry Andric     }
1027e3b55780SDimitry Andric     auto ts = *type_system_or_err;
1028e3b55780SDimitry Andric     if (!ts) {
1029e3b55780SDimitry Andric       err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: "
1030e3b55780SDimitry Andric                                    "couldn't corresponding type system is "
1031e3b55780SDimitry Andric                                    "no longer live.");
1032e3b55780SDimitry Andric       return;
1033e3b55780SDimitry Andric     }
103414f1b3e8SDimitry Andric     PersistentExpressionState *persistent_state =
1035e3b55780SDimitry Andric         ts->GetPersistentExpressionState();
1036e81d9d49SDimitry Andric 
103714f1b3e8SDimitry Andric     if (!persistent_state) {
103814f1b3e8SDimitry Andric       err.SetErrorString("Couldn't dematerialize a result variable: "
103914f1b3e8SDimitry Andric                          "corresponding type system doesn't handle persistent "
104014f1b3e8SDimitry Andric                          "variables");
1041e81d9d49SDimitry Andric       return;
1042e81d9d49SDimitry Andric     }
1043e81d9d49SDimitry Andric 
1044cfca06d7SDimitry Andric     ConstString name = m_delegate
104514f1b3e8SDimitry Andric                            ? m_delegate->GetName()
1046cfca06d7SDimitry Andric                            : persistent_state->GetNextPersistentVariableName();
1047e81d9d49SDimitry Andric 
104814f1b3e8SDimitry Andric     lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(
104914f1b3e8SDimitry Andric         exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize());
1050f034231aSEd Maste 
105114f1b3e8SDimitry Andric     if (!ret) {
105214f1b3e8SDimitry Andric       err.SetErrorStringWithFormat("couldn't dematerialize a result variable: "
105314f1b3e8SDimitry Andric                                    "failed to make persistent variable %s",
105414f1b3e8SDimitry Andric                                    name.AsCString());
1055f034231aSEd Maste       return;
1056f034231aSEd Maste     }
1057f034231aSEd Maste 
105814f1b3e8SDimitry Andric     lldb::ProcessSP process_sp =
105914f1b3e8SDimitry Andric         map.GetBestExecutionContextScope()->CalculateProcess();
1060f034231aSEd Maste 
106114f1b3e8SDimitry Andric     if (m_delegate) {
1062e81d9d49SDimitry Andric       m_delegate->DidDematerialize(ret);
1063e81d9d49SDimitry Andric     }
1064e81d9d49SDimitry Andric 
106514f1b3e8SDimitry Andric     bool can_persist =
106614f1b3e8SDimitry Andric         (m_is_program_reference && process_sp && process_sp->CanJIT() &&
106714f1b3e8SDimitry Andric          !(address >= frame_bottom && address < frame_top));
1068f034231aSEd Maste 
106914f1b3e8SDimitry Andric     if (can_persist && m_keep_in_memory) {
107014f1b3e8SDimitry Andric       ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name,
107114f1b3e8SDimitry Andric                                                       address, eAddressTypeLoad,
1072f21a844fSEd Maste                                                       map.GetAddressByteSize());
1073f034231aSEd Maste     }
1074f034231aSEd Maste 
1075f034231aSEd Maste     ret->ValueUpdated();
1076f034231aSEd Maste 
1077145449b1SDimitry Andric     const size_t pvar_byte_size = ret->GetByteSize().value_or(0);
1078f034231aSEd Maste     uint8_t *pvar_data = ret->GetValueBytes();
1079f034231aSEd Maste 
1080f034231aSEd Maste     map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);
1081f034231aSEd Maste 
108214f1b3e8SDimitry Andric     if (!read_error.Success()) {
108314f1b3e8SDimitry Andric       err.SetErrorString(
108414f1b3e8SDimitry Andric           "Couldn't dematerialize a result variable: couldn't read its memory");
1085f034231aSEd Maste       return;
1086f034231aSEd Maste     }
1087f034231aSEd Maste 
108814f1b3e8SDimitry Andric     if (!can_persist || !m_keep_in_memory) {
1089e81d9d49SDimitry Andric       ret->m_flags |= ExpressionVariable::EVNeedsAllocation;
1090f034231aSEd Maste 
109114f1b3e8SDimitry Andric       if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
1092b76161e4SDimitry Andric         Status free_error;
1093f034231aSEd Maste         map.Free(m_temporary_allocation, free_error);
1094f034231aSEd Maste       }
109514f1b3e8SDimitry Andric     } else {
1096e81d9d49SDimitry Andric       ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
1097f034231aSEd Maste     }
1098f034231aSEd Maste 
1099f034231aSEd Maste     m_temporary_allocation = LLDB_INVALID_ADDRESS;
1100f034231aSEd Maste     m_temporary_allocation_size = 0;
1101f034231aSEd Maste   }
1102f034231aSEd Maste 
DumpToLog(IRMemoryMap & map,lldb::addr_t process_address,Log * log)110314f1b3e8SDimitry Andric   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
110414f1b3e8SDimitry Andric                  Log *log) override {
1105f034231aSEd Maste     StreamString dump_stream;
1106f034231aSEd Maste 
1107f034231aSEd Maste     const lldb::addr_t load_addr = process_address + m_offset;
1108f034231aSEd Maste 
1109f034231aSEd Maste     dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr);
1110f034231aSEd Maste 
1111b76161e4SDimitry Andric     Status err;
1112f034231aSEd Maste 
1113f034231aSEd Maste     lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
1114f034231aSEd Maste 
1115f034231aSEd Maste     {
1116f034231aSEd Maste       dump_stream.Printf("Pointer:\n");
1117f034231aSEd Maste 
1118f034231aSEd Maste       DataBufferHeap data(m_size, 0);
1119f034231aSEd Maste 
1120f034231aSEd Maste       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1121f034231aSEd Maste 
112214f1b3e8SDimitry Andric       if (!err.Success()) {
1123f034231aSEd Maste         dump_stream.Printf("  <could not be read>\n");
112414f1b3e8SDimitry Andric       } else {
112514f1b3e8SDimitry Andric         DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
112614f1b3e8SDimitry Andric                                 map.GetByteOrder(), map.GetAddressByteSize());
1127f034231aSEd Maste 
112874a628f7SDimitry Andric         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
112974a628f7SDimitry Andric                      load_addr);
1130f034231aSEd Maste 
11316f8fc217SDimitry Andric         lldb::offset_t offset = 0;
1132f034231aSEd Maste 
1133cfca06d7SDimitry Andric         ptr = extractor.GetAddress(&offset);
1134f034231aSEd Maste 
1135f034231aSEd Maste         dump_stream.PutChar('\n');
1136f034231aSEd Maste       }
1137f034231aSEd Maste     }
1138f034231aSEd Maste 
113914f1b3e8SDimitry Andric     if (m_temporary_allocation == LLDB_INVALID_ADDRESS) {
1140f034231aSEd Maste       dump_stream.Printf("Points to process memory:\n");
114114f1b3e8SDimitry Andric     } else {
1142f034231aSEd Maste       dump_stream.Printf("Temporary allocation:\n");
1143f034231aSEd Maste     }
1144f034231aSEd Maste 
114514f1b3e8SDimitry Andric     if (ptr == LLDB_INVALID_ADDRESS) {
1146f034231aSEd Maste       dump_stream.Printf("  <could not be be found>\n");
114714f1b3e8SDimitry Andric     } else {
1148f034231aSEd Maste       DataBufferHeap data(m_temporary_allocation_size, 0);
1149f034231aSEd Maste 
115014f1b3e8SDimitry Andric       map.ReadMemory(data.GetBytes(), m_temporary_allocation,
115114f1b3e8SDimitry Andric                      m_temporary_allocation_size, err);
1152f034231aSEd Maste 
115314f1b3e8SDimitry Andric       if (!err.Success()) {
1154f034231aSEd Maste         dump_stream.Printf("  <could not be read>\n");
115514f1b3e8SDimitry Andric       } else {
115674a628f7SDimitry Andric         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
115774a628f7SDimitry Andric                      load_addr);
1158f034231aSEd Maste 
1159f034231aSEd Maste         dump_stream.PutChar('\n');
1160f034231aSEd Maste       }
1161f034231aSEd Maste     }
1162f034231aSEd Maste 
116314f1b3e8SDimitry Andric     log->PutString(dump_stream.GetString());
1164f034231aSEd Maste   }
1165f034231aSEd Maste 
Wipe(IRMemoryMap & map,lldb::addr_t process_address)116614f1b3e8SDimitry Andric   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
116714f1b3e8SDimitry Andric     if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) {
1168b76161e4SDimitry Andric       Status free_error;
1169f034231aSEd Maste 
1170f034231aSEd Maste       map.Free(m_temporary_allocation, free_error);
1171f034231aSEd Maste     }
1172f034231aSEd Maste 
1173f034231aSEd Maste     m_temporary_allocation = LLDB_INVALID_ADDRESS;
1174f034231aSEd Maste     m_temporary_allocation_size = 0;
1175f034231aSEd Maste   }
1176e81d9d49SDimitry Andric 
1177f034231aSEd Maste private:
1178e81d9d49SDimitry Andric   CompilerType m_type;
1179f034231aSEd Maste   bool m_is_program_reference;
1180f034231aSEd Maste   bool m_keep_in_memory;
1181f034231aSEd Maste 
1182145449b1SDimitry Andric   lldb::addr_t m_temporary_allocation = LLDB_INVALID_ADDRESS;
1183145449b1SDimitry Andric   size_t m_temporary_allocation_size = 0;
1184e81d9d49SDimitry Andric   Materializer::PersistentVariableDelegate *m_delegate;
1185f034231aSEd Maste };
1186f034231aSEd Maste 
AddResultVariable(const CompilerType & type,bool is_program_reference,bool keep_in_memory,PersistentVariableDelegate * delegate,Status & err)118714f1b3e8SDimitry Andric uint32_t Materializer::AddResultVariable(const CompilerType &type,
1188e81d9d49SDimitry Andric                                          bool is_program_reference,
1189e81d9d49SDimitry Andric                                          bool keep_in_memory,
1190e81d9d49SDimitry Andric                                          PersistentVariableDelegate *delegate,
1191b76161e4SDimitry Andric                                          Status &err) {
1192f034231aSEd Maste   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1193cfca06d7SDimitry Andric   *iter = std::make_unique<EntityResultVariable>(type, is_program_reference,
1194cfca06d7SDimitry Andric                                                  keep_in_memory, delegate);
1195f034231aSEd Maste   uint32_t ret = AddStructMember(**iter);
1196f034231aSEd Maste   (*iter)->SetOffset(ret);
1197f034231aSEd Maste   return ret;
1198f034231aSEd Maste }
1199f034231aSEd Maste 
120014f1b3e8SDimitry Andric class EntitySymbol : public Materializer::Entity {
1201f034231aSEd Maste public:
EntitySymbol(const Symbol & symbol)120214f1b3e8SDimitry Andric   EntitySymbol(const Symbol &symbol) : Entity(), m_symbol(symbol) {
1203f034231aSEd Maste     // Hard-coding to maximum size of a symbol
12044b4fe385SDimitry Andric     m_size = g_default_var_byte_size;
12054b4fe385SDimitry Andric     m_alignment = g_default_var_alignment;
1206f034231aSEd Maste   }
1207f034231aSEd Maste 
Materialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,Status & err)120814f1b3e8SDimitry Andric   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1209b76161e4SDimitry Andric                    lldb::addr_t process_address, Status &err) override {
1210145449b1SDimitry Andric     Log *log = GetLog(LLDBLog::Expressions);
1211f034231aSEd Maste 
1212f034231aSEd Maste     const lldb::addr_t load_addr = process_address + m_offset;
1213f034231aSEd Maste 
121414f1b3e8SDimitry Andric     if (log) {
1215ead24645SDimitry Andric       LLDB_LOGF(log,
1216ead24645SDimitry Andric                 "EntitySymbol::Materialize [address = 0x%" PRIx64
121714f1b3e8SDimitry Andric                 ", m_symbol = %s]",
121814f1b3e8SDimitry Andric                 (uint64_t)load_addr, m_symbol.GetName().AsCString());
1219f034231aSEd Maste     }
1220f034231aSEd Maste 
12215e95aa85SEd Maste     const Address sym_address = m_symbol.GetAddress();
1222f034231aSEd Maste 
1223cfca06d7SDimitry Andric     ExecutionContextScope *exe_scope = frame_sp.get();
1224cfca06d7SDimitry Andric     if (!exe_scope)
1225cfca06d7SDimitry Andric       exe_scope = map.GetBestExecutionContextScope();
1226f034231aSEd Maste 
1227f034231aSEd Maste     lldb::TargetSP target_sp;
1228f034231aSEd Maste 
1229f034231aSEd Maste     if (exe_scope)
1230f034231aSEd Maste       target_sp = map.GetBestExecutionContextScope()->CalculateTarget();
1231f034231aSEd Maste 
123214f1b3e8SDimitry Andric     if (!target_sp) {
123314f1b3e8SDimitry Andric       err.SetErrorStringWithFormat(
123414f1b3e8SDimitry Andric           "couldn't resolve symbol %s because there is no target",
123514f1b3e8SDimitry Andric           m_symbol.GetName().AsCString());
1236f034231aSEd Maste       return;
1237f034231aSEd Maste     }
1238f034231aSEd Maste 
1239f034231aSEd Maste     lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get());
1240f034231aSEd Maste 
1241f034231aSEd Maste     if (resolved_address == LLDB_INVALID_ADDRESS)
1242f034231aSEd Maste       resolved_address = sym_address.GetFileAddress();
1243f034231aSEd Maste 
1244b76161e4SDimitry Andric     Status pointer_write_error;
1245f034231aSEd Maste 
1246f034231aSEd Maste     map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);
1247f034231aSEd Maste 
124814f1b3e8SDimitry Andric     if (!pointer_write_error.Success()) {
124914f1b3e8SDimitry Andric       err.SetErrorStringWithFormat(
125014f1b3e8SDimitry Andric           "couldn't write the address of symbol %s: %s",
125114f1b3e8SDimitry Andric           m_symbol.GetName().AsCString(), pointer_write_error.AsCString());
1252f034231aSEd Maste       return;
1253f034231aSEd Maste     }
1254f034231aSEd Maste   }
1255f034231aSEd Maste 
Dematerialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,lldb::addr_t frame_top,lldb::addr_t frame_bottom,Status & err)125614f1b3e8SDimitry Andric   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
125714f1b3e8SDimitry Andric                      lldb::addr_t process_address, lldb::addr_t frame_top,
1258b76161e4SDimitry Andric                      lldb::addr_t frame_bottom, Status &err) override {
1259145449b1SDimitry Andric     Log *log = GetLog(LLDBLog::Expressions);
1260f034231aSEd Maste 
1261f034231aSEd Maste     const lldb::addr_t load_addr = process_address + m_offset;
1262f034231aSEd Maste 
126314f1b3e8SDimitry Andric     if (log) {
1264ead24645SDimitry Andric       LLDB_LOGF(log,
1265ead24645SDimitry Andric                 "EntitySymbol::Dematerialize [address = 0x%" PRIx64
126614f1b3e8SDimitry Andric                 ", m_symbol = %s]",
126714f1b3e8SDimitry Andric                 (uint64_t)load_addr, m_symbol.GetName().AsCString());
1268f034231aSEd Maste     }
1269f034231aSEd Maste 
1270f034231aSEd Maste     // no work needs to be done
1271f034231aSEd Maste   }
1272f034231aSEd Maste 
DumpToLog(IRMemoryMap & map,lldb::addr_t process_address,Log * log)127314f1b3e8SDimitry Andric   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
127414f1b3e8SDimitry Andric                  Log *log) override {
1275f034231aSEd Maste     StreamString dump_stream;
1276f034231aSEd Maste 
1277b76161e4SDimitry Andric     Status err;
1278f034231aSEd Maste 
1279f034231aSEd Maste     const lldb::addr_t load_addr = process_address + m_offset;
1280f034231aSEd Maste 
128114f1b3e8SDimitry Andric     dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr,
128214f1b3e8SDimitry Andric                        m_symbol.GetName().AsCString());
1283f034231aSEd Maste 
1284f034231aSEd Maste     {
1285f034231aSEd Maste       dump_stream.Printf("Pointer:\n");
1286f034231aSEd Maste 
1287f034231aSEd Maste       DataBufferHeap data(m_size, 0);
1288f034231aSEd Maste 
1289f034231aSEd Maste       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1290f034231aSEd Maste 
129114f1b3e8SDimitry Andric       if (!err.Success()) {
1292f034231aSEd Maste         dump_stream.Printf("  <could not be read>\n");
129314f1b3e8SDimitry Andric       } else {
129474a628f7SDimitry Andric         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
129574a628f7SDimitry Andric                      load_addr);
1296f034231aSEd Maste 
1297f034231aSEd Maste         dump_stream.PutChar('\n');
1298f034231aSEd Maste       }
1299f034231aSEd Maste     }
1300f034231aSEd Maste 
130114f1b3e8SDimitry Andric     log->PutString(dump_stream.GetString());
1302f034231aSEd Maste   }
1303f034231aSEd Maste 
Wipe(IRMemoryMap & map,lldb::addr_t process_address)130414f1b3e8SDimitry Andric   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
1305e81d9d49SDimitry Andric 
1306f034231aSEd Maste private:
1307f034231aSEd Maste   Symbol m_symbol;
1308f034231aSEd Maste };
1309f034231aSEd Maste 
AddSymbol(const Symbol & symbol_sp,Status & err)1310b76161e4SDimitry Andric uint32_t Materializer::AddSymbol(const Symbol &symbol_sp, Status &err) {
1311f034231aSEd Maste   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1312cfca06d7SDimitry Andric   *iter = std::make_unique<EntitySymbol>(symbol_sp);
1313f034231aSEd Maste   uint32_t ret = AddStructMember(**iter);
1314f034231aSEd Maste   (*iter)->SetOffset(ret);
1315f034231aSEd Maste   return ret;
1316f034231aSEd Maste }
1317f034231aSEd Maste 
131814f1b3e8SDimitry Andric class EntityRegister : public Materializer::Entity {
1319f034231aSEd Maste public:
EntityRegister(const RegisterInfo & register_info)132014f1b3e8SDimitry Andric   EntityRegister(const RegisterInfo &register_info)
132114f1b3e8SDimitry Andric       : Entity(), m_register_info(register_info) {
1322f034231aSEd Maste     // Hard-coding alignment conservatively
1323f034231aSEd Maste     m_size = m_register_info.byte_size;
1324f034231aSEd Maste     m_alignment = m_register_info.byte_size;
1325f034231aSEd Maste   }
1326f034231aSEd Maste 
Materialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,Status & err)132714f1b3e8SDimitry Andric   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1328b76161e4SDimitry Andric                    lldb::addr_t process_address, Status &err) override {
1329145449b1SDimitry Andric     Log *log = GetLog(LLDBLog::Expressions);
1330f034231aSEd Maste 
1331f034231aSEd Maste     const lldb::addr_t load_addr = process_address + m_offset;
1332f034231aSEd Maste 
133314f1b3e8SDimitry Andric     if (log) {
1334ead24645SDimitry Andric       LLDB_LOGF(log,
1335ead24645SDimitry Andric                 "EntityRegister::Materialize [address = 0x%" PRIx64
133614f1b3e8SDimitry Andric                 ", m_register_info = %s]",
133714f1b3e8SDimitry Andric                 (uint64_t)load_addr, m_register_info.name);
1338f034231aSEd Maste     }
1339f034231aSEd Maste 
1340f034231aSEd Maste     RegisterValue reg_value;
1341f034231aSEd Maste 
134214f1b3e8SDimitry Andric     if (!frame_sp.get()) {
134314f1b3e8SDimitry Andric       err.SetErrorStringWithFormat(
134414f1b3e8SDimitry Andric           "couldn't materialize register %s without a stack frame",
134514f1b3e8SDimitry Andric           m_register_info.name);
1346f034231aSEd Maste       return;
1347f034231aSEd Maste     }
1348f034231aSEd Maste 
1349f034231aSEd Maste     lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1350f034231aSEd Maste 
135114f1b3e8SDimitry Andric     if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) {
135214f1b3e8SDimitry Andric       err.SetErrorStringWithFormat("couldn't read the value of register %s",
135314f1b3e8SDimitry Andric                                    m_register_info.name);
1354f034231aSEd Maste       return;
1355f034231aSEd Maste     }
1356f034231aSEd Maste 
1357f034231aSEd Maste     DataExtractor register_data;
1358f034231aSEd Maste 
135914f1b3e8SDimitry Andric     if (!reg_value.GetData(register_data)) {
136014f1b3e8SDimitry Andric       err.SetErrorStringWithFormat("couldn't get the data for register %s",
136114f1b3e8SDimitry Andric                                    m_register_info.name);
1362f034231aSEd Maste       return;
1363f034231aSEd Maste     }
1364f034231aSEd Maste 
136514f1b3e8SDimitry Andric     if (register_data.GetByteSize() != m_register_info.byte_size) {
136614f1b3e8SDimitry Andric       err.SetErrorStringWithFormat(
136714f1b3e8SDimitry Andric           "data for register %s had size %llu but we expected %llu",
136814f1b3e8SDimitry Andric           m_register_info.name, (unsigned long long)register_data.GetByteSize(),
136914f1b3e8SDimitry Andric           (unsigned long long)m_register_info.byte_size);
1370f034231aSEd Maste       return;
1371f034231aSEd Maste     }
1372f034231aSEd Maste 
13735f29bb8aSDimitry Andric     m_register_contents = std::make_shared<DataBufferHeap>(
13745f29bb8aSDimitry Andric         register_data.GetDataStart(), register_data.GetByteSize());
1375f034231aSEd Maste 
1376b76161e4SDimitry Andric     Status write_error;
1377f034231aSEd Maste 
137814f1b3e8SDimitry Andric     map.WriteMemory(load_addr, register_data.GetDataStart(),
137914f1b3e8SDimitry Andric                     register_data.GetByteSize(), write_error);
1380f034231aSEd Maste 
138114f1b3e8SDimitry Andric     if (!write_error.Success()) {
138214f1b3e8SDimitry Andric       err.SetErrorStringWithFormat(
138314f1b3e8SDimitry Andric           "couldn't write the contents of register %s: %s",
138414f1b3e8SDimitry Andric           m_register_info.name, write_error.AsCString());
1385f034231aSEd Maste       return;
1386f034231aSEd Maste     }
1387f034231aSEd Maste   }
1388f034231aSEd Maste 
Dematerialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,lldb::addr_t frame_top,lldb::addr_t frame_bottom,Status & err)138914f1b3e8SDimitry Andric   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
139014f1b3e8SDimitry Andric                      lldb::addr_t process_address, lldb::addr_t frame_top,
1391b76161e4SDimitry Andric                      lldb::addr_t frame_bottom, Status &err) override {
1392145449b1SDimitry Andric     Log *log = GetLog(LLDBLog::Expressions);
1393f034231aSEd Maste 
1394f034231aSEd Maste     const lldb::addr_t load_addr = process_address + m_offset;
1395f034231aSEd Maste 
139614f1b3e8SDimitry Andric     if (log) {
1397ead24645SDimitry Andric       LLDB_LOGF(log,
1398ead24645SDimitry Andric                 "EntityRegister::Dematerialize [address = 0x%" PRIx64
139914f1b3e8SDimitry Andric                 ", m_register_info = %s]",
140014f1b3e8SDimitry Andric                 (uint64_t)load_addr, m_register_info.name);
1401f034231aSEd Maste     }
1402f034231aSEd Maste 
1403b76161e4SDimitry Andric     Status extract_error;
1404f034231aSEd Maste 
1405f034231aSEd Maste     DataExtractor register_data;
1406f034231aSEd Maste 
140714f1b3e8SDimitry Andric     if (!frame_sp.get()) {
140814f1b3e8SDimitry Andric       err.SetErrorStringWithFormat(
140914f1b3e8SDimitry Andric           "couldn't dematerialize register %s without a stack frame",
141014f1b3e8SDimitry Andric           m_register_info.name);
1411f034231aSEd Maste       return;
1412f034231aSEd Maste     }
1413f034231aSEd Maste 
1414f034231aSEd Maste     lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1415f034231aSEd Maste 
141614f1b3e8SDimitry Andric     map.GetMemoryData(register_data, load_addr, m_register_info.byte_size,
141714f1b3e8SDimitry Andric                       extract_error);
1418f034231aSEd Maste 
141914f1b3e8SDimitry Andric     if (!extract_error.Success()) {
142014f1b3e8SDimitry Andric       err.SetErrorStringWithFormat("couldn't get the data for register %s: %s",
142114f1b3e8SDimitry Andric                                    m_register_info.name,
142214f1b3e8SDimitry Andric                                    extract_error.AsCString());
1423f034231aSEd Maste       return;
1424f034231aSEd Maste     }
1425f034231aSEd Maste 
142614f1b3e8SDimitry Andric     if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(),
142714f1b3e8SDimitry Andric                 register_data.GetByteSize())) {
142814f1b3e8SDimitry Andric       // No write required, and in particular we avoid errors if the register
142914f1b3e8SDimitry Andric       // wasn't writable
1430f034231aSEd Maste 
1431f034231aSEd Maste       m_register_contents.reset();
1432f034231aSEd Maste       return;
1433f034231aSEd Maste     }
1434f034231aSEd Maste 
1435f034231aSEd Maste     m_register_contents.reset();
1436f034231aSEd Maste 
1437b60736ecSDimitry Andric     RegisterValue register_value(register_data.GetData(),
1438b60736ecSDimitry Andric                                  register_data.GetByteOrder());
1439f034231aSEd Maste 
144014f1b3e8SDimitry Andric     if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) {
144114f1b3e8SDimitry Andric       err.SetErrorStringWithFormat("couldn't write the value of register %s",
144214f1b3e8SDimitry Andric                                    m_register_info.name);
1443f034231aSEd Maste       return;
1444f034231aSEd Maste     }
1445f034231aSEd Maste   }
1446f034231aSEd Maste 
DumpToLog(IRMemoryMap & map,lldb::addr_t process_address,Log * log)144714f1b3e8SDimitry Andric   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
144814f1b3e8SDimitry Andric                  Log *log) override {
1449f034231aSEd Maste     StreamString dump_stream;
1450f034231aSEd Maste 
1451b76161e4SDimitry Andric     Status err;
1452f034231aSEd Maste 
1453f034231aSEd Maste     const lldb::addr_t load_addr = process_address + m_offset;
1454f034231aSEd Maste 
145514f1b3e8SDimitry Andric     dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr,
145614f1b3e8SDimitry Andric                        m_register_info.name);
1457f034231aSEd Maste 
1458f034231aSEd Maste     {
1459f034231aSEd Maste       dump_stream.Printf("Value:\n");
1460f034231aSEd Maste 
1461f034231aSEd Maste       DataBufferHeap data(m_size, 0);
1462f034231aSEd Maste 
1463f034231aSEd Maste       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1464f034231aSEd Maste 
146514f1b3e8SDimitry Andric       if (!err.Success()) {
1466f034231aSEd Maste         dump_stream.Printf("  <could not be read>\n");
146714f1b3e8SDimitry Andric       } else {
146874a628f7SDimitry Andric         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
146974a628f7SDimitry Andric                      load_addr);
1470f034231aSEd Maste 
1471f034231aSEd Maste         dump_stream.PutChar('\n');
1472f034231aSEd Maste       }
1473f034231aSEd Maste     }
1474f034231aSEd Maste 
147514f1b3e8SDimitry Andric     log->PutString(dump_stream.GetString());
1476f034231aSEd Maste   }
1477f034231aSEd Maste 
Wipe(IRMemoryMap & map,lldb::addr_t process_address)147814f1b3e8SDimitry Andric   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
1479e81d9d49SDimitry Andric 
1480f034231aSEd Maste private:
1481f034231aSEd Maste   RegisterInfo m_register_info;
1482f034231aSEd Maste   lldb::DataBufferSP m_register_contents;
1483f034231aSEd Maste };
1484f034231aSEd Maste 
AddRegister(const RegisterInfo & register_info,Status & err)148514f1b3e8SDimitry Andric uint32_t Materializer::AddRegister(const RegisterInfo &register_info,
1486b76161e4SDimitry Andric                                    Status &err) {
1487f034231aSEd Maste   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1488cfca06d7SDimitry Andric   *iter = std::make_unique<EntityRegister>(register_info);
1489f034231aSEd Maste   uint32_t ret = AddStructMember(**iter);
1490f034231aSEd Maste   (*iter)->SetOffset(ret);
1491f034231aSEd Maste   return ret;
1492f034231aSEd Maste }
1493f034231aSEd Maste 
~Materializer()149414f1b3e8SDimitry Andric Materializer::~Materializer() {
1495f034231aSEd Maste   DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1496f034231aSEd Maste 
1497f034231aSEd Maste   if (dematerializer_sp)
1498f034231aSEd Maste     dematerializer_sp->Wipe();
1499f034231aSEd Maste }
1500f034231aSEd Maste 
1501f034231aSEd Maste Materializer::DematerializerSP
Materialize(lldb::StackFrameSP & frame_sp,IRMemoryMap & map,lldb::addr_t process_address,Status & error)150214f1b3e8SDimitry Andric Materializer::Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1503b76161e4SDimitry Andric                           lldb::addr_t process_address, Status &error) {
1504f034231aSEd Maste   ExecutionContextScope *exe_scope = frame_sp.get();
1505f034231aSEd Maste   if (!exe_scope)
1506f034231aSEd Maste     exe_scope = map.GetBestExecutionContextScope();
1507f034231aSEd Maste 
1508f034231aSEd Maste   DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1509f034231aSEd Maste 
151014f1b3e8SDimitry Andric   if (dematerializer_sp) {
1511f034231aSEd Maste     error.SetErrorToGenericError();
1512f034231aSEd Maste     error.SetErrorString("Couldn't materialize: already materialized");
1513f034231aSEd Maste   }
1514f034231aSEd Maste 
151514f1b3e8SDimitry Andric   DematerializerSP ret(
151614f1b3e8SDimitry Andric       new Dematerializer(*this, frame_sp, map, process_address));
1517f034231aSEd Maste 
151814f1b3e8SDimitry Andric   if (!exe_scope) {
1519f034231aSEd Maste     error.SetErrorToGenericError();
1520f034231aSEd Maste     error.SetErrorString("Couldn't materialize: target doesn't exist");
1521f034231aSEd Maste   }
1522f034231aSEd Maste 
152314f1b3e8SDimitry Andric   for (EntityUP &entity_up : m_entities) {
1524f034231aSEd Maste     entity_up->Materialize(frame_sp, map, process_address, error);
1525f034231aSEd Maste 
1526f034231aSEd Maste     if (!error.Success())
1527f034231aSEd Maste       return DematerializerSP();
1528f034231aSEd Maste   }
1529f034231aSEd Maste 
1530145449b1SDimitry Andric   if (Log *log = GetLog(LLDBLog::Expressions)) {
1531ead24645SDimitry Andric     LLDB_LOGF(
1532ead24645SDimitry Andric         log,
153314f1b3e8SDimitry Andric         "Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64
153414f1b3e8SDimitry Andric         ") materialized:",
15350cac4ca3SEd Maste         static_cast<void *>(frame_sp.get()), process_address);
1536f034231aSEd Maste     for (EntityUP &entity_up : m_entities)
1537f034231aSEd Maste       entity_up->DumpToLog(map, process_address, log);
1538f034231aSEd Maste   }
1539f034231aSEd Maste 
1540f034231aSEd Maste   m_dematerializer_wp = ret;
1541f034231aSEd Maste 
1542f034231aSEd Maste   return ret;
1543f034231aSEd Maste }
1544f034231aSEd Maste 
Dematerialize(Status & error,lldb::addr_t frame_bottom,lldb::addr_t frame_top)1545b76161e4SDimitry Andric void Materializer::Dematerializer::Dematerialize(Status &error,
1546e81d9d49SDimitry Andric                                                  lldb::addr_t frame_bottom,
154714f1b3e8SDimitry Andric                                                  lldb::addr_t frame_top) {
1548f034231aSEd Maste   lldb::StackFrameSP frame_sp;
1549f034231aSEd Maste 
1550f034231aSEd Maste   lldb::ThreadSP thread_sp = m_thread_wp.lock();
1551f034231aSEd Maste   if (thread_sp)
1552f034231aSEd Maste     frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);
1553f034231aSEd Maste 
1554cfca06d7SDimitry Andric   ExecutionContextScope *exe_scope = frame_sp.get();
1555cfca06d7SDimitry Andric   if (!exe_scope)
1556cfca06d7SDimitry Andric     exe_scope = m_map->GetBestExecutionContextScope();
1557f034231aSEd Maste 
155814f1b3e8SDimitry Andric   if (!IsValid()) {
1559f034231aSEd Maste     error.SetErrorToGenericError();
1560f034231aSEd Maste     error.SetErrorString("Couldn't dematerialize: invalid dematerializer");
1561f034231aSEd Maste   }
1562f034231aSEd Maste 
156314f1b3e8SDimitry Andric   if (!exe_scope) {
1564f034231aSEd Maste     error.SetErrorToGenericError();
1565f034231aSEd Maste     error.SetErrorString("Couldn't dematerialize: target is gone");
156614f1b3e8SDimitry Andric   } else {
1567145449b1SDimitry Andric     if (Log *log = GetLog(LLDBLog::Expressions)) {
1568ead24645SDimitry Andric       LLDB_LOGF(log,
1569ead24645SDimitry Andric                 "Materializer::Dematerialize (frame_sp = %p, process_address "
157014f1b3e8SDimitry Andric                 "= 0x%" PRIx64 ") about to dematerialize:",
15710cac4ca3SEd Maste                 static_cast<void *>(frame_sp.get()), m_process_address);
1572f034231aSEd Maste       for (EntityUP &entity_up : m_materializer->m_entities)
1573f034231aSEd Maste         entity_up->DumpToLog(*m_map, m_process_address, log);
1574f034231aSEd Maste     }
1575f034231aSEd Maste 
157614f1b3e8SDimitry Andric     for (EntityUP &entity_up : m_materializer->m_entities) {
157714f1b3e8SDimitry Andric       entity_up->Dematerialize(frame_sp, *m_map, m_process_address, frame_top,
157814f1b3e8SDimitry Andric                                frame_bottom, error);
1579f034231aSEd Maste 
1580f034231aSEd Maste       if (!error.Success())
1581f034231aSEd Maste         break;
1582f034231aSEd Maste     }
1583f034231aSEd Maste   }
1584f034231aSEd Maste 
1585f034231aSEd Maste   Wipe();
1586f034231aSEd Maste }
1587f034231aSEd Maste 
Wipe()158814f1b3e8SDimitry Andric void Materializer::Dematerializer::Wipe() {
1589f034231aSEd Maste   if (!IsValid())
1590f034231aSEd Maste     return;
1591f034231aSEd Maste 
159214f1b3e8SDimitry Andric   for (EntityUP &entity_up : m_materializer->m_entities) {
1593f034231aSEd Maste     entity_up->Wipe(*m_map, m_process_address);
1594f034231aSEd Maste   }
1595f034231aSEd Maste 
1596e81d9d49SDimitry Andric   m_materializer = nullptr;
1597e81d9d49SDimitry Andric   m_map = nullptr;
1598f034231aSEd Maste   m_process_address = LLDB_INVALID_ADDRESS;
1599f034231aSEd Maste }
1600e81d9d49SDimitry Andric 
16017fa27ce4SDimitry Andric Materializer::PersistentVariableDelegate::PersistentVariableDelegate() =
16027fa27ce4SDimitry Andric     default;
160314f1b3e8SDimitry Andric Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() =
160414f1b3e8SDimitry Andric     default;
1605