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