@@ -216,16 +216,113 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
216
216
217
217
// Unary Operators.
218
218
mlir::Value VisitUnaryPostDec (const UnaryOperator *E) {
219
- llvm_unreachable ( " NYI " );
219
+ return buildScalarPrePostIncDec (E );
220
220
}
221
221
mlir::Value VisitUnaryPostInc (const UnaryOperator *E) {
222
- llvm_unreachable ( " NYI " );
222
+ return buildScalarPrePostIncDec (E );
223
223
}
224
224
mlir::Value VisitUnaryPreDec (const UnaryOperator *E) {
225
- llvm_unreachable ( " NYI " );
225
+ return buildScalarPrePostIncDec (E );
226
226
}
227
227
mlir::Value VisitUnaryPreInc (const UnaryOperator *E) {
228
- llvm_unreachable (" NYI" );
228
+ return buildScalarPrePostIncDec (E);
229
+ }
230
+ mlir::Value buildScalarPrePostIncDec (const UnaryOperator *E) {
231
+ QualType type = E->getSubExpr ()->getType ();
232
+
233
+ auto LV = CGF.buildLValue (E->getSubExpr ());
234
+ mlir::Value Value;
235
+ mlir::Value Input;
236
+
237
+ if (const AtomicType *atomicTy = type->getAs <AtomicType>()) {
238
+ assert (0 && " no atomics inc/dec yet" );
239
+ } else {
240
+ Value = buildLoadOfLValue (LV, E->getExprLoc ());
241
+ Input = Value;
242
+ }
243
+
244
+ // NOTE: When possible, more frequent cases are handled first.
245
+
246
+ // Special case of integer increment that we have to check first: bool++.
247
+ // Due to promotion rules, we get:
248
+ // bool++ -> bool = bool + 1
249
+ // -> bool = (int)bool + 1
250
+ // -> bool = ((int)bool + 1 != 0)
251
+ // An interesting aspect of this is that increment is always true.
252
+ // Decrement does not have this property.
253
+ if (E->isIncrementOp () && type->isBooleanType ()) {
254
+ assert (0 && " inc simplification for booleans not implemented yet" );
255
+
256
+ // NOTE: We likely want the code below, but loading/store booleans need to work first.
257
+ // See CIRGenFunction::buildFromMemory().
258
+ Value = Builder.create <mlir::cir::ConstantOp>(CGF.getLoc (E->getExprLoc ()),
259
+ CGF.getCIRType (type),
260
+ Builder.getBoolAttr (true ));
261
+ } else if (type->isIntegerType ()) {
262
+ bool canPerformLossyDemotionCheck = false ;
263
+ if (type->isPromotableIntegerType ()) {
264
+ canPerformLossyDemotionCheck = true ;
265
+ assert (0 && " no promotable integer inc/dec yet" );
266
+ }
267
+
268
+ if (CGF.SanOpts .hasOneOf (
269
+ SanitizerKind::ImplicitIntegerArithmeticValueChange) &&
270
+ canPerformLossyDemotionCheck) {
271
+ assert (0 &&
272
+ " perform lossy demotion case for inc/dec not implemented yet" );
273
+ } else if (E->canOverflow () && type->isSignedIntegerOrEnumerationType ()) {
274
+ Value = buildIncDecConsiderOverflowBehavior (E, Value);
275
+ } else if (E->canOverflow () && type->isUnsignedIntegerType () &&
276
+ CGF.SanOpts .has (SanitizerKind::UnsignedIntegerOverflow)) {
277
+ assert (0 &&
278
+ " unsigned integer overflow sanitized inc/dec not implemented" );
279
+ } else {
280
+ auto Kind = E->isIncrementOp () ? mlir::cir::UnaryOpKind::Inc
281
+ : mlir::cir::UnaryOpKind::Dec;
282
+ Value = buildUnaryOp (E, Kind, Input);
283
+ }
284
+ } else if (const PointerType *ptr = type->getAs <PointerType>()) {
285
+ assert (0 && " no pointer inc/dec yet" );
286
+ } else if (type->isVectorType ()) {
287
+ assert (0 && " no vector inc/dec yet" );
288
+ } else if (type->isRealFloatingType ()) {
289
+ assert (0 && " no float inc/dec yet" );
290
+ } else if (type->isFixedPointType ()) {
291
+ assert (0 && " no fixed point inc/dec yet" );
292
+ } else {
293
+ assert (type->castAs <ObjCObjectPointerType>());
294
+ assert (0 && " no objc pointer type inc/dec yet" );
295
+ }
296
+
297
+ CIRGenFunction::SourceLocRAIIObject sourceloc{
298
+ CGF, CGF.getLoc (E->getSourceRange ())};
299
+
300
+ if (LV.isBitField ())
301
+ assert (0 && " no bitfield inc/dec yet" );
302
+ else
303
+ CGF.buildStoreThroughLValue (RValue::get (Value), LV, nullptr );
304
+
305
+ return E->isPrefix () ? Value : Input;
306
+ }
307
+
308
+ mlir::Value buildIncDecConsiderOverflowBehavior (const UnaryOperator *E,
309
+ mlir::Value V) {
310
+ switch (CGF.getLangOpts ().getSignedOverflowBehavior ()) {
311
+ case LangOptions::SOB_Defined: {
312
+ auto Kind = E->isIncrementOp () ? mlir::cir::UnaryOpKind::Inc
313
+ : mlir::cir::UnaryOpKind::Dec;
314
+ return buildUnaryOp (E, Kind, V);
315
+ break ;
316
+ }
317
+ case LangOptions::SOB_Undefined:
318
+ assert (0 &&
319
+ " inc/dec overflow behavior SOB_Undefined not implemented yet" );
320
+ break ;
321
+ case LangOptions::SOB_Trapping:
322
+ assert (0 && " inc/dec overflow behavior SOB_Trapping not implemented yet" );
323
+ break ;
324
+ }
325
+ llvm_unreachable (" Unknown SignedOverflowBehaviorTy" );
229
326
}
230
327
231
328
mlir::Value VisitUnaryAddrOf (const UnaryOperator *E) {
@@ -256,6 +353,13 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
256
353
llvm_unreachable (" NYI" );
257
354
}
258
355
356
+ mlir::Value buildUnaryOp (const UnaryOperator *E, mlir::cir::UnaryOpKind kind,
357
+ mlir::Value input) {
358
+ return Builder.create <mlir::cir::UnaryOp>(
359
+ CGF.getLoc (E->getSourceRange ().getBegin ()),
360
+ CGF.getCIRType (E->getType ()), kind, input);
361
+ }
362
+
259
363
// C++
260
364
mlir::Value VisitMaterializeTemporaryExpr (const MaterializeTemporaryExpr *E) {
261
365
llvm_unreachable (" NYI" );
0 commit comments