diff --git a/flang/include/flang/Optimizer/Builder/Complex.h b/flang/include/flang/Optimizer/Builder/Complex.h --- a/flang/include/flang/Optimizer/Builder/Complex.h +++ b/flang/include/flang/Optimizer/Builder/Complex.h @@ -32,6 +32,9 @@ mlir::Type getComplexPartType(mlir::Value cplx) const; mlir::Type getComplexPartType(mlir::Type complexType) const; + // Get the Complex type as an FIR type + fir::RealType getComplexPartFIRType(mlir::Type complexType) const; + /// Complex operation creation. They create MLIR operations. mlir::Value createComplex(fir::KindTy kind, mlir::Value real, mlir::Value imag); 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; @@ -144,11 +145,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()); @@ -157,8 +157,9 @@ fir::FortranVariableOpInterface gen(const Fortran::evaluate::SymbolRef &symbolRef) { if (std::optional varDef = - getSymMap().lookupVariableDefinition(symbolRef)) + getSymMap().lookupVariableDefinition(symbolRef)) { return *varDef; + } TODO(getLoc(), "lowering symbol to HLFIR"); } @@ -189,7 +190,36 @@ 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.getComplexPartFIRType(base); + mlir::Type changedType = changeElementType(resultType, cmplxValueType); + mlir::Type designatorType = fir::ReferenceType::get(changedType); + + // Get base's shape if type is not a box address + if (partInfo.base && changedType.isa() && + !fir::isBoxAddress(changedType)) { + partInfo.resultShape = + hlfir::genShape(getLoc(), getBuilder(), *partInfo.base); + } + + // Box designator type if applicable + if (changedType.isa() || + fir::hasDynamicSize(changedType) || + partInfo.base->hasNonDefaultLowerBounds()) { + designatorType = fir::BoxType::get(changedType); + } + + return genDesignate(designatorType, partInfo, {}); } fir::FortranVariableOpInterface diff --git a/flang/lib/Optimizer/Builder/Complex.cpp b/flang/lib/Optimizer/Builder/Complex.cpp --- a/flang/lib/Optimizer/Builder/Complex.cpp +++ b/flang/lib/Optimizer/Builder/Complex.cpp @@ -12,15 +12,25 @@ // Complex Factory implementation //===----------------------------------------------------------------------===// +fir::KindTy getComplexPartKindTy(mlir::Type complexType) { + return complexType.cast().getFKind(); +} + mlir::Type fir::factory::Complex::getComplexPartType(mlir::Type complexType) const { - return builder.getRealType(complexType.cast().getFKind()); + return builder.getRealType(getComplexPartKindTy(complexType)); } mlir::Type fir::factory::Complex::getComplexPartType(mlir::Value cplx) const { return getComplexPartType(cplx.getType()); } +fir::RealType +fir::factory::Complex::getComplexPartFIRType(mlir::Type complexType) const { + return fir::RealType::get(builder.getContext(), + getComplexPartKindTy(complexType)); +} + mlir::Value fir::factory::Complex::createComplex(fir::KindTy kind, mlir::Value real, mlir::Value imag) { 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,35 @@ ! 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>