I have brought LLDB up-to-date with top of tree
LLVM/Clang.  This brings in several fixes, including:

- Improvements in the Just-In-Time compiler's
  allocation of memory: the JIT now allocates
  memory in chunks of sections, improving its
  ability to generate relocations.  I have
  revamped the RecordingMemoryManager to reflect
  these changes, as well as to get the memory
  allocation and data copying out fo the
  ClangExpressionParser code.  Jim Grosbach wrote
  the updates to the JIT on the LLVM side.

- A new ExternalASTSource interface to allow LLDB to
  report accurate structure layout information to
  Clang.  Previously we could only report the sizes
  of fields, not their offsets.  This meant that if
  data structures included field alignment
  directives, we could not communicate the necessary
  alignment to Clang and accesses to the data would
  fail.  Now we can (and I have update the relevant
  test case).  Thanks to Doug Gregor for implementing
  the Clang side of this fix.

- The way Objective-C interfaces are completed by
  Clang has been made consistent with RecordDecls;
  with help from Doug Gregor and Greg Clayton I have
  ensured that this still works.

- I have eliminated all local LLVM and Clang patches,
  committing the ones that are still relevant to LLVM
  and Clang as needed.

I have tested the changes extensively locally, but
please let me know if they cause any trouble for you.


git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@149775 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/ClangASTSource.cpp b/source/Expression/ClangASTSource.cpp
index 162dfab..738b342 100644
--- a/source/Expression/ClangASTSource.cpp
+++ b/source/Expression/ClangASTSource.cpp
@@ -9,6 +9,7 @@
 
 
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleList.h"
@@ -448,7 +449,7 @@
     }
     else if (isa<ObjCInterfaceDecl>(context.m_decl_context))
     {
-        FindObjCPropertyDecls(context);
+        FindObjCPropertyAndIvarDecls(context);
     }
     else if (!isa<TranslationUnitDecl>(context.m_decl_context))
     {
@@ -499,6 +500,12 @@
     
     const char *name_unique_cstr = name.GetCString();
     
+    static ConstString id_name("id");
+    static ConstString Class_name("Class");
+    
+    if (name == id_name || name == Class_name)
+        return;
+    
     if (name_unique_cstr == NULL)
         return;
     
@@ -567,16 +574,10 @@
         }
     }
     
-    static ConstString id_name("id");
-    static ConstString Class_name("Class");
-    
     do 
     {
         TypeList types;
         SymbolContext null_sc;
-        
-        if (name == id_name || name == Class_name)
-            break;
       
         if (module_sp && namespace_decl)
             module_sp->FindTypes(null_sc, name, &namespace_decl, true, 1, types);
@@ -788,62 +789,308 @@
     }
 }
 
+template <class D> class TaggedASTDecl {
+public:
+    TaggedASTDecl() : decl(NULL) { }
+    TaggedASTDecl(D *_decl) : decl(_decl) { }
+    bool IsValid() const { return (decl != NULL); }
+    bool IsInvalid() const { return !IsValid(); }
+    D *operator->() const { return decl; }
+    D *decl;
+};
+
+template <class D2, template <class D> class TD, class D1> 
+TD<D2>
+DynCast(TD<D1> source)
+{
+    return TD<D2> (dyn_cast<D2>(source.decl));
+}
+
+template <class D = Decl> class DeclFromParser;
+template <class D = Decl> class DeclFromUser;
+
+template <class D> class DeclFromParser : public TaggedASTDecl<D> { 
+public:
+    DeclFromParser() : TaggedASTDecl<D>() { }
+    DeclFromParser(D *_decl) : TaggedASTDecl<D>(_decl) { }
+    
+    DeclFromUser<D> GetOrigin(ClangASTImporter *importer);
+};
+
+template <class D> class DeclFromUser : public TaggedASTDecl<D> { 
+public:
+    DeclFromUser() : TaggedASTDecl<D>() { }
+    DeclFromUser(D *_decl) : TaggedASTDecl<D>(_decl) { }
+    
+    DeclFromParser<D> Import(ClangASTImporter *importer, ASTContext &dest_ctx);
+};
+
+template <class D>
+DeclFromUser<D>
+DeclFromParser<D>::GetOrigin(ClangASTImporter *importer)
+{
+    DeclFromUser <> origin_decl;
+    importer->ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL);
+    if (origin_decl.IsInvalid())
+        return DeclFromUser<D>();
+    return DeclFromUser<D>(dyn_cast<D>(origin_decl.decl));
+}
+
+template <class D>
+DeclFromParser<D>
+DeclFromUser<D>::Import(ClangASTImporter *importer, ASTContext &dest_ctx)
+{
+    DeclFromParser <> parser_generic_decl(importer->CopyDecl(&dest_ctx, &this->decl->getASTContext(), this->decl));
+    if (parser_generic_decl.IsInvalid())
+        return DeclFromParser<D>();
+    return DeclFromParser<D>(dyn_cast<D>(parser_generic_decl.decl));
+}
+
 void
