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
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) {
150 setAlignmentSource(info.getAlignmentSource());
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 & MatrixElt row idx
172 mlir::Value matrixColIdx; // Matrix column index for MatrixElt
173 mlir::Attribute vectorElts; // ExtVector element subset: V.xyx
174 mlir::Type elementType;
175 LValueBaseInfo baseInfo;
176 const CIRGenBitFieldInfo *bitFieldInfo{nullptr};
177 // This flag shows if a nontemporal load/stores should be used when accessing
178 // this lvalue.
179 bool nontemporal;
180
181 void initialize(clang::QualType type, clang::Qualifiers quals,
182 clang::CharUnits alignment, LValueBaseInfo baseInfo) {
183 assert((!alignment.isZero() || type->isIncompleteType()) &&
184 "initializing l-value with zero alignment!");
185 this->type = type;
186 this->quals = quals;
187 const unsigned maxAlign = 1U << 31;
188 this->alignment = alignment.getQuantity() <= maxAlign
189 ? alignment.getQuantity()
190 : maxAlign;
191 assert(this->alignment == alignment.getQuantity() &&
192 "Alignment exceeds allowed max!");
193 this->baseInfo = baseInfo;
194 this->nontemporal = false;
195 }
196
197public:
198 bool isSimple() const { return lvType == Simple; }
199 bool isVectorElt() const { return lvType == VectorElt; }
200 bool isBitField() const { return lvType == BitField; }
201 bool isExtVectorElt() const { return lvType == ExtVectorElt; }
202 bool isGlobalReg() const { return lvType == GlobalReg; }
203 bool isMatrixElt() const { return lvType == MatrixElt; }
204 bool isMatrixRow() const { return lvType == MatrixRow; }
205 bool isVolatile() const { return quals.hasVolatile(); }
206
207 bool isVolatileQualified() const { return quals.hasVolatile(); }
208
209 bool isNontemporal() const { return nontemporal; }
210 void setNontemporal(bool v) { nontemporal = v; }
211
212 unsigned getVRQualifiers() const {
213 return quals.getCVRQualifiers() & ~clang::Qualifiers::Const;
214 }
215
216 clang::QualType getType() const { return type; }
217
218 mlir::Value getPointer() const { return v; }
219
221 return clang::CharUnits::fromQuantity(alignment);
222 }
223 void setAlignment(clang::CharUnits a) { alignment = a.getQuantity(); }
224
226 return Address(getPointer(), elementType, getAlignment());
227 }
228
229 void setAddress(Address address) {
230 assert(isSimple());
231 v = address.getPointer();
232 elementType = address.getElementType();
233 alignment = address.getAlignment().getQuantity();
235 }
236
237 const clang::Qualifiers &getQuals() const { return quals; }
238 clang::Qualifiers &getQuals() { return quals; }
239
240 LValueBaseInfo getBaseInfo() const { return baseInfo; }
241 void setBaseInfo(LValueBaseInfo info) { baseInfo = info; }
242
244 LValueBaseInfo baseInfo) {
245 // Classic codegen sets the objc gc qualifier here. That requires an
246 // ASTContext, which is passed in from CIRGenFunction::makeAddrLValue.
248
249 LValue r;
250 r.lvType = Simple;
251 r.v = address.getPointer();
252 r.elementType = address.getElementType();
253 r.initialize(t, t.getQualifiers(), address.getAlignment(), baseInfo);
254 return r;
255 }
256
258 return Address(getVectorPointer(), elementType, getAlignment());
259 }
260
261 mlir::Value getVectorPointer() const {
262 assert(isVectorElt());
263 return v;
264 }
265
266 mlir::Value getVectorIdx() const {
267 assert(isVectorElt());
268 return vectorIdx;
269 }
270
271 // extended vector elements.
273 assert(isExtVectorElt());
274 return Address(getExtVectorPointer(), elementType, getAlignment());
275 }
276
277 mlir::Value getExtVectorPointer() const {
278 assert(isExtVectorElt());
279 return v;
280 }
281
282 mlir::ArrayAttr getExtVectorElts() const {
283 assert(isExtVectorElt());
284 return mlir::cast<mlir::ArrayAttr>(vectorElts);
285 }
286
287 static LValue makeVectorElt(Address vecAddress, mlir::Value index,
288 clang::QualType t, LValueBaseInfo baseInfo) {
289 LValue r;
290 r.lvType = VectorElt;
291 r.v = vecAddress.getPointer();
292 r.elementType = vecAddress.getElementType();
293 r.vectorIdx = index;
294 r.initialize(t, t.getQualifiers(), vecAddress.getAlignment(), baseInfo);
295 return r;
296 }
297
299 assert(isMatrixElt());
300 return Address(v, elementType, getAlignment());
301 }
302
303 mlir::Value getMatrixRowIdx() const {
304 assert(isMatrixElt());
305 return vectorIdx;
306 }
307
308 mlir::Value getMatrixColumnIdx() const {
309 assert(isMatrixElt());
310 return matrixColIdx;
311 }
312
313 static LValue makeMatrixElt(Address matAddress, mlir::Value rowIdx,
314 mlir::Value colIdx, clang::QualType t,
315 LValueBaseInfo baseInfo) {
316 LValue r;
317 r.lvType = MatrixElt;
318 r.v = matAddress.getPointer();
319 r.elementType = matAddress.getElementType();
320 r.vectorIdx = rowIdx;
321 r.matrixColIdx = colIdx;
322 r.initialize(t, t.getQualifiers(), matAddress.getAlignment(), baseInfo);
323 return r;
324 }
325
326 static LValue makeExtVectorElt(Address vecAddress, mlir::ArrayAttr elts,
327 clang::QualType type,
328 LValueBaseInfo baseInfo) {
329 LValue r;
330 r.lvType = ExtVectorElt;
331 r.v = vecAddress.getPointer();
332 r.elementType = vecAddress.getElementType();
333 r.vectorElts = elts;
334 r.initialize(type, type.getQualifiers(), vecAddress.getAlignment(),
335 baseInfo);
336 return r;
337 }
338
339 // bitfield lvalue
341 return Address(getBitFieldPointer(), elementType, getAlignment());
342 }
343
344 mlir::Value getBitFieldPointer() const {
345 assert(isBitField());
346 return v;
347 }
348
350 assert(isBitField());
351 return *bitFieldInfo;
352 }
353
354 /// Create a new object to represent a bit-field access.
355 ///
356 /// \param Addr - The base address of the bit-field sequence this
357 /// bit-field refers to.
358 /// \param Info - The information describing how to perform the bit-field
359 /// access.
361 clang::QualType type, LValueBaseInfo baseInfo) {
362 LValue r;
363 r.lvType = BitField;
364 r.v = addr.getPointer();
365 r.elementType = addr.getElementType();
366 r.bitFieldInfo = &info;
367 r.initialize(type, type.getQualifiers(), addr.getAlignment(), baseInfo);
368 return r;
369 }
370
374};
375
376/// An aggregate value slot.
378
379 Address addr;
380 clang::Qualifiers quals;
381
382 /// This is set to true if some external code is responsible for setting up a
383 /// destructor for the slot. Otherwise the code which constructs it should
384 /// push the appropriate cleanup.
385 [[maybe_unused]]
386 LLVM_PREFERRED_TYPE(bool) unsigned destructedFlag : 1;
387
388 /// This is set to true if the memory in the slot is known to be zero before
389 /// the assignment into it. This means that zero fields don't need to be set.
390 LLVM_PREFERRED_TYPE(bool)
391 unsigned zeroedFlag : 1;
392
393 /// This is set to true if the slot might be aliased and it's not undefined
394 /// behavior to access it through such an alias. Note that it's always
395 /// undefined behavior to access a C++ object that's under construction
396 /// through an alias derived from outside the construction process.
397 ///
398 /// This flag controls whether calls that produce the aggregate
399 /// value may be evaluated directly into the slot, or whether they
400 /// must be evaluated into an unaliased temporary and then memcpy'ed
401 /// over. Since it's invalid in general to memcpy a non-POD C++
402 /// object, it's important that this flag never be set when
403 /// evaluating an expression which constructs such an object.
404 [[maybe_unused]]
405 LLVM_PREFERRED_TYPE(bool) unsigned aliasedFlag : 1;
406
407 /// This is set to true if the tail padding of this slot might overlap
408 /// another object that may have already been initialized (and whose
409 /// value must be preserved by this initialization). If so, we may only
410 /// store up to the dsize of the type. Otherwise we can widen stores to
411 /// the size of the type.
412 [[maybe_unused]]
413 LLVM_PREFERRED_TYPE(bool) unsigned overlapFlag : 1;
414
415public:
420
421 /// Returns an aggregate value slot indicating that the aggregate
422 /// value is being ignored.
427
428 AggValueSlot(Address addr, clang::Qualifiers quals, bool destructedFlag,
429 bool zeroedFlag, bool aliasedFlag, bool overlapFlag)
430 : addr(addr), quals(quals), destructedFlag(destructedFlag),
431 zeroedFlag(zeroedFlag), aliasedFlag(aliasedFlag),
432 overlapFlag(overlapFlag) {}
433
435 IsDestructed_t isDestructed,
438 return AggValueSlot(addr, quals, isDestructed, isZeroed, isAliased,
439 mayOverlap);
440 }
441
442 static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed,
445 return forAddr(LV.getAddress(), LV.getQuals(), isDestructed, isAliased,
447 }
448
450 return IsDestructed_t(destructedFlag);
451 }
452 void setExternallyDestructed(bool destructed = true) {
453 destructedFlag = destructed;
454 }
455
456 clang::Qualifiers getQualifiers() const { return quals; }
457
458 bool isVolatile() const { return quals.hasVolatile(); }
459
460 void setVolatile(bool flag) {
461 if (flag)
462 quals.addVolatile();
463 else
464 quals.removeVolatile();
465 }
466
467 Address getAddress() const { return addr; }
468
469 bool isIgnored() const { return !addr.isValid(); }
470
471 mlir::Value getPointer() const { return addr.getPointer(); }
472
473 Overlap_t mayOverlap() const { return Overlap_t(overlapFlag); }
474
475 IsZeroed_t isZeroed() const { return IsZeroed_t(zeroedFlag); }
476
477 IsAliased_t isPotentiallyAliased() const { return IsAliased_t(aliasedFlag); }
478
479 RValue asRValue() const {
480 if (isIgnored())
481 return RValue::getIgnored();
484 }
485};
486
487} // namespace clang::CIRGen
488
489#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()
Address getMatrixAddress() const
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
mlir::Value getMatrixColumnIdx() const
void setBaseInfo(LValueBaseInfo info)
bool isNontemporal() const
bool isVolatile() const
static LValue makeMatrixElt(Address matAddress, mlir::Value rowIdx, mlir::Value colIdx, clang::QualType t, LValueBaseInfo baseInfo)
bool isGlobalReg() const
const CIRGenBitFieldInfo & getBitFieldInfo() const
Address getBitFieldAddress() const
Address getExtVectorAddress() const
mlir::Value getMatrixRowIdx() 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
This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
Definition CharUnits.h:155
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:58
A (possibly-)qualified type.
Definition TypeBase.h:938
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8486
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...
Top level wrappers for InstallAPI frontend operations.
QualType pointeeType(QualType T)
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.