Browse Source

Added v[f]table parsing support.

pull/16/merge
triton 12 years ago
parent
commit
dbd9fbc9d5
  1. 28
      src/AST/Class.cs
  2. 114
      src/AST/ClassLayout.cs
  3. 131
      src/Parser/Parser.cpp
  4. 4
      src/Parser/Parser.h

28
src/AST/Class.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace CppSharp.AST
@ -57,33 +58,6 @@ namespace CppSharp.AST @@ -57,33 +58,6 @@ namespace CppSharp.AST
}
}
// Represents a C++ virtual function table.
public class VFTable
{
}
// Represents a C++ virtual base table.
public class VBTable
{
}
// Represents ABI-specific layout details for a class.
public class ClassLayout
{
public CppAbi ABI { get; set; }
public VFTable VirtualFunctions { get; set; }
public VBTable VirtualBases { get; set; }
public bool HasOwnVFTable;
public bool HasVirtualBases;
public int Alignment;
public int Size;
public int DataSize;
}
public enum ClassType
{
ValueType,

114
src/AST/ClassLayout.cs

@ -0,0 +1,114 @@ @@ -0,0 +1,114 @@
using System.Collections.Generic;
using System.Diagnostics;
namespace CppSharp.AST
{
/// <summary>
/// Virtual table component kind.
/// </summary>
public enum VTableComponentKind
{
VCallOffset,
VBaseOffset,
OffsetToTop,
RTTI,
FunctionPointer,
CompleteDtorPointer,
DeletingDtorPointer,
UnusedFunctionPointer,
}
/// <summary>
/// Represents a C++ virtual table component.
/// </summary>
[DebuggerDisplay("{Kind}, {Offset}, {Declaration}")]
public struct VTableComponent
{
public VTableComponentKind Kind;
public ulong Offset;
public Declaration Declaration;
/// Method declaration (if Kind == FunctionPointer).
public Method Method
{
get
{
Debug.Assert(Kind == VTableComponentKind.FunctionPointer);
return Declaration as Method;
}
}
}
/// <summary>
/// Represents a C++ virtual table layout.
/// </summary>
public class VTableLayout
{
public List<VTableComponent> Components { get; set; }
public VTableLayout()
{
Components = new List<VTableComponent>();
}
}
/// <summary>
/// Contains information about virtual function pointers.
/// </summary>
public struct VFTableInfo
{
/// If nonzero, holds the vbtable index of the virtual base with the vfptr.
public ulong VBTableIndex;
/// This is the offset of the vfptr from the start of the last vbase,
/// or the complete type if there are no virtual bases.
public long VFPtrOffset;
/// This is the full offset of the vfptr from the start of the complete type.
public long VFPtrFullOffset;
/// Layout of the table at this pointer.
public VTableLayout Layout;
}
// Represents ABI-specific layout details for a class.
public class ClassLayout
{
public CppAbi ABI { get; set; }
/// Virtual function tables in Microsoft mode.
public List<VFTableInfo> VFTables { get; set; }
/// Virtual table layout in Itanium mode.
public VTableLayout Layout { get; set; }
public ClassLayout()
{
VFTables = new List<VFTableInfo>();
}
/// <summary>
/// Does this class provide its own virtual-function table
/// pointer, rather than inheriting one from a primary base
/// class? If so, it is at offset zero.
/// </summary>
public bool HasOwnVFPtr;
/// <summary>
/// Get the offset for virtual base table pointer.
/// This is only meaningful with the Microsoft ABI.
/// </summary>
public long VBPtrOffset;
/// <summary>
/// Primary base for this record.
/// </summary>
public Class PrimaryBase;
public bool HasVirtualBases;
public int Alignment;
public int Size;
public int DataSize;
}
}

131
src/Parser/Parser.cpp

@ -367,6 +367,133 @@ static CppSharp::AST::AccessSpecifier ConvertToAccess(clang::AccessSpecifier AS) @@ -367,6 +367,133 @@ static CppSharp::AST::AccessSpecifier ConvertToAccess(clang::AccessSpecifier AS)
return CppSharp::AST::AccessSpecifier::Public;
}
CppSharp::AST::VTableComponent
Parser::WalkVTableComponent(const clang::VTableComponent& Component)
{
using namespace clang;
CppSharp::AST::VTableComponent VTC;
switch(Component.getKind())
{
case VTableComponent::CK_VCallOffset:
{
VTC.Kind = CppSharp::AST::VTableComponentKind::VBaseOffset;
VTC.Offset = Component.getVCallOffset().getQuantity();
break;
}
case VTableComponent::CK_VBaseOffset:
{
VTC.Kind = CppSharp::AST::VTableComponentKind::VBaseOffset;
VTC.Offset = Component.getVBaseOffset().getQuantity();
break;
}
case VTableComponent::CK_OffsetToTop:
{
VTC.Kind = CppSharp::AST::VTableComponentKind::OffsetToTop;
VTC.Offset = Component.getOffsetToTop().getQuantity();
break;
}
case VTableComponent::CK_RTTI:
{
VTC.Kind = CppSharp::AST::VTableComponentKind::RTTI;
auto RD = const_cast<CXXRecordDecl*>(Component.getRTTIDecl());
VTC.Declaration = WalkRecordCXX(RD);
break;
}
case VTableComponent::CK_FunctionPointer:
{
VTC.Kind = CppSharp::AST::VTableComponentKind::FunctionPointer;
auto MD = const_cast<CXXMethodDecl*>(Component.getFunctionDecl());
VTC.Declaration = WalkMethodCXX(MD);
break;
}
case VTableComponent::CK_CompleteDtorPointer:
{
VTC.Kind = CppSharp::AST::VTableComponentKind::CompleteDtorPointer;
auto MD = const_cast<CXXDestructorDecl*>(Component.getDestructorDecl());
VTC.Declaration = WalkMethodCXX(MD);
break;
}
case VTableComponent::CK_DeletingDtorPointer:
{
VTC.Kind = CppSharp::AST::VTableComponentKind::DeletingDtorPointer;
auto MD = const_cast<CXXDestructorDecl*>(Component.getDestructorDecl());
VTC.Declaration = WalkMethodCXX(MD);
break;
}
case VTableComponent::CK_UnusedFunctionPointer:
{
VTC.Kind = CppSharp::AST::VTableComponentKind::UnusedFunctionPointer;
auto MD = const_cast<CXXMethodDecl*>(Component.getUnusedFunctionDecl());
VTC.Declaration = WalkMethodCXX(MD);
break;
}
default:
llvm_unreachable("Unknown vtable component kind");
}
return VTC;
}
CppSharp::AST::VTableLayout^
Parser::WalkVTableLayout(const clang::VTableLayout& VTLayout)
{
auto Layout = gcnew CppSharp::AST::VTableLayout();
for (auto I = VTLayout.vtable_component_begin(),
E = VTLayout.vtable_component_end(); I != E; ++I)
{
auto VTComponent = WalkVTableComponent(*I);
Layout->Components->Add(VTComponent);
}
return Layout;
}
void Parser::WalkVTable(clang::CXXRecordDecl* RD, CppSharp::AST::Class^ C)
{
using namespace clang;
using namespace clix;
assert(RD->isDynamicClass() && "Only dynamic classes have virtual tables");
switch(TargetABI)
{
case TargetCXXABI::Microsoft:
{
MicrosoftVFTableContext VTContext(*AST);
auto VFPtrs = VTContext.getVFPtrOffsets(RD);
for (auto I = VFPtrs.begin(), E = VFPtrs.end(); I != E; ++I)
{
auto& VFPtrInfo = *I;
CppSharp::AST::VFTableInfo Info;
Info.VBTableIndex = VFPtrInfo.VBTableIndex;
Info.VFPtrOffset = VFPtrInfo.VFPtrOffset.getQuantity();
Info.VFPtrFullOffset = VFPtrInfo.VFPtrFullOffset.getQuantity();
auto& VTLayout = VTContext.getVFTableLayout(RD, VFPtrInfo.VFPtrOffset);
Info.Layout = WalkVTableLayout(VTLayout);
C->Layout->VFTables->Add(Info);
break;
}
}
case TargetCXXABI::GenericItanium:
{
VTableContext VTContext(*AST);
auto& VTLayout = VTContext.getVTableLayout(RD);
C->Layout->Layout = WalkVTableLayout(VTLayout);
break;
}
default:
llvm_unreachable("Unsupported C++ ABI kind");
}
}
CppSharp::AST::Class^ Parser::WalkRecordCXX(clang::CXXRecordDecl* Record)
{
using namespace clang;
@ -432,6 +559,10 @@ CppSharp::AST::Class^ Parser::WalkRecordCXX(clang::CXXRecordDecl* Record) @@ -432,6 +559,10 @@ CppSharp::AST::Class^ Parser::WalkRecordCXX(clang::CXXRecordDecl* Record)
RC->Layout->Alignment = (int)Layout-> getAlignment().getQuantity();
RC->Layout->Size = (int)Layout->getSize().getQuantity();
RC->Layout->DataSize = (int)Layout->getDataSize().getQuantity();
RC->Layout->HasOwnVFPtr = Layout->hasOwnVFPtr();
RC->Layout->VBPtrOffset = Layout->getVBPtrOffset().getQuantity();
if (Record->isDynamicClass())
WalkVTable(Record, RC);
}
CppSharp::AST::AccessSpecifierDecl^ AccessDecl = nullptr;

4
src/Parser/Parser.h

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
#include <clang/AST/RawCommentList.h>
#include <clang/AST/Comment.h>
#include <clang/AST/RecordLayout.h>
#include <clang/AST/VTableBuilder.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Lex/PreprocessingRecord.h>
#include <clang/Parse/ParseAST.h>
@ -149,6 +150,9 @@ protected: @@ -149,6 +150,9 @@ protected:
CppSharp::AST::RawComment^ WalkRawComment(const clang::RawComment*);
CppSharp::AST::Type^ WalkType(clang::QualType, clang::TypeLoc* = 0,
bool DesugarType = false);
void WalkVTable(clang::CXXRecordDecl*, CppSharp::AST::Class^);
CppSharp::AST::VTableLayout^ WalkVTableLayout(const clang::VTableLayout&);
CppSharp::AST::VTableComponent WalkVTableComponent(const clang::VTableComponent&);
// Clang helpers
SourceLocationKind GetLocationKind(const clang::SourceLocation& Loc);

Loading…
Cancel
Save