Observed issues › oop/cce-polymorphic-dispatch-device-link
dynamic dispatch of a type-bound procedure in device code fails at the link
Legality: not independently confirmed. Independent readings are uncertain: The accessed binding area is deferred and its abstract interface has no body and no declare target; the overriders have it. The text does not say whether the deferred binding or the overriders count, nor does it define device-side dynamic dispatch. so a link failure is not shown to be a violation. How this is checked
A declare target function calls a type-bound procedure through a CLASS(shape) dummy argument (dynamic dispatch); every procedure bound to the binding is declare target. CCE 19, 20 and 21 fail at the device link with an undefined __GET_TYPE_BOUND_PROC. The same program calling the binding on the non-polymorphic objects themselves (no dispatch) works. AFAR compiles and runs the program correctly.
Affected variants
| Compiler | MI300A gfx942 unified memory (XNACK 1) | MI300A gfx942 copy (XNACK 0) | MI250X gfx90a copy (XNACK 0) | MI300X gfx942 copy (XNACK 0) | MI350X gfx950 copy (XNACK 0) | A100 sm_80 separate memory | A100 sm_80 managed memory |
|---|---|---|---|---|---|---|---|
| AFAR 24.3.0 | correct | correct | unknown not run | correct | correct | n/a | n/a |
| CCE 19.0.0 | not supported | not supported | unknown not run | unknown not run | unknown not run | n/a | n/a |
| CCE 20.0.2 | not supported | not supported | unknown not run | unknown not run | unknown not run | n/a | n/a |
| CCE 21.0.3 | not supported | not supported | unknown not run | unknown not run | unknown not run | n/a | n/a |
| CCE 21.0.4 | not supported | not supported | unknown not run | unknown not run | unknown not run | n/a | n/a |
| NVHPC 25.11 | n/a | n/a | n/a | n/a | n/a | fails another way | fails another way |
| NVHPC 26.9 | n/a | n/a | n/a | n/a | n/a | fails another way | fails another way |
| GCC 16.2.0 | fails another way | fails another way | fails another way | fails another way | fails another way | fails another way | n/a |
"behaves incorrectly" / "not supported": this issue, confirmed in up to four environments (another build directory, another node, a repeat). "fails another way": a different failure, not counted as this issue. "unknown": not run there, or the runs disagree.
Messages
| Result | Compiler and GPU | Message |
|---|---|---|
| not supported | CCE 19.0.0, MI300A unified CCE 19.0.0, MI300A copy | showWarning: Headers and libraries from cray-libsci/25.03.0 will be ignored because depends on PE_MPICH which is unavailable.. lld: error: undefined symbol: __GET_TYPE_BOUND_PROC >>> referenced by <dir>:(oop_$ck_L82_2) >>> referenced by <dir>:(oop_$ck_L82_2) |
| not supported | CCE 20.0.2, MI300A unified CCE 20.0.2, MI300A copy | showWarning: Headers and libraries from cray-libsci/25.09.0 will be ignored because depends on PE_MPICH which is unavailable.. lld: error: undefined symbol: __GET_TYPE_BOUND_PROC >>> referenced by <dir>:(oop_$ck_L82_2) >>> referenced by <dir>:(oop_$ck_L82_2) |
| not supported | CCE 21.0.3, MI300A unified CCE 21.0.3, MI300A copy | showWarning: Headers and libraries from cray-libsci/26.03.0 will be ignored because depends on PE_MPICH which is unavailable.. lld: error: undefined symbol: __GET_TYPE_BOUND_PROC >>> referenced by <dir>//cooltmpdir-1hIYs0/repro-cce-openmppost_lld.amdgpu.lto.o:(oop_$ck_L82_2) >>> referenced by <dir>//cooltmpdir-1hIYs0/repro-cce-openmppost_lld.amdgpu.lto.o:(oop_$ck_L82_2) |
| not supported | CCE 21.0.4, MI300A unified CCE 21.0.4, MI300A copy | showWarning: Headers and libraries from cray-libsci/26.03.0 will be ignored because depends on PE_MPICH which is unavailable.. lld: error: undefined symbol: __GET_TYPE_BOUND_PROC >>> referenced by <dir>//cooltmpdir-LPWReR/repro-cce-openmppost_lld.amdgpu.lto.o:(oop_$ck_L82_2) >>> referenced by <dir>//cooltmpdir-LPWReR/repro-cce-openmppost_lld.amdgpu.lto.o:(oop_$ck_L82_2) |
| fails another way | NVHPC 25.11, A100 separate NVHPC 25.11, A100 managed | showNVFORTRAN-W-0155-Compiler failed to translate accelerator region (see -Minfo messages): No device symbol for address reference (site-oop--cce-polymorphic-dispatch-device-link.f90: 84) NVFORTRAN-F-0704-Compilation aborted due to previous errors. (site-oop--cce-polymorphic-dispatch-device-link.f90) NVFORTRAN/x86-64 Linux 25.11-0: compilation aborted |
| fails another way | NVHPC 26.9, A100 separate NVHPC 26.9, A100 managed | showNVFORTRAN-W-0155-Compiler failed to translate accelerator region (see -Minfo messages): No device symbol for address reference (site-oop--cce-polymorphic-dispatch-device-link.f90: 84) NVFORTRAN-F-0704-Compilation aborted due to previous errors. (site-oop--cce-polymorphic-dispatch-device-link.f90) NVFORTRAN/x86-64 Linux 26.9-0: compilation aborted |
| fails another way | GCC 16.2.0, MI300A unified | showRUN_TIMEOUT |
| fails another way | GCC 16.2.0, MI300A copy | showMemory access fault by GPU node-7 (Agent handle: 0x591bc0) on address 0x401000. Reason: Unknown. Program received signal SIGABRT: Process abort signal. Backtrace for this error: #0 0x15555469662f in ??? #1 0x1555546965af in ??? #2 0x155554669ee4 in ??? #3 0x1555540d6bfe in ??? #4 0x1555540d4288 in ??? |
| fails another way | GCC 16.2.0, MI250X | showMemory access fault by GPU node-6 (Agent handle: 0x783070) on address 0x400000. Reason: Unknown. Program received signal SIGABRT: Process abort signal. Backtrace for this error: #0 0x15555469662f in ??? #1 0x1555546965af in ??? #2 0x155554669ee4 in ??? #3 0x1555540d6bfe in ??? #4 0x1555540d4288 in ??? |
| fails another way | GCC 16.2.0, MI300X | showMemory access fault by GPU node-1 (Agent handle: 0x1dccf00) on address 0x401000. Reason: Unknown. Program received signal SIGABRT: Process abort signal. Backtrace for this error: #0 0x7fcb58a3ebef in ??? #1 0x7fcb58a8bedc in ??? #2 0x7fcb58a3eb45 in ??? #3 0x7fcb58a28832 in ??? #4 0x7fcb58689a5e in ??? |
| fails another way | GCC 16.2.0, MI350X | showMemory access fault by GPU node-1 (Agent handle: 0xdbb5c0) on address 0x401000. Reason: Unknown. Program received signal SIGABRT: Process abort signal. Backtrace for this error: #0 0x7f65ce83fc2f in ??? #1 0x7f65ce88d02c in ??? #2 0x7f65ce83fb85 in ??? #3 0x7f65ce829872 in ??? #4 0x7f65ce489a5e in ??? |
| fails another way | GCC 16.2.0, A100 separate | showlibgomp: cuCtxSynchronize error: an illegal memory access was encountered libgomp: cuModuleGetFunction (__do_global_dtors__entry) error: an illegal memory access was encountered libgomp: cuMemFree_v2 error: an illegal memory access was encountered libgomp: device finalization failed |
Reproduce
CCE 19.0.0, MI300A unified
module load cce/19.0.0 craype-accel-amd-gfx942 rocm/6.4.3 module unload cray-mpich ftn -fopenmp -O2 repro.f90 -o repro HSA_XNACK=1 OMP_TARGET_OFFLOAD=mandatory ./repro
CCE 20.0.2, MI300A unified
module load cce/20.0.2 craype-accel-amd-gfx942 rocm/6.4.3 module unload cray-mpich ftn -fopenmp -O2 repro.f90 -o repro HSA_XNACK=1 OMP_TARGET_OFFLOAD=mandatory ./repro
CCE 21.0.3, MI300A unified
module load cce/21.0.3 craype-accel-amd-gfx942 rocm/7.2.0 module unload cray-mpich ftn -fopenmp -O2 repro.f90 -o repro HSA_XNACK=1 OMP_TARGET_OFFLOAD=mandatory ./repro
CCE 21.0.4, MI300A unified
module load cce/21.0.4 craype-accel-amd-gfx942 rocm/7.2.0 module unload cray-mpich ftn -fopenmp -O2 repro.f90 -o repro HSA_XNACK=1 OMP_TARGET_OFFLOAD=mandatory ./repro
AFAR 24.3.0, MI300A unified (runs correctly)
$AFAR/bin/amdflang -fopenmp --offload-arch=gfx942 -O2 repro.f90 -o repro HSA_XNACK=1 OMP_TARGET_OFFLOAD=mandatory ./repro
Program (91 lines)
! # Finding (fortran-oop): a type-bound call through a CLASS dummy in device code fails to link (__GET_TYPE_BOUND_PROC)
!
! - toolchains and modes that fail: cce19 (CCE 19.0.0: copy, unified), cce20 (CCE 20.0.2: copy, unified), cce21 (CCE 21.0.3: copy,
! unified), cce21_4 (CCE 21.0.4: copy, unified); -O2
! - build: ftn -fopenmp -O2 (module load cce/<v> craype-accel-amd-gfx942 rocm/<r>; OpenACC: ftn -h acc)
! - failure: rejected (link_undefined_symbol, the program's own object); OMP_TARGET_OFFLOAD=mandatory
! - observed: `lld: error: undefined symbol: __GET_TYPE_BOUND_PROC` at the device link, every CCE release, both modes: dynamic
! dispatch of a binding of an abstract type, in a loop, through an override that calls its parent's binding, through a
! polymorphic pointer, and a binding that calls another binding of its CLASS dummy
! - expected: compiles; `r1= 29` (area of a 3x3 square plus a 4x5 rectangle)
! - rule: every type-bound procedure the region accesses is in a declare target directive (5.2 §1.2.6 p.19 l.1-3; checked by the
! rules, typebound-declaretarget-001), which is all OpenMP asks of a derived type used in a target region
! - same-compiler control: the same program with the region calling the binding on the TYPE objects, q%area() + rr%area(), instead
! of area_of's CLASS(shape) dummy (controls/poly-dispatch-static.f90, one change): correct (check=pass) on CCE 19, 20, 21.0.3
! and 21.0.4 in both modes, in the stored run and the gate's four environments a-d with (c) on another node
! (results/oop/probe/ctl2.*.poly-dispatch-static.*.jsonl)
! - other families: AFAR correct on all five; GCC 16.2 compiles them and aborts at run time (gcc-polymorphic-dispatch-abort.f90);
! OpenACC's routine form (unspecified behaviour) fails the same way on CCE with ftn-7066 'Unsupported accelerator code error:
! Calls -- __GET_TYPE_BOUND_PROC'
! - gate and confirmer: 40 cells, 40 confirmed in the gate's four environments (a-d; results/oop/main/gate_reruns*.jsonl);
! confirmer (results/oop/main/confirm.jsonl): compiler_bug (R10b-own-link-or-hang) 40
! - programs (5): oop-poly-dispatch, oop-poly-dispatch-loop, oop-poly-parent-call, oop-poly-pointer, oop-tbp-nested-call
! (offload/engine/oop_gen.py; this file is the first one)
! - legality: for the cce cells: the rules (offload.engine.rules, with the fortran-oop restrictions) and AFAR's flang front end
! (-fsyntax-only) and NVHPC 26.9 nvfortran (compile only) (tools/campaigns/oop.py legality, results/oop/main/legality.json)
module oop_m
implicit none
integer, parameter :: n = 64
type, abstract :: shape
integer :: id = 0
contains
procedure(area_if), deferred :: area
end type shape
abstract interface
integer function area_if(s)
import :: shape
class(shape), intent(in) :: s
end function area_if
end interface
type, extends(shape) :: sq
integer :: side = 0
contains
procedure :: area => sq_area
end type sq
type, extends(shape) :: rect
integer :: w = 0, h = 0
contains
procedure :: area => rect_area
end type rect
contains
integer function sq_area(s)
!$omp declare target
class(sq), intent(in) :: s
sq_area = s%side * s%side
end function sq_area
integer function rect_area(s)
!$omp declare target
class(rect), intent(in) :: s
rect_area = s%w * s%h
end function rect_area
integer function area_of(s)
!$omp declare target
class(shape), intent(in) :: s
area_of = s%area()
end function area_of
end module oop_m
program oop
use omp_lib
use oop_m
implicit none
integer :: host_flag
logical :: ok
integer :: r1
type(sq) :: q
type(rect) :: rr
host_flag = 1
!$omp target map(from: host_flag)
host_flag = merge(1, 0, omp_is_initial_device())
!$omp end target
q%side = 3
rr%w = 4
rr%h = 5
!$omp target map(tofrom: q, rr) map(from: r1)
r1 = area_of(q) + area_of(rr)
!$omp end target
ok = .true.
ok = ok .and. (r1 == 29)
print '(a,i0)', 'r1= ', r1
print '(a,i0,a,a)', 'RESULT ran_on_host=', host_flag, ' check=', merge('pass', 'fail', ok)
end program oop
Something to add? Dispute its legality · Report it fixed in a newer release · Report a mistake on this page
Expected and observed
Observed where it behaves incorrectly
Warning: Headers and libraries from cray-libsci/25.03.0 will be ignored because depends on PE_MPICH which is unavailable.. lld: error: undefined symbol: __GET_TYPE_BOUND_PROC >>> referenced by <dir>:(oop_$ck_L82_2) >>> referenced by <dir>:(oop_$ck_L82_2)
What the specification requires
The specification text this program relies on and the compiler is expected to support.
OpenMP 5.2 §1.2.6 p.19 l.1-3
Evidence
Same compiler, one change
- the same program; the binding is called on the TYPE objects (statically resolved) instead of through a CLASS dummy: not run yet
Control program
! control for oop-poly-dispatch: the same program; one change: the region calls the binding on the TYPE objects ! (statically resolved) instead of through area_of's CLASS(shape) dummy ! fortran-oop poly/dispatch (OpenMP 5.2, free-form Fortran): ! dynamic dispatch of a deferred binding (abstract type) through a CLASS(shape) dummy on the ! device ! spec: OpenMP 5.2 §1.2.6 p.19 l.1-3 (type-bound procedures accessed in a target region appear in a ! declare target directive); OpenMP 5.2 §7.8.1 p.205-207 (declare target, procedures) ! legality: defined ! expected (computed by compliance/oop_gen.py): r1= 29 module oop_m implicit none integer, parameter :: n = 64 type, abstract :: shape integer :: id = 0 contains procedure(area_if), deferred :: area end type shape abstract interface integer function area_if(s) import :: shape class(shape), intent(in) :: s end function area_if end interface type, extends(shape) :: sq integer :: side = 0 contains procedure :: area => sq_area end type sq type, extends(shape) :: rect integer :: w = 0, h = 0 contains procedure :: area => rect_area end type rect contains integer function sq_area(s) !$omp declare target class(sq), intent(in) :: s sq_area = s%side * s%side end function sq_area integer function rect_area(s) !$omp declare target class(rect), intent(in) :: s rect_area = s%w * s%h end function rect_area integer function area_of(s) !$omp declare target class(shape), intent(in) :: s area_of = s%area() end function area_of end module oop_m program oop use omp_lib use oop_m implicit none integer :: host_flag logical :: ok integer :: r1 type(sq) :: q type(rect) :: rr host_flag = 1 !$omp target map(from: host_flag) host_flag = merge(1, 0, omp_is_initial_device()) !$omp end target q%side = 3 rr%w = 4 rr%h = 5 !$omp target map(tofrom: q, rr) map(from: r1) r1 = q%area() + rr%area() !$omp end target ok = .true. ok = ok .and. (r1 == 29) print '(a,i0)', 'r1= ', r1 print '(a,i0,a,a)', 'RESULT ran_on_host=', host_flag, ' check=', merge('pass', 'fail', ok) end program oop
Other compilers run it correctly
AFAR 24.3.0