@@ -29,7 +29,8 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> {
2929 void runOnOp (mlir::Operation *op);
3030 void lowerCastOp (cir::CastOp op);
3131 void lowerUnaryOp (cir::UnaryOp op);
32- void lowerArrayCtor (ArrayCtor op);
32+ void lowerArrayDtor (cir::ArrayDtor op);
33+ void lowerArrayCtor (cir::ArrayCtor op);
3334
3435 // /
3536 // / AST related
@@ -172,28 +173,30 @@ void LoweringPreparePass::lowerUnaryOp(cir::UnaryOp op) {
172173static void lowerArrayDtorCtorIntoLoop (cir::CIRBaseBuilderTy &builder,
173174 clang::ASTContext *astCtx,
174175 mlir::Operation *op, mlir::Type eltTy,
175- mlir::Value arrayAddr,
176- uint64_t arrayLen ) {
176+ mlir::Value arrayAddr, uint64_t arrayLen,
177+ bool isCtor ) {
177178 // Generate loop to call into ctor/dtor for every element.
178179 mlir::Location loc = op->getLoc ();
179180
180- // TODO: instead of fixed integer size, create alias for PtrDiffTy and unify
181- // with CIRGen stuff.
181+ // TODO: instead of getting the size from the AST context , create alias for
182+ // PtrDiffTy and unify with CIRGen stuff.
182183 const unsigned sizeTypeSize =
183184 astCtx->getTypeSize (astCtx->getSignedSizeType ());
184- auto ptrDiffTy =
185- cir::IntType::get (builder. getContext (), sizeTypeSize, /* isSigned= */ false );
186- mlir::Value numArrayElementsConst = builder.getUnsignedInt (loc, arrayLen, 64 );
185+ uint64_t endOffset = isCtor ? arrayLen : arrayLen - 1 ;
186+ mlir::Value endOffsetVal =
187+ builder.getUnsignedInt (loc, endOffset, sizeTypeSize );
187188
188- auto begin = builder.create <cir::CastOp>(
189- loc, eltTy, cir::CastKind::array_to_ptrdecay, arrayAddr);
190- mlir::Value end = builder.create <cir::PtrStrideOp>(loc, eltTy, begin,
191- numArrayElementsConst);
189+ auto begin = cir::CastOp::create (builder, loc, eltTy,
190+ cir::CastKind::array_to_ptrdecay, arrayAddr);
191+ mlir::Value end =
192+ cir::PtrStrideOp::create (builder, loc, eltTy, begin, endOffsetVal);
193+ mlir::Value start = isCtor ? begin : end;
194+ mlir::Value stop = isCtor ? end : begin;
192195
193196 mlir::Value tmpAddr = builder.createAlloca (
194197 loc, /* addr type*/ builder.getPointerTo (eltTy),
195198 /* var type*/ eltTy, " __array_idx" , builder.getAlignmentAttr (1 ));
196- builder.createStore (loc, begin , tmpAddr);
199+ builder.createStore (loc, start , tmpAddr);
197200
198201 cir::DoWhileOp loop = builder.createDoWhile (
199202 loc,
@@ -202,7 +205,7 @@ static void lowerArrayDtorCtorIntoLoop(cir::CIRBaseBuilderTy &builder,
202205 auto currentElement = b.create <cir::LoadOp>(loc, eltTy, tmpAddr);
203206 mlir::Type boolTy = cir::BoolType::get (b.getContext ());
204207 auto cmp = builder.create <cir::CmpOp>(loc, boolTy, cir::CmpOpKind::ne,
205- currentElement, end );
208+ currentElement, stop );
206209 builder.createCondition (cmp);
207210 },
208211 /* bodyBuilder=*/
@@ -213,15 +216,19 @@ static void lowerArrayDtorCtorIntoLoop(cir::CIRBaseBuilderTy &builder,
213216 op->walk ([&](cir::CallOp c) { ctorCall = c; });
214217 assert (ctorCall && " expected ctor call" );
215218
216- auto one = builder.create <cir::ConstantOp>(
217- loc, ptrDiffTy, cir::IntAttr::get (ptrDiffTy, 1 ));
219+ // Array elements get constructed in order but destructed in reverse.
220+ mlir::Value stride;
221+ if (isCtor)
222+ stride = builder.getUnsignedInt (loc, 1 , sizeTypeSize);
223+ else
224+ stride = builder.getSignedInt (loc, -1 , sizeTypeSize);
218225
219- ctorCall->moveAfter (one );
226+ ctorCall->moveBefore (stride. getDefiningOp () );
220227 ctorCall->setOperand (0 , currentElement);
228+ auto nextElement = cir::PtrStrideOp::create (builder, loc, eltTy,
229+ currentElement, stride);
221230
222- // Advance pointer and store them to temporary variable
223- auto nextElement =
224- builder.create <cir::PtrStrideOp>(loc, eltTy, currentElement, one);
231+ // Store the element pointer to the temporary variable
225232 builder.createStore (loc, nextElement, tmpAddr);
226233 builder.createYield (loc);
227234 });
@@ -230,6 +237,18 @@ static void lowerArrayDtorCtorIntoLoop(cir::CIRBaseBuilderTy &builder,
230237 op->erase ();
231238}
232239
240+ void LoweringPreparePass::lowerArrayDtor (cir::ArrayDtor op) {
241+ CIRBaseBuilderTy builder (getContext ());
242+ builder.setInsertionPointAfter (op.getOperation ());
243+
244+ mlir::Type eltTy = op->getRegion (0 ).getArgument (0 ).getType ();
245+ assert (!cir::MissingFeatures::vlas ());
246+ auto arrayLen =
247+ mlir::cast<cir::ArrayType>(op.getAddr ().getType ().getPointee ()).getSize ();
248+ lowerArrayDtorCtorIntoLoop (builder, astCtx, op, eltTy, op.getAddr (), arrayLen,
249+ false );
250+ }
251+
233252void LoweringPreparePass::lowerArrayCtor (cir::ArrayCtor op) {
234253 cir::CIRBaseBuilderTy builder (getContext ());
235254 builder.setInsertionPointAfter (op.getOperation ());
@@ -238,13 +257,15 @@ void LoweringPreparePass::lowerArrayCtor(cir::ArrayCtor op) {
238257 assert (!cir::MissingFeatures::vlas ());
239258 auto arrayLen =
240259 mlir::cast<cir::ArrayType>(op.getAddr ().getType ().getPointee ()).getSize ();
241- lowerArrayDtorCtorIntoLoop (builder, astCtx, op, eltTy, op.getAddr (),
242- arrayLen );
260+ lowerArrayDtorCtorIntoLoop (builder, astCtx, op, eltTy, op.getAddr (), arrayLen,
261+ true );
243262}
244263
245264void LoweringPreparePass::runOnOp (mlir::Operation *op) {
246265 if (auto arrayCtor = dyn_cast<ArrayCtor>(op))
247266 lowerArrayCtor (arrayCtor);
267+ else if (auto arrayDtor = dyn_cast<cir::ArrayDtor>(op))
268+ lowerArrayDtor (arrayDtor);
248269 else if (auto cast = mlir::dyn_cast<cir::CastOp>(op))
249270 lowerCastOp (cast);
250271 else if (auto unary = mlir::dyn_cast<cir::UnaryOp>(op))
@@ -257,7 +278,8 @@ void LoweringPreparePass::runOnOperation() {
257278 llvm::SmallVector<mlir::Operation *> opsToTransform;
258279
259280 op->walk ([&](mlir::Operation *op) {
260- if (mlir::isa<cir::ArrayCtor, cir::CastOp, cir::UnaryOp>(op))
281+ if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp, cir::UnaryOp>(
282+ op))
261283 opsToTransform.push_back (op);
262284 });
263285
0 commit comments