diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -88,6 +88,7 @@ std::string componentName{}; mlir::Value componentShape; hlfir::DesignateOp::Subscripts subscripts; + std::optional complexPart; mlir::Value resultShape; llvm::SmallVector typeParams; llvm::SmallVector substring; @@ -98,8 +99,14 @@ // fir.box)... template mlir::Type computeDesignatorType(mlir::Type resultValueType, - const PartInfo &partInfo, + PartInfo &partInfo, const T &designatorNode) { + // Get base's shape if its a sequence type with no previously computed + // result shape + if (partInfo.base && resultValueType.isa() && + !partInfo.resultShape) + partInfo.resultShape = + hlfir::genShape(getLoc(), getBuilder(), *partInfo.base); // Dynamic type of polymorphic base must be kept if the designator is // polymorphic. if (isPolymorphic(designatorNode)) @@ -144,11 +151,10 @@ fir::FortranVariableOpInterface genDesignate(mlir::Type designatorType, PartInfo &partInfo, fir::FortranVariableFlagsAttr attributes) { - std::optional complexPart; auto designate = getBuilder().create( getLoc(), designatorType, partInfo.base.value().getBase(), partInfo.componentName, partInfo.componentShape, partInfo.subscripts, - partInfo.substring, complexPart, partInfo.resultShape, + partInfo.substring, partInfo.complexPart, partInfo.resultShape, partInfo.typeParams, attributes); return mlir::cast( designate.getOperation()); @@ -240,7 +246,21 @@ fir::FortranVariableOpInterface gen(const Fortran::evaluate::ComplexPart &complexPart) { - TODO(getLoc(), "lowering complex part to HLFIR"); + PartInfo partInfo; + fir::factory::Complex cmplxHelper(getBuilder(), getLoc()); + + bool complexBit = + complexPart.part() == Fortran::evaluate::ComplexPart::Part::IM; + partInfo.complexPart = {complexBit}; + + mlir::Type resultType = visit(complexPart.complex(), partInfo); + + // Determine complex part type + mlir::Type base = hlfir::getFortranElementType(resultType); + mlir::Type cmplxValueType = cmplxHelper.getComplexPartType(base); + mlir::Type designatorType = changeElementType(resultType, cmplxValueType); + + return genDesignate(designatorType, partInfo, complexPart); } fir::FortranVariableOpInterface diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp --- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp +++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp @@ -336,7 +336,9 @@ // length may differ because of substrings. if (resultElementType != outputElementType && !(resultElementType.isa() && - outputElementType.isa())) + outputElementType.isa()) && + !(resultElementType.isa() && + outputElementType.isa())) return emitOpError( "result element type is not consistent with operands, expected ") << outputElementType; diff --git a/flang/test/Lower/HLFIR/designators.f90 b/flang/test/Lower/HLFIR/designators.f90 --- a/flang/test/Lower/HLFIR/designators.f90 +++ b/flang/test/Lower/HLFIR/designators.f90 @@ -112,3 +112,58 @@ ! CHECK: %[[VAL_19:.*]] = arith.select %[[VAL_18]], %[[VAL_17]], %[[VAL_14]] : index ! CHECK: %[[VAL_20:.*]] = fir.shape %[[VAL_19]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_10]]:%[[VAL_12]]#1:%[[VAL_13]]) shape %[[VAL_20]] typeparams %[[VAL_3]] : (!fir.box>>, index, index, index, !fir.shape<1>, index) -> !fir.box>> + +! Checks related to complex numbers + +subroutine complex_imag_ref(x) + complex :: x(:) + print *, x%im +end subroutine +! CHECK-LABEL: func.func @_QPcomplex_imag_ref( +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFcomplex_imag_refEx"} : (!fir.box>>) -> (!fir.box>>, !fir.box>>) +! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_4:.*]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[VAL_5:.*]] = hlfir.designate %[[VAL_2]]#0 imag shape %[[VAL_3]] : (!fir.box>>, !fir.shape<1>) -> !fir.box> + +subroutine complex_real_ref(x) + complex :: x(:) + print *, x%re +end subroutine +! CHECK-LABEL: func.func @_QPcomplex_real_ref( +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFcomplex_real_refEx"} : (!fir.box>>) -> (!fir.box>>, !fir.box>>) +! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_4:.*]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[VAL_5:.*]] = hlfir.designate %[[VAL_2]]#0 real shape %[[VAL_3]] : (!fir.box>>, !fir.shape<1>) -> !fir.box> + +subroutine complex_individual_ref(x, n) + complex :: x(:) + integer :: n + print *, x(n)%im +end subroutine +! CHECK-LABEL: func.func @_QPcomplex_individual_ref( +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFcomplex_individual_refEn"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFcomplex_individual_refEx"} : (!fir.box>>) -> (!fir.box>>, !fir.box>>) +! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref +! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> i64 +! CHECK: %[[VAL_6:.*]] = hlfir.designate %1#0 (%[[VAL_5]]) imag : (!fir.box>>, i64) -> !fir.ref + +subroutine complex_slice_ref(x, start, end) + complex :: x(:) + integer :: start, end + print *, x(start:end)%re +end subroutine +! CHECK-LABEL: func.func @_QPcomplex_slice_ref( +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFcomplex_slice_refEend"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFcomplex_slice_refEstart"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %arg0 {uniq_name = "_QFcomplex_slice_refEx"} : (!fir.box>>) -> (!fir.box>>, !fir.box>>) +! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i32) -> i64 +! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref +! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i32) -> i64 +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_6]] : (i64) -> index +! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_8]] : (i64) -> index +! CHECK: %[[VAL_11:.*]] = arith.subi %[[VAL_10]], %[[VAL_9]] : index +! CHECK: %[[VAL_12:.*]] = arith.addi %[[VAL_11]], %{{.*}} : index +! CHECK: %[[VAL_13:.*]] = arith.divsi %[[VAL_12]], %{{.*}} : index +! CHECK: %[[VAL_14:.*]] = arith.cmpi sgt, %[[VAL_13]], %{{.*}} : index +! CHECK: %[[VAL_15:.*]] = arith.select %[[VAL_14]], %[[VAL_13]], %{{.*}} : index +! CHECK: %[[VAL_16:.*]] = fir.shape %[[VAL_15]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_9]]:%[[VAL_10]]:%{{.*}}) real shape %[[VAL_16]] : (!fir.box>>, index, index, index, !fir.shape<1>) -> !fir.box>