llvm-project/clang/lib/AST/RecordLayout.cpp
Warren Hunt 7b252d24ad Support MS-ABI's concept of "Required Alignment" imposed by
__declspec(align())

This patch implements required alignment in a way that makes 
__declspec(align()) and #pragma pack play correctly together. In the 
MS-ABI, __declspec(align()) is a hard rule and cannot be overridden by 
#pragma pack. This cases each record to have two interesting alignments 
"preferred alignment" (which matches Itanium's concept of alignment) and 
"required alignment" which is an alignment that must never be violated, 
even in the case of #pragma pack. This patch introduces the concept of 
Required Alignment to the record builder and tracks/uses it 
appropriately. Test cases are included.

Differential Revision: http://llvm-reviews.chandlerc.com/D2283

llvm-svn: 196549
2013-12-06 00:01:17 +00:00

99 lines
3.8 KiB
C++

//===-- RecordLayout.cpp - Layout information for a struct/union -*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the RecordLayout interface.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/TargetInfo.h"
using namespace clang;
void ASTRecordLayout::Destroy(ASTContext &Ctx) {
if (FieldOffsets)
Ctx.Deallocate(FieldOffsets);
if (CXXInfo) {
Ctx.Deallocate(CXXInfo);
CXXInfo->~CXXRecordLayoutInfo();
}
this->~ASTRecordLayout();
Ctx.Deallocate(this);
}
ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size,
CharUnits alignment,
CharUnits requiredAlignment,
CharUnits datasize,
const uint64_t *fieldoffsets,
unsigned fieldcount)
: Size(size), DataSize(datasize), Alignment(alignment),
RequiredAlignment(requiredAlignment), FieldOffsets(0),
FieldCount(fieldcount), CXXInfo(0) {
if (FieldCount > 0) {
FieldOffsets = new (Ctx) uint64_t[FieldCount];
memcpy(FieldOffsets, fieldoffsets, FieldCount * sizeof(*FieldOffsets));
}
}
// Constructor for C++ records.
ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
CharUnits size, CharUnits alignment,
CharUnits requiredAlignment,
bool hasOwnVFPtr, bool hasExtendableVFPtr,
CharUnits vbptroffset,
CharUnits datasize,
const uint64_t *fieldoffsets,
unsigned fieldcount,
CharUnits nonvirtualsize,
CharUnits nonvirtualalign,
CharUnits SizeOfLargestEmptySubobject,
const CXXRecordDecl *PrimaryBase,
bool IsPrimaryBaseVirtual,
const CXXRecordDecl *BaseSharingVBPtr,
const BaseOffsetsMapTy& BaseOffsets,
const VBaseOffsetsMapTy& VBaseOffsets)
: Size(size), DataSize(datasize), Alignment(alignment),
RequiredAlignment(requiredAlignment), FieldOffsets(0),
FieldCount(fieldcount), CXXInfo(new (Ctx) CXXRecordLayoutInfo)
{
if (FieldCount > 0) {
FieldOffsets = new (Ctx) uint64_t[FieldCount];
memcpy(FieldOffsets, fieldoffsets, FieldCount * sizeof(*FieldOffsets));
}
CXXInfo->PrimaryBase.setPointer(PrimaryBase);
CXXInfo->PrimaryBase.setInt(IsPrimaryBaseVirtual);
CXXInfo->NonVirtualSize = nonvirtualsize;
CXXInfo->NonVirtualAlign = nonvirtualalign;
CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject;
CXXInfo->BaseOffsets = BaseOffsets;
CXXInfo->VBaseOffsets = VBaseOffsets;
CXXInfo->HasOwnVFPtr = hasOwnVFPtr;
CXXInfo->VBPtrOffset = vbptroffset;
CXXInfo->HasExtendableVFPtr = hasExtendableVFPtr;
CXXInfo->BaseSharingVBPtr = BaseSharingVBPtr;
#ifndef NDEBUG
if (const CXXRecordDecl *PrimaryBase = getPrimaryBase()) {
if (isPrimaryBaseVirtual()) {
if (Ctx.getTargetInfo().getCXXABI().hasPrimaryVBases()) {
assert(getVBaseClassOffset(PrimaryBase).isZero() &&
"Primary virtual base must be at offset 0!");
}
} else {
assert(getBaseClassOffset(PrimaryBase).isZero() &&
"Primary base must be at offset 0!");
}
}
#endif
}