//===--- CGRecordLayoutBuilder.cpp - CGRecordLayout builder ----*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// // // Builder implementation for CGRecordLayout objects. // //===----------------------------------------------------------------------===// #include "ABIInfoImpl.h" #include "CGCXXABI.h" #include "CGRecordLayout.h" #include "CodeGenTypes.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/CodeGenOptions.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Type.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" usingnamespaceclang; usingnamespaceCodeGen; namespace { /// 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. This is computed when accumulating bitfields in /// accumulateBitfields. /// 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(); }; // a must be clipped because: /// struct B : A { char b; }; // b goes at offset 3 /// * The allocation of bitfield access units is described in more detail in /// CGRecordLowering::accumulateBitFields. /// * 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. /// * 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 { … }; } // namespace { CGRecordLowering::CGRecordLowering(CodeGenTypes &Types, const RecordDecl *D, bool Packed) : … { … } void CGRecordLowering::setBitFieldInfo( const FieldDecl *FD, CharUnits StartOffset, llvm::Type *StorageType) { … } void CGRecordLowering::lower(bool NVBaseType) { … } void CGRecordLowering::lowerUnion(bool isNoUniqueAddress) { … } void CGRecordLowering::accumulateFields(bool isNonVirtualBaseType) { … } // Create members for bitfields. Field is a bitfield, and FieldEnd is the end // iterator of the record. Return the first non-bitfield encountered. We need // to know whether this is the base or complete layout, as virtual bases could // affect the upper bound of bitfield access unit allocation. RecordDecl::field_iterator CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, RecordDecl::field_iterator Field, RecordDecl::field_iterator FieldEnd) { … } void CGRecordLowering::accumulateBases() { … } /// 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() { … } void CGRecordLowering::accumulateVPtrs() { … } CharUnits CGRecordLowering::calculateTailClippingOffset(bool isNonVirtualBaseType) const { … } void CGRecordLowering::accumulateVBases() { … } bool CGRecordLowering::hasOwnStorage(const CXXRecordDecl *Decl, const CXXRecordDecl *Query) const { … } void CGRecordLowering::calculateZeroInit() { … } // Verify accumulateBitfields computed the correct storage representations. void CGRecordLowering::checkBitfieldClipping(bool IsNonVirtualBaseType) const { … } void CGRecordLowering::determinePacked(bool NVBaseType) { … } void CGRecordLowering::insertPadding() { … } void CGRecordLowering::fillOutputFields() { … } CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, const FieldDecl *FD, uint64_t Offset, uint64_t Size, uint64_t StorageSize, CharUnits StorageOffset) { … } std::unique_ptr<CGRecordLayout> CodeGenTypes::ComputeRecordLayout(const RecordDecl *D, llvm::StructType *Ty) { … } void CGRecordLayout::print(raw_ostream &OS) const { … } LLVM_DUMP_METHOD void CGRecordLayout::dump() const { … } void CGBitFieldInfo::print(raw_ostream &OS) const { … } LLVM_DUMP_METHOD void CGBitFieldInfo::dump() const { … }