-ClangASTSource::FindObjCPropertyDecls (NameSearchContext &context)
+ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context)
 {
     lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
 
     static unsigned int invocation_id = 0;
     unsigned int current_id = invocation_id++;
     
-    const ObjCInterfaceDecl *iface_decl = cast<ObjCInterfaceDecl>(context.m_decl_context);
-    Decl *orig_decl;
-    ASTContext *orig_ast_ctx;
+    DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl(cast<ObjCInterfaceDecl>(context.m_decl_context));
+    DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer));
     
-    m_ast_importer->ResolveDeclOrigin(iface_decl, &orig_decl, &orig_ast_ctx);
-    
-    if (!orig_decl)
+    if (origin_iface_decl.IsInvalid())
         return;
     
-    ObjCInterfaceDecl *orig_iface_decl = dyn_cast<ObjCInterfaceDecl>(orig_decl);
-    
-    if (!orig_iface_decl)
-        return;
-    
-    if (!ClangASTContext::GetCompleteDecl(orig_ast_ctx, orig_iface_decl))
-        return;
-    
-    std::string property_name_str = context.m_decl_name.getAsString();
-    StringRef property_name(property_name_str.c_str());
-    ObjCPropertyDecl *property_decl = orig_iface_decl->FindPropertyDeclaration(&orig_ast_ctx->Idents.get(property_name));
+    std::string name_str = context.m_decl_name.getAsString();
+    StringRef name(name_str.c_str());
+    IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name));
     
     if (log)
-        log->Printf("ClangASTSource::FindObjCPropertyDecls[%d] on (ASTContext*)%p for property '%s.%s'",
+        log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'",
                     current_id, 
                     m_ast_context,
-                    iface_decl->getNameAsString().c_str(), 
-                    property_name_str.c_str());
+                    parser_iface_decl->getNameAsString().c_str(), 
+                    name_str.c_str());
     
-    if (!property_decl)
-        return;
+    DeclFromUser<ObjCPropertyDecl> origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier));
     
-    Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, orig_ast_ctx, property_decl);
+    if (origin_property_decl.IsValid())
+    {
+        DeclFromParser<ObjCPropertyDecl> parser_property_decl(origin_property_decl.Import(m_ast_importer, *m_ast_context));
+        if (parser_property_decl.IsValid())
+        {
+            if (log)
+            {
+                ASTDumper dumper((Decl*)parser_property_decl.decl);
+                log->Printf("  CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
+            }
+            
+            context.AddNamedDecl(parser_property_decl.decl);
+        }
+    }
     
-    if (!copied_decl)
-        return;
+    DeclFromUser<ObjCIvarDecl> origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier));
     
