Bugfixes to the expression parser.  Fixes include:

 - If you put a semicolon at the end of an expression,
   this no longer causes the expression parser to
   error out.  This was a two-part fix: first,
   ClangExpressionDeclMap::Materialize now handles
   an empty struct (such as when there is no return
   value); second, ASTResultSynthesizer walks backward
   from the end of the ASTs until it reaches something
   that's not a NullStmt.

 - ClangExpressionVariable now properly byte-swaps when
   printing itself.

 - ClangUtilityFunction now cleans up after itself when
   it's done compiling itself.

 - Utility functions can now use external functions just
   like user expressions.

 - If you end your expression with a statement that does
   not return a value, the expression now runs correctly
   anyway.

Also, added the beginnings of an Objective-C object
validator function, which is neither installed nor used
as yet.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@113789 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/ASTResultSynthesizer.cpp b/source/Expression/ASTResultSynthesizer.cpp
index b3790f2..8838fdd 100644
--- a/source/Expression/ASTResultSynthesizer.cpp
+++ b/source/Expression/ASTResultSynthesizer.cpp
@@ -113,6 +113,18 @@
     if (!function_decl)
         return false;
     
+    if (log)
+    {
+        std::string s;
+        raw_string_ostream os(s);
+        
+        function_decl->print(os);
+        
+        os.flush();
+        
+        log->Printf("Function AST before transforming:\n%s", s.c_str());
+    }
+    
     Stmt *function_body = function_decl->getBody();
     CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);
     
@@ -125,6 +137,15 @@
     Stmt **last_stmt_ptr = compound_stmt->body_end() - 1;
     Stmt *last_stmt = *last_stmt_ptr;
     
+    while (dyn_cast<NullStmt>(last_stmt))
+    {
+        if (last_stmt_ptr != compound_stmt->body_begin())
+        {
+            last_stmt_ptr--;
+            last_stmt = *last_stmt_ptr;
+        }
+    }
+    
     Expr *last_expr = dyn_cast<Expr>(last_stmt);
     
     if (!last_expr)
diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp
index ef0be1e..37d13a9 100644
--- a/source/Expression/ClangExpressionDeclMap.cpp
+++ b/source/Expression/ClangExpressionDeclMap.cpp
@@ -401,6 +401,16 @@
         return LLDB_INVALID_ADDRESS;
     }
     
+    if (!m_struct_size)
+    {
+        if (log)
+            log->PutCString("Not bothering to allocate a struct because no arguments are needed");
+        
+        m_allocated_area = NULL;
+        
+        return true;
+    }
+    
     const SymbolContext &sym_ctx(exe_ctx->frame->GetSymbolContext(lldb::eSymbolContextEverything));
     
     if (!dematerialize)
diff --git a/source/Expression/ClangExpressionParser.cpp b/source/Expression/ClangExpressionParser.cpp
index 1bc8866..f8b71ed 100644
--- a/source/Expression/ClangExpressionParser.cpp
+++ b/source/Expression/ClangExpressionParser.cpp
@@ -403,7 +403,10 @@
         
         std::auto_ptr<llvm::TargetMachine> target_machine(target->createTargetMachine(m_target_triple, ""));
         
-        IRForTarget ir_for_target(decl_map, target_machine->getTargetData(), m_expr.FunctionName());
+        IRForTarget ir_for_target(decl_map, 
+                                  target_machine->getTargetData(),
+                                  m_expr.NeedsVariableResolution(),
+                                  m_expr.FunctionName());
         
         if (!ir_for_target.runOnModule(*module))
         {
@@ -412,14 +415,17 @@
             return err;
         }
         
-        IRDynamicChecks ir_dynamic_checks(*exe_ctx.process->GetDynamicCheckers(), m_expr.FunctionName());
-        
-        if (!ir_dynamic_checks.runOnModule(*module))
+        if (m_expr.NeedsValidation())
         {
-            err.SetErrorToGenericError();
-            err.SetErrorString("Couldn't add dynamic checks to the expression");
-            return err;
-        }        
+            IRDynamicChecks ir_dynamic_checks(*exe_ctx.process->GetDynamicCheckers(), m_expr.FunctionName());
+        
+            if (!ir_dynamic_checks.runOnModule(*module))
+            {
+                err.SetErrorToGenericError();
+                err.SetErrorString("Couldn't add dynamic checks to the expression");
+                return err;
+            }
+        }
     }
     
     m_jit_mm = new RecordingMemoryManager();
