12
12
#ifndef LLVM_CLANG_CIR_DIALECT_IR_CIRDATALAYOUT_H
13
13
#define LLVM_CLANG_CIR_DIALECT_IR_CIRDATALAYOUT_H
14
14
15
- #include " mlir/Dialect/DLTI/DLTI.h"
16
15
#include " mlir/IR/BuiltinOps.h"
17
16
#include " clang/CIR/Dialect/IR/CIRTypes.h"
18
- #include " llvm/ADT/StringRef.h"
17
+ #include " llvm/IR/DataLayout.h"
18
+ #include " llvm/Support/Alignment.h"
19
+ #include " llvm/Support/TypeSize.h"
19
20
20
21
namespace cir {
21
22
23
+ class StructLayout ;
24
+
25
+ // FIXME(cir): This might be replaced by a CIRDataLayout interface which can
26
+ // provide the same functionalities.
22
27
class CIRDataLayout {
23
28
bool bigEndian = false ;
24
29
30
+ // / Primitive type alignment data. This is sorted by type and bit
31
+ // / width during construction.
32
+ llvm::DataLayout::PrimitiveSpec StructAlignment;
33
+
34
+ // The StructType -> StructLayout map.
35
+ mutable void *LayoutMap = nullptr ;
36
+
25
37
public:
26
38
mlir::DataLayout layout;
27
39
28
- // / Constructs a DataLayout from a specification string. See reset().
29
- explicit CIRDataLayout (llvm::StringRef dataLayout, mlir::ModuleOp module)
30
- : layout(module) {
31
- reset (dataLayout);
32
- }
40
+ // / Constructs a DataLayout the module's data layout attribute.
41
+ CIRDataLayout (mlir::ModuleOp modOp);
33
42
34
43
// / Parse a data layout string (with fallback to default values).
35
- void reset (llvm::StringRef dataLayout );
44
+ void reset ();
36
45
37
46
// Free all internal data structures.
38
47
void clear ();
39
48
40
- CIRDataLayout (mlir::ModuleOp modOp);
41
-
42
49
bool isBigEndian () const { return bigEndian; }
43
50
44
- // `useABI` is `true` if not using prefered alignment.
45
- unsigned getAlignment (mlir::Type ty, bool useABI) const {
46
- if (llvm::isa<mlir::cir::StructType>(ty)) {
47
- auto sTy = mlir::cast<mlir::cir::StructType>(ty);
48
- if (sTy .getPacked () && useABI)
49
- return 1 ;
50
- } else if (llvm::isa<mlir::cir::ArrayType>(ty)) {
51
- return getAlignment (mlir::cast<mlir::cir::ArrayType>(ty).getEltType (),
52
- useABI);
53
- }
54
-
55
- return useABI ? layout.getTypeABIAlignment (ty)
56
- : layout.getTypePreferredAlignment (ty);
57
- }
51
+ // / Returns a StructLayout object, indicating the alignment of the
52
+ // / struct, its size, and the offsets of its fields.
53
+ // /
54
+ // / Note that this information is lazily cached.
55
+ const StructLayout *getStructLayout (mlir::cir::StructType Ty) const ;
56
+
57
+ // / Internal helper method that returns requested alignment for type.
58
+ llvm::Align getAlignment (mlir::Type Ty, bool abi_or_pref) const ;
58
59
59
- unsigned getABITypeAlign (mlir::Type ty) const {
60
+ llvm::Align getABITypeAlign (mlir::Type ty) const {
60
61
return getAlignment (ty, true );
61
62
}
62
63
@@ -67,10 +68,10 @@ class CIRDataLayout {
67
68
// / the runtime size will be a positive integer multiple of the base size.
68
69
// /
69
70
// / For example, returns 5 for i36 and 10 for x86_fp80.
70
- unsigned getTypeStoreSize (mlir::Type Ty) const {
71
- // FIXME: this is a bit inaccurate, see DataLayout::getTypeStoreSize for
72
- // more information.
73
- return llvm::divideCeil (layout. getTypeSizeInBits (Ty), 8 ) ;
71
+ llvm::TypeSize getTypeStoreSize (mlir::Type Ty) const {
72
+ llvm::TypeSize BaseSize = getTypeSizeInBits (Ty);
73
+ return { llvm::divideCeil (BaseSize. getKnownMinValue (), 8 ),
74
+ BaseSize. isScalable ()} ;
74
75
}
75
76
76
77
// / Returns the offset in bytes between successive objects of the
@@ -81,20 +82,20 @@ class CIRDataLayout {
81
82
// /
82
83
// / This is the amount that alloca reserves for this type. For example,
83
84
// / returns 12 or 16 for x86_fp80, depending on alignment.
84
- unsigned getTypeAllocSize (mlir::Type Ty) const {
85
+ llvm::TypeSize getTypeAllocSize (mlir::Type Ty) const {
85
86
// Round up to the next alignment boundary.
86
- return llvm::alignTo (getTypeStoreSize (Ty), getABITypeAlign (Ty));
87
+ return llvm::alignTo (getTypeStoreSize (Ty), getABITypeAlign (Ty). value () );
87
88
}
88
89
89
- unsigned getPointerTypeSizeInBits (mlir::Type Ty) const {
90
+ llvm::TypeSize getPointerTypeSizeInBits (mlir::Type Ty) const {
90
91
assert (mlir::isa<mlir::cir::PointerType>(Ty) &&
91
92
" This should only be called with a pointer type" );
92
93
return layout.getTypeSizeInBits (Ty);
93
94
}
94
95
95
- unsigned getTypeSizeInBits (mlir::Type Ty) const {
96
- return layout. getTypeSizeInBits (Ty);
97
- }
96
+ // The implementation of this method is provided inline as it is particularly
97
+ // well suited to constant folding when called on a specific Type subclass.
98
+ llvm::TypeSize getTypeSizeInBits (mlir::Type Ty) const ;
98
99
99
100
mlir::Type getIntPtrType (mlir::Type Ty) const {
100
101
assert (mlir::isa<mlir::cir::PointerType>(Ty) && " Expected pointer type" );
@@ -104,6 +105,58 @@ class CIRDataLayout {
104
105
}
105
106
};
106
107
108
+ // / Used to lazily calculate structure layout information for a target machine,
109
+ // / based on the DataLayout structure.
110
+ class StructLayout final
111
+ : public llvm::TrailingObjects<StructLayout, llvm::TypeSize> {
112
+ llvm::TypeSize StructSize;
113
+ llvm::Align StructAlignment;
114
+ unsigned IsPadded : 1 ;
115
+ unsigned NumElements : 31 ;
116
+
117
+ public:
118
+ llvm::TypeSize getSizeInBytes () const { return StructSize; }
119
+
120
+ llvm::TypeSize getSizeInBits () const { return 8 * StructSize; }
121
+
122
+ llvm::Align getAlignment () const { return StructAlignment; }
123
+
124
+ // / Returns whether the struct has padding or not between its fields.
125
+ // / NB: Padding in nested element is not taken into account.
126
+ bool hasPadding () const { return IsPadded; }
127
+
128
+ // / Given a valid byte offset into the structure, returns the structure
129
+ // / index that contains it.
130
+ unsigned getElementContainingOffset (uint64_t FixedOffset) const ;
131
+
132
+ llvm::MutableArrayRef<llvm::TypeSize> getMemberOffsets () {
133
+ return llvm::MutableArrayRef (getTrailingObjects<llvm::TypeSize>(),
134
+ NumElements);
135
+ }
136
+
137
+ llvm::ArrayRef<llvm::TypeSize> getMemberOffsets () const {
138
+ return llvm::ArrayRef (getTrailingObjects<llvm::TypeSize>(), NumElements);
139
+ }
140
+
141
+ llvm::TypeSize getElementOffset (unsigned Idx) const {
142
+ assert (Idx < NumElements && " Invalid element idx!" );
143
+ return getMemberOffsets ()[Idx];
144
+ }
145
+
146
+ llvm::TypeSize getElementOffsetInBits (unsigned Idx) const {
147
+ return getElementOffset (Idx) * 8 ;
148
+ }
149
+
150
+ private:
151
+ friend class CIRDataLayout ; // Only DataLayout can create this class
152
+
153
+ StructLayout (mlir::cir::StructType ST, const CIRDataLayout &DL);
154
+
155
+ size_t numTrailingObjects (OverloadToken<llvm::TypeSize>) const {
156
+ return NumElements;
157
+ }
158
+ };
159
+
107
160
} // namespace cir
108
161
109
162
#endif
0 commit comments