Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenValue.h
213799 views
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
25
#include "clang/CIR/MissingFeatures.h"
26
27
namespace 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.
33
class RValue {
34
enum Flavor { Scalar, Complex, Aggregate };
35
36
union {
37
mlir::Value value;
38
39
// Stores aggregate address.
40
Address aggregateAddr;
41
};
42
43
unsigned isVolatile : 1;
44
unsigned flavor : 2;
45
46
public:
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
53
bool isVolatileQualified() const { return isVolatile; }
54
55
/// Return the value of this scalar value.
56
mlir::Value getValue() const {
57
assert(isScalar() && "Not a scalar!");
58
return value;
59
}
60
61
/// Return the value of the address of the aggregate.
62
Address getAggregateAddress() const {
63
assert(isAggregate() && "Not an aggregate!");
64
return aggregateAddr;
65
}
66
67
mlir::Value getAggregatePointer(QualType pointeeType) const {
68
return getAggregateAddress().getPointer();
69
}
70
71
static RValue getIgnored() {
72
// FIXME: should we make this a more explicit state?
73
return get(nullptr);
74
}
75
76
static RValue get(mlir::Value v) {
77
RValue er;
78
er.value = v;
79
er.flavor = Scalar;
80
er.isVolatile = false;
81
return er;
82
}
83
84
static RValue getComplex(mlir::Value v) {
85
RValue er;
86
er.value = v;
87
er.flavor = Complex;
88
er.isVolatile = false;
89
return er;
90
}
91
92
// volatile or not. Remove default to find all places that probably get this
93
// wrong.
94
95
/// Convert an Address to an RValue. If the Address is not
96
/// signed, create an RValue using the unsigned address. Otherwise, resign the
97
/// address using the provided type.
98
static RValue getAggregate(Address addr, bool isVolatile = false) {
99
RValue er;
100
er.aggregateAddr = addr;
101
er.flavor = Aggregate;
102
er.isVolatile = isVolatile;
103
return er;
104
}
105
};
106
107
/// The source of the alignment of an l-value; an expression of
108
/// confidence in the alignment actually matching the estimate.
109
enum class AlignmentSource {
110
/// The l-value was an access to a declared entity or something
111
/// equivalently strong, like the address of an array allocated by a
112
/// language runtime.
113
Decl,
114
115
/// The l-value was considered opaque, so the alignment was
116
/// determined from a type, but that type was an explicitly-aligned
117
/// typedef.
118
AttributedType,
119
120
/// The l-value was considered opaque, so the alignment was
121
/// determined from a type.
122
Type
123
};
124
125
/// Given that the base address has the given alignment source, what's
126
/// our confidence in the alignment of the field?
127
static inline AlignmentSource getFieldAlignmentSource(AlignmentSource source) {
128
// For now, we don't distinguish fields of opaque pointers from
129
// top-level declarations, but maybe we should.
130
return AlignmentSource::Decl;
131
}
132
133
class LValueBaseInfo {
134
AlignmentSource alignSource;
135
136
public:
137
explicit LValueBaseInfo(AlignmentSource source = AlignmentSource::Type)
138
: alignSource(source) {}
139
AlignmentSource getAlignmentSource() const { return alignSource; }
140
void setAlignmentSource(AlignmentSource source) { alignSource = source; }
141
142
void mergeForCast(const LValueBaseInfo &info) {
143
setAlignmentSource(info.getAlignmentSource());
144
}
145
};
146
147
class LValue {
148
enum {
149
Simple, // This is a normal l-value, use getAddress().
150
VectorElt, // This is a vector element l-value (V[i]), use getVector*
151
BitField, // This is a bitfield l-value, use getBitfield*.
152
ExtVectorElt, // This is an extended vector subset, use getExtVectorComp
153
GlobalReg, // This is a register l-value, use getGlobalReg()
154
MatrixElt // This is a matrix element, use getVector*
155
} lvType;
156
clang::QualType type;
157
clang::Qualifiers quals;
158
159
// The alignment to use when accessing this lvalue. (For vector elements,
160
// this is the alignment of the whole vector)
161
unsigned alignment;
162
mlir::Value v;
163
mlir::Value vectorIdx; // Index for vector subscript
164
mlir::Type elementType;
165
LValueBaseInfo baseInfo;
166
const CIRGenBitFieldInfo *bitFieldInfo{nullptr};
167
168
void initialize(clang::QualType type, clang::Qualifiers quals,
169
clang::CharUnits alignment, LValueBaseInfo baseInfo) {
170
assert((!alignment.isZero() || type->isIncompleteType()) &&
171
"initializing l-value with zero alignment!");
172
this->type = type;
173
this->quals = quals;
174
const unsigned maxAlign = 1U << 31;
175
this->alignment = alignment.getQuantity() <= maxAlign
176
? alignment.getQuantity()
177
: maxAlign;
178
assert(this->alignment == alignment.getQuantity() &&
179
"Alignment exceeds allowed max!");
180
this->baseInfo = baseInfo;
181
}
182
183
public:
184
bool isSimple() const { return lvType == Simple; }
185
bool isVectorElt() const { return lvType == VectorElt; }
186
bool isBitField() const { return lvType == BitField; }
187
bool isVolatile() const { return quals.hasVolatile(); }
188
189
bool isVolatileQualified() const { return quals.hasVolatile(); }
190
191
unsigned getVRQualifiers() const {
192
return quals.getCVRQualifiers() & ~clang::Qualifiers::Const;
193
}
194
195
clang::QualType getType() const { return type; }
196
197
mlir::Value getPointer() const { return v; }
198
199
clang::CharUnits getAlignment() const {
200
return clang::CharUnits::fromQuantity(alignment);
201
}
202
void setAlignment(clang::CharUnits a) { alignment = a.getQuantity(); }
203
204
Address getAddress() const {
205
return Address(getPointer(), elementType, getAlignment());
206
}
207
208
const clang::Qualifiers &getQuals() const { return quals; }
209
clang::Qualifiers &getQuals() { return quals; }
210
211
LValueBaseInfo getBaseInfo() const { return baseInfo; }
212
void setBaseInfo(LValueBaseInfo info) { baseInfo = info; }
213
214
static LValue makeAddr(Address address, clang::QualType t,
215
LValueBaseInfo baseInfo) {
216
// Classic codegen sets the objc gc qualifier here. That requires an
217
// ASTContext, which is passed in from CIRGenFunction::makeAddrLValue.
218
assert(!cir::MissingFeatures::objCGC());
219
220
LValue r;
221
r.lvType = Simple;
222
r.v = address.getPointer();
223
r.elementType = address.getElementType();
224
r.initialize(t, t.getQualifiers(), address.getAlignment(), baseInfo);
225
return r;
226
}
227
228
Address getVectorAddress() const {
229
return Address(getVectorPointer(), elementType, getAlignment());
230
}
231
232
mlir::Value getVectorPointer() const {
233
assert(isVectorElt());
234
return v;
235
}
236
237
mlir::Value getVectorIdx() const {
238
assert(isVectorElt());
239
return vectorIdx;
240
}
241
242
static LValue makeVectorElt(Address vecAddress, mlir::Value index,
243
clang::QualType t, LValueBaseInfo baseInfo) {
244
LValue r;
245
r.lvType = VectorElt;
246
r.v = vecAddress.getPointer();
247
r.elementType = vecAddress.getElementType();
248
r.vectorIdx = index;
249
r.initialize(t, t.getQualifiers(), vecAddress.getAlignment(), baseInfo);
250
return r;
251
}
252
253
// bitfield lvalue
254
Address getBitFieldAddress() const {
255
return Address(getBitFieldPointer(), elementType, getAlignment());
256
}
257
258
mlir::Value getBitFieldPointer() const {
259
assert(isBitField());
260
return v;
261
}
262
263
const CIRGenBitFieldInfo &getBitFieldInfo() const {
264
assert(isBitField());
265
return *bitFieldInfo;
266
}
267
268
/// Create a new object to represent a bit-field access.
269
///
270
/// \param Addr - The base address of the bit-field sequence this
271
/// bit-field refers to.
272
/// \param Info - The information describing how to perform the bit-field
273
/// access.
274
static LValue makeBitfield(Address addr, const CIRGenBitFieldInfo &info,
275
clang::QualType type, LValueBaseInfo baseInfo) {
276
LValue r;
277
r.lvType = BitField;
278
r.v = addr.getPointer();
279
r.elementType = addr.getElementType();
280
r.bitFieldInfo = &info;
281
r.initialize(type, type.getQualifiers(), addr.getAlignment(), baseInfo);
282
return r;
283
}
284
};
285
286
/// An aggregate value slot.
287
class AggValueSlot {
288
289
Address addr;
290
clang::Qualifiers quals;
291
292
/// This is set to true if some external code is responsible for setting up a
293
/// destructor for the slot. Otherwise the code which constructs it should
294
/// push the appropriate cleanup.
295
LLVM_PREFERRED_TYPE(bool)
296
LLVM_ATTRIBUTE_UNUSED unsigned destructedFlag : 1;
297
298
/// This is set to true if the memory in the slot is known to be zero before
299
/// the assignment into it. This means that zero fields don't need to be set.
300
LLVM_PREFERRED_TYPE(bool)
301
unsigned zeroedFlag : 1;
302
303
/// This is set to true if the slot might be aliased and it's not undefined
304
/// behavior to access it through such an alias. Note that it's always
305
/// undefined behavior to access a C++ object that's under construction
306
/// through an alias derived from outside the construction process.
307
///
308
/// This flag controls whether calls that produce the aggregate
309
/// value may be evaluated directly into the slot, or whether they
310
/// must be evaluated into an unaliased temporary and then memcpy'ed
311
/// over. Since it's invalid in general to memcpy a non-POD C++
312
/// object, it's important that this flag never be set when
313
/// evaluating an expression which constructs such an object.
314
LLVM_PREFERRED_TYPE(bool)
315
LLVM_ATTRIBUTE_UNUSED unsigned aliasedFlag : 1;
316
317
/// This is set to true if the tail padding of this slot might overlap
318
/// another object that may have already been initialized (and whose
319
/// value must be preserved by this initialization). If so, we may only
320
/// store up to the dsize of the type. Otherwise we can widen stores to
321
/// the size of the type.
322
LLVM_PREFERRED_TYPE(bool)
323
LLVM_ATTRIBUTE_UNUSED unsigned overlapFlag : 1;
324
325
public:
326
enum IsDestructed_t { IsNotDestructed, IsDestructed };
327
enum IsZeroed_t { IsNotZeroed, IsZeroed };
328
enum IsAliased_t { IsNotAliased, IsAliased };
329
enum Overlap_t { MayOverlap, DoesNotOverlap };
330
331
/// Returns an aggregate value slot indicating that the aggregate
332
/// value is being ignored.
333
static AggValueSlot ignored() {
334
return forAddr(Address::invalid(), clang::Qualifiers(), IsNotDestructed,
335
IsNotAliased, DoesNotOverlap);
336
}
337
338
AggValueSlot(Address addr, clang::Qualifiers quals, bool destructedFlag,
339
bool zeroedFlag, bool aliasedFlag, bool overlapFlag)
340
: addr(addr), quals(quals), destructedFlag(destructedFlag),
341
zeroedFlag(zeroedFlag), aliasedFlag(aliasedFlag),
342
overlapFlag(overlapFlag) {}
343
344
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals,
345
IsDestructed_t isDestructed,
346
IsAliased_t isAliased, Overlap_t mayOverlap,
347
IsZeroed_t isZeroed = IsNotZeroed) {
348
return AggValueSlot(addr, quals, isDestructed, isZeroed, isAliased,
349
mayOverlap);
350
}
351
352
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed,
353
IsAliased_t isAliased, Overlap_t mayOverlap,
354
IsZeroed_t isZeroed = IsNotZeroed) {
355
return forAddr(LV.getAddress(), LV.getQuals(), isDestructed, isAliased,
356
mayOverlap, isZeroed);
357
}
358
359
clang::Qualifiers getQualifiers() const { return quals; }
360
361
Address getAddress() const { return addr; }
362
363
bool isIgnored() const { return !addr.isValid(); }
364
365
mlir::Value getPointer() const { return addr.getPointer(); }
366
367
IsZeroed_t isZeroed() const { return IsZeroed_t(zeroedFlag); }
368
369
RValue asRValue() const {
370
if (isIgnored())
371
return RValue::getIgnored();
372
assert(!cir::MissingFeatures::aggValueSlot());
373
return RValue::getAggregate(getAddress());
374
}
375
};
376
377
} // namespace clang::CIRGen
378
379
#endif // CLANG_LIB_CIR_CIRGENVALUE_H
380
381