clang 23.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 isMatrixRow() const { return lvType == MatrixRow; }
203 bool isVolatile() const { return quals.hasVolatile(); }
204
205 bool isVolatileQualified() const { return quals.hasVolatile(); }
206
207 bool isNontemporal() const { return nontemporal; }
208 void setNontemporal(bool v) { nontemporal = v; }
209
210 unsigned getVRQualifiers() const {
211 return quals.getCVRQualifiers() & ~clang::Qualifiers::Const;
212 }
213
214 clang::QualType getType() const { return type; }
215
216 mlir::Value getPointer() const { return v; }
217
219 return clang::CharUnits::fromQuantity(alignment);
220 }
221 void setAlignment(clang::CharUnits a) { alignment = a.getQuantity(); }
222
224 return Address(getPointer(), elementType, getAlignment());
225 }
226
227 void setAddress(Address address) {
228 assert(isSimple());
229 v = address.getPointer();
230 elementType = address.getElementType();
231 alignment = address.getAlignment().getQuantity();
233 }
234
235 const clang::Qualifiers &getQuals() const { return quals; }
236 clang::Qualifiers &getQuals() { return quals; }
237
238 LValueBaseInfo getBaseInfo() const { return baseInfo; }
239 void setBaseInfo(LValueBaseInfo info) { baseInfo = info; }
240
242 LValueBaseInfo baseInfo) {
243 // Classic codegen sets the objc gc qualifier here. That requires an
244 // ASTContext, which is passed in from CIRGenFunction::makeAddrLValue.
246
247 LValue r;
248 r.lvType = Simple;
249 r.v = address.getPointer();
250 r.elementType = address.getElementType();
251 r.initialize(t, t.getQualifiers(), address.getAlignment(), baseInfo);
252 return r;
253 }
254
256 return Address(getVectorPointer(), elementType, getAlignment());
257 }
258
259 mlir::Value getVectorPointer() const {
260 assert(isVectorElt());
261 return v;
262 }
263
264 mlir::Value getVectorIdx() const {
265 assert(isVectorElt());
266 return vectorIdx;
267 }
268
269 // extended vector elements.
271 assert(isExtVectorElt());
272 return Address(getExtVectorPointer(), elementType, getAlignment());
273 }
274
275 mlir::Value getExtVectorPointer() const {
276 assert(isExtVectorElt());
277 return v;
278 }
279
280 mlir::ArrayAttr getExtVectorElts() const {
281 assert(isExtVectorElt());
282 return mlir::cast<mlir::ArrayAttr>(vectorElts);
283 }
284
285 static LValue makeVectorElt(Address vecAddress, mlir::Value index,
286 clang::QualType t, LValueBaseInfo baseInfo) {
287 LValue r;
288 r.lvType = VectorElt;
289 r.v = vecAddress.getPointer();
290 r.elementType = vecAddress.getElementType();
291 r.vectorIdx = index;
292 r.initialize(t, t.getQualifiers(), vecAddress.getAlignment(), baseInfo);
293 return r;
294 }
295
296 static LValue makeExtVectorElt(Address vecAddress, mlir::ArrayAttr elts,
297 clang::QualType type,
298 LValueBaseInfo baseInfo) {
299 LValue r;
300 r.lvType = ExtVectorElt;
301 r.v = vecAddress.getPointer();
302 r.elementType = vecAddress.getElementType();
303 r.vectorElts = elts;
304 r.initialize(type, type.getQualifiers(), vecAddress.getAlignment(),
305 baseInfo);
306 return r;
307 }
308
309 // bitfield lvalue
311 return Address(getBitFieldPointer(), elementType, getAlignment());
312 }
313
314 mlir::Value getBitFieldPointer() const {
315 assert(isBitField());
316 return v;
317 }
318
320 assert(isBitField());
321 return *bitFieldInfo;
322 }
323
324 /// Create a new object to represent a bit-field access.
325 ///
326 /// \param Addr - The base address of the bit-field sequence this
327 /// bit-field refers to.
328 /// \param Info - The information describing how to perform the bit-field
329 /// access.
331 clang::QualType type, LValueBaseInfo baseInfo) {
332 LValue r;
333 r.lvType = BitField;
334 r.v = addr.getPointer();
335 r.elementType = addr.getElementType();
336 r.bitFieldInfo = &info;
337 r.initialize(type, type.getQualifiers(), addr.getAlignment(), baseInfo);
338 return r;
339 }
340
344};
345
346/// An aggregate value slot.
348
349 Address addr;
350 clang::Qualifiers quals;
351
352 /// This is set to true if some external code is responsible for setting up a
353 /// destructor for the slot. Otherwise the code which constructs it should
354 /// push the appropriate cleanup.
355 [[maybe_unused]]
356 LLVM_PREFERRED_TYPE(bool) unsigned destructedFlag : 1;
357
358 /// This is set to true if the memory in the slot is known to be zero before
359 /// the assignment into it. This means that zero fields don't need to be set.
360 LLVM_PREFERRED_TYPE(bool)
361 unsigned zeroedFlag : 1;
362
363 /// This is set to true if the slot might be aliased and it's not undefined
364 /// behavior to access it through such an alias. Note that it's always
365 /// undefined behavior to access a C++ object that's under construction
366 /// through an alias derived from outside the construction process.
367 ///
368 /// This flag controls whether calls that produce the aggregate
369 /// value may be evaluated directly into the slot, or whether they
370 /// must be evaluated into an unaliased temporary and then memcpy'ed
371 /// over. Since it's invalid in general to memcpy a non-POD C++
372 /// object, it's important that this flag never be set when
373 /// evaluating an expression which constructs such an object.
374 [[maybe_unused]]
375 LLVM_PREFERRED_TYPE(bool) unsigned aliasedFlag : 1;
376
377 /// This is set to true if the tail padding of this slot might overlap
378 /// another object that may have already been initialized (and whose
379 /// value must be preserved by this initialization). If so, we may only
380 /// store up to the dsize of the type. Otherwise we can widen stores to
381 /// the size of the type.
382 [[maybe_unused]]
383 LLVM_PREFERRED_TYPE(bool) unsigned overlapFlag : 1;
384
385public:
390
391 /// Returns an aggregate value slot indicating that the aggregate
392 /// value is being ignored.
397
398 AggValueSlot(Address addr, clang::Qualifiers quals, bool destructedFlag,
399 bool zeroedFlag, bool aliasedFlag, bool overlapFlag)
400 : addr(addr), quals(quals), destructedFlag(destructedFlag),
401 zeroedFlag(zeroedFlag), aliasedFlag(aliasedFlag),
402 overlapFlag(overlapFlag) {}
403
405 IsDestructed_t isDestructed,
408 return AggValueSlot(addr, quals, isDestructed, isZeroed, isAliased,
409 mayOverlap);
410 }
411
412 static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed,
415 return forAddr(LV.getAddress(), LV.getQuals(), isDestructed, isAliased,
417 }
418
420 return IsDestructed_t(destructedFlag);
421 }
422 void setExternallyDestructed(bool destructed = true) {
423 destructedFlag = destructed;
424 }
425
426 clang::Qualifiers getQualifiers() const { return quals; }
427
428 bool isVolatile() const { return quals.hasVolatile(); }
429
430 void setVolatile(bool flag) {
431 if (flag)
432 quals.addVolatile();
433 else
434 quals.removeVolatile();
435 }
436
437 Address getAddress() const { return addr; }
438
439 bool isIgnored() const { return !addr.isValid(); }
440
441 mlir::Value getPointer() const { return addr.getPointer(); }
442
443 Overlap_t mayOverlap() const { return Overlap_t(overlapFlag); }
444
445 IsZeroed_t isZeroed() const { return IsZeroed_t(zeroedFlag); }
446
447 IsAliased_t isPotentiallyAliased() const { return IsAliased_t(aliasedFlag); }
448
449 RValue asRValue() const {
450 if (isIgnored())
451 return RValue::getIgnored();
454 }
455};
456
457} // namespace clang::CIRGen
458
459#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
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:937
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8487
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
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.