diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td index b5e2a4493dcbf..88acf78bf61a1 100644 --- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td +++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td @@ -457,4 +457,29 @@ def hlfir_ApplyOp : hlfir_Op<"apply", [NoMemoryEffect, AttrSizedOperandSegments] ]; } +def hlfir_NullOp : hlfir_Op<"null", [NoMemoryEffect, fir_FortranVariableOpInterface]> { + let summary = "create a NULL() address"; + + let description = [{ + Create a NULL() address. + So far is not intended to represent NULL(MOLD). + }]; + + let results = (outs AnyFortranVariable); + let builders = [OpBuilder<(ins)>]; + + let assemblyFormat = "type(results) attr-dict"; + let extraClassDeclaration = [{ + // Implement FortranVariableInterface interface. + std::optional getFortranAttrs() const { + return std::nullopt; + } + mlir::Value getShape() const {return mlir::Value{};} + mlir::OperandRange getExplicitTypeParams() const { + // Return an empty range. + return {(*this)->getOperands().begin(), (*this)->getOperands().begin()}; + } + }]; +} + #endif // FORTRAN_DIALECT_HLFIR_OPS diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp index 654414ac8603f..ba62f511e5348 100644 --- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp +++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp @@ -503,5 +503,15 @@ void hlfir::ApplyOp::build(mlir::OpBuilder &builder, build(builder, odsState, resultType, expr, indices, typeparams); } +//===----------------------------------------------------------------------===// +// NullOp +//===----------------------------------------------------------------------===// + +void hlfir::NullOp::build(mlir::OpBuilder &builder, + mlir::OperationState &odsState) { + return build(builder, odsState, + fir::ReferenceType::get(builder.getNoneType())); +} + #define GET_OP_CLASSES #include "flang/Optimizer/HLFIR/HLFIROps.cpp.inc" diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp index a5c31b3e09395..561f3e3c07b6d 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp @@ -291,6 +291,18 @@ class NoReassocOpConversion } }; +class NullOpConversion : public mlir::OpRewritePattern { +public: + explicit NullOpConversion(mlir::MLIRContext *ctx) : OpRewritePattern{ctx} {} + + mlir::LogicalResult + matchAndRewrite(hlfir::NullOp nullop, + mlir::PatternRewriter &rewriter) const override { + rewriter.replaceOpWithNewOp(nullop, nullop.getType()); + return mlir::success(); + } +}; + class ConvertHLFIRtoFIR : public hlfir::impl::ConvertHLFIRtoFIRBase { public: @@ -302,8 +314,9 @@ class ConvertHLFIRtoFIR auto module = this->getOperation(); auto *context = &getContext(); mlir::RewritePatternSet patterns(context); - patterns.insert(context); + patterns + .insert(context); mlir::ConversionTarget target(*context); target.addIllegalDialect(); target.markUnknownOpDynamicallyLegal( diff --git a/flang/test/HLFIR/null-codegen.fir b/flang/test/HLFIR/null-codegen.fir new file mode 100644 index 0000000000000..4568c45e92270 --- /dev/null +++ b/flang/test/HLFIR/null-codegen.fir @@ -0,0 +1,9 @@ +// Test hlfir.null code generation to FIR + +// RUN: fir-opt %s -convert-hlfir-to-fir | FileCheck %s + +func.func @test() { + // CHECK: fir.zero_bits !fir.ref + %0 = hlfir.null !fir.ref + return +} diff --git a/flang/test/HLFIR/null.fir b/flang/test/HLFIR/null.fir new file mode 100644 index 0000000000000..4614f2bc25e5d --- /dev/null +++ b/flang/test/HLFIR/null.fir @@ -0,0 +1,9 @@ +// Test hlfir.null operation parse, verify (no errors), and unparse. + +// RUN: fir-opt %s | fir-opt | FileCheck %s + +func.func @test() { + // CHECK: hlfir.null !fir.ref + %0 = hlfir.null !fir.ref + return +}