Sema: Add initial support for '#pragma options align=mac68k'.

- Docs are fairly sketchy, if someone wants to pore through gcc to look for
   holes I'd appreciate any failing test cases!

llvm-svn: 104809
This commit is contained in:
Daniel Dunbar 2010-05-27 05:45:51 +00:00
parent 439edd1aea
commit 6da1098b4b
4 changed files with 147 additions and 28 deletions

View File

@ -297,7 +297,11 @@ class RecordLayoutBuilder {
llvm::SmallVector<uint64_t, 16> FieldOffsets;
/// Packed - Whether the record is packed or not.
bool Packed;
unsigned Packed : 1;
unsigned IsUnion : 1;
unsigned IsMac68kAlign : 1;
/// UnfilledBitsInLastByte - If the last field laid out was a bitfield,
/// this contains the number of bits in the last byte that can be used for
@ -311,8 +315,6 @@ class RecordLayoutBuilder {
/// DataSize - The data size of the record being laid out.
uint64_t DataSize;
bool IsUnion;
uint64_t NonVirtualSize;
unsigned NonVirtualAlignment;
@ -350,9 +352,10 @@ class RecordLayoutBuilder {
RecordLayoutBuilder(ASTContext &Context, EmptySubobjectMap *EmptySubobjects)
: Context(Context), EmptySubobjects(EmptySubobjects), Size(0), Alignment(8),
Packed(false), UnfilledBitsInLastByte(0), MaxFieldAlignment(0), DataSize(0),
IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8), PrimaryBase(0),
PrimaryBaseIsVirtual(false), FirstNearlyEmptyVBase(0) { }
Packed(false), IsUnion(false), IsMac68kAlign(false),
UnfilledBitsInLastByte(0), MaxFieldAlignment(0), DataSize(0),
NonVirtualSize(0), NonVirtualAlignment(8), PrimaryBase(0),
PrimaryBaseIsVirtual(false), FirstNearlyEmptyVBase(0) { }
void Layout(const RecordDecl *D);
void Layout(const CXXRecordDecl *D);
@ -423,7 +426,7 @@ class RecordLayoutBuilder {
void UpdateEmptyClassOffsets(const FieldDecl *FD, uint64_t Offset);
/// InitializeLayout - Initialize record layout for the given record decl.
void InitializeLayout(const RecordDecl *D);
void InitializeLayout(const Decl *D);
/// FinishLayout - Finalize record layout. Adjust record size based on the
/// alignment.
@ -942,16 +945,27 @@ RecordLayoutBuilder::UpdateEmptyClassOffsets(const FieldDecl *FD,
}
}
void RecordLayoutBuilder::InitializeLayout(const RecordDecl *D) {
IsUnion = D->isUnion();
void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
IsUnion = RD->isUnion();
Packed = D->hasAttr<PackedAttr>();
if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
MaxFieldAlignment = MFAA->getAlignment();
// mac68k alignment supersedes maximum field alignment and attribute aligned,
// and forces all structures to have 2-byte alignment. The IBM docs on it
// allude to additional (more complicated) semantics, especially with regard
// to bit-fields, but gcc appears not to follow that.
if (D->hasAttr<AlignMac68kAttr>()) {
IsMac68kAlign = true;
MaxFieldAlignment = 2 * 8;
Alignment = 2 * 8;
} else {
if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
MaxFieldAlignment = MFAA->getAlignment();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
UpdateAlignment(AA->getMaxAlignment());
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
UpdateAlignment(AA->getMaxAlignment());
}
}
void RecordLayoutBuilder::Layout(const RecordDecl *D) {
@ -1020,13 +1034,7 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
DataSize = Size;
}
Packed = D->hasAttr<PackedAttr>();
if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
MaxFieldAlignment = MFAA->getAlignment();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
UpdateAlignment(AA->getMaxAlignment());
InitializeLayout(D);
// Layout each ivar sequentially.
llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
@ -1239,6 +1247,10 @@ void RecordLayoutBuilder::FinishLayout() {
}
void RecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) {
// The alignment is not modified when using 'mac68k' alignment.
if (IsMac68kAlign)
return;
if (NewAlignment <= Alignment)
return;

View File

@ -25,6 +25,10 @@ using namespace clang;
namespace {
struct PackStackEntry {
// We just use a sentinel to represent when the stack is set to mac68k
// alignment.
static const unsigned kMac68kAlignmentSentinel = ~0U;
unsigned Alignment;
IdentifierInfo *Name;
};
@ -102,8 +106,12 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext);
// Otherwise, check to see if we need a max field alignment attribute.
if (unsigned Alignment = Stack->getAlignment())
RD->addAttr(::new (Context) MaxFieldAlignmentAttr(Alignment * 8));
if (unsigned Alignment = Stack->getAlignment()) {
if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
RD->addAttr(::new (Context) AlignMac68kAttr());
else
RD->addAttr(::new (Context) MaxFieldAlignmentAttr(Alignment * 8));
}
}
void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
@ -139,11 +147,9 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
return;
} else {
// Otherwise, just warn about it for now.
Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
<< KindLoc;
}
Context->push(0);
Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
break;
default:
@ -195,7 +201,10 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
// FIXME: This should come from the target.
if (AlignmentVal == 0)
AlignmentVal = 8;
Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel)
Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
else
Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
break;
case Action::PPK_Push: // pack(push [, id] [, [n])

