Skip to content
IRInterpreter.cpp 48.5 KiB
Newer Older
//===-- IRInterpreter.cpp ---------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/DataEncoder.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/ClangExpressionVariable.h"
#include "lldb/Expression/IRForTarget.h"
#include "lldb/Expression/IRInterpreter.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"

#include <map>

using namespace llvm;

static std::string 
PrintValue(const Value *value, bool truncate = false)
{
    std::string s;
    raw_string_ostream rso(s);
    value->print(rso);
    rso.flush();
    if (truncate)
        s.resize(s.length() - 1);
    
    size_t offset;
    while ((offset = s.find('\n')) != s.npos)
        s.erase(offset, 1);
    while (s[0] == ' ' || s[0] == '\t')
        s.erase(0, 1);
        
    return s;
}

static std::string
PrintType(const Type *type, bool truncate = false)
{
    std::string s;
    raw_string_ostream rso(s);
    type->print(rso);
    rso.flush();
    if (truncate)
        s.resize(s.length() - 1);
    return s;
}

class InterpreterStackFrame
    typedef std::map <const Value*, lldb::addr_t> ValueMap;
    struct PlacedValue
        lldb_private::Value     lldb_value;
        lldb::addr_t            process_address;
        size_t                  size;
        
        PlacedValue (lldb_private::Value &_lldb_value,
                     lldb::addr_t _process_address,
                     size_t _size) :
            lldb_value(_lldb_value),
            process_address(_process_address),
            size(_size)
    typedef std::vector <PlacedValue> PlacedValueVector;
    PlacedValueVector                       m_placed_values;
    DataLayout                             &m_target_data;
    lldb_private::IRMemoryMap              &m_memory_map;
    const BasicBlock                       *m_bb;
    BasicBlock::const_iterator              m_ii;
    BasicBlock::const_iterator              m_ie;
    
    lldb::addr_t                            m_frame_process_address;
    size_t                                  m_frame_size;
    lldb::addr_t                            m_stack_pointer;
    
    lldb::ByteOrder                         m_byte_order;
    size_t                                  m_addr_byte_size;
    
    InterpreterStackFrame (DataLayout &target_data,
                           lldb_private::IRMemoryMap &memory_map) :
        m_target_data (target_data),
        m_memory_map (memory_map)
    {
        m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle : lldb::eByteOrderBig);
        m_addr_byte_size = (target_data.getPointerSize(0));
        
        m_frame_size = 512 * 1024;
        
        lldb_private::Error alloc_error;
        
        m_frame_process_address = memory_map.Malloc(m_frame_size,
                                                    m_addr_byte_size,
                                                    lldb::ePermissionsReadable | lldb::ePermissionsWritable,
                                                    lldb_private::IRMemoryMap::eAllocationPolicyMirror,
                                                    alloc_error);
        
        if (alloc_error.Success())
        {
            m_stack_pointer = m_frame_process_address + m_frame_size;
        }
        else
        {
            m_frame_process_address = LLDB_INVALID_ADDRESS;
            m_stack_pointer = LLDB_INVALID_ADDRESS;
        }    
    }
    
    ~InterpreterStackFrame ()
    {
        if (m_frame_process_address != LLDB_INVALID_ADDRESS)
        {
            lldb_private::Error free_error;
            m_memory_map.Free(m_frame_process_address, free_error);
            m_frame_process_address = LLDB_INVALID_ADDRESS;
        }
    }
    
    void Jump (const BasicBlock *bb)
    {
        m_bb = bb;
        m_ii = m_bb->begin();
        m_ie = m_bb->end();
    }
    
    std::string SummarizeValue (const Value *value)
    {
        lldb_private::StreamString ss;

        ss.Printf("%s", PrintValue(value).c_str());
        
        ValueMap::iterator i = m_values.find(value);

        if (i != m_values.end())
        {
            lldb::addr_t addr = i->second;
            ss.Printf(" 0x%llx", (unsigned long long)addr);
        }
        
        return ss.GetString();
    }
    
    bool AssignToMatchType (lldb_private::Scalar &scalar, uint64_t u64value, Type *type)
    {
        size_t type_size = m_target_data.getTypeStoreSize(type);

        switch (type_size)
        {
        case 1:
            scalar = (uint8_t)u64value;
            break;
        case 2:
            scalar = (uint16_t)u64value;
            break;
        case 4:
            scalar = (uint32_t)u64value;
            break;
        case 8:
            scalar = (uint64_t)u64value;
            break;
        default:
            return false;
        }
        
        return true;
    }
    
    bool EvaluateValue (lldb_private::Scalar &scalar, const Value *value, Module &module)
    {
        const Constant *constant = dyn_cast<Constant>(value);
        
        if (constant)
        {
            if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant))
            {                
                return AssignToMatchType(scalar, constant_int->getLimitedValue(), value->getType());
            }
        }
        else
        {
            lldb::addr_t process_address = ResolveValue(value, module);
Loading
Loading full blame...