-    ObjCPropertyDecl *copied_property_decl = dyn_cast<ObjCPropertyDecl>(copied_decl);
+    if (origin_ivar_decl.IsValid())
+    {
+        DeclFromParser<ObjCIvarDecl> parser_ivar_decl(origin_ivar_decl.Import(m_ast_importer, *m_ast_context));
+        if (parser_ivar_decl.IsValid())
+        {
+            if (log)
+            {
+                ASTDumper dumper((Decl*)parser_ivar_decl.decl);
+                log->Printf("  CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
+            }
+            
+            context.AddNamedDecl(parser_ivar_decl.decl);
+        }
+    }
+}
+
+typedef llvm::DenseMap <const FieldDecl *, uint64_t> FieldOffsetMap;
+typedef llvm::DenseMap <const CXXRecordDecl *, CharUnits> BaseOffsetMap;
+
+template <class D, class O>
+static bool
+ImportOffsetMap (llvm::DenseMap <const D*, O> &destination_map, 
+                 llvm::DenseMap <const D*, O> &source_map,
+                 ClangASTImporter *importer,
+                 ASTContext &dest_ctx)
+{
+    typedef llvm::DenseMap <const D*, O> MapType;
     
-    if (!copied_property_decl)
-        return;
+    for (typename MapType::iterator fi = source_map.begin(), fe = source_map.end();
+         fi != fe;
+         ++fi)
+    {
+        DeclFromUser <D> user_decl(const_cast<D*>(fi->first));
+        DeclFromParser <D> parser_decl(user_decl.Import(importer, dest_ctx));
+        if (parser_decl.IsInvalid())
+            return false;
+        destination_map.insert(std::pair<const D *, O>(parser_decl.decl, fi->second));
+    }
+    
+    return true;
+}
+
+template <bool IsVirtual> bool ExtractBaseOffsets (const ASTRecordLayout &record_layout,
+                                                   DeclFromUser<const CXXRecordDecl> &record,
+                                                   BaseOffsetMap &base_offsets)
+{
+    for (CXXRecordDecl::base_class_const_iterator 
+            bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()), 
+            be = (IsVirtual ? record->vbases_end() : record->bases_end());
+         bi != be;
+         ++bi)
+    {
+        if (!IsVirtual && bi->isVirtual())
+            continue;
+        
+        const clang::Type *origin_base_type = bi->getType().getTypePtr();
+        const clang::RecordType *origin_base_record_type = origin_base_type->getAs<RecordType>();
+        
+        if (!origin_base_record_type)
+            return false;
+        
+        DeclFromUser <RecordDecl> origin_base_record(origin_base_record_type->getDecl());
+        
+        if (origin_base_record.IsInvalid())
+            return false;
+        
+        DeclFromUser <CXXRecordDecl> origin_base_cxx_record(DynCast<CXXRecordDecl>(origin_base_record));
+        
+        if (origin_base_cxx_record.IsInvalid())
+            return false;
+        
+        CharUnits base_offset;
+        
+        if (IsVirtual)
+            base_offset = record_layout.getVBaseClassOffset(origin_base_cxx_record.decl);
+        else
+            base_offset = record_layout.getBaseClassOffset(origin_base_cxx_record.decl);
+        
+        base_offsets.insert(std::pair<const CXXRecordDecl *, CharUnits>(origin_base_cxx_record.decl, base_offset));
+    }
+    
+    return true;
+}
+                         
+bool 
+ClangASTSource::layoutRecordType(const RecordDecl *record,
+                                 uint64_t &size, 
+                                 uint64_t &alignment,
+                                 FieldOffsetMap &field_offsets,
+                                 BaseOffsetMap &base_offsets,
+                                 BaseOffsetMap &virtual_base_offsets)
+{
+    static unsigned int invocation_id = 0;
+    unsigned int current_id = invocation_id++;
+    
+    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+    
+    if (!record->getNameAsString().compare("PseudoObjectExprBitfields"))
+        fprintf(stderr, "THIS IS THE ONE!");
     
     if (log)
     {
-        ASTDumper dumper((Decl*)copied_property_decl);
-        log->Printf("  CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
+        log->Printf("LayoutRecordType[%u] on (RecordDecl*)%p [name = '%s']",
+                    current_id,
+                    m_ast_context,
+                    record->getNameAsString().c_str());
     }
- 
-    context.AddNamedDecl(copied_property_decl);
+    
+    
+    DeclFromParser <const RecordDecl> parser_record(record);
+    DeclFromUser <const RecordDecl> origin_record(parser_record.GetOrigin(m_ast_importer));
+    
+    if (origin_record.IsInvalid())
+        return false;
+        
+    FieldOffsetMap origin_field_offsets;
+    BaseOffsetMap origin_base_offsets;
+    BaseOffsetMap origin_virtual_base_offsets;
+    
+    const ASTRecordLayout &record_layout(origin_record->getASTContext().getASTRecordLayout(origin_record.decl));
+    
+    int field_idx = 0;
+    
+    for (RecordDecl::field_iterator fi = origin_record->field_begin(), fe = origin_record->field_end();
+         fi != fe;
+         ++fi)
+    {
+        uint64_t field_offset = record_layout.getFieldOffset(field_idx);
+        
+        origin_field_offsets.insert(std::pair<const FieldDecl *, uint64_t>(*fi, field_offset));
+        
+        field_idx++;
+    }
+        
+    ASTContext &parser_ast_context(record->getASTContext());
+
+    DeclFromUser <const CXXRecordDecl> origin_cxx_record(DynCast<const CXXRecordDecl>(origin_record));
+
+    if (origin_cxx_record.IsValid())
+    {
+        if (!ExtractBaseOffsets<false>(record_layout, origin_cxx_record, origin_base_offsets) ||
+            !ExtractBaseOffsets<true>(record_layout, origin_cxx_record, origin_virtual_base_offsets))
+            return false;
+    }
+
+    if (!ImportOffsetMap(field_offsets, origin_field_offsets, m_ast_importer, parser_ast_context) ||
+        !ImportOffsetMap(base_offsets, origin_base_offsets, m_ast_importer, parser_ast_context) ||
+        !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, m_ast_importer, parser_ast_context))
+        return false;
+    
+    size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth();
+    alignment = record_layout.getAlignment().getQuantity() * m_ast_context->getCharWidth();
+    
+    if (log)
+    {
+        log->Printf("LRT[%u] returned:", current_id);
+        log->Printf("LRT[%u]   Original = (RecordDecl*)%p", current_id, origin_record.decl);
+        log->Printf("LRT[%u]   Size = %lld", current_id, size);
+        log->Printf("LRT[%u]   Alignment = %lld", current_id, alignment);
+        log->Printf("LRT[%u]   Fields:", current_id);
+        for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end();
+             fi != fe;
+             ++fi)
+        {
+            log->Printf("LRT[%u]     (FieldDecl*)%p, Name = '%s', Offset = %lld bits",
+                        current_id,
+                        *fi,
+                        fi->getNameAsString().c_str(),
+                        field_offsets[*fi]);
+        }
+        DeclFromParser <const CXXRecordDecl> parser_cxx_record = DynCast<const CXXRecordDecl>(parser_record);
+        if (parser_cxx_record.IsValid())
+        {
+            log->Printf("LRT[%u]   Bases:", current_id);
+            for (CXXRecordDecl::base_class_const_iterator bi = parser_cxx_record->bases_begin(), be = parser_cxx_record->bases_end();
+                 bi != be;
+                 ++bi)
+            {
+                bool is_virtual = bi->isVirtual();
+                
+                QualType base_type = bi->getType();
+                const RecordType *base_record_type = base_type->getAs<RecordType>();
+                DeclFromParser <RecordDecl> base_record(base_record_type->getDecl());
+                DeclFromParser <CXXRecordDecl> base_cxx_record = DynCast<CXXRecordDecl>(base_record);
+                
+                log->Printf("LRT[%u]     %s(CXXRecordDecl*)%p, Name = '%s', Offset = %lld chars",
+                            current_id,
+                            (is_virtual ? "Virtual " : ""),
+                            base_cxx_record.decl,
+                            base_cxx_record.decl->getNameAsString().c_str(),
+                            (is_virtual ? virtual_base_offsets[base_cxx_record.decl].getQuantity() :
+                                          base_offsets[base_cxx_record.decl].getQuantity()));
+            }
+        }
+        else
+        {
+            log->Printf("LRD[%u]   Not a CXXRecord, so no bases", current_id);
+        }
+    }
+    
+    return true;
 }
 
 void 
diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp
index 128db9c..19c3c0e 100644
--- a/source/Expression/ClangExpressionDeclMap.cpp
+++ b/source/Expression/ClangExpressionDeclMap.cpp
@@ -415,7 +415,8 @@
         const size_t pvar_byte_size = pvar_sp->GetByteSize();
         uint8_t *pvar_data = pvar_sp->GetValueBytes();
         
-        ReadTarget(pvar_data, value, pvar_byte_size);
+        if (!ReadTarget(pvar_data, value, pvar_byte_size))
+            return false;
         
         pvar_sp->m_flags &= ~(ClangExpressionVariable::EVNeedsFreezeDry);
     }
@@ -425,6 +426,16 @@
     return true;
 }
 
+void
+ClangExpressionDeclMap::RemoveResultVariable
+(
+    const ConstString &name
+)
+{
+    ClangExpressionVariableSP pvar_sp = m_parser_vars->m_persistent_vars->GetVariable(name);
+    m_parser_vars->m_persistent_vars->RemovePersistentVariable(pvar_sp);
+}
+
 bool 
 ClangExpressionDeclMap::AddPersistentVariable 
 (
@@ -2322,6 +2333,12 @@
     if (name_unique_cstr == NULL)
         return;
     
+    static ConstString id_name("id");
+    static ConstString Class_name("Class");
+    
+    if (name == id_name || name == Class_name)
+        return;
+    
     // Only look for functions by name out in our symbols if the function 
     // doesn't start with our phony prefix of '$'
     Target *target = m_parser_vars->m_exe_ctx->GetTargetPtr();
diff --git a/source/Expression/ClangExpressionParser.cpp b/source/Expression/ClangExpressionParser.cpp
index 625b03e..958d18b 100644
--- a/source/Expression/ClangExpressionParser.cpp
+++ b/source/Expression/ClangExpressionParser.cpp
@@ -172,8 +172,7 @@
     // If there are any AST files to merge, create a frontend action
     // adaptor to perform the merge.
     if (!CI.getFrontendOpts().ASTMergeFiles.empty())
-        Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
-                                 CI.getFrontendOpts().ASTMergeFiles.size());
+        Act = new ASTMergeAction(Act, CI.getFrontendOpts().ASTMergeFiles);
     
     return Act;
 }
