2010-03-31 08:11:27 +08:00
|
|
|
//===--- CGRecordLayoutBuilder.cpp - CGRecordLayout builder ----*- C++ -*-===//
|
2009-07-23 11:17:50 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2009-07-23 11:17:50 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2010-03-31 08:11:27 +08:00
|
|
|
// Builder implementation for CGRecordLayout objects.
|
2009-07-23 11:17:50 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-03-31 06:26:10 +08:00
|
|
|
#include "CGRecordLayout.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "CGCXXABI.h"
|
|
|
|
#include "CodeGenTypes.h"
|
2009-07-23 11:17:50 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
|
|
|
#include "clang/AST/Attr.h"
|
2010-11-25 06:50:27 +08:00
|
|
|
#include "clang/AST/CXXInheritance.h"
|
2009-07-23 11:17:50 +08:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
|
|
|
#include "clang/AST/Expr.h"
|
|
|
|
#include "clang/AST/RecordLayout.h"
|
2018-12-11 11:18:39 +08:00
|
|
|
#include "clang/Basic/CodeGenOptions.h"
|
2013-01-02 19:45:17 +08:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
|
|
#include "llvm/IR/Type.h"
|
2010-04-22 03:10:49 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2010-04-13 02:14:18 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2009-07-23 11:17:50 +08:00
|
|
|
using namespace clang;
|
|
|
|
using namespace CodeGen;
|
|
|
|
|
2010-12-01 07:17:27 +08:00
|
|
|
namespace {
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
/// The CGRecordLowering is responsible for lowering an ASTRecordLayout to an
|
|
|
|
/// llvm::Type. Some of the lowering is straightforward, some is not. Here we
|
|
|
|
/// detail some of the complexities and weirdnesses here.
|
|
|
|
/// * LLVM does not have unions - Unions can, in theory be represented by any
|
|
|
|
/// llvm::Type with correct size. We choose a field via a specific heuristic
|
|
|
|
/// and add padding if necessary.
|
|
|
|
/// * LLVM does not have bitfields - Bitfields are collected into contiguous
|
|
|
|
/// runs and allocated as a single storage type for the run. ASTRecordLayout
|
|
|
|
/// contains enough information to determine where the runs break. Microsoft
|
|
|
|
/// and Itanium follow different rules and use different codepaths.
|
|
|
|
/// * It is desired that, when possible, bitfields use the appropriate iN type
|
|
|
|
/// when lowered to llvm types. For example unsigned x : 24 gets lowered to
|
|
|
|
/// i24. This isn't always possible because i24 has storage size of 32 bit
|
|
|
|
/// and if it is possible to use that extra byte of padding we must use
|
|
|
|
/// [i8 x 3] instead of i24. The function clipTailPadding does this.
|
|
|
|
/// C++ examples that require clipping:
|
|
|
|
/// struct { int a : 24; char b; }; // a must be clipped, b goes at offset 3
|
|
|
|
/// struct A { int a : 24; }; // a must be clipped because a struct like B
|
|
|
|
// could exist: struct B : A { char b; }; // b goes at offset 3
|
|
|
|
/// * Clang ignores 0 sized bitfields and 0 sized bases but *not* zero sized
|
|
|
|
/// fields. The existing asserts suggest that LLVM assumes that *every* field
|
|
|
|
/// has an underlying storage type. Therefore empty structures containing
|
|
|
|
/// zero sized subobjects such as empty records or zero sized arrays still get
|
|
|
|
/// a zero sized (empty struct) storage type.
|
|
|
|
/// * Clang reads the complete type rather than the base type when generating
|
|
|
|
/// code to access fields. Bitfields in tail position with tail padding may
|
|
|
|
/// be clipped in the base class but not the complete class (we may discover
|
|
|
|
/// that the tail padding is not used in the complete class.) However,
|
|
|
|
/// because LLVM reads from the complete type it can generate incorrect code
|
|
|
|
/// if we do not clip the tail padding off of the bitfield in the complete
|
|
|
|
/// layout. This introduces a somewhat awkward extra unnecessary clip stage.
|
2018-04-06 23:14:32 +08:00
|
|
|
/// The location of the clip is stored internally as a sentinel of type
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
/// SCISSOR. If LLVM were updated to read base types (which it probably
|
|
|
|
/// should because locations of things such as VBases are bogus in the llvm
|
|
|
|
/// type anyway) then we could eliminate the SCISSOR.
|
|
|
|
/// * Itanium allows nearly empty primary virtual bases. These bases don't get
|
|
|
|
/// get their own storage because they're laid out as part of another base
|
|
|
|
/// or at the beginning of the structure. Determining if a VBase actually
|
|
|
|
/// gets storage awkwardly involves a walk of all bases.
|
|
|
|
/// * VFPtrs and VBPtrs do *not* make a record NotZeroInitializable.
|
|
|
|
struct CGRecordLowering {
|
|
|
|
// MemberInfo is a helper structure that contains information about a record
|
|
|
|
// member. In additional to the standard member types, there exists a
|
2018-04-06 23:14:32 +08:00
|
|
|
// sentinel member type that ensures correct rounding.
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
struct MemberInfo {
|
|
|
|
CharUnits Offset;
|
|
|
|
enum InfoKind { VFPtr, VBPtr, Field, Base, VBase, Scissor } Kind;
|
|
|
|
llvm::Type *Data;
|
|
|
|
union {
|
|
|
|
const FieldDecl *FD;
|
|
|
|
const CXXRecordDecl *RD;
|
|
|
|
};
|
|
|
|
MemberInfo(CharUnits Offset, InfoKind Kind, llvm::Type *Data,
|
2014-05-21 13:09:00 +08:00
|
|
|
const FieldDecl *FD = nullptr)
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
: Offset(Offset), Kind(Kind), Data(Data), FD(FD) {}
|
|
|
|
MemberInfo(CharUnits Offset, InfoKind Kind, llvm::Type *Data,
|
|
|
|
const CXXRecordDecl *RD)
|
|
|
|
: Offset(Offset), Kind(Kind), Data(Data), RD(RD) {}
|
|
|
|
// MemberInfos are sorted so we define a < operator.
|
|
|
|
bool operator <(const MemberInfo& a) const { return Offset < a.Offset; }
|
|
|
|
};
|
|
|
|
// The constructor.
|
2014-09-28 14:39:30 +08:00
|
|
|
CGRecordLowering(CodeGenTypes &Types, const RecordDecl *D, bool Packed);
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
// Short helper routines.
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Constructs a MemberInfo instance from an offset and llvm::Type *.
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
MemberInfo StorageInfo(CharUnits Offset, llvm::Type *Data) {
|
|
|
|
return MemberInfo(Offset, MemberInfo::Field, Data);
|
|
|
|
}
|
2015-04-28 08:17:18 +08:00
|
|
|
|
|
|
|
/// The Microsoft bitfield layout rule allocates discrete storage
|
|
|
|
/// units of the field's formal type and only combines adjacent
|
|
|
|
/// fields of the same formal type. We want to emit a layout with
|
|
|
|
/// these discrete storage units instead of combining them into a
|
|
|
|
/// continuous run.
|
|
|
|
bool isDiscreteBitFieldABI() {
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
return Context.getTargetInfo().getCXXABI().isMicrosoft() ||
|
|
|
|
D->isMsStruct(Context);
|
|
|
|
}
|
2015-04-28 08:17:18 +08:00
|
|
|
|
[ARM] Follow AACPS standard for volatile bit-fields access width
This patch resumes the work of D16586.
According to the AAPCS, volatile bit-fields should
be accessed using containers of the widht of their
declarative type. In such case:
```
struct S1 {
short a : 1;
}
```
should be accessed using load and stores of the width
(sizeof(short)), where now the compiler does only load
the minimum required width (char in this case).
However, as discussed in D16586,
that could overwrite non-volatile bit-fields, which
conflicted with C and C++ object models by creating
data race conditions that are not part of the bit-field,
e.g.
```
struct S2 {
short a;
int b : 16;
}
```
Accessing `S2.b` would also access `S2.a`.
The AAPCS Release 2020Q2
(https://documentation-service.arm.com/static/5efb7fbedbdee951c1ccf186?token=)
section 8.1 Data Types, page 36, "Volatile bit-fields -
preserving number and width of container accesses" has been
updated to avoid conflict with the C++ Memory Model.
Now it reads in the note:
```
This ABI does not place any restrictions on the access widths of bit-fields where the container
overlaps with a non-bit-field member or where the container overlaps with any zero length bit-field
placed between two other bit-fields. This is because the C/C++ memory model defines these as being
separate memory locations, which can be accessed by two threads simultaneously. For this reason,
compilers must be permitted to use a narrower memory access width (including splitting the access into
multiple instructions) to avoid writing to a different memory location. For example, in
struct S { int a:24; char b; }; a write to a must not also write to the location occupied by b, this requires at least two
memory accesses in all current Arm architectures. In the same way, in struct S { int a:24; int:0; int b:8; };,
writes to a or b must not overwrite each other.
```
I've updated the patch D16586 to follow such behavior by verifying that we
only change volatile bit-field access when:
- it won't overlap with any other non-bit-field member
- we only access memory inside the bounds of the record
- avoid overlapping zero-length bit-fields.
Regarding the number of memory accesses, that should be preserved, that will
be implemented by D67399.
Reviewed By: ostannard
Differential Revision: https://reviews.llvm.org/D72932
2020-09-30 21:44:27 +08:00
|
|
|
/// Helper function to check if we are targeting AAPCS.
|
|
|
|
bool isAAPCS() const {
|
|
|
|
return Context.getTargetInfo().getABI().startswith("aapcs");
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Helper function to check if the target machine is BigEndian.
|
|
|
|
bool isBE() const { return Context.getTargetInfo().isBigEndian(); }
|
|
|
|
|
2015-04-28 08:17:18 +08:00
|
|
|
/// The Itanium base layout rule allows virtual bases to overlap
|
|
|
|
/// other bases, which complicates layout in specific ways.
|
|
|
|
///
|
|
|
|
/// Note specifically that the ms_struct attribute doesn't change this.
|
|
|
|
bool isOverlappingVBaseABI() {
|
|
|
|
return !Context.getTargetInfo().getCXXABI().isMicrosoft();
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Wraps llvm::Type::getIntNTy with some implicit arguments.
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
llvm::Type *getIntNType(uint64_t NumBits) {
|
|
|
|
return llvm::Type::getIntNTy(Types.getLLVMContext(),
|
2016-01-15 05:00:27 +08:00
|
|
|
(unsigned)llvm::alignTo(NumBits, 8));
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
}
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Gets an llvm type of size NumBytes and alignment 1.
|
2014-02-22 08:41:07 +08:00
|
|
|
llvm::Type *getByteArrayType(CharUnits NumBytes) {
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
assert(!NumBytes.isZero() && "Empty byte arrays aren't allowed.");
|
|
|
|
llvm::Type *Type = llvm::Type::getInt8Ty(Types.getLLVMContext());
|
|
|
|
return NumBytes == CharUnits::One() ? Type :
|
|
|
|
(llvm::Type *)llvm::ArrayType::get(Type, NumBytes.getQuantity());
|
|
|
|
}
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Gets the storage type for a field decl and handles storage
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
/// for itanium bitfields that are smaller than their declared type.
|
|
|
|
llvm::Type *getStorageType(const FieldDecl *FD) {
|
|
|
|
llvm::Type *Type = Types.ConvertTypeForMem(FD->getType());
|
2015-04-28 08:17:18 +08:00
|
|
|
if (!FD->isBitField()) return Type;
|
|
|
|
if (isDiscreteBitFieldABI()) return Type;
|
|
|
|
return getIntNType(std::min(FD->getBitWidthValue(Context),
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
(unsigned)Context.toBits(getSize(Type))));
|
|
|
|
}
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Gets the llvm Basesubobject type from a CXXRecordDecl.
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
llvm::Type *getStorageType(const CXXRecordDecl *RD) {
|
|
|
|
return Types.getCGRecordLayout(RD).getBaseSubobjectLLVMType();
|
|
|
|
}
|
|
|
|
CharUnits bitsToCharUnits(uint64_t BitOffset) {
|
|
|
|
return Context.toCharUnitsFromBits(BitOffset);
|
|
|
|
}
|
|
|
|
CharUnits getSize(llvm::Type *Type) {
|
|
|
|
return CharUnits::fromQuantity(DataLayout.getTypeAllocSize(Type));
|
|
|
|
}
|
|
|
|
CharUnits getAlignment(llvm::Type *Type) {
|
|
|
|
return CharUnits::fromQuantity(DataLayout.getABITypeAlignment(Type));
|
|
|
|
}
|
|
|
|
bool isZeroInitializable(const FieldDecl *FD) {
|
2015-05-27 05:28:50 +08:00
|
|
|
return Types.isZeroInitializable(FD->getType());
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
}
|
|
|
|
bool isZeroInitializable(const RecordDecl *RD) {
|
2015-05-27 05:28:50 +08:00
|
|
|
return Types.isZeroInitializable(RD);
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
}
|
|
|
|
void appendPaddingBytes(CharUnits Size) {
|
|
|
|
if (!Size.isZero())
|
|
|
|
FieldTypes.push_back(getByteArrayType(Size));
|
|
|
|
}
|
|
|
|
uint64_t getFieldBitOffset(const FieldDecl *FD) {
|
|
|
|
return Layout.getFieldOffset(FD->getFieldIndex());
|
|
|
|
}
|
|
|
|
// Layout routines.
|
2018-07-31 03:24:48 +08:00
|
|
|
void setBitFieldInfo(const FieldDecl *FD, CharUnits StartOffset,
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
llvm::Type *StorageType);
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Lowers an ASTRecordLayout to a llvm type.
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void lower(bool NonVirtualBaseType);
|
|
|
|
void lowerUnion();
|
|
|
|
void accumulateFields();
|
|
|
|
void accumulateBitFields(RecordDecl::field_iterator Field,
|
[ARM] Follow AACPS standard for volatile bit-fields access width
This patch resumes the work of D16586.
According to the AAPCS, volatile bit-fields should
be accessed using containers of the widht of their
declarative type. In such case:
```
struct S1 {
short a : 1;
}
```
should be accessed using load and stores of the width
(sizeof(short)), where now the compiler does only load
the minimum required width (char in this case).
However, as discussed in D16586,
that could overwrite non-volatile bit-fields, which
conflicted with C and C++ object models by creating
data race conditions that are not part of the bit-field,
e.g.
```
struct S2 {
short a;
int b : 16;
}
```
Accessing `S2.b` would also access `S2.a`.
The AAPCS Release 2020Q2
(https://documentation-service.arm.com/static/5efb7fbedbdee951c1ccf186?token=)
section 8.1 Data Types, page 36, "Volatile bit-fields -
preserving number and width of container accesses" has been
updated to avoid conflict with the C++ Memory Model.
Now it reads in the note:
```
This ABI does not place any restrictions on the access widths of bit-fields where the container
overlaps with a non-bit-field member or where the container overlaps with any zero length bit-field
placed between two other bit-fields. This is because the C/C++ memory model defines these as being
separate memory locations, which can be accessed by two threads simultaneously. For this reason,
compilers must be permitted to use a narrower memory access width (including splitting the access into
multiple instructions) to avoid writing to a different memory location. For example, in
struct S { int a:24; char b; }; a write to a must not also write to the location occupied by b, this requires at least two
memory accesses in all current Arm architectures. In the same way, in struct S { int a:24; int:0; int b:8; };,
writes to a or b must not overwrite each other.
```
I've updated the patch D16586 to follow such behavior by verifying that we
only change volatile bit-field access when:
- it won't overlap with any other non-bit-field member
- we only access memory inside the bounds of the record
- avoid overlapping zero-length bit-fields.
Regarding the number of memory accesses, that should be preserved, that will
be implemented by D67399.
Reviewed By: ostannard
Differential Revision: https://reviews.llvm.org/D72932
2020-09-30 21:44:27 +08:00
|
|
|
RecordDecl::field_iterator FieldEnd);
|
|
|
|
void computeVolatileBitfields();
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void accumulateBases();
|
|
|
|
void accumulateVPtrs();
|
|
|
|
void accumulateVBases();
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Recursively searches all of the bases to find out if a vbase is
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
/// not the primary vbase of some base class.
|
|
|
|
bool hasOwnStorage(const CXXRecordDecl *Decl, const CXXRecordDecl *Query);
|
|
|
|
void calculateZeroInit();
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Lowers bitfield storage types to I8 arrays for bitfields with tail
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
/// padding that is or can potentially be used.
|
|
|
|
void clipTailPadding();
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Determines if we need a packed llvm struct.
|
2014-09-28 14:39:30 +08:00
|
|
|
void determinePacked(bool NVBaseType);
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Inserts padding everywhere it's needed.
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void insertPadding();
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Fills out the structures that are ultimately consumed.
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void fillOutputFields();
|
|
|
|
// Input memoization fields.
|
|
|
|
CodeGenTypes &Types;
|
|
|
|
const ASTContext &Context;
|
|
|
|
const RecordDecl *D;
|
|
|
|
const CXXRecordDecl *RD;
|
|
|
|
const ASTRecordLayout &Layout;
|
|
|
|
const llvm::DataLayout &DataLayout;
|
|
|
|
// Helpful intermediate data-structures.
|
|
|
|
std::vector<MemberInfo> Members;
|
|
|
|
// Output fields, consumed by CodeGenTypes::ComputeRecordLayout.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<llvm::Type *, 16> FieldTypes;
|
2011-02-15 14:40:56 +08:00
|
|
|
llvm::DenseMap<const FieldDecl *, unsigned> Fields;
|
|
|
|
llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields;
|
|
|
|
llvm::DenseMap<const CXXRecordDecl *, unsigned> NonVirtualBases;
|
|
|
|
llvm::DenseMap<const CXXRecordDecl *, unsigned> VirtualBases;
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
bool IsZeroInitializable : 1;
|
|
|
|
bool IsZeroInitializableAsBase : 1;
|
|
|
|
bool Packed : 1;
|
2010-03-31 08:11:27 +08:00
|
|
|
private:
|
2015-02-16 06:54:08 +08:00
|
|
|
CGRecordLowering(const CGRecordLowering &) = delete;
|
|
|
|
void operator =(const CGRecordLowering &) = delete;
|
2010-03-31 08:11:27 +08:00
|
|
|
};
|
2015-06-23 07:07:51 +08:00
|
|
|
} // namespace {
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
|
2018-04-13 04:46:31 +08:00
|
|
|
CGRecordLowering::CGRecordLowering(CodeGenTypes &Types, const RecordDecl *D,
|
|
|
|
bool Packed)
|
|
|
|
: Types(Types), Context(Types.getContext()), D(D),
|
|
|
|
RD(dyn_cast<CXXRecordDecl>(D)),
|
|
|
|
Layout(Types.getContext().getASTRecordLayout(D)),
|
|
|
|
DataLayout(Types.getDataLayout()), IsZeroInitializable(true),
|
|
|
|
IsZeroInitializableAsBase(true), Packed(Packed) {}
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
|
|
|
|
void CGRecordLowering::setBitFieldInfo(
|
|
|
|
const FieldDecl *FD, CharUnits StartOffset, llvm::Type *StorageType) {
|
2014-04-19 11:48:30 +08:00
|
|
|
CGBitFieldInfo &Info = BitFields[FD->getCanonicalDecl()];
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
Info.IsSigned = FD->getType()->isSignedIntegerOrEnumerationType();
|
|
|
|
Info.Offset = (unsigned)(getFieldBitOffset(FD) - Context.toBits(StartOffset));
|
|
|
|
Info.Size = FD->getBitWidthValue(Context);
|
|
|
|
Info.StorageSize = (unsigned)DataLayout.getTypeAllocSizeInBits(StorageType);
|
Respect alignment of nested bitfields
tools/clang/test/CodeGen/packed-nest-unpacked.c contains this test:
struct XBitfield {
unsigned b1 : 10;
unsigned b2 : 12;
unsigned b3 : 10;
};
struct YBitfield {
char x;
struct XBitfield y;
} __attribute((packed));
struct YBitfield gbitfield;
unsigned test7() {
// CHECK: @test7
// CHECK: load i32, i32* getelementptr inbounds (%struct.YBitfield, %struct.YBitfield* @gbitfield, i32 0, i32 1, i32 0), align 4
return gbitfield.y.b2;
}
The "align 4" is actually wrong. Accessing all of "gbitfield.y" as a single
i32 is of course possible, but that still doesn't make it 4-byte aligned as
it remains packed at offset 1 in the surrounding gbitfield object.
This alignment was changed by commit r169489, which also introduced changes
to bitfield access code in CGExpr.cpp. Code before that change used to take
into account *both* the alignment of the field to be accessed within the
current struct, *and* the alignment of that outer struct itself; this logic
was removed by the above commit.
Neglecting to consider both values can cause incorrect code to be generated
(I've seen an unaligned access crash on SystemZ due to this bug).
In order to always use the best known alignment value, this patch removes
the CGBitFieldInfo::StorageAlignment member and replaces it with a
StorageOffset member specifying the offset from the start of the surrounding
struct to the bitfield's underlying storage. This offset can then be combined
with the best-known alignment for a bitfield access lvalue to determine the
alignment to use when accessing the bitfield's storage.
Differential Revision: http://reviews.llvm.org/D11034
llvm-svn: 241916
2015-07-11 01:30:00 +08:00
|
|
|
Info.StorageOffset = StartOffset;
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
if (Info.Size > Info.StorageSize)
|
|
|
|
Info.Size = Info.StorageSize;
|
2012-12-09 15:26:04 +08:00
|
|
|
// Reverse the bit offsets for big endian machines. Because we represent
|
|
|
|
// a bitfield as a single large integer load, we can imagine the bits
|
|
|
|
// counting from the most-significant-bit instead of the
|
|
|
|
// least-significant-bit.
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
if (DataLayout.isBigEndian())
|
|
|
|
Info.Offset = Info.StorageSize - (Info.Offset + Info.Size);
|
[ARM] Follow AACPS standard for volatile bit-fields access width
This patch resumes the work of D16586.
According to the AAPCS, volatile bit-fields should
be accessed using containers of the widht of their
declarative type. In such case:
```
struct S1 {
short a : 1;
}
```
should be accessed using load and stores of the width
(sizeof(short)), where now the compiler does only load
the minimum required width (char in this case).
However, as discussed in D16586,
that could overwrite non-volatile bit-fields, which
conflicted with C and C++ object models by creating
data race conditions that are not part of the bit-field,
e.g.
```
struct S2 {
short a;
int b : 16;
}
```
Accessing `S2.b` would also access `S2.a`.
The AAPCS Release 2020Q2
(https://documentation-service.arm.com/static/5efb7fbedbdee951c1ccf186?token=)
section 8.1 Data Types, page 36, "Volatile bit-fields -
preserving number and width of container accesses" has been
updated to avoid conflict with the C++ Memory Model.
Now it reads in the note:
```
This ABI does not place any restrictions on the access widths of bit-fields where the container
overlaps with a non-bit-field member or where the container overlaps with any zero length bit-field
placed between two other bit-fields. This is because the C/C++ memory model defines these as being
separate memory locations, which can be accessed by two threads simultaneously. For this reason,
compilers must be permitted to use a narrower memory access width (including splitting the access into
multiple instructions) to avoid writing to a different memory location. For example, in
struct S { int a:24; char b; }; a write to a must not also write to the location occupied by b, this requires at least two
memory accesses in all current Arm architectures. In the same way, in struct S { int a:24; int:0; int b:8; };,
writes to a or b must not overwrite each other.
```
I've updated the patch D16586 to follow such behavior by verifying that we
only change volatile bit-field access when:
- it won't overlap with any other non-bit-field member
- we only access memory inside the bounds of the record
- avoid overlapping zero-length bit-fields.
Regarding the number of memory accesses, that should be preserved, that will
be implemented by D67399.
Reviewed By: ostannard
Differential Revision: https://reviews.llvm.org/D72932
2020-09-30 21:44:27 +08:00
|
|
|
|
|
|
|
Info.VolatileStorageSize = 0;
|
|
|
|
Info.VolatileOffset = 0;
|
|
|
|
Info.VolatileStorageOffset = CharUnits::Zero();
|
2010-09-03 07:53:28 +08:00
|
|
|
}
|
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void CGRecordLowering::lower(bool NVBaseType) {
|
|
|
|
// The lowering process implemented in this function takes a variety of
|
|
|
|
// carefully ordered phases.
|
|
|
|
// 1) Store all members (fields and bases) in a list and sort them by offset.
|
|
|
|
// 2) Add a 1-byte capstone member at the Size of the structure.
|
|
|
|
// 3) Clip bitfield storages members if their tail padding is or might be
|
2018-07-31 03:24:48 +08:00
|
|
|
// used by another field or base. The clipping process uses the capstone
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
// by treating it as another object that occurs after the record.
|
|
|
|
// 4) Determine if the llvm-struct requires packing. It's important that this
|
|
|
|
// phase occur after clipping, because clipping changes the llvm type.
|
|
|
|
// This phase reads the offset of the capstone when determining packedness
|
|
|
|
// and updates the alignment of the capstone to be equal of the alignment
|
|
|
|
// of the record after doing so.
|
|
|
|
// 5) Insert padding everywhere it is needed. This phase requires 'Packed' to
|
|
|
|
// have been computed and needs to know the alignment of the record in
|
|
|
|
// order to understand if explicit tail padding is needed.
|
|
|
|
// 6) Remove the capstone, we don't need it anymore.
|
|
|
|
// 7) Determine if this record can be zero-initialized. This phase could have
|
|
|
|
// been placed anywhere after phase 1.
|
|
|
|
// 8) Format the complete list of members in a way that can be consumed by
|
|
|
|
// CodeGenTypes::ComputeRecordLayout.
|
|
|
|
CharUnits Size = NVBaseType ? Layout.getNonVirtualSize() : Layout.getSize();
|
[ARM] Follow AACPS standard for volatile bit-fields access width
This patch resumes the work of D16586.
According to the AAPCS, volatile bit-fields should
be accessed using containers of the widht of their
declarative type. In such case:
```
struct S1 {
short a : 1;
}
```
should be accessed using load and stores of the width
(sizeof(short)), where now the compiler does only load
the minimum required width (char in this case).
However, as discussed in D16586,
that could overwrite non-volatile bit-fields, which
conflicted with C and C++ object models by creating
data race conditions that are not part of the bit-field,
e.g.
```
struct S2 {
short a;
int b : 16;
}
```
Accessing `S2.b` would also access `S2.a`.
The AAPCS Release 2020Q2
(https://documentation-service.arm.com/static/5efb7fbedbdee951c1ccf186?token=)
section 8.1 Data Types, page 36, "Volatile bit-fields -
preserving number and width of container accesses" has been
updated to avoid conflict with the C++ Memory Model.
Now it reads in the note:
```
This ABI does not place any restrictions on the access widths of bit-fields where the container
overlaps with a non-bit-field member or where the container overlaps with any zero length bit-field
placed between two other bit-fields. This is because the C/C++ memory model defines these as being
separate memory locations, which can be accessed by two threads simultaneously. For this reason,
compilers must be permitted to use a narrower memory access width (including splitting the access into
multiple instructions) to avoid writing to a different memory location. For example, in
struct S { int a:24; char b; }; a write to a must not also write to the location occupied by b, this requires at least two
memory accesses in all current Arm architectures. In the same way, in struct S { int a:24; int:0; int b:8; };,
writes to a or b must not overwrite each other.
```
I've updated the patch D16586 to follow such behavior by verifying that we
only change volatile bit-field access when:
- it won't overlap with any other non-bit-field member
- we only access memory inside the bounds of the record
- avoid overlapping zero-length bit-fields.
Regarding the number of memory accesses, that should be preserved, that will
be implemented by D67399.
Reviewed By: ostannard
Differential Revision: https://reviews.llvm.org/D72932
2020-09-30 21:44:27 +08:00
|
|
|
if (D->isUnion()) {
|
|
|
|
lowerUnion();
|
|
|
|
computeVolatileBitfields();
|
|
|
|
return;
|
|
|
|
}
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
accumulateFields();
|
|
|
|
// RD implies C++.
|
|
|
|
if (RD) {
|
|
|
|
accumulateVPtrs();
|
|
|
|
accumulateBases();
|
[ARM] Follow AACPS standard for volatile bit-fields access width
This patch resumes the work of D16586.
According to the AAPCS, volatile bit-fields should
be accessed using containers of the widht of their
declarative type. In such case:
```
struct S1 {
short a : 1;
}
```
should be accessed using load and stores of the width
(sizeof(short)), where now the compiler does only load
the minimum required width (char in this case).
However, as discussed in D16586,
that could overwrite non-volatile bit-fields, which
conflicted with C and C++ object models by creating
data race conditions that are not part of the bit-field,
e.g.
```
struct S2 {
short a;
int b : 16;
}
```
Accessing `S2.b` would also access `S2.a`.
The AAPCS Release 2020Q2
(https://documentation-service.arm.com/static/5efb7fbedbdee951c1ccf186?token=)
section 8.1 Data Types, page 36, "Volatile bit-fields -
preserving number and width of container accesses" has been
updated to avoid conflict with the C++ Memory Model.
Now it reads in the note:
```
This ABI does not place any restrictions on the access widths of bit-fields where the container
overlaps with a non-bit-field member or where the container overlaps with any zero length bit-field
placed between two other bit-fields. This is because the C/C++ memory model defines these as being
separate memory locations, which can be accessed by two threads simultaneously. For this reason,
compilers must be permitted to use a narrower memory access width (including splitting the access into
multiple instructions) to avoid writing to a different memory location. For example, in
struct S { int a:24; char b; }; a write to a must not also write to the location occupied by b, this requires at least two
memory accesses in all current Arm architectures. In the same way, in struct S { int a:24; int:0; int b:8; };,
writes to a or b must not overwrite each other.
```
I've updated the patch D16586 to follow such behavior by verifying that we
only change volatile bit-field access when:
- it won't overlap with any other non-bit-field member
- we only access memory inside the bounds of the record
- avoid overlapping zero-length bit-fields.
Regarding the number of memory accesses, that should be preserved, that will
be implemented by D67399.
Reviewed By: ostannard
Differential Revision: https://reviews.llvm.org/D72932
2020-09-30 21:44:27 +08:00
|
|
|
if (Members.empty()) {
|
|
|
|
appendPaddingBytes(Size);
|
|
|
|
computeVolatileBitfields();
|
|
|
|
return;
|
|
|
|
}
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
if (!NVBaseType)
|
|
|
|
accumulateVBases();
|
|
|
|
}
|
2019-04-24 22:43:05 +08:00
|
|
|
llvm::stable_sort(Members);
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
Members.push_back(StorageInfo(Size, getIntNType(8)));
|
|
|
|
clipTailPadding();
|
2014-09-28 14:39:30 +08:00
|
|
|
determinePacked(NVBaseType);
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
insertPadding();
|
|
|
|
Members.pop_back();
|
|
|
|
calculateZeroInit();
|
|
|
|
fillOutputFields();
|
[ARM] Follow AACPS standard for volatile bit-fields access width
This patch resumes the work of D16586.
According to the AAPCS, volatile bit-fields should
be accessed using containers of the widht of their
declarative type. In such case:
```
struct S1 {
short a : 1;
}
```
should be accessed using load and stores of the width
(sizeof(short)), where now the compiler does only load
the minimum required width (char in this case).
However, as discussed in D16586,
that could overwrite non-volatile bit-fields, which
conflicted with C and C++ object models by creating
data race conditions that are not part of the bit-field,
e.g.
```
struct S2 {
short a;
int b : 16;
}
```
Accessing `S2.b` would also access `S2.a`.
The AAPCS Release 2020Q2
(https://documentation-service.arm.com/static/5efb7fbedbdee951c1ccf186?token=)
section 8.1 Data Types, page 36, "Volatile bit-fields -
preserving number and width of container accesses" has been
updated to avoid conflict with the C++ Memory Model.
Now it reads in the note:
```
This ABI does not place any restrictions on the access widths of bit-fields where the container
overlaps with a non-bit-field member or where the container overlaps with any zero length bit-field
placed between two other bit-fields. This is because the C/C++ memory model defines these as being
separate memory locations, which can be accessed by two threads simultaneously. For this reason,
compilers must be permitted to use a narrower memory access width (including splitting the access into
multiple instructions) to avoid writing to a different memory location. For example, in
struct S { int a:24; char b; }; a write to a must not also write to the location occupied by b, this requires at least two
memory accesses in all current Arm architectures. In the same way, in struct S { int a:24; int:0; int b:8; };,
writes to a or b must not overwrite each other.
```
I've updated the patch D16586 to follow such behavior by verifying that we
only change volatile bit-field access when:
- it won't overlap with any other non-bit-field member
- we only access memory inside the bounds of the record
- avoid overlapping zero-length bit-fields.
Regarding the number of memory accesses, that should be preserved, that will
be implemented by D67399.
Reviewed By: ostannard
Differential Revision: https://reviews.llvm.org/D72932
2020-09-30 21:44:27 +08:00
|
|
|
computeVolatileBitfields();
|
2009-07-23 11:17:50 +08:00
|
|
|
}
|
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void CGRecordLowering::lowerUnion() {
|
2014-03-01 08:38:40 +08:00
|
|
|
CharUnits LayoutSize = Layout.getSize();
|
2014-05-21 13:09:00 +08:00
|
|
|
llvm::Type *StorageType = nullptr;
|
2014-10-15 15:57:41 +08:00
|
|
|
bool SeenNamedMember = false;
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
// Iterate through the fields setting bitFieldInfo and the Fields array. Also
|
|
|
|
// locate the "most appropriate" storage type. The heuristic for finding the
|
|
|
|
// storage type isn't necessary, the first (non-0-length-bitfield) field's
|
2014-10-15 15:57:38 +08:00
|
|
|
// type would work fine and be simpler but would be different than what we've
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
// been doing and cause lit tests to change.
|
2014-03-09 04:12:42 +08:00
|
|
|
for (const auto *Field : D->fields()) {
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
if (Field->isBitField()) {
|
2018-04-03 02:29:43 +08:00
|
|
|
if (Field->isZeroLengthBitField(Context))
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
continue;
|
2014-03-09 04:12:42 +08:00
|
|
|
llvm::Type *FieldType = getStorageType(Field);
|
2014-03-01 08:38:40 +08:00
|
|
|
if (LayoutSize < getSize(FieldType))
|
|
|
|
FieldType = getByteArrayType(LayoutSize);
|
2014-03-09 04:12:42 +08:00
|
|
|
setBitFieldInfo(Field, CharUnits::Zero(), FieldType);
|
2009-08-09 03:38:24 +08:00
|
|
|
}
|
2014-04-19 11:48:30 +08:00
|
|
|
Fields[Field->getCanonicalDecl()] = 0;
|
2014-03-09 04:12:42 +08:00
|
|
|
llvm::Type *FieldType = getStorageType(Field);
|
2014-10-16 00:36:11 +08:00
|
|
|
// Compute zero-initializable status.
|
2014-10-15 15:57:41 +08:00
|
|
|
// This union might not be zero initialized: it may contain a pointer to
|
|
|
|
// data member which might have some exotic initialization sequence.
|
|
|
|
// If this is the case, then we aught not to try and come up with a "better"
|
|
|
|
// type, it might not be very easy to come up with a Constant which
|
|
|
|
// correctly initializes it.
|
2015-05-30 17:12:07 +08:00
|
|
|
if (!SeenNamedMember) {
|
|
|
|
SeenNamedMember = Field->getIdentifier();
|
|
|
|
if (!SeenNamedMember)
|
2018-07-28 10:16:13 +08:00
|
|
|
if (const auto *FieldRD = Field->getType()->getAsRecordDecl())
|
|
|
|
SeenNamedMember = FieldRD->findFirstNamedDataMember();
|
2015-05-30 17:12:07 +08:00
|
|
|
if (SeenNamedMember && !isZeroInitializable(Field)) {
|
2014-10-16 00:36:11 +08:00
|
|
|
IsZeroInitializable = IsZeroInitializableAsBase = false;
|
2014-10-15 15:57:41 +08:00
|
|
|
StorageType = FieldType;
|
|
|
|
}
|
|
|
|
}
|
2014-10-16 00:36:11 +08:00
|
|
|
// Because our union isn't zero initializable, we won't be getting a better
|
|
|
|
// storage type.
|
|
|
|
if (!IsZeroInitializable)
|
|
|
|
continue;
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
// Conditionally update our storage type if we've got a new "better" one.
|
|
|
|
if (!StorageType ||
|
|
|
|
getAlignment(FieldType) > getAlignment(StorageType) ||
|
|
|
|
(getAlignment(FieldType) == getAlignment(StorageType) &&
|
|
|
|
getSize(FieldType) > getSize(StorageType)))
|
2014-10-16 00:36:11 +08:00
|
|
|
StorageType = FieldType;
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
}
|
|
|
|
// If we have no storage type just pad to the appropriate size and return.
|
|
|
|
if (!StorageType)
|
|
|
|
return appendPaddingBytes(LayoutSize);
|
|
|
|
// If our storage size was bigger than our required size (can happen in the
|
|
|
|
// case of packed bitfields on Itanium) then just use an I8 array.
|
|
|
|
if (LayoutSize < getSize(StorageType))
|
|
|
|
StorageType = getByteArrayType(LayoutSize);
|
|
|
|
FieldTypes.push_back(StorageType);
|
|
|
|
appendPaddingBytes(LayoutSize - getSize(StorageType));
|
|
|
|
// Set packed if we need it.
|
|
|
|
if (LayoutSize % getAlignment(StorageType))
|
|
|
|
Packed = true;
|
|
|
|
}
|
2009-08-05 00:29:15 +08:00
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void CGRecordLowering::accumulateFields() {
|
|
|
|
for (RecordDecl::field_iterator Field = D->field_begin(),
|
|
|
|
FieldEnd = D->field_end();
|
2019-06-21 04:44:45 +08:00
|
|
|
Field != FieldEnd;) {
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
if (Field->isBitField()) {
|
|
|
|
RecordDecl::field_iterator Start = Field;
|
|
|
|
// Iterate to gather the list of bitfields.
|
|
|
|
for (++Field; Field != FieldEnd && Field->isBitField(); ++Field);
|
|
|
|
accumulateBitFields(Start, Field);
|
2019-06-21 04:44:45 +08:00
|
|
|
} else if (!Field->isZeroSize(Context)) {
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
Members.push_back(MemberInfo(
|
|
|
|
bitsToCharUnits(getFieldBitOffset(*Field)), MemberInfo::Field,
|
|
|
|
getStorageType(*Field), *Field));
|
|
|
|
++Field;
|
2019-06-21 04:44:45 +08:00
|
|
|
} else {
|
|
|
|
++Field;
|
2011-04-18 05:56:13 +08:00
|
|
|
}
|
2019-06-21 04:44:45 +08:00
|
|
|
}
|
2009-07-23 11:17:50 +08:00
|
|
|
}
|
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void
|
|
|
|
CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
|
|
|
|
RecordDecl::field_iterator FieldEnd) {
|
|
|
|
// Run stores the first element of the current run of bitfields. FieldEnd is
|
|
|
|
// used as a special value to note that we don't have a current run. A
|
|
|
|
// bitfield run is a contiguous collection of bitfields that can be stored in
|
|
|
|
// the same storage block. Zero-sized bitfields and bitfields that would
|
|
|
|
// cross an alignment boundary break a run and start a new one.
|
|
|
|
RecordDecl::field_iterator Run = FieldEnd;
|
|
|
|
// Tail is the offset of the first bit off the end of the current run. It's
|
|
|
|
// used to determine if the ASTRecordLayout is treating these two bitfields as
|
|
|
|
// contiguous. StartBitOffset is offset of the beginning of the Run.
|
|
|
|
uint64_t StartBitOffset, Tail = 0;
|
2015-04-28 08:17:18 +08:00
|
|
|
if (isDiscreteBitFieldABI()) {
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
for (; Field != FieldEnd; ++Field) {
|
|
|
|
uint64_t BitOffset = getFieldBitOffset(*Field);
|
|
|
|
// Zero-width bitfields end runs.
|
2018-04-03 02:29:43 +08:00
|
|
|
if (Field->isZeroLengthBitField(Context)) {
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
Run = FieldEnd;
|
|
|
|
continue;
|
|
|
|
}
|
2020-04-18 01:44:19 +08:00
|
|
|
llvm::Type *Type =
|
|
|
|
Types.ConvertTypeForMem(Field->getType(), /*ForBitFields=*/true);
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
// If we don't have a run yet, or don't live within the previous run's
|
|
|
|
// allocated storage then we allocate some storage and start a new run.
|
|
|
|
if (Run == FieldEnd || BitOffset >= Tail) {
|
|
|
|
Run = Field;
|
|
|
|
StartBitOffset = BitOffset;
|
|
|
|
Tail = StartBitOffset + DataLayout.getTypeAllocSizeInBits(Type);
|
|
|
|
// Add the storage member to the record. This must be added to the
|
|
|
|
// record before the bitfield members so that it gets laid out before
|
|
|
|
// the bitfields it contains get laid out.
|
|
|
|
Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset), Type));
|
|
|
|
}
|
|
|
|
// Bitfields get the offset of their storage but come afterward and remain
|
|
|
|
// there after a stable sort.
|
|
|
|
Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset),
|
2014-05-21 13:09:00 +08:00
|
|
|
MemberInfo::Field, nullptr, *Field));
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
}
|
|
|
|
return;
|
2010-04-18 04:49:27 +08:00
|
|
|
}
|
2017-10-17 00:50:27 +08:00
|
|
|
|
2020-06-12 17:26:53 +08:00
|
|
|
// Check if OffsetInRecord (the size in bits of the current run) is better
|
|
|
|
// as a single field run. When OffsetInRecord has legal integer width, and
|
|
|
|
// its bitfield offset is naturally aligned, it is better to make the
|
|
|
|
// bitfield a separate storage component so as it can be accessed directly
|
|
|
|
// with lower cost.
|
2018-05-10 20:31:12 +08:00
|
|
|
auto IsBetterAsSingleFieldRun = [&](uint64_t OffsetInRecord,
|
|
|
|
uint64_t StartBitOffset) {
|
2017-10-17 00:50:27 +08:00
|
|
|
if (!Types.getCodeGenOpts().FineGrainedBitfieldAccesses)
|
|
|
|
return false;
|
2020-06-12 17:26:53 +08:00
|
|
|
if (OffsetInRecord < 8 || !llvm::isPowerOf2_64(OffsetInRecord) ||
|
|
|
|
!DataLayout.fitsInLegalInteger(OffsetInRecord))
|
2017-10-17 00:50:27 +08:00
|
|
|
return false;
|
[ARM] Follow AACPS standard for volatile bit-fields access width
This patch resumes the work of D16586.
According to the AAPCS, volatile bit-fields should
be accessed using containers of the widht of their
declarative type. In such case:
```
struct S1 {
short a : 1;
}
```
should be accessed using load and stores of the width
(sizeof(short)), where now the compiler does only load
the minimum required width (char in this case).
However, as discussed in D16586,
that could overwrite non-volatile bit-fields, which
conflicted with C and C++ object models by creating
data race conditions that are not part of the bit-field,
e.g.
```
struct S2 {
short a;
int b : 16;
}
```
Accessing `S2.b` would also access `S2.a`.
The AAPCS Release 2020Q2
(https://documentation-service.arm.com/static/5efb7fbedbdee951c1ccf186?token=)
section 8.1 Data Types, page 36, "Volatile bit-fields -
preserving number and width of container accesses" has been
updated to avoid conflict with the C++ Memory Model.
Now it reads in the note:
```
This ABI does not place any restrictions on the access widths of bit-fields where the container
overlaps with a non-bit-field member or where the container overlaps with any zero length bit-field
placed between two other bit-fields. This is because the C/C++ memory model defines these as being
separate memory locations, which can be accessed by two threads simultaneously. For this reason,
compilers must be permitted to use a narrower memory access width (including splitting the access into
multiple instructions) to avoid writing to a different memory location. For example, in
struct S { int a:24; char b; }; a write to a must not also write to the location occupied by b, this requires at least two
memory accesses in all current Arm architectures. In the same way, in struct S { int a:24; int:0; int b:8; };,
writes to a or b must not overwrite each other.
```
I've updated the patch D16586 to follow such behavior by verifying that we
only change volatile bit-field access when:
- it won't overlap with any other non-bit-field member
- we only access memory inside the bounds of the record
- avoid overlapping zero-length bit-fields.
Regarding the number of memory accesses, that should be preserved, that will
be implemented by D67399.
Reviewed By: ostannard
Differential Revision: https://reviews.llvm.org/D72932
2020-09-30 21:44:27 +08:00
|
|
|
// Make sure StartBitOffset is naturally aligned if it is treated as an
|
2018-05-10 20:31:12 +08:00
|
|
|
// IType integer.
|
[ARM] Follow AACPS standard for volatile bit-fields access width
This patch resumes the work of D16586.
According to the AAPCS, volatile bit-fields should
be accessed using containers of the widht of their
declarative type. In such case:
```
struct S1 {
short a : 1;
}
```
should be accessed using load and stores of the width
(sizeof(short)), where now the compiler does only load
the minimum required width (char in this case).
However, as discussed in D16586,
that could overwrite non-volatile bit-fields, which
conflicted with C and C++ object models by creating
data race conditions that are not part of the bit-field,
e.g.
```
struct S2 {
short a;
int b : 16;
}
```
Accessing `S2.b` would also access `S2.a`.
The AAPCS Release 2020Q2
(https://documentation-service.arm.com/static/5efb7fbedbdee951c1ccf186?token=)
section 8.1 Data Types, page 36, "Volatile bit-fields -
preserving number and width of container accesses" has been
updated to avoid conflict with the C++ Memory Model.
Now it reads in the note:
```
This ABI does not place any restrictions on the access widths of bit-fields where the container
overlaps with a non-bit-field member or where the container overlaps with any zero length bit-field
placed between two other bit-fields. This is because the C/C++ memory model defines these as being
separate memory locations, which can be accessed by two threads simultaneously. For this reason,
compilers must be permitted to use a narrower memory access width (including splitting the access into
multiple instructions) to avoid writing to a different memory location. For example, in
struct S { int a:24; char b; }; a write to a must not also write to the location occupied by b, this requires at least two
memory accesses in all current Arm architectures. In the same way, in struct S { int a:24; int:0; int b:8; };,
writes to a or b must not overwrite each other.
```
I've updated the patch D16586 to follow such behavior by verifying that we
only change volatile bit-field access when:
- it won't overlap with any other non-bit-field member
- we only access memory inside the bounds of the record
- avoid overlapping zero-length bit-fields.
Regarding the number of memory accesses, that should be preserved, that will
be implemented by D67399.
Reviewed By: ostannard
Differential Revision: https://reviews.llvm.org/D72932
2020-09-30 21:44:27 +08:00
|
|
|
if (StartBitOffset %
|
2018-05-10 20:31:12 +08:00
|
|
|
Context.toBits(getAlignment(getIntNType(OffsetInRecord))) !=
|
2017-10-17 00:50:27 +08:00
|
|
|
0)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
// The start field is better as a single field run.
|
|
|
|
bool StartFieldAsSingleRun = false;
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
for (;;) {
|
|
|
|
// Check to see if we need to start a new run.
|
|
|
|
if (Run == FieldEnd) {
|
|
|
|
// If we're out of fields, return.
|
|
|
|
if (Field == FieldEnd)
|
|
|
|
break;
|
|
|
|
// Any non-zero-length bitfield can start a new run.
|
2018-04-03 02:29:43 +08:00
|
|
|
if (!Field->isZeroLengthBitField(Context)) {
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
Run = Field;
|
|
|
|
StartBitOffset = getFieldBitOffset(*Field);
|
|
|
|
Tail = StartBitOffset + Field->getBitWidthValue(Context);
|
2018-05-10 20:31:12 +08:00
|
|
|
StartFieldAsSingleRun = IsBetterAsSingleFieldRun(Tail - StartBitOffset,
|
2018-07-31 03:24:48 +08:00
|
|
|
StartBitOffset);
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
}
|
|
|
|
++Field;
|
2010-04-18 04:49:27 +08:00
|
|
|
continue;
|
2011-12-07 09:30:11 +08:00
|
|
|
}
|
2017-10-17 00:50:27 +08:00
|
|
|
|
|
|
|
// If the start field of a new run is better as a single run, or
|
2018-05-10 20:31:12 +08:00
|
|
|
// if current field (or consecutive fields) is better as a single run, or
|
2018-02-01 11:04:15 +08:00
|
|
|
// if current field has zero width bitfield and either
|
|
|
|
// UseZeroLengthBitfieldAlignment or UseBitFieldTypeAlignment is set to
|
|
|
|
// true, or
|
2017-10-17 00:50:27 +08:00
|
|
|
// if the offset of current field is inconsistent with the offset of
|
|
|
|
// previous field plus its offset,
|
|
|
|
// skip the block below and go ahead to emit the storage.
|
|
|
|
// Otherwise, try to add bitfields to the run.
|
|
|
|
if (!StartFieldAsSingleRun && Field != FieldEnd &&
|
2018-05-10 20:31:12 +08:00
|
|
|
!IsBetterAsSingleFieldRun(Tail - StartBitOffset, StartBitOffset) &&
|
2018-04-03 02:29:43 +08:00
|
|
|
(!Field->isZeroLengthBitField(Context) ||
|
2018-02-01 11:04:15 +08:00
|
|
|
(!Context.getTargetInfo().useZeroLengthBitfieldAlignment() &&
|
|
|
|
!Context.getTargetInfo().useBitFieldTypeAlignment())) &&
|
2014-08-14 23:44:29 +08:00
|
|
|
Tail == getFieldBitOffset(*Field)) {
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
Tail += Field->getBitWidthValue(Context);
|
|
|
|
++Field;
|
2009-07-23 11:43:54 +08:00
|
|
|
continue;
|
|
|
|
}
|
2017-10-17 00:50:27 +08:00
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
// We've hit a break-point in the run and need to emit a storage field.
|
|
|
|
llvm::Type *Type = getIntNType(Tail - StartBitOffset);
|
|
|
|
// Add the storage member to the record and set the bitfield info for all of
|
|
|
|
// the bitfields in the run. Bitfields get the offset of their storage but
|
|
|
|
// come afterward and remain there after a stable sort.
|
|
|
|
Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset), Type));
|
|
|
|
for (; Run != Field; ++Run)
|
|
|
|
Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset),
|
2014-05-21 13:09:00 +08:00
|
|
|
MemberInfo::Field, nullptr, *Run));
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
Run = FieldEnd;
|
2017-10-17 00:50:27 +08:00
|
|
|
StartFieldAsSingleRun = false;
|
2009-07-23 11:43:54 +08:00
|
|
|
}
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void CGRecordLowering::accumulateBases() {
|
|
|
|
// If we've got a primary virtual base, we need to add it with the bases.
|
2014-04-26 05:56:30 +08:00
|
|
|
if (Layout.isPrimaryBaseVirtual()) {
|
|
|
|
const CXXRecordDecl *BaseDecl = Layout.getPrimaryBase();
|
|
|
|
Members.push_back(MemberInfo(CharUnits::Zero(), MemberInfo::Base,
|
|
|
|
getStorageType(BaseDecl), BaseDecl));
|
|
|
|
}
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
// Accumulate the non-virtual bases.
|
2014-03-13 23:41:46 +08:00
|
|
|
for (const auto &Base : RD->bases()) {
|
|
|
|
if (Base.isVirtual())
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
continue;
|
2015-04-26 12:43:26 +08:00
|
|
|
|
|
|
|
// Bases can be zero-sized even if not technically empty if they
|
|
|
|
// contain only a trailing array member.
|
2014-03-13 23:41:46 +08:00
|
|
|
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
|
2015-04-26 12:43:26 +08:00
|
|
|
if (!BaseDecl->isEmpty() &&
|
2015-10-23 02:04:22 +08:00
|
|
|
!Context.getASTRecordLayout(BaseDecl).getNonVirtualSize().isZero())
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
Members.push_back(MemberInfo(Layout.getBaseClassOffset(BaseDecl),
|
|
|
|
MemberInfo::Base, getStorageType(BaseDecl), BaseDecl));
|
2009-11-07 04:47:40 +08:00
|
|
|
}
|
2009-07-23 11:43:54 +08:00
|
|
|
}
|
|
|
|
|
[ARM] Follow AACPS standard for volatile bit-fields access width
This patch resumes the work of D16586.
According to the AAPCS, volatile bit-fields should
be accessed using containers of the widht of their
declarative type. In such case:
```
struct S1 {
short a : 1;
}
```
should be accessed using load and stores of the width
(sizeof(short)), where now the compiler does only load
the minimum required width (char in this case).
However, as discussed in D16586,
that could overwrite non-volatile bit-fields, which
conflicted with C and C++ object models by creating
data race conditions that are not part of the bit-field,
e.g.
```
struct S2 {
short a;
int b : 16;
}
```
Accessing `S2.b` would also access `S2.a`.
The AAPCS Release 2020Q2
(https://documentation-service.arm.com/static/5efb7fbedbdee951c1ccf186?token=)
section 8.1 Data Types, page 36, "Volatile bit-fields -
preserving number and width of container accesses" has been
updated to avoid conflict with the C++ Memory Model.
Now it reads in the note:
```
This ABI does not place any restrictions on the access widths of bit-fields where the container
overlaps with a non-bit-field member or where the container overlaps with any zero length bit-field
placed between two other bit-fields. This is because the C/C++ memory model defines these as being
separate memory locations, which can be accessed by two threads simultaneously. For this reason,
compilers must be permitted to use a narrower memory access width (including splitting the access into
multiple instructions) to avoid writing to a different memory location. For example, in
struct S { int a:24; char b; }; a write to a must not also write to the location occupied by b, this requires at least two
memory accesses in all current Arm architectures. In the same way, in struct S { int a:24; int:0; int b:8; };,
writes to a or b must not overwrite each other.
```
I've updated the patch D16586 to follow such behavior by verifying that we
only change volatile bit-field access when:
- it won't overlap with any other non-bit-field member
- we only access memory inside the bounds of the record
- avoid overlapping zero-length bit-fields.
Regarding the number of memory accesses, that should be preserved, that will
be implemented by D67399.
Reviewed By: ostannard
Differential Revision: https://reviews.llvm.org/D72932
2020-09-30 21:44:27 +08:00
|
|
|
/// The AAPCS that defines that, when possible, bit-fields should
|
|
|
|
/// be accessed using containers of the declared type width:
|
|
|
|
/// When a volatile bit-field is read, and its container does not overlap with
|
|
|
|
/// any non-bit-field member or any zero length bit-field member, its container
|
|
|
|
/// must be read exactly once using the access width appropriate to the type of
|
|
|
|
/// the container. When a volatile bit-field is written, and its container does
|
|
|
|
/// not overlap with any non-bit-field member or any zero-length bit-field
|
|
|
|
/// member, its container must be read exactly once and written exactly once
|
|
|
|
/// using the access width appropriate to the type of the container. The two
|
|
|
|
/// accesses are not atomic.
|
|
|
|
///
|
|
|
|
/// Enforcing the width restriction can be disabled using
|
|
|
|
/// -fno-aapcs-bitfield-width.
|
|
|
|
void CGRecordLowering::computeVolatileBitfields() {
|
|
|
|
if (!isAAPCS() || !Types.getCodeGenOpts().AAPCSBitfieldWidth)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (auto &I : BitFields) {
|
|
|
|
const FieldDecl *Field = I.first;
|
|
|
|
CGBitFieldInfo &Info = I.second;
|
|
|
|
llvm::Type *ResLTy = Types.ConvertTypeForMem(Field->getType());
|
|
|
|
// If the record alignment is less than the type width, we can't enforce a
|
|
|
|
// aligned load, bail out.
|
|
|
|
if ((uint64_t)(Context.toBits(Layout.getAlignment())) <
|
|
|
|
ResLTy->getPrimitiveSizeInBits())
|
|
|
|
continue;
|
|
|
|
// CGRecordLowering::setBitFieldInfo() pre-adjusts the bit-field offsets
|
|
|
|
// for big-endian targets, but it assumes a container of width
|
|
|
|
// Info.StorageSize. Since AAPCS uses a different container size (width
|
|
|
|
// of the type), we first undo that calculation here and redo it once
|
|
|
|
// the bit-field offset within the new container is calculated.
|
|
|
|
const unsigned OldOffset =
|
|
|
|
isBE() ? Info.StorageSize - (Info.Offset + Info.Size) : Info.Offset;
|
|
|
|
// Offset to the bit-field from the beginning of the struct.
|
|
|
|
const unsigned AbsoluteOffset =
|
|
|
|
Context.toBits(Info.StorageOffset) + OldOffset;
|
|
|
|
|
|
|
|
// Container size is the width of the bit-field type.
|
|
|
|
const unsigned StorageSize = ResLTy->getPrimitiveSizeInBits();
|
|
|
|
// Nothing to do if the access uses the desired
|
|
|
|
// container width and is naturally aligned.
|
|
|
|
if (Info.StorageSize == StorageSize && (OldOffset % StorageSize == 0))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Offset within the container.
|
|
|
|
unsigned Offset = AbsoluteOffset & (StorageSize - 1);
|
|
|
|
// Bail out if an aligned load of the container cannot cover the entire
|
|
|
|
// bit-field. This can happen for example, if the bit-field is part of a
|
|
|
|
// packed struct. AAPCS does not define access rules for such cases, we let
|
|
|
|
// clang to follow its own rules.
|
|
|
|
if (Offset + Info.Size > StorageSize)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Re-adjust offsets for big-endian targets.
|
|
|
|
if (isBE())
|
|
|
|
Offset = StorageSize - (Offset + Info.Size);
|
|
|
|
|
|
|
|
const CharUnits StorageOffset =
|
|
|
|
Context.toCharUnitsFromBits(AbsoluteOffset & ~(StorageSize - 1));
|
|
|
|
const CharUnits End = StorageOffset +
|
|
|
|
Context.toCharUnitsFromBits(StorageSize) -
|
|
|
|
CharUnits::One();
|
|
|
|
|
|
|
|
const ASTRecordLayout &Layout =
|
|
|
|
Context.getASTRecordLayout(Field->getParent());
|
|
|
|
// If we access outside memory outside the record, than bail out.
|
|
|
|
const CharUnits RecordSize = Layout.getSize();
|
|
|
|
if (End >= RecordSize)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Bail out if performing this load would access non-bit-fields members.
|
|
|
|
bool Conflict = false;
|
|
|
|
for (const auto *F : D->fields()) {
|
|
|
|
// Allow sized bit-fields overlaps.
|
|
|
|
if (F->isBitField() && !F->isZeroLengthBitField(Context))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const CharUnits FOffset = Context.toCharUnitsFromBits(
|
|
|
|
Layout.getFieldOffset(F->getFieldIndex()));
|
|
|
|
|
|
|
|
// As C11 defines, a zero sized bit-field defines a barrier, so
|
|
|
|
// fields after and before it should be race condition free.
|
|
|
|
// The AAPCS acknowledges it and imposes no restritions when the
|
|
|
|
// natural container overlaps a zero-length bit-field.
|
|
|
|
if (F->isZeroLengthBitField(Context)) {
|
|
|
|
if (End > FOffset && StorageOffset < FOffset) {
|
|
|
|
Conflict = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const CharUnits FEnd =
|
|
|
|
FOffset +
|
|
|
|
Context.toCharUnitsFromBits(
|
|
|
|
Types.ConvertTypeForMem(F->getType())->getPrimitiveSizeInBits()) -
|
|
|
|
CharUnits::One();
|
|
|
|
// If no overlap, continue.
|
|
|
|
if (End < FOffset || FEnd < StorageOffset)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// The desired load overlaps a non-bit-field member, bail out.
|
|
|
|
Conflict = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Conflict)
|
|
|
|
continue;
|
|
|
|
// Write the new bit-field access parameters.
|
|
|
|
// As the storage offset now is defined as the number of elements from the
|
|
|
|
// start of the structure, we should divide the Offset by the element size.
|
|
|
|
Info.VolatileStorageOffset =
|
|
|
|
StorageOffset / Context.toCharUnitsFromBits(StorageSize).getQuantity();
|
|
|
|
Info.VolatileStorageSize = StorageSize;
|
|
|
|
Info.VolatileOffset = Offset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void CGRecordLowering::accumulateVPtrs() {
|
|
|
|
if (Layout.hasOwnVFPtr())
|
|
|
|
Members.push_back(MemberInfo(CharUnits::Zero(), MemberInfo::VFPtr,
|
|
|
|
llvm::FunctionType::get(getIntNType(32), /*isVarArg=*/true)->
|
|
|
|
getPointerTo()->getPointerTo()));
|
|
|
|
if (Layout.hasOwnVBPtr())
|
|
|
|
Members.push_back(MemberInfo(Layout.getVBPtrOffset(), MemberInfo::VBPtr,
|
|
|
|
llvm::Type::getInt32PtrTy(Types.getLLVMContext())));
|
2010-12-05 07:59:48 +08:00
|
|
|
}
|
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void CGRecordLowering::accumulateVBases() {
|
2014-04-26 05:56:30 +08:00
|
|
|
CharUnits ScissorOffset = Layout.getNonVirtualSize();
|
|
|
|
// In the itanium ABI, it's possible to place a vbase at a dsize that is
|
|
|
|
// smaller than the nvsize. Here we check to see if such a base is placed
|
|
|
|
// before the nvsize and set the scissor offset to that, instead of the
|
|
|
|
// nvsize.
|
2015-04-28 08:17:18 +08:00
|
|
|
if (isOverlappingVBaseABI())
|
2014-04-26 05:56:30 +08:00
|
|
|
for (const auto &Base : RD->vbases()) {
|
|
|
|
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
|
|
|
|
if (BaseDecl->isEmpty())
|
|
|
|
continue;
|
|
|
|
// If the vbase is a primary virtual base of some base, then it doesn't
|
|
|
|
// get its own storage location but instead lives inside of that base.
|
|
|
|
if (Context.isNearlyEmpty(BaseDecl) && !hasOwnStorage(RD, BaseDecl))
|
|
|
|
continue;
|
|
|
|
ScissorOffset = std::min(ScissorOffset,
|
|
|
|
Layout.getVBaseClassOffset(BaseDecl));
|
|
|
|
}
|
2014-05-21 13:09:00 +08:00
|
|
|
Members.push_back(MemberInfo(ScissorOffset, MemberInfo::Scissor, nullptr,
|
|
|
|
RD));
|
2014-03-14 00:15:17 +08:00
|
|
|
for (const auto &Base : RD->vbases()) {
|
|
|
|
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
if (BaseDecl->isEmpty())
|
|
|
|
continue;
|
|
|
|
CharUnits Offset = Layout.getVBaseClassOffset(BaseDecl);
|
|
|
|
// If the vbase is a primary virtual base of some base, then it doesn't
|
|
|
|
// get its own storage location but instead lives inside of that base.
|
2015-04-28 08:17:18 +08:00
|
|
|
if (isOverlappingVBaseABI() &&
|
|
|
|
Context.isNearlyEmpty(BaseDecl) &&
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
!hasOwnStorage(RD, BaseDecl)) {
|
2014-05-21 13:09:00 +08:00
|
|
|
Members.push_back(MemberInfo(Offset, MemberInfo::VBase, nullptr,
|
|
|
|
BaseDecl));
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// If we've got a vtordisp, add it as a storage type.
|
|
|
|
if (Layout.getVBaseOffsetsMap().find(BaseDecl)->second.hasVtorDisp())
|
|
|
|
Members.push_back(StorageInfo(Offset - CharUnits::fromQuantity(4),
|
|
|
|
getIntNType(32)));
|
|
|
|
Members.push_back(MemberInfo(Offset, MemberInfo::VBase,
|
|
|
|
getStorageType(BaseDecl), BaseDecl));
|
2011-02-15 14:40:56 +08:00
|
|
|
}
|
|
|
|
}
|
2010-11-25 09:59:35 +08:00
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
bool CGRecordLowering::hasOwnStorage(const CXXRecordDecl *Decl,
|
|
|
|
const CXXRecordDecl *Query) {
|
|
|
|
const ASTRecordLayout &DeclLayout = Context.getASTRecordLayout(Decl);
|
|
|
|
if (DeclLayout.isPrimaryBaseVirtual() && DeclLayout.getPrimaryBase() == Query)
|
2011-12-13 07:13:20 +08:00
|
|
|
return false;
|
2014-03-13 23:41:46 +08:00
|
|
|
for (const auto &Base : Decl->bases())
|
|
|
|
if (!hasOwnStorage(Base.getType()->getAsCXXRecordDecl(), Query))
|
2011-12-13 07:13:20 +08:00
|
|
|
return false;
|
|
|
|
return true;
|
2011-11-08 12:01:03 +08:00
|
|
|
}
|
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void CGRecordLowering::calculateZeroInit() {
|
|
|
|
for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
|
|
|
|
MemberEnd = Members.end();
|
|
|
|
IsZeroInitializableAsBase && Member != MemberEnd; ++Member) {
|
|
|
|
if (Member->Kind == MemberInfo::Field) {
|
|
|
|
if (!Member->FD || isZeroInitializable(Member->FD))
|
2010-11-29 03:18:44 +08:00
|
|
|
continue;
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
IsZeroInitializable = IsZeroInitializableAsBase = false;
|
|
|
|
} else if (Member->Kind == MemberInfo::Base ||
|
|
|
|
Member->Kind == MemberInfo::VBase) {
|
|
|
|
if (isZeroInitializable(Member->RD))
|
|
|
|
continue;
|
|
|
|
IsZeroInitializable = false;
|
|
|
|
if (Member->Kind == MemberInfo::Base)
|
|
|
|
IsZeroInitializableAsBase = false;
|
2010-11-29 03:18:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void CGRecordLowering::clipTailPadding() {
|
|
|
|
std::vector<MemberInfo>::iterator Prior = Members.begin();
|
|
|
|
CharUnits Tail = getSize(Prior->Data);
|
|
|
|
for (std::vector<MemberInfo>::iterator Member = Prior + 1,
|
|
|
|
MemberEnd = Members.end();
|
|
|
|
Member != MemberEnd; ++Member) {
|
|
|
|
// Only members with data and the scissor can cut into tail padding.
|
|
|
|
if (!Member->Data && Member->Kind != MemberInfo::Scissor)
|
2010-05-18 13:12:20 +08:00
|
|
|
continue;
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
if (Member->Offset < Tail) {
|
2019-06-21 04:44:45 +08:00
|
|
|
assert(Prior->Kind == MemberInfo::Field &&
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
"Only storage fields have tail padding!");
|
2019-06-21 04:44:45 +08:00
|
|
|
if (!Prior->FD || Prior->FD->isBitField())
|
|
|
|
Prior->Data = getByteArrayType(bitsToCharUnits(llvm::alignTo(
|
|
|
|
cast<llvm::IntegerType>(Prior->Data)->getIntegerBitWidth(), 8)));
|
|
|
|
else {
|
|
|
|
assert(Prior->FD->hasAttr<NoUniqueAddressAttr>() &&
|
|
|
|
"should not have reused this field's tail padding");
|
|
|
|
Prior->Data = getByteArrayType(
|
2020-08-24 16:19:29 +08:00
|
|
|
Context.getTypeInfoDataSizeInChars(Prior->FD->getType()).Width);
|
2019-06-21 04:44:45 +08:00
|
|
|
}
|
2014-01-10 07:51:31 +08:00
|
|
|
}
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
if (Member->Data)
|
|
|
|
Prior = Member;
|
|
|
|
Tail = Prior->Offset + getSize(Prior->Data);
|
2014-01-10 07:51:31 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-28 14:39:30 +08:00
|
|
|
void CGRecordLowering::determinePacked(bool NVBaseType) {
|
|
|
|
if (Packed)
|
|
|
|
return;
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
CharUnits Alignment = CharUnits::One();
|
2014-09-28 14:39:30 +08:00
|
|
|
CharUnits NVAlignment = CharUnits::One();
|
|
|
|
CharUnits NVSize =
|
|
|
|
!NVBaseType && RD ? Layout.getNonVirtualSize() : CharUnits::Zero();
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
|
|
|
|
MemberEnd = Members.end();
|
|
|
|
Member != MemberEnd; ++Member) {
|
|
|
|
if (!Member->Data)
|
2012-12-06 19:14:44 +08:00
|
|
|
continue;
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
// If any member falls at an offset that it not a multiple of its alignment,
|
|
|
|
// then the entire record must be packed.
|
|
|
|
if (Member->Offset % getAlignment(Member->Data))
|
|
|
|
Packed = true;
|
2014-09-28 14:39:30 +08:00
|
|
|
if (Member->Offset < NVSize)
|
|
|
|
NVAlignment = std::max(NVAlignment, getAlignment(Member->Data));
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
Alignment = std::max(Alignment, getAlignment(Member->Data));
|
|
|
|
}
|
|
|
|
// If the size of the record (the capstone's offset) is not a multiple of the
|
|
|
|
// record's alignment, it must be packed.
|
|
|
|
if (Members.back().Offset % Alignment)
|
|
|
|
Packed = true;
|
2014-09-28 14:39:30 +08:00
|
|
|
// If the non-virtual sub-object is not a multiple of the non-virtual
|
|
|
|
// sub-object's alignment, it must be packed. We cannot have a packed
|
|
|
|
// non-virtual sub-object and an unpacked complete object or vise versa.
|
|
|
|
if (NVSize % NVAlignment)
|
|
|
|
Packed = true;
|
2018-04-06 23:14:32 +08:00
|
|
|
// Update the alignment of the sentinel.
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
if (!Packed)
|
|
|
|
Members.back().Data = getIntNType(Context.toBits(Alignment));
|
2009-07-23 11:17:50 +08:00
|
|
|
}
|
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void CGRecordLowering::insertPadding() {
|
|
|
|
std::vector<std::pair<CharUnits, CharUnits> > Padding;
|
|
|
|
CharUnits Size = CharUnits::Zero();
|
|
|
|
for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
|
|
|
|
MemberEnd = Members.end();
|
|
|
|
Member != MemberEnd; ++Member) {
|
|
|
|
if (!Member->Data)
|
|
|
|
continue;
|
|
|
|
CharUnits Offset = Member->Offset;
|
|
|
|
assert(Offset >= Size);
|
|
|
|
// Insert padding if we need to.
|
2016-01-15 05:00:27 +08:00
|
|
|
if (Offset !=
|
|
|
|
Size.alignTo(Packed ? CharUnits::One() : getAlignment(Member->Data)))
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
Padding.push_back(std::make_pair(Size, Offset - Size));
|
|
|
|
Size = Offset + getSize(Member->Data);
|
|
|
|
}
|
|
|
|
if (Padding.empty())
|
2009-12-08 09:24:23 +08:00
|
|
|
return;
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
// Add the padding to the Members list and sort it.
|
|
|
|
for (std::vector<std::pair<CharUnits, CharUnits> >::const_iterator
|
|
|
|
Pad = Padding.begin(), PadEnd = Padding.end();
|
|
|
|
Pad != PadEnd; ++Pad)
|
|
|
|
Members.push_back(StorageInfo(Pad->first, getByteArrayType(Pad->second)));
|
2019-04-24 22:43:05 +08:00
|
|
|
llvm::stable_sort(Members);
|
2009-07-27 22:55:54 +08:00
|
|
|
}
|
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
void CGRecordLowering::fillOutputFields() {
|
|
|
|
for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
|
|
|
|
MemberEnd = Members.end();
|
|
|
|
Member != MemberEnd; ++Member) {
|
|
|
|
if (Member->Data)
|
|
|
|
FieldTypes.push_back(Member->Data);
|
|
|
|
if (Member->Kind == MemberInfo::Field) {
|
|
|
|
if (Member->FD)
|
2014-04-19 11:48:30 +08:00
|
|
|
Fields[Member->FD->getCanonicalDecl()] = FieldTypes.size() - 1;
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
// A field without storage must be a bitfield.
|
|
|
|
if (!Member->Data)
|
|
|
|
setBitFieldInfo(Member->FD, Member->Offset, FieldTypes.back());
|
|
|
|
} else if (Member->Kind == MemberInfo::Base)
|
|
|
|
NonVirtualBases[Member->RD] = FieldTypes.size() - 1;
|
|
|
|
else if (Member->Kind == MemberInfo::VBase)
|
|
|
|
VirtualBases[Member->RD] = FieldTypes.size() - 1;
|
2009-07-23 11:17:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
|
|
|
|
const FieldDecl *FD,
|
|
|
|
uint64_t Offset, uint64_t Size,
|
|
|
|
uint64_t StorageSize,
|
Respect alignment of nested bitfields
tools/clang/test/CodeGen/packed-nest-unpacked.c contains this test:
struct XBitfield {
unsigned b1 : 10;
unsigned b2 : 12;
unsigned b3 : 10;
};
struct YBitfield {
char x;
struct XBitfield y;
} __attribute((packed));
struct YBitfield gbitfield;
unsigned test7() {
// CHECK: @test7
// CHECK: load i32, i32* getelementptr inbounds (%struct.YBitfield, %struct.YBitfield* @gbitfield, i32 0, i32 1, i32 0), align 4
return gbitfield.y.b2;
}
The "align 4" is actually wrong. Accessing all of "gbitfield.y" as a single
i32 is of course possible, but that still doesn't make it 4-byte aligned as
it remains packed at offset 1 in the surrounding gbitfield object.
This alignment was changed by commit r169489, which also introduced changes
to bitfield access code in CGExpr.cpp. Code before that change used to take
into account *both* the alignment of the field to be accessed within the
current struct, *and* the alignment of that outer struct itself; this logic
was removed by the above commit.
Neglecting to consider both values can cause incorrect code to be generated
(I've seen an unaligned access crash on SystemZ due to this bug).
In order to always use the best known alignment value, this patch removes
the CGBitFieldInfo::StorageAlignment member and replaces it with a
StorageOffset member specifying the offset from the start of the surrounding
struct to the bitfield's underlying storage. This offset can then be combined
with the best-known alignment for a bitfield access lvalue to determine the
alignment to use when accessing the bitfield's storage.
Differential Revision: http://reviews.llvm.org/D11034
llvm-svn: 241916
2015-07-11 01:30:00 +08:00
|
|
|
CharUnits StorageOffset) {
|
2018-07-31 03:24:48 +08:00
|
|
|
// This function is vestigial from CGRecordLayoutBuilder days but is still
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
// used in GCObjCRuntime.cpp. That usage has a "fixme" attached to it that
|
|
|
|
// when addressed will allow for the removal of this function.
|
|
|
|
llvm::Type *Ty = Types.ConvertTypeForMem(FD->getType());
|
|
|
|
CharUnits TypeSizeInBytes =
|
|
|
|
CharUnits::fromQuantity(Types.getDataLayout().getTypeAllocSize(Ty));
|
|
|
|
uint64_t TypeSizeInBits = Types.getContext().toBits(TypeSizeInBytes);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
bool IsSigned = FD->getType()->isSignedIntegerOrEnumerationType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
if (Size > TypeSizeInBits) {
|
|
|
|
// We have a wide bit-field. The extra bits are only used for padding, so
|
|
|
|
// if we have a bitfield of type T, with size N:
|
|
|
|
//
|
|
|
|
// T t : N;
|
|
|
|
//
|
|
|
|
// We can just assume that it's:
|
|
|
|
//
|
|
|
|
// T t : sizeof(T);
|
|
|
|
//
|
|
|
|
Size = TypeSizeInBits;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
// Reverse the bit offsets for big endian machines. Because we represent
|
|
|
|
// a bitfield as a single large integer load, we can imagine the bits
|
|
|
|
// counting from the most-significant-bit instead of the
|
|
|
|
// least-significant-bit.
|
|
|
|
if (Types.getDataLayout().isBigEndian()) {
|
|
|
|
Offset = StorageSize - (Offset + Size);
|
2010-05-19 00:51:41 +08:00
|
|
|
}
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
|
Respect alignment of nested bitfields
tools/clang/test/CodeGen/packed-nest-unpacked.c contains this test:
struct XBitfield {
unsigned b1 : 10;
unsigned b2 : 12;
unsigned b3 : 10;
};
struct YBitfield {
char x;
struct XBitfield y;
} __attribute((packed));
struct YBitfield gbitfield;
unsigned test7() {
// CHECK: @test7
// CHECK: load i32, i32* getelementptr inbounds (%struct.YBitfield, %struct.YBitfield* @gbitfield, i32 0, i32 1, i32 0), align 4
return gbitfield.y.b2;
}
The "align 4" is actually wrong. Accessing all of "gbitfield.y" as a single
i32 is of course possible, but that still doesn't make it 4-byte aligned as
it remains packed at offset 1 in the surrounding gbitfield object.
This alignment was changed by commit r169489, which also introduced changes
to bitfield access code in CGExpr.cpp. Code before that change used to take
into account *both* the alignment of the field to be accessed within the
current struct, *and* the alignment of that outer struct itself; this logic
was removed by the above commit.
Neglecting to consider both values can cause incorrect code to be generated
(I've seen an unaligned access crash on SystemZ due to this bug).
In order to always use the best known alignment value, this patch removes
the CGBitFieldInfo::StorageAlignment member and replaces it with a
StorageOffset member specifying the offset from the start of the surrounding
struct to the bitfield's underlying storage. This offset can then be combined
with the best-known alignment for a bitfield access lvalue to determine the
alignment to use when accessing the bitfield's storage.
Differential Revision: http://reviews.llvm.org/D11034
llvm-svn: 241916
2015-07-11 01:30:00 +08:00
|
|
|
return CGBitFieldInfo(Offset, Size, IsSigned, StorageSize, StorageOffset);
|
2010-05-19 00:51:41 +08:00
|
|
|
}
|
2010-03-31 08:11:27 +08:00
|
|
|
|
2020-04-29 11:40:31 +08:00
|
|
|
std::unique_ptr<CGRecordLayout>
|
|
|
|
CodeGenTypes::ComputeRecordLayout(const RecordDecl *D, llvm::StructType *Ty) {
|
2014-09-28 14:39:30 +08:00
|
|
|
CGRecordLowering Builder(*this, D, /*Packed=*/false);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2014-09-28 14:39:30 +08:00
|
|
|
Builder.lower(/*NonVirtualBaseType=*/false);
|
2009-07-24 23:20:52 +08:00
|
|
|
|
2011-02-15 14:40:56 +08:00
|
|
|
// If we're in C++, compute the base subobject type.
|
2014-05-21 13:09:00 +08:00
|
|
|
llvm::StructType *BaseTy = nullptr;
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
if (isa<CXXRecordDecl>(D) && !D->isUnion() && !D->hasAttr<FinalAttr>()) {
|
|
|
|
BaseTy = Ty;
|
|
|
|
if (Builder.Layout.getNonVirtualSize() != Builder.Layout.getSize()) {
|
2014-09-28 14:39:30 +08:00
|
|
|
CGRecordLowering BaseBuilder(*this, D, /*Packed=*/Builder.Packed);
|
|
|
|
BaseBuilder.lower(/*NonVirtualBaseType=*/true);
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
BaseTy = llvm::StructType::create(
|
|
|
|
getLLVMContext(), BaseBuilder.FieldTypes, "", BaseBuilder.Packed);
|
|
|
|
addRecordTypeName(D, BaseTy, ".base");
|
2014-09-28 14:39:30 +08:00
|
|
|
// BaseTy and Ty must agree on their packedness for getLLVMFieldNo to work
|
|
|
|
// on both of them with the same index.
|
|
|
|
assert(Builder.Packed == BaseBuilder.Packed &&
|
|
|
|
"Non-virtual and complete types must agree on packedness");
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
}
|
2010-11-09 13:25:47 +08:00
|
|
|
}
|
|
|
|
|
2014-02-27 08:03:39 +08:00
|
|
|
// Fill in the struct *after* computing the base type. Filling in the body
|
|
|
|
// signifies that the type is no longer opaque and record layout is complete,
|
|
|
|
// but we may need to recursively layout D while laying D out as a base type.
|
|
|
|
Ty->setBody(Builder.FieldTypes, Builder.Packed);
|
|
|
|
|
2020-04-29 11:40:31 +08:00
|
|
|
auto RL = std::make_unique<CGRecordLayout>(
|
|
|
|
Ty, BaseTy, (bool)Builder.IsZeroInitializable,
|
|
|
|
(bool)Builder.IsZeroInitializableAsBase);
|
2010-03-31 09:09:11 +08:00
|
|
|
|
2011-02-15 14:40:56 +08:00
|
|
|
RL->NonVirtualBases.swap(Builder.NonVirtualBases);
|
|
|
|
RL->CompleteObjectVirtualBases.swap(Builder.VirtualBases);
|
2010-05-18 13:22:06 +08:00
|
|
|
|
2009-07-23 11:17:50 +08:00
|
|
|
// Add all the field numbers.
|
2011-02-15 14:40:56 +08:00
|
|
|
RL->FieldInfo.swap(Builder.Fields);
|
2009-07-23 11:17:50 +08:00
|
|
|
|
|
|
|
// Add bitfield info.
|
2011-02-15 14:40:56 +08:00
|
|
|
RL->BitFields.swap(Builder.BitFields);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-04-20 04:44:47 +08:00
|
|
|
// Dump the layout, if requested.
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getContext().getLangOpts().DumpRecordLayouts) {
|
2013-07-13 06:30:03 +08:00
|
|
|
llvm::outs() << "\n*** Dumping IRgen Record Layout\n";
|
|
|
|
llvm::outs() << "Record: ";
|
|
|
|
D->dump(llvm::outs());
|
|
|
|
llvm::outs() << "\nLayout: ";
|
|
|
|
RL->print(llvm::outs());
|
2010-04-14 04:58:55 +08:00
|
|
|
}
|
2010-04-13 02:14:18 +08:00
|
|
|
|
2010-04-22 10:35:46 +08:00
|
|
|
#ifndef NDEBUG
|
2010-04-20 04:44:47 +08:00
|
|
|
// Verify that the computed LLVM struct size matches the AST layout size.
|
2010-11-09 13:25:47 +08:00
|
|
|
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(D);
|
|
|
|
|
2011-02-11 09:54:29 +08:00
|
|
|
uint64_t TypeSizeInBits = getContext().toBits(Layout.getSize());
|
2012-10-09 00:25:52 +08:00
|
|
|
assert(TypeSizeInBits == getDataLayout().getTypeAllocSizeInBits(Ty) &&
|
2010-04-20 04:44:47 +08:00
|
|
|
"Type size mismatch!");
|
|
|
|
|
2010-11-09 13:25:47 +08:00
|
|
|
if (BaseTy) {
|
2011-02-08 10:02:47 +08:00
|
|
|
CharUnits NonVirtualSize = Layout.getNonVirtualSize();
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
uint64_t AlignedNonVirtualTypeSizeInBits =
|
Complete Rewrite of CGRecordLayoutBuilder
CGRecordLayoutBuilder was aging, complex, multi-pass, and shows signs of
existing before ASTRecordLayoutBuilder. It redundantly performed many
layout operations that are now performed by ASTRecordLayoutBuilder and
asserted that the results were the same. With the addition of support
for the MS-ABI, such as placement of vbptrs, vtordisps, different
bitfield layout and a variety of other features, CGRecordLayoutBuilder
was growing unwieldy in its redundancy.
This patch re-architects CGRecordLayoutBuilder to not perform any
redundant layout but rather, as directly as possible, lower an
ASTRecordLayout to an llvm::type. The new architecture is significantly
smaller and simpler than the CGRecordLayoutBuilder and contains fewer
ABI-specific code paths. It's also one pass.
The architecture of the new system is described in the comments. For the
most part, the new system simply takes all of the fields and bases from
an ASTRecordLayout, sorts them, inserts padding and dumps a record.
Bitfields, unions and primary virtual bases make this process a bit more
complicated. See the inline comments.
In addition, this patch updates a few lit tests due to the fact that the
new system computes more accurate llvm types than CGRecordLayoutBuilder.
Each change is commented individually in the review.
Differential Revision: http://llvm-reviews.chandlerc.com/D2795
llvm-svn: 201907
2014-02-22 07:49:50 +08:00
|
|
|
getContext().toBits(NonVirtualSize);
|
2010-11-09 13:25:47 +08:00
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
assert(AlignedNonVirtualTypeSizeInBits ==
|
2012-10-09 00:25:52 +08:00
|
|
|
getDataLayout().getTypeAllocSizeInBits(BaseTy) &&
|
2010-11-09 13:25:47 +08:00
|
|
|
"Type size mismatch!");
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-04-22 03:10:49 +08:00
|
|
|
// Verify that the LLVM and AST field offsets agree.
|
2018-03-01 13:43:23 +08:00
|
|
|
llvm::StructType *ST = RL->getLLVMType();
|
2012-10-09 00:25:52 +08:00
|
|
|
const llvm::StructLayout *SL = getDataLayout().getStructLayout(ST);
|
2010-04-22 03:10:49 +08:00
|
|
|
|
|
|
|
const ASTRecordLayout &AST_RL = getContext().getASTRecordLayout(D);
|
|
|
|
RecordDecl::field_iterator it = D->field_begin();
|
|
|
|
for (unsigned i = 0, e = AST_RL.getFieldCount(); i != e; ++i, ++it) {
|
2012-06-07 04:45:41 +08:00
|
|
|
const FieldDecl *FD = *it;
|
2010-04-22 10:35:46 +08:00
|
|
|
|
2019-06-21 04:44:45 +08:00
|
|
|
// Ignore zero-sized fields.
|
|
|
|
if (FD->isZeroSize(getContext()))
|
|
|
|
continue;
|
|
|
|
|
2010-04-22 10:35:46 +08:00
|
|
|
// For non-bit-fields, just check that the LLVM struct offset matches the
|
|
|
|
// AST offset.
|
|
|
|
if (!FD->isBitField()) {
|
2010-04-22 03:10:49 +08:00
|
|
|
unsigned FieldNo = RL->getLLVMFieldNo(FD);
|
|
|
|
assert(AST_RL.getFieldOffset(i) == SL->getElementOffsetInBits(FieldNo) &&
|
|
|
|
"Invalid field offset!");
|
2010-04-22 10:35:46 +08:00
|
|
|
continue;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-04-22 10:35:46 +08:00
|
|
|
// Ignore unnamed bit-fields.
|
2013-06-27 04:50:34 +08:00
|
|
|
if (!FD->getDeclName())
|
2010-04-22 10:35:46 +08:00
|
|
|
continue;
|
2012-12-06 19:14:44 +08:00
|
|
|
|
2010-04-22 10:35:46 +08:00
|
|
|
const CGBitFieldInfo &Info = RL->getBitFieldInfo(FD);
|
2012-12-09 18:33:27 +08:00
|
|
|
llvm::Type *ElementTy = ST->getTypeAtIndex(RL->getLLVMFieldNo(FD));
|
|
|
|
|
2012-12-06 19:14:44 +08:00
|
|
|
// Unions have overlapping elements dictating their layout, but for
|
|
|
|
// non-unions we can verify that this section of the layout is the exact
|
2012-12-09 18:33:27 +08:00
|
|
|
// expected size.
|
2012-12-06 19:14:44 +08:00
|
|
|
if (D->isUnion()) {
|
2012-12-09 18:33:27 +08:00
|
|
|
// For unions we verify that the start is zero and the size
|
|
|
|
// is in-bounds. However, on BE systems, the offset may be non-zero, but
|
|
|
|
// the size + offset should match the storage size in that case as it
|
|
|
|
// "starts" at the back.
|
|
|
|
if (getDataLayout().isBigEndian())
|
2013-01-16 07:13:49 +08:00
|
|
|
assert(static_cast<unsigned>(Info.Offset + Info.Size) ==
|
|
|
|
Info.StorageSize &&
|
2012-12-09 18:33:27 +08:00
|
|
|
"Big endian union bitfield does not end at the back");
|
|
|
|
else
|
|
|
|
assert(Info.Offset == 0 &&
|
|
|
|
"Little endian union bitfield with a non-zero offset");
|
2012-12-06 19:14:44 +08:00
|
|
|
assert(Info.StorageSize <= SL->getSizeInBits() &&
|
|
|
|
"Union not large enough for bitfield storage");
|
|
|
|
} else {
|
[ARM] Follow AACPS standard for volatile bit-fields access width
This patch resumes the work of D16586.
According to the AAPCS, volatile bit-fields should
be accessed using containers of the widht of their
declarative type. In such case:
```
struct S1 {
short a : 1;
}
```
should be accessed using load and stores of the width
(sizeof(short)), where now the compiler does only load
the minimum required width (char in this case).
However, as discussed in D16586,
that could overwrite non-volatile bit-fields, which
conflicted with C and C++ object models by creating
data race conditions that are not part of the bit-field,
e.g.
```
struct S2 {
short a;
int b : 16;
}
```
Accessing `S2.b` would also access `S2.a`.
The AAPCS Release 2020Q2
(https://documentation-service.arm.com/static/5efb7fbedbdee951c1ccf186?token=)
section 8.1 Data Types, page 36, "Volatile bit-fields -
preserving number and width of container accesses" has been
updated to avoid conflict with the C++ Memory Model.
Now it reads in the note:
```
This ABI does not place any restrictions on the access widths of bit-fields where the container
overlaps with a non-bit-field member or where the container overlaps with any zero length bit-field
placed between two other bit-fields. This is because the C/C++ memory model defines these as being
separate memory locations, which can be accessed by two threads simultaneously. For this reason,
compilers must be permitted to use a narrower memory access width (including splitting the access into
multiple instructions) to avoid writing to a different memory location. For example, in
struct S { int a:24; char b; }; a write to a must not also write to the location occupied by b, this requires at least two
memory accesses in all current Arm architectures. In the same way, in struct S { int a:24; int:0; int b:8; };,
writes to a or b must not overwrite each other.
```
I've updated the patch D16586 to follow such behavior by verifying that we
only change volatile bit-field access when:
- it won't overlap with any other non-bit-field member
- we only access memory inside the bounds of the record
- avoid overlapping zero-length bit-fields.
Regarding the number of memory accesses, that should be preserved, that will
be implemented by D67399.
Reviewed By: ostannard
Differential Revision: https://reviews.llvm.org/D72932
2020-09-30 21:44:27 +08:00
|
|
|
assert((Info.StorageSize ==
|
|
|
|
getDataLayout().getTypeAllocSizeInBits(ElementTy) ||
|
|
|
|
Info.VolatileStorageSize ==
|
|
|
|
getDataLayout().getTypeAllocSizeInBits(ElementTy)) &&
|
2012-12-06 19:14:44 +08:00
|
|
|
"Storage size does not match the element type size");
|
2010-04-22 03:10:49 +08:00
|
|
|
}
|
2012-12-06 19:14:44 +08:00
|
|
|
assert(Info.Size > 0 && "Empty bitfield!");
|
2012-12-19 02:53:14 +08:00
|
|
|
assert(static_cast<unsigned>(Info.Offset) + Info.Size <= Info.StorageSize &&
|
2012-12-06 19:14:44 +08:00
|
|
|
"Bitfield outside of its allocated storage");
|
2010-04-22 03:10:49 +08:00
|
|
|
}
|
|
|
|
#endif
|
2010-04-20 04:44:47 +08:00
|
|
|
|
2010-03-31 09:09:11 +08:00
|
|
|
return RL;
|
2009-07-23 11:17:50 +08:00
|
|
|
}
|
2010-04-13 02:14:18 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
void CGRecordLayout::print(raw_ostream &OS) const {
|
2010-04-13 02:14:18 +08:00
|
|
|
OS << "<CGRecordLayout\n";
|
2011-02-15 14:40:56 +08:00
|
|
|
OS << " LLVMType:" << *CompleteObjectType << "\n";
|
|
|
|
if (BaseSubobjectType)
|
2018-07-31 03:24:48 +08:00
|
|
|
OS << " NonVirtualBaseLLVMType:" << *BaseSubobjectType << "\n";
|
2010-08-23 05:01:12 +08:00
|
|
|
OS << " IsZeroInitializable:" << IsZeroInitializable << "\n";
|
2010-04-13 02:14:18 +08:00
|
|
|
OS << " BitFields:[\n";
|
2010-04-22 10:35:36 +08:00
|
|
|
|
|
|
|
// Print bit-field infos in declaration order.
|
|
|
|
std::vector<std::pair<unsigned, const CGBitFieldInfo*> > BFIs;
|
2010-04-13 02:14:18 +08:00
|
|
|
for (llvm::DenseMap<const FieldDecl*, CGBitFieldInfo>::const_iterator
|
|
|
|
it = BitFields.begin(), ie = BitFields.end();
|
|
|
|
it != ie; ++it) {
|
2010-04-22 10:35:36 +08:00
|
|
|
const RecordDecl *RD = it->first->getParent();
|
|
|
|
unsigned Index = 0;
|
|
|
|
for (RecordDecl::field_iterator
|
2012-06-07 04:45:41 +08:00
|
|
|
it2 = RD->field_begin(); *it2 != it->first; ++it2)
|
2010-04-22 10:35:36 +08:00
|
|
|
++Index;
|
|
|
|
BFIs.push_back(std::make_pair(Index, &it->second));
|
|
|
|
}
|
|
|
|
llvm::array_pod_sort(BFIs.begin(), BFIs.end());
|
|
|
|
for (unsigned i = 0, e = BFIs.size(); i != e; ++i) {
|
2010-04-14 04:58:55 +08:00
|
|
|
OS.indent(4);
|
2010-04-22 10:35:36 +08:00
|
|
|
BFIs[i].second->print(OS);
|
2010-04-13 02:14:18 +08:00
|
|
|
OS << "\n";
|
|
|
|
}
|
2010-04-22 10:35:36 +08:00
|
|
|
|
2010-04-13 02:14:18 +08:00
|
|
|
OS << "]>\n";
|
|
|
|
}
|
|
|
|
|
2016-01-30 03:38:18 +08:00
|
|
|
LLVM_DUMP_METHOD void CGRecordLayout::dump() const {
|
2010-04-13 02:14:18 +08:00
|
|
|
print(llvm::errs());
|
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
void CGBitFieldInfo::print(raw_ostream &OS) const {
|
2012-12-06 19:14:44 +08:00
|
|
|
OS << "<CGBitFieldInfo"
|
[ARM] Follow AACPS standard for volatile bit-fields access width
This patch resumes the work of D16586.
According to the AAPCS, volatile bit-fields should
be accessed using containers of the widht of their
declarative type. In such case:
```
struct S1 {
short a : 1;
}
```
should be accessed using load and stores of the width
(sizeof(short)), where now the compiler does only load
the minimum required width (char in this case).
However, as discussed in D16586,
that could overwrite non-volatile bit-fields, which
conflicted with C and C++ object models by creating
data race conditions that are not part of the bit-field,
e.g.
```
struct S2 {
short a;
int b : 16;
}
```
Accessing `S2.b` would also access `S2.a`.
The AAPCS Release 2020Q2
(https://documentation-service.arm.com/static/5efb7fbedbdee951c1ccf186?token=)
section 8.1 Data Types, page 36, "Volatile bit-fields -
preserving number and width of container accesses" has been
updated to avoid conflict with the C++ Memory Model.
Now it reads in the note:
```
This ABI does not place any restrictions on the access widths of bit-fields where the container
overlaps with a non-bit-field member or where the container overlaps with any zero length bit-field
placed between two other bit-fields. This is because the C/C++ memory model defines these as being
separate memory locations, which can be accessed by two threads simultaneously. For this reason,
compilers must be permitted to use a narrower memory access width (including splitting the access into
multiple instructions) to avoid writing to a different memory location. For example, in
struct S { int a:24; char b; }; a write to a must not also write to the location occupied by b, this requires at least two
memory accesses in all current Arm architectures. In the same way, in struct S { int a:24; int:0; int b:8; };,
writes to a or b must not overwrite each other.
```
I've updated the patch D16586 to follow such behavior by verifying that we
only change volatile bit-field access when:
- it won't overlap with any other non-bit-field member
- we only access memory inside the bounds of the record
- avoid overlapping zero-length bit-fields.
Regarding the number of memory accesses, that should be preserved, that will
be implemented by D67399.
Reviewed By: ostannard
Differential Revision: https://reviews.llvm.org/D72932
2020-09-30 21:44:27 +08:00
|
|
|
<< " Offset:" << Offset << " Size:" << Size << " IsSigned:" << IsSigned
|
2012-12-06 19:14:44 +08:00
|
|
|
<< " StorageSize:" << StorageSize
|
[ARM] Follow AACPS standard for volatile bit-fields access width
This patch resumes the work of D16586.
According to the AAPCS, volatile bit-fields should
be accessed using containers of the widht of their
declarative type. In such case:
```
struct S1 {
short a : 1;
}
```
should be accessed using load and stores of the width
(sizeof(short)), where now the compiler does only load
the minimum required width (char in this case).
However, as discussed in D16586,
that could overwrite non-volatile bit-fields, which
conflicted with C and C++ object models by creating
data race conditions that are not part of the bit-field,
e.g.
```
struct S2 {
short a;
int b : 16;
}
```
Accessing `S2.b` would also access `S2.a`.
The AAPCS Release 2020Q2
(https://documentation-service.arm.com/static/5efb7fbedbdee951c1ccf186?token=)
section 8.1 Data Types, page 36, "Volatile bit-fields -
preserving number and width of container accesses" has been
updated to avoid conflict with the C++ Memory Model.
Now it reads in the note:
```
This ABI does not place any restrictions on the access widths of bit-fields where the container
overlaps with a non-bit-field member or where the container overlaps with any zero length bit-field
placed between two other bit-fields. This is because the C/C++ memory model defines these as being
separate memory locations, which can be accessed by two threads simultaneously. For this reason,
compilers must be permitted to use a narrower memory access width (including splitting the access into
multiple instructions) to avoid writing to a different memory location. For example, in
struct S { int a:24; char b; }; a write to a must not also write to the location occupied by b, this requires at least two
memory accesses in all current Arm architectures. In the same way, in struct S { int a:24; int:0; int b:8; };,
writes to a or b must not overwrite each other.
```
I've updated the patch D16586 to follow such behavior by verifying that we
only change volatile bit-field access when:
- it won't overlap with any other non-bit-field member
- we only access memory inside the bounds of the record
- avoid overlapping zero-length bit-fields.
Regarding the number of memory accesses, that should be preserved, that will
be implemented by D67399.
Reviewed By: ostannard
Differential Revision: https://reviews.llvm.org/D72932
2020-09-30 21:44:27 +08:00
|
|
|
<< " StorageOffset:" << StorageOffset.getQuantity()
|
|
|
|
<< " VolatileOffset:" << VolatileOffset
|
|
|
|
<< " VolatileStorageSize:" << VolatileStorageSize
|
|
|
|
<< " VolatileStorageOffset:" << VolatileStorageOffset.getQuantity() << ">";
|
2010-04-13 02:14:18 +08:00
|
|
|
}
|
|
|
|
|
2016-01-30 03:38:18 +08:00
|
|
|
LLVM_DUMP_METHOD void CGBitFieldInfo::dump() const {
|
2010-04-13 02:14:18 +08:00
|
|
|
print(llvm::errs());
|
|
|
|
}
|