This operation will be used to declare named variables in HLFIR. See the added description in HLFIROpBase.td for more info about it. The motivation behind this operation is described in https://reviews.llvm.org/D137634. The FortranVariableInterface verifier is changed a bit. It used to operate using the result type to verify the provided shape and length parameters. This is a bit incorrect because what matters to verify the information is the input address (This worked OK with fir.declare where the input memref type is the same as the output result). Also, not all operation defining variables will have an input memref with the same meaning (hlfir.designate and hlfir.associate for instance). Hence, this verifier is now optional and must be provided a memref to operate. Differential Revision: https://reviews.llvm.org/D137781
70 lines
3.1 KiB
C++
70 lines
3.1 KiB
C++
//===-- FortranVariableInterface.cpp.cpp ----------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "flang/Optimizer/Dialect/FortranVariableInterface.h"
|
|
|
|
#include "flang/Optimizer/Dialect/FortranVariableInterface.cpp.inc"
|
|
|
|
mlir::LogicalResult
|
|
fir::FortranVariableOpInterface::verifyDeclareLikeOpImpl(mlir::Value memref) {
|
|
const unsigned numExplicitTypeParams = getExplicitTypeParams().size();
|
|
mlir::Type memType = memref.getType();
|
|
const bool sourceIsBoxValue = memType.isa<fir::BaseBoxType>();
|
|
const bool sourceIsBoxAddress = fir::isBoxAddress(memType);
|
|
const bool sourceIsBox = sourceIsBoxValue || sourceIsBoxAddress;
|
|
if (isCharacter()) {
|
|
if (numExplicitTypeParams > 1)
|
|
return emitOpError(
|
|
"of character entity must have at most one length parameter");
|
|
if (numExplicitTypeParams == 0 && !sourceIsBox)
|
|
return emitOpError("must be provided exactly one type parameter when its "
|
|
"base is a character that is not a box");
|
|
|
|
} else if (auto recordType = getElementType().dyn_cast<fir::RecordType>()) {
|
|
if (numExplicitTypeParams < recordType.getNumLenParams() && !sourceIsBox)
|
|
return emitOpError("must be provided all the derived type length "
|
|
"parameters when the base is not a box");
|
|
if (numExplicitTypeParams > recordType.getNumLenParams())
|
|
return emitOpError("has too many length parameters");
|
|
} else if (numExplicitTypeParams != 0) {
|
|
return emitOpError("of numeric, logical, or assumed type entity must not "
|
|
"have length parameters");
|
|
}
|
|
|
|
if (isArray()) {
|
|
if (mlir::Value shape = getShape()) {
|
|
if (sourceIsBoxAddress)
|
|
return emitOpError("for box address must not have a shape operand");
|
|
unsigned shapeRank = 0;
|
|
if (auto shapeType = shape.getType().dyn_cast<fir::ShapeType>()) {
|
|
shapeRank = shapeType.getRank();
|
|
} else if (auto shapeShiftType =
|
|
shape.getType().dyn_cast<fir::ShapeShiftType>()) {
|
|
shapeRank = shapeShiftType.getRank();
|
|
} else {
|
|
if (!sourceIsBoxValue)
|
|
emitOpError("of array entity with a raw address base must have a "
|
|
"shape operand that is a shape or shapeshift");
|
|
shapeRank = shape.getType().cast<fir::ShiftType>().getRank();
|
|
}
|
|
|
|
llvm::Optional<unsigned> rank = getRank();
|
|
if (!rank || *rank != shapeRank)
|
|
return emitOpError("has conflicting shape and base operand ranks");
|
|
} else if (!sourceIsBox) {
|
|
emitOpError("of array entity with a raw address base must have a shape "
|
|
"operand that is a shape or shapeshift");
|
|
}
|
|
}
|
|
return mlir::success();
|
|
}
|