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-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLVM_CLANG_LIB_CIR_CIRGENRECORDLAYOUT_H |
10 | #define LLVM_CLANG_LIB_CIR_CIRGENRECORDLAYOUT_H |
11 | |
12 | #include "clang/AST/Decl.h" |
13 | #include "clang/CIR/Dialect/IR/CIRTypes.h" |
14 | |
15 | namespace clang::CIRGen { |
16 | |
17 | /// This class handles record and union layout info while lowering AST types |
18 | /// to CIR types. |
19 | /// |
20 | /// These layout objects are only created on demand as CIR generation requires. |
21 | class CIRGenRecordLayout { |
22 | friend class CIRGenTypes; |
23 | |
24 | CIRGenRecordLayout(const CIRGenRecordLayout &) = delete; |
25 | void operator=(const CIRGenRecordLayout &) = delete; |
26 | |
27 | private: |
28 | /// The CIR type corresponding to this record layout; used when laying it out |
29 | /// as a complete object. |
30 | cir::RecordType completeObjectType; |
31 | |
32 | /// The CIR type for the non-virtual part of this record layout; used when |
33 | /// laying it out as a base subobject. |
34 | cir::RecordType baseSubobjectType; |
35 | |
36 | /// Map from (non-bit-field) record field to the corresponding cir record type |
37 | /// field no. This info is populated by the record builder. |
38 | llvm::DenseMap<const clang::FieldDecl *, unsigned> fieldIdxMap; |
39 | |
40 | // FIXME: Maybe we could use CXXBaseSpecifier as the key and use a single map |
41 | // for both virtual and non-virtual bases. |
42 | llvm::DenseMap<const clang::CXXRecordDecl *, unsigned> nonVirtualBases; |
43 | |
44 | /// False if any direct or indirect subobject of this class, when considered |
45 | /// as a complete object, requires a non-zero bitpattern when |
46 | /// zero-initialized. |
47 | LLVM_PREFERRED_TYPE(bool) |
48 | unsigned zeroInitializable : 1; |
49 | |
50 | /// False if any direct or indirect subobject of this class, when considered |
51 | /// as a base subobject, requires a non-zero bitpattern when zero-initialized. |
52 | LLVM_PREFERRED_TYPE(bool) |
53 | unsigned zeroInitializableAsBase : 1; |
54 | |
55 | public: |
56 | CIRGenRecordLayout(cir::RecordType completeObjectType, |
57 | cir::RecordType baseSubobjectType, bool zeroInitializable, |
58 | bool zeroInitializableAsBase) |
59 | : completeObjectType(completeObjectType), |
60 | baseSubobjectType(baseSubobjectType), |
61 | zeroInitializable(zeroInitializable), |
62 | zeroInitializableAsBase(zeroInitializableAsBase) {} |
63 | |
64 | /// Return the "complete object" LLVM type associated with |
65 | /// this record. |
66 | cir::RecordType getCIRType() const { return completeObjectType; } |
67 | |
68 | /// Return the "base subobject" LLVM type associated with |
69 | /// this record. |
70 | cir::RecordType getBaseSubobjectCIRType() const { return baseSubobjectType; } |
71 | |
72 | /// Return cir::RecordType element number that corresponds to the field FD. |
73 | unsigned getCIRFieldNo(const clang::FieldDecl *fd) const { |
74 | fd = fd->getCanonicalDecl(); |
75 | assert(fieldIdxMap.count(fd) && "Invalid field for record!" ); |
76 | return fieldIdxMap.lookup(Val: fd); |
77 | } |
78 | |
79 | /// Check whether this struct can be C++ zero-initialized |
80 | /// with a zeroinitializer. |
81 | bool isZeroInitializable() const { return zeroInitializable; } |
82 | |
83 | /// Check whether this struct can be C++ zero-initialized |
84 | /// with a zeroinitializer when considered as a base subobject. |
85 | bool isZeroInitializableAsBase() const { return zeroInitializableAsBase; } |
86 | }; |
87 | |
88 | } // namespace clang::CIRGen |
89 | |
90 | #endif |
91 | |