using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace CppSharp.AST { /// /// Virtual table component kind. /// public enum VTableComponentKind { VCallOffset, VBaseOffset, OffsetToTop, RTTI, FunctionPointer, CompleteDtorPointer, DeletingDtorPointer, UnusedFunctionPointer, } /// /// Represents a C++ virtual table component. /// [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; } } } /// /// Represents a C++ virtual table layout. /// public class VTableLayout { public List Components { get; set; } public VTableLayout() { Components = new List(); } } /// /// Contains information about virtual function pointers. /// 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; } public enum RecordArgABI { /// /// Pass it using the normal C aggregate rules for the ABI, /// potentially introducing extra copies and passing some /// or all of it in registers. /// Default = 0, /// /// Pass it on the stack using its defined layout. /// The argument must be evaluated directly into the correct /// stack position in the arguments area, and the call machinery /// must not move it or introduce extra copies. /// DirectInMemory = 1, /// Pass it as a pointer to temporary memory. Indirect = 2 }; // Represents ABI-specific layout details for a class. public class ClassLayout { public CppAbi ABI { get; set; } /// Provides native argument ABI information. public RecordArgABI ArgABI { get; set; } /// Virtual function tables in Microsoft mode. public List VFTables { get; set; } /// Virtual table layout in Itanium mode. public VTableLayout Layout { get; set; } public ClassLayout() { VFTables = new List(); Fields = new List(); Bases = new List(); } public List Fields { get; private set; } public List Bases { get; private set; } public ClassLayout(ClassLayout classLayout) : this() { ABI = classLayout.ABI; HasOwnVFPtr = classLayout.HasOwnVFPtr; VBPtrOffset = classLayout.VBPtrOffset; PrimaryBase = classLayout.PrimaryBase; HasVirtualBases = classLayout.HasVirtualBases; Alignment = classLayout.Alignment; Size = classLayout.Size; DataSize = classLayout.DataSize; VFTables.AddRange(classLayout.VFTables); if (classLayout.Layout != null) { Layout = new VTableLayout(); Layout.Components.AddRange(classLayout.Layout.Components); } } /// /// 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. /// public bool HasOwnVFPtr; /// /// Get the offset for virtual base table pointer. /// This is only meaningful with the Microsoft ABI. /// public long VBPtrOffset; /// /// Primary base for this record. /// public Class PrimaryBase; public bool HasVirtualBases; public int Alignment; public int Size; public int DataSize; public IList VTablePointers { get { if (vTablePointers == null) { vTablePointers = ABI == CppAbi.Microsoft ? new List(Fields.Where(f => f.IsVTablePtr)) : new List { Fields.First(f => f.IsVTablePtr) }; } return vTablePointers; } } /// /// Indicates whether this class layout has a subclass at a non-zero offset. /// public bool HasSubclassAtNonZeroOffset { get; set; } private List vTablePointers; } }