1a2e7af75SValentin Clement //===-- MutableBox.cpp -- MutableBox utilities ----------------------------===// 2a2e7af75SValentin Clement // 3a2e7af75SValentin Clement // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a2e7af75SValentin Clement // See https://llvm.org/LICENSE.txt for license information. 5a2e7af75SValentin Clement // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a2e7af75SValentin Clement // 7a2e7af75SValentin Clement //===----------------------------------------------------------------------===// 8a2e7af75SValentin Clement // 9a2e7af75SValentin Clement // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ 10a2e7af75SValentin Clement // 11a2e7af75SValentin Clement //===----------------------------------------------------------------------===// 12a2e7af75SValentin Clement 13a2e7af75SValentin Clement #include "flang/Optimizer/Builder/MutableBox.h" 14a2e7af75SValentin Clement #include "flang/Optimizer/Builder/Character.h" 15a2e7af75SValentin Clement #include "flang/Optimizer/Builder/FIRBuilder.h" 162a59ead1SValentin Clement #include "flang/Optimizer/Builder/Runtime/Derived.h" 172a59ead1SValentin Clement #include "flang/Optimizer/Builder/Runtime/Stop.h" 185b66cc10SValentin Clement #include "flang/Optimizer/Builder/Todo.h" 19cc14bf22STom Eccles #include "flang/Optimizer/Dialect/FIRAttr.h" 20a2e7af75SValentin Clement #include "flang/Optimizer/Dialect/FIROps.h" 21a2e7af75SValentin Clement #include "flang/Optimizer/Dialect/FIROpsSupport.h" 22a2e7af75SValentin Clement #include "flang/Optimizer/Support/FatalError.h" 23a2e7af75SValentin Clement 242a59ead1SValentin Clement /// Create a fir.box describing the new address, bounds, and length parameters 252a59ead1SValentin Clement /// for a MutableBox \p box. 26880b37f1SValentin Clement static mlir::Value 27880b37f1SValentin Clement createNewFirBox(fir::FirOpBuilder &builder, mlir::Location loc, 28880b37f1SValentin Clement const fir::MutableBoxValue &box, mlir::Value addr, 29880b37f1SValentin Clement mlir::ValueRange lbounds, mlir::ValueRange extents, 30880b37f1SValentin Clement mlir::ValueRange lengths, mlir::Value tdesc = {}) { 31fac349a1SChristian Sigg if (mlir::isa<fir::BaseBoxType>(addr.getType())) 322a59ead1SValentin Clement // The entity is already boxed. 332a59ead1SValentin Clement return builder.createConvert(loc, box.getBoxTy(), addr); 342a59ead1SValentin Clement 352a59ead1SValentin Clement mlir::Value shape; 362a59ead1SValentin Clement if (!extents.empty()) { 372a59ead1SValentin Clement if (lbounds.empty()) { 38b22fa865SJean Perier shape = builder.create<fir::ShapeOp>(loc, extents); 392a59ead1SValentin Clement } else { 402a59ead1SValentin Clement llvm::SmallVector<mlir::Value> shapeShiftBounds; 412a59ead1SValentin Clement for (auto [lb, extent] : llvm::zip(lbounds, extents)) { 422a59ead1SValentin Clement shapeShiftBounds.emplace_back(lb); 432a59ead1SValentin Clement shapeShiftBounds.emplace_back(extent); 442a59ead1SValentin Clement } 452a59ead1SValentin Clement auto shapeShiftType = 462a59ead1SValentin Clement fir::ShapeShiftType::get(builder.getContext(), extents.size()); 472a59ead1SValentin Clement shape = builder.create<fir::ShapeShiftOp>(loc, shapeShiftType, 482a59ead1SValentin Clement shapeShiftBounds); 492a59ead1SValentin Clement } 502a59ead1SValentin Clement } // Otherwise, this a scalar. Leave the shape empty. 512a59ead1SValentin Clement 522a59ead1SValentin Clement // Ignore lengths if already constant in the box type (this would trigger an 532a59ead1SValentin Clement // error in the embox). 542a59ead1SValentin Clement llvm::SmallVector<mlir::Value> cleanedLengths; 552a59ead1SValentin Clement auto cleanedAddr = addr; 56fac349a1SChristian Sigg if (auto charTy = mlir::dyn_cast<fir::CharacterType>(box.getEleTy())) { 572a59ead1SValentin Clement // Cast address to box type so that both input and output type have 582a59ead1SValentin Clement // unknown or constant lengths. 592a59ead1SValentin Clement auto bt = box.getBaseTy(); 602a59ead1SValentin Clement auto addrTy = addr.getType(); 61fac349a1SChristian Sigg auto type = mlir::isa<fir::HeapType>(addrTy) ? fir::HeapType::get(bt) 62fac349a1SChristian Sigg : mlir::isa<fir::PointerType>(addrTy) 63fac349a1SChristian Sigg ? fir::PointerType::get(bt) 642a59ead1SValentin Clement : builder.getRefType(bt); 652a59ead1SValentin Clement cleanedAddr = builder.createConvert(loc, type, addr); 662a59ead1SValentin Clement if (charTy.getLen() == fir::CharacterType::unknownLen()) 672a59ead1SValentin Clement cleanedLengths.append(lengths.begin(), lengths.end()); 6839ad49ecSValentin Clement } else if (fir::isUnlimitedPolymorphicType(box.getBoxTy())) { 69fac349a1SChristian Sigg if (auto charTy = mlir::dyn_cast<fir::CharacterType>( 70fac349a1SChristian Sigg fir::dyn_cast_ptrEleTy(addr.getType()))) { 7139ad49ecSValentin Clement if (charTy.getLen() == fir::CharacterType::unknownLen()) 7239ad49ecSValentin Clement cleanedLengths.append(lengths.begin(), lengths.end()); 7339ad49ecSValentin Clement } 741bffc753SEric Schweitz } else if (box.isDerivedWithLenParameters()) { 752a59ead1SValentin Clement TODO(loc, "updating mutablebox of derived type with length parameters"); 762a59ead1SValentin Clement cleanedLengths = lengths; 772a59ead1SValentin Clement } 782a59ead1SValentin Clement mlir::Value emptySlice; 792a59ead1SValentin Clement return builder.create<fir::EmboxOp>(loc, box.getBoxTy(), cleanedAddr, shape, 80880b37f1SValentin Clement emptySlice, cleanedLengths, tdesc); 812a59ead1SValentin Clement } 822a59ead1SValentin Clement 83a2e7af75SValentin Clement //===----------------------------------------------------------------------===// 84a2e7af75SValentin Clement // MutableBoxValue writer and reader 85a2e7af75SValentin Clement //===----------------------------------------------------------------------===// 86a2e7af75SValentin Clement 87a2e7af75SValentin Clement namespace { 88a2e7af75SValentin Clement /// MutablePropertyWriter and MutablePropertyReader implementations are the only 89a2e7af75SValentin Clement /// places that depend on how the properties of MutableBoxValue (pointers and 90a2e7af75SValentin Clement /// allocatables) that can be modified in the lifetime of the entity (address, 91a2e7af75SValentin Clement /// extents, lower bounds, length parameters) are represented. 92a2e7af75SValentin Clement /// That is, the properties may be only stored in a fir.box in memory if we 93a2e7af75SValentin Clement /// need to enforce a single point of truth for the properties across calls. 94a2e7af75SValentin Clement /// Or, they can be tracked as independent local variables when it is safe to 95a2e7af75SValentin Clement /// do so. Using bare variables benefits from all optimization passes, even 96a2e7af75SValentin Clement /// when they are not aware of what a fir.box is and fir.box have not been 97a2e7af75SValentin Clement /// optimized out yet. 98a2e7af75SValentin Clement 99a2e7af75SValentin Clement /// MutablePropertyWriter allows reading the properties of a MutableBoxValue. 100a2e7af75SValentin Clement class MutablePropertyReader { 101a2e7af75SValentin Clement public: 102a2e7af75SValentin Clement MutablePropertyReader(fir::FirOpBuilder &builder, mlir::Location loc, 103a2e7af75SValentin Clement const fir::MutableBoxValue &box, 104a2e7af75SValentin Clement bool forceIRBoxRead = false) 105a2e7af75SValentin Clement : builder{builder}, loc{loc}, box{box} { 106a2e7af75SValentin Clement if (forceIRBoxRead || !box.isDescribedByVariables()) 107a2e7af75SValentin Clement irBox = builder.create<fir::LoadOp>(loc, box.getAddr()); 108a2e7af75SValentin Clement } 109a2e7af75SValentin Clement /// Get base address of allocated/associated entity. 110a2e7af75SValentin Clement mlir::Value readBaseAddress() { 111a2e7af75SValentin Clement if (irBox) { 11296d9df41SValentin Clement auto memrefTy = box.getBoxTy().getEleTy(); 11396d9df41SValentin Clement if (!fir::isa_ref_type(memrefTy)) 11496d9df41SValentin Clement memrefTy = builder.getRefType(memrefTy); 11596d9df41SValentin Clement return builder.create<fir::BoxAddrOp>(loc, memrefTy, irBox); 116a2e7af75SValentin Clement } 117a2e7af75SValentin Clement auto addrVar = box.getMutableProperties().addr; 118a2e7af75SValentin Clement return builder.create<fir::LoadOp>(loc, addrVar); 119a2e7af75SValentin Clement } 120a2e7af75SValentin Clement /// Return {lbound, extent} values read from the MutableBoxValue given 121a2e7af75SValentin Clement /// the dimension. 122a2e7af75SValentin Clement std::pair<mlir::Value, mlir::Value> readShape(unsigned dim) { 123a2e7af75SValentin Clement auto idxTy = builder.getIndexType(); 124a2e7af75SValentin Clement if (irBox) { 125a2e7af75SValentin Clement auto dimVal = builder.createIntegerConstant(loc, idxTy, dim); 126a2e7af75SValentin Clement auto dimInfo = builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, 127a2e7af75SValentin Clement irBox, dimVal); 128a2e7af75SValentin Clement return {dimInfo.getResult(0), dimInfo.getResult(1)}; 129a2e7af75SValentin Clement } 130a2e7af75SValentin Clement const auto &mutableProperties = box.getMutableProperties(); 131a2e7af75SValentin Clement auto lb = builder.create<fir::LoadOp>(loc, mutableProperties.lbounds[dim]); 132a2e7af75SValentin Clement auto ext = builder.create<fir::LoadOp>(loc, mutableProperties.extents[dim]); 133a2e7af75SValentin Clement return {lb, ext}; 134a2e7af75SValentin Clement } 135a2e7af75SValentin Clement 136a2e7af75SValentin Clement /// Return the character length. If the length was not deferred, the value 137a2e7af75SValentin Clement /// that was specified is returned (The mutable fields is not read). 138a2e7af75SValentin Clement mlir::Value readCharacterLength() { 139a2e7af75SValentin Clement if (box.hasNonDeferredLenParams()) 140a2e7af75SValentin Clement return box.nonDeferredLenParams()[0]; 141a2e7af75SValentin Clement if (irBox) 142a2e7af75SValentin Clement return fir::factory::CharacterExprHelper{builder, loc}.readLengthFromBox( 143a2e7af75SValentin Clement irBox); 144a2e7af75SValentin Clement const auto &deferred = box.getMutableProperties().deferredParams; 145a2e7af75SValentin Clement if (deferred.empty()) 146a2e7af75SValentin Clement fir::emitFatalError(loc, "allocatable entity has no length property"); 147a2e7af75SValentin Clement return builder.create<fir::LoadOp>(loc, deferred[0]); 148a2e7af75SValentin Clement } 149a2e7af75SValentin Clement 150a2e7af75SValentin Clement /// Read and return all extents. If \p lbounds vector is provided, lbounds are 151a2e7af75SValentin Clement /// also read into it. 152a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> 153a2e7af75SValentin Clement readShape(llvm::SmallVectorImpl<mlir::Value> *lbounds = nullptr) { 15496d9df41SValentin Clement llvm::SmallVector<mlir::Value> extents; 155a2e7af75SValentin Clement auto rank = box.rank(); 156a2e7af75SValentin Clement for (decltype(rank) dim = 0; dim < rank; ++dim) { 157a2e7af75SValentin Clement auto [lb, extent] = readShape(dim); 158a2e7af75SValentin Clement if (lbounds) 159a2e7af75SValentin Clement lbounds->push_back(lb); 160a2e7af75SValentin Clement extents.push_back(extent); 161a2e7af75SValentin Clement } 162a2e7af75SValentin Clement return extents; 163a2e7af75SValentin Clement } 164a2e7af75SValentin Clement 165a2e7af75SValentin Clement /// Read all mutable properties. Return the base address. 166a2e7af75SValentin Clement mlir::Value read(llvm::SmallVectorImpl<mlir::Value> &lbounds, 167a2e7af75SValentin Clement llvm::SmallVectorImpl<mlir::Value> &extents, 168a2e7af75SValentin Clement llvm::SmallVectorImpl<mlir::Value> &lengths) { 169a2e7af75SValentin Clement extents = readShape(&lbounds); 170a2e7af75SValentin Clement if (box.isCharacter()) 171a2e7af75SValentin Clement lengths.emplace_back(readCharacterLength()); 1721bffc753SEric Schweitz else if (box.isDerivedWithLenParameters()) 173a2e7af75SValentin Clement TODO(loc, "read allocatable or pointer derived type LEN parameters"); 174a2e7af75SValentin Clement return readBaseAddress(); 175a2e7af75SValentin Clement } 176a2e7af75SValentin Clement 177a2e7af75SValentin Clement /// Return the loaded fir.box. 178a2e7af75SValentin Clement mlir::Value getIrBox() const { 179a2e7af75SValentin Clement assert(irBox); 180a2e7af75SValentin Clement return irBox; 181a2e7af75SValentin Clement } 182a2e7af75SValentin Clement 183a2e7af75SValentin Clement /// Read the lower bounds 184a2e7af75SValentin Clement void getLowerBounds(llvm::SmallVectorImpl<mlir::Value> &lbounds) { 185a2e7af75SValentin Clement auto rank = box.rank(); 186a2e7af75SValentin Clement for (decltype(rank) dim = 0; dim < rank; ++dim) 187a2e7af75SValentin Clement lbounds.push_back(std::get<0>(readShape(dim))); 188a2e7af75SValentin Clement } 189a2e7af75SValentin Clement 190a2e7af75SValentin Clement private: 191a2e7af75SValentin Clement fir::FirOpBuilder &builder; 192a2e7af75SValentin Clement mlir::Location loc; 193a2e7af75SValentin Clement fir::MutableBoxValue box; 194a2e7af75SValentin Clement mlir::Value irBox; 195a2e7af75SValentin Clement }; 196a2e7af75SValentin Clement 197a2e7af75SValentin Clement /// MutablePropertyWriter allows modifying the properties of a MutableBoxValue. 198a2e7af75SValentin Clement class MutablePropertyWriter { 199a2e7af75SValentin Clement public: 200a2e7af75SValentin Clement MutablePropertyWriter(fir::FirOpBuilder &builder, mlir::Location loc, 2010b19ac83SValentin Clement const fir::MutableBoxValue &box, 202*bbdb1e40SValentin Clement (バレンタイン クレメン) mlir::Value typeSourceBox = {}, unsigned allocator = 0) 203*bbdb1e40SValentin Clement (バレンタイン クレメン) : builder{builder}, loc{loc}, box{box}, typeSourceBox{typeSourceBox}, 204*bbdb1e40SValentin Clement (バレンタイン クレメン) allocator{allocator} {} 205a2e7af75SValentin Clement /// Update MutableBoxValue with new address, shape and length parameters. 206a2e7af75SValentin Clement /// Extents and lbounds must all have index type. 207a2e7af75SValentin Clement /// lbounds can be empty in which case all ones is assumed. 208a2e7af75SValentin Clement /// Length parameters must be provided for the length parameters that are 209a2e7af75SValentin Clement /// deferred. 210a2e7af75SValentin Clement void updateMutableBox(mlir::Value addr, mlir::ValueRange lbounds, 211880b37f1SValentin Clement mlir::ValueRange extents, mlir::ValueRange lengths, 212880b37f1SValentin Clement mlir::Value tdesc = {}) { 213a2e7af75SValentin Clement if (box.isDescribedByVariables()) 214a2e7af75SValentin Clement updateMutableProperties(addr, lbounds, extents, lengths); 215a2e7af75SValentin Clement else 216880b37f1SValentin Clement updateIRBox(addr, lbounds, extents, lengths, tdesc); 217a2e7af75SValentin Clement } 218a2e7af75SValentin Clement 219a2e7af75SValentin Clement /// Update MutableBoxValue with a new fir.box. This requires that the mutable 220a2e7af75SValentin Clement /// box is not described by a set of variables, since they could not describe 221a2e7af75SValentin Clement /// all that can be described in the new fir.box (e.g. non contiguous entity). 222a2e7af75SValentin Clement void updateWithIrBox(mlir::Value newBox) { 223a2e7af75SValentin Clement assert(!box.isDescribedByVariables()); 224a2e7af75SValentin Clement builder.create<fir::StoreOp>(loc, newBox, box.getAddr()); 225a2e7af75SValentin Clement } 226a2e7af75SValentin Clement /// Set unallocated/disassociated status for the entity described by 227a2e7af75SValentin Clement /// MutableBoxValue. Deallocation is not performed by this helper. 228a2e7af75SValentin Clement void setUnallocatedStatus() { 229a2e7af75SValentin Clement if (box.isDescribedByVariables()) { 230a2e7af75SValentin Clement auto addrVar = box.getMutableProperties().addr; 231a2e7af75SValentin Clement auto nullTy = fir::dyn_cast_ptrEleTy(addrVar.getType()); 232a2e7af75SValentin Clement builder.create<fir::StoreOp>(loc, builder.createNullConstant(loc, nullTy), 233a2e7af75SValentin Clement addrVar); 234a2e7af75SValentin Clement } else { 235a2e7af75SValentin Clement // Note that the dynamic type of polymorphic entities must be reset to the 236a2e7af75SValentin Clement // declaration type of the mutable box. See Fortran 2018 7.8.2 NOTE 1. 237a2e7af75SValentin Clement // For those, we cannot simply set the address to zero. The way we are 238a2e7af75SValentin Clement // currently unallocating fir.box guarantees that we are resetting the 239a2e7af75SValentin Clement // type to the declared type. Beware if changing this. 240a2e7af75SValentin Clement // Note: the standard is not clear in Deallocate and p => NULL semantics 241a2e7af75SValentin Clement // regarding the new dynamic type the entity must have. So far, assume 242a2e7af75SValentin Clement // this is just like NULLIFY and the dynamic type must be set to the 243a2e7af75SValentin Clement // declared type, not retain the previous dynamic type. 244a2e7af75SValentin Clement auto deallocatedBox = fir::factory::createUnallocatedBox( 2450b19ac83SValentin Clement builder, loc, box.getBoxTy(), box.nonDeferredLenParams(), 246*bbdb1e40SValentin Clement (バレンタイン クレメン) typeSourceBox, allocator); 247a2e7af75SValentin Clement builder.create<fir::StoreOp>(loc, deallocatedBox, box.getAddr()); 248a2e7af75SValentin Clement } 249a2e7af75SValentin Clement } 250a2e7af75SValentin Clement 251a2e7af75SValentin Clement /// Copy Values from the fir.box into the property variables if any. 252a2e7af75SValentin Clement void syncMutablePropertiesFromIRBox() { 253a2e7af75SValentin Clement if (!box.isDescribedByVariables()) 254a2e7af75SValentin Clement return; 255a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> lbounds; 256a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> extents; 257a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> lengths; 258a2e7af75SValentin Clement auto addr = 259a2e7af75SValentin Clement MutablePropertyReader{builder, loc, box, /*forceIRBoxRead=*/true}.read( 260a2e7af75SValentin Clement lbounds, extents, lengths); 261a2e7af75SValentin Clement updateMutableProperties(addr, lbounds, extents, lengths); 262a2e7af75SValentin Clement } 263a2e7af75SValentin Clement 264a2e7af75SValentin Clement /// Copy Values from property variables, if any, into the fir.box. 265a2e7af75SValentin Clement void syncIRBoxFromMutableProperties() { 266a2e7af75SValentin Clement if (!box.isDescribedByVariables()) 267a2e7af75SValentin Clement return; 268a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> lbounds; 269a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> extents; 270a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> lengths; 271a2e7af75SValentin Clement auto addr = MutablePropertyReader{builder, loc, box}.read(lbounds, extents, 272a2e7af75SValentin Clement lengths); 273a2e7af75SValentin Clement updateIRBox(addr, lbounds, extents, lengths); 274a2e7af75SValentin Clement } 275a2e7af75SValentin Clement 276a2e7af75SValentin Clement private: 277a2e7af75SValentin Clement /// Update the IR box (fir.ref<fir.box<T>>) of the MutableBoxValue. 278a2e7af75SValentin Clement void updateIRBox(mlir::Value addr, mlir::ValueRange lbounds, 279880b37f1SValentin Clement mlir::ValueRange extents, mlir::ValueRange lengths, 280*bbdb1e40SValentin Clement (バレンタイン クレメン) mlir::Value tdesc = {}, 281*bbdb1e40SValentin Clement (バレンタイン クレメン) unsigned allocator = kDefaultAllocator) { 282880b37f1SValentin Clement mlir::Value irBox = createNewFirBox(builder, loc, box, addr, lbounds, 283880b37f1SValentin Clement extents, lengths, tdesc); 284a2e7af75SValentin Clement builder.create<fir::StoreOp>(loc, irBox, box.getAddr()); 285a2e7af75SValentin Clement } 286a2e7af75SValentin Clement 287a2e7af75SValentin Clement /// Update the set of property variables of the MutableBoxValue. 288a2e7af75SValentin Clement void updateMutableProperties(mlir::Value addr, mlir::ValueRange lbounds, 289a2e7af75SValentin Clement mlir::ValueRange extents, 290a2e7af75SValentin Clement mlir::ValueRange lengths) { 291a2e7af75SValentin Clement auto castAndStore = [&](mlir::Value val, mlir::Value addr) { 292a2e7af75SValentin Clement auto type = fir::dyn_cast_ptrEleTy(addr.getType()); 293a2e7af75SValentin Clement builder.create<fir::StoreOp>(loc, builder.createConvert(loc, type, val), 294a2e7af75SValentin Clement addr); 295a2e7af75SValentin Clement }; 296a2e7af75SValentin Clement const auto &mutableProperties = box.getMutableProperties(); 297a2e7af75SValentin Clement castAndStore(addr, mutableProperties.addr); 298a2e7af75SValentin Clement for (auto [extent, extentVar] : 299a2e7af75SValentin Clement llvm::zip(extents, mutableProperties.extents)) 300a2e7af75SValentin Clement castAndStore(extent, extentVar); 301a2e7af75SValentin Clement if (!mutableProperties.lbounds.empty()) { 302a2e7af75SValentin Clement if (lbounds.empty()) { 303a2e7af75SValentin Clement auto one = 304a2e7af75SValentin Clement builder.createIntegerConstant(loc, builder.getIndexType(), 1); 305a2e7af75SValentin Clement for (auto lboundVar : mutableProperties.lbounds) 306a2e7af75SValentin Clement castAndStore(one, lboundVar); 307a2e7af75SValentin Clement } else { 308a2e7af75SValentin Clement for (auto [lbound, lboundVar] : 309a2e7af75SValentin Clement llvm::zip(lbounds, mutableProperties.lbounds)) 310a2e7af75SValentin Clement castAndStore(lbound, lboundVar); 311a2e7af75SValentin Clement } 312a2e7af75SValentin Clement } 313a2e7af75SValentin Clement if (box.isCharacter()) 314a2e7af75SValentin Clement // llvm::zip account for the fact that the length only needs to be stored 315a2e7af75SValentin Clement // when it is specified in the allocation and deferred in the 316a2e7af75SValentin Clement // MutableBoxValue. 317a2e7af75SValentin Clement for (auto [len, lenVar] : 318a2e7af75SValentin Clement llvm::zip(lengths, mutableProperties.deferredParams)) 319a2e7af75SValentin Clement castAndStore(len, lenVar); 3201bffc753SEric Schweitz else if (box.isDerivedWithLenParameters()) 321a2e7af75SValentin Clement TODO(loc, "update allocatable derived type length parameters"); 322a2e7af75SValentin Clement } 323a2e7af75SValentin Clement fir::FirOpBuilder &builder; 324a2e7af75SValentin Clement mlir::Location loc; 325a2e7af75SValentin Clement fir::MutableBoxValue box; 3260b19ac83SValentin Clement mlir::Value typeSourceBox; 327*bbdb1e40SValentin Clement (バレンタイン クレメン) unsigned allocator; 328a2e7af75SValentin Clement }; 329a2e7af75SValentin Clement 330a2e7af75SValentin Clement } // namespace 331a2e7af75SValentin Clement 3320b19ac83SValentin Clement mlir::Value fir::factory::createUnallocatedBox( 3330b19ac83SValentin Clement fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type boxType, 334*bbdb1e40SValentin Clement (バレンタイン クレメン) mlir::ValueRange nonDeferredParams, mlir::Value typeSourceBox, 335*bbdb1e40SValentin Clement (バレンタイン クレメン) unsigned allocator) { 3364abbf995SjeanPerier auto baseBoxType = mlir::cast<fir::BaseBoxType>(boxType); 3374abbf995SjeanPerier // Giving unallocated/disassociated status to assumed-rank POINTER/ 3384abbf995SjeanPerier // ALLOCATABLE is not directly possible to a Fortran user. But the 3394abbf995SjeanPerier // compiler may need to create such temporary descriptor to deal with 3404abbf995SjeanPerier // cases like ENTRY or host association. In such case, all that mater 3414abbf995SjeanPerier // is that the base address is set to zero and the rank is set to 3424abbf995SjeanPerier // some defined value. Hence, a scalar descriptor is created and 3434abbf995SjeanPerier // cast to assumed-rank. 3444abbf995SjeanPerier const bool isAssumedRank = baseBoxType.isAssumedRank(); 3454abbf995SjeanPerier if (isAssumedRank) 3464abbf995SjeanPerier baseBoxType = baseBoxType.getBoxTypeWithNewShape(/*rank=*/0); 3474abbf995SjeanPerier auto baseAddrType = baseBoxType.getEleTy(); 34894a11063SValentin Clement if (!fir::isa_ref_type(baseAddrType)) 34994a11063SValentin Clement baseAddrType = builder.getRefType(baseAddrType); 35094a11063SValentin Clement auto type = fir::unwrapRefType(baseAddrType); 35194a11063SValentin Clement auto eleTy = fir::unwrapSequenceType(type); 352fac349a1SChristian Sigg if (auto recTy = mlir::dyn_cast<fir::RecordType>(eleTy)) 353a2e7af75SValentin Clement if (recTy.getNumLenParams() > 0) 354a2e7af75SValentin Clement TODO(loc, "creating unallocated fir.box of derived type with length " 355a2e7af75SValentin Clement "parameters"); 35694a11063SValentin Clement auto nullAddr = builder.createNullConstant(loc, baseAddrType); 357a2e7af75SValentin Clement mlir::Value shape; 358fac349a1SChristian Sigg if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(type)) { 359a2e7af75SValentin Clement auto zero = builder.createIntegerConstant(loc, builder.getIndexType(), 0); 360a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> extents(seqTy.getDimension(), zero); 361a2e7af75SValentin Clement shape = builder.createShape( 3629a417395SKazu Hirata loc, fir::ArrayBoxValue{nullAddr, extents, /*lbounds=*/std::nullopt}); 363a2e7af75SValentin Clement } 364a2e7af75SValentin Clement // Provide dummy length parameters if they are dynamic. If a length parameter 365a2e7af75SValentin Clement // is deferred. It is set to zero here and will be set on allocation. 366a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> lenParams; 367fac349a1SChristian Sigg if (auto charTy = mlir::dyn_cast<fir::CharacterType>(eleTy)) { 368a2e7af75SValentin Clement if (charTy.getLen() == fir::CharacterType::unknownLen()) { 369a2e7af75SValentin Clement if (!nonDeferredParams.empty()) { 370a2e7af75SValentin Clement lenParams.push_back(nonDeferredParams[0]); 371a2e7af75SValentin Clement } else { 372a2e7af75SValentin Clement auto zero = builder.createIntegerConstant( 373a2e7af75SValentin Clement loc, builder.getCharacterLengthType(), 0); 374a2e7af75SValentin Clement lenParams.push_back(zero); 375a2e7af75SValentin Clement } 376a2e7af75SValentin Clement } 377a2e7af75SValentin Clement } 378a2e7af75SValentin Clement mlir::Value emptySlice; 3794abbf995SjeanPerier auto embox = builder.create<fir::EmboxOp>( 3804abbf995SjeanPerier loc, baseBoxType, nullAddr, shape, emptySlice, lenParams, typeSourceBox); 381*bbdb1e40SValentin Clement (バレンタイン クレメン) if (allocator != 0) 382*bbdb1e40SValentin Clement (バレンタイン クレメン) embox.setAllocatorIdx(allocator); 3834abbf995SjeanPerier if (isAssumedRank) 3844abbf995SjeanPerier return builder.createConvert(loc, boxType, embox); 3854abbf995SjeanPerier return embox; 386a2e7af75SValentin Clement } 387a2e7af75SValentin Clement 3880b19ac83SValentin Clement fir::MutableBoxValue fir::factory::createTempMutableBox( 3890b19ac83SValentin Clement fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type type, 390658595d0SValentin Clement llvm::StringRef name, mlir::Value typeSourceBox, bool isPolymorphic) { 3910b19ac83SValentin Clement mlir::Type boxType; 392658595d0SValentin Clement if (typeSourceBox || isPolymorphic) 3930b19ac83SValentin Clement boxType = fir::ClassType::get(fir::HeapType::get(type)); 3940b19ac83SValentin Clement else 3950b19ac83SValentin Clement boxType = fir::BoxType::get(fir::HeapType::get(type)); 396a2e7af75SValentin Clement auto boxAddr = builder.createTemporary(loc, boxType, name); 397a2e7af75SValentin Clement auto box = 398a2e7af75SValentin Clement fir::MutableBoxValue(boxAddr, /*nonDeferredParams=*/mlir::ValueRange(), 399a2e7af75SValentin Clement /*mutableProperties=*/{}); 4000b19ac83SValentin Clement MutablePropertyWriter{builder, loc, box, typeSourceBox} 4010b19ac83SValentin Clement .setUnallocatedStatus(); 402a2e7af75SValentin Clement return box; 403a2e7af75SValentin Clement } 404a2e7af75SValentin Clement 405a2e7af75SValentin Clement /// Helper to decide if a MutableBoxValue must be read to a BoxValue or 406a2e7af75SValentin Clement /// can be read to a reified box value. 407a2e7af75SValentin Clement static bool readToBoxValue(const fir::MutableBoxValue &box, 408a2e7af75SValentin Clement bool mayBePolymorphic) { 409a2e7af75SValentin Clement // If this is described by a set of local variables, the value 410a2e7af75SValentin Clement // should not be tracked as a fir.box. 411a2e7af75SValentin Clement if (box.isDescribedByVariables()) 412a2e7af75SValentin Clement return false; 413a2e7af75SValentin Clement // Polymorphism might be a source of discontiguity, even on allocatables. 414a2e7af75SValentin Clement // Track value as fir.box 415a2e7af75SValentin Clement if ((box.isDerived() && mayBePolymorphic) || box.isUnlimitedPolymorphic()) 416a2e7af75SValentin Clement return true; 417d99cf1b9SjeanPerier if (box.hasAssumedRank()) 418d99cf1b9SjeanPerier return true; 419a2e7af75SValentin Clement // Intrinsic allocatables are contiguous, no need to track the value by 420a2e7af75SValentin Clement // fir.box. 421a2e7af75SValentin Clement if (box.isAllocatable() || box.rank() == 0) 422a2e7af75SValentin Clement return false; 423a2e7af75SValentin Clement // Pointers are known to be contiguous at compile time iff they have the 424a2e7af75SValentin Clement // CONTIGUOUS attribute. 425a2e7af75SValentin Clement return !fir::valueHasFirAttribute(box.getAddr(), 426a2e7af75SValentin Clement fir::getContiguousAttrName()); 427a2e7af75SValentin Clement } 428a2e7af75SValentin Clement 429a2e7af75SValentin Clement fir::ExtendedValue 430a2e7af75SValentin Clement fir::factory::genMutableBoxRead(fir::FirOpBuilder &builder, mlir::Location loc, 431a2e7af75SValentin Clement const fir::MutableBoxValue &box, 43267402fe5SjeanPerier bool mayBePolymorphic, 43367402fe5SjeanPerier bool preserveLowerBounds) { 434a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> lbounds; 435a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> extents; 436a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> lengths; 437a2e7af75SValentin Clement if (readToBoxValue(box, mayBePolymorphic)) { 438a2e7af75SValentin Clement auto reader = MutablePropertyReader(builder, loc, box); 439d99cf1b9SjeanPerier if (preserveLowerBounds && !box.hasAssumedRank()) 440a2e7af75SValentin Clement reader.getLowerBounds(lbounds); 441a2e7af75SValentin Clement return fir::BoxValue{reader.getIrBox(), lbounds, 442a2e7af75SValentin Clement box.nonDeferredLenParams()}; 443a2e7af75SValentin Clement } 444a2e7af75SValentin Clement // Contiguous intrinsic type entity: all the data can be extracted from the 445a2e7af75SValentin Clement // fir.box. 446a2e7af75SValentin Clement auto addr = 447a2e7af75SValentin Clement MutablePropertyReader(builder, loc, box).read(lbounds, extents, lengths); 44867402fe5SjeanPerier if (!preserveLowerBounds) 44967402fe5SjeanPerier lbounds.clear(); 450a2e7af75SValentin Clement auto rank = box.rank(); 451a2e7af75SValentin Clement if (box.isCharacter()) { 452a2e7af75SValentin Clement auto len = lengths.empty() ? mlir::Value{} : lengths[0]; 453a2e7af75SValentin Clement if (rank) 454a2e7af75SValentin Clement return fir::CharArrayBoxValue{addr, len, extents, lbounds}; 455a2e7af75SValentin Clement return fir::CharBoxValue{addr, len}; 456a2e7af75SValentin Clement } 4579f1bb307SValentin Clement mlir::Value sourceBox; 45821b82573SValentin Clement if (box.isPolymorphic()) 4599f1bb307SValentin Clement sourceBox = builder.create<fir::LoadOp>(loc, box.getAddr()); 4609f1bb307SValentin Clement if (rank) 4619f1bb307SValentin Clement return fir::ArrayBoxValue{addr, extents, lbounds, sourceBox}; 4629f1bb307SValentin Clement if (box.isPolymorphic()) 4639f1bb307SValentin Clement return fir::PolymorphicValue(addr, sourceBox); 464a2e7af75SValentin Clement return addr; 465a2e7af75SValentin Clement } 466a2e7af75SValentin Clement 467a2e7af75SValentin Clement mlir::Value 468a2e7af75SValentin Clement fir::factory::genIsAllocatedOrAssociatedTest(fir::FirOpBuilder &builder, 469a2e7af75SValentin Clement mlir::Location loc, 470a2e7af75SValentin Clement const fir::MutableBoxValue &box) { 471a2e7af75SValentin Clement auto addr = MutablePropertyReader(builder, loc, box).readBaseAddress(); 47270ade047Svdonaldson return builder.genIsNotNullAddr(loc, addr); 473a2e7af75SValentin Clement } 474a2e7af75SValentin Clement 475b2bf995cSValentin Clement mlir::Value fir::factory::genIsNotAllocatedOrAssociatedTest( 476b2bf995cSValentin Clement fir::FirOpBuilder &builder, mlir::Location loc, 477b2bf995cSValentin Clement const fir::MutableBoxValue &box) { 478b2bf995cSValentin Clement auto addr = MutablePropertyReader(builder, loc, box).readBaseAddress(); 479b2bf995cSValentin Clement return builder.genIsNullAddr(loc, addr); 480b2bf995cSValentin Clement } 481b2bf995cSValentin Clement 4822cb31fe8SjeanPerier /// Call freemem. This does not check that the 483a2e7af75SValentin Clement /// address was allocated. 4842cb31fe8SjeanPerier static void genFreemem(fir::FirOpBuilder &builder, mlir::Location loc, 485a2e7af75SValentin Clement mlir::Value addr) { 486a2e7af75SValentin Clement // A heap (ALLOCATABLE) object may have been converted to a ptr (POINTER), 487a2e7af75SValentin Clement // so make sure the heap type is restored before deallocation. 488a2e7af75SValentin Clement auto cast = builder.createConvert( 489a2e7af75SValentin Clement loc, fir::HeapType::get(fir::dyn_cast_ptrEleTy(addr.getType())), addr); 490a2e7af75SValentin Clement builder.create<fir::FreeMemOp>(loc, cast); 491a2e7af75SValentin Clement } 492a2e7af75SValentin Clement 4932cb31fe8SjeanPerier void fir::factory::genFreememIfAllocated(fir::FirOpBuilder &builder, 494a2e7af75SValentin Clement mlir::Location loc, 495a2e7af75SValentin Clement const fir::MutableBoxValue &box) { 496a2e7af75SValentin Clement auto addr = MutablePropertyReader(builder, loc, box).readBaseAddress(); 49770ade047Svdonaldson auto isAllocated = builder.genIsNotNullAddr(loc, addr); 498a2e7af75SValentin Clement auto ifOp = builder.create<fir::IfOp>(loc, isAllocated, 499a2e7af75SValentin Clement /*withElseRegion=*/false); 500a2e7af75SValentin Clement auto insPt = builder.saveInsertionPoint(); 501149ad3d5SShraiysh Vaishay builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); 5022cb31fe8SjeanPerier ::genFreemem(builder, loc, addr); 503a2e7af75SValentin Clement builder.restoreInsertionPoint(insPt); 504a2e7af75SValentin Clement } 505a2e7af75SValentin Clement 506a2e7af75SValentin Clement //===----------------------------------------------------------------------===// 507a2e7af75SValentin Clement // MutableBoxValue writing interface implementation 508a2e7af75SValentin Clement //===----------------------------------------------------------------------===// 509a2e7af75SValentin Clement 510a2e7af75SValentin Clement void fir::factory::associateMutableBox(fir::FirOpBuilder &builder, 511a2e7af75SValentin Clement mlir::Location loc, 512a2e7af75SValentin Clement const fir::MutableBoxValue &box, 513a2e7af75SValentin Clement const fir::ExtendedValue &source, 514a2e7af75SValentin Clement mlir::ValueRange lbounds) { 515a2e7af75SValentin Clement MutablePropertyWriter writer(builder, loc, box); 516a2e7af75SValentin Clement source.match( 517ea1e767aSValentin Clement [&](const fir::PolymorphicValue &p) { 5189f1bb307SValentin Clement mlir::Value sourceBox; 519880b37f1SValentin Clement if (auto polyBox = source.getBoxOf<fir::PolymorphicValue>()) 5209f1bb307SValentin Clement sourceBox = polyBox->getSourceBox(); 5219a417395SKazu Hirata writer.updateMutableBox(p.getAddr(), /*lbounds=*/std::nullopt, 5229a417395SKazu Hirata /*extents=*/std::nullopt, 5239f1bb307SValentin Clement /*lengths=*/std::nullopt, sourceBox); 524ea1e767aSValentin Clement }, 525a2e7af75SValentin Clement [&](const fir::UnboxedValue &addr) { 5269a417395SKazu Hirata writer.updateMutableBox(addr, /*lbounds=*/std::nullopt, 5279a417395SKazu Hirata /*extents=*/std::nullopt, 5289a417395SKazu Hirata /*lengths=*/std::nullopt); 529a2e7af75SValentin Clement }, 530a2e7af75SValentin Clement [&](const fir::CharBoxValue &ch) { 5319a417395SKazu Hirata writer.updateMutableBox(ch.getAddr(), /*lbounds=*/std::nullopt, 5329a417395SKazu Hirata /*extents=*/std::nullopt, {ch.getLen()}); 533a2e7af75SValentin Clement }, 534a2e7af75SValentin Clement [&](const fir::ArrayBoxValue &arr) { 535a2e7af75SValentin Clement writer.updateMutableBox(arr.getAddr(), 536a2e7af75SValentin Clement lbounds.empty() ? arr.getLBounds() : lbounds, 5379a417395SKazu Hirata arr.getExtents(), /*lengths=*/std::nullopt); 538a2e7af75SValentin Clement }, 539a2e7af75SValentin Clement [&](const fir::CharArrayBoxValue &arr) { 540a2e7af75SValentin Clement writer.updateMutableBox(arr.getAddr(), 541a2e7af75SValentin Clement lbounds.empty() ? arr.getLBounds() : lbounds, 542a2e7af75SValentin Clement arr.getExtents(), {arr.getLen()}); 543a2e7af75SValentin Clement }, 544a2e7af75SValentin Clement [&](const fir::BoxValue &arr) { 545a2e7af75SValentin Clement // Rebox array fir.box to the pointer type and apply potential new lower 546a2e7af75SValentin Clement // bounds. 547a2e7af75SValentin Clement mlir::ValueRange newLbounds = lbounds.empty() 548a2e7af75SValentin Clement ? mlir::ValueRange{arr.getLBounds()} 549a2e7af75SValentin Clement : mlir::ValueRange{lbounds}; 550fa08e97dSjeanPerier if (box.hasAssumedRank()) { 551fa08e97dSjeanPerier assert(arr.hasAssumedRank() && 552fa08e97dSjeanPerier "expect both arr and box to be assumed-rank"); 553fa08e97dSjeanPerier mlir::Value reboxed = builder.create<fir::ReboxAssumedRankOp>( 554fa08e97dSjeanPerier loc, box.getBoxTy(), arr.getAddr(), 555fa08e97dSjeanPerier fir::LowerBoundModifierAttribute::Preserve); 556fa08e97dSjeanPerier writer.updateWithIrBox(reboxed); 557fa08e97dSjeanPerier } else if (box.isDescribedByVariables()) { 558a2e7af75SValentin Clement // LHS is a contiguous pointer described by local variables. Open RHS 559a2e7af75SValentin Clement // fir.box to update the LHS. 560a2e7af75SValentin Clement auto rawAddr = builder.create<fir::BoxAddrOp>(loc, arr.getMemTy(), 561a2e7af75SValentin Clement arr.getAddr()); 5621bffc753SEric Schweitz auto extents = fir::factory::getExtents(loc, builder, source); 563a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> lenParams; 564a2e7af75SValentin Clement if (arr.isCharacter()) { 565a2e7af75SValentin Clement lenParams.emplace_back( 566a2e7af75SValentin Clement fir::factory::readCharLen(builder, loc, source)); 5671bffc753SEric Schweitz } else if (arr.isDerivedWithLenParameters()) { 568a2e7af75SValentin Clement TODO(loc, "pointer assignment to derived with length parameters"); 569a2e7af75SValentin Clement } 570a2e7af75SValentin Clement writer.updateMutableBox(rawAddr, newLbounds, extents, lenParams); 571a2e7af75SValentin Clement } else { 572a2e7af75SValentin Clement mlir::Value shift; 573a2e7af75SValentin Clement if (!newLbounds.empty()) { 574a2e7af75SValentin Clement auto shiftType = 575a2e7af75SValentin Clement fir::ShiftType::get(builder.getContext(), newLbounds.size()); 576a2e7af75SValentin Clement shift = builder.create<fir::ShiftOp>(loc, shiftType, newLbounds); 577a2e7af75SValentin Clement } 578a2e7af75SValentin Clement auto reboxed = 579a2e7af75SValentin Clement builder.create<fir::ReboxOp>(loc, box.getBoxTy(), arr.getAddr(), 580a2e7af75SValentin Clement shift, /*slice=*/mlir::Value()); 581a2e7af75SValentin Clement writer.updateWithIrBox(reboxed); 582a2e7af75SValentin Clement } 583a2e7af75SValentin Clement }, 584a2e7af75SValentin Clement [&](const fir::MutableBoxValue &) { 585a2e7af75SValentin Clement // No point implementing this, if right-hand side is a 586a2e7af75SValentin Clement // pointer/allocatable, the related MutableBoxValue has been read into 587a2e7af75SValentin Clement // another ExtendedValue category. 588a2e7af75SValentin Clement fir::emitFatalError(loc, 589a2e7af75SValentin Clement "Cannot write MutableBox to another MutableBox"); 590a2e7af75SValentin Clement }, 591a2e7af75SValentin Clement [&](const fir::ProcBoxValue &) { 592331145e6SValentin Clement TODO(loc, "procedure pointer assignment"); 593a2e7af75SValentin Clement }); 594a2e7af75SValentin Clement } 595a2e7af75SValentin Clement 596a2e7af75SValentin Clement void fir::factory::associateMutableBoxWithRemap( 597a2e7af75SValentin Clement fir::FirOpBuilder &builder, mlir::Location loc, 598a2e7af75SValentin Clement const fir::MutableBoxValue &box, const fir::ExtendedValue &source, 599a2e7af75SValentin Clement mlir::ValueRange lbounds, mlir::ValueRange ubounds) { 600a2e7af75SValentin Clement // Compute new extents 601a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> extents; 602a2e7af75SValentin Clement auto idxTy = builder.getIndexType(); 603a2e7af75SValentin Clement if (!lbounds.empty()) { 604a2e7af75SValentin Clement auto one = builder.createIntegerConstant(loc, idxTy, 1); 605a2e7af75SValentin Clement for (auto [lb, ub] : llvm::zip(lbounds, ubounds)) { 606a2e7af75SValentin Clement auto lbi = builder.createConvert(loc, idxTy, lb); 607a2e7af75SValentin Clement auto ubi = builder.createConvert(loc, idxTy, ub); 608092601d4SAndrzej Warzynski auto diff = builder.create<mlir::arith::SubIOp>(loc, idxTy, ubi, lbi); 609a2e7af75SValentin Clement extents.emplace_back( 610092601d4SAndrzej Warzynski builder.create<mlir::arith::AddIOp>(loc, idxTy, diff, one)); 611a2e7af75SValentin Clement } 612a2e7af75SValentin Clement } else { 613a2e7af75SValentin Clement // lbounds are default. Upper bounds and extents are the same. 614a2e7af75SValentin Clement for (auto ub : ubounds) { 615a2e7af75SValentin Clement auto cast = builder.createConvert(loc, idxTy, ub); 616a2e7af75SValentin Clement extents.emplace_back(cast); 617a2e7af75SValentin Clement } 618a2e7af75SValentin Clement } 619a2e7af75SValentin Clement const auto newRank = extents.size(); 620a2e7af75SValentin Clement auto cast = [&](mlir::Value addr) -> mlir::Value { 621a2e7af75SValentin Clement // Cast base addr to new sequence type. 622a2e7af75SValentin Clement auto ty = fir::dyn_cast_ptrEleTy(addr.getType()); 623fac349a1SChristian Sigg if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty)) { 624a2e7af75SValentin Clement fir::SequenceType::Shape shape(newRank, 625a2e7af75SValentin Clement fir::SequenceType::getUnknownExtent()); 626a2e7af75SValentin Clement ty = fir::SequenceType::get(shape, seqTy.getEleTy()); 627a2e7af75SValentin Clement } 628a2e7af75SValentin Clement return builder.createConvert(loc, builder.getRefType(ty), addr); 629a2e7af75SValentin Clement }; 630a2e7af75SValentin Clement MutablePropertyWriter writer(builder, loc, box); 631a2e7af75SValentin Clement source.match( 632ea1e767aSValentin Clement [&](const fir::PolymorphicValue &p) { 633ea1e767aSValentin Clement writer.updateMutableBox(cast(p.getAddr()), lbounds, extents, 6349a417395SKazu Hirata /*lengths=*/std::nullopt); 635ea1e767aSValentin Clement }, 636a2e7af75SValentin Clement [&](const fir::UnboxedValue &addr) { 637a2e7af75SValentin Clement writer.updateMutableBox(cast(addr), lbounds, extents, 6389a417395SKazu Hirata /*lengths=*/std::nullopt); 639a2e7af75SValentin Clement }, 640a2e7af75SValentin Clement [&](const fir::CharBoxValue &ch) { 641a2e7af75SValentin Clement writer.updateMutableBox(cast(ch.getAddr()), lbounds, extents, 642a2e7af75SValentin Clement {ch.getLen()}); 643a2e7af75SValentin Clement }, 644a2e7af75SValentin Clement [&](const fir::ArrayBoxValue &arr) { 645a2e7af75SValentin Clement writer.updateMutableBox(cast(arr.getAddr()), lbounds, extents, 6469a417395SKazu Hirata /*lengths=*/std::nullopt); 647a2e7af75SValentin Clement }, 648a2e7af75SValentin Clement [&](const fir::CharArrayBoxValue &arr) { 649a2e7af75SValentin Clement writer.updateMutableBox(cast(arr.getAddr()), lbounds, extents, 650a2e7af75SValentin Clement {arr.getLen()}); 651a2e7af75SValentin Clement }, 652a2e7af75SValentin Clement [&](const fir::BoxValue &arr) { 653a2e7af75SValentin Clement // Rebox right-hand side fir.box with a new shape and type. 654a2e7af75SValentin Clement if (box.isDescribedByVariables()) { 655a2e7af75SValentin Clement // LHS is a contiguous pointer described by local variables. Open RHS 656a2e7af75SValentin Clement // fir.box to update the LHS. 657a2e7af75SValentin Clement auto rawAddr = builder.create<fir::BoxAddrOp>(loc, arr.getMemTy(), 658a2e7af75SValentin Clement arr.getAddr()); 659a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> lenParams; 660a2e7af75SValentin Clement if (arr.isCharacter()) { 661a2e7af75SValentin Clement lenParams.emplace_back( 662a2e7af75SValentin Clement fir::factory::readCharLen(builder, loc, source)); 6631bffc753SEric Schweitz } else if (arr.isDerivedWithLenParameters()) { 664a2e7af75SValentin Clement TODO(loc, "pointer assignment to derived with length parameters"); 665a2e7af75SValentin Clement } 666a2e7af75SValentin Clement writer.updateMutableBox(rawAddr, lbounds, extents, lenParams); 667a2e7af75SValentin Clement } else { 668a2e7af75SValentin Clement auto shapeType = 669a2e7af75SValentin Clement fir::ShapeShiftType::get(builder.getContext(), extents.size()); 670a2e7af75SValentin Clement llvm::SmallVector<mlir::Value> shapeArgs; 671a2e7af75SValentin Clement auto idxTy = builder.getIndexType(); 672a2e7af75SValentin Clement for (auto [lbnd, ext] : llvm::zip(lbounds, extents)) { 673a2e7af75SValentin Clement auto lb = builder.createConvert(loc, idxTy, lbnd); 674a2e7af75SValentin Clement shapeArgs.push_back(lb); 675a2e7af75SValentin Clement shapeArgs.push_back(ext); 676a2e7af75SValentin Clement } 677a2e7af75SValentin Clement auto shape = 678a2e7af75SValentin Clement builder.create<fir::ShapeShiftOp>(loc, shapeType, shapeArgs); 679a2e7af75SValentin Clement auto reboxed = 680a2e7af75SValentin Clement builder.create<fir::ReboxOp>(loc, box.getBoxTy(), arr.getAddr(), 681a2e7af75SValentin Clement shape, /*slice=*/mlir::Value()); 682a2e7af75SValentin Clement writer.updateWithIrBox(reboxed); 683a2e7af75SValentin Clement } 684a2e7af75SValentin Clement }, 685a2e7af75SValentin Clement [&](const fir::MutableBoxValue &) { 686a2e7af75SValentin Clement // No point implementing this, if right-hand side is a pointer or 687a2e7af75SValentin Clement // allocatable, the related MutableBoxValue has already been read into 688a2e7af75SValentin Clement // another ExtendedValue category. 689a2e7af75SValentin Clement fir::emitFatalError(loc, 690a2e7af75SValentin Clement "Cannot write MutableBox to another MutableBox"); 691a2e7af75SValentin Clement }, 692a2e7af75SValentin Clement [&](const fir::ProcBoxValue &) { 693331145e6SValentin Clement TODO(loc, "procedure pointer assignment"); 694a2e7af75SValentin Clement }); 695a2e7af75SValentin Clement } 696a2e7af75SValentin Clement 697a2e7af75SValentin Clement void fir::factory::disassociateMutableBox(fir::FirOpBuilder &builder, 698a2e7af75SValentin Clement mlir::Location loc, 69990e9fcbbSValentin Clement const fir::MutableBoxValue &box, 700*bbdb1e40SValentin Clement (バレンタイン クレメン) bool polymorphicSetType, 701*bbdb1e40SValentin Clement (バレンタイン クレメン) unsigned allocator) { 70290e9fcbbSValentin Clement if (box.isPolymorphic() && polymorphicSetType) { 70390e9fcbbSValentin Clement // 7.3.2.3 point 7. The dynamic type of a disassociated pointer is the 70490e9fcbbSValentin Clement // same as its declared type. 705fac349a1SChristian Sigg auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(box.getBoxTy()); 706f81d5e54SjeanPerier auto eleTy = fir::unwrapPassByRefType(boxTy.getEleTy()); 707ef063270SValentin Clement mlir::Type derivedType = fir::getDerivedType(eleTy); 708fac349a1SChristian Sigg if (auto recTy = mlir::dyn_cast<fir::RecordType>(derivedType)) { 70990e9fcbbSValentin Clement fir::runtime::genNullifyDerivedType(builder, loc, box.getAddr(), recTy, 71090e9fcbbSValentin Clement box.rank()); 71190e9fcbbSValentin Clement return; 71290e9fcbbSValentin Clement } 71304a920b7SJean Perier } 714*bbdb1e40SValentin Clement (バレンタイン クレメン) MutablePropertyWriter{builder, loc, box, {}, allocator} 715*bbdb1e40SValentin Clement (バレンタイン クレメン) .setUnallocatedStatus(); 716a2e7af75SValentin Clement } 717a2e7af75SValentin Clement 7182a59ead1SValentin Clement static llvm::SmallVector<mlir::Value> 7192a59ead1SValentin Clement getNewLengths(fir::FirOpBuilder &builder, mlir::Location loc, 7202a59ead1SValentin Clement const fir::MutableBoxValue &box, mlir::ValueRange lenParams) { 7212a59ead1SValentin Clement llvm::SmallVector<mlir::Value> lengths; 7222a59ead1SValentin Clement auto idxTy = builder.getIndexType(); 723fac349a1SChristian Sigg if (auto charTy = mlir::dyn_cast<fir::CharacterType>(box.getEleTy())) { 7242a59ead1SValentin Clement if (charTy.getLen() == fir::CharacterType::unknownLen()) { 725c8a9afe7SJean Perier if (box.hasNonDeferredLenParams()) { 7262a59ead1SValentin Clement lengths.emplace_back( 7272a59ead1SValentin Clement builder.createConvert(loc, idxTy, box.nonDeferredLenParams()[0])); 728c8a9afe7SJean Perier } else if (!lenParams.empty()) { 729c8a9afe7SJean Perier mlir::Value len = 730c8a9afe7SJean Perier fir::factory::genMaxWithZero(builder, loc, lenParams[0]); 731c8a9afe7SJean Perier lengths.emplace_back(builder.createConvert(loc, idxTy, len)); 732c8a9afe7SJean Perier } else { 7332a59ead1SValentin Clement fir::emitFatalError( 7342a59ead1SValentin Clement loc, "could not deduce character lengths in character allocation"); 7352a59ead1SValentin Clement } 7362a59ead1SValentin Clement } 737c8a9afe7SJean Perier } 7382a59ead1SValentin Clement return lengths; 7392a59ead1SValentin Clement } 7402a59ead1SValentin Clement 7412a59ead1SValentin Clement static mlir::Value allocateAndInitNewStorage(fir::FirOpBuilder &builder, 7422a59ead1SValentin Clement mlir::Location loc, 7432a59ead1SValentin Clement const fir::MutableBoxValue &box, 7442a59ead1SValentin Clement mlir::ValueRange extents, 7452a59ead1SValentin Clement mlir::ValueRange lenParams, 7462a59ead1SValentin Clement llvm::StringRef allocName) { 7472a59ead1SValentin Clement auto lengths = getNewLengths(builder, loc, box, lenParams); 7482a59ead1SValentin Clement auto newStorage = builder.create<fir::AllocMemOp>( 7492a59ead1SValentin Clement loc, box.getBaseTy(), allocName, lengths, extents); 750fac349a1SChristian Sigg if (mlir::isa<fir::RecordType>(box.getEleTy())) { 7512a59ead1SValentin Clement // TODO: skip runtime initialization if this is not required. Currently, 7522a59ead1SValentin Clement // there is no way to know here if a derived type needs it or not. But the 7532a59ead1SValentin Clement // information is available at compile time and could be reflected here 7542a59ead1SValentin Clement // somehow. 7552a59ead1SValentin Clement mlir::Value irBox = createNewFirBox(builder, loc, box, newStorage, 7569a417395SKazu Hirata std::nullopt, extents, lengths); 7572a59ead1SValentin Clement fir::runtime::genDerivedTypeInitialize(builder, loc, irBox); 7582a59ead1SValentin Clement } 7592a59ead1SValentin Clement return newStorage; 7602a59ead1SValentin Clement } 7612a59ead1SValentin Clement 762cc14bf22STom Eccles void fir::factory::genInlinedAllocation( 763cc14bf22STom Eccles fir::FirOpBuilder &builder, mlir::Location loc, 764cc14bf22STom Eccles const fir::MutableBoxValue &box, mlir::ValueRange lbounds, 765cc14bf22STom Eccles mlir::ValueRange extents, mlir::ValueRange lenParams, 766cc14bf22STom Eccles llvm::StringRef allocName, bool mustBeHeap) { 767fe252f8eSValentin Clement auto lengths = getNewLengths(builder, loc, box, lenParams); 768c8a9afe7SJean Perier llvm::SmallVector<mlir::Value> safeExtents; 769c8a9afe7SJean Perier for (mlir::Value extent : extents) 770c8a9afe7SJean Perier safeExtents.push_back(fir::factory::genMaxWithZero(builder, loc, extent)); 771fe252f8eSValentin Clement auto heap = builder.create<fir::AllocMemOp>(loc, box.getBaseTy(), allocName, 772c8a9afe7SJean Perier lengths, safeExtents); 773c8a9afe7SJean Perier MutablePropertyWriter{builder, loc, box}.updateMutableBox( 774c8a9afe7SJean Perier heap, lbounds, safeExtents, lengths); 775fac349a1SChristian Sigg if (mlir::isa<fir::RecordType>(box.getEleTy())) { 776fe252f8eSValentin Clement // TODO: skip runtime initialization if this is not required. Currently, 777fe252f8eSValentin Clement // there is no way to know here if a derived type needs it or not. But the 778fe252f8eSValentin Clement // information is available at compile time and could be reflected here 779fe252f8eSValentin Clement // somehow. 780fe252f8eSValentin Clement mlir::Value irBox = fir::factory::getMutableIRBox(builder, loc, box); 781fe252f8eSValentin Clement fir::runtime::genDerivedTypeInitialize(builder, loc, irBox); 782fe252f8eSValentin Clement } 783cc14bf22STom Eccles 784cc14bf22STom Eccles heap->setAttr(fir::MustBeHeapAttr::getAttrName(), 785cc14bf22STom Eccles fir::MustBeHeapAttr::get(builder.getContext(), mustBeHeap)); 786a2e7af75SValentin Clement } 787a2e7af75SValentin Clement 7882cb31fe8SjeanPerier mlir::Value fir::factory::genFreemem(fir::FirOpBuilder &builder, 789a2e7af75SValentin Clement mlir::Location loc, 790a2e7af75SValentin Clement const fir::MutableBoxValue &box) { 791a2e7af75SValentin Clement auto addr = MutablePropertyReader(builder, loc, box).readBaseAddress(); 7922cb31fe8SjeanPerier ::genFreemem(builder, loc, addr); 793a2e7af75SValentin Clement MutablePropertyWriter{builder, loc, box}.setUnallocatedStatus(); 7942e1982f3SValentin Clement return addr; 795a2e7af75SValentin Clement } 796a2e7af75SValentin Clement 79773026a4fSSlava Zakharin fir::factory::MutableBoxReallocation fir::factory::genReallocIfNeeded( 79873026a4fSSlava Zakharin fir::FirOpBuilder &builder, mlir::Location loc, 79973026a4fSSlava Zakharin const fir::MutableBoxValue &box, mlir::ValueRange shape, 80073026a4fSSlava Zakharin mlir::ValueRange lengthParams, 80173026a4fSSlava Zakharin fir::factory::ReallocStorageHandlerFunc storageHandler) { 802a2e7af75SValentin Clement // Implement 10.2.1.3 point 3 logic when lhs is an array. 803a2e7af75SValentin Clement auto reader = MutablePropertyReader(builder, loc, box); 804a2e7af75SValentin Clement auto addr = reader.readBaseAddress(); 8052a59ead1SValentin Clement auto i1Type = builder.getI1Type(); 8062a59ead1SValentin Clement auto addrType = addr.getType(); 80770ade047Svdonaldson auto isAllocated = builder.genIsNotNullAddr(loc, addr); 80873026a4fSSlava Zakharin auto getExtValForStorage = [&](mlir::Value newAddr) -> fir::ExtendedValue { 80973026a4fSSlava Zakharin mlir::SmallVector<mlir::Value> extents; 81073026a4fSSlava Zakharin if (box.hasRank()) { 81173026a4fSSlava Zakharin if (shape.empty()) 81273026a4fSSlava Zakharin extents = reader.readShape(); 81373026a4fSSlava Zakharin else 81473026a4fSSlava Zakharin extents.append(shape.begin(), shape.end()); 81573026a4fSSlava Zakharin } 81673026a4fSSlava Zakharin if (box.isCharacter()) { 81773026a4fSSlava Zakharin auto len = box.hasNonDeferredLenParams() ? reader.readCharacterLength() 81873026a4fSSlava Zakharin : lengthParams[0]; 81973026a4fSSlava Zakharin if (box.hasRank()) 82073026a4fSSlava Zakharin return fir::CharArrayBoxValue{newAddr, len, extents}; 82173026a4fSSlava Zakharin return fir::CharBoxValue{newAddr, len}; 82273026a4fSSlava Zakharin } 82373026a4fSSlava Zakharin if (box.isDerivedWithLenParameters()) 82473026a4fSSlava Zakharin TODO(loc, "reallocation of derived type entities with length parameters"); 82573026a4fSSlava Zakharin if (box.hasRank()) 82673026a4fSSlava Zakharin return fir::ArrayBoxValue{newAddr, extents}; 82773026a4fSSlava Zakharin return newAddr; 82873026a4fSSlava Zakharin }; 8292a59ead1SValentin Clement auto ifOp = 8302a59ead1SValentin Clement builder 8312a59ead1SValentin Clement .genIfOp(loc, {i1Type, addrType}, isAllocated, 8322a59ead1SValentin Clement /*withElseRegion=*/true) 833a2e7af75SValentin Clement .genThen([&]() { 8342a59ead1SValentin Clement // The box is allocated. Check if it must be reallocated and 8352a59ead1SValentin Clement // reallocate. 8362a59ead1SValentin Clement auto mustReallocate = builder.createBool(loc, false); 8372a59ead1SValentin Clement auto compareProperty = [&](mlir::Value previous, 8382a59ead1SValentin Clement mlir::Value required) { 839a2e7af75SValentin Clement auto castPrevious = 840a2e7af75SValentin Clement builder.createConvert(loc, required.getType(), previous); 8412a59ead1SValentin Clement auto cmp = builder.create<mlir::arith::CmpIOp>( 8422a59ead1SValentin Clement loc, mlir::arith::CmpIPredicate::ne, castPrevious, required); 843dec8af70SRiver Riddle mustReallocate = builder.create<mlir::arith::SelectOp>( 844dec8af70SRiver Riddle loc, cmp, cmp, mustReallocate); 845a2e7af75SValentin Clement }; 8462a59ead1SValentin Clement llvm::SmallVector<mlir::Value> previousExtents = reader.readShape(); 847a2e7af75SValentin Clement if (!shape.empty()) 848a2e7af75SValentin Clement for (auto [previousExtent, requested] : 849a2e7af75SValentin Clement llvm::zip(previousExtents, shape)) 850a2e7af75SValentin Clement compareProperty(previousExtent, requested); 851a2e7af75SValentin Clement 852a2e7af75SValentin Clement if (box.isCharacter() && !box.hasNonDeferredLenParams()) { 853a2e7af75SValentin Clement // When the allocatable length is not deferred, it must not be 8542a59ead1SValentin Clement // reallocated in case of length mismatch, instead, 8552a59ead1SValentin Clement // padding/trimming will occur in later assignment to it. 856a2e7af75SValentin Clement assert(!lengthParams.empty() && 857a2e7af75SValentin Clement "must provide length parameters for character"); 858a2e7af75SValentin Clement compareProperty(reader.readCharacterLength(), lengthParams[0]); 8591bffc753SEric Schweitz } else if (box.isDerivedWithLenParameters()) { 8602a59ead1SValentin Clement TODO(loc, "automatic allocation of derived type allocatable with " 8612a59ead1SValentin Clement "length parameters"); 862a2e7af75SValentin Clement } 86374d5c3c0SPeter Steinfeld auto ifOp = builder 8642a59ead1SValentin Clement .genIfOp(loc, {addrType}, mustReallocate, 8652a59ead1SValentin Clement /*withElseRegion=*/true) 866a2e7af75SValentin Clement .genThen([&]() { 86774d5c3c0SPeter Steinfeld // If shape or length mismatch, allocate new 86874d5c3c0SPeter Steinfeld // storage. When rhs is a scalar, keep the 86974d5c3c0SPeter Steinfeld // previous shape 87074d5c3c0SPeter Steinfeld auto extents = 87174d5c3c0SPeter Steinfeld shape.empty() 8722a59ead1SValentin Clement ? mlir::ValueRange(previousExtents) 8732a59ead1SValentin Clement : shape; 8742a59ead1SValentin Clement auto heap = allocateAndInitNewStorage( 8752a59ead1SValentin Clement builder, loc, box, extents, lengthParams, 8762a59ead1SValentin Clement ".auto.alloc"); 87773026a4fSSlava Zakharin if (storageHandler) 87873026a4fSSlava Zakharin storageHandler(getExtValForStorage(heap)); 8792a59ead1SValentin Clement builder.create<fir::ResultOp>(loc, heap); 880a2e7af75SValentin Clement }) 88173026a4fSSlava Zakharin .genElse([&]() { 88273026a4fSSlava Zakharin if (storageHandler) 88373026a4fSSlava Zakharin storageHandler(getExtValForStorage(addr)); 88473026a4fSSlava Zakharin builder.create<fir::ResultOp>(loc, addr); 88573026a4fSSlava Zakharin }); 8862a59ead1SValentin Clement ifOp.end(); 8872a59ead1SValentin Clement auto newAddr = ifOp.getResults()[0]; 8882a59ead1SValentin Clement builder.create<fir::ResultOp>( 8892a59ead1SValentin Clement loc, mlir::ValueRange{mustReallocate, newAddr}); 890a2e7af75SValentin Clement }) 891a2e7af75SValentin Clement .genElse([&]() { 8922a59ead1SValentin Clement auto trueValue = builder.createBool(loc, true); 893a2e7af75SValentin Clement // The box is not yet allocated, simply allocate it. 894a2e7af75SValentin Clement if (shape.empty() && box.rank() != 0) { 8952a59ead1SValentin Clement // See 10.2.1.3 p3. 8962a59ead1SValentin Clement fir::runtime::genReportFatalUserError( 8972a59ead1SValentin Clement builder, loc, 8982a59ead1SValentin Clement "array left hand side must be allocated when the right hand " 8992a59ead1SValentin Clement "side is a scalar"); 9002a59ead1SValentin Clement builder.create<fir::ResultOp>(loc, 9012a59ead1SValentin Clement mlir::ValueRange{trueValue, addr}); 902a2e7af75SValentin Clement } else { 9032a59ead1SValentin Clement auto heap = allocateAndInitNewStorage( 9042a59ead1SValentin Clement builder, loc, box, shape, lengthParams, ".auto.alloc"); 90573026a4fSSlava Zakharin if (storageHandler) 90673026a4fSSlava Zakharin storageHandler(getExtValForStorage(heap)); 9072a59ead1SValentin Clement builder.create<fir::ResultOp>(loc, 9082a59ead1SValentin Clement mlir::ValueRange{trueValue, heap}); 909a2e7af75SValentin Clement } 9102a59ead1SValentin Clement }); 9112a59ead1SValentin Clement ifOp.end(); 9122a59ead1SValentin Clement auto wasReallocated = ifOp.getResults()[0]; 9132a59ead1SValentin Clement auto newAddr = ifOp.getResults()[1]; 9142a59ead1SValentin Clement // Create an ExtentedValue for the new storage. 91573026a4fSSlava Zakharin auto newValue = getExtValForStorage(newAddr); 9162a59ead1SValentin Clement return {newValue, addr, wasReallocated, isAllocated}; 9172a59ead1SValentin Clement } 9182a59ead1SValentin Clement 9192a59ead1SValentin Clement void fir::factory::finalizeRealloc(fir::FirOpBuilder &builder, 9202a59ead1SValentin Clement mlir::Location loc, 9212a59ead1SValentin Clement const fir::MutableBoxValue &box, 9222a59ead1SValentin Clement mlir::ValueRange lbounds, 9232a59ead1SValentin Clement bool takeLboundsIfRealloc, 9242a59ead1SValentin Clement const MutableBoxReallocation &realloc) { 9252a59ead1SValentin Clement builder.genIfThen(loc, realloc.wasReallocated) 9262a59ead1SValentin Clement .genThen([&]() { 9272a59ead1SValentin Clement auto reader = MutablePropertyReader(builder, loc, box); 9282a59ead1SValentin Clement llvm::SmallVector<mlir::Value> previousLbounds; 9292a59ead1SValentin Clement if (!takeLboundsIfRealloc && box.hasRank()) 9302a59ead1SValentin Clement reader.readShape(&previousLbounds); 9312a59ead1SValentin Clement auto lbs = 9322a59ead1SValentin Clement takeLboundsIfRealloc ? lbounds : mlir::ValueRange{previousLbounds}; 9332a59ead1SValentin Clement llvm::SmallVector<mlir::Value> lenParams; 9342a59ead1SValentin Clement if (box.isCharacter()) 9352a59ead1SValentin Clement lenParams.push_back(fir::getLen(realloc.newValue)); 9361bffc753SEric Schweitz if (box.isDerivedWithLenParameters()) 9372a59ead1SValentin Clement TODO(loc, 9382a59ead1SValentin Clement "reallocation of derived type entities with length parameters"); 9392a59ead1SValentin Clement auto lengths = getNewLengths(builder, loc, box, lenParams); 9402a59ead1SValentin Clement auto heap = fir::getBase(realloc.newValue); 9411bffc753SEric Schweitz auto extents = fir::factory::getExtents(loc, builder, realloc.newValue); 9422a59ead1SValentin Clement builder.genIfThen(loc, realloc.oldAddressWasAllocated) 9432cb31fe8SjeanPerier .genThen([&]() { ::genFreemem(builder, loc, realloc.oldAddress); }) 9442a59ead1SValentin Clement .end(); 9452a59ead1SValentin Clement MutablePropertyWriter{builder, loc, box}.updateMutableBox( 9462a59ead1SValentin Clement heap, lbs, extents, lengths); 947a2e7af75SValentin Clement }) 948a2e7af75SValentin Clement .end(); 949a2e7af75SValentin Clement } 950a2e7af75SValentin Clement 951a2e7af75SValentin Clement //===----------------------------------------------------------------------===// 952a2e7af75SValentin Clement // MutableBoxValue syncing implementation 953a2e7af75SValentin Clement //===----------------------------------------------------------------------===// 954a2e7af75SValentin Clement 955a2e7af75SValentin Clement /// Depending on the implementation, allocatable/pointer descriptor and the 956a2e7af75SValentin Clement /// MutableBoxValue need to be synced before and after calls passing the 957a2e7af75SValentin Clement /// descriptor. These calls will generate the syncing if needed or be no-op. 958a2e7af75SValentin Clement mlir::Value fir::factory::getMutableIRBox(fir::FirOpBuilder &builder, 959a2e7af75SValentin Clement mlir::Location loc, 960a2e7af75SValentin Clement const fir::MutableBoxValue &box) { 961a2e7af75SValentin Clement MutablePropertyWriter{builder, loc, box}.syncIRBoxFromMutableProperties(); 962a2e7af75SValentin Clement return box.getAddr(); 963a2e7af75SValentin Clement } 964a2e7af75SValentin Clement void fir::factory::syncMutableBoxFromIRBox(fir::FirOpBuilder &builder, 965a2e7af75SValentin Clement mlir::Location loc, 966a2e7af75SValentin Clement const fir::MutableBoxValue &box) { 967a2e7af75SValentin Clement MutablePropertyWriter{builder, loc, box}.syncMutablePropertiesFromIRBox(); 968a2e7af75SValentin Clement } 969498f706bSSlava Zakharin 970498f706bSSlava Zakharin mlir::Value fir::factory::genNullBoxStorage(fir::FirOpBuilder &builder, 971498f706bSSlava Zakharin mlir::Location loc, 972498f706bSSlava Zakharin mlir::Type boxTy) { 973498f706bSSlava Zakharin mlir::Value boxStorage = builder.createTemporary(loc, boxTy); 974498f706bSSlava Zakharin mlir::Value nullBox = fir::factory::createUnallocatedBox( 975498f706bSSlava Zakharin builder, loc, boxTy, /*nonDeferredParams=*/{}); 976498f706bSSlava Zakharin builder.create<fir::StoreOp>(loc, nullBox, boxStorage); 977498f706bSSlava Zakharin return boxStorage; 978498f706bSSlava Zakharin } 979