@@ -492,12 +491,7 @@
                                   error_stream,
                                   function_name.c_str());
         
-        if (!ir_for_target.runOnModule(*module))
-        {
-            err.SetErrorToGenericError();
-            err.SetErrorString("Couldn't prepare the expression for execution in the target");
-            return err;
-        }
+        ir_for_target.runOnModule(*module);
         
         Error &interpreter_error(ir_for_target.getInterpreterError());
         
@@ -519,6 +513,7 @@
                 err.SetErrorString("Execution needed to run in the target, but the target can't be run");
             else
                 err.SetErrorStringWithFormat("Interpreting the expression locally failed: %s", interpreter_error.AsCString());
+
             return err;
         }
         
@@ -629,58 +624,9 @@
         err.SetErrorString("Couldn't write the JIT compiled code into the target because there is no target");
         return err;
     }
-    
-    // Look over the regions allocated for the function compiled.  The JIT
-    // tries to allocate the functions & stubs close together, so we should try to
-    // write them that way too...
-    // For now I only write functions with no stubs, globals, exception tables,
-    // etc.  So I only need to write the functions.
-    
-    size_t alloc_size = 0;
-    
-    std::map<uint8_t *, uint8_t *>::iterator fun_pos = jit_memory_manager->m_functions.begin();
-    std::map<uint8_t *, uint8_t *>::iterator fun_end = jit_memory_manager->m_functions.end();
-
-    for (; fun_pos != fun_end; ++fun_pos)
-    {
-        size_t mem_size = fun_pos->second - fun_pos->first;
-        if (log)
-            log->Printf ("JIT memory: [%p - %p) size = %zu", fun_pos->first, fun_pos->second, mem_size);
-        alloc_size += mem_size;
-    }
-    
-    Error alloc_error;
-    func_allocation_addr = process->AllocateMemory (alloc_size, 
-                                                                lldb::ePermissionsReadable|lldb::ePermissionsExecutable, 
-                                                                alloc_error);
-    
-    if (func_allocation_addr == LLDB_INVALID_ADDRESS)
-    {
-        err.SetErrorToGenericError();
-        err.SetErrorStringWithFormat("Couldn't allocate memory for the JITted function: %s", alloc_error.AsCString("unknown error"));
-        return err;
-    }
-    
-    lldb::addr_t cursor = func_allocation_addr;
         
-    for (fun_pos = jit_memory_manager->m_functions.begin(); fun_pos != fun_end; fun_pos++)
-    {
-        lldb::addr_t lstart = (lldb::addr_t) (*fun_pos).first;
-        lldb::addr_t lend = (lldb::addr_t) (*fun_pos).second;
-        size_t size = lend - lstart;
-        
-        Error write_error;
-        
-        if (process->WriteMemory(cursor, (void *) lstart, size, write_error) != size)
-        {
-            err.SetErrorToGenericError();
-            err.SetErrorStringWithFormat("Couldn't copy JIT code for function into the target: %s", write_error.AsCString("unknown error"));
-            return err;
-        }
-            
-        jit_memory_manager->AddToLocalToRemoteMap (lstart, size, cursor);
-        cursor += size;
-    }
+    jit_memory_manager->CommitAllocations(*process);
+    jit_memory_manager->WriteData(*process);
     
     std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
     
@@ -690,7 +636,8 @@
     
         if (!(*pos).m_name.compare(function_name.c_str()))
         {
-            func_end = jit_memory_manager->GetRemoteRangeForLocal ((*pos).m_local_addr).second;
+            RecordingMemoryManager::AddrRange func_range = jit_memory_manager->GetRemoteRangeForLocal((*pos).m_local_addr);
+            func_end = func_range.first + func_range.second;
             func_addr = (*pos).m_remote_addr;
         }
     }
@@ -766,7 +713,7 @@
     }
     
     if (log)
