@@ -29,6 +29,7 @@ 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 lowerArrayDtor (ArrayDtor op);
3233 void lowerArrayCtor (ArrayCtor op);
3334
3435 // /
@@ -172,28 +173,29 @@ 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+ mlir::Value numArrayElementsConst =
186+ builder.getUnsignedInt (loc, arrayLen, sizeTypeSize);
187187
188188 auto begin = builder.create <cir::CastOp>(
189189 loc, eltTy, cir::CastKind::array_to_ptrdecay, arrayAddr);
190190 mlir::Value end = builder.create <cir::PtrStrideOp>(loc, eltTy, begin,
191191 numArrayElementsConst);
192+ mlir::Value start = isCtor ? begin : end;
193+ mlir::Value stop = isCtor ? end : begin;
192194
193195 mlir::Value tmpAddr = builder.createAlloca (
194196 loc, /* addr type*/ builder.getPointerTo (eltTy),
195197 /* var type*/ eltTy, " __array_idx" , builder.getAlignmentAttr (1 ));
196- builder.createStore (loc, begin , tmpAddr);
198+ builder.createStore (loc, start , tmpAddr);
197199
198200 cir::DoWhileOp loop = builder.createDoWhile (
199201 loc,
@@ -202,7 +204,7 @@ static void lowerArrayDtorCtorIntoLoop(cir::CIRBaseBuilderTy &builder,
202204 auto currentElement = b.create <cir::LoadOp>(loc, eltTy, tmpAddr);
203205 mlir::Type boolTy = cir::BoolType::get (b.getContext ());
204206 auto cmp = builder.create <cir::CmpOp>(loc, boolTy, cir::CmpOpKind::ne,
205- currentElement, end );
207+ currentElement, stop );
206208 builder.createCondition (cmp);
207209 },
208210 /* bodyBuilder=*/
@@ -213,15 +215,23 @@ static void lowerArrayDtorCtorIntoLoop(cir::CIRBaseBuilderTy &builder,
213215 op->walk ([&](cir::CallOp c) { ctorCall = c; });
214216 assert (ctorCall && " expected ctor call" );
215217
216- auto one = builder.create <cir::ConstantOp>(
217- loc, ptrDiffTy, cir::IntAttr::get (ptrDiffTy, 1 ));
218-
219- ctorCall->moveAfter (one);
220- ctorCall->setOperand (0 , currentElement);
221-
222- // Advance pointer and store them to temporary variable
223- auto nextElement =
224- builder.create <cir::PtrStrideOp>(loc, eltTy, currentElement, one);
218+ // Array elements get constructed in order but destructed in reverse.
219+ cir::PtrStrideOp nextElement;
220+ if (isCtor) {
221+ mlir::Value stride = builder.getUnsignedInt (loc, 1 , sizeTypeSize);
222+ ctorCall->moveBefore (stride.getDefiningOp ());
223+ ctorCall->setOperand (0 , currentElement);
224+ nextElement = builder.create <cir::PtrStrideOp>(
225+ loc, eltTy, currentElement, stride);
226+ } else {
227+ mlir::Value stride = builder.getSignedInt (loc, -1 , sizeTypeSize);
228+ nextElement = builder.create <cir::PtrStrideOp>(
229+ loc, eltTy, currentElement, stride);
230+ ctorCall->moveAfter (nextElement);
231+ ctorCall->setOperand (0 , nextElement);
232+ }
233+
234+ // Store the element pointer to the temporary variable
225235 builder.createStore (loc, nextElement, tmpAddr);
226236 builder.createYield (loc);
227237 });
@@ -230,6 +240,17 @@ static void lowerArrayDtorCtorIntoLoop(cir::CIRBaseBuilderTy &builder,
230240 op->erase ();
231241}
232242
243+ void LoweringPreparePass::lowerArrayDtor (ArrayDtor op) {
244+ CIRBaseBuilderTy builder (getContext ());
245+ builder.setInsertionPointAfter (op.getOperation ());
246+
247+ mlir::Type eltTy = op->getRegion (0 ).getArgument (0 ).getType ();
248+ auto arrayLen =
249+ mlir::cast<cir::ArrayType>(op.getAddr ().getType ().getPointee ()).getSize ();
250+ lowerArrayDtorCtorIntoLoop (builder, astCtx, op, eltTy, op.getAddr (), arrayLen,
251+ false );
252+ }
253+
233254void LoweringPreparePass::lowerArrayCtor (cir::ArrayCtor op) {
234255 cir::CIRBaseBuilderTy builder (getContext ());
235256 builder.setInsertionPointAfter (op.getOperation ());
@@ -238,8 +259,8 @@ void LoweringPreparePass::lowerArrayCtor(cir::ArrayCtor op) {
238259 assert (!cir::MissingFeatures::vlas ());
239260 auto arrayLen =
240261 mlir::cast<cir::ArrayType>(op.getAddr ().getType ().getPointee ()).getSize ();
241- lowerArrayDtorCtorIntoLoop (builder, astCtx, op, eltTy, op.getAddr (),
242- arrayLen );
262+ lowerArrayDtorCtorIntoLoop (builder, astCtx, op, eltTy, op.getAddr (), arrayLen,
263+ true );
243264}
244265
245266void LoweringPreparePass::runOnOp (mlir::Operation *op) {
@@ -249,6 +270,8 @@ void LoweringPreparePass::runOnOp(mlir::Operation *op) {
249270 lowerCastOp (cast);
250271 else if (auto unary = mlir::dyn_cast<cir::UnaryOp>(op))
251272 lowerUnaryOp (unary);
273+ else if (auto arrayDtor = dyn_cast<ArrayDtor>(op))
274+ lowerArrayDtor (arrayDtor);
252275}
253276
254277void LoweringPreparePass::runOnOperation () {
@@ -257,7 +280,8 @@ void LoweringPreparePass::runOnOperation() {
257280 llvm::SmallVector<mlir::Operation *> opsToTransform;
258281
259282 op->walk ([&](mlir::Operation *op) {
260- if (mlir::isa<cir::ArrayCtor, cir::CastOp, cir::UnaryOp>(op))
283+ if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp, cir::UnaryOp>(
284+ op))
261285 opsToTransform.push_back (op);
262286 });
263287
0 commit comments