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/CIRGenExprScalar.cpp
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
// Emit Expr nodes with scalar CIR types as CIR code.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "CIRGenFunction.h"
14
#include "CIRGenValue.h"
15
16
#include "clang/AST/Expr.h"
17
#include "clang/AST/StmtVisitor.h"
18
#include "clang/CIR/MissingFeatures.h"
19
20
#include "mlir/IR/Location.h"
21
#include "mlir/IR/Value.h"
22
23
#include <cassert>
24
#include <utility>
25
26
using namespace clang;
27
using namespace clang::CIRGen;
28
29
namespace {
30
31
struct BinOpInfo {
32
mlir::Value lhs;
33
mlir::Value rhs;
34
SourceRange loc;
35
QualType fullType; // Type of operands and result
36
QualType compType; // Type used for computations. Element type
37
// for vectors, otherwise same as FullType.
38
BinaryOperator::Opcode opcode; // Opcode of BinOp to perform
39
FPOptions fpfeatures;
40
const Expr *e; // Entire expr, for error unsupported. May not be binop.
41
42
/// Check if the binop computes a division or a remainder.
43
bool isDivRemOp() const {
44
return opcode == BO_Div || opcode == BO_Rem || opcode == BO_DivAssign ||
45
opcode == BO_RemAssign;
46
}
47
48
/// Check if the binop can result in integer overflow.
49
bool mayHaveIntegerOverflow() const {
50
// Without constant input, we can't rule out overflow.
51
auto lhsci = dyn_cast<cir::ConstantOp>(lhs.getDefiningOp());
52
auto rhsci = dyn_cast<cir::ConstantOp>(rhs.getDefiningOp());
53
if (!lhsci || !rhsci)
54
return true;
55
56
assert(!cir::MissingFeatures::mayHaveIntegerOverflow());
57
// TODO(cir): For now we just assume that we might overflow
58
return true;
59
}
60
61
/// Check if at least one operand is a fixed point type. In such cases,
62
/// this operation did not follow usual arithmetic conversion and both
63
/// operands might not be of the same type.
64
bool isFixedPointOp() const {
65
// We cannot simply check the result type since comparison operations
66
// return an int.
67
if (const auto *binOp = llvm::dyn_cast<BinaryOperator>(e)) {
68
QualType lhstype = binOp->getLHS()->getType();
69
QualType rhstype = binOp->getRHS()->getType();
70
return lhstype->isFixedPointType() || rhstype->isFixedPointType();
71
}
72
if (const auto *unop = llvm::dyn_cast<UnaryOperator>(e))
73
return unop->getSubExpr()->getType()->isFixedPointType();
74
return false;
75
}
76
};
77
78
class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
79
CIRGenFunction &cgf;
80
CIRGenBuilderTy &builder;
81
bool ignoreResultAssign;
82
83
public:
84
ScalarExprEmitter(CIRGenFunction &cgf, CIRGenBuilderTy &builder)
85
: cgf(cgf), builder(builder) {}
86
87
//===--------------------------------------------------------------------===//
88
// Utilities
89
//===--------------------------------------------------------------------===//
90
91
mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
92
return builder.createFloatingCast(result, cgf.convertType(promotionType));
93
}
94
95
mlir::Value emitUnPromotedValue(mlir::Value result, QualType exprType) {
96
return builder.createFloatingCast(result, cgf.convertType(exprType));
97
}
98
99
mlir::Value emitPromoted(const Expr *e, QualType promotionType);
100
101
mlir::Value maybePromoteBoolResult(mlir::Value value,
102
mlir::Type dstTy) const {
103
if (mlir::isa<cir::IntType>(dstTy))
104
return builder.createBoolToInt(value, dstTy);
105
if (mlir::isa<cir::BoolType>(dstTy))
106
return value;
107
llvm_unreachable("Can only promote integer or boolean types");
108
}
109
110
//===--------------------------------------------------------------------===//
111
// Visitor Methods
112
//===--------------------------------------------------------------------===//
113
114
mlir::Value Visit(Expr *e) {
115
return StmtVisitor<ScalarExprEmitter, mlir::Value>::Visit(e);
116
}
117
118
mlir::Value VisitStmt(Stmt *s) {
119
llvm_unreachable("Statement passed to ScalarExprEmitter");
120
}
121
122
mlir::Value VisitExpr(Expr *e) {
123
cgf.getCIRGenModule().errorNYI(
124
e->getSourceRange(), "scalar expression kind: ", e->getStmtClassName());
125
return {};
126
}
127
128
mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
129
return Visit(e->getSelectedExpr());
130
}
131
132
mlir::Value VisitParenExpr(ParenExpr *pe) { return Visit(pe->getSubExpr()); }
133
134
mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
135
return Visit(ge->getResultExpr());
136
}
137
138
/// Emits the address of the l-value, then loads and returns the result.
139
mlir::Value emitLoadOfLValue(const Expr *e) {
140
LValue lv = cgf.emitLValue(e);
141
// FIXME: add some akin to EmitLValueAlignmentAssumption(E, V);
142
return cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();
143
}
144
145
mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc) {
146
return cgf.emitLoadOfLValue(lv, loc).getValue();
147
}
148
149
// l-values
150
mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
151
if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
152
return cgf.emitScalarConstant(constant, e);
153
154
return emitLoadOfLValue(e);
155
}
156
157
mlir::Value VisitIntegerLiteral(const IntegerLiteral *e) {
158
mlir::Type type = cgf.convertType(e->getType());
159
return builder.create<cir::ConstantOp>(
160
cgf.getLoc(e->getExprLoc()), cir::IntAttr::get(type, e->getValue()));
161
}
162
163
mlir::Value VisitFloatingLiteral(const FloatingLiteral *e) {
164
mlir::Type type = cgf.convertType(e->getType());
165
assert(mlir::isa<cir::FPTypeInterface>(type) &&
166
"expect floating-point type");
167
return builder.create<cir::ConstantOp>(
168
cgf.getLoc(e->getExprLoc()), cir::FPAttr::get(type, e->getValue()));
169
}
170
171
mlir::Value VisitCharacterLiteral(const CharacterLiteral *e) {
172
mlir::Type ty = cgf.convertType(e->getType());
173
auto init = cir::IntAttr::get(ty, e->getValue());
174
return builder.create<cir::ConstantOp>(cgf.getLoc(e->getExprLoc()), init);
175
}
176
177
mlir::Value VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *e) {
178
return builder.getBool(e->getValue(), cgf.getLoc(e->getExprLoc()));
179
}
180
181
mlir::Value VisitCastExpr(CastExpr *e);
182
mlir::Value VisitCallExpr(const CallExpr *e);
183
184
mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
185
if (e->getBase()->getType()->isVectorType()) {
186
assert(!cir::MissingFeatures::scalableVectors());
187
188
const mlir::Location loc = cgf.getLoc(e->getSourceRange());
189
const mlir::Value vecValue = Visit(e->getBase());
190
const mlir::Value indexValue = Visit(e->getIdx());
191
return cgf.builder.create<cir::VecExtractOp>(loc, vecValue, indexValue);
192
}
193
// Just load the lvalue formed by the subscript expression.
194
return emitLoadOfLValue(e);
195
}
196
197
mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
198
if (e->getNumSubExprs() == 2) {
199
// The undocumented form of __builtin_shufflevector.
200
mlir::Value inputVec = Visit(e->getExpr(0));
201
mlir::Value indexVec = Visit(e->getExpr(1));
202
return cgf.builder.create<cir::VecShuffleDynamicOp>(
203
cgf.getLoc(e->getSourceRange()), inputVec, indexVec);
204
}
205
206
mlir::Value vec1 = Visit(e->getExpr(0));
207
mlir::Value vec2 = Visit(e->getExpr(1));
208
209
// The documented form of __builtin_shufflevector, where the indices are
210
// a variable number of integer constants. The constants will be stored
211
// in an ArrayAttr.
212
SmallVector<mlir::Attribute, 8> indices;
213
for (unsigned i = 2; i < e->getNumSubExprs(); ++i) {
214
indices.push_back(
215
cir::IntAttr::get(cgf.builder.getSInt64Ty(),
216
e->getExpr(i)
217
->EvaluateKnownConstInt(cgf.getContext())
218
.getSExtValue()));
219
}
220
221
return cgf.builder.create<cir::VecShuffleOp>(
222
cgf.getLoc(e->getSourceRange()), cgf.convertType(e->getType()), vec1,
223
vec2, cgf.builder.getArrayAttr(indices));
224
}
225
226
mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
227
// __builtin_convertvector is an element-wise cast, and is implemented as a
228
// regular cast. The back end handles casts of vectors correctly.
229
return emitScalarConversion(Visit(e->getSrcExpr()),
230
e->getSrcExpr()->getType(), e->getType(),
231
e->getSourceRange().getBegin());
232
}
233
234
mlir::Value VisitMemberExpr(MemberExpr *e);
235
236
mlir::Value VisitInitListExpr(InitListExpr *e);
237
238
mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
239
return VisitCastExpr(e);
240
}
241
242
mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
243
return cgf.cgm.emitNullConstant(e->getType(),
244
cgf.getLoc(e->getSourceRange()));
245
}
246
247
/// Perform a pointer to boolean conversion.
248
mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
249
// TODO(cir): comparing the ptr to null is done when lowering CIR to LLVM.
250
// We might want to have a separate pass for these types of conversions.
251
return cgf.getBuilder().createPtrToBoolCast(v);
252
}
253
254
mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
255
cir::BoolType boolTy = builder.getBoolTy();
256
return builder.create<cir::CastOp>(loc, boolTy,
257
cir::CastKind::float_to_bool, src);
258
}
259
260
mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
261
// Because of the type rules of C, we often end up computing a
262
// logical value, then zero extending it to int, then wanting it
263
// as a logical value again.
264
// TODO: optimize this common case here or leave it for later
265
// CIR passes?
266
cir::BoolType boolTy = builder.getBoolTy();
267
return builder.create<cir::CastOp>(loc, boolTy, cir::CastKind::int_to_bool,
268
srcVal);
269
}
270
271
/// Convert the specified expression value to a boolean (!cir.bool) truth
272
/// value. This is equivalent to "Val != 0".
273
mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
274
mlir::Location loc) {
275
assert(srcType.isCanonical() && "EmitScalarConversion strips typedefs");
276
277
if (srcType->isRealFloatingType())
278
return emitFloatToBoolConversion(src, loc);
279
280
if (llvm::isa<MemberPointerType>(srcType)) {
281
cgf.getCIRGenModule().errorNYI(loc, "member pointer to bool conversion");
282
return builder.getFalse(loc);
283
}
284
285
if (srcType->isIntegerType())
286
return emitIntToBoolConversion(src, loc);
287
288
assert(::mlir::isa<cir::PointerType>(src.getType()));
289
return emitPointerToBoolConversion(src, srcType);
290
}
291
292
// Emit a conversion from the specified type to the specified destination
293
// type, both of which are CIR scalar types.
294
struct ScalarConversionOpts {
295
bool treatBooleanAsSigned;
296
bool emitImplicitIntegerTruncationChecks;
297
bool emitImplicitIntegerSignChangeChecks;
298
299
ScalarConversionOpts()
300
: treatBooleanAsSigned(false),
301
emitImplicitIntegerTruncationChecks(false),
302
emitImplicitIntegerSignChangeChecks(false) {}
303
304
ScalarConversionOpts(clang::SanitizerSet sanOpts)
305
: treatBooleanAsSigned(false),
306
emitImplicitIntegerTruncationChecks(
307
sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
308
emitImplicitIntegerSignChangeChecks(
309
sanOpts.has(SanitizerKind::ImplicitIntegerSignChange)) {}
310
};
311
312
// Conversion from bool, integral, or floating-point to integral or
313
// floating-point. Conversions involving other types are handled elsewhere.
314
// Conversion to bool is handled elsewhere because that's a comparison against
315
// zero, not a simple cast. This handles both individual scalars and vectors.
316
mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
317
QualType dstType, mlir::Type srcTy,
318
mlir::Type dstTy, ScalarConversionOpts opts) {
319
assert(!srcType->isMatrixType() && !dstType->isMatrixType() &&
320
"Internal error: matrix types not handled by this function.");
321
assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
322
mlir::isa<mlir::IntegerType>(dstTy)) &&
323
"Obsolete code. Don't use mlir::IntegerType with CIR.");
324
325
mlir::Type fullDstTy = dstTy;
326
if (mlir::isa<cir::VectorType>(srcTy) &&
327
mlir::isa<cir::VectorType>(dstTy)) {
328
// Use the element types of the vectors to figure out the CastKind.
329
srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
330
dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
331
}
332
333
std::optional<cir::CastKind> castKind;
334
335
if (mlir::isa<cir::BoolType>(srcTy)) {
336
if (opts.treatBooleanAsSigned)
337
cgf.getCIRGenModule().errorNYI("signed bool");
338
if (cgf.getBuilder().isInt(dstTy))
339
castKind = cir::CastKind::bool_to_int;
340
else if (mlir::isa<cir::FPTypeInterface>(dstTy))
341
castKind = cir::CastKind::bool_to_float;
342
else
343
llvm_unreachable("Internal error: Cast to unexpected type");
344
} else if (cgf.getBuilder().isInt(srcTy)) {
345
if (cgf.getBuilder().isInt(dstTy))
346
castKind = cir::CastKind::integral;
347
else if (mlir::isa<cir::FPTypeInterface>(dstTy))
348
castKind = cir::CastKind::int_to_float;
349
else
350
llvm_unreachable("Internal error: Cast to unexpected type");
351
} else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
352
if (cgf.getBuilder().isInt(dstTy)) {
353
// If we can't recognize overflow as undefined behavior, assume that
354
// overflow saturates. This protects against normal optimizations if we
355
// are compiling with non-standard FP semantics.
356
if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
357
cgf.getCIRGenModule().errorNYI("strict float cast overflow");
358
assert(!cir::MissingFeatures::fpConstraints());
359
castKind = cir::CastKind::float_to_int;
360
} else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
361
// TODO: split this to createFPExt/createFPTrunc
362
return builder.createFloatingCast(src, fullDstTy);
363
} else {
364
llvm_unreachable("Internal error: Cast to unexpected type");
365
}
366
} else {
367
llvm_unreachable("Internal error: Cast from unexpected type");
368
}
369
370
assert(castKind.has_value() && "Internal error: CastKind not set.");
371
return builder.create<cir::CastOp>(src.getLoc(), fullDstTy, *castKind, src);
372
}
373
374
mlir::Value
375
VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
376
return Visit(e->getReplacement());
377
}
378
379
mlir::Value VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *e);
380
mlir::Value
381
VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);
382
383
// Unary Operators.
384
mlir::Value VisitUnaryPostDec(const UnaryOperator *e) {
385
LValue lv = cgf.emitLValue(e->getSubExpr());
386
return emitScalarPrePostIncDec(e, lv, false, false);
387
}
388
mlir::Value VisitUnaryPostInc(const UnaryOperator *e) {
389
LValue lv = cgf.emitLValue(e->getSubExpr());
390
return emitScalarPrePostIncDec(e, lv, true, false);
391
}
392
mlir::Value VisitUnaryPreDec(const UnaryOperator *e) {
393
LValue lv = cgf.emitLValue(e->getSubExpr());
394
return emitScalarPrePostIncDec(e, lv, false, true);
395
}
396
mlir::Value VisitUnaryPreInc(const UnaryOperator *e) {
397
LValue lv = cgf.emitLValue(e->getSubExpr());
398
return emitScalarPrePostIncDec(e, lv, true, true);
399
}
400
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv,
401
bool isInc, bool isPre) {
402
if (cgf.getLangOpts().OpenMP)
403
cgf.cgm.errorNYI(e->getSourceRange(), "inc/dec OpenMP");
404
405
QualType type = e->getSubExpr()->getType();
406
407
mlir::Value value;
408
mlir::Value input;
409
410
if (type->getAs<AtomicType>()) {
411
cgf.cgm.errorNYI(e->getSourceRange(), "Atomic inc/dec");
412
// TODO(cir): This is not correct, but it will produce reasonable code
413
// until atomic operations are implemented.
414
value = cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();
415
input = value;
416
} else {
417
value = cgf.emitLoadOfLValue(lv, e->getExprLoc()).getValue();
418
input = value;
419
}
420
421
// NOTE: When possible, more frequent cases are handled first.
422
423
// Special case of integer increment that we have to check first: bool++.
424
// Due to promotion rules, we get:
425
// bool++ -> bool = bool + 1
426
// -> bool = (int)bool + 1
427
// -> bool = ((int)bool + 1 != 0)
428
// An interesting aspect of this is that increment is always true.
429
// Decrement does not have this property.
430
if (isInc && type->isBooleanType()) {
431
value = builder.getTrue(cgf.getLoc(e->getExprLoc()));
432
} else if (type->isIntegerType()) {
433
QualType promotedType;
434
bool canPerformLossyDemotionCheck = false;
435
if (cgf.getContext().isPromotableIntegerType(type)) {
436
promotedType = cgf.getContext().getPromotedIntegerType(type);
437
assert(promotedType != type && "Shouldn't promote to the same type.");
438
canPerformLossyDemotionCheck = true;
439
canPerformLossyDemotionCheck &=
440
cgf.getContext().getCanonicalType(type) !=
441
cgf.getContext().getCanonicalType(promotedType);
442
canPerformLossyDemotionCheck &=
443
type->isIntegerType() && promotedType->isIntegerType();
444
445
// TODO(cir): Currently, we store bitwidths in CIR types only for
446
// integers. This might also be required for other types.
447
448
assert(
449
(!canPerformLossyDemotionCheck ||
450
type->isSignedIntegerOrEnumerationType() ||
451
promotedType->isSignedIntegerOrEnumerationType() ||
452
mlir::cast<cir::IntType>(cgf.convertType(type)).getWidth() ==
453
mlir::cast<cir::IntType>(cgf.convertType(type)).getWidth()) &&
454
"The following check expects that if we do promotion to different "
455
"underlying canonical type, at least one of the types (either "
456
"base or promoted) will be signed, or the bitwidths will match.");
457
}
458
459
assert(!cir::MissingFeatures::sanitizers());
460
if (e->canOverflow() && type->isSignedIntegerOrEnumerationType()) {
461
value = emitIncDecConsiderOverflowBehavior(e, value, isInc);
462
} else {
463
cir::UnaryOpKind kind =
464
e->isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;
465
// NOTE(CIR): clang calls CreateAdd but folds this to a unary op
466
value = emitUnaryOp(e, kind, input, /*nsw=*/false);
467
}
468
} else if (const PointerType *ptr = type->getAs<PointerType>()) {
469
QualType type = ptr->getPointeeType();
470
if (cgf.getContext().getAsVariableArrayType(type)) {
471
// VLA types don't have constant size.
472
cgf.cgm.errorNYI(e->getSourceRange(), "Pointer arithmetic on VLA");
473
return {};
474
} else if (type->isFunctionType()) {
475
// Arithmetic on function pointers (!) is just +-1.
476
cgf.cgm.errorNYI(e->getSourceRange(),
477
"Pointer arithmetic on function pointer");
478
return {};
479
} else {
480
// For everything else, we can just do a simple increment.
481
mlir::Location loc = cgf.getLoc(e->getSourceRange());
482
CIRGenBuilderTy &builder = cgf.getBuilder();
483
int amount = (isInc ? 1 : -1);
484
mlir::Value amt = builder.getSInt32(amount, loc);
485
assert(!cir::MissingFeatures::sanitizers());
486
value = builder.createPtrStride(loc, value, amt);
487
}
488
} else if (type->isVectorType()) {
489
cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec vector");
490
return {};
491
} else if (type->isRealFloatingType()) {
492
assert(!cir::MissingFeatures::cgFPOptionsRAII());
493
494
if (type->isHalfType() &&
495
!cgf.getContext().getLangOpts().NativeHalfType) {
496
cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec half");
497
return {};
498
}
499
500
if (mlir::isa<cir::SingleType, cir::DoubleType>(value.getType())) {
501
// Create the inc/dec operation.
502
// NOTE(CIR): clang calls CreateAdd but folds this to a unary op
503
cir::UnaryOpKind kind =
504
(isInc ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec);
505
value = emitUnaryOp(e, kind, value);
506
} else {
507
cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec other fp type");
508
return {};
509
}
510
} else if (type->isFixedPointType()) {
511
cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec other fixed point");
512
return {};
513
} else {
514
assert(type->castAs<ObjCObjectPointerType>());
515
cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec ObjectiveC pointer");
516
return {};
517
}
518
519
CIRGenFunction::SourceLocRAIIObject sourceloc{
520
cgf, cgf.getLoc(e->getSourceRange())};
521
522
// Store the updated result through the lvalue
523
if (lv.isBitField())
524
return cgf.emitStoreThroughBitfieldLValue(RValue::get(value), lv);
525
else
526
cgf.emitStoreThroughLValue(RValue::get(value), lv);
527
528
// If this is a postinc, return the value read from memory, otherwise use
529
// the updated value.
530
return isPre ? value : input;
531
}
532
533
mlir::Value emitIncDecConsiderOverflowBehavior(const UnaryOperator *e,
534
mlir::Value inVal,
535
bool isInc) {
536
cir::UnaryOpKind kind =
537
e->isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;
538
switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
539
case LangOptions::SOB_Defined:
540
return emitUnaryOp(e, kind, inVal, /*nsw=*/false);
541
case LangOptions::SOB_Undefined:
542
assert(!cir::MissingFeatures::sanitizers());
543
return emitUnaryOp(e, kind, inVal, /*nsw=*/true);
544
case LangOptions::SOB_Trapping:
545
if (!e->canOverflow())
546
return emitUnaryOp(e, kind, inVal, /*nsw=*/true);
547
cgf.cgm.errorNYI(e->getSourceRange(), "inc/def overflow SOB_Trapping");
548
return {};
549
}
550
llvm_unreachable("Unexpected signed overflow behavior kind");
551
}
552
553
mlir::Value VisitUnaryAddrOf(const UnaryOperator *e) {
554
if (llvm::isa<MemberPointerType>(e->getType())) {
555
cgf.cgm.errorNYI(e->getSourceRange(), "Address of member pointer");
556
return builder.getNullPtr(cgf.convertType(e->getType()),
557
cgf.getLoc(e->getExprLoc()));
558
}
559
560
return cgf.emitLValue(e->getSubExpr()).getPointer();
561
}
562
563
mlir::Value VisitUnaryDeref(const UnaryOperator *e) {
564
if (e->getType()->isVoidType())
565
return Visit(e->getSubExpr()); // the actual value should be unused
566
return emitLoadOfLValue(e);
567
}
568
569
mlir::Value VisitUnaryPlus(const UnaryOperator *e) {
570
return emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus);
571
}
572
573
mlir::Value VisitUnaryMinus(const UnaryOperator *e) {
574
return emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus);
575
}
576
577
mlir::Value emitUnaryPlusOrMinus(const UnaryOperator *e,
578
cir::UnaryOpKind kind) {
579
ignoreResultAssign = false;
580
581
QualType promotionType = getPromotionType(e->getSubExpr()->getType());
582
583
mlir::Value operand;
584
if (!promotionType.isNull())
585
operand = cgf.emitPromotedScalarExpr(e->getSubExpr(), promotionType);
586
else
587
operand = Visit(e->getSubExpr());
588
589
bool nsw =
590
kind == cir::UnaryOpKind::Minus && e->getType()->isSignedIntegerType();
591
592
// NOTE: LLVM codegen will lower this directly to either a FNeg
593
// or a Sub instruction. In CIR this will be handled later in LowerToLLVM.
594
mlir::Value result = emitUnaryOp(e, kind, operand, nsw);
595
if (result && !promotionType.isNull())
596
return emitUnPromotedValue(result, e->getType());
597
return result;
598
}
599
600
mlir::Value emitUnaryOp(const UnaryOperator *e, cir::UnaryOpKind kind,
601
mlir::Value input, bool nsw = false) {
602
return builder.create<cir::UnaryOp>(
603
cgf.getLoc(e->getSourceRange().getBegin()), input.getType(), kind,
604
input, nsw);
605
}
606
607
mlir::Value VisitUnaryNot(const UnaryOperator *e) {
608
ignoreResultAssign = false;
609
mlir::Value op = Visit(e->getSubExpr());
610
return emitUnaryOp(e, cir::UnaryOpKind::Not, op);
611
}
612
613
mlir::Value VisitUnaryLNot(const UnaryOperator *e);
614
615
mlir::Value VisitUnaryReal(const UnaryOperator *e);
616
617
mlir::Value VisitUnaryImag(const UnaryOperator *e);
618
619
mlir::Value VisitCXXThisExpr(CXXThisExpr *te) { return cgf.loadCXXThis(); }
620
621
mlir::Value VisitCXXNewExpr(const CXXNewExpr *e) {
622
return cgf.emitCXXNewExpr(e);
623
}
624
625
/// Emit a conversion from the specified type to the specified destination
626
/// type, both of which are CIR scalar types.
627
/// TODO: do we need ScalarConversionOpts here? Should be done in another
628
/// pass.
629
mlir::Value
630
emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
631
SourceLocation loc,
632
ScalarConversionOpts opts = ScalarConversionOpts()) {
633
// All conversions involving fixed point types should be handled by the
634
// emitFixedPoint family functions. This is done to prevent bloating up
635
// this function more, and although fixed point numbers are represented by
636
// integers, we do not want to follow any logic that assumes they should be
637
// treated as integers.
638
// TODO(leonardchan): When necessary, add another if statement checking for
639
// conversions to fixed point types from other types.
640
// conversions to fixed point types from other types.
641
if (srcType->isFixedPointType() || dstType->isFixedPointType()) {
642
cgf.getCIRGenModule().errorNYI(loc, "fixed point conversions");
643
return {};
644
}
645
646
srcType = srcType.getCanonicalType();
647
dstType = dstType.getCanonicalType();
648
if (srcType == dstType) {
649
if (opts.emitImplicitIntegerSignChangeChecks)
650
cgf.getCIRGenModule().errorNYI(loc,
651
"implicit integer sign change checks");
652
return src;
653
}
654
655
if (dstType->isVoidType())
656
return {};
657
658
mlir::Type mlirSrcType = src.getType();
659
660
// Handle conversions to bool first, they are special: comparisons against
661
// 0.
662
if (dstType->isBooleanType())
663
return emitConversionToBool(src, srcType, cgf.getLoc(loc));
664
665
mlir::Type mlirDstType = cgf.convertType(dstType);
666
667
if (srcType->isHalfType() &&
668
!cgf.getContext().getLangOpts().NativeHalfType) {
669
// Cast to FP using the intrinsic if the half type itself isn't supported.
670
if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
671
if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
672
cgf.getCIRGenModule().errorNYI(loc,
673
"cast via llvm.convert.from.fp16");
674
} else {
675
// Cast to other types through float, using either the intrinsic or
676
// FPExt, depending on whether the half type itself is supported (as
677
// opposed to operations on half, available with NativeHalfType).
678
if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
679
cgf.getCIRGenModule().errorNYI(loc,
680
"cast via llvm.convert.from.fp16");
681
// FIXME(cir): For now lets pretend we shouldn't use the conversion
682
// intrinsics and insert a cast here unconditionally.
683
src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
684
cgf.FloatTy);
685
srcType = cgf.getContext().FloatTy;
686
mlirSrcType = cgf.FloatTy;
687
}
688
}
689
690
// TODO(cir): LLVM codegen ignore conversions like int -> uint,
691
// is there anything to be done for CIR here?
692
if (mlirSrcType == mlirDstType) {
693
if (opts.emitImplicitIntegerSignChangeChecks)
694
cgf.getCIRGenModule().errorNYI(loc,
695
"implicit integer sign change checks");
696
return src;
697
}
698
699
// Handle pointer conversions next: pointers can only be converted to/from
700
// other pointers and integers. Check for pointer types in terms of LLVM, as
701
// some native types (like Obj-C id) may map to a pointer type.
702
if (auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
703
cgf.getCIRGenModule().errorNYI(loc, "pointer casts");
704
return builder.getNullPtr(dstPT, src.getLoc());
705
}
706
707
if (isa<cir::PointerType>(mlirSrcType)) {
708
// Must be an ptr to int cast.
709
assert(isa<cir::IntType>(mlirDstType) && "not ptr->int?");
710
return builder.createPtrToInt(src, mlirDstType);
711
}
712
713
// A scalar can be splatted to an extended vector of the same element type
714
if (dstType->isExtVectorType() && !srcType->isVectorType()) {
715
// Sema should add casts to make sure that the source expression's type
716
// is the same as the vector's element type (sans qualifiers)
717
assert(dstType->castAs<ExtVectorType>()->getElementType().getTypePtr() ==
718
srcType.getTypePtr() &&
719
"Splatted expr doesn't match with vector element type?");
720
721
cgf.getCIRGenModule().errorNYI(loc, "vector splatting");
722
return {};
723
}
724
725
if (srcType->isMatrixType() && dstType->isMatrixType()) {
726
cgf.getCIRGenModule().errorNYI(loc,
727
"matrix type to matrix type conversion");
728
return {};
729
}
730
assert(!srcType->isMatrixType() && !dstType->isMatrixType() &&
731
"Internal error: conversion between matrix type and scalar type");
732
733
// Finally, we have the arithmetic types or vectors of arithmetic types.
734
mlir::Value res = nullptr;
735
mlir::Type resTy = mlirDstType;
736
737
res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
738
739
if (mlirDstType != resTy) {
740
if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
741
cgf.getCIRGenModule().errorNYI(loc, "cast via llvm.convert.to.fp16");
742
}
743
// FIXME(cir): For now we never use FP16 conversion intrinsics even if
744
// required by the target. Change that once this is implemented
745
res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
746
resTy);
747
}
748
749
if (opts.emitImplicitIntegerTruncationChecks)
750
cgf.getCIRGenModule().errorNYI(loc, "implicit integer truncation checks");
751
752
if (opts.emitImplicitIntegerSignChangeChecks)
753
cgf.getCIRGenModule().errorNYI(loc,
754
"implicit integer sign change checks");
755
756
return res;
757
}
758
759
BinOpInfo emitBinOps(const BinaryOperator *e,
760
QualType promotionType = QualType()) {
761
BinOpInfo result;
762
result.lhs = cgf.emitPromotedScalarExpr(e->getLHS(), promotionType);
763
result.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionType);
764
if (!promotionType.isNull())
765
result.fullType = promotionType;
766
else
767
result.fullType = e->getType();
768
result.compType = result.fullType;
769
if (const auto *vecType = dyn_cast_or_null<VectorType>(result.fullType)) {
770
result.compType = vecType->getElementType();
771
}
772
result.opcode = e->getOpcode();
773
result.loc = e->getSourceRange();
774
// TODO(cir): Result.FPFeatures
775
assert(!cir::MissingFeatures::cgFPOptionsRAII());
776
result.e = e;
777
return result;
778
}
779
780
mlir::Value emitMul(const BinOpInfo &ops);
781
mlir::Value emitDiv(const BinOpInfo &ops);
782
mlir::Value emitRem(const BinOpInfo &ops);
783
mlir::Value emitAdd(const BinOpInfo &ops);
784
mlir::Value emitSub(const BinOpInfo &ops);
785
mlir::Value emitShl(const BinOpInfo &ops);
786
mlir::Value emitShr(const BinOpInfo &ops);
787
mlir::Value emitAnd(const BinOpInfo &ops);
788
mlir::Value emitXor(const BinOpInfo &ops);
789
mlir::Value emitOr(const BinOpInfo &ops);
790
791
LValue emitCompoundAssignLValue(
792
const CompoundAssignOperator *e,
793
mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &),
794
mlir::Value &result);
795
mlir::Value
796
emitCompoundAssign(const CompoundAssignOperator *e,
797
mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &));
798
799
// TODO(cir): Candidate to be in a common AST helper between CIR and LLVM
800
// codegen.
801
QualType getPromotionType(QualType ty) {
802
if (ty->getAs<ComplexType>()) {
803
assert(!cir::MissingFeatures::complexType());
804
cgf.cgm.errorNYI("promotion to complex type");
805
return QualType();
806
}
807
if (ty.UseExcessPrecision(cgf.getContext())) {
808
if (ty->getAs<VectorType>()) {
809
assert(!cir::MissingFeatures::vectorType());
810
cgf.cgm.errorNYI("promotion to vector type");
811
return QualType();
812
}
813
return cgf.getContext().FloatTy;
814
}
815
return QualType();
816
}
817
818
// Binary operators and binary compound assignment operators.
819
#define HANDLEBINOP(OP) \
820
mlir::Value VisitBin##OP(const BinaryOperator *e) { \
821
QualType promotionTy = getPromotionType(e->getType()); \
822
auto result = emit##OP(emitBinOps(e, promotionTy)); \
823
if (result && !promotionTy.isNull()) \
824
result = emitUnPromotedValue(result, e->getType()); \
825
return result; \
826
} \
827
mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
828
return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
829
}
830
831
HANDLEBINOP(Mul)
832
HANDLEBINOP(Div)
833
HANDLEBINOP(Rem)
834
HANDLEBINOP(Add)
835
HANDLEBINOP(Sub)
836
HANDLEBINOP(Shl)
837
HANDLEBINOP(Shr)
838
HANDLEBINOP(And)
839
HANDLEBINOP(Xor)
840
HANDLEBINOP(Or)
841
#undef HANDLEBINOP
842
843
mlir::Value emitCmp(const BinaryOperator *e) {
844
const mlir::Location loc = cgf.getLoc(e->getExprLoc());
845
mlir::Value result;
846
QualType lhsTy = e->getLHS()->getType();
847
QualType rhsTy = e->getRHS()->getType();
848
849
auto clangCmpToCIRCmp =
850
[](clang::BinaryOperatorKind clangCmp) -> cir::CmpOpKind {
851
switch (clangCmp) {
852
case BO_LT:
853
return cir::CmpOpKind::lt;
854
case BO_GT:
855
return cir::CmpOpKind::gt;
856
case BO_LE:
857
return cir::CmpOpKind::le;
858
case BO_GE:
859
return cir::CmpOpKind::ge;
860
case BO_EQ:
861
return cir::CmpOpKind::eq;
862
case BO_NE:
863
return cir::CmpOpKind::ne;
864
default:
865
llvm_unreachable("unsupported comparison kind for cir.cmp");
866
}
867
};
868
869
cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode());
870
if (lhsTy->getAs<MemberPointerType>()) {
871
assert(!cir::MissingFeatures::dataMemberType());
872
assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE);
873
mlir::Value lhs = cgf.emitScalarExpr(e->getLHS());
874
mlir::Value rhs = cgf.emitScalarExpr(e->getRHS());
875
result = builder.createCompare(loc, kind, lhs, rhs);
876
} else if (!lhsTy->isAnyComplexType() && !rhsTy->isAnyComplexType()) {
877
BinOpInfo boInfo = emitBinOps(e);
878
mlir::Value lhs = boInfo.lhs;
879
mlir::Value rhs = boInfo.rhs;
880
881
if (lhsTy->isVectorType()) {
882
if (!e->getType()->isVectorType()) {
883
// If AltiVec, the comparison results in a numeric type, so we use
884
// intrinsics comparing vectors and giving 0 or 1 as a result
885
cgf.cgm.errorNYI(loc, "AltiVec comparison");
886
} else {
887
// Other kinds of vectors. Element-wise comparison returning
888
// a vector.
889
result = builder.create<cir::VecCmpOp>(
890
cgf.getLoc(boInfo.loc), cgf.convertType(boInfo.fullType), kind,
891
boInfo.lhs, boInfo.rhs);
892
}
893
} else if (boInfo.isFixedPointOp()) {
894
assert(!cir::MissingFeatures::fixedPointType());
895
cgf.cgm.errorNYI(loc, "fixed point comparisons");
896
result = builder.getBool(false, loc);
897
} else {
898
// integers and pointers
899
if (cgf.cgm.getCodeGenOpts().StrictVTablePointers &&
900
mlir::isa<cir::PointerType>(lhs.getType()) &&
901
mlir::isa<cir::PointerType>(rhs.getType())) {
902
cgf.cgm.errorNYI(loc, "strict vtable pointer comparisons");
903
}
904
905
cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode());
906
result = builder.createCompare(loc, kind, lhs, rhs);
907
}
908
} else {
909
// Complex Comparison: can only be an equality comparison.
910
assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE);
911
912
BinOpInfo boInfo = emitBinOps(e);
913
result = builder.create<cir::CmpOp>(loc, kind, boInfo.lhs, boInfo.rhs);
914
}
915
916
return emitScalarConversion(result, cgf.getContext().BoolTy, e->getType(),
917
e->getExprLoc());
918
}
919
920
// Comparisons.
921
#define VISITCOMP(CODE) \
922
mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
923
VISITCOMP(LT)
924
VISITCOMP(GT)
925
VISITCOMP(LE)
926
VISITCOMP(GE)
927
VISITCOMP(EQ)
928
VISITCOMP(NE)
929
#undef VISITCOMP
930
931
mlir::Value VisitBinAssign(const BinaryOperator *e) {
932
const bool ignore = std::exchange(ignoreResultAssign, false);
933
934
mlir::Value rhs;
935
LValue lhs;
936
937
switch (e->getLHS()->getType().getObjCLifetime()) {
938
case Qualifiers::OCL_Strong:
939
case Qualifiers::OCL_Autoreleasing:
940
case Qualifiers::OCL_ExplicitNone:
941
case Qualifiers::OCL_Weak:
942
assert(!cir::MissingFeatures::objCLifetime());
943
break;
944
case Qualifiers::OCL_None:
945
// __block variables need to have the rhs evaluated first, plus this
946
// should improve codegen just a little.
947
rhs = Visit(e->getRHS());
948
assert(!cir::MissingFeatures::sanitizers());
949
// TODO(cir): This needs to be emitCheckedLValue() once we support
950
// sanitizers
951
lhs = cgf.emitLValue(e->getLHS());
952
953
// Store the value into the LHS. Bit-fields are handled specially because
954
// the result is altered by the store, i.e., [C99 6.5.16p1]
955
// 'An assignment expression has the value of the left operand after the
956
// assignment...'.
957
if (lhs.isBitField()) {
958
rhs = cgf.emitStoreThroughBitfieldLValue(RValue::get(rhs), lhs);
959
} else {
960
cgf.emitNullabilityCheck(lhs, rhs, e->getExprLoc());
961
CIRGenFunction::SourceLocRAIIObject loc{
962
cgf, cgf.getLoc(e->getSourceRange())};
963
cgf.emitStoreThroughLValue(RValue::get(rhs), lhs);
964
}
965
}
966
967
// If the result is clearly ignored, return now.
968
if (ignore)
969
return nullptr;
970
971
// The result of an assignment in C is the assigned r-value.
972
if (!cgf.getLangOpts().CPlusPlus)
973
return rhs;
974
975
// If the lvalue is non-volatile, return the computed value of the
976
// assignment.
977
if (!lhs.isVolatile())
978
return rhs;
979
980
// Otherwise, reload the value.
981
return emitLoadOfLValue(lhs, e->getExprLoc());
982
}
983
984
mlir::Value VisitBinComma(const BinaryOperator *e) {
985
cgf.emitIgnoredExpr(e->getLHS());
986
// NOTE: We don't need to EnsureInsertPoint() like LLVM codegen.
987
return Visit(e->getRHS());
988
}
989
990
mlir::Value VisitBinLAnd(const clang::BinaryOperator *e) {
991
if (e->getType()->isVectorType()) {
992
assert(!cir::MissingFeatures::vectorType());
993
return {};
994
}
995
996
assert(!cir::MissingFeatures::instrumentation());
997
mlir::Type resTy = cgf.convertType(e->getType());
998
mlir::Location loc = cgf.getLoc(e->getExprLoc());
999
1000
CIRGenFunction::ConditionalEvaluation eval(cgf);
1001
1002
mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->getLHS());
1003
auto resOp = builder.create<cir::TernaryOp>(
1004
loc, lhsCondV, /*trueBuilder=*/
1005
[&](mlir::OpBuilder &b, mlir::Location loc) {
1006
CIRGenFunction::LexicalScope lexScope{cgf, loc,
1007
b.getInsertionBlock()};
1008
cgf.curLexScope->setAsTernary();
1009
b.create<cir::YieldOp>(loc, cgf.evaluateExprAsBool(e->getRHS()));
1010
},
1011
/*falseBuilder*/
1012
[&](mlir::OpBuilder &b, mlir::Location loc) {
1013
CIRGenFunction::LexicalScope lexScope{cgf, loc,
1014
b.getInsertionBlock()};
1015
cgf.curLexScope->setAsTernary();
1016
auto res = b.create<cir::ConstantOp>(loc, builder.getFalseAttr());
1017
b.create<cir::YieldOp>(loc, res.getRes());
1018
});
1019
return maybePromoteBoolResult(resOp.getResult(), resTy);
1020
}
1021
1022
mlir::Value VisitBinLOr(const clang::BinaryOperator *e) {
1023
if (e->getType()->isVectorType()) {
1024
assert(!cir::MissingFeatures::vectorType());
1025
return {};
1026
}
1027
1028
assert(!cir::MissingFeatures::instrumentation());
1029
mlir::Type resTy = cgf.convertType(e->getType());
1030
mlir::Location loc = cgf.getLoc(e->getExprLoc());
1031
1032
CIRGenFunction::ConditionalEvaluation eval(cgf);
1033
1034
mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->getLHS());
1035
auto resOp = builder.create<cir::TernaryOp>(
1036
loc, lhsCondV, /*trueBuilder=*/
1037
[&](mlir::OpBuilder &b, mlir::Location loc) {
1038
CIRGenFunction::LexicalScope lexScope{cgf, loc,
1039
b.getInsertionBlock()};
1040
cgf.curLexScope->setAsTernary();
1041
auto res = b.create<cir::ConstantOp>(loc, builder.getTrueAttr());
1042
b.create<cir::YieldOp>(loc, res.getRes());
1043
},
1044
/*falseBuilder*/
1045
[&](mlir::OpBuilder &b, mlir::Location loc) {
1046
CIRGenFunction::LexicalScope lexScope{cgf, loc,
1047
b.getInsertionBlock()};
1048
cgf.curLexScope->setAsTernary();
1049
b.create<cir::YieldOp>(loc, cgf.evaluateExprAsBool(e->getRHS()));
1050
});
1051
1052
return maybePromoteBoolResult(resOp.getResult(), resTy);
1053
}
1054
};
1055
1056
LValue ScalarExprEmitter::emitCompoundAssignLValue(
1057
const CompoundAssignOperator *e,
1058
mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &),
1059
mlir::Value &result) {
1060
QualType lhsTy = e->getLHS()->getType();
1061
BinOpInfo opInfo;
1062
1063
if (e->getComputationResultType()->isAnyComplexType()) {
1064
cgf.cgm.errorNYI(result.getLoc(), "complex lvalue assign");
1065
return LValue();
1066
}
1067
1068
// Emit the RHS first. __block variables need to have the rhs evaluated
1069
// first, plus this should improve codegen a little.
1070
1071
QualType promotionTypeCR = getPromotionType(e->getComputationResultType());
1072
if (promotionTypeCR.isNull())
1073
promotionTypeCR = e->getComputationResultType();
1074
1075
QualType promotionTypeLHS = getPromotionType(e->getComputationLHSType());
1076
QualType promotionTypeRHS = getPromotionType(e->getRHS()->getType());
1077
1078
if (!promotionTypeRHS.isNull())
1079
opInfo.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionTypeRHS);
1080
else
1081
opInfo.rhs = Visit(e->getRHS());
1082
1083
opInfo.fullType = promotionTypeCR;
1084
opInfo.compType = opInfo.fullType;
1085
if (const auto *vecType = dyn_cast_or_null<VectorType>(opInfo.fullType))
1086
opInfo.compType = vecType->getElementType();
1087
opInfo.opcode = e->getOpcode();
1088
opInfo.fpfeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
1089
opInfo.e = e;
1090
opInfo.loc = e->getSourceRange();
1091
1092
// Load/convert the LHS
1093
LValue lhsLV = cgf.emitLValue(e->getLHS());
1094
1095
if (lhsTy->getAs<AtomicType>()) {
1096
cgf.cgm.errorNYI(result.getLoc(), "atomic lvalue assign");
1097
return LValue();
1098
}
1099
1100
opInfo.lhs = emitLoadOfLValue(lhsLV, e->getExprLoc());
1101
1102
CIRGenFunction::SourceLocRAIIObject sourceloc{
1103
cgf, cgf.getLoc(e->getSourceRange())};
1104
SourceLocation loc = e->getExprLoc();
1105
if (!promotionTypeLHS.isNull())
1106
opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1107
else
1108
opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1109
e->getComputationLHSType(), loc);
1110
1111
// Expand the binary operator.
1112
result = (this->*func)(opInfo);
1113
1114
// Convert the result back to the LHS type,
1115
// potentially with Implicit Conversion sanitizer check.
1116
result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1117
ScalarConversionOpts(cgf.sanOpts));
1118
1119
// Store the result value into the LHS lvalue. Bit-fields are handled
1120
// specially because the result is altered by the store, i.e., [C99 6.5.16p1]
1121
// 'An assignment expression has the value of the left operand after the
1122
// assignment...'.
1123
if (lhsLV.isBitField())
1124
cgf.cgm.errorNYI(e->getSourceRange(), "store through bitfield lvalue");
1125
else
1126
cgf.emitStoreThroughLValue(RValue::get(result), lhsLV);
1127
1128
if (cgf.getLangOpts().OpenMP)
1129
cgf.cgm.errorNYI(e->getSourceRange(), "openmp");
1130
1131
return lhsLV;
1132
}
1133
1134
mlir::Value ScalarExprEmitter::emitPromoted(const Expr *e,
1135
QualType promotionType) {
1136
e = e->IgnoreParens();
1137
if (const auto *bo = dyn_cast<BinaryOperator>(e)) {
1138
switch (bo->getOpcode()) {
1139
#define HANDLE_BINOP(OP) \
1140
case BO_##OP: \
1141
return emit##OP(emitBinOps(bo, promotionType));
1142
HANDLE_BINOP(Add)
1143
HANDLE_BINOP(Sub)
1144
HANDLE_BINOP(Mul)
1145
HANDLE_BINOP(Div)
1146
#undef HANDLE_BINOP
1147
default:
1148
break;
1149
}
1150
} else if (isa<UnaryOperator>(e)) {
1151
cgf.cgm.errorNYI(e->getSourceRange(), "unary operators");
1152
return {};
1153
}
1154
mlir::Value result = Visit(const_cast<Expr *>(e));
1155
if (result) {
1156
if (!promotionType.isNull())
1157
return emitPromotedValue(result, promotionType);
1158
return emitUnPromotedValue(result, e->getType());
1159
}
1160
return result;
1161
}
1162
1163
mlir::Value ScalarExprEmitter::emitCompoundAssign(
1164
const CompoundAssignOperator *e,
1165
mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &)) {
1166
1167
bool ignore = std::exchange(ignoreResultAssign, false);
1168
mlir::Value rhs;
1169
LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1170
1171
// If the result is clearly ignored, return now.
1172
if (ignore)
1173
return {};
1174
1175
// The result of an assignment in C is the assigned r-value.
1176
if (!cgf.getLangOpts().CPlusPlus)
1177
return rhs;
1178
1179
// If the lvalue is non-volatile, return the computed value of the assignment.
1180
if (!lhs.isVolatile())
1181
return rhs;
1182
1183
// Otherwise, reload the value.
1184
return emitLoadOfLValue(lhs, e->getExprLoc());
1185
}
1186
1187
} // namespace
1188
1189
LValue
1190
CIRGenFunction::emitCompoundAssignmentLValue(const CompoundAssignOperator *e) {
1191
ScalarExprEmitter emitter(*this, builder);
1192
mlir::Value result;
1193
switch (e->getOpcode()) {
1194
#define COMPOUND_OP(Op) \
1195
case BO_##Op##Assign: \
1196
return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1197
result)
1198
COMPOUND_OP(Mul);
1199
COMPOUND_OP(Div);
1200
COMPOUND_OP(Rem);
1201
COMPOUND_OP(Add);
1202
COMPOUND_OP(Sub);
1203
COMPOUND_OP(Shl);
1204
COMPOUND_OP(Shr);
1205
COMPOUND_OP(And);
1206
COMPOUND_OP(Xor);
1207
COMPOUND_OP(Or);
1208
#undef COMPOUND_OP
1209
1210
case BO_PtrMemD:
1211
case BO_PtrMemI:
1212
case BO_Mul:
1213
case BO_Div:
1214
case BO_Rem:
1215
case BO_Add:
1216
case BO_Sub:
1217
case BO_Shl:
1218
case BO_Shr:
1219
case BO_LT:
1220
case BO_GT:
1221
case BO_LE:
1222
case BO_GE:
1223
case BO_EQ:
1224
case BO_NE:
1225
case BO_Cmp:
1226
case BO_And:
1227
case BO_Xor:
1228
case BO_Or:
1229
case BO_LAnd:
1230
case BO_LOr:
1231
case BO_Assign:
1232
case BO_Comma:
1233
llvm_unreachable("Not valid compound assignment operators");
1234
}
1235
llvm_unreachable("Unhandled compound assignment operator");
1236
}
1237
1238
/// Emit the computation of the specified expression of scalar type.
1239
mlir::Value CIRGenFunction::emitScalarExpr(const Expr *e) {
1240
assert(e && hasScalarEvaluationKind(e->getType()) &&
1241
"Invalid scalar expression to emit");
1242
1243
return ScalarExprEmitter(*this, builder).Visit(const_cast<Expr *>(e));
1244
}
1245
1246
mlir::Value CIRGenFunction::emitPromotedScalarExpr(const Expr *e,
1247
QualType promotionType) {
1248
if (!promotionType.isNull())
1249
return ScalarExprEmitter(*this, builder).emitPromoted(e, promotionType);
1250
return ScalarExprEmitter(*this, builder).Visit(const_cast<Expr *>(e));
1251
}
1252
1253
[[maybe_unused]] static bool mustVisitNullValue(const Expr *e) {
1254
// If a null pointer expression's type is the C++0x nullptr_t and
1255
// the expression is not a simple literal, it must be evaluated
1256
// for its potential side effects.
1257
if (isa<IntegerLiteral>(e) || isa<CXXNullPtrLiteralExpr>(e))
1258
return false;
1259
return e->getType()->isNullPtrType();
1260
}
1261
1262
/// If \p e is a widened promoted integer, get its base (unpromoted) type.
1263
static std::optional<QualType>
1264
getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e) {
1265
const Expr *base = e->IgnoreImpCasts();
1266
if (e == base)
1267
return std::nullopt;
1268
1269
QualType baseTy = base->getType();
1270
if (!astContext.isPromotableIntegerType(baseTy) ||
1271
astContext.getTypeSize(baseTy) >= astContext.getTypeSize(e->getType()))
1272
return std::nullopt;
1273
1274
return baseTy;
1275
}
1276
1277
/// Check if \p e is a widened promoted integer.
1278
[[maybe_unused]] static bool isWidenedIntegerOp(const ASTContext &astContext,
1279
const Expr *e) {
1280
return getUnwidenedIntegerType(astContext, e).has_value();
1281
}
1282
1283
/// Check if we can skip the overflow check for \p Op.
1284
[[maybe_unused]] static bool canElideOverflowCheck(const ASTContext &astContext,
1285
const BinOpInfo &op) {
1286
assert((isa<UnaryOperator>(op.e) || isa<BinaryOperator>(op.e)) &&
1287
"Expected a unary or binary operator");
1288
1289
// If the binop has constant inputs and we can prove there is no overflow,
1290
// we can elide the overflow check.
1291
if (!op.mayHaveIntegerOverflow())
1292
return true;
1293
1294
// If a unary op has a widened operand, the op cannot overflow.
1295
if (const auto *uo = dyn_cast<UnaryOperator>(op.e))
1296
return !uo->canOverflow();
1297
1298
// We usually don't need overflow checks for binops with widened operands.
1299
// Multiplication with promoted unsigned operands is a special case.
1300
const auto *bo = cast<BinaryOperator>(op.e);
1301
std::optional<QualType> optionalLHSTy =
1302
getUnwidenedIntegerType(astContext, bo->getLHS());
1303
if (!optionalLHSTy)
1304
return false;
1305
1306
std::optional<QualType> optionalRHSTy =
1307
getUnwidenedIntegerType(astContext, bo->getRHS());
1308
if (!optionalRHSTy)
1309
return false;
1310
1311
QualType lhsTy = *optionalLHSTy;
1312
QualType rhsTy = *optionalRHSTy;
1313
1314
// This is the simple case: binops without unsigned multiplication, and with
1315
// widened operands. No overflow check is needed here.
1316
if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1317
!lhsTy->isUnsignedIntegerType() || !rhsTy->isUnsignedIntegerType())
1318
return true;
1319
1320
// For unsigned multiplication the overflow check can be elided if either one
1321
// of the unpromoted types are less than half the size of the promoted type.
1322
unsigned promotedSize = astContext.getTypeSize(op.e->getType());
1323
return (2 * astContext.getTypeSize(lhsTy)) < promotedSize ||
1324
(2 * astContext.getTypeSize(rhsTy)) < promotedSize;
1325
}
1326
1327
/// Emit pointer + index arithmetic.
1328
static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf,
1329
const BinOpInfo &op,
1330
bool isSubtraction) {
1331
// Must have binary (not unary) expr here. Unary pointer
1332
// increment/decrement doesn't use this path.
1333
const BinaryOperator *expr = cast<BinaryOperator>(op.e);
1334
1335
mlir::Value pointer = op.lhs;
1336
Expr *pointerOperand = expr->getLHS();
1337
mlir::Value index = op.rhs;
1338
Expr *indexOperand = expr->getRHS();
1339
1340
// In the case of subtraction, the FE has ensured that the LHS is always the
1341
// pointer. However, addition can have the pointer on either side. We will
1342
// always have a pointer operand and an integer operand, so if the LHS wasn't
1343
// a pointer, we need to swap our values.
1344
if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1345
std::swap(pointer, index);
1346
std::swap(pointerOperand, indexOperand);
1347
}
1348
assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1349
"Need a pointer operand");
1350
assert(mlir::isa<cir::IntType>(index.getType()) && "Need an integer operand");
1351
1352
// Some versions of glibc and gcc use idioms (particularly in their malloc
1353
// routines) that add a pointer-sized integer (known to be a pointer value)
1354
// to a null pointer in order to cast the value back to an integer or as
1355
// part of a pointer alignment algorithm. This is undefined behavior, but
1356
// we'd like to be able to compile programs that use it.
1357
//
1358
// Normally, we'd generate a GEP with a null-pointer base here in response
1359
// to that code, but it's also UB to dereference a pointer created that
1360
// way. Instead (as an acknowledged hack to tolerate the idiom) we will
1361
// generate a direct cast of the integer value to a pointer.
1362
//
1363
// The idiom (p = nullptr + N) is not met if any of the following are true:
1364
//
1365
// The operation is subtraction.
1366
// The index is not pointer-sized.
1367
// The pointer type is not byte-sized.
1368
//
1369
if (BinaryOperator::isNullPointerArithmeticExtension(
1370
cgf.getContext(), op.opcode, expr->getLHS(), expr->getRHS()))
1371
return cgf.getBuilder().createIntToPtr(index, pointer.getType());
1372
1373
// Differently from LLVM codegen, ABI bits for index sizes is handled during
1374
// LLVM lowering.
1375
1376
// If this is subtraction, negate the index.
1377
if (isSubtraction)
1378
index = cgf.getBuilder().createNeg(index);
1379
1380
assert(!cir::MissingFeatures::sanitizers());
1381
1382
const PointerType *pointerType =
1383
pointerOperand->getType()->getAs<PointerType>();
1384
if (!pointerType) {
1385
cgf.cgm.errorNYI("Objective-C:pointer arithmetic with non-pointer type");
1386
return nullptr;
1387
}
1388
1389
QualType elementType = pointerType->getPointeeType();
1390
if (cgf.getContext().getAsVariableArrayType(elementType)) {
1391
cgf.cgm.errorNYI("variable array type");
1392
return nullptr;
1393
}
1394
1395
if (elementType->isVoidType() || elementType->isFunctionType()) {
1396
cgf.cgm.errorNYI("void* or function pointer arithmetic");
1397
return nullptr;
1398
}
1399
1400
assert(!cir::MissingFeatures::sanitizers());
1401
return cgf.getBuilder().create<cir::PtrStrideOp>(
1402
cgf.getLoc(op.e->getExprLoc()), pointer.getType(), pointer, index);
1403
}
1404
1405
mlir::Value ScalarExprEmitter::emitMul(const BinOpInfo &ops) {
1406
const mlir::Location loc = cgf.getLoc(ops.loc);
1407
if (ops.compType->isSignedIntegerOrEnumerationType()) {
1408
switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
1409
case LangOptions::SOB_Defined:
1410
if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
1411
return builder.createMul(loc, ops.lhs, ops.rhs);
1412
[[fallthrough]];
1413
case LangOptions::SOB_Undefined:
1414
if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
1415
return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1416
[[fallthrough]];
1417
case LangOptions::SOB_Trapping:
1418
if (canElideOverflowCheck(cgf.getContext(), ops))
1419
return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1420
cgf.cgm.errorNYI("sanitizers");
1421
}
1422
}
1423
if (ops.fullType->isConstantMatrixType()) {
1424
assert(!cir::MissingFeatures::matrixType());
1425
cgf.cgm.errorNYI("matrix types");
1426
return nullptr;
1427
}
1428
if (ops.compType->isUnsignedIntegerType() &&
1429
cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
1430
!canElideOverflowCheck(cgf.getContext(), ops))
1431
cgf.cgm.errorNYI("unsigned int overflow sanitizer");
1432
1433
if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1434
assert(!cir::MissingFeatures::cgFPOptionsRAII());
1435
return builder.createFMul(loc, ops.lhs, ops.rhs);
1436
}
1437
1438
if (ops.isFixedPointOp()) {
1439
assert(!cir::MissingFeatures::fixedPointType());
1440
cgf.cgm.errorNYI("fixed point");
1441
return nullptr;
1442
}
1443
1444
return builder.create<cir::BinOp>(cgf.getLoc(ops.loc),
1445
cgf.convertType(ops.fullType),
1446
cir::BinOpKind::Mul, ops.lhs, ops.rhs);
1447
}
1448
mlir::Value ScalarExprEmitter::emitDiv(const BinOpInfo &ops) {
1449
return builder.create<cir::BinOp>(cgf.getLoc(ops.loc),
1450
cgf.convertType(ops.fullType),
1451
cir::BinOpKind::Div, ops.lhs, ops.rhs);
1452
}
1453
mlir::Value ScalarExprEmitter::emitRem(const BinOpInfo &ops) {
1454
return builder.create<cir::BinOp>(cgf.getLoc(ops.loc),
1455
cgf.convertType(ops.fullType),
1456
cir::BinOpKind::Rem, ops.lhs, ops.rhs);
1457
}
1458
1459
mlir::Value ScalarExprEmitter::emitAdd(const BinOpInfo &ops) {
1460
if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
1461
mlir::isa<cir::PointerType>(ops.rhs.getType()))
1462
return emitPointerArithmetic(cgf, ops, /*isSubtraction=*/false);
1463
1464
const mlir::Location loc = cgf.getLoc(ops.loc);
1465
if (ops.compType->isSignedIntegerOrEnumerationType()) {
1466
switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
1467
case LangOptions::SOB_Defined:
1468
if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
1469
return builder.createAdd(loc, ops.lhs, ops.rhs);
1470
[[fallthrough]];
1471
case LangOptions::SOB_Undefined:
1472
if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
1473
return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1474
[[fallthrough]];
1475
case LangOptions::SOB_Trapping:
1476
if (canElideOverflowCheck(cgf.getContext(), ops))
1477
return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1478
cgf.cgm.errorNYI("sanitizers");
1479
}
1480
}
1481
if (ops.fullType->isConstantMatrixType()) {
1482
assert(!cir::MissingFeatures::matrixType());
1483
cgf.cgm.errorNYI("matrix types");
1484
return nullptr;
1485
}
1486
1487
if (ops.compType->isUnsignedIntegerType() &&
1488
cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
1489
!canElideOverflowCheck(cgf.getContext(), ops))
1490
cgf.cgm.errorNYI("unsigned int overflow sanitizer");
1491
1492
if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1493
assert(!cir::MissingFeatures::cgFPOptionsRAII());
1494
return builder.createFAdd(loc, ops.lhs, ops.rhs);
1495
}
1496
1497
if (ops.isFixedPointOp()) {
1498
assert(!cir::MissingFeatures::fixedPointType());
1499
cgf.cgm.errorNYI("fixed point");
1500
return {};
1501
}
1502
1503
return builder.create<cir::BinOp>(loc, cgf.convertType(ops.fullType),
1504
cir::BinOpKind::Add, ops.lhs, ops.rhs);
1505
}
1506
1507
mlir::Value ScalarExprEmitter::emitSub(const BinOpInfo &ops) {
1508
const mlir::Location loc = cgf.getLoc(ops.loc);
1509
// The LHS is always a pointer if either side is.
1510
if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
1511
if (ops.compType->isSignedIntegerOrEnumerationType()) {
1512
switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
1513
case LangOptions::SOB_Defined: {
1514
if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
1515
return builder.createSub(loc, ops.lhs, ops.rhs);
1516
[[fallthrough]];
1517
}
1518
case LangOptions::SOB_Undefined:
1519
if (!cgf.sanOpts.has(SanitizerKind::SignedIntegerOverflow))
1520
return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1521
[[fallthrough]];
1522
case LangOptions::SOB_Trapping:
1523
if (canElideOverflowCheck(cgf.getContext(), ops))
1524
return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1525
cgf.cgm.errorNYI("sanitizers");
1526
}
1527
}
1528
1529
if (ops.fullType->isConstantMatrixType()) {
1530
assert(!cir::MissingFeatures::matrixType());
1531
cgf.cgm.errorNYI("matrix types");
1532
return nullptr;
1533
}
1534
1535
if (ops.compType->isUnsignedIntegerType() &&
1536
cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
1537
!canElideOverflowCheck(cgf.getContext(), ops))
1538
cgf.cgm.errorNYI("unsigned int overflow sanitizer");
1539
1540
if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1541
assert(!cir::MissingFeatures::cgFPOptionsRAII());
1542
return builder.createFSub(loc, ops.lhs, ops.rhs);
1543
}
1544
1545
if (ops.isFixedPointOp()) {
1546
assert(!cir::MissingFeatures::fixedPointType());
1547
cgf.cgm.errorNYI("fixed point");
1548
return {};
1549
}
1550
1551
return builder.create<cir::BinOp>(cgf.getLoc(ops.loc),
1552
cgf.convertType(ops.fullType),
1553
cir::BinOpKind::Sub, ops.lhs, ops.rhs);
1554
}
1555
1556
// If the RHS is not a pointer, then we have normal pointer
1557
// arithmetic.
1558
if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
1559
return emitPointerArithmetic(cgf, ops, /*isSubtraction=*/true);
1560
1561
// Otherwise, this is a pointer subtraction
1562
1563
// Do the raw subtraction part.
1564
//
1565
// TODO(cir): note for LLVM lowering out of this; when expanding this into
1566
// LLVM we shall take VLA's, division by element size, etc.
1567
//
1568
// See more in `EmitSub` in CGExprScalar.cpp.
1569
assert(!cir::MissingFeatures::ptrDiffOp());
1570
cgf.cgm.errorNYI("ptrdiff");
1571
return {};
1572
}
1573
1574
mlir::Value ScalarExprEmitter::emitShl(const BinOpInfo &ops) {
1575
// TODO: This misses out on the sanitizer check below.
1576
if (ops.isFixedPointOp()) {
1577
assert(cir::MissingFeatures::fixedPointType());
1578
cgf.cgm.errorNYI("fixed point");
1579
return {};
1580
}
1581
1582
// CIR accepts shift between different types, meaning nothing special
1583
// to be done here. OTOH, LLVM requires the LHS and RHS to be the same type:
1584
// promote or truncate the RHS to the same size as the LHS.
1585
1586
bool sanitizeSignedBase = cgf.sanOpts.has(SanitizerKind::ShiftBase) &&
1587
ops.compType->hasSignedIntegerRepresentation() &&
1588
!cgf.getLangOpts().isSignedOverflowDefined() &&
1589
!cgf.getLangOpts().CPlusPlus20;
1590
bool sanitizeUnsignedBase =
1591
cgf.sanOpts.has(SanitizerKind::UnsignedShiftBase) &&
1592
ops.compType->hasUnsignedIntegerRepresentation();
1593
bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
1594
bool sanitizeExponent = cgf.sanOpts.has(SanitizerKind::ShiftExponent);
1595
1596
// OpenCL 6.3j: shift values are effectively % word size of LHS.
1597
if (cgf.getLangOpts().OpenCL)
1598
cgf.cgm.errorNYI("opencl");
1599
else if ((sanitizeBase || sanitizeExponent) &&
1600
mlir::isa<cir::IntType>(ops.lhs.getType()))
1601
cgf.cgm.errorNYI("sanitizers");
1602
1603
return builder.createShiftLeft(cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
1604
}
1605
1606
mlir::Value ScalarExprEmitter::emitShr(const BinOpInfo &ops) {
1607
// TODO: This misses out on the sanitizer check below.
1608
if (ops.isFixedPointOp()) {
1609
assert(cir::MissingFeatures::fixedPointType());
1610
cgf.cgm.errorNYI("fixed point");
1611
return {};
1612
}
1613
1614
// CIR accepts shift between different types, meaning nothing special
1615
// to be done here. OTOH, LLVM requires the LHS and RHS to be the same type:
1616
// promote or truncate the RHS to the same size as the LHS.
1617
1618
// OpenCL 6.3j: shift values are effectively % word size of LHS.
1619
if (cgf.getLangOpts().OpenCL)
1620
cgf.cgm.errorNYI("opencl");
1621
else if (cgf.sanOpts.has(SanitizerKind::ShiftExponent) &&
1622
mlir::isa<cir::IntType>(ops.lhs.getType()))
1623
cgf.cgm.errorNYI("sanitizers");
1624
1625
// Note that we don't need to distinguish unsigned treatment at this
1626
// point since it will be handled later by LLVM lowering.
1627
return builder.createShiftRight(cgf.getLoc(ops.loc), ops.lhs, ops.rhs);
1628
}
1629
1630
mlir::Value ScalarExprEmitter::emitAnd(const BinOpInfo &ops) {
1631
return builder.create<cir::BinOp>(cgf.getLoc(ops.loc),
1632
cgf.convertType(ops.fullType),
1633
cir::BinOpKind::And, ops.lhs, ops.rhs);
1634
}
1635
mlir::Value ScalarExprEmitter::emitXor(const BinOpInfo &ops) {
1636
return builder.create<cir::BinOp>(cgf.getLoc(ops.loc),
1637
cgf.convertType(ops.fullType),
1638
cir::BinOpKind::Xor, ops.lhs, ops.rhs);
1639
}
1640
mlir::Value ScalarExprEmitter::emitOr(const BinOpInfo &ops) {
1641
return builder.create<cir::BinOp>(cgf.getLoc(ops.loc),
1642
cgf.convertType(ops.fullType),
1643
cir::BinOpKind::Or, ops.lhs, ops.rhs);
1644
}
1645
1646
// Emit code for an explicit or implicit cast. Implicit
1647
// casts have to handle a more broad range of conversions than explicit
1648
// casts, as they handle things like function to ptr-to-function decay
1649
// etc.
1650
mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
1651
Expr *subExpr = ce->getSubExpr();
1652
QualType destTy = ce->getType();
1653
CastKind kind = ce->getCastKind();
1654
1655
// These cases are generally not written to ignore the result of evaluating
1656
// their sub-expressions, so we clear this now.
1657
ignoreResultAssign = false;
1658
1659
switch (kind) {
1660
case clang::CK_Dependent:
1661
llvm_unreachable("dependent cast kind in CIR gen!");
1662
case clang::CK_BuiltinFnToFnPtr:
1663
llvm_unreachable("builtin functions are handled elsewhere");
1664
1665
case CK_CPointerToObjCPointerCast:
1666
case CK_BlockPointerToObjCPointerCast:
1667
case CK_AnyPointerToBlockPointerCast:
1668
case CK_BitCast: {
1669
mlir::Value src = Visit(const_cast<Expr *>(subExpr));
1670
mlir::Type dstTy = cgf.convertType(destTy);
1671
1672
assert(!cir::MissingFeatures::addressSpace());
1673
1674
if (cgf.sanOpts.has(SanitizerKind::CFIUnrelatedCast))
1675
cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
1676
"sanitizer support");
1677
1678
if (cgf.cgm.getCodeGenOpts().StrictVTablePointers)
1679
cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
1680
"strict vtable pointers");
1681
1682
// Update heapallocsite metadata when there is an explicit pointer cast.
1683
assert(!cir::MissingFeatures::addHeapAllocSiteMetadata());
1684
1685
// If Src is a fixed vector and Dst is a scalable vector, and both have the
1686
// same element type, use the llvm.vector.insert intrinsic to perform the
1687
// bitcast.
1688
assert(!cir::MissingFeatures::scalableVectors());
1689
1690
// If Src is a scalable vector and Dst is a fixed vector, and both have the
1691
// same element type, use the llvm.vector.extract intrinsic to perform the
1692
// bitcast.
1693
assert(!cir::MissingFeatures::scalableVectors());
1694
1695
// Perform VLAT <-> VLST bitcast through memory.
1696
// TODO: since the llvm.experimental.vector.{insert,extract} intrinsics
1697
// require the element types of the vectors to be the same, we
1698
// need to keep this around for bitcasts between VLAT <-> VLST where
1699
// the element types of the vectors are not the same, until we figure
1700
// out a better way of doing these casts.
1701
assert(!cir::MissingFeatures::scalableVectors());
1702
1703
return cgf.getBuilder().createBitcast(cgf.getLoc(subExpr->getSourceRange()),
1704
src, dstTy);
1705
}
1706
1707
case CK_AtomicToNonAtomic: {
1708
cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
1709
"CastExpr: ", ce->getCastKindName());
1710
mlir::Location loc = cgf.getLoc(subExpr->getSourceRange());
1711
return cgf.createDummyValue(loc, destTy);
1712
}
1713
case CK_NonAtomicToAtomic:
1714
case CK_UserDefinedConversion:
1715
return Visit(const_cast<Expr *>(subExpr));
1716
case CK_NoOp: {
1717
auto v = Visit(const_cast<Expr *>(subExpr));
1718
if (v) {
1719
// CK_NoOp can model a pointer qualification conversion, which can remove
1720
// an array bound and change the IR type.
1721
// FIXME: Once pointee types are removed from IR, remove this.
1722
mlir::Type t = cgf.convertType(destTy);
1723
if (t != v.getType())
1724
cgf.getCIRGenModule().errorNYI("pointer qualification conversion");
1725
}
1726
return v;
1727
}
1728
1729
case CK_ArrayToPointerDecay:
1730
return cgf.emitArrayToPointerDecay(subExpr).getPointer();
1731
1732
case CK_NullToPointer: {
1733
if (mustVisitNullValue(subExpr))
1734
cgf.emitIgnoredExpr(subExpr);
1735
1736
// Note that DestTy is used as the MLIR type instead of a custom
1737
// nullptr type.
1738
mlir::Type ty = cgf.convertType(destTy);
1739
return builder.getNullPtr(ty, cgf.getLoc(subExpr->getExprLoc()));
1740
}
1741
1742
case CK_LValueToRValue:
1743
assert(cgf.getContext().hasSameUnqualifiedType(subExpr->getType(), destTy));
1744
assert(subExpr->isGLValue() && "lvalue-to-rvalue applied to r-value!");
1745
return Visit(const_cast<Expr *>(subExpr));
1746
1747
case CK_IntegralCast: {
1748
ScalarConversionOpts opts;
1749
if (auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
1750
if (!ice->isPartOfExplicitCast())
1751
opts = ScalarConversionOpts(cgf.sanOpts);
1752
}
1753
return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
1754
ce->getExprLoc(), opts);
1755
}
1756
1757
case CK_FloatingRealToComplex:
1758
case CK_FloatingComplexCast:
1759
case CK_IntegralRealToComplex:
1760
case CK_IntegralComplexCast:
1761
case CK_IntegralComplexToFloatingComplex:
1762
case CK_FloatingComplexToIntegralComplex:
1763
llvm_unreachable("scalar cast to non-scalar value");
1764
1765
case CK_PointerToIntegral: {
1766
assert(!destTy->isBooleanType() && "bool should use PointerToBool");
1767
if (cgf.cgm.getCodeGenOpts().StrictVTablePointers)
1768
cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
1769
"strict vtable pointers");
1770
return builder.createPtrToInt(Visit(subExpr), cgf.convertType(destTy));
1771
}
1772
case CK_ToVoid:
1773
cgf.emitIgnoredExpr(subExpr);
1774
return {};
1775
1776
case CK_IntegralToFloating:
1777
case CK_FloatingToIntegral:
1778
case CK_FloatingCast:
1779
case CK_FixedPointToFloating:
1780
case CK_FloatingToFixedPoint: {
1781
if (kind == CK_FixedPointToFloating || kind == CK_FloatingToFixedPoint) {
1782
cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
1783
"fixed point casts");
1784
return {};
1785
}
1786
assert(!cir::MissingFeatures::cgFPOptionsRAII());
1787
return emitScalarConversion(Visit(subExpr), subExpr->getType(), destTy,
1788
ce->getExprLoc());
1789
}
1790
1791
case CK_IntegralToBoolean:
1792
return emitIntToBoolConversion(Visit(subExpr),
1793
cgf.getLoc(ce->getSourceRange()));
1794
1795
case CK_PointerToBoolean:
1796
return emitPointerToBoolConversion(Visit(subExpr), subExpr->getType());
1797
case CK_FloatingToBoolean:
1798
return emitFloatToBoolConversion(Visit(subExpr),
1799
cgf.getLoc(subExpr->getExprLoc()));
1800
case CK_MemberPointerToBoolean: {
1801
mlir::Value memPtr = Visit(subExpr);
1802
return builder.createCast(cgf.getLoc(ce->getSourceRange()),
1803
cir::CastKind::member_ptr_to_bool, memPtr,
1804
cgf.convertType(destTy));
1805
}
1806
1807
case CK_VectorSplat: {
1808
// Create a vector object and fill all elements with the same scalar value.
1809
assert(destTy->isVectorType() && "CK_VectorSplat to non-vector type");
1810
return builder.create<cir::VecSplatOp>(
1811
cgf.getLoc(subExpr->getSourceRange()), cgf.convertType(destTy),
1812
Visit(subExpr));
1813
}
1814
1815
default:
1816
cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
1817
"CastExpr: ", ce->getCastKindName());
1818
}
1819
return {};
1820
}
1821
1822
mlir::Value ScalarExprEmitter::VisitCallExpr(const CallExpr *e) {
1823
if (e->getCallReturnType(cgf.getContext())->isReferenceType())
1824
return emitLoadOfLValue(e);
1825
1826
auto v = cgf.emitCallExpr(e).getValue();
1827
assert(!cir::MissingFeatures::emitLValueAlignmentAssumption());
1828
return v;
1829
}
1830
1831
mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
1832
// TODO(cir): The classic codegen calls tryEmitAsConstant() here. Folding
1833
// constants sound like work for MLIR optimizers, but we'll keep an assertion
1834
// for now.
1835
assert(!cir::MissingFeatures::tryEmitAsConstant());
1836
Expr::EvalResult result;
1837
if (e->EvaluateAsInt(result, cgf.getContext(), Expr::SE_AllowSideEffects)) {
1838
cgf.cgm.errorNYI(e->getSourceRange(), "Constant interger member expr");
1839
// Fall through to emit this as a non-constant access.
1840
}
1841
return emitLoadOfLValue(e);
1842
}
1843
1844
mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
1845
const unsigned numInitElements = e->getNumInits();
1846
1847
if (e->hadArrayRangeDesignator()) {
1848
cgf.cgm.errorNYI(e->getSourceRange(), "ArrayRangeDesignator");
1849
return {};
1850
}
1851
1852
if (e->getType()->isVectorType()) {
1853
const auto vectorType =
1854
mlir::cast<cir::VectorType>(cgf.convertType(e->getType()));
1855
1856
SmallVector<mlir::Value, 16> elements;
1857
for (Expr *init : e->inits()) {
1858
elements.push_back(Visit(init));
1859
}
1860
1861
// Zero-initialize any remaining values.
1862
if (numInitElements < vectorType.getSize()) {
1863
const mlir::Value zeroValue = cgf.getBuilder().getNullValue(
1864
vectorType.getElementType(), cgf.getLoc(e->getSourceRange()));
1865
std::fill_n(std::back_inserter(elements),
1866
vectorType.getSize() - numInitElements, zeroValue);
1867
}
1868
1869
return cgf.getBuilder().create<cir::VecCreateOp>(
1870
cgf.getLoc(e->getSourceRange()), vectorType, elements);
1871
}
1872
1873
if (numInitElements == 0) {
1874
cgf.cgm.errorNYI(e->getSourceRange(),
1875
"InitListExpr Non VectorType with 0 init elements");
1876
return {};
1877
}
1878
1879
return Visit(e->getInit(0));
1880
}
1881
1882
mlir::Value CIRGenFunction::emitScalarConversion(mlir::Value src,
1883
QualType srcTy, QualType dstTy,
1884
SourceLocation loc) {
1885
assert(CIRGenFunction::hasScalarEvaluationKind(srcTy) &&
1886
CIRGenFunction::hasScalarEvaluationKind(dstTy) &&
1887
"Invalid scalar expression to emit");
1888
return ScalarExprEmitter(*this, builder)
1889
.emitScalarConversion(src, srcTy, dstTy, loc);
1890
}
1891
1892
mlir::Value ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *e) {
1893
// Perform vector logical not on comparison with zero vector.
1894
if (e->getType()->isVectorType() &&
1895
e->getType()->castAs<VectorType>()->getVectorKind() ==
1896
VectorKind::Generic) {
1897
assert(!cir::MissingFeatures::vectorType());
1898
cgf.cgm.errorNYI(e->getSourceRange(), "vector logical not");
1899
return {};
1900
}
1901
1902
// Compare operand to zero.
1903
mlir::Value boolVal = cgf.evaluateExprAsBool(e->getSubExpr());
1904
1905
// Invert value.
1906
boolVal = builder.createNot(boolVal);
1907
1908
// ZExt result to the expr type.
1909
return maybePromoteBoolResult(boolVal, cgf.convertType(e->getType()));
1910
}
1911
1912
mlir::Value ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *e) {
1913
// TODO(cir): handle scalar promotion.
1914
Expr *op = e->getSubExpr();
1915
if (op->getType()->isAnyComplexType()) {
1916
// If it's an l-value, load through the appropriate subobject l-value.
1917
// Note that we have to ask `e` because `op` might be an l-value that
1918
// this won't work for, e.g. an Obj-C property.
1919
if (e->isGLValue()) {
1920
mlir::Location loc = cgf.getLoc(e->getExprLoc());
1921
mlir::Value complex = cgf.emitComplexExpr(op);
1922
return cgf.builder.createComplexReal(loc, complex);
1923
}
1924
1925
// Otherwise, calculate and project.
1926
cgf.cgm.errorNYI(e->getSourceRange(),
1927
"VisitUnaryReal calculate and project");
1928
}
1929
1930
return Visit(op);
1931
}
1932
1933
mlir::Value ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *e) {
1934
// TODO(cir): handle scalar promotion.
1935
Expr *op = e->getSubExpr();
1936
if (op->getType()->isAnyComplexType()) {
1937
// If it's an l-value, load through the appropriate subobject l-value.
1938
// Note that we have to ask `e` because `op` might be an l-value that
1939
// this won't work for, e.g. an Obj-C property.
1940
if (e->isGLValue()) {
1941
mlir::Location loc = cgf.getLoc(e->getExprLoc());
1942
mlir::Value complex = cgf.emitComplexExpr(op);
1943
return cgf.builder.createComplexImag(loc, complex);
1944
}
1945
1946
// Otherwise, calculate and project.
1947
cgf.cgm.errorNYI(e->getSourceRange(),
1948
"VisitUnaryImag calculate and project");
1949
}
1950
1951
return Visit(op);
1952
}
1953
1954
/// Return the size or alignment of the type of argument of the sizeof
1955
/// expression as an integer.
1956
mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
1957
const UnaryExprOrTypeTraitExpr *e) {
1958
const QualType typeToSize = e->getTypeOfArgument();
1959
const mlir::Location loc = cgf.getLoc(e->getSourceRange());
1960
if (auto kind = e->getKind();
1961
kind == UETT_SizeOf || kind == UETT_DataSizeOf) {
1962
if (cgf.getContext().getAsVariableArrayType(typeToSize)) {
1963
cgf.getCIRGenModule().errorNYI(e->getSourceRange(),
1964
"sizeof operator for VariableArrayType",
1965
e->getStmtClassName());
1966
return builder.getConstant(
1967
loc, cir::IntAttr::get(cgf.cgm.UInt64Ty,
1968
llvm::APSInt(llvm::APInt(64, 1), true)));
1969
}
1970
} else if (e->getKind() == UETT_OpenMPRequiredSimdAlign) {
1971
cgf.getCIRGenModule().errorNYI(
1972
e->getSourceRange(), "sizeof operator for OpenMpRequiredSimdAlign",
1973
e->getStmtClassName());
1974
return builder.getConstant(
1975
loc, cir::IntAttr::get(cgf.cgm.UInt64Ty,
1976
llvm::APSInt(llvm::APInt(64, 1), true)));
1977
}
1978
1979
return builder.getConstant(
1980
loc, cir::IntAttr::get(cgf.cgm.UInt64Ty,
1981
e->EvaluateKnownConstInt(cgf.getContext())));
1982
}
1983
1984
/// Return true if the specified expression is cheap enough and side-effect-free
1985
/// enough to evaluate unconditionally instead of conditionally. This is used
1986
/// to convert control flow into selects in some cases.
1987
/// TODO(cir): can be shared with LLVM codegen.
1988
static bool isCheapEnoughToEvaluateUnconditionally(const Expr *e,
1989
CIRGenFunction &cgf) {
1990
// Anything that is an integer or floating point constant is fine.
1991
return e->IgnoreParens()->isEvaluatable(cgf.getContext());
1992
1993
// Even non-volatile automatic variables can't be evaluated unconditionally.
1994
// Referencing a thread_local may cause non-trivial initialization work to
1995
// occur. If we're inside a lambda and one of the variables is from the scope
1996
// outside the lambda, that function may have returned already. Reading its
1997
// locals is a bad idea. Also, these reads may introduce races there didn't
1998
// exist in the source-level program.
1999
}
2000
2001
mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2002
const AbstractConditionalOperator *e) {
2003
CIRGenBuilderTy &builder = cgf.getBuilder();
2004
mlir::Location loc = cgf.getLoc(e->getSourceRange());
2005
ignoreResultAssign = false;
2006
2007
// Bind the common expression if necessary.
2008
CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2009
2010
Expr *condExpr = e->getCond();
2011
Expr *lhsExpr = e->getTrueExpr();
2012
Expr *rhsExpr = e->getFalseExpr();
2013
2014
// If the condition constant folds and can be elided, try to avoid emitting
2015
// the condition and the dead arm.
2016
bool condExprBool;
2017
if (cgf.constantFoldsToBool(condExpr, condExprBool)) {
2018
Expr *live = lhsExpr, *dead = rhsExpr;
2019
if (!condExprBool)
2020
std::swap(live, dead);
2021
2022
// If the dead side doesn't have labels we need, just emit the Live part.
2023
if (!cgf.containsLabel(dead)) {
2024
if (condExprBool)
2025
assert(!cir::MissingFeatures::incrementProfileCounter());
2026
mlir::Value result = Visit(live);
2027
2028
// If the live part is a throw expression, it acts like it has a void
2029
// type, so evaluating it returns a null Value. However, a conditional
2030
// with non-void type must return a non-null Value.
2031
if (!result && !e->getType()->isVoidType()) {
2032
cgf.cgm.errorNYI(e->getSourceRange(),
2033
"throw expression in conditional operator");
2034
result = {};
2035
}
2036
2037
return result;
2038
}
2039
}
2040
2041
QualType condType = condExpr->getType();
2042
2043
// OpenCL: If the condition is a vector, we can treat this condition like
2044
// the select function.
2045
if ((cgf.getLangOpts().OpenCL && condType->isVectorType()) ||
2046
condType->isExtVectorType()) {
2047
assert(!cir::MissingFeatures::vectorType());
2048
cgf.cgm.errorNYI(e->getSourceRange(), "vector ternary op");
2049
}
2050
2051
if (condType->isVectorType() || condType->isSveVLSBuiltinType()) {
2052
if (!condType->isVectorType()) {
2053
assert(!cir::MissingFeatures::vecTernaryOp());
2054
cgf.cgm.errorNYI(loc, "TernaryOp for SVE vector");
2055
return {};
2056
}
2057
2058
mlir::Value condValue = Visit(condExpr);
2059
mlir::Value lhsValue = Visit(lhsExpr);
2060
mlir::Value rhsValue = Visit(rhsExpr);
2061
return builder.create<cir::VecTernaryOp>(loc, condValue, lhsValue,
2062
rhsValue);
2063
}
2064
2065
// If this is a really simple expression (like x ? 4 : 5), emit this as a
2066
// select instead of as control flow. We can only do this if it is cheap
2067
// and safe to evaluate the LHS and RHS unconditionally.
2068
if (isCheapEnoughToEvaluateUnconditionally(lhsExpr, cgf) &&
2069
isCheapEnoughToEvaluateUnconditionally(rhsExpr, cgf)) {
2070
bool lhsIsVoid = false;
2071
mlir::Value condV = cgf.evaluateExprAsBool(condExpr);
2072
assert(!cir::MissingFeatures::incrementProfileCounter());
2073
2074
mlir::Value lhs = Visit(lhsExpr);
2075
if (!lhs) {
2076
lhs = builder.getNullValue(cgf.VoidTy, loc);
2077
lhsIsVoid = true;
2078
}
2079
2080
mlir::Value rhs = Visit(rhsExpr);
2081
if (lhsIsVoid) {
2082
assert(!rhs && "lhs and rhs types must match");
2083
rhs = builder.getNullValue(cgf.VoidTy, loc);
2084
}
2085
2086
return builder.createSelect(loc, condV, lhs, rhs);
2087
}
2088
2089
mlir::Value condV = cgf.emitOpOnBoolExpr(loc, condExpr);
2090
CIRGenFunction::ConditionalEvaluation eval(cgf);
2091
SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2092
mlir::Type yieldTy{};
2093
2094
auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *expr) {
2095
CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()};
2096
cgf.curLexScope->setAsTernary();
2097
2098
assert(!cir::MissingFeatures::incrementProfileCounter());
2099
eval.beginEvaluation();
2100
mlir::Value branch = Visit(expr);
2101
eval.endEvaluation();
2102
2103
if (branch) {
2104
yieldTy = branch.getType();
2105
b.create<cir::YieldOp>(loc, branch);
2106
} else {
2107
// If LHS or RHS is a throw or void expression we need to patch
2108
// arms as to properly match yield types.
2109
insertPoints.push_back(b.saveInsertionPoint());
2110
}
2111
};
2112
2113
mlir::Value result = builder
2114
.create<cir::TernaryOp>(
2115
loc, condV,
2116
/*trueBuilder=*/
2117
[&](mlir::OpBuilder &b, mlir::Location loc) {
2118
emitBranch(b, loc, lhsExpr);
2119
},
2120
/*falseBuilder=*/
2121
[&](mlir::OpBuilder &b, mlir::Location loc) {
2122
emitBranch(b, loc, rhsExpr);
2123
})
2124
.getResult();
2125
2126
if (!insertPoints.empty()) {
2127
// If both arms are void, so be it.
2128
if (!yieldTy)
2129
yieldTy = cgf.VoidTy;
2130
2131
// Insert required yields.
2132
for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2133
mlir::OpBuilder::InsertionGuard guard(builder);
2134
builder.restoreInsertionPoint(toInsert);
2135
2136
// Block does not return: build empty yield.
2137
if (mlir::isa<cir::VoidType>(yieldTy)) {
2138
builder.create<cir::YieldOp>(loc);
2139
} else { // Block returns: set null yield value.
2140
mlir::Value op0 = builder.getNullValue(yieldTy, loc);
2141
builder.create<cir::YieldOp>(loc, op0);
2142
}
2143
}
2144
}
2145
2146
return result;
2147
}
2148
2149
mlir::Value CIRGenFunction::emitScalarPrePostIncDec(const UnaryOperator *e,
2150
LValue lv, bool isInc,
2151
bool isPre) {
2152
return ScalarExprEmitter(*this, builder)
2153
.emitScalarPrePostIncDec(e, lv, isInc, isPre);
2154
}
2155
2156