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