View File

@ -8,5 +8,5 @@
#pragma options align=natural
#pragma options align=reset
/* expected-warning {{unsupported alignment option}} */ #pragma options align=mac68k
#pragma options align=mac68k
/* expected-warning {{unsupported alignment option}} */ #pragma options align=power

View File

@ -0,0 +1,98 @@
// RUN: %clang-cc1 -triple i386-apple-darwin9 -fsyntax-only -verify %s
#include <stddef.h>
#pragma options align=mac68k
typedef float __attribute__((vector_size (8))) v2f_t;
typedef float __attribute__((vector_size (16))) v4f_t;
extern int a0_0[__alignof(v2f_t) == 8 ? 1 : -1];
extern int a0_1[__alignof(v4f_t) == 16 ? 1 : -1];
struct s1 {
char f0;
int f1;
};
extern int a1_0[offsetof(struct s1, f0) == 0 ? 1 : -1];
extern int a1_1[offsetof(struct s1, f1) == 2 ? 1 : -1];
extern int a1_2[sizeof(struct s1) == 6 ? 1 : -1];
extern int a1_3[__alignof(struct s1) == 2 ? 1 : -1];
struct s2 {
char f0;
double f1;
};
extern int a2_0[offsetof(struct s2, f0) == 0 ? 1 : -1];
extern int a2_1[offsetof(struct s2, f1) == 2 ? 1 : -1];
extern int a2_2[sizeof(struct s2) == 10 ? 1 : -1];
extern int a2_3[__alignof(struct s2) == 2 ? 1 : -1];
struct s3 {
char f0;
v4f_t f1;
};
extern int a3_0[offsetof(struct s3, f0) == 0 ? 1 : -1];
extern int a3_1[offsetof(struct s3, f1) == 2 ? 1 : -1];
extern int a3_2[sizeof(struct s3) == 18 ? 1 : -1];
extern int a3_3[__alignof(struct s3) == 2 ? 1 : -1];
struct s4 {
char f0;
char f1;
};
extern int a4_0[offsetof(struct s4, f0) == 0 ? 1 : -1];
extern int a4_1[offsetof(struct s4, f1) == 1 ? 1 : -1];
extern int a4_2[sizeof(struct s4) == 2 ? 1 : -1];
extern int a4_3[__alignof(struct s4) == 2 ? 1 : -1];
struct s5 {
unsigned f0 : 9;
unsigned f1 : 9;
};
extern int a5_0[sizeof(struct s5) == 4 ? 1 : -1];
extern int a5_1[__alignof(struct s5) == 2 ? 1 : -1];
struct s6 {
unsigned : 0;
unsigned : 0;
};
extern int a6_0[sizeof(struct s6) == 0 ? 1 : -1];
extern int a6_1[__alignof(struct s6) == 2 ? 1 : -1];
struct s7 {
char : 1;
unsigned : 1;
};
extern int a7_0[sizeof(struct s7) == 2 ? 1 : -1];
extern int a7_1[__alignof(struct s7) == 2 ? 1 : -1];
struct s8 {
char f0;
unsigned : 1;
};
extern int a8_0[sizeof(struct s8) == 2 ? 1 : -1];
extern int a8_1[__alignof(struct s8) == 2 ? 1 : -1];
struct s9 {
char f0[3];
unsigned : 0;
char f1;
};
extern int a9_0[sizeof(struct s9) == 6 ? 1 : -1];
extern int a9_1[__alignof(struct s9) == 2 ? 1 : -1];
struct s10 {
char f0;
};
extern int a10_0[sizeof(struct s10) == 2 ? 1 : -1];
extern int a10_1[__alignof(struct s10) == 2 ? 1 : -1];
struct s11 {
char f0;
v2f_t f1;
};
extern int a11_0[offsetof(struct s11, f0) == 0 ? 1 : -1];
extern int a11_1[offsetof(struct s11, f1) == 2 ? 1 : -1];
extern int a11_2[sizeof(struct s11) == 10 ? 1 : -1];
extern int a11_3[__alignof(struct s11) == 2 ? 1 : -1];