Skip to content
IRInterpreter.cpp 54.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/DataExtractor.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Host/Endian.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.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;
}

static bool
CanIgnoreCall (const CallInst *call)
{
    const llvm::Function *called_function = call->getCalledFunction();
    
    if (!called_function)
        return false;
    
    if (called_function->isIntrinsic())
    {
        switch (called_function->getIntrinsicID())
        {
        default:
            break;
        case llvm::Intrinsic::dbg_declare:
        case llvm::Intrinsic::dbg_value:
            return true;
        }
    }
    
    return false;
}

class InterpreterStackFrame
    typedef std::map <const Value*, lldb::addr_t> ValueMap;
    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,
                           lldb::addr_t stack_frame_bottom,
                           lldb::addr_t stack_frame_top) :
        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_process_address = stack_frame_bottom;
        m_frame_size = stack_frame_top - stack_frame_bottom;
        m_stack_pointer = stack_frame_top;
    }
    
    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)
        {
            APInt value_apint;
            
            if (!ResolveConstantValue(value_apint, constant))
                return false;
            
            return AssignToMatchType(scalar, value_apint.getLimitedValue(), value->getType());
            lldb::addr_t process_address = ResolveValue(value, module);
            size_t value_size = m_target_data.getTypeStoreSize(value->getType());
        
            lldb_private::DataExtractor value_extractor;
            lldb_private::Error extract_error;
            m_memory_map.GetMemoryData(value_extractor, process_address, value_size, extract_error);
            
            if (!extract_error.Success())
Greg Clayton's avatar
Greg Clayton committed
            lldb::offset_t offset = 0;
            if (value_size == 1 || value_size == 2 || value_size == 4 || value_size == 8)
Loading
Loading full blame...