diff --git a/source/Expression/ClangExpressionVariable.cpp b/source/Expression/ClangExpressionVariable.cpp
index d576578..3931cfb 100644
--- a/source/Expression/ClangExpressionVariable.cpp
+++ b/source/Expression/ClangExpressionVariable.cpp
@@ -18,6 +18,8 @@
 #include "lldb/Core/DataExtractor.h"
 #include "lldb/Core/Stream.h"
 #include "lldb/Core/Value.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
 
 using namespace lldb_private;
 using namespace clang;
@@ -79,6 +81,12 @@
     DataExtractor data;
     Error expr_error = val.GetValueAsData (&exe_ctx, ast_context, data, 0);
     
+    
+    // Set byte order and pointer size to TARGET byte order and pointer size!
+    
+    data.SetByteOrder(exe_ctx.process->GetByteOrder());
+    data.SetAddressByteSize(exe_ctx.process->GetAddressByteSize());
+    
     if (!expr_error.Success ())
     {
         err.SetErrorToGenericError ();
diff --git a/source/Expression/ClangUserExpression.cpp b/source/Expression/ClangUserExpression.cpp
index d8841d3..4e49c48 100644
--- a/source/Expression/ClangUserExpression.cpp
+++ b/source/Expression/ClangUserExpression.cpp
@@ -196,13 +196,16 @@
             
             Error dump_error;
             
-            if (!m_expr_decl_map->DumpMaterializedStruct(&exe_ctx, args, dump_error))
+            if (struct_address)
             {
-                log->Printf("Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
-            }
-            else
-            {
-                log->Printf("Structure contents:\n%s", args.GetData());
+                if (!m_expr_decl_map->DumpMaterializedStruct(&exe_ctx, args, dump_error))
+                {
+                    log->Printf("Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
+                }
+                else
+                {
+                    log->Printf("Structure contents:\n%s", args.GetData());
+                }
             }
         }
         
diff --git a/source/Expression/ClangUtilityFunction.cpp b/source/Expression/ClangUtilityFunction.cpp
index 17ba7db..310cac9 100644
--- a/source/Expression/ClangUtilityFunction.cpp
+++ b/source/Expression/ClangUtilityFunction.cpp
@@ -17,6 +17,7 @@
 
 #include "lldb/Core/ConstString.h"
 #include "lldb/Core/Stream.h"
+#include "lldb/Expression/ClangExpressionDeclMap.h"
 #include "lldb/Expression/ClangExpressionParser.h"
 #include "lldb/Expression/ClangUtilityFunction.h"
 #include "lldb/Host/Host.h"
@@ -93,6 +94,8 @@
     //////////////////////////
     // Parse the expression
     //
+    
+    m_expr_decl_map.reset(new ClangExpressionDeclMap(&exe_ctx));
         
     ClangExpressionParser parser(target_triple.GetCString(), *this);
     
@@ -101,6 +104,9 @@
     if (num_errors)
     {
         error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
+        
+        m_expr_decl_map.reset();
+        
         return false;
     }
     
@@ -110,6 +116,8 @@
         
     Error jit_error = parser.MakeJIT (m_jit_begin, m_jit_end, exe_ctx);
     
+    m_expr_decl_map.reset();
+    
     if (jit_error.Success())
     {
         return true;
diff --git a/source/Expression/IRDynamicChecks.cpp b/source/Expression/IRDynamicChecks.cpp
index 0f98123..b5a706d 100644
--- a/source/Expression/IRDynamicChecks.cpp
+++ b/source/Expression/IRDynamicChecks.cpp
@@ -8,9 +8,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Expression/IRDynamicChecks.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
 
+#include "lldb/Core/ConstString.h"
 #include "lldb/Core/Log.h"
+#include "lldb/Expression/ClangUtilityFunction.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/StackFrame.h"
 
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Function.h"
@@ -23,6 +26,9 @@
 
 static char ID;
 
+static const char valid_pointer_check_name[] = 
+"___clang_valid_pointer_check";
+
 static const char valid_pointer_check_text[] = 
     "extern \"C\" void "
     "___clang_valid_pointer_check (unsigned char *ptr)"
@@ -30,13 +36,57 @@
         "unsigned char val = *ptr;"
     "}";
 
-static const char valid_pointer_check_name[] = 
-    "___clang_valid_pointer_check";
+static const char objc_object_check_name[] =
+    "___clang_objc_object_check";
+
+static bool FunctionExists(const SymbolContext &sym_ctx, const char *name)
+{
+    ConstString name_cs(name);
+
+    SymbolContextList sym_ctxs;
+    
+    sym_ctx.FindFunctionsByName(name_cs, false, sym_ctxs);
+
+    return (sym_ctxs.GetSize() != 0);
+}
+
+static const char *objc_object_check_text(ExecutionContext &exe_ctx)
+{
+    std::string ret;
+    
+    if (!exe_ctx.frame)
+        return "extern \"C\" void ___clang_objc_object_check (unsigned char *obj) { }";
+    
+    const SymbolContext &sym_ctx(exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextEverything));
+
+    if (FunctionExists(sym_ctx, "gdb_object_getClass"))
+    {
+        return  "extern \"C\" void "
+                "___clang_objc_object_check(uint8_t *obj)"
+                "{"
+                    ""
+                "}";
+    }
+    else if (FunctionExists(sym_ctx, "gdb_class_getClass"))
+    {
+        return  "extern \"C\" void "
+                "___clang_objc_object_check(uint8_t *obj)"
+                "{"
+                    ""
+                "}";
+    }
+    else
+    {
+        return  "extern \"C\" void "
+                "___clang_objc_object_check(uint8_t *obj)"
+                "{"
+                    ""
+                "}";
+    }
+}
 
 DynamicCheckerFunctions::DynamicCheckerFunctions ()
 {
-    m_valid_pointer_check.reset(new ClangUtilityFunction(valid_pointer_check_text,
-                                                         valid_pointer_check_name));
 }
 
 DynamicCheckerFunctions::~DynamicCheckerFunctions ()
@@ -47,6 +97,9 @@
 DynamicCheckerFunctions::Install(Stream &error_stream,
                                  ExecutionContext &exe_ctx)
 {
+    m_valid_pointer_check.reset(new ClangUtilityFunction(valid_pointer_check_text,
+                                                         valid_pointer_check_name));
+    
     if (!m_valid_pointer_check->Install(error_stream, exe_ctx))
         return false;
         
@@ -104,7 +157,8 @@
     Instrumenter (llvm::Module &module,
                   DynamicCheckerFunctions &checker_functions) :
         m_module(module),
-        m_checker_functions(checker_functions)
+        m_checker_functions(checker_functions),
+        m_i8ptr_ty(NULL)
     {
     }
     
@@ -222,12 +276,42 @@
         return true;
     }
     
+    //------------------------------------------------------------------
+    /// Build a function pointer for a function with signature 
+    /// void (*)(uint8_t*) with a given address
+    ///
+    /// @param[in] start_address
+    ///     The address of the function.
+    ///
+    /// @return
+    ///     The function pointer, for use in a CallInst.
+    //------------------------------------------------------------------
+    llvm::Value *BuildPointerValidatorFunc(lldb::addr_t start_address)
+    {
+        std::vector<const llvm::Type*> params;
+        
+        const IntegerType *intptr_ty = llvm::Type::getIntNTy(m_module.getContext(),
+                                                             (m_module.getPointerSize() == llvm::Module::Pointer64) ? 64 : 32);
+        
+        if (!m_i8ptr_ty)
+            m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext());
+        
+        params.push_back(m_i8ptr_ty);
+        
+        FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true);
+        PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
+        Constant *fun_addr_int = ConstantInt::get(intptr_ty, start_address, false);
+        return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
+    }
+    
     typedef std::vector <llvm::Instruction *>   InstVector;
     typedef InstVector::iterator                InstIterator;
     
     InstVector                  m_to_instrument;        ///< List of instructions the inspector found
     llvm::Module               &m_module;               ///< The module which is being instrumented
     DynamicCheckerFunctions    &m_checker_functions;    ///< The dynamic checker functions for the process
