clang 24.0.0git
CIRGenValue.h
Go to the documentation of this file.
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// These classes implement wrappers around mlir::Value in order to fully
10// represent the range of values for C L- and R- values.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef CLANG_LIB_CIR_CIRGENVALUE_H
15#define CLANG_LIB_CIR_CIRGENVALUE_H
16
17#include "Address.h"
18
19#include "clang/AST/CharUnits.h"
20#include "clang/AST/Type.h"
21
22#include "CIRGenRecordLayout.h"
23#include "mlir/IR/Value.h"
24
26
27namespace clang::CIRGen {
28
29/// This trivial value class is used to represent the result of an
30/// expression that is evaluated. It can be one of three things: either a
31/// simple MLIR SSA value, a pair of SSA values for complex numbers, or the
32/// address of an aggregate value in memory.
33class RValue {
34 enum Flavor { Scalar, Complex, Aggregate };
35
36 union {
37 mlir::Value value;
38
39 // Stores aggregate address.
41 };
42
43 unsigned isVolatile : 1;
44 unsigned flavor : 2;
45
46public:
47 RValue() : value(nullptr), flavor(Scalar) {}
48
49 bool isScalar() const { return flavor == Scalar; }
50 bool isComplex() const { return flavor == Complex; }
51 bool isAggregate() const { return flavor == Aggregate; }
52 bool isIgnored() const { return isScalar() && !getValue(); }
53
54 bool isVolatileQualified() const { return isVolatile; }
55
56 /// Return the value of this scalar value.
57 mlir::Value getValue() const {
58 assert(isScalar() && "Not a scalar!");
59 return value;
60 }
61
62 /// Return the value of this complex value.
63 mlir::Value getComplexValue() const {
64 assert(isComplex() && "Not a complex!");
65 return value;
66 }
67
68 /// Return the value of the address of the aggregate.
70 assert(isAggregate() && "Not an aggregate!");
71 return aggregateAddr;
72 }
73
74 mlir::Value getAggregatePointer(QualType pointeeType) const {
76 }
77
78 static RValue getIgnored() {
79 // FIXME: should we make this a more explicit state?
80 return get(nullptr);
81 }
82
83 static RValue get(mlir::Value v) {
84 RValue er;
85 er.value = v;
86 er.flavor = Scalar;
87 er.isVolatile = false;
88 return er;
89 }
90
91 static RValue getComplex(mlir::Value v) {
92 RValue er;
93 er.value = v;
94 er.flavor = Complex;
95 er.isVolatile = false;
96 return er;
97 }
98
99 // volatile or not. Remove default to find all places that probably get this
100 // wrong.
101
102 /// Convert an Address to an RValue. If the Address is not
103 /// signed, create an RValue using the unsigned address. Otherwise, resign the
104 /// address using the provided type.
105 static RValue getAggregate(Address addr, bool isVolatile = false) {
106 RValue er;
107 er.aggregateAddr = addr;
108 er.flavor = Aggregate;
109 er.isVolatile = isVolatile;
110 return er;
111 }
112};
113
114/// The source of the alignment of an l-value; an expression of
115/// confidence in the alignment actually matching the estimate.
116enum class AlignmentSource {
117 /// The l-value was an access to a declared entity or something
118 /// equivalently strong, like the address of an array allocated by a
119 /// language runtime.
121
122 /// The l-value was considered opaque, so the alignment was
123 /// determined from a type, but that type was an explicitly-aligned
124 /// typedef.
126
127 /// The l-value was considered opaque, so the alignment was
128 /// determined from a type.
130};
131
132/// Given that the base address has the given alignment source, what's
133/// our confidence in the alignment of the field?
135 // For now, we don't distinguish fields of opaque pointers from
136 // top-level declarations, but maybe we should.
138}
139
141 AlignmentSource alignSource;
142
143public:
145 : alignSource(source) {}
146 AlignmentSource getAlignmentSource() const { return alignSource; }
147 void setAlignmentSource(AlignmentSource source) { alignSource = source; }
148
149 void mergeForCast(const LValueBaseInfo &info) {
151 }
152};
153
154class LValue {
155 enum {
156 Simple, // This is a normal l-value, use getAddress().
157 VectorElt, // This is a vector element l-value (V[i]), use getVector*
158 BitField, // This is a bitfield l-value, use getBitfield*.
159 ExtVectorElt, // This is an extended vector subset, use getExtVectorComp
160 GlobalReg, // This is a register l-value, use getGlobalReg()
161 MatrixElt, // This is a matrix element, use getVector*
162 MatrixRow // This is a matrix vector subset, use getVector*
163 } lvType;
164 clang::QualType type;
165 clang::Qualifiers quals;
166
167 // The alignment to use when accessing this lvalue. (For vector elements,
168 // this is the alignment of the whole vector)
169 unsigned alignment;
170 mlir::Value v;
171 mlir::Value vectorIdx; // Index for vector subscript
172 mlir::Attribute vectorElts; // ExtVector element subset: V.xyx
173 mlir::Type elementType;
174 LValueBaseInfo baseInfo;
175 const CIRGenBitFieldInfo *bitFieldInfo{nullptr};
176 // This flag shows if a nontemporal load/stores should be used when accessing
177 // this lvalue.
178 bool nontemporal;
179
180 void initialize(clang::QualType type, clang::Qualifiers quals,
181 clang::CharUnits alignment, LValueBaseInfo baseInfo) {
182 assert((!alignment.isZero() || type->isIncompleteType()) &&
183 "initializing l-value with zero alignment!");
184 this->type = type;
185 this->quals = quals;
186 const unsigned maxAlign = 1U << 31;
187 this->alignment = alignment.getQuantity() <= maxAlign
188 ? alignment.getQuantity()
189 : maxAlign;
190 assert(this->alignment == alignment.getQuantity() &&
191 "Alignment exceeds allowed max!");
192 this->baseInfo = baseInfo;
193 this->nontemporal = false;
194 }
195
196public:
197 bool isSimple() const { return lvType == Simple; }
198 bool isVectorElt() const { return lvType == VectorElt; }
199 bool isBitField() const { return lvType == BitField; }
200 bool isExtVectorElt() const { return lvType == ExtVectorElt; }
201 bool isGlobalReg() const { return lvType == GlobalReg; }
202 bool isMatrixElt() const { return lvType == MatrixElt; }
203 bool isMatrixRow() const { return lvType == MatrixRow; }
204 bool isVolatile() const { return quals.hasVolatile(); }
205
206 bool isVolatileQualified() const { return quals.hasVolatile(); }
207
208 bool isNontemporal() const { return nontemporal; }
209 void setNontemporal(bool v) { nontemporal = v; }
210
211 unsigned getVRQualifiers() const {
212 return quals.getCVRQualifiers() & ~clang::Qualifiers::Const;
213 }
214
215 clang::QualType getType() const { return type; }
216
217 mlir::Value getPointer() const { return v; }
218
220 return clang::CharUnits::fromQuantity(alignment);
221 }
222 void setAlignment(clang::CharUnits a) { alignment = a.getQuantity(); }
223
225 return Address(getPointer(), elementType, getAlignment());
226 }
227
228 void setAddress(Address address) {
229 assert(isSimple());
230 v = address.getPointer();
231 elementType = address.getElementType();
232 alignment = address.getAlignment().getQuantity();
234 }
235
236 const clang::Qualifiers &getQuals() const { return quals; }
237 clang::Qualifiers &getQuals() { return quals; }
238
239 LValueBaseInfo getBaseInfo() const { return baseInfo; }
240 void setBaseInfo(LValueBaseInfo info) { baseInfo = info; }
241
243 LValueBaseInfo baseInfo) {
244 // Classic codegen sets the objc gc qualifier here. That requires an
245 // ASTContext, which is passed in from CIRGenFunction::makeAddrLValue.
247
248 LValue r;
249 r.lvType = Simple;
250 r.v = address.getPointer();
251 r.elementType = address.getElementType();
252 r.initialize(t, t.getQualifiers(), address.getAlignment(), baseInfo);
253 return r;
254 }
255
257 return Address(getVectorPointer(), elementType, getAlignment());
258 }
259
260 mlir::Value getVectorPointer() const {
261 assert(isVectorElt());
262 return v;
263 }
264
265 mlir::Value getVectorIdx() const {
266 assert(isVectorElt());
267 return vectorIdx;
268 }
269
270 // extended vector elements.
272 assert(isExtVectorElt());
273 return Address(getExtVectorPointer(), elementType, getAlignment());
274 }
275
276 mlir::Value getExtVectorPointer() const {
277 assert(isExtVectorElt());
278 return v;
279 }
280
281 mlir::ArrayAttr getExtVectorElts() const {
282 assert(isExtVectorElt());
283 return mlir::cast<mlir::ArrayAttr>(vectorElts);
284 }
285
286 static LValue makeVectorElt(Address vecAddress, mlir::Value index,
287 clang::QualType t, LValueBaseInfo baseInfo) {
288 LValue r;
289 r.lvType = VectorElt;
290 r.v = vecAddress.getPointer();
291 r.elementType = vecAddress.getElementType();
292 r.vectorIdx = index;
293 r.initialize(t, t.getQualifiers(), vecAddress.getAlignment(), baseInfo);
294 return r;
295 }
296
297 static LValue makeExtVectorElt(Address vecAddress, mlir::ArrayAttr elts,
298 clang::QualType type,
299 LValueBaseInfo baseInfo) {
300 LValue r;
301 r.lvType = ExtVectorElt;
302 r.v = vecAddress.getPointer();
303 r.elementType = vecAddress.getElementType();
304 r.vectorElts = elts;
305 r.initialize(type, type.getQualifiers(), vecAddress.getAlignment(),
306 baseInfo);
307 return r;
308 }
309
310 // bitfield lvalue
312 return Address(getBitFieldPointer(), elementType, getAlignment());
313 }
314
315 mlir::Value getBitFieldPointer() const {
316 assert(isBitField());
317 return v;
318 }
319
321 assert(isBitField());
322 return *bitFieldInfo;
323 }
324
325 /// Create a new object to represent a bit-field access.
326 ///
327 /// \param Addr - The base address of the bit-field sequence this
328 /// bit-field refers to.
329 /// \param Info - The information describing how to perform the bit-field
330 /// access.
332 clang::QualType type, LValueBaseInfo baseInfo) {
333 LValue r;
334 r.lvType = BitField;
335 r.v = addr.getPointer();
336 r.elementType = addr.getElementType();
337 r.bitFieldInfo = &info;
338 r.initialize(type, type.getQualifiers(), addr.getAlignment(), baseInfo);
339 return r;
340 }
341
345};
346
347/// An aggregate value slot.
349
350 Address addr;
351 clang::Qualifiers quals;
352
353 /// This is set to true if some external code is responsible for setting up a
354 /// destructor for the slot. Otherwise the code which constructs it should
355 /// push the appropriate cleanup.
356 [[maybe_unused]]
357 LLVM_PREFERRED_TYPE(bool) unsigned destructedFlag : 1;
358
359 /// This is set to true if the memory in the slot is known to be zero before
360 /// the assignment into it. This means that zero fields don't need to be set.
361 LLVM_PREFERRED_TYPE(bool)
362 unsigned zeroedFlag : 1;
363
364 /// This is set to true if the slot might be aliased and it's not undefined
365 /// behavior to access it through such an alias. Note that it's always
366 /// undefined behavior to access a C++ object that's under construction
367 /// through an alias derived from outside the construction process.
368 ///
369 /// This flag controls whether calls that produce the aggregate
370 /// value may be evaluated directly into the slot, or whether they
371 /// must be evaluated into an unaliased temporary and then memcpy'ed
372 /// over. Since it's invalid in general to memcpy a non-POD C++
373 /// object, it's important that this flag never be set when
374 /// evaluating an expression which constructs such an object.
375 [[maybe_unused]]
376 LLVM_PREFERRED_TYPE(bool) unsigned aliasedFlag : 1;
377
378 /// This is set to true if the tail padding of this slot might overlap
379 /// another object that may have already been initialized (and whose
380 /// value must be preserved by this initialization). If so, we may only
381 /// store up to the dsize of the type. Otherwise we can widen stores to
382 /// the size of the type.
383 [[maybe_unused]]
384 LLVM_PREFERRED_TYPE(bool) unsigned overlapFlag : 1;
385
386public:
391
392 /// Returns an aggregate value slot indicating that the aggregate
393 /// value is being ignored.
398
399 AggValueSlot(Address addr, clang::Qualifiers quals, bool destructedFlag,
400 bool zeroedFlag, bool aliasedFlag, bool overlapFlag)
401 : addr(addr), quals(quals), destructedFlag(destructedFlag),
402 zeroedFlag(zeroedFlag), aliasedFlag(aliasedFlag),
403 overlapFlag(overlapFlag) {}
404
406 IsDestructed_t isDestructed,
409 return AggValueSlot(addr, quals, isDestructed, isZeroed, isAliased,
410 mayOverlap);
411 }
412
413 static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed,
416 return forAddr(LV.getAddress(), LV.getQuals(), isDestructed, isAliased,
418 }
419
421 return IsDestructed_t(destructedFlag);
422 }
423 void setExternallyDestructed(bool destructed = true) {
424 destructedFlag = destructed;
425 }
426
427 clang::Qualifiers getQualifiers() const { return quals; }
428
429 bool isVolatile() const { return quals.hasVolatile(); }
430
431 void setVolatile(bool flag) {
432 if (flag)
433 quals.addVolatile();
434 else
435 quals.removeVolatile();
436 }
437
438 Address getAddress() const { return addr; }
439
440 bool isIgnored() const { return !addr.isValid(); }
441
442 mlir::Value getPointer() const { return addr.getPointer(); }
443
444 Overlap_t mayOverlap() const { return Overlap_t(overlapFlag); }
445
446 IsZeroed_t isZeroed() const { return IsZeroed_t(zeroedFlag); }
447
448 IsAliased_t isPotentiallyAliased() const { return IsAliased_t(aliasedFlag); }
449
450 RValue asRValue() const {
451 if (isIgnored())
452 return RValue::getIgnored();
455 }
456};
457
458} // namespace clang::CIRGen
459
460#endif // CLANG_LIB_CIR_CIRGENVALUE_H
C Language Family Type Representation.
mlir::Value getPointer() const
Definition Address.h:98
mlir::Type getElementType() const
Definition Address.h:125
static Address invalid()
Definition Address.h:76
clang::CharUnits getAlignment() const
Definition Address.h:138
IsZeroed_t isZeroed() const
Overlap_t mayOverlap() const
IsDestructed_t
This is set to true if the slot might be aliased and it's not undefined behavior to access it through...
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
IsDestructed_t isExternallyDestructed() const
AggValueSlot(Address addr, clang::Qualifiers quals, bool destructedFlag, bool zeroedFlag, bool aliasedFlag, bool overlapFlag)
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
void setExternallyDestructed(bool destructed=true)
static AggValueSlot ignored()
Returns an aggregate value slot indicating that the aggregate value is being ignored.
IsAliased_t isPotentiallyAliased() const
mlir::Value getPointer() const
clang::Qualifiers getQualifiers() const
void setVolatile(bool flag)
AlignmentSource getAlignmentSource() const
void mergeForCast(const LValueBaseInfo &info)
LValueBaseInfo(AlignmentSource source=AlignmentSource::Type)
void setAlignmentSource(AlignmentSource source)
bool isExtVectorElt() const
mlir::Value getBitFieldPointer() const
mlir::Value getVectorPointer() const
const clang::Qualifiers & getQuals() const
mlir::Value getExtVectorPointer() const
bool isMatrixRow() const
static LValue makeExtVectorElt(Address vecAddress, mlir::ArrayAttr elts, clang::QualType type, LValueBaseInfo baseInfo)
mlir::Value getVectorIdx() const
bool isVectorElt() const
Address getAddress() const
static LValue makeAddr(Address address, clang::QualType t, LValueBaseInfo baseInfo)
mlir::ArrayAttr getExtVectorElts() const
bool isMatrixElt() const
static LValue makeVectorElt(Address vecAddress, mlir::Value index, clang::QualType t, LValueBaseInfo baseInfo)
RValue asAggregateRValue() const
unsigned getVRQualifiers() const
clang::QualType getType() const
static LValue makeBitfield(Address addr, const CIRGenBitFieldInfo &info, clang::QualType type, LValueBaseInfo baseInfo)
Create a new object to represent a bit-field access.
mlir::Value getPointer() const
clang::Qualifiers & getQuals()
void setNontemporal(bool v)
bool isVolatileQualified() const
bool isBitField() const
void setAlignment(clang::CharUnits a)
Address getVectorAddress() const
clang::CharUnits getAlignment() const
LValueBaseInfo getBaseInfo() const
void setBaseInfo(LValueBaseInfo info)
bool isNontemporal() const
bool isVolatile() const
bool isGlobalReg() const
const CIRGenBitFieldInfo & getBitFieldInfo() const
Address getBitFieldAddress() const
Address getExtVectorAddress() const
void setAddress(Address address)
bool isSimple() const
This trivial value class is used to represent the result of an expression that is evaluated.
Definition CIRGenValue.h:33
Address getAggregateAddress() const
Return the value of the address of the aggregate.
Definition CIRGenValue.h:69
bool isAggregate() const
Definition CIRGenValue.h:51
static RValue get(mlir::Value v)
Definition CIRGenValue.h:83
static RValue getAggregate(Address addr, bool isVolatile=false)
Convert an Address to an RValue.
mlir::Value getAggregatePointer(QualType pointeeType) const
Definition CIRGenValue.h:74
static RValue getComplex(mlir::Value v)
Definition CIRGenValue.h:91
bool isComplex() const
Definition CIRGenValue.h:50
bool isVolatileQualified() const
Definition CIRGenValue.h:54
mlir::Value getValue() const
Return the value of this scalar value.
Definition CIRGenValue.h:57
bool isScalar() const
Definition CIRGenValue.h:49
bool isIgnored() const
Definition CIRGenValue.h:52
mlir::Value getComplexValue() const
Return the value of this complex value.
Definition CIRGenValue.h:63
static RValue getIgnored()
Definition CIRGenValue.h:78
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
A (possibly-)qualified type.
Definition TypeBase.h:938
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8529
The collection of all-type qualifiers we support.
Definition TypeBase.h:332
AlignmentSource
The source of the alignment of an l-value; an expression of confidence in the alignment actually matc...
@ AttributedType
The l-value was considered opaque, so the alignment was determined from a type, but that type was an ...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
static AlignmentSource getFieldAlignmentSource(AlignmentSource source)
Given that the base address has the given alignment source, what's our confidence in the alignment of...
The JSON file list parser is used to communicate input to InstallAPI.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
static bool aggValueSlot()
static bool addressIsKnownNonNull()
Record with information about how a bitfield should be accessed.