-        log->Printf("Function's code range is [0x%llx-0x%llx]", func_range.first, func_range.second);
+        log->Printf("Function's code range is [0x%llx+0x%llx]", func_range.first, func_range.second);
     
     Target *target = exe_ctx.GetTargetPtr();
     if (!target)
@@ -775,7 +722,7 @@
         ret.SetErrorString("Couldn't find the target");
     }
     
-    lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second - func_remote_addr, 0));
+    lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));
     
     Process *process = exe_ctx.GetProcessPtr();
     Error err;
diff --git a/source/Expression/ClangPersistentVariables.cpp b/source/Expression/ClangPersistentVariables.cpp
index 3da9dc8..db062d2 100644
--- a/source/Expression/ClangPersistentVariables.cpp
+++ b/source/Expression/ClangPersistentVariables.cpp
@@ -46,6 +46,20 @@
     return var_sp;
 }
 
+void
+ClangPersistentVariables::RemovePersistentVariable (lldb::ClangExpressionVariableSP variable)
+{
+    RemoveVariable(variable);
+    
+    const char *name = variable->GetName().AsCString();
+    
+    if (*name != '$')
+        return;
+    name++;
+    
+    if (strtoul(name, NULL, 0) == m_next_persistent_variable_id - 1)
+        m_next_persistent_variable_id--;
+}
 
 ConstString
 ClangPersistentVariables::GetNextPersistentVariableName ()
diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp
index 15ba250..5cd1708 100644
--- a/source/Expression/IRForTarget.cpp
+++ b/source/Expression/IRForTarget.cpp
@@ -2669,6 +2669,11 @@
             return true;
     }
     
+    if (m_execution_policy == lldb_private::eExecutionPolicyNever) {
+        m_decl_map->RemoveResultVariable(m_result_name);
+        return false;
+    }
+    
     if (log && log->GetVerbose())
     {
         std::string s;
diff --git a/source/Expression/IRInterpreter.cpp b/source/Expression/IRInterpreter.cpp
index a7ca4c8..741f27e 100644
--- a/source/Expression/IRInterpreter.cpp
+++ b/source/Expression/IRInterpreter.cpp
@@ -873,6 +873,7 @@
 static const char *memory_write_error               = "Interpreter couldn't write to memory";
 static const char *memory_read_error                = "Interpreter couldn't read from memory";
 static const char *infinite_loop_error              = "Interpreter ran for too many cycles";
+static const char *bad_result_error                 = "Result of expression is in bad memory";
 
 bool
 IRInterpreter::supportsFunction (Function &llvm_function, 
@@ -1524,7 +1525,17 @@
                     return true;
                 
                 GlobalValue *result_value = llvm_module.getNamedValue(result_name.GetCString());
-                return frame.ConstructResult(result, result_value, result_name, result_type, llvm_module);
+                
+                if (!frame.ConstructResult(result, result_value, result_name, result_type, llvm_module))
+                {
+                    if (log)
+                        log->Printf("Couldn't construct the expression's result");
+                    err.SetErrorToGenericError();
+                    err.SetErrorString(bad_result_error);
+                    return false;
+                }
+                
+                return true;
             }
         case Instruction::Store:
             {
diff --git a/source/Expression/RecordingMemoryManager.cpp b/source/Expression/RecordingMemoryManager.cpp
index de14fe4..3d0cda3 100644
--- a/source/Expression/RecordingMemoryManager.cpp
+++ b/source/Expression/RecordingMemoryManager.cpp
@@ -43,8 +43,7 @@
 RecordingMemoryManager::startFunctionBody(const llvm::Function *F,
                      uintptr_t &ActualSize)
 {
-    uint8_t *return_value = m_default_mm_ap->startFunctionBody(F, ActualSize);
-    return return_value;
+    return m_default_mm_ap->startFunctionBody(F, ActualSize);
 }
 
 uint8_t *
@@ -52,7 +51,21 @@
                 unsigned Alignment)
 {
     uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment);
-    m_stubs.insert (std::pair<uint8_t *,unsigned>(return_value, StubSize));
+    
+    Allocation allocation;
+    allocation.m_size = StubSize;
+    allocation.m_alignment = Alignment;
+    allocation.m_local_start = (uintptr_t)return_value;
+
+    if (m_log)
+    {
+        m_log->Printf("RecordingMemoryManager::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p",
+                      F, StubSize, Alignment, return_value);
+        allocation.dump(m_log);
+    }
+    
+    m_allocations.push_back(allocation);
+    
     return return_value;
 }
 
