forked from OSchip/llvm-project
Scaffolding for supporting empty bases/fields.
llvm-svn: 82678
This commit is contained in:
parent
26ea28eb5f
commit
6522b05db7
|
@ -219,8 +219,18 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD,
|
bool ASTRecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD,
|
||||||
bool IsVirtualBase) {
|
uint64_t Offset) const {
|
||||||
|
// FIXME: Implement.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
|
||||||
|
uint64_t Offset) {
|
||||||
|
// FIXME: Implement.
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
|
||||||
const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
|
const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
|
||||||
if (!Bases.empty()) {
|
if (!Bases.empty()) {
|
||||||
assert(BaseInfo.getDataSize() > 0 &&
|
assert(BaseInfo.getDataSize() > 0 &&
|
||||||
|
@ -229,15 +239,32 @@ void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD,
|
||||||
|
|
||||||
unsigned BaseAlign = BaseInfo.getNonVirtualAlign();
|
unsigned BaseAlign = BaseInfo.getNonVirtualAlign();
|
||||||
uint64_t BaseSize = BaseInfo.getNonVirtualSize();
|
uint64_t BaseSize = BaseInfo.getNonVirtualSize();
|
||||||
|
|
||||||
// Round up the current record size to the base's alignment boundary.
|
// Round up the current record size to the base's alignment boundary.
|
||||||
Size = (Size + (BaseAlign-1)) & ~(BaseAlign-1);
|
uint64_t Offset = llvm::RoundUpToAlignment(Size, BaseAlign);
|
||||||
|
|
||||||
|
// Reserve space for this base.
|
||||||
|
Size = Offset + BaseSize;
|
||||||
|
|
||||||
|
// Remember the next available offset.
|
||||||
|
NextOffset = Size;
|
||||||
|
|
||||||
|
// Remember max struct/class alignment.
|
||||||
|
UpdateAlignment(BaseAlign);
|
||||||
|
|
||||||
|
return Offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD,
|
||||||
|
bool IsVirtualBase) {
|
||||||
|
// Layout the base.
|
||||||
|
unsigned Offset = LayoutBase(RD);
|
||||||
|
|
||||||
// Add base class offsets.
|
// Add base class offsets.
|
||||||
if (IsVirtualBase)
|
if (IsVirtualBase)
|
||||||
VBases.push_back(std::make_pair(RD, Size));
|
VBases.push_back(std::make_pair(RD, Offset));
|
||||||
else
|
else
|
||||||
Bases.push_back(std::make_pair(RD, Size));
|
Bases.push_back(std::make_pair(RD, Offset));
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// And now add offsets for all our primary virtual bases as well, so
|
// And now add offsets for all our primary virtual bases as well, so
|
||||||
|
@ -254,15 +281,6 @@ void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD,
|
||||||
L = &Ctx.getASTRecordLayout(PB);
|
L = &Ctx.getASTRecordLayout(PB);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Reserve space for this base.
|
|
||||||
Size += BaseSize;
|
|
||||||
|
|
||||||
// Remember the next available offset.
|
|
||||||
NextOffset = Size;
|
|
||||||
|
|
||||||
// Remember max struct/class alignment.
|
|
||||||
UpdateAlignment(BaseAlign);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
|
void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
|
||||||
|
@ -408,7 +426,7 @@ void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) {
|
||||||
FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
|
FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
|
||||||
|
|
||||||
// Round up the current record size to the field's alignment boundary.
|
// Round up the current record size to the field's alignment boundary.
|
||||||
FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
|
FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place this field at the current location.
|
// Place this field at the current location.
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/SmallSet.h"
|
#include "llvm/ADT/SmallSet.h"
|
||||||
#include "llvm/Support/DataTypes.h"
|
#include "llvm/Support/DataTypes.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
class ASTContext;
|
class ASTContext;
|
||||||
|
@ -53,6 +54,10 @@ class ASTRecordLayoutBuilder {
|
||||||
/// primary base classes for some other direct or indirect base class.
|
/// primary base classes for some other direct or indirect base class.
|
||||||
llvm::SmallSet<const CXXRecordDecl*, 32> IndirectPrimaryBases;
|
llvm::SmallSet<const CXXRecordDecl*, 32> IndirectPrimaryBases;
|
||||||
|
|
||||||
|
/// EmptyClassOffsets - A map from offsets to empty record decls.
|
||||||
|
typedef std::multimap<uint64_t, const CXXRecordDecl *> EmptyClassOffsetsTy;
|
||||||
|
EmptyClassOffsetsTy EmptyClassOffsets;
|
||||||
|
|
||||||
ASTRecordLayoutBuilder(ASTContext &Ctx);
|
ASTRecordLayoutBuilder(ASTContext &Ctx);
|
||||||
|
|
||||||
void Layout(const RecordDecl *D);
|
void Layout(const RecordDecl *D);
|
||||||
|
@ -79,6 +84,10 @@ class ASTRecordLayoutBuilder {
|
||||||
|
|
||||||
bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
|
bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
|
||||||
|
|
||||||
|
/// LayoutBase - Will lay out a base and return the offset where it was
|
||||||
|
/// placed, in bits.
|
||||||
|
uint64_t LayoutBase(const CXXRecordDecl *RD);
|
||||||
|
|
||||||
void LayoutVtable(const CXXRecordDecl *RD);
|
void LayoutVtable(const CXXRecordDecl *RD);
|
||||||
void LayoutNonVirtualBases(const CXXRecordDecl *RD);
|
void LayoutNonVirtualBases(const CXXRecordDecl *RD);
|
||||||
void LayoutBaseNonVirtually(const CXXRecordDecl *RD, bool IsVBase);
|
void LayoutBaseNonVirtually(const CXXRecordDecl *RD, bool IsVBase);
|
||||||
|
@ -88,6 +97,18 @@ class ASTRecordLayoutBuilder {
|
||||||
llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
|
llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
|
||||||
llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary);
|
llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary);
|
||||||
|
|
||||||
|
/// canPlaceRecordAtOffset - Return whether a record (either a base class
|
||||||
|
/// or a field) can be placed at the given offset.
|
||||||
|
/// Returns false if placing the record will result in two components
|
||||||
|
/// (direct or indirect) of the same type having the same offset.
|
||||||
|
bool canPlaceRecordAtOffset(const CXXRecordDecl *RD, uint64_t Offset) const;
|
||||||
|
|
||||||
|
/// UpdateEmptyClassOffsets - Called after a record (either a base class
|
||||||
|
/// or a field) has been placed at the given offset. Will update the
|
||||||
|
/// EmptyClassOffsets map if the class is empty or has any empty bases or
|
||||||
|
/// fields.
|
||||||
|
void UpdateEmptyClassOffsets(const CXXRecordDecl *RD, uint64_t Offset);
|
||||||
|
|
||||||
/// FinishLayout - Finalize record layout. Adjust record size based on the
|
/// FinishLayout - Finalize record layout. Adjust record size based on the
|
||||||
/// alignment.
|
/// alignment.
|
||||||
void FinishLayout();
|
void FinishLayout();
|
||||||
|
|
Loading…
Reference in New Issue