mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 05:32:28 +08:00
enabled LLVM make style building and made this compile LLDB on Mac OS X. We can now iterate on this to make the build work on both linux and macosx. llvm-svn: 108009
1023 lines
34 KiB
C++
1023 lines
34 KiB
C++
//===-- ClangStmtVisitor.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/Expression/ClangStmtVisitor.h"
|
|
|
|
// C Includes
|
|
// C++ Includes
|
|
// Other libraries and framework includes
|
|
#include "clang/AST/RecordLayout.h"
|
|
|
|
#include "lldb/Core/dwarf.h"
|
|
#include "lldb/Core/Scalar.h"
|
|
#include "lldb/Core/StreamString.h"
|
|
#include "lldb/Expression/ClangExpressionDeclMap.h"
|
|
#include "lldb/Expression/ClangExpressionVariable.h"
|
|
|
|
//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
|
|
#ifdef ENABLE_DEBUG_PRINTF
|
|
#include <stdio.h>
|
|
#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
|
|
#else
|
|
#define DEBUG_PRINTF(fmt, ...)
|
|
#endif
|
|
|
|
// Project includes
|
|
|
|
static lldb_private::Scalar::Type
|
|
GetScalarTypeForClangType (clang::ASTContext &ast_context, clang::QualType clang_type, uint32_t &count)
|
|
{
|
|
count = 1;
|
|
|
|
switch (clang_type->getTypeClass())
|
|
{
|
|
default:
|
|
break;
|
|
|
|
case clang::Type::FunctionNoProto:
|
|
case clang::Type::FunctionProto:
|
|
break;
|
|
|
|
case clang::Type::IncompleteArray:
|
|
case clang::Type::VariableArray:
|
|
break;
|
|
|
|
case clang::Type::ConstantArray:
|
|
break;
|
|
|
|
case clang::Type::ExtVector:
|
|
case clang::Type::Vector:
|
|
// TODO: Set this to more than one???
|
|
break;
|
|
|
|
case clang::Type::Builtin:
|
|
switch (cast<clang::BuiltinType>(clang_type)->getKind())
|
|
{
|
|
default: assert(0 && "Unknown builtin type!");
|
|
case clang::BuiltinType::Void:
|
|
break;
|
|
|
|
case clang::BuiltinType::Bool:
|
|
case clang::BuiltinType::Char_S:
|
|
case clang::BuiltinType::SChar:
|
|
case clang::BuiltinType::WChar:
|
|
case clang::BuiltinType::Char16:
|
|
case clang::BuiltinType::Char32:
|
|
case clang::BuiltinType::Short:
|
|
case clang::BuiltinType::Int:
|
|
case clang::BuiltinType::Long:
|
|
case clang::BuiltinType::LongLong:
|
|
case clang::BuiltinType::Int128:
|
|
return lldb_private::Scalar::GetValueTypeForSignedIntegerWithByteSize ((ast_context.getTypeSize(clang_type)/CHAR_BIT)/count);
|
|
|
|
case clang::BuiltinType::Char_U:
|
|
case clang::BuiltinType::UChar:
|
|
case clang::BuiltinType::UShort:
|
|
case clang::BuiltinType::UInt:
|
|
case clang::BuiltinType::ULong:
|
|
case clang::BuiltinType::ULongLong:
|
|
case clang::BuiltinType::UInt128:
|
|
case clang::BuiltinType::NullPtr:
|
|
return lldb_private::Scalar::GetValueTypeForUnsignedIntegerWithByteSize ((ast_context.getTypeSize(clang_type)/CHAR_BIT)/count);
|
|
|
|
case clang::BuiltinType::Float:
|
|
case clang::BuiltinType::Double:
|
|
case clang::BuiltinType::LongDouble:
|
|
return lldb_private::Scalar::GetValueTypeForFloatWithByteSize ((ast_context.getTypeSize(clang_type)/CHAR_BIT)/count);
|
|
}
|
|
break;
|
|
// All pointer types are represented as unsigned integer encodings.
|
|
// We may nee to add a eEncodingPointer if we ever need to know the
|
|
// difference
|
|
case clang::Type::ObjCObjectPointer:
|
|
case clang::Type::BlockPointer:
|
|
case clang::Type::Pointer:
|
|
case clang::Type::LValueReference:
|
|
case clang::Type::RValueReference:
|
|
case clang::Type::MemberPointer:
|
|
return lldb_private::Scalar::GetValueTypeForUnsignedIntegerWithByteSize ((ast_context.getTypeSize(clang_type)/CHAR_BIT)/count);
|
|
|
|
// Complex numbers are made up of floats
|
|
case clang::Type::Complex:
|
|
count = 2;
|
|
return lldb_private::Scalar::GetValueTypeForFloatWithByteSize ((ast_context.getTypeSize(clang_type)/CHAR_BIT) / count);
|
|
|
|
case clang::Type::ObjCInterface: break;
|
|
case clang::Type::Record: break;
|
|
case clang::Type::Enum:
|
|
return lldb_private::Scalar::GetValueTypeForSignedIntegerWithByteSize ((ast_context.getTypeSize(clang_type)/CHAR_BIT)/count);
|
|
|
|
case clang::Type::Typedef:
|
|
return GetScalarTypeForClangType(ast_context, cast<clang::TypedefType>(clang_type)->LookThroughTypedefs(), count);
|
|
break;
|
|
|
|
case clang::Type::TypeOfExpr:
|
|
case clang::Type::TypeOf:
|
|
case clang::Type::Decltype:
|
|
//case clang::Type::QualifiedName:
|
|
case clang::Type::TemplateSpecialization: break;
|
|
}
|
|
count = 0;
|
|
return lldb_private::Scalar::e_void;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// ClangStmtVisitor constructor
|
|
//----------------------------------------------------------------------
|
|
lldb_private::ClangStmtVisitor::ClangStmtVisitor
|
|
(
|
|
clang::ASTContext &ast_context,
|
|
lldb_private::ClangExpressionVariableList &variable_list,
|
|
lldb_private::ClangExpressionDeclMap *decl_map,
|
|
lldb_private::StreamString &strm
|
|
) :
|
|
m_ast_context (ast_context),
|
|
m_decl_map (decl_map),
|
|
m_variable_list (variable_list),
|
|
m_stream (strm)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Destructor
|
|
//----------------------------------------------------------------------
|
|
lldb_private::ClangStmtVisitor::~ClangStmtVisitor()
|
|
{
|
|
}
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitStmt (clang::Stmt *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
|
|
clang::Stmt::child_iterator pos;
|
|
clang::Stmt::child_iterator begin = Node->child_begin();
|
|
clang::Stmt::child_iterator end = Node->child_end();
|
|
bool clear_before_next_stmt = false;
|
|
for (pos = begin; pos != end; ++pos)
|
|
{
|
|
#ifdef ENABLE_DEBUG_PRINTF
|
|
pos->dump();
|
|
#endif
|
|
clang::Stmt *child_stmt = *pos;
|
|
uint32_t pre_visit_stream_offset = m_stream.GetSize();
|
|
bool not_null_stmt = dyn_cast<clang::NullStmt>(child_stmt) == NULL;
|
|
if (clear_before_next_stmt && not_null_stmt)
|
|
m_stream.PutHex8(DW_OP_APPLE_clear);
|
|
Visit (child_stmt);
|
|
if (not_null_stmt)
|
|
clear_before_next_stmt = pre_visit_stream_offset != m_stream.GetSize();
|
|
}
|
|
}
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitDeclStmt (clang::DeclStmt *decl_stmt)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
clang::DeclGroupRef decl_group_ref = decl_stmt->getDeclGroup();
|
|
clang::DeclGroupRef::iterator pos, end = decl_group_ref.end();
|
|
for (pos = decl_group_ref.begin(); pos != end; ++pos)
|
|
{
|
|
clang::Decl *decl = *pos;
|
|
if (decl)
|
|
{
|
|
clang::Decl::Kind decl_kind = decl->getKind();
|
|
|
|
switch (decl_kind)
|
|
{
|
|
case clang::Decl::Namespace:
|
|
case clang::Decl::Enum:
|
|
case clang::Decl::Record:
|
|
case clang::Decl::CXXRecord:
|
|
case clang::Decl::ObjCMethod:
|
|
case clang::Decl::ObjCInterface:
|
|
case clang::Decl::ObjCCategory:
|
|
case clang::Decl::ObjCProtocol:
|
|
case clang::Decl::ObjCImplementation:
|
|
case clang::Decl::ObjCCategoryImpl:
|
|
case clang::Decl::LinkageSpec:
|
|
case clang::Decl::Block:
|
|
case clang::Decl::Function:
|
|
case clang::Decl::CXXMethod:
|
|
case clang::Decl::CXXConstructor:
|
|
case clang::Decl::CXXDestructor:
|
|
case clang::Decl::CXXConversion:
|
|
case clang::Decl::Field:
|
|
case clang::Decl::Typedef:
|
|
case clang::Decl::EnumConstant:
|
|
case clang::Decl::ImplicitParam:
|
|
case clang::Decl::ParmVar:
|
|
case clang::Decl::ObjCProperty:
|
|
break;
|
|
|
|
case clang::Decl::Var:
|
|
{
|
|
const clang::VarDecl *var_decl = cast<clang::VarDecl>(decl)->getCanonicalDecl();
|
|
uint32_t expr_local_var_idx = UINT32_MAX;
|
|
if (m_variable_list.GetVariableForVarDecl (m_ast_context, var_decl, expr_local_var_idx, true))
|
|
{
|
|
const clang::Expr* var_decl_expr = var_decl->getAnyInitializer();
|
|
// If there is an inialization expression, then assign the
|
|
// variable.
|
|
if (var_decl_expr)
|
|
{
|
|
m_stream.PutHex8(DW_OP_APPLE_expr_local);
|
|
m_stream.PutULEB128(expr_local_var_idx);
|
|
Visit ((clang::Stmt *)var_decl_expr);
|
|
m_stream.PutHex8(DW_OP_APPLE_assign);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
assert(!"decl unhandled");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitLabelStmt (clang::LabelStmt *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitGotoStmt (clang::GotoStmt *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
// Exprs
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitExpr (clang::Expr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitDeclRefExpr (clang::DeclRefExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
clang::NamedDecl *decl = Node->getDecl();
|
|
clang::QualType clang_type = Node->getType();
|
|
|
|
#ifdef ENABLE_DEBUG_PRINTF
|
|
//decl->dump();
|
|
//clang_type.dump("lldb_private::ClangStmtVisitor::VisitDeclRefExpr() -> clang_type.dump() = ");
|
|
#endif
|
|
uint32_t expr_local_var_idx = UINT32_MAX;
|
|
if (m_variable_list.GetVariableForVarDecl (m_ast_context, cast<clang::VarDecl>(decl)->getCanonicalDecl(), expr_local_var_idx, false) &&
|
|
expr_local_var_idx != UINT32_MAX)
|
|
{
|
|
m_stream.PutHex8(DW_OP_APPLE_expr_local);
|
|
m_stream.PutULEB128(expr_local_var_idx);
|
|
}
|
|
else if (m_decl_map &&
|
|
m_decl_map->GetIndexForDecl(expr_local_var_idx, decl->getCanonicalDecl()))
|
|
{
|
|
m_stream.PutHex8(DW_OP_APPLE_extern);
|
|
m_stream.PutULEB128(expr_local_var_idx);
|
|
}
|
|
else
|
|
{
|
|
m_stream.PutHex8 (DW_OP_APPLE_error);
|
|
}
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitPredefinedExpr (clang::PredefinedExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitCharacterLiteral (clang::CharacterLiteral *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
clang::QualType clang_type = Node->getType();
|
|
uint64_t clang_type_size = m_ast_context.getTypeSize (clang_type);
|
|
if (clang_type_size <= 64)
|
|
{
|
|
// Encode the integer into our DWARF expression
|
|
if (clang_type->isSignedIntegerType())
|
|
EncodeSInt64(Node->getValue(), clang_type_size);
|
|
else
|
|
EncodeUInt64(Node->getValue(), clang_type_size);
|
|
}
|
|
else
|
|
{
|
|
// TODO: eventually support integer math over 64 bits, probably using
|
|
// APInt as the class.
|
|
m_stream.PutHex8(DW_OP_APPLE_error);
|
|
}
|
|
}
|
|
|
|
bool
|
|
lldb_private::ClangStmtVisitor::EncodeUInt64 (uint64_t uval, uint32_t bit_size)
|
|
{
|
|
// If "bit_size" is zero, then encode "uval" in the most efficient way
|
|
if (bit_size <= 8 || (bit_size == 0 && uval <= UINT8_MAX))
|
|
{
|
|
m_stream.PutHex8 (DW_OP_const1u);
|
|
m_stream.PutHex8 (uval);
|
|
}
|
|
else if (bit_size <= 16 || (bit_size == 0 && uval <= UINT16_MAX))
|
|
{
|
|
m_stream.PutHex8 (DW_OP_const2u);
|
|
m_stream.PutHex16 (uval);
|
|
}
|
|
else if (bit_size <= 32 || (bit_size == 0 && uval <= UINT32_MAX))
|
|
{
|
|
m_stream.PutHex8 (DW_OP_const4u);
|
|
m_stream.PutHex32 (uval);
|
|
}
|
|
else if (bit_size <= 64 || (bit_size == 0))
|
|
{
|
|
m_stream.PutHex8 (DW_OP_const8u);
|
|
m_stream.PutHex64 (uval);
|
|
}
|
|
else
|
|
{
|
|
m_stream.PutHex8 (DW_OP_APPLE_error);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
lldb_private::ClangStmtVisitor::EncodeSInt64 (int64_t sval, uint32_t bit_size)
|
|
{
|
|
if (bit_size <= 8 || (bit_size == 0 && INT8_MIN <= sval && sval <= INT8_MAX))
|
|
{
|
|
m_stream.PutHex8 (DW_OP_const1s);
|
|
m_stream.PutHex8 (sval);
|
|
}
|
|
else if (bit_size <= 16 || (bit_size == 0 && INT16_MIN <= sval && sval <= INT16_MAX))
|
|
{
|
|
m_stream.PutHex8 (DW_OP_const2s);
|
|
m_stream.PutHex16 (sval);
|
|
}
|
|
else if (bit_size <= 32 || (bit_size == 0 && INT32_MIN <= sval && sval <= INT32_MAX))
|
|
{
|
|
m_stream.PutHex8 (DW_OP_const4s);
|
|
m_stream.PutHex32 (sval);
|
|
}
|
|
else if (bit_size <= 64 || (bit_size == 0))
|
|
{
|
|
m_stream.PutHex8 (DW_OP_const8s);
|
|
m_stream.PutHex64 (sval);
|
|
}
|
|
else
|
|
{
|
|
m_stream.PutHex8 (DW_OP_APPLE_error);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitIntegerLiteral (clang::IntegerLiteral *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
const llvm::APInt &ap_int = Node->getValue();
|
|
if (ap_int.getBitWidth() <= 64)
|
|
{
|
|
clang::QualType clang_type = Node->getType();
|
|
uint64_t clang_type_size = m_ast_context.getTypeSize (clang_type);
|
|
// Encode the integer into our DWARF expression
|
|
if (clang_type->isSignedIntegerType())
|
|
EncodeSInt64(ap_int.getLimitedValue(), clang_type_size);
|
|
else
|
|
EncodeUInt64(ap_int.getLimitedValue(), clang_type_size);
|
|
}
|
|
else
|
|
{
|
|
// TODO: eventually support integer math over 64 bits, probably using
|
|
// APInt as the class.
|
|
m_stream.PutHex8(DW_OP_APPLE_error);
|
|
}
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitFloatingLiteral (clang::FloatingLiteral *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
const llvm::APFloat &ap_float = Node->getValue();
|
|
// Put the length of the float in bytes into a single byte
|
|
llvm::APInt ap_int(ap_float.bitcastToAPInt());
|
|
const unsigned byte_size = ap_int.getBitWidth() / CHAR_BIT;
|
|
if (byte_size == sizeof(float))
|
|
{
|
|
if (sizeof(float) == 4)
|
|
{
|
|
m_stream.PutHex8(DW_OP_APPLE_constf);
|
|
m_stream.PutHex8 (byte_size);
|
|
m_stream.PutHex32 (ap_int.getLimitedValue());
|
|
return;
|
|
}
|
|
else if (sizeof(float) == 8)
|
|
{
|
|
m_stream.PutHex8(DW_OP_APPLE_constf);
|
|
m_stream.PutHex8 (byte_size);
|
|
m_stream.PutHex64 (ap_int.getLimitedValue());
|
|
return;
|
|
}
|
|
}
|
|
else if (byte_size == sizeof(double))
|
|
{
|
|
if (sizeof(double) == 4)
|
|
{
|
|
m_stream.PutHex8(DW_OP_APPLE_constf);
|
|
m_stream.PutHex8 (byte_size);
|
|
m_stream.PutHex32 (ap_int.getLimitedValue());
|
|
return;
|
|
}
|
|
else if (sizeof(double) == 8)
|
|
{
|
|
m_stream.PutHex8(DW_OP_APPLE_constf);
|
|
m_stream.PutHex8 (byte_size);
|
|
m_stream.PutHex64 (ap_int.getLimitedValue());
|
|
return;
|
|
}
|
|
}
|
|
else if (byte_size == sizeof(long double))
|
|
{
|
|
if (sizeof(long double) == 8)
|
|
{
|
|
m_stream.PutHex8(DW_OP_APPLE_constf);
|
|
m_stream.PutHex8 (byte_size);
|
|
m_stream.PutHex64 (ap_int.getLimitedValue());
|
|
return;
|
|
}
|
|
}
|
|
// TODO: eventually support float constants of all sizes using
|
|
// APFloat as the class.
|
|
m_stream.PutHex8(DW_OP_APPLE_error);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitStringLiteral (clang::StringLiteral *Str)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
|
|
size_t byte_length = Str->getByteLength();
|
|
bool is_wide = Str->isWide();
|
|
|
|
size_t new_length = byte_length + (is_wide ? 1 : 2);
|
|
|
|
std::string null_terminated_string (Str->getStrData(), byte_length);
|
|
|
|
Value *val = new Value((uint8_t*)null_terminated_string.c_str(), new_length);
|
|
val->SetContext(Value::eContextTypeOpaqueClangQualType, Str->getType().getAsOpaquePtr());
|
|
|
|
uint32_t val_idx = m_variable_list.AppendValue(val);
|
|
|
|
m_stream.PutHex8(DW_OP_APPLE_expr_local);
|
|
m_stream.PutULEB128(val_idx);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitUnaryOperator (clang::UnaryOperator *unary_op)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
|
|
Visit(unary_op->getSubExpr());
|
|
|
|
switch (unary_op->getOpcode())
|
|
{
|
|
case clang::UnaryOperator::PostInc:
|
|
// Duplciate the top of stack value (which must be something that can
|
|
// be assignable/incremented) and push its current value
|
|
m_stream.PutHex8 (DW_OP_dup); // x, x
|
|
m_stream.PutHex8 (DW_OP_APPLE_value_of); // x, val(x)
|
|
m_stream.PutHex8 (DW_OP_swap); // val(x), x
|
|
m_stream.PutHex8 (DW_OP_dup); // val(x), x, x
|
|
m_stream.PutHex8 (DW_OP_lit1); // val(x), x, x, 1
|
|
m_stream.PutHex8 (DW_OP_plus); // val(x), x, val(x)+1
|
|
m_stream.PutHex8 (DW_OP_APPLE_assign); // val(x), x
|
|
m_stream.PutHex8 (DW_OP_drop); // val(x)
|
|
break;
|
|
|
|
case clang::UnaryOperator::PostDec:
|
|
// Duplciate the top of stack value (which must be something that can
|
|
// be assignable/incremented) and push its current value
|
|
m_stream.PutHex8 (DW_OP_dup); // x, x
|
|
m_stream.PutHex8 (DW_OP_APPLE_value_of); // x, val(x)
|
|
m_stream.PutHex8 (DW_OP_swap); // val(x), x
|
|
m_stream.PutHex8 (DW_OP_dup); // val(x), x, x
|
|
m_stream.PutHex8 (DW_OP_lit1); // val(x), x, x, 1
|
|
m_stream.PutHex8 (DW_OP_minus); // val(x), x, val(x)-1
|
|
m_stream.PutHex8 (DW_OP_APPLE_assign); // val(x), x
|
|
m_stream.PutHex8 (DW_OP_drop); // val(x)
|
|
break;
|
|
|
|
case clang::UnaryOperator::PreInc:
|
|
m_stream.PutHex8 (DW_OP_dup); // x, x
|
|
m_stream.PutHex8 (DW_OP_APPLE_value_of); // x, val(x)
|
|
m_stream.PutHex8 (DW_OP_lit1); // x, val(x), 1
|
|
m_stream.PutHex8 (DW_OP_plus); // x, val(x)+1
|
|
m_stream.PutHex8 (DW_OP_APPLE_assign); // x with new value
|
|
break;
|
|
|
|
case clang::UnaryOperator::PreDec:
|
|
m_stream.PutHex8 (DW_OP_dup); // x, x
|
|
m_stream.PutHex8 (DW_OP_APPLE_value_of); // x, val(x)
|
|
m_stream.PutHex8 (DW_OP_lit1); // x, val(x), 1
|
|
m_stream.PutHex8 (DW_OP_minus); // x, val(x)-1
|
|
m_stream.PutHex8 (DW_OP_APPLE_assign); // x with new value
|
|
break;
|
|
|
|
case clang::UnaryOperator::AddrOf:
|
|
m_stream.PutHex8 (DW_OP_APPLE_address_of);
|
|
break;
|
|
|
|
case clang::UnaryOperator::Deref:
|
|
m_stream.PutHex8 (DW_OP_APPLE_deref_type);
|
|
break;
|
|
|
|
case clang::UnaryOperator::Plus:
|
|
m_stream.PutHex8 (DW_OP_abs);
|
|
break;
|
|
|
|
case clang::UnaryOperator::Minus:
|
|
m_stream.PutHex8 (DW_OP_neg);
|
|
break;
|
|
|
|
case clang::UnaryOperator::Not:
|
|
m_stream.PutHex8 (DW_OP_not);
|
|
break;
|
|
|
|
case clang::UnaryOperator::LNot:
|
|
m_stream.PutHex8 (DW_OP_lit0);
|
|
m_stream.PutHex8 (DW_OP_eq);
|
|
break;
|
|
|
|
case clang::UnaryOperator::Real:
|
|
m_stream.PutHex8(DW_OP_APPLE_error);
|
|
break;
|
|
|
|
case clang::UnaryOperator::Imag:
|
|
m_stream.PutHex8(DW_OP_APPLE_error);
|
|
break;
|
|
|
|
case clang::UnaryOperator::Extension:
|
|
m_stream.PutHex8(DW_OP_APPLE_error);
|
|
break;
|
|
|
|
case clang::UnaryOperator::OffsetOf:
|
|
break;
|
|
|
|
default:
|
|
assert(!"Unknown unary operator!");
|
|
break;
|
|
}
|
|
}
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitCastExpr (clang::CastExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
// CastExpr::CastKind cast_kind = Node->getCastKind();
|
|
// switch (cast_kind)
|
|
// {
|
|
// case CastExpr::CK_Unknown:
|
|
// case CastExpr::CK_BitCast: // Used for reinterpret_cast.
|
|
// case CastExpr::CK_NoOp: // Used for const_cast.
|
|
// case CastExpr::CK_BaseToDerived: // Base to derived class casts.
|
|
// case CastExpr::CK_DerivedToBase: // Derived to base class casts.
|
|
// case CastExpr::CK_Dynamic: // Dynamic cast.
|
|
// case CastExpr::CK_ToUnion: // Cast to union (GCC extension).
|
|
// case CastExpr::CK_ArrayToPointerDecay: // Array to pointer decay.
|
|
// case CastExpr::CK_FunctionToPointerDecay: // Function to pointer decay.
|
|
// case CastExpr::CK_NullToMemberPointer: // Null pointer to member pointer.
|
|
// case CastExpr::CK_BaseToDerivedMemberPointer: // Member pointer in base class to member pointer in derived class.
|
|
// case CastExpr::CK_DerivedToBaseMemberPointer: // Member pointer in derived class to member pointer in base class.
|
|
// case CastExpr::CK_UserDefinedConversion: // Conversion using a user defined type conversion function.
|
|
// case CastExpr::CK_ConstructorConversion: // Conversion by constructor
|
|
// case CastExpr::CK_IntegralToPointer: // Integral to pointer
|
|
// case CastExpr::CK_PointerToIntegral: // Pointer to integral
|
|
// case CastExpr::CK_ToVoid: // Cast to void
|
|
// case CastExpr::CK_VectorSplat: // Casting from an integer/floating type to an extended
|
|
// // vector type with the same element type as the src type. Splats the
|
|
// // src expression into the destination expression.
|
|
// case CastExpr::CK_IntegralCast: // Casting between integral types of different size.
|
|
// case CastExpr::CK_IntegralToFloating: // Integral to floating point.
|
|
// case CastExpr::CK_FloatingToIntegral: // Floating point to integral.
|
|
// case CastExpr::CK_FloatingCast: // Casting between floating types of different size.
|
|
// m_stream.PutHex8(DW_OP_APPLE_error);
|
|
// break;
|
|
// }
|
|
uint32_t cast_type_count = 0;
|
|
lldb_private::Scalar::Type cast_type_encoding = GetScalarTypeForClangType (m_ast_context, Node->getType(), cast_type_count);
|
|
|
|
|
|
Visit (Node->getSubExpr());
|
|
|
|
// Simple scalar cast
|
|
if (cast_type_encoding != lldb_private::Scalar::e_void && cast_type_count == 1)
|
|
{
|
|
// Only cast if our scalar types mismatch
|
|
uint32_t castee_type_count = 0;
|
|
lldb_private::Scalar::Type castee_type_encoding = GetScalarTypeForClangType (m_ast_context, Node->getSubExpr()->getType(), castee_type_count);
|
|
if (cast_type_encoding != castee_type_encoding &&
|
|
castee_type_encoding != lldb_private::Scalar::e_void)
|
|
{
|
|
m_stream.PutHex8(DW_OP_APPLE_scalar_cast);
|
|
m_stream.PutHex8(cast_type_encoding);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Handle more complex casts with clang types soon!
|
|
m_stream.PutHex8(DW_OP_APPLE_error);
|
|
}
|
|
}
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitArraySubscriptExpr (clang::ArraySubscriptExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
Visit (Node->getBase());
|
|
Visit (Node->getIdx());
|
|
m_stream.PutHex8(DW_OP_APPLE_array_ref);
|
|
}
|
|
|
|
//
|
|
//CLANG_STMT_RESULT
|
|
//lldb_private::ClangStmtVisitor::VisitImplicitCastExpr (clang::ImplicitCastExpr *Node)
|
|
//{
|
|
// DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
// m_stream.PutHex8(DW_OP_APPLE_scalar_cast);
|
|
// Visit (Node->getSubExpr());
|
|
//}
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitSizeOfAlignOfExpr (clang::SizeOfAlignOfExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitMemberExpr (clang::MemberExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
clang::Expr *parent = Node->getBase();
|
|
Visit (parent);
|
|
clang::QualType parent_clang_type = parent->getType();
|
|
clang::NamedDecl *member_named_decl = cast<clang::NamedDecl>(Node->getMemberDecl()->getCanonicalDecl());
|
|
|
|
// DeclarationName member_name = member->getDeclName();
|
|
|
|
clang::Type::TypeClass parent_type_class = parent_clang_type->getTypeClass();
|
|
if (parent_type_class == clang::Type::Pointer)
|
|
{
|
|
clang::PointerType *pointer_type = cast<clang::PointerType>(parent_clang_type.getTypePtr());
|
|
parent_clang_type = pointer_type->getPointeeType();
|
|
parent_type_class = parent_clang_type->getTypeClass();
|
|
}
|
|
|
|
switch (parent_type_class)
|
|
{
|
|
case clang::Type::Record:
|
|
{
|
|
const clang::RecordType *record_type = cast<clang::RecordType>(parent_clang_type.getTypePtr());
|
|
const clang::RecordDecl *record_decl = record_type->getDecl();
|
|
assert(record_decl);
|
|
const clang::ASTRecordLayout &record_layout = m_ast_context.getASTRecordLayout(record_decl);
|
|
uint32_t field_idx = 0;
|
|
clang::RecordDecl::field_iterator field, field_end;
|
|
for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx)
|
|
{
|
|
clang::NamedDecl *field_named_decl = cast<clang::NamedDecl>(field->getCanonicalDecl());
|
|
if (field_named_decl == member_named_decl)
|
|
{
|
|
std::pair<uint64_t, unsigned> field_type_info = m_ast_context.getTypeInfo(field->getType());
|
|
uint64_t field_bit_offset = record_layout.getFieldOffset (field_idx);
|
|
uint64_t field_byte_offset = field_bit_offset / 8;
|
|
uint32_t field_bitfield_bit_size = 0;
|
|
//uint32_t field_bitfield_bit_offset = field_bit_offset % 8;
|
|
|
|
if (field->isBitField())
|
|
{
|
|
clang::Expr* bit_width_expr = field->getBitWidth();
|
|
if (bit_width_expr)
|
|
{
|
|
llvm::APSInt bit_width_apsint;
|
|
if (bit_width_expr->isIntegerConstantExpr(bit_width_apsint, m_ast_context))
|
|
{
|
|
field_bitfield_bit_size = bit_width_apsint.getLimitedValue(UINT32_MAX);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Node->isArrow())
|
|
{
|
|
m_stream.PutHex8(DW_OP_deref);
|
|
}
|
|
else
|
|
{
|
|
m_stream.PutHex8(DW_OP_APPLE_address_of);
|
|
}
|
|
|
|
if (field_byte_offset)
|
|
{
|
|
if (EncodeUInt64(field_byte_offset, 0))
|
|
{
|
|
m_stream.PutHex8(DW_OP_plus);
|
|
}
|
|
}
|
|
m_stream.PutHex8(DW_OP_APPLE_clang_cast);
|
|
m_stream.PutPointer(field->getType().getAsOpaquePtr());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
assert(!"Unhandled MemberExpr");
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitExtVectorElementExpr (clang::ExtVectorElementExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitParenExpr(clang::ParenExpr *paren_expr)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
Visit (paren_expr->getSubExpr());
|
|
}
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitInitListExpr (clang::InitListExpr *init_list_expr)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitBinaryOperator (clang::BinaryOperator *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
|
|
Visit(Node->getLHS());
|
|
Visit(Node->getRHS());
|
|
|
|
switch (Node->getOpcode())
|
|
{
|
|
default: assert(0 && "Unknown binary operator!");
|
|
case clang::BinaryOperator::PtrMemD: m_stream.PutHex8(DW_OP_APPLE_error); break;
|
|
case clang::BinaryOperator::PtrMemI: m_stream.PutHex8(DW_OP_APPLE_error); break;
|
|
case clang::BinaryOperator::Mul: m_stream.PutHex8(DW_OP_mul); break;
|
|
case clang::BinaryOperator::Div: m_stream.PutHex8(DW_OP_div); break;
|
|
case clang::BinaryOperator::Rem: m_stream.PutHex8(DW_OP_mod); break;
|
|
case clang::BinaryOperator::Add: m_stream.PutHex8(DW_OP_plus); break;
|
|
case clang::BinaryOperator::Sub: m_stream.PutHex8(DW_OP_minus); break;
|
|
case clang::BinaryOperator::Shl: m_stream.PutHex8(DW_OP_shl); break;
|
|
case clang::BinaryOperator::Shr: m_stream.PutHex8(DW_OP_shr); break;
|
|
case clang::BinaryOperator::LT: m_stream.PutHex8(DW_OP_lt); break;
|
|
case clang::BinaryOperator::GT: m_stream.PutHex8(DW_OP_gt); break;
|
|
case clang::BinaryOperator::LE: m_stream.PutHex8(DW_OP_le); break;
|
|
case clang::BinaryOperator::GE: m_stream.PutHex8(DW_OP_ge); break;
|
|
case clang::BinaryOperator::EQ: m_stream.PutHex8(DW_OP_eq); break;
|
|
case clang::BinaryOperator::NE: m_stream.PutHex8(DW_OP_ne); break;
|
|
case clang::BinaryOperator::And: m_stream.PutHex8(DW_OP_and); break;
|
|
case clang::BinaryOperator::Xor: m_stream.PutHex8(DW_OP_xor); break;
|
|
case clang::BinaryOperator::Or : m_stream.PutHex8(DW_OP_or); break;
|
|
case clang::BinaryOperator::LAnd:
|
|
// Do we need to call an operator here on objects? If so
|
|
// we will need a DW_OP_apple_logical_and
|
|
m_stream.PutHex8(DW_OP_lit0);
|
|
m_stream.PutHex8(DW_OP_ne);
|
|
m_stream.PutHex8(DW_OP_swap);
|
|
m_stream.PutHex8(DW_OP_lit0);
|
|
m_stream.PutHex8(DW_OP_ne);
|
|
m_stream.PutHex8(DW_OP_and);
|
|
break;
|
|
|
|
case clang::BinaryOperator::LOr :
|
|
// Do we need to call an operator here on objects? If so
|
|
// we will need a DW_OP_apple_logical_or
|
|
m_stream.PutHex8(DW_OP_lit0);
|
|
m_stream.PutHex8(DW_OP_ne);
|
|
m_stream.PutHex8(DW_OP_swap);
|
|
m_stream.PutHex8(DW_OP_lit0);
|
|
m_stream.PutHex8(DW_OP_ne);
|
|
m_stream.PutHex8(DW_OP_or);
|
|
break;
|
|
|
|
case clang::BinaryOperator::Assign:
|
|
m_stream.PutHex8(DW_OP_APPLE_assign);
|
|
break;
|
|
|
|
case clang::BinaryOperator::MulAssign:
|
|
m_stream.PutHex8(DW_OP_over);
|
|
m_stream.PutHex8(DW_OP_swap);
|
|
m_stream.PutHex8(DW_OP_mul);
|
|
m_stream.PutHex8(DW_OP_APPLE_assign);
|
|
break;
|
|
|
|
case clang::BinaryOperator::DivAssign:
|
|
m_stream.PutHex8(DW_OP_over);
|
|
m_stream.PutHex8(DW_OP_swap);
|
|
m_stream.PutHex8(DW_OP_div);
|
|
m_stream.PutHex8(DW_OP_APPLE_assign);
|
|
break;
|
|
|
|
case clang::BinaryOperator::RemAssign:
|
|
m_stream.PutHex8(DW_OP_over);
|
|
m_stream.PutHex8(DW_OP_swap);
|
|
m_stream.PutHex8(DW_OP_mod);
|
|
m_stream.PutHex8(DW_OP_APPLE_assign);
|
|
break;
|
|
|
|
case clang::BinaryOperator::AddAssign:
|
|
m_stream.PutHex8(DW_OP_over);
|
|
m_stream.PutHex8(DW_OP_swap);
|
|
m_stream.PutHex8(DW_OP_plus);
|
|
m_stream.PutHex8(DW_OP_APPLE_assign);
|
|
break;
|
|
|
|
case clang::BinaryOperator::SubAssign:
|
|
m_stream.PutHex8(DW_OP_over);
|
|
m_stream.PutHex8(DW_OP_swap);
|
|
m_stream.PutHex8(DW_OP_minus);
|
|
m_stream.PutHex8(DW_OP_APPLE_assign);
|
|
break;
|
|
|
|
case clang::BinaryOperator::ShlAssign:
|
|
m_stream.PutHex8(DW_OP_over);
|
|
m_stream.PutHex8(DW_OP_swap);
|
|
m_stream.PutHex8(DW_OP_shl);
|
|
m_stream.PutHex8(DW_OP_APPLE_assign);
|
|
break;
|
|
|
|
case clang::BinaryOperator::ShrAssign:
|
|
m_stream.PutHex8(DW_OP_over);
|
|
m_stream.PutHex8(DW_OP_swap);
|
|
m_stream.PutHex8(DW_OP_shr);
|
|
m_stream.PutHex8(DW_OP_APPLE_assign);
|
|
break;
|
|
|
|
case clang::BinaryOperator::AndAssign:
|
|
m_stream.PutHex8(DW_OP_over);
|
|
m_stream.PutHex8(DW_OP_swap);
|
|
m_stream.PutHex8(DW_OP_and);
|
|
m_stream.PutHex8(DW_OP_APPLE_assign);
|
|
break;
|
|
|
|
case clang::BinaryOperator::OrAssign:
|
|
m_stream.PutHex8(DW_OP_over);
|
|
m_stream.PutHex8(DW_OP_swap);
|
|
m_stream.PutHex8(DW_OP_or);
|
|
m_stream.PutHex8(DW_OP_APPLE_assign);
|
|
break;
|
|
|
|
case clang::BinaryOperator::XorAssign:
|
|
m_stream.PutHex8(DW_OP_over);
|
|
m_stream.PutHex8(DW_OP_swap);
|
|
m_stream.PutHex8(DW_OP_xor);
|
|
m_stream.PutHex8(DW_OP_APPLE_assign);
|
|
break;
|
|
|
|
case clang::BinaryOperator::Comma:
|
|
// Nothing needs to be done here right?
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//CLANG_STMT_RESULT
|
|
//lldb_private::ClangStmtVisitor::VisitCompoundAssignOperator (CompoundAssignOperator *Node)
|
|
//{
|
|
// DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
//
|
|
//}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitAddrLabelExpr (clang::AddrLabelExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitTypesCompatibleExpr (clang::TypesCompatibleExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
|
|
// C++
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitCXXNamedCastExpr (clang::CXXNamedCastExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitCXXBoolLiteralExpr (clang::CXXBoolLiteralExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitCXXThisExpr (clang::CXXThisExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitCXXFunctionalCastExpr (clang::CXXFunctionalCastExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
|
|
// ObjC
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitObjCEncodeExpr (clang::ObjCEncodeExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitObjCMessageExpr (clang::ObjCMessageExpr* Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitObjCSelectorExpr (clang::ObjCSelectorExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitObjCProtocolExpr (clang::ObjCProtocolExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitObjCPropertyRefExpr (clang::ObjCPropertyRefExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitObjCImplicitSetterGetterRefExpr (clang::ObjCImplicitSetterGetterRefExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitObjCIvarRefExpr (clang::ObjCIvarRefExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|
|
CLANG_STMT_RESULT
|
|
lldb_private::ClangStmtVisitor::VisitObjCSuperExpr (clang::ObjCSuperExpr *Node)
|
|
{
|
|
DEBUG_PRINTF("%s\n", __PRETTY_FUNCTION__);
|
|
}
|
|
|
|
|