Index: flang/lib/Optimizer/CodeGen/TypeConverter.h =================================================================== --- flang/lib/Optimizer/CodeGen/TypeConverter.h +++ flang/lib/Optimizer/CodeGen/TypeConverter.h @@ -59,11 +59,8 @@ LLVM_DEBUG(llvm::dbgs() << "type convert: " << boxchar << '\n'); return convertType(specifics->boxcharMemoryType(boxchar.getEleTy())); }); - addConversion([&](BoxProcType boxproc) { - // TODO: Support for this type will be added later when the Fortran 2003 - // procedure pointer feature is implemented. - return llvm::None; - }); + addConversion( + [&](BoxProcType boxproc) { return convertBoxProcType(boxproc); }); addConversion( [&](fir::ClassType classTy) { return convertBoxType(classTy); }); addConversion( @@ -179,6 +176,8 @@ // context of a record type. if (auto box = mem.second.dyn_cast()) members.push_back(convertBoxTypeAsStruct(box)); + else if (auto boxproc = mem.second.dyn_cast()) + members.push_back(convertBoxProcType(boxproc)); else members.push_back(convertType(mem.second).cast()); } @@ -275,14 +274,9 @@ .getElementType(); } - // fir.boxproc --> llvm<"{ any*, i8* }"> + // fir.boxproc --> any* mlir::Type convertBoxProcType(BoxProcType boxproc) { - auto funcTy = convertType(boxproc.getEleTy()); - auto i8PtrTy = mlir::LLVM::LLVMPointerType::get( - mlir::IntegerType::get(&getContext(), 8)); - llvm::SmallVector tuple = {funcTy, i8PtrTy}; - return mlir::LLVM::LLVMStructType::getLiteral(&getContext(), tuple, - /*isPacked=*/false); + return convertType(boxproc.getEleTy()); } unsigned characterBitsize(fir::CharacterType charTy) { Index: flang/lib/Optimizer/Dialect/FIRType.cpp =================================================================== --- flang/lib/Optimizer/Dialect/FIRType.cpp +++ flang/lib/Optimizer/Dialect/FIRType.cpp @@ -63,11 +63,10 @@ } bool verifyRecordMemberType(mlir::Type ty) { - return !(ty.isa() || ty.isa() || - ty.isa() || ty.isa() || - ty.isa() || ty.isa() || ty.isa() || - ty.isa() || ty.isa() || - ty.isa()); + return !(ty.isa() || ty.isa() || + ty.isa() || ty.isa() || + ty.isa() || ty.isa() || ty.isa() || + ty.isa() || ty.isa()); } bool verifySameLists(llvm::ArrayRef a1, Index: flang/test/Fir/Todo/boxproc_host.fir =================================================================== --- flang/test/Fir/Todo/boxproc_host.fir +++ flang/test/Fir/Todo/boxproc_host.fir @@ -1,10 +1,9 @@ -// RUN: not fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s 2>&1 | FileCheck %s +// RUN: %not_todo_cmd fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s 2>&1 | FileCheck %s // Test that `fir.boxproc_host` fails conversion to llvm. -// At the moment this test fails since `fir.boxproc` type does not have a conversion. -// CHECK: failed to legalize operation 'func.func' func.func @test(%bproc: !fir.boxproc<(i32) -> ()>) { + // CHECK: not yet implemented: fir.boxproc_host codegen %tuple = fir.boxproc_host %bproc : (!fir.boxproc<(i32) -> ()>) -> (!fir.ref>) return } Index: flang/test/Fir/Todo/unboxproc.fir =================================================================== --- flang/test/Fir/Todo/unboxproc.fir +++ flang/test/Fir/Todo/unboxproc.fir @@ -1,11 +1,10 @@ -// RUN: not fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s 2>&1 | FileCheck %s +// RUN: %not_todo_cmd fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s 2>&1 | FileCheck %s // Test `fir.unboxproc` conversion to llvm. // Not implemented yet. -// Currently fails since coversion for boxproc type is not implemented. -// CHECK: failed to legalize operation 'func.func' func.func @boxing_match(%bproc: !fir.boxproc<(i32) -> ()>) { + // CHECK: not yet implemented: fir.unboxproc codegen %ubproc:2 = fir.unboxproc %bproc : (!fir.boxproc<(i32) -> ()>) -> ((i32) -> (), !fir.ref>) return } Index: flang/test/Fir/proc_pointer.fir =================================================================== --- /dev/null +++ flang/test/Fir/proc_pointer.fir @@ -0,0 +1,18 @@ +// RUN: fir-opt --fir-to-llvm-ir %s | tco | FileCheck %s + +// Test that record type with a boxproc type conversion to llvm. + +// CHECK-LABEL: define void @proc_pointer_component( +// CHECK-SAME: ptr %[[arg0:.*]]) +// CHECK: %[[VAL_1:.*]] = alloca %_QFtestTmatrix, i64 1, align 8 +// CHECK: %[[VAL_2:.*]] = getelementptr %_QFtestTmatrix, ptr %[[VAL_1]], i32 0, i32 1 +// CHECK: store ptr %[[arg0]], ptr %[[VAL_2]], align 8 +// CHECK: ret void + +func.func @proc_pointer_component(%arg0 : !fir.boxproc<(!fir.ref) -> f32>) { + %0 = fir.alloca !fir.type<_QFtestTmatrix{element:!fir.array<2x2xf32>,solve:!fir.boxproc<(!fir.ref) -> f32>}> + %1 = fir.field_index solve, !fir.type<_QFtestTmatrix{element:!fir.array<2x2xf32>,solve:!fir.boxproc<(!fir.ref) -> f32>}> + %2 = fir.coordinate_of %0, %1 : (!fir.ref,solve:!fir.boxproc<(!fir.ref) -> f32>}>>, !fir.field) -> !fir.ref) -> f32>> + fir.store %arg0 to %2 : !fir.ref) -> f32>> + return +}