|
11 | 11 | #include "flang/Optimizer/Builder/Character.h" |
12 | 12 | #include "flang/Optimizer/Builder/Complex.h" |
13 | 13 | #include "flang/Optimizer/Builder/MutableBox.h" |
| 14 | +#include "flang/Optimizer/Builder/Runtime/Allocatable.h" |
14 | 15 | #include "flang/Optimizer/Builder/Runtime/Assign.h" |
15 | 16 | #include "flang/Optimizer/Builder/Runtime/Derived.h" |
16 | 17 | #include "flang/Optimizer/Builder/Todo.h" |
@@ -362,6 +363,72 @@ mlir::Value fir::FirOpBuilder::createHeapTemporary( |
362 | 363 | name, dynamicLength, dynamicShape, attrs); |
363 | 364 | } |
364 | 365 |
|
| 366 | +std::pair<mlir::Value, bool> fir::FirOpBuilder::createArrayTemp( |
| 367 | + mlir::Location loc, fir::SequenceType arrayType, mlir::Value shape, |
| 368 | + llvm::ArrayRef<mlir::Value> extents, llvm::ArrayRef<mlir::Value> typeParams, |
| 369 | + const std::function<decltype(FirOpBuilder::genTempDeclareOp)> &genDeclare, |
| 370 | + mlir::Value polymorphicMold, bool useStack, llvm::StringRef tmpName) { |
| 371 | + if (polymorphicMold) { |
| 372 | + // Create *allocated* polymorphic temporary using the dynamic type |
| 373 | + // of the mold and the provided shape/extents. The created temporary |
| 374 | + // array will be written element per element, that is why it has to be |
| 375 | + // allocated. |
| 376 | + mlir::Type boxHeapType = fir::HeapType::get(arrayType); |
| 377 | + mlir::Value alloc = fir::factory::genNullBoxStorage( |
| 378 | + *this, loc, fir::ClassType::get(boxHeapType)); |
| 379 | + fir::FortranVariableFlagsAttr declAttrs = |
| 380 | + fir::FortranVariableFlagsAttr::get( |
| 381 | + getContext(), fir::FortranVariableFlagsEnum::allocatable); |
| 382 | + |
| 383 | + mlir::Value base = genDeclare(*this, loc, alloc, tmpName, |
| 384 | + /*shape=*/nullptr, typeParams, declAttrs); |
| 385 | + |
| 386 | + int rank = extents.size(); |
| 387 | + fir::runtime::genAllocatableApplyMold(*this, loc, alloc, polymorphicMold, |
| 388 | + rank); |
| 389 | + if (!extents.empty()) { |
| 390 | + mlir::Type idxTy = getIndexType(); |
| 391 | + mlir::Value one = createIntegerConstant(loc, idxTy, 1); |
| 392 | + unsigned dim = 0; |
| 393 | + for (mlir::Value extent : extents) { |
| 394 | + mlir::Value dimIndex = createIntegerConstant(loc, idxTy, dim++); |
| 395 | + fir::runtime::genAllocatableSetBounds(*this, loc, alloc, dimIndex, one, |
| 396 | + extent); |
| 397 | + } |
| 398 | + } |
| 399 | + if (!typeParams.empty()) { |
| 400 | + // We should call AllocatableSetDerivedLength() here. |
| 401 | + // TODO: does the mold provide the length parameters or |
| 402 | + // the operation itself or should they be in sync? |
| 403 | + TODO(loc, "polymorphic type with length parameters"); |
| 404 | + } |
| 405 | + fir::runtime::genAllocatableAllocate(*this, loc, alloc); |
| 406 | + |
| 407 | + return {base, /*isHeapAllocation=*/true}; |
| 408 | + } |
| 409 | + mlir::Value allocmem; |
| 410 | + if (useStack) |
| 411 | + allocmem = createTemporary(loc, arrayType, tmpName, extents, typeParams); |
| 412 | + else |
| 413 | + allocmem = |
| 414 | + createHeapTemporary(loc, arrayType, tmpName, extents, typeParams); |
| 415 | + mlir::Value base = genDeclare(*this, loc, allocmem, tmpName, shape, |
| 416 | + typeParams, fir::FortranVariableFlagsAttr{}); |
| 417 | + return {base, !useStack}; |
| 418 | +} |
| 419 | + |
| 420 | +mlir::Value fir::FirOpBuilder::genTempDeclareOp( |
| 421 | + fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value memref, |
| 422 | + llvm::StringRef name, mlir::Value shape, |
| 423 | + llvm::ArrayRef<mlir::Value> typeParams, |
| 424 | + fir::FortranVariableFlagsAttr fortranAttrs) { |
| 425 | + auto nameAttr = mlir::StringAttr::get(builder.getContext(), name); |
| 426 | + return builder.create<fir::DeclareOp>(loc, memref.getType(), memref, shape, |
| 427 | + typeParams, |
| 428 | + /*dummy_scope=*/nullptr, nameAttr, |
| 429 | + fortranAttrs, cuf::DataAttributeAttr{}); |
| 430 | +} |
| 431 | + |
365 | 432 | mlir::Value fir::FirOpBuilder::genStackSave(mlir::Location loc) { |
366 | 433 | mlir::Type voidPtr = mlir::LLVM::LLVMPointerType::get( |
367 | 434 | getContext(), fir::factory::getAllocaAddressSpace(&getDataLayout())); |
@@ -1825,3 +1892,29 @@ llvm::SmallVector<mlir::Value> fir::factory::updateRuntimeExtentsForEmptyArrays( |
1825 | 1892 | } |
1826 | 1893 | return newExtents; |
1827 | 1894 | } |
| 1895 | + |
| 1896 | +void fir::factory::genDimInfoFromBox( |
| 1897 | + fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value box, |
| 1898 | + llvm::SmallVectorImpl<mlir::Value> *lbounds, |
| 1899 | + llvm::SmallVectorImpl<mlir::Value> *extents, |
| 1900 | + llvm::SmallVectorImpl<mlir::Value> *strides) { |
| 1901 | + auto boxType = mlir::dyn_cast<fir::BaseBoxType>(box.getType()); |
| 1902 | + assert(boxType && "must be a box"); |
| 1903 | + if (!lbounds && !extents && !strides) |
| 1904 | + return; |
| 1905 | + |
| 1906 | + unsigned rank = fir::getBoxRank(boxType); |
| 1907 | + assert(rank != 0 && "must be an array of known rank"); |
| 1908 | + mlir::Type idxTy = builder.getIndexType(); |
| 1909 | + for (unsigned i = 0; i < rank; ++i) { |
| 1910 | + mlir::Value dim = builder.createIntegerConstant(loc, idxTy, i); |
| 1911 | + auto dimInfo = |
| 1912 | + builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, box, dim); |
| 1913 | + if (lbounds) |
| 1914 | + lbounds->push_back(dimInfo.getLowerBound()); |
| 1915 | + if (extents) |
| 1916 | + extents->push_back(dimInfo.getExtent()); |
| 1917 | + if (strides) |
| 1918 | + strides->push_back(dimInfo.getByteStride()); |
| 1919 | + } |
| 1920 | +} |
0 commit comments