+
+    const PointerType          *m_i8ptr_ty;
 };
 
 class ValidPointerChecker : public Instrumenter
@@ -249,21 +333,7 @@
                         PrintValue(inst).c_str());
         
         if (!m_valid_pointer_check_func)
-        {
-            std::vector<const llvm::Type*> params;
-            
-            const IntegerType *intptr_ty = llvm::Type::getIntNTy(m_module.getContext(),
-                                                                 (m_module.getPointerSize() == llvm::Module::Pointer64) ? 64 : 32);
-            
-            m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext());
-            
-            params.push_back(m_i8ptr_ty);
-            
-            FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true);
-            PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
-            Constant *fun_addr_int = ConstantInt::get(intptr_ty, m_checker_functions.m_valid_pointer_check->StartAddress(), false);
-            m_valid_pointer_check_func = ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
-        }
+            m_valid_pointer_check_func = BuildPointerValidatorFunc(m_checker_functions.m_valid_pointer_check->StartAddress());
         
         llvm::Value *dereferenced_ptr;
         
@@ -305,6 +375,104 @@
     }
     
     llvm::Value         *m_valid_pointer_check_func;
+};
+
+class ObjcObjectChecker : public Instrumenter
+{
+public:
+    ObjcObjectChecker(llvm::Module &module,
+                        DynamicCheckerFunctions &checker_functions) :
+        Instrumenter(module, checker_functions),
+        m_objc_object_check_func(NULL)
+    {
+    }
+private:
+    bool InstrumentInstruction(llvm::Instruction *inst)
+    {
+        CallInst *call_inst = dyn_cast<CallInst>(inst);
+        
+        if (!call_inst)
+            return false; // this really should be true, because otherwise InspectInstruction wouldn't have registered it
+        
+        if (!m_objc_object_check_func)
+            m_objc_object_check_func = BuildPointerValidatorFunc(m_checker_functions.m_objc_object_check->StartAddress());
+        
+        llvm::Value *target_object;
+        
+        // id objc_msgSend(id theReceiver, SEL theSelector, ...)
+        
+        target_object = call_inst->getArgOperand(0);
+        
+        // Insert an instruction to cast the receiver id to int8_t*
+        
+        BitCastInst *bit_cast = new BitCastInst(target_object,
+                                                m_i8ptr_ty,
+                                                "",
+                                                inst);
+        
+        // Insert an instruction to call the helper with the result
+        
+        SmallVector <llvm::Value*, 1> args;
+        args.push_back(bit_cast);
+        
+        CallInst::Create(m_objc_object_check_func, 
+                         args.begin(),
+                         args.end(),
+                         "",
+                         inst);
+        
+        return true;
+    }
+    
+    bool InspectInstruction(llvm::Instruction &i)
+    {
+        lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+
+        CallInst *call_inst = dyn_cast<CallInst>(&i);
+        
+        if (call_inst)
+        {
+            // This metadata is set by IRForTarget::MaybeHandleCall().
+            
+            MDNode *metadata = call_inst->getMetadata("lldb.call.realName");
+                        
+            if (!metadata)
+                return true;
+            
+            if (metadata->getNumOperands() != 1)
+            {
+                if (log)
+                    log->Printf("Function call metadata has %d operands for [%p] %s", metadata->getNumOperands(), call_inst, PrintValue(call_inst).c_str());
+                return false;
+            }
+            
+            ConstantArray *real_name = dyn_cast<ConstantArray>(metadata->getOperand(0));
+            
+            if (!real_name)
+            {
+                if (log)
+                    log->Printf("Function call metadata is not a ConstantArray for [%p] %s", call_inst, PrintValue(call_inst).c_str());
+                return false;
+            }
+            
+            if (!real_name->isString())
+            {
+                if (log)
+                    log->Printf("Function call metadata is not a string for [%p] %s", call_inst, PrintValue(call_inst).c_str());
+                return false;
+            }
+            
+            if (log)
+                log->Printf("Found call to %s: %s\n", real_name->getAsString().c_str(), PrintValue(call_inst).c_str());
+            
+            if (real_name->getAsString().find("objc_msgSend") != std::string::npos)
+                RegisterInstruction(i);
+        }
+        
+        return true;
+    }
+    
+    llvm::Value         *m_objc_object_check_func;
     const PointerType   *m_i8ptr_ty;
 };
 
