}
}
+ /// Given converted LHS and RHS of the assignment, generate
+ /// explicit type conversion for implicit Logical<->Integer
+ /// conversion. Return Value representing the converted RHS,
+ /// if the implicit Logical<->Integer is detected, otherwise,
+ /// return nullptr. The caller is responsible for inserting
+ /// DestroyOp in case the returned value has hlfir::ExprType.
+ mlir::Value
+ genImplicitLogicalConvert(const Fortran::evaluate::Assignment &assign,
+ hlfir::Entity lhs, hlfir::Entity rhs) {
+ mlir::Type fromTy = rhs.getFortranElementType();
+ mlir::Type toTy = lhs.getFortranElementType();
+ if (fromTy == toTy)
+ return nullptr;
+
+ if (!fromTy.isa<mlir::IntegerType, fir::LogicalType>())
+ return nullptr;
+ if (!toTy.isa<mlir::IntegerType, fir::LogicalType>())
+ return nullptr;
+
+ mlir::Location loc = toLocation();
+ auto &builder = getFirOpBuilder();
+ if (assign.rhs.Rank() == 0)
+ return builder.createConvert(loc, toTy, rhs);
+
+ mlir::Value shape = hlfir::genShape(loc, builder, rhs);
+ auto genKernel =
+ [&rhs, &toTy](mlir::Location loc, fir::FirOpBuilder &builder,
+ mlir::ValueRange oneBasedIndices) -> hlfir::Entity {
+ auto elementPtr = hlfir::getElementAt(loc, builder, rhs, oneBasedIndices);
+ auto val = hlfir::loadTrivialScalar(loc, builder, elementPtr);
+ return hlfir::EntityWithAttributes{builder.createConvert(loc, toTy, val)};
+ };
+ return hlfir::genElementalOp(loc, builder, toTy, shape, /*typeParams=*/{},
+ genKernel);
+ }
+
/// Shared for both assignments and pointer assignments.
void genAssignment(const Fortran::evaluate::Assignment &assign) {
mlir::Location loc = toLocation();
// Dereference pointer LHS: the target is being assigned to.
lhs = hlfir::derefPointersAndAllocatables(loc, builder, lhs);
}
+
+ // Logical<->Integer assignments are allowed as an extension,
+ // but there is no explicit Convert expression for the RHS.
+ // Recognize the type mismatch here and insert explicit
+ // scalar convert or ElementalOp for array assignment.
+ mlir::Value logicalConvert =
+ genImplicitLogicalConvert(assign, lhs, rhs);
+ if (logicalConvert)
+ rhs = hlfir::EntityWithAttributes{logicalConvert};
+
builder.create<hlfir::AssignOp>(
loc, rhs, lhs, isWholeAllocatableAssignment,
keepLhsLengthInAllocatableAssignment);
+
+ // Mark the end of life range of the ElementalOp's result.
+ if (logicalConvert &&
+ logicalConvert.getType().isa<hlfir::ExprType>())
+ builder.create<hlfir::DestroyOp>(loc, rhs);
},
// [2] User defined assignment. If the context is a scalar
// expression then call the procedure.
--- /dev/null
+! RUN: bbc -emit-fir -hlfir %s -o - | FileCheck %s
+
+! CHECK-LABEL: func.func @_QPtest1(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "x"},
+! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "y"}) {
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest1Ex"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest1Ey"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
+! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (!fir.logical<4>) -> i32
+! CHECK: hlfir.assign %[[VAL_5]] to %[[VAL_2]]#0 : i32, !fir.ref<i32>
+! CHECK: return
+! CHECK: }
+subroutine test1(x, y)
+ integer :: x
+ logical :: y
+ x = y
+end subroutine test1
+
+! CHECK-LABEL: func.func @_QPtest2(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "x"},
+! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "y"}) {
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest2Ex"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest2Ey"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
+! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32>
+! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_5]] to %[[VAL_3]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: return
+! CHECK: }
+subroutine test2(x, y)
+ integer :: x
+ logical :: y
+ y = x
+end subroutine test2
+
+! CHECK-LABEL: func.func @_QPtest3(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "x"},
+! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "y"}) {
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest3Ex"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest3Ey"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32>
+! CHECK: %[[VAL_5:.*]] = arith.constant 1 : i32
+! CHECK: %[[VAL_6:.*]] = arith.cmpi eq, %[[VAL_4]], %[[VAL_5]] : i32
+! CHECK: %[[VAL_7:.*]] = hlfir.no_reassoc %[[VAL_6]] : i1
+! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i1) -> !fir.logical<4>
+! CHECK: hlfir.assign %[[VAL_8]] to %[[VAL_2]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
+! CHECK: return
+! CHECK: }
+subroutine test3(x, y)
+ logical :: x
+ integer :: y
+ x = (y.eq.1)
+end subroutine test3
+
+! CHECK-LABEL: func.func @_QPtest4(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "x"},
+! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "y"}) {
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest4Ex"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest4Ey"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32>
+! CHECK: %[[VAL_5:.*]] = arith.constant 1 : i32
+! CHECK: %[[VAL_6:.*]] = arith.cmpi eq, %[[VAL_4]], %[[VAL_5]] : i32
+! CHECK: %[[VAL_7:.*]] = hlfir.no_reassoc %[[VAL_6]] : i1
+! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i1) -> i32
+! CHECK: hlfir.assign %[[VAL_8]] to %[[VAL_2]]#0 : i32, !fir.ref<i32>
+! CHECK: return
+! CHECK: }
+subroutine test4(x, y)
+ integer :: x
+ integer :: y
+ x = (y.eq.1)
+end subroutine test4
+
+! CHECK-LABEL: func.func @_QPtest5(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "x"},
+! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "y"}) {
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest5Ex"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>)
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest5Ey"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
+! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (!fir.logical<4>) -> i32
+! CHECK: hlfir.assign %[[VAL_5]] to %[[VAL_2]]#0 : i32, !fir.box<!fir.array<?xi32>>
+! CHECK: return
+! CHECK: }
+subroutine test5(x, y)
+ integer :: x(:)
+ logical :: y
+ x = y
+end subroutine test5
+
+! CHECK-LABEL: func.func @_QPtest6(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "x"},
+! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "y"}) {
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest6Ex"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>)
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest6Ey"} : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>)
+! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_3]]#0, %[[VAL_4]] : (!fir.box<!fir.array<?x!fir.logical<4>>>, index) -> (index, index, index)
+! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]]#1 : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_7:.*]] = hlfir.elemental %[[VAL_6]] : (!fir.shape<1>) -> !hlfir.expr<?xi32> {
+! CHECK: ^bb0(%[[VAL_8:.*]]: index):
+! CHECK: %[[VAL_9:.*]] = hlfir.designate %[[VAL_3]]#0 (%[[VAL_8]]) : (!fir.box<!fir.array<?x!fir.logical<4>>>, index) -> !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_9]] : !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (!fir.logical<4>) -> i32
+! CHECK: hlfir.yield_element %[[VAL_11]] : i32
+! CHECK: }
+! CHECK: hlfir.assign %[[VAL_12:.*]] to %[[VAL_2]]#0 : !hlfir.expr<?xi32>, !fir.box<!fir.array<?xi32>>
+! CHECK: hlfir.destroy %[[VAL_12]] : !hlfir.expr<?xi32>
+! CHECK: return
+! CHECK: }
+subroutine test6(x, y)
+ integer :: x(:)
+ logical :: y(:)
+ x = y
+end subroutine test6
+
+! CHECK-LABEL: func.func @_QPtest7(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "x"},
+! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "y"}) {
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest7Ex"} : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>)
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest7Ey"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>)
+! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_3]]#0, %[[VAL_4]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
+! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]]#1 : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_7:.*]] = hlfir.elemental %[[VAL_6]] : (!fir.shape<1>) -> !hlfir.expr<?x!fir.logical<4>> {
+! CHECK: ^bb0(%[[VAL_8:.*]]: index):
+! CHECK: %[[VAL_9:.*]] = hlfir.designate %[[VAL_3]]#0 (%[[VAL_8]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
+! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_9]] : !fir.ref<i32>
+! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (i32) -> !fir.logical<4>
+! CHECK: hlfir.yield_element %[[VAL_11]] : !fir.logical<4>
+! CHECK: }
+! CHECK: hlfir.assign %[[VAL_12:.*]] to %[[VAL_2]]#0 : !hlfir.expr<?x!fir.logical<4>>, !fir.box<!fir.array<?x!fir.logical<4>>>
+! CHECK: hlfir.destroy %[[VAL_12]] : !hlfir.expr<?x!fir.logical<4>>
+! CHECK: return
+! CHECK: }
+subroutine test7(x, y)
+ logical :: x(:)
+ integer :: y(:)
+ x = y
+end subroutine test7