brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.2 KiB · c936497 Raw
216 lines · c
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_LIB_CIR_CIRGENRECORDLAYOUT_H10#define LLVM_CLANG_LIB_CIR_CIRGENRECORDLAYOUT_H11 12#include "clang/AST/Decl.h"13#include "clang/CIR/Dialect/IR/CIRTypes.h"14 15namespace clang::CIRGen {16 17/// Record with information about how a bitfield should be accessed. This is18/// very similar to what LLVM codegen does, once CIR evolves it's possible we19/// can use a more higher level representation.20///21/// Often we lay out a sequence of bitfields as a contiguous sequence of bits.22/// When the AST record layout does this, we represent it in CIR as a23/// `!cir.record` type, which directly reflects the structure's layout,24/// including bitfield packing and padding, using CIR types such as25/// `!cir.bool`, `!s8i`, `!u16i`.26///27/// To access a particular bitfield in CIR, we use the operations28/// `cir.get_bitfield` (`GetBitfieldOp`) or `cir.set_bitfield`29/// (`SetBitfieldOp`). These operations rely on the `bitfield_info`30/// attribute, which provides detailed metadata required for access,31/// such as the size and offset of the bitfield, the type and size of32/// the underlying storage, and whether the value is signed.33/// The CIRGenRecordLayout also has a bitFields map which encodes which34/// byte-sequence this bitfield falls within. Let's assume the following C35/// struct:36///37///   struct S {38///     char a, b, c;39///     unsigned bits : 3;40///     unsigned more_bits : 4;41///     unsigned still_more_bits : 7;42///   };43///44/// This will end up as the following cir.record. The bitfield members are45/// represented by one !u16i value, and the array provides padding to align the46/// struct to a 4-byte alignment.47///48///   !rec_S = !cir.record<struct "S" padded {!s8i, !s8i, !s8i, !u16i,49///   !cir.array<!u8i x 3>}>50///51/// When generating code to access more_bits, we'll generate something52/// essentially like this:53///54///   #bfi_more_bits = #cir.bitfield_info<name = "more_bits", storage_type =55///   !u16i, size = 4, offset = 3, is_signed = false>56///57///   cir.func @store_field() {58///     %0 = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s"] {alignment = 4 : i64}59///     %1 = cir.const #cir.int<2> : !s32i60///     %2 = cir.cast integral %1 : !s32i -> !u32i61///     %3 = cir.get_member %0[3] {name = "more_bits"} : !cir.ptr<!rec_S> ->62///     !cir.ptr<!u16i>63///     %4 = cir.set_bitfield(#bfi_more_bits, %3 :64///     !cir.ptr<!u16i>, %2 : !u32i) -> !u32i65///     cir.return66///   }67///68struct CIRGenBitFieldInfo {69  /// The offset within a contiguous run of bitfields that are represented as70  /// a single "field" within the cir.record type. This offset is in bits.71  unsigned offset : 16;72 73  /// The total size of the bit-field, in bits.74  unsigned size : 15;75 76  /// Whether the bit-field is signed.77  unsigned isSigned : 1;78 79  /// The storage size in bits which should be used when accessing this80  /// bitfield.81  unsigned storageSize;82 83  /// The offset of the bitfield storage from the start of the record.84  clang::CharUnits storageOffset;85 86  /// The offset within a contiguous run of bitfields that are represented as a87  /// single "field" within the cir.record type, taking into account the AAPCS88  /// rules for volatile bitfields. This offset is in bits.89  unsigned volatileOffset : 16;90 91  /// The storage size in bits which should be used when accessing this92  /// bitfield.93  unsigned volatileStorageSize;94 95  /// The offset of the bitfield storage from the start of the record.96  clang::CharUnits volatileStorageOffset;97 98  /// The name of a bitfield99  llvm::StringRef name;100 101  // The actual storage type for the bitfield102  mlir::Type storageType;103 104  CIRGenBitFieldInfo()105      : offset(), size(), isSigned(), storageSize(), volatileOffset(),106        volatileStorageSize() {}107 108  CIRGenBitFieldInfo(unsigned offset, unsigned size, bool isSigned,109                     unsigned storageSize, clang::CharUnits storageOffset)110      : offset(offset), size(size), isSigned(isSigned),111        storageSize(storageSize), storageOffset(storageOffset) {}112 113  void print(llvm::raw_ostream &os) const;114  LLVM_DUMP_METHOD void dump() const;115};116 117/// This class handles record and union layout info while lowering AST types118/// to CIR types.119///120/// These layout objects are only created on demand as CIR generation requires.121class CIRGenRecordLayout {122  friend class CIRGenTypes;123 124  CIRGenRecordLayout(const CIRGenRecordLayout &) = delete;125  void operator=(const CIRGenRecordLayout &) = delete;126 127private:128  /// The CIR type corresponding to this record layout; used when laying it out129  /// as a complete object.130  cir::RecordType completeObjectType;131 132  /// The CIR type for the non-virtual part of this record layout; used when133  /// laying it out as a base subobject.134  cir::RecordType baseSubobjectType;135 136  /// Map from (non-bit-field) record field to the corresponding cir record type137  /// field no. This info is populated by the record builder.138  llvm::DenseMap<const clang::FieldDecl *, unsigned> fieldIdxMap;139 140  // FIXME: Maybe we could use CXXBaseSpecifier as the key and use a single map141  // for both virtual and non-virtual bases.142  llvm::DenseMap<const clang::CXXRecordDecl *, unsigned> nonVirtualBases;143 144  /// Map from virtual bases to their field index in the complete object.145  llvm::DenseMap<const clang::CXXRecordDecl *, unsigned>146      completeObjectVirtualBases;147 148  /// Map from (bit-field) record field to the corresponding CIR record type149  /// field no. This info is populated by record builder.150  llvm::DenseMap<const clang::FieldDecl *, CIRGenBitFieldInfo> bitFields;151 152  /// False if any direct or indirect subobject of this class, when considered153  /// as a complete object, requires a non-zero bitpattern when154  /// zero-initialized.155  LLVM_PREFERRED_TYPE(bool)156  unsigned zeroInitializable : 1;157 158  /// False if any direct or indirect subobject of this class, when considered159  /// as a base subobject, requires a non-zero bitpattern when zero-initialized.160  LLVM_PREFERRED_TYPE(bool)161  unsigned zeroInitializableAsBase : 1;162 163public:164  CIRGenRecordLayout(cir::RecordType completeObjectType,165                     cir::RecordType baseSubobjectType, bool zeroInitializable,166                     bool zeroInitializableAsBase)167      : completeObjectType(completeObjectType),168        baseSubobjectType(baseSubobjectType),169        zeroInitializable(zeroInitializable),170        zeroInitializableAsBase(zeroInitializableAsBase) {}171 172  /// Return the "complete object" LLVM type associated with173  /// this record.174  cir::RecordType getCIRType() const { return completeObjectType; }175 176  /// Return the "base subobject" LLVM type associated with177  /// this record.178  cir::RecordType getBaseSubobjectCIRType() const { return baseSubobjectType; }179 180  /// Return cir::RecordType element number that corresponds to the field FD.181  unsigned getCIRFieldNo(const clang::FieldDecl *fd) const {182    fd = fd->getCanonicalDecl();183    assert(fieldIdxMap.count(fd) && "Invalid field for record!");184    return fieldIdxMap.lookup(fd);185  }186 187  unsigned getNonVirtualBaseCIRFieldNo(const CXXRecordDecl *rd) const {188    assert(nonVirtualBases.count(rd) && "Invalid non-virtual base!");189    return nonVirtualBases.lookup(rd);190  }191 192  /// Check whether this struct can be C++ zero-initialized193  /// with a zeroinitializer.194  bool isZeroInitializable() const { return zeroInitializable; }195 196  /// Check whether this struct can be C++ zero-initialized197  /// with a zeroinitializer when considered as a base subobject.198  bool isZeroInitializableAsBase() const { return zeroInitializableAsBase; }199 200  /// Return the BitFieldInfo that corresponds to the field FD.201  const CIRGenBitFieldInfo &getBitFieldInfo(const clang::FieldDecl *fd) const {202    fd = fd->getCanonicalDecl();203    assert(fd->isBitField() && "Invalid call for non-bit-field decl!");204    llvm::DenseMap<const clang::FieldDecl *, CIRGenBitFieldInfo>::const_iterator205        it = bitFields.find(fd);206    assert(it != bitFields.end() && "Unable to find bitfield info");207    return it->second;208  }209  void print(raw_ostream &os) const;210  LLVM_DUMP_METHOD void dump() const;211};212 213} // namespace clang::CIRGen214 215#endif216