@@ -61,31 +74,96 @@
                uint8_t *FunctionEnd)
 {
     m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd);
-    if (m_log)
-        m_log->Printf("Adding [%p-%p] to m_functions",
-                      FunctionStart, FunctionEnd);
-    m_functions.insert(std::pair<uint8_t *, uint8_t *>(FunctionStart, FunctionEnd));
 }
 
 uint8_t *
 RecordingMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
 {
     uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment);
+    
+    Allocation allocation;
+    allocation.m_size = Size;
+    allocation.m_alignment = Alignment;
+    allocation.m_local_start = (uintptr_t)return_value;
+    
     if (m_log)
-        m_log->Printf("RecordingMemoryManager::allocateSpace(Size=0x%llx, Alignment=%u) = %p",
+    {
+        m_log->Printf("RecordingMemoryManager::allocateSpace(Size=%llu, Alignment=%u) = %p",
                       (uint64_t)Size, Alignment, return_value);
-    m_spaceBlocks.insert (std::pair<uint8_t *, intptr_t>(return_value, Size));
+        allocation.dump(m_log);
+    }
+    
+    m_allocations.push_back(allocation);
+    
     return return_value;
 }
 
 uint8_t *
+RecordingMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID)
+{
+    uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID);
+    
+    Allocation allocation;
+    allocation.m_size = Size;
+    allocation.m_alignment = Alignment;
+    allocation.m_local_start = (uintptr_t)return_value;
+    allocation.m_section_id = SectionID;
+    allocation.m_executable = true;
+    
+    if (m_log)
+    {
+        m_log->Printf("RecordingMemoryManager::allocateCodeSection(Size=0x%llx, Alignment=%u, SectionID=%u) = %p",
+                      (uint64_t)Size, Alignment, SectionID, return_value);
+        allocation.dump(m_log);
+    }
+    
+    m_allocations.push_back(allocation);
+    
+    return return_value;
+}
+
+uint8_t *
+RecordingMemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID)
+{
+    uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID);
+    
+    Allocation allocation;
+    allocation.m_size = Size;
+    allocation.m_alignment = Alignment;
+    allocation.m_local_start = (uintptr_t)return_value;
+    allocation.m_section_id = SectionID;
+    
+    if (m_log)
+    {
+        m_log->Printf("RecordingMemoryManager::allocateDataSection(Size=0x%llx, Alignment=%u, SectionID=%u) = %p",
+                      (uint64_t)Size, Alignment, SectionID, return_value);
+        allocation.dump(m_log);
+    }
+    
+    m_allocations.push_back(allocation);
+    
+    return return_value; 
+}
+
+uint8_t *
 RecordingMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
 {
     uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment);
+    
+    Allocation allocation;
+    allocation.m_size = Size;
+    allocation.m_alignment = Alignment;
+    allocation.m_local_start = (uintptr_t)return_value;
+    
     if (m_log)
+    {
         m_log->Printf("RecordingMemoryManager::allocateGlobal(Size=0x%llx, Alignment=%u) = %p",
                       (uint64_t)Size, Alignment, return_value);
-    m_globals.insert (std::pair<uint8_t *, uintptr_t>(return_value, Size));
+        allocation.dump(m_log);
+    }
+    
+    m_allocations.push_back(allocation);
+
     return return_value;
 }
 
@@ -99,8 +177,7 @@
 RecordingMemoryManager::startExceptionTable(const llvm::Function* F,
                        uintptr_t &ActualSize)
 {
-    uint8_t *return_value = m_default_mm_ap->startExceptionTable(F, ActualSize);
-    return return_value;
+    return m_default_mm_ap->startExceptionTable(F, ActualSize);
 }
 
 void
@@ -108,7 +185,6 @@
                  uint8_t *TableEnd, uint8_t* FrameRegister)
 {
     m_default_mm_ap->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
-    m_exception_tables.insert (std::pair<uint8_t *, uint8_t *>(TableStart, TableEnd));
 }
 
 void
@@ -120,43 +196,125 @@
 lldb::addr_t
 RecordingMemoryManager::GetRemoteAddressForLocal (lldb::addr_t local_address)
 {
-    std::vector<LocalToRemoteAddressRange>::iterator pos, end = m_address_map.end();
-    for (pos = m_address_map.begin(); pos < end; pos++)
+    for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
+         ai != ae;
+         ++ai)
     {
-        lldb::addr_t lstart = (*pos).m_local_start;
-        if (local_address >= lstart && local_address < lstart + (*pos).m_size)
-        {
-            return (*pos).m_remote_start + (local_address - lstart);
-        }
+        if (local_address >= ai->m_local_start &&
+            local_address < ai->m_local_start + ai->m_size)
+            return ai->m_remote_start + (local_address - ai->m_local_start);
     }
