@@ -231,3 +231,127 @@ void fir::factory::AnyValueStack::destroy(mlir::Location loc,
231
231
fir::FirOpBuilder &builder) {
232
232
fir::runtime::genDestroyValueStack (loc, builder, opaquePtr);
233
233
}
234
+
235
+ // ===----------------------------------------------------------------------===//
236
+ // fir::factory::AnyVariableStack implementation.
237
+ // ===----------------------------------------------------------------------===//
238
+
239
+ fir::factory::AnyVariableStack::AnyVariableStack (mlir::Location loc,
240
+ fir::FirOpBuilder &builder,
241
+ mlir::Type variableStaticType)
242
+ : variableStaticType{variableStaticType},
243
+ counter{loc, builder,
244
+ builder.createIntegerConstant (loc, builder.getI64Type (), 0 ),
245
+ /* stackThroughLoops=*/ true } {
246
+ opaquePtr = fir::runtime::genCreateDescriptorStack (loc, builder);
247
+ mlir::Type storageType =
248
+ hlfir::getFortranElementOrSequenceType (variableStaticType);
249
+ mlir::Type ptrType = fir::PointerType::get (storageType);
250
+ mlir::Type boxType;
251
+ if (hlfir::isPolymorphicType (variableStaticType))
252
+ boxType = fir::ClassType::get (ptrType);
253
+ else
254
+ boxType = fir::BoxType::get (ptrType);
255
+ retValueBox = builder.createTemporary (loc, boxType);
256
+ }
257
+
258
+ void fir::factory::AnyVariableStack::pushValue (mlir::Location loc,
259
+ fir::FirOpBuilder &builder,
260
+ mlir::Value variable) {
261
+ hlfir::Entity entity{variable};
262
+ mlir::Type storageElementType =
263
+ hlfir::getFortranElementType (retValueBox.getType ());
264
+ auto [box, maybeCleanUp] =
265
+ hlfir::convertToBox (loc, builder, entity, storageElementType);
266
+ fir::runtime::genPushDescriptor (loc, builder, opaquePtr, fir::getBase (box));
267
+ if (maybeCleanUp)
268
+ (*maybeCleanUp)();
269
+ }
270
+
271
+ void fir::factory::AnyVariableStack::resetFetchPosition (
272
+ mlir::Location loc, fir::FirOpBuilder &builder) {
273
+ counter.reset (loc, builder);
274
+ }
275
+
276
+ mlir::Value fir::factory::AnyVariableStack::fetch (mlir::Location loc,
277
+ fir::FirOpBuilder &builder) {
278
+ mlir::Value indexValue = counter.getAndIncrementIndex (loc, builder);
279
+ fir::runtime::genDescriptorAt (loc, builder, opaquePtr, indexValue,
280
+ retValueBox);
281
+ hlfir::Entity retBox{builder.create <fir::LoadOp>(loc, retValueBox)};
282
+ // The runtime always tracks variable as address, but the form of the variable
283
+ // that was saved may be different (raw address, fir.boxchar), ensure
284
+ // the returned variable has the same form of the one that was saved.
285
+ if (mlir::isa<fir::BaseBoxType>(variableStaticType))
286
+ return builder.createConvert (loc, variableStaticType, retBox);
287
+ if (mlir::isa<fir::BoxCharType>(variableStaticType))
288
+ return hlfir::genVariableBoxChar (loc, builder, retBox);
289
+ mlir::Value rawAddr = genVariableRawAddress (loc, builder, retBox);
290
+ return builder.createConvert (loc, variableStaticType, rawAddr);
291
+ }
292
+
293
+ void fir::factory::AnyVariableStack::destroy (mlir::Location loc,
294
+ fir::FirOpBuilder &builder) {
295
+ fir::runtime::genDestroyDescriptorStack (loc, builder, opaquePtr);
296
+ }
297
+
298
+ // ===----------------------------------------------------------------------===//
299
+ // fir::factory::AnyVectorSubscriptStack implementation.
300
+ // ===----------------------------------------------------------------------===//
301
+
302
+ fir::factory::AnyVectorSubscriptStack::AnyVectorSubscriptStack (
303
+ mlir::Location loc, fir::FirOpBuilder &builder,
304
+ mlir::Type variableStaticType, bool shapeCanBeSavedAsRegister, int rank)
305
+ : AnyVariableStack{loc, builder, variableStaticType} {
306
+ if (shapeCanBeSavedAsRegister) {
307
+ shapeTemp =
308
+ std::unique_ptr<TemporaryStorage>(new TemporaryStorage{SSARegister{}});
309
+ return ;
310
+ }
311
+ // The shape will be tracked as the dimension inside a descriptor because
312
+ // that is the easiest from a lowering point of view, and this is an
313
+ // edge case situation that will probably not very well be exercised.
314
+ mlir::Type type =
315
+ fir::BoxType::get (builder.getVarLenSeqTy (builder.getI32Type (), rank));
316
+ boxType = type;
317
+ shapeTemp = std::unique_ptr<TemporaryStorage>(
318
+ new TemporaryStorage{AnyVariableStack{loc, builder, type}});
319
+ }
320
+
321
+ void fir::factory::AnyVectorSubscriptStack::pushShape (
322
+ mlir::Location loc, fir::FirOpBuilder &builder, mlir::Value shape) {
323
+ if (boxType) {
324
+ // The shape is saved as a dimensions inside a descriptors.
325
+ mlir::Type refType = fir::ReferenceType::get (
326
+ hlfir::getFortranElementOrSequenceType (*boxType));
327
+ mlir::Value null = builder.createNullConstant (loc, refType);
328
+ mlir::Value descriptor =
329
+ builder.create <fir::EmboxOp>(loc, *boxType, null, shape);
330
+ shapeTemp->pushValue (loc, builder, descriptor);
331
+ return ;
332
+ }
333
+ // Otherwise, simply keep track of the fir.shape itself, it is invariant.
334
+ shapeTemp->cast <SSARegister>().pushValue (loc, builder, shape);
335
+ }
336
+
337
+ void fir::factory::AnyVectorSubscriptStack::resetFetchPosition (
338
+ mlir::Location loc, fir::FirOpBuilder &builder) {
339
+ static_cast <AnyVariableStack *>(this )->resetFetchPosition (loc, builder);
340
+ shapeTemp->resetFetchPosition (loc, builder);
341
+ }
342
+
343
+ mlir::Value
344
+ fir::factory::AnyVectorSubscriptStack::fetchShape (mlir::Location loc,
345
+ fir::FirOpBuilder &builder) {
346
+ if (boxType) {
347
+ hlfir::Entity descriptor{shapeTemp->fetch (loc, builder)};
348
+ return hlfir::genShape (loc, builder, descriptor);
349
+ }
350
+ return shapeTemp->cast <SSARegister>().fetch (loc, builder);
351
+ }
352
+
353
+ void fir::factory::AnyVectorSubscriptStack::destroy (
354
+ mlir::Location loc, fir::FirOpBuilder &builder) {
355
+ static_cast <AnyVariableStack *>(this )->destroy (loc, builder);
356
+ shapeTemp->destroy (loc, builder);
357
+ }
0 commit comments