]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Expression/Materializer.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Expression / Materializer.cpp
1 //===-- Materializer.cpp ----------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "lldb/Expression/Materializer.h"
10 #include "lldb/Core/DumpDataExtractor.h"
11 #include "lldb/Core/ValueObjectConstResult.h"
12 #include "lldb/Core/ValueObjectVariable.h"
13 #include "lldb/Expression/ExpressionVariable.h"
14 #include "lldb/Symbol/ClangASTContext.h"
15 #include "lldb/Symbol/Symbol.h"
16 #include "lldb/Symbol/Type.h"
17 #include "lldb/Symbol/Variable.h"
18 #include "lldb/Target/ExecutionContext.h"
19 #include "lldb/Target/RegisterContext.h"
20 #include "lldb/Target/StackFrame.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Target/Thread.h"
23 #include "lldb/Utility/Log.h"
24 #include "lldb/Utility/RegisterValue.h"
25
26 #include <memory>
27
28 using namespace lldb_private;
29
30 uint32_t Materializer::AddStructMember(Entity &entity) {
31   uint32_t size = entity.GetSize();
32   uint32_t alignment = entity.GetAlignment();
33
34   uint32_t ret;
35
36   if (m_current_offset == 0)
37     m_struct_alignment = alignment;
38
39   if (m_current_offset % alignment)
40     m_current_offset += (alignment - (m_current_offset % alignment));
41
42   ret = m_current_offset;
43
44   m_current_offset += size;
45
46   return ret;
47 }
48
49 void Materializer::Entity::SetSizeAndAlignmentFromType(CompilerType &type) {
50   if (llvm::Optional<uint64_t> size = type.GetByteSize(nullptr))
51     m_size = *size;
52
53   uint32_t bit_alignment = type.GetTypeBitAlign();
54
55   if (bit_alignment % 8) {
56     bit_alignment += 8;
57     bit_alignment &= ~((uint32_t)0x111u);
58   }
59
60   m_alignment = bit_alignment / 8;
61 }
62
63 class EntityPersistentVariable : public Materializer::Entity {
64 public:
65   EntityPersistentVariable(lldb::ExpressionVariableSP &persistent_variable_sp,
66                            Materializer::PersistentVariableDelegate *delegate)
67       : Entity(), m_persistent_variable_sp(persistent_variable_sp),
68         m_delegate(delegate) {
69     // Hard-coding to maximum size of a pointer since persistent variables are
70     // materialized by reference
71     m_size = 8;
72     m_alignment = 8;
73   }
74
75   void MakeAllocation(IRMemoryMap &map, Status &err) {
76     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
77
78     // Allocate a spare memory area to store the persistent variable's
79     // contents.
80
81     Status allocate_error;
82     const bool zero_memory = false;
83
84     lldb::addr_t mem = map.Malloc(
85         m_persistent_variable_sp->GetByteSize(), 8,
86         lldb::ePermissionsReadable | lldb::ePermissionsWritable,
87         IRMemoryMap::eAllocationPolicyMirror, zero_memory, allocate_error);
88
89     if (!allocate_error.Success()) {
90       err.SetErrorStringWithFormat(
91           "couldn't allocate a memory area to store %s: %s",
92           m_persistent_variable_sp->GetName().GetCString(),
93           allocate_error.AsCString());
94       return;
95     }
96
97     if (log)
98       log->Printf("Allocated %s (0x%" PRIx64 ") successfully",
99                   m_persistent_variable_sp->GetName().GetCString(), mem);
100
101     // Put the location of the spare memory into the live data of the
102     // ValueObject.
103
104     m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create(
105         map.GetBestExecutionContextScope(),
106         m_persistent_variable_sp->GetCompilerType(),
107         m_persistent_variable_sp->GetName(), mem, eAddressTypeLoad,
108         map.GetAddressByteSize());
109
110     // Clear the flag if the variable will never be deallocated.
111
112     if (m_persistent_variable_sp->m_flags &
113         ExpressionVariable::EVKeepInTarget) {
114       Status leak_error;
115       map.Leak(mem, leak_error);
116       m_persistent_variable_sp->m_flags &=
117           ~ExpressionVariable::EVNeedsAllocation;
118     }
119
120     // Write the contents of the variable to the area.
121
122     Status write_error;
123
124     map.WriteMemory(mem, m_persistent_variable_sp->GetValueBytes(),
125                     m_persistent_variable_sp->GetByteSize(), write_error);
126
127     if (!write_error.Success()) {
128       err.SetErrorStringWithFormat(
129           "couldn't write %s to the target: %s",
130           m_persistent_variable_sp->GetName().AsCString(),
131           write_error.AsCString());
132       return;
133     }
134   }
135
136   void DestroyAllocation(IRMemoryMap &map, Status &err) {
137     Status deallocate_error;
138
139     map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue()
140                  .GetScalar()
141                  .ULongLong(),
142              deallocate_error);
143
144     m_persistent_variable_sp->m_live_sp.reset();
145
146     if (!deallocate_error.Success()) {
147       err.SetErrorStringWithFormat(
148           "couldn't deallocate memory for %s: %s",
149           m_persistent_variable_sp->GetName().GetCString(),
150           deallocate_error.AsCString());
151     }
152   }
153
154   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
155                    lldb::addr_t process_address, Status &err) override {
156     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
157
158     const lldb::addr_t load_addr = process_address + m_offset;
159
160     if (log) {
161       log->Printf("EntityPersistentVariable::Materialize [address = 0x%" PRIx64
162                   ", m_name = %s, m_flags = 0x%hx]",
163                   (uint64_t)load_addr,
164                   m_persistent_variable_sp->GetName().AsCString(),
165                   m_persistent_variable_sp->m_flags);
166     }
167
168     if (m_persistent_variable_sp->m_flags &
169         ExpressionVariable::EVNeedsAllocation) {
170       MakeAllocation(map, err);
171       m_persistent_variable_sp->m_flags |=
172           ExpressionVariable::EVIsLLDBAllocated;
173
174       if (!err.Success())
175         return;
176     }
177
178     if ((m_persistent_variable_sp->m_flags &
179              ExpressionVariable::EVIsProgramReference &&
180          m_persistent_variable_sp->m_live_sp) ||
181         m_persistent_variable_sp->m_flags &
182             ExpressionVariable::EVIsLLDBAllocated) {
183       Status write_error;
184
185       map.WriteScalarToMemory(
186           load_addr,
187           m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(),
188           map.GetAddressByteSize(), write_error);
189
190       if (!write_error.Success()) {
191         err.SetErrorStringWithFormat(
192             "couldn't write the location of %s to memory: %s",
193             m_persistent_variable_sp->GetName().AsCString(),
194             write_error.AsCString());
195       }
196     } else {
197       err.SetErrorStringWithFormat(
198           "no materialization happened for persistent variable %s",
199           m_persistent_variable_sp->GetName().AsCString());
200       return;
201     }
202   }
203
204   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
205                      lldb::addr_t process_address, lldb::addr_t frame_top,
206                      lldb::addr_t frame_bottom, Status &err) override {
207     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
208
209     const lldb::addr_t load_addr = process_address + m_offset;
210
211     if (log) {
212       log->Printf(
213           "EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64
214           ", m_name = %s, m_flags = 0x%hx]",
215           (uint64_t)process_address + m_offset,
216           m_persistent_variable_sp->GetName().AsCString(),
217           m_persistent_variable_sp->m_flags);
218     }
219
220     if (m_delegate) {
221       m_delegate->DidDematerialize(m_persistent_variable_sp);
222     }
223
224     if ((m_persistent_variable_sp->m_flags &
225          ExpressionVariable::EVIsLLDBAllocated) ||
226         (m_persistent_variable_sp->m_flags &
227          ExpressionVariable::EVIsProgramReference)) {
228       if (m_persistent_variable_sp->m_flags &
229               ExpressionVariable::EVIsProgramReference &&
230           !m_persistent_variable_sp->m_live_sp) {
231         // If the reference comes from the program, then the
232         // ClangExpressionVariable's live variable data hasn't been set up yet.
233         // Do this now.
234
235         lldb::addr_t location;
236         Status read_error;
237
238         map.ReadPointerFromMemory(&location, load_addr, read_error);
239
240         if (!read_error.Success()) {
241           err.SetErrorStringWithFormat(
242               "couldn't read the address of program-allocated variable %s: %s",
243               m_persistent_variable_sp->GetName().GetCString(),
244               read_error.AsCString());
245           return;
246         }
247
248         m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create(
249             map.GetBestExecutionContextScope(),
250             m_persistent_variable_sp.get()->GetCompilerType(),
251             m_persistent_variable_sp->GetName(), location, eAddressTypeLoad,
252             m_persistent_variable_sp->GetByteSize());
253
254         if (frame_top != LLDB_INVALID_ADDRESS &&
255             frame_bottom != LLDB_INVALID_ADDRESS && location >= frame_bottom &&
256             location <= frame_top) {
257           // If the variable is resident in the stack frame created by the
258           // expression, then it cannot be relied upon to stay around.  We
259           // treat it as needing reallocation.
260           m_persistent_variable_sp->m_flags |=
261               ExpressionVariable::EVIsLLDBAllocated;
262           m_persistent_variable_sp->m_flags |=
263               ExpressionVariable::EVNeedsAllocation;
264           m_persistent_variable_sp->m_flags |=
265               ExpressionVariable::EVNeedsFreezeDry;
266           m_persistent_variable_sp->m_flags &=
267               ~ExpressionVariable::EVIsProgramReference;
268         }
269       }
270
271       lldb::addr_t mem = m_persistent_variable_sp->m_live_sp->GetValue()
272                              .GetScalar()
273                              .ULongLong();
274
275       if (!m_persistent_variable_sp->m_live_sp) {
276         err.SetErrorStringWithFormat(
277             "couldn't find the memory area used to store %s",
278             m_persistent_variable_sp->GetName().GetCString());
279         return;
280       }
281
282       if (m_persistent_variable_sp->m_live_sp->GetValue()
283               .GetValueAddressType() != eAddressTypeLoad) {
284         err.SetErrorStringWithFormat(
285             "the address of the memory area for %s is in an incorrect format",
286             m_persistent_variable_sp->GetName().GetCString());
287         return;
288       }
289
290       if (m_persistent_variable_sp->m_flags &
291               ExpressionVariable::EVNeedsFreezeDry ||
292           m_persistent_variable_sp->m_flags &
293               ExpressionVariable::EVKeepInTarget) {
294         if (log)
295           log->Printf(
296               "Dematerializing %s from 0x%" PRIx64 " (size = %llu)",
297               m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem,
298               (unsigned long long)m_persistent_variable_sp->GetByteSize());
299
300         // Read the contents of the spare memory area
301
302         m_persistent_variable_sp->ValueUpdated();
303
304         Status read_error;
305
306         map.ReadMemory(m_persistent_variable_sp->GetValueBytes(), mem,
307                        m_persistent_variable_sp->GetByteSize(), read_error);
308
309         if (!read_error.Success()) {
310           err.SetErrorStringWithFormat(
311               "couldn't read the contents of %s from memory: %s",
312               m_persistent_variable_sp->GetName().GetCString(),
313               read_error.AsCString());
314           return;
315         }
316
317         m_persistent_variable_sp->m_flags &=
318             ~ExpressionVariable::EVNeedsFreezeDry;
319       }
320     } else {
321       err.SetErrorStringWithFormat(
322           "no dematerialization happened for persistent variable %s",
323           m_persistent_variable_sp->GetName().AsCString());
324       return;
325     }
326
327     lldb::ProcessSP process_sp =
328         map.GetBestExecutionContextScope()->CalculateProcess();
329     if (!process_sp || !process_sp->CanJIT()) {
330       // Allocations are not persistent so persistent variables cannot stay
331       // materialized.
332
333       m_persistent_variable_sp->m_flags |=
334           ExpressionVariable::EVNeedsAllocation;
335
336       DestroyAllocation(map, err);
337       if (!err.Success())
338         return;
339     } else if (m_persistent_variable_sp->m_flags &
340                    ExpressionVariable::EVNeedsAllocation &&
341                !(m_persistent_variable_sp->m_flags &
342                  ExpressionVariable::EVKeepInTarget)) {
343       DestroyAllocation(map, err);
344       if (!err.Success())
345         return;
346     }
347   }
348
349   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
350                  Log *log) override {
351     StreamString dump_stream;
352
353     Status err;
354
355     const lldb::addr_t load_addr = process_address + m_offset;
356
357     dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n",
358                        load_addr,
359                        m_persistent_variable_sp->GetName().AsCString());
360
361     {
362       dump_stream.Printf("Pointer:\n");
363
364       DataBufferHeap data(m_size, 0);
365
366       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
367
368       if (!err.Success()) {
369         dump_stream.Printf("  <could not be read>\n");
370       } else {
371         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
372                      load_addr);
373
374         dump_stream.PutChar('\n');
375       }
376     }
377
378     {
379       dump_stream.Printf("Target:\n");
380
381       lldb::addr_t target_address;
382
383       map.ReadPointerFromMemory(&target_address, load_addr, err);
384
385       if (!err.Success()) {
386         dump_stream.Printf("  <could not be read>\n");
387       } else {
388         DataBufferHeap data(m_persistent_variable_sp->GetByteSize(), 0);
389
390         map.ReadMemory(data.GetBytes(), target_address,
391                        m_persistent_variable_sp->GetByteSize(), err);
392
393         if (!err.Success()) {
394           dump_stream.Printf("  <could not be read>\n");
395         } else {
396           DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
397                        target_address);
398
399           dump_stream.PutChar('\n');
400         }
401       }
402     }
403
404     log->PutString(dump_stream.GetString());
405   }
406
407   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
408
409 private:
410   lldb::ExpressionVariableSP m_persistent_variable_sp;
411   Materializer::PersistentVariableDelegate *m_delegate;
412 };
413
414 uint32_t Materializer::AddPersistentVariable(
415     lldb::ExpressionVariableSP &persistent_variable_sp,
416     PersistentVariableDelegate *delegate, Status &err) {
417   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
418   iter->reset(new EntityPersistentVariable(persistent_variable_sp, delegate));
419   uint32_t ret = AddStructMember(**iter);
420   (*iter)->SetOffset(ret);
421   return ret;
422 }
423
424 class EntityVariable : public Materializer::Entity {
425 public:
426   EntityVariable(lldb::VariableSP &variable_sp)
427       : Entity(), m_variable_sp(variable_sp), m_is_reference(false),
428         m_temporary_allocation(LLDB_INVALID_ADDRESS),
429         m_temporary_allocation_size(0) {
430     // Hard-coding to maximum size of a pointer since all variables are
431     // materialized by reference
432     m_size = 8;
433     m_alignment = 8;
434     m_is_reference =
435         m_variable_sp->GetType()->GetForwardCompilerType().IsReferenceType();
436   }
437
438   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
439                    lldb::addr_t process_address, Status &err) override {
440     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
441
442     const lldb::addr_t load_addr = process_address + m_offset;
443     if (log) {
444       log->Printf("EntityVariable::Materialize [address = 0x%" PRIx64
445                   ", m_variable_sp = %s]",
446                   (uint64_t)load_addr, m_variable_sp->GetName().AsCString());
447     }
448
449     ExecutionContextScope *scope = frame_sp.get();
450
451     if (!scope)
452       scope = map.GetBestExecutionContextScope();
453
454     lldb::ValueObjectSP valobj_sp =
455         ValueObjectVariable::Create(scope, m_variable_sp);
456
457     if (!valobj_sp) {
458       err.SetErrorStringWithFormat(
459           "couldn't get a value object for variable %s",
460           m_variable_sp->GetName().AsCString());
461       return;
462     }
463
464     Status valobj_error = valobj_sp->GetError();
465
466     if (valobj_error.Fail()) {
467       err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s",
468                                    m_variable_sp->GetName().AsCString(),
469                                    valobj_error.AsCString());
470       return;
471     }
472
473     if (m_is_reference) {
474       DataExtractor valobj_extractor;
475       Status extract_error;
476       valobj_sp->GetData(valobj_extractor, extract_error);
477
478       if (!extract_error.Success()) {
479         err.SetErrorStringWithFormat(
480             "couldn't read contents of reference variable %s: %s",
481             m_variable_sp->GetName().AsCString(), extract_error.AsCString());
482         return;
483       }
484
485       lldb::offset_t offset = 0;
486       lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset);
487
488       Status write_error;
489       map.WritePointerToMemory(load_addr, reference_addr, write_error);
490
491       if (!write_error.Success()) {
492         err.SetErrorStringWithFormat("couldn't write the contents of reference "
493                                      "variable %s to memory: %s",
494                                      m_variable_sp->GetName().AsCString(),
495                                      write_error.AsCString());
496         return;
497       }
498     } else {
499       AddressType address_type = eAddressTypeInvalid;
500       const bool scalar_is_load_address = false;
501       lldb::addr_t addr_of_valobj =
502           valobj_sp->GetAddressOf(scalar_is_load_address, &address_type);
503       if (addr_of_valobj != LLDB_INVALID_ADDRESS) {
504         Status write_error;
505         map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);
506
507         if (!write_error.Success()) {
508           err.SetErrorStringWithFormat(
509               "couldn't write the address of variable %s to memory: %s",
510               m_variable_sp->GetName().AsCString(), write_error.AsCString());
511           return;
512         }
513       } else {
514         DataExtractor data;
515         Status extract_error;
516         valobj_sp->GetData(data, extract_error);
517         if (!extract_error.Success()) {
518           err.SetErrorStringWithFormat("couldn't get the value of %s: %s",
519                                        m_variable_sp->GetName().AsCString(),
520                                        extract_error.AsCString());
521           return;
522         }
523
524         if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
525           err.SetErrorStringWithFormat(
526               "trying to create a temporary region for %s but one exists",
527               m_variable_sp->GetName().AsCString());
528           return;
529         }
530
531         if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize()) {
532           if (data.GetByteSize() == 0 &&
533               !m_variable_sp->LocationExpression().IsValid()) {
534             err.SetErrorStringWithFormat("the variable '%s' has no location, "
535                                          "it may have been optimized out",
536                                          m_variable_sp->GetName().AsCString());
537           } else {
538             err.SetErrorStringWithFormat(
539                 "size of variable %s (%" PRIu64
540                 ") is larger than the ValueObject's size (%" PRIu64 ")",
541                 m_variable_sp->GetName().AsCString(),
542                 m_variable_sp->GetType()->GetByteSize().getValueOr(0),
543                 data.GetByteSize());
544           }
545           return;
546         }
547
548         size_t bit_align =
549             m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign();
550         size_t byte_align = (bit_align + 7) / 8;
551
552         if (!byte_align)
553           byte_align = 1;
554
555         Status alloc_error;
556         const bool zero_memory = false;
557
558         m_temporary_allocation = map.Malloc(
559             data.GetByteSize(), byte_align,
560             lldb::ePermissionsReadable | lldb::ePermissionsWritable,
561             IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error);
562
563         m_temporary_allocation_size = data.GetByteSize();
564
565         m_original_data = std::make_shared<DataBufferHeap>(data.GetDataStart(),
566                                                            data.GetByteSize());
567
568         if (!alloc_error.Success()) {
569           err.SetErrorStringWithFormat(
570               "couldn't allocate a temporary region for %s: %s",
571               m_variable_sp->GetName().AsCString(), alloc_error.AsCString());
572           return;
573         }
574
575         Status write_error;
576
577         map.WriteMemory(m_temporary_allocation, data.GetDataStart(),
578                         data.GetByteSize(), write_error);
579
580         if (!write_error.Success()) {
581           err.SetErrorStringWithFormat(
582               "couldn't write to the temporary region for %s: %s",
583               m_variable_sp->GetName().AsCString(), write_error.AsCString());
584           return;
585         }
586
587         Status pointer_write_error;
588
589         map.WritePointerToMemory(load_addr, m_temporary_allocation,
590                                  pointer_write_error);
591
592         if (!pointer_write_error.Success()) {
593           err.SetErrorStringWithFormat(
594               "couldn't write the address of the temporary region for %s: %s",
595               m_variable_sp->GetName().AsCString(),
596               pointer_write_error.AsCString());
597         }
598       }
599     }
600   }
601
602   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
603                      lldb::addr_t process_address, lldb::addr_t frame_top,
604                      lldb::addr_t frame_bottom, Status &err) override {
605     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
606
607     const lldb::addr_t load_addr = process_address + m_offset;
608     if (log) {
609       log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64
610                   ", m_variable_sp = %s]",
611                   (uint64_t)load_addr, m_variable_sp->GetName().AsCString());
612     }
613
614     if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
615       ExecutionContextScope *scope = frame_sp.get();
616
617       if (!scope)
618         scope = map.GetBestExecutionContextScope();
619
620       lldb::ValueObjectSP valobj_sp =
621           ValueObjectVariable::Create(scope, m_variable_sp);
622
623       if (!valobj_sp) {
624         err.SetErrorStringWithFormat(
625             "couldn't get a value object for variable %s",
626             m_variable_sp->GetName().AsCString());
627         return;
628       }
629
630       lldb_private::DataExtractor data;
631
632       Status extract_error;
633
634       map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(),
635                         extract_error);
636
637       if (!extract_error.Success()) {
638         err.SetErrorStringWithFormat("couldn't get the data for variable %s",
639                                      m_variable_sp->GetName().AsCString());
640         return;
641       }
642
643       bool actually_write = true;
644
645       if (m_original_data) {
646         if ((data.GetByteSize() == m_original_data->GetByteSize()) &&
647             !memcmp(m_original_data->GetBytes(), data.GetDataStart(),
648                     data.GetByteSize())) {
649           actually_write = false;
650         }
651       }
652
653       Status set_error;
654
655       if (actually_write) {
656         valobj_sp->SetData(data, set_error);
657
658         if (!set_error.Success()) {
659           err.SetErrorStringWithFormat(
660               "couldn't write the new contents of %s back into the variable",
661               m_variable_sp->GetName().AsCString());
662           return;
663         }
664       }
665
666       Status free_error;
667
668       map.Free(m_temporary_allocation, free_error);
669
670       if (!free_error.Success()) {
671         err.SetErrorStringWithFormat(
672             "couldn't free the temporary region for %s: %s",
673             m_variable_sp->GetName().AsCString(), free_error.AsCString());
674         return;
675       }
676
677       m_original_data.reset();
678       m_temporary_allocation = LLDB_INVALID_ADDRESS;
679       m_temporary_allocation_size = 0;
680     }
681   }
682
683   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
684                  Log *log) override {
685     StreamString dump_stream;
686
687     const lldb::addr_t load_addr = process_address + m_offset;
688     dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr);
689
690     Status err;
691
692     lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
693
694     {
695       dump_stream.Printf("Pointer:\n");
696
697       DataBufferHeap data(m_size, 0);
698
699       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
700
701       if (!err.Success()) {
702         dump_stream.Printf("  <could not be read>\n");
703       } else {
704         DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
705                                 map.GetByteOrder(), map.GetAddressByteSize());
706
707         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
708                      load_addr);
709
710         lldb::offset_t offset;
711
712         ptr = extractor.GetPointer(&offset);
713
714         dump_stream.PutChar('\n');
715       }
716     }
717
718     if (m_temporary_allocation == LLDB_INVALID_ADDRESS) {
719       dump_stream.Printf("Points to process memory:\n");
720     } else {
721       dump_stream.Printf("Temporary allocation:\n");
722     }
723
724     if (ptr == LLDB_INVALID_ADDRESS) {
725       dump_stream.Printf("  <could not be be found>\n");
726     } else {
727       DataBufferHeap data(m_temporary_allocation_size, 0);
728
729       map.ReadMemory(data.GetBytes(), m_temporary_allocation,
730                      m_temporary_allocation_size, err);
731
732       if (!err.Success()) {
733         dump_stream.Printf("  <could not be read>\n");
734       } else {
735         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
736                      load_addr);
737
738         dump_stream.PutChar('\n');
739       }
740     }
741
742     log->PutString(dump_stream.GetString());
743   }
744
745   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
746     if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
747       Status free_error;
748
749       map.Free(m_temporary_allocation, free_error);
750
751       m_temporary_allocation = LLDB_INVALID_ADDRESS;
752       m_temporary_allocation_size = 0;
753     }
754   }
755
756 private:
757   lldb::VariableSP m_variable_sp;
758   bool m_is_reference;
759   lldb::addr_t m_temporary_allocation;
760   size_t m_temporary_allocation_size;
761   lldb::DataBufferSP m_original_data;
762 };
763
764 uint32_t Materializer::AddVariable(lldb::VariableSP &variable_sp, Status &err) {
765   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
766   iter->reset(new EntityVariable(variable_sp));
767   uint32_t ret = AddStructMember(**iter);
768   (*iter)->SetOffset(ret);
769   return ret;
770 }
771
772 class EntityResultVariable : public Materializer::Entity {
773 public:
774   EntityResultVariable(const CompilerType &type, bool is_program_reference,
775                        bool keep_in_memory,
776                        Materializer::PersistentVariableDelegate *delegate)
777       : Entity(), m_type(type), m_is_program_reference(is_program_reference),
778         m_keep_in_memory(keep_in_memory),
779         m_temporary_allocation(LLDB_INVALID_ADDRESS),
780         m_temporary_allocation_size(0), m_delegate(delegate) {
781     // Hard-coding to maximum size of a pointer since all results are
782     // materialized by reference
783     m_size = 8;
784     m_alignment = 8;
785   }
786
787   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
788                    lldb::addr_t process_address, Status &err) override {
789     if (!m_is_program_reference) {
790       if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
791         err.SetErrorString("Trying to create a temporary region for the result "
792                            "but one exists");
793         return;
794       }
795
796       const lldb::addr_t load_addr = process_address + m_offset;
797
798       ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
799
800       llvm::Optional<uint64_t> byte_size = m_type.GetByteSize(exe_scope);
801       if (!byte_size) {
802         err.SetErrorString("can't get size of type");
803         return;
804       }
805       size_t bit_align = m_type.GetTypeBitAlign();
806       size_t byte_align = (bit_align + 7) / 8;
807
808       if (!byte_align)
809         byte_align = 1;
810
811       Status alloc_error;
812       const bool zero_memory = true;
813
814       m_temporary_allocation = map.Malloc(
815           *byte_size, byte_align,
816           lldb::ePermissionsReadable | lldb::ePermissionsWritable,
817           IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error);
818       m_temporary_allocation_size = *byte_size;
819
820       if (!alloc_error.Success()) {
821         err.SetErrorStringWithFormat(
822             "couldn't allocate a temporary region for the result: %s",
823             alloc_error.AsCString());
824         return;
825       }
826
827       Status pointer_write_error;
828
829       map.WritePointerToMemory(load_addr, m_temporary_allocation,
830                                pointer_write_error);
831
832       if (!pointer_write_error.Success()) {
833         err.SetErrorStringWithFormat("couldn't write the address of the "
834                                      "temporary region for the result: %s",
835                                      pointer_write_error.AsCString());
836       }
837     }
838   }
839
840   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
841                      lldb::addr_t process_address, lldb::addr_t frame_top,
842                      lldb::addr_t frame_bottom, Status &err) override {
843     err.Clear();
844
845     ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
846
847     if (!exe_scope) {
848       err.SetErrorString("Couldn't dematerialize a result variable: invalid "
849                          "execution context scope");
850       return;
851     }
852
853     lldb::addr_t address;
854     Status read_error;
855     const lldb::addr_t load_addr = process_address + m_offset;
856
857     map.ReadPointerFromMemory(&address, load_addr, read_error);
858
859     if (!read_error.Success()) {
860       err.SetErrorString("Couldn't dematerialize a result variable: couldn't "
861                          "read its address");
862       return;
863     }
864
865     lldb::TargetSP target_sp = exe_scope->CalculateTarget();
866
867     if (!target_sp) {
868       err.SetErrorString("Couldn't dematerialize a result variable: no target");
869       return;
870     }
871
872     Status type_system_error;
873     TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(
874         &type_system_error, m_type.GetMinimumLanguage());
875
876     if (!type_system) {
877       err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: "
878                                    "couldn't get the corresponding type "
879                                    "system: %s",
880                                    type_system_error.AsCString());
881       return;
882     }
883
884     PersistentExpressionState *persistent_state =
885         type_system->GetPersistentExpressionState();
886
887     if (!persistent_state) {
888       err.SetErrorString("Couldn't dematerialize a result variable: "
889                          "corresponding type system doesn't handle persistent "
890                          "variables");
891       return;
892     }
893
894     ConstString name =
895         m_delegate
896             ? m_delegate->GetName()
897             : persistent_state->GetNextPersistentVariableName(
898                   *target_sp, persistent_state->GetPersistentVariablePrefix());
899
900     lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(
901         exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize());
902
903     if (!ret) {
904       err.SetErrorStringWithFormat("couldn't dematerialize a result variable: "
905                                    "failed to make persistent variable %s",
906                                    name.AsCString());
907       return;
908     }
909
910     lldb::ProcessSP process_sp =
911         map.GetBestExecutionContextScope()->CalculateProcess();
912
913     if (m_delegate) {
914       m_delegate->DidDematerialize(ret);
915     }
916
917     bool can_persist =
918         (m_is_program_reference && process_sp && process_sp->CanJIT() &&
919          !(address >= frame_bottom && address < frame_top));
920
921     if (can_persist && m_keep_in_memory) {
922       ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name,
923                                                       address, eAddressTypeLoad,
924                                                       map.GetAddressByteSize());
925     }
926
927     ret->ValueUpdated();
928
929     const size_t pvar_byte_size = ret->GetByteSize();
930     uint8_t *pvar_data = ret->GetValueBytes();
931
932     map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);
933
934     if (!read_error.Success()) {
935       err.SetErrorString(
936           "Couldn't dematerialize a result variable: couldn't read its memory");
937       return;
938     }
939
940     if (!can_persist || !m_keep_in_memory) {
941       ret->m_flags |= ExpressionVariable::EVNeedsAllocation;
942
943       if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
944         Status free_error;
945         map.Free(m_temporary_allocation, free_error);
946       }
947     } else {
948       ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
949     }
950
951     m_temporary_allocation = LLDB_INVALID_ADDRESS;
952     m_temporary_allocation_size = 0;
953   }
954
955   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
956                  Log *log) override {
957     StreamString dump_stream;
958
959     const lldb::addr_t load_addr = process_address + m_offset;
960
961     dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr);
962
963     Status err;
964
965     lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
966
967     {
968       dump_stream.Printf("Pointer:\n");
969
970       DataBufferHeap data(m_size, 0);
971
972       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
973
974       if (!err.Success()) {
975         dump_stream.Printf("  <could not be read>\n");
976       } else {
977         DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
978                                 map.GetByteOrder(), map.GetAddressByteSize());
979
980         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
981                      load_addr);
982
983         lldb::offset_t offset;
984
985         ptr = extractor.GetPointer(&offset);
986
987         dump_stream.PutChar('\n');
988       }
989     }
990
991     if (m_temporary_allocation == LLDB_INVALID_ADDRESS) {
992       dump_stream.Printf("Points to process memory:\n");
993     } else {
994       dump_stream.Printf("Temporary allocation:\n");
995     }
996
997     if (ptr == LLDB_INVALID_ADDRESS) {
998       dump_stream.Printf("  <could not be be found>\n");
999     } else {
1000       DataBufferHeap data(m_temporary_allocation_size, 0);
1001
1002       map.ReadMemory(data.GetBytes(), m_temporary_allocation,
1003                      m_temporary_allocation_size, err);
1004
1005       if (!err.Success()) {
1006         dump_stream.Printf("  <could not be read>\n");
1007       } else {
1008         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1009                      load_addr);
1010
1011         dump_stream.PutChar('\n');
1012       }
1013     }
1014
1015     log->PutString(dump_stream.GetString());
1016   }
1017
1018   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
1019     if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) {
1020       Status free_error;
1021
1022       map.Free(m_temporary_allocation, free_error);
1023     }
1024
1025     m_temporary_allocation = LLDB_INVALID_ADDRESS;
1026     m_temporary_allocation_size = 0;
1027   }
1028
1029 private:
1030   CompilerType m_type;
1031   bool m_is_program_reference;
1032   bool m_keep_in_memory;
1033
1034   lldb::addr_t m_temporary_allocation;
1035   size_t m_temporary_allocation_size;
1036   Materializer::PersistentVariableDelegate *m_delegate;
1037 };
1038
1039 uint32_t Materializer::AddResultVariable(const CompilerType &type,
1040                                          bool is_program_reference,
1041                                          bool keep_in_memory,
1042                                          PersistentVariableDelegate *delegate,
1043                                          Status &err) {
1044   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1045   iter->reset(new EntityResultVariable(type, is_program_reference,
1046                                        keep_in_memory, delegate));
1047   uint32_t ret = AddStructMember(**iter);
1048   (*iter)->SetOffset(ret);
1049   return ret;
1050 }
1051
1052 class EntitySymbol : public Materializer::Entity {
1053 public:
1054   EntitySymbol(const Symbol &symbol) : Entity(), m_symbol(symbol) {
1055     // Hard-coding to maximum size of a symbol
1056     m_size = 8;
1057     m_alignment = 8;
1058   }
1059
1060   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1061                    lldb::addr_t process_address, Status &err) override {
1062     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
1063
1064     const lldb::addr_t load_addr = process_address + m_offset;
1065
1066     if (log) {
1067       log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64
1068                   ", m_symbol = %s]",
1069                   (uint64_t)load_addr, m_symbol.GetName().AsCString());
1070     }
1071
1072     const Address sym_address = m_symbol.GetAddress();
1073
1074     ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
1075
1076     lldb::TargetSP target_sp;
1077
1078     if (exe_scope)
1079       target_sp = map.GetBestExecutionContextScope()->CalculateTarget();
1080
1081     if (!target_sp) {
1082       err.SetErrorStringWithFormat(
1083           "couldn't resolve symbol %s because there is no target",
1084           m_symbol.GetName().AsCString());
1085       return;
1086     }
1087
1088     lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get());
1089
1090     if (resolved_address == LLDB_INVALID_ADDRESS)
1091       resolved_address = sym_address.GetFileAddress();
1092
1093     Status pointer_write_error;
1094
1095     map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);
1096
1097     if (!pointer_write_error.Success()) {
1098       err.SetErrorStringWithFormat(
1099           "couldn't write the address of symbol %s: %s",
1100           m_symbol.GetName().AsCString(), pointer_write_error.AsCString());
1101       return;
1102     }
1103   }
1104
1105   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1106                      lldb::addr_t process_address, lldb::addr_t frame_top,
1107                      lldb::addr_t frame_bottom, Status &err) override {
1108     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
1109
1110     const lldb::addr_t load_addr = process_address + m_offset;
1111
1112     if (log) {
1113       log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64
1114                   ", m_symbol = %s]",
1115                   (uint64_t)load_addr, m_symbol.GetName().AsCString());
1116     }
1117
1118     // no work needs to be done
1119   }
1120
1121   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1122                  Log *log) override {
1123     StreamString dump_stream;
1124
1125     Status err;
1126
1127     const lldb::addr_t load_addr = process_address + m_offset;
1128
1129     dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr,
1130                        m_symbol.GetName().AsCString());
1131
1132     {
1133       dump_stream.Printf("Pointer:\n");
1134
1135       DataBufferHeap data(m_size, 0);
1136
1137       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1138
1139       if (!err.Success()) {
1140         dump_stream.Printf("  <could not be read>\n");
1141       } else {
1142         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1143                      load_addr);
1144
1145         dump_stream.PutChar('\n');
1146       }
1147     }
1148
1149     log->PutString(dump_stream.GetString());
1150   }
1151
1152   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
1153
1154 private:
1155   Symbol m_symbol;
1156 };
1157
1158 uint32_t Materializer::AddSymbol(const Symbol &symbol_sp, Status &err) {
1159   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1160   iter->reset(new EntitySymbol(symbol_sp));
1161   uint32_t ret = AddStructMember(**iter);
1162   (*iter)->SetOffset(ret);
1163   return ret;
1164 }
1165
1166 class EntityRegister : public Materializer::Entity {
1167 public:
1168   EntityRegister(const RegisterInfo &register_info)
1169       : Entity(), m_register_info(register_info) {
1170     // Hard-coding alignment conservatively
1171     m_size = m_register_info.byte_size;
1172     m_alignment = m_register_info.byte_size;
1173   }
1174
1175   void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1176                    lldb::addr_t process_address, Status &err) override {
1177     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
1178
1179     const lldb::addr_t load_addr = process_address + m_offset;
1180
1181     if (log) {
1182       log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64
1183                   ", m_register_info = %s]",
1184                   (uint64_t)load_addr, m_register_info.name);
1185     }
1186
1187     RegisterValue reg_value;
1188
1189     if (!frame_sp.get()) {
1190       err.SetErrorStringWithFormat(
1191           "couldn't materialize register %s without a stack frame",
1192           m_register_info.name);
1193       return;
1194     }
1195
1196     lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1197
1198     if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) {
1199       err.SetErrorStringWithFormat("couldn't read the value of register %s",
1200                                    m_register_info.name);
1201       return;
1202     }
1203
1204     DataExtractor register_data;
1205
1206     if (!reg_value.GetData(register_data)) {
1207       err.SetErrorStringWithFormat("couldn't get the data for register %s",
1208                                    m_register_info.name);
1209       return;
1210     }
1211
1212     if (register_data.GetByteSize() != m_register_info.byte_size) {
1213       err.SetErrorStringWithFormat(
1214           "data for register %s had size %llu but we expected %llu",
1215           m_register_info.name, (unsigned long long)register_data.GetByteSize(),
1216           (unsigned long long)m_register_info.byte_size);
1217       return;
1218     }
1219
1220     m_register_contents = std::make_shared<DataBufferHeap>(
1221         register_data.GetDataStart(), register_data.GetByteSize());
1222
1223     Status write_error;
1224
1225     map.WriteMemory(load_addr, register_data.GetDataStart(),
1226                     register_data.GetByteSize(), write_error);
1227
1228     if (!write_error.Success()) {
1229       err.SetErrorStringWithFormat(
1230           "couldn't write the contents of register %s: %s",
1231           m_register_info.name, write_error.AsCString());
1232       return;
1233     }
1234   }
1235
1236   void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1237                      lldb::addr_t process_address, lldb::addr_t frame_top,
1238                      lldb::addr_t frame_bottom, Status &err) override {
1239     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
1240
1241     const lldb::addr_t load_addr = process_address + m_offset;
1242
1243     if (log) {
1244       log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64
1245                   ", m_register_info = %s]",
1246                   (uint64_t)load_addr, m_register_info.name);
1247     }
1248
1249     Status extract_error;
1250
1251     DataExtractor register_data;
1252
1253     if (!frame_sp.get()) {
1254       err.SetErrorStringWithFormat(
1255           "couldn't dematerialize register %s without a stack frame",
1256           m_register_info.name);
1257       return;
1258     }
1259
1260     lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1261
1262     map.GetMemoryData(register_data, load_addr, m_register_info.byte_size,
1263                       extract_error);
1264
1265     if (!extract_error.Success()) {
1266       err.SetErrorStringWithFormat("couldn't get the data for register %s: %s",
1267                                    m_register_info.name,
1268                                    extract_error.AsCString());
1269       return;
1270     }
1271
1272     if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(),
1273                 register_data.GetByteSize())) {
1274       // No write required, and in particular we avoid errors if the register
1275       // wasn't writable
1276
1277       m_register_contents.reset();
1278       return;
1279     }
1280
1281     m_register_contents.reset();
1282
1283     RegisterValue register_value(
1284         const_cast<uint8_t *>(register_data.GetDataStart()),
1285         register_data.GetByteSize(), register_data.GetByteOrder());
1286
1287     if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) {
1288       err.SetErrorStringWithFormat("couldn't write the value of register %s",
1289                                    m_register_info.name);
1290       return;
1291     }
1292   }
1293
1294   void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1295                  Log *log) override {
1296     StreamString dump_stream;
1297
1298     Status err;
1299
1300     const lldb::addr_t load_addr = process_address + m_offset;
1301
1302     dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr,
1303                        m_register_info.name);
1304
1305     {
1306       dump_stream.Printf("Value:\n");
1307
1308       DataBufferHeap data(m_size, 0);
1309
1310       map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1311
1312       if (!err.Success()) {
1313         dump_stream.Printf("  <could not be read>\n");
1314       } else {
1315         DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1316                      load_addr);
1317
1318         dump_stream.PutChar('\n');
1319       }
1320     }
1321
1322     log->PutString(dump_stream.GetString());
1323   }
1324
1325   void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
1326
1327 private:
1328   RegisterInfo m_register_info;
1329   lldb::DataBufferSP m_register_contents;
1330 };
1331
1332 uint32_t Materializer::AddRegister(const RegisterInfo &register_info,
1333                                    Status &err) {
1334   EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1335   iter->reset(new EntityRegister(register_info));
1336   uint32_t ret = AddStructMember(**iter);
1337   (*iter)->SetOffset(ret);
1338   return ret;
1339 }
1340
1341 Materializer::Materializer()
1342     : m_dematerializer_wp(), m_current_offset(0), m_struct_alignment(8) {}
1343
1344 Materializer::~Materializer() {
1345   DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1346
1347   if (dematerializer_sp)
1348     dematerializer_sp->Wipe();
1349 }
1350
1351 Materializer::DematerializerSP
1352 Materializer::Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
1353                           lldb::addr_t process_address, Status &error) {
1354   ExecutionContextScope *exe_scope = frame_sp.get();
1355
1356   if (!exe_scope)
1357     exe_scope = map.GetBestExecutionContextScope();
1358
1359   DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1360
1361   if (dematerializer_sp) {
1362     error.SetErrorToGenericError();
1363     error.SetErrorString("Couldn't materialize: already materialized");
1364   }
1365
1366   DematerializerSP ret(
1367       new Dematerializer(*this, frame_sp, map, process_address));
1368
1369   if (!exe_scope) {
1370     error.SetErrorToGenericError();
1371     error.SetErrorString("Couldn't materialize: target doesn't exist");
1372   }
1373
1374   for (EntityUP &entity_up : m_entities) {
1375     entity_up->Materialize(frame_sp, map, process_address, error);
1376
1377     if (!error.Success())
1378       return DematerializerSP();
1379   }
1380
1381   if (Log *log =
1382           lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
1383     log->Printf(
1384         "Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64
1385         ") materialized:",
1386         static_cast<void *>(frame_sp.get()), process_address);
1387     for (EntityUP &entity_up : m_entities)
1388       entity_up->DumpToLog(map, process_address, log);
1389   }
1390
1391   m_dematerializer_wp = ret;
1392
1393   return ret;
1394 }
1395
1396 void Materializer::Dematerializer::Dematerialize(Status &error,
1397                                                  lldb::addr_t frame_bottom,
1398                                                  lldb::addr_t frame_top) {
1399   lldb::StackFrameSP frame_sp;
1400
1401   lldb::ThreadSP thread_sp = m_thread_wp.lock();
1402   if (thread_sp)
1403     frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);
1404
1405   ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope();
1406
1407   if (!IsValid()) {
1408     error.SetErrorToGenericError();
1409     error.SetErrorString("Couldn't dematerialize: invalid dematerializer");
1410   }
1411
1412   if (!exe_scope) {
1413     error.SetErrorToGenericError();
1414     error.SetErrorString("Couldn't dematerialize: target is gone");
1415   } else {
1416     if (Log *log =
1417             lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
1418       log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address "
1419                   "= 0x%" PRIx64 ") about to dematerialize:",
1420                   static_cast<void *>(frame_sp.get()), m_process_address);
1421       for (EntityUP &entity_up : m_materializer->m_entities)
1422         entity_up->DumpToLog(*m_map, m_process_address, log);
1423     }
1424
1425     for (EntityUP &entity_up : m_materializer->m_entities) {
1426       entity_up->Dematerialize(frame_sp, *m_map, m_process_address, frame_top,
1427                                frame_bottom, error);
1428
1429       if (!error.Success())
1430         break;
1431     }
1432   }
1433
1434   Wipe();
1435 }
1436
1437 void Materializer::Dematerializer::Wipe() {
1438   if (!IsValid())
1439     return;
1440
1441   for (EntityUP &entity_up : m_materializer->m_entities) {
1442     entity_up->Wipe(*m_map, m_process_address);
1443   }
1444
1445   m_materializer = nullptr;
1446   m_map = nullptr;
1447   m_process_address = LLDB_INVALID_ADDRESS;
1448 }
1449
1450 Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() =
1451     default;