blob: 35dcabfdd591a01a5743df7913dc174135d36426 [file] [log] [blame]
//===-- Variable.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/Symbol/Variable.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
// Variable constructor
//----------------------------------------------------------------------
Variable::Variable(lldb::user_id_t uid,
const ConstString& name,
Type *type,
ValueType scope,
SymbolContextScope *context,
Declaration* decl_ptr,
const DWARFExpression& location,
bool external,
bool artificial) :
UserID(uid),
m_name(name),
m_type(type),
m_scope(scope),
m_context(context),
m_declaration(decl_ptr),
m_location(location),
m_external(external),
m_artificial(artificial)
{
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
Variable::~Variable()
{
}
void
Variable::Dump(Stream *s, bool show_context) const
{
s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
s->Indent();
*s << "Variable" << (const UserID&)*this;
if (m_name)
*s << ", name = \"" << m_name << "\"";
if (m_type != NULL)
{
*s << ", type = " << (void*)m_type << " (";
m_type->DumpTypeName(s);
s->PutChar(')');
}
if (m_scope != eValueTypeInvalid)
{
s->PutCString(", scope = ");
switch (m_scope)
{
case eValueTypeVariableGlobal: s->PutCString(m_external ? "global" : "static"); break;
case eValueTypeVariableArgument: s->PutCString("parameter"); break;
case eValueTypeVariableLocal: s->PutCString("local"); break;
default: *s << "??? (" << m_scope << ')';
}
}
if (show_context && m_context != NULL)
{
s->PutCString(", context = ( ");
m_context->DumpSymbolContext(s);
s->PutCString(" )");
}
m_declaration.Dump(s);
if (m_location.IsValid())
{
s->PutCString(", location = ");
m_location.GetDescription(s, lldb::eDescriptionLevelBrief);
}
if (m_external)
s->PutCString(", external");
if (m_artificial)
s->PutCString(", artificial");
s->EOL();
}
size_t
Variable::MemorySize() const
{
return sizeof(Variable);
}
void
Variable::CalculateSymbolContext (SymbolContext *sc)
{
if (m_context)
m_context->CalculateSymbolContext(sc);
else
sc->Clear();
}
bool
Variable::IsInScope (StackFrame *frame)
{
switch (m_scope)
{
case eValueTypeVariableGlobal:
// Globals and statics are always in scope.
return true;
case eValueTypeVariableArgument:
case eValueTypeVariableLocal:
// Check if the location has a location list that describes the value
// of the variable with address ranges and different locations for each
// address range?
if (m_location.IsLocationList())
{
// It is a location list. We just need to tell if the location
// list contains the current address when converted to a load
// address
return m_location.LocationListContainsLoadAddress (&frame->GetThread().GetProcess(), frame->GetPC());
}
else
{
// We don't have a location list, we just need to see if the block
// that this variable was defined in is currently
Block *frame_block = frame->GetSymbolContext(eSymbolContextBlock).block;
if (frame_block)
{
SymbolContext variable_sc;
CalculateSymbolContext (&variable_sc);
if (variable_sc.function && variable_sc.block)
return variable_sc.block->ContainsBlockWithID (frame_block->GetID());
}
}
break;
default:
break;
}
return false;
}