mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 02:46:06 +00:00

__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
99 lines
3.8 KiB
C++
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
|
|
}
|