@@ -343,6 +511,16 @@
     if (!vpc.Instrument())
         return false;
     
+    /*
+    ObjcObjectChecker ooc(M, m_checker_functions);
+    
+    if (!ooc.Inspect(*function))
+        return false;
+    
+    if (!ooc.Instrument())
+        return false;
+    */
+    
     if (log)
     {
         std::string s;
diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp
index e220b16..f368b8d 100644
--- a/source/Expression/IRForTarget.cpp
+++ b/source/Expression/IRForTarget.cpp
@@ -32,12 +32,14 @@
 
 IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,
                          const TargetData *target_data,
+                         bool resolve_vars,
                          const char *func_name) :
     ModulePass(&ID),
     m_decl_map(decl_map),
     m_target_data(target_data),
     m_sel_registerName(NULL),
-    m_func_name(func_name)
+    m_func_name(func_name),
+    m_resolve_vars(resolve_vars)
 {
 }
 
@@ -65,7 +67,10 @@
 {
     lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
     
-    // Find the result variable
+    if (!m_resolve_vars)
+        return true;
+    
+    // Find the result variable.  If it doesn't exist, we can give up right here.
             
     Value *result_value = M.getNamedValue("___clang_expr_result");
     
@@ -73,9 +78,10 @@
     {
         if (log)
             log->PutCString("Couldn't find result variable");
-        return false;
+                
+        return true;
     }
-    
+        
     if (log)
         log->Printf("Found result in the IR: %s", PrintValue(result_value, false).c_str());
     
@@ -429,6 +435,9 @@
 IRForTarget::rewritePersistentAllocs(llvm::Module &M,
                                      llvm::BasicBlock &BB)
 {
+    if (!m_resolve_vars)
+        return true;
+    
     lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
     
     BasicBlock::iterator ii;
@@ -649,6 +658,17 @@
     
     C->setCalledFunction(fun_addr_ptr);
     
+    ConstantArray *func_name = (ConstantArray*)ConstantArray::get(M.getContext(), fun->getName());
+    
+    Value *values[1];
+    values[0] = func_name;
+    MDNode *func_metadata = MDNode::get(M.getContext(), values, 1);
+    
+    C->setMetadata("lldb.call.realName", func_metadata);
+    
+    if (log)
+        log->Printf("Set metadata for %p [%d, %s]", C, func_name->isString(), func_name->getAsString().c_str());
+    
     return true;
 }
 
@@ -667,13 +687,16 @@
     {
         Instruction &inst = *ii;
         
-        if (LoadInst *load = dyn_cast<LoadInst>(&inst))
-            if (!MaybeHandleVariable(M, load->getPointerOperand(), false))
-                return false;
+        if (m_resolve_vars)
+        {
+            if (LoadInst *load = dyn_cast<LoadInst>(&inst))
+                if (!MaybeHandleVariable(M, load->getPointerOperand(), false))
+                    return false;
             
-        if (StoreInst *store = dyn_cast<StoreInst>(&inst))
-            if (!MaybeHandleVariable(M, store->getPointerOperand(), true))
-                return false;
+            if (StoreInst *store = dyn_cast<StoreInst>(&inst))
+                if (!MaybeHandleVariable(M, store->getPointerOperand(), true))
+                    return false;
+        }
         
         if (CallInst *call = dyn_cast<CallInst>(&inst))
             if (!MaybeHandleCall(M, call))
@@ -886,6 +909,9 @@
 bool 
 IRForTarget::replaceVariables(Module &M, Function &F)
 {
+    if (!m_resolve_vars)
+        return true;
+    
     lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
 
     m_decl_map->DoStructLayout();