+
     return LLDB_INVALID_ADDRESS;
 }
 
-std::pair <lldb::addr_t, lldb::addr_t>
+RecordingMemoryManager::AddrRange
 RecordingMemoryManager::GetRemoteRangeForLocal (lldb::addr_t local_address)
 {
-    std::vector<LocalToRemoteAddressRange>::iterator pos, end = m_address_map.end();
-    
-    for (pos = m_address_map.begin(); pos < end; ++pos)
+    for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
+         ai != ae;
+         ++ai)
     {
-        lldb::addr_t lstart = pos->m_local_start;
-        lldb::addr_t lend = lstart + pos->m_size;
+        if (local_address >= ai->m_local_start &&
+            local_address < ai->m_local_start + ai->m_size)
+            return AddrRange(ai->m_remote_start, ai->m_size);
+    }
+    
+    return AddrRange (0, 0);
+}
+
+bool
+RecordingMemoryManager::CommitAllocations (Process &process)
+{
+    bool ret = true;
+    
+    for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
+         ai != ae;
+         ++ai)
+    {
+        if (ai->m_allocated)
+            continue;
         
-        if (local_address >= lstart && local_address < lend)
+        lldb_private::Error err;
+        
+        ai->m_remote_allocation = process.AllocateMemory(
+            ai->m_size + ai->m_alignment - 1, 
+            ai->m_executable ? (lldb::ePermissionsReadable | lldb::ePermissionsExecutable) 
+                             : (lldb::ePermissionsReadable | lldb::ePermissionsWritable), 
+            err);
+        
+        uint64_t mask = ai->m_alignment - 1;
+        
+        ai->m_remote_start = (ai->m_remote_allocation + mask) & (~mask);
+        
+        if (!err.Success())
         {
-            return std::pair <lldb::addr_t, lldb::addr_t> (pos->m_remote_start, pos->m_remote_start + pos->m_size);
+            ret = false;
+            break;
+        }
+        
+        ai->m_allocated = true;
+        
+        if (m_log)
+        {
+            m_log->Printf("RecordingMemoryManager::CommitAllocations() committed an allocation");
+            ai->dump(m_log);
         }
     }
     
-    return std::pair <lldb::addr_t, lldb::addr_t> (0, 0);
-}
-
-void
-RecordingMemoryManager::AddToLocalToRemoteMap (lldb::addr_t lstart, size_t size, lldb::addr_t rstart)
-{
-    if (m_log)
-        m_log->Printf("Adding local [0x%llx-0x%llx], remote [0x%llx-0x%llx] to local->remote map", lstart, lstart + size, rstart, rstart + size);
+    if (!ret)
+    {
+        for (AllocationList::iterator ai = m_allocations.end(), ae = m_allocations.end();
+             ai != ae;
+             ++ai)
+        {
+            if (ai->m_allocated)
+                process.DeallocateMemory(ai->m_remote_start);
+        }
+    }
     
-    m_address_map.push_back (LocalToRemoteAddressRange(lstart, size, rstart));
+    return ret;
 }
 
+bool
+RecordingMemoryManager::WriteData (Process &process)
+{    
+    for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
+         ai != ae;
+         ++ai)
+    {
+        if (!ai->m_allocated)
+            return false;
+        
+        lldb_private::Error err;
+        
+        if (process.WriteMemory(ai->m_remote_start, 
+                                (void*)ai->m_local_start, 
+                                ai->m_size, 
+                                err) != ai->m_size ||
+            !err.Success())
+            return false;
+        
+        if (m_log)
+        {
+            m_log->Printf("RecordingMemoryManager::CommitAllocations() wrote an allocation");
+            ai->dump(m_log);
+        }
+    }
+    
+    return true;
+}
+
+void 
+RecordingMemoryManager::Allocation::dump (lldb::LogSP log)
+{
+    if (!log)
+        return;
+    
+    log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)",
+                (unsigned long long)m_local_start,
+                (unsigned long long)m_size,
+                (unsigned long long)m_remote_start,
+                (unsigned)m_alignment,
+                (unsigned)m_section_id);
+}