# Copyright 2023-2024 Free Software Foundation, Inc. # Copyright (C) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. # This file is part of GDB. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Test that GDB sees a SIGFPE when an ALU exception is triggered on an # AMDGPU device. load_lib rocm.exp require allow_hip_tests standard_testfile .cpp if {[build_executable "failed to prepare $testfile" $testfile $srcfile \ {debug hip}]} { return } # The Windows runtime doesn't support passing exceptions yet. We use # this variable to kfail the first timeout FAIL, and skip testing # passing exception again afterwards, to avoid wasting time with # multiple timeouts. set supports_passing_exceptions 1 proc test_passing_exception {} { set msg "pass exception to runtime" if {$::supports_passing_exceptions} { setup_kfail "*-*-mingw*" "AIRUNTIME=35" gdb_test_multiple "continue" $msg { -re -wrap "HSA_STATUS_ERROR_EXCEPTION.*received signal SIGABRT, Aborted.*" { pass $gdb_test_name } timeout { set ::supports_passing_exceptions 0 fail "$gdb_test_name (timeout)" } } } else { unsupported $msg } } proc do_test { exception_name precise_alu_exceptions_supported } { set location_where_excp_reported {} with_test_prefix "$exception_name, precise=off" { clean_restart $::binfile with_rocm_gpu_lock { gdb_test_no_output "set args $exception_name" if ![runto_main] { return } gdb_breakpoint "enable_alu_exceptions" "allow-pending" gdb_continue_to_breakpoint "enable_alu_exceptions" enable_alu_exception $exception_name set bp_line [gdb_get_line_number "Break here for $exception_name"] gdb_breakpoint $bp_line \ "break before exception" gdb_continue_to_breakpoint "$exception_name" set pc "invalid" gdb_test_multiple "display/x \$pc" "" { -re "pc = ($::hex)" { set pc $expect_out(1,string) exp_continue } -re -wrap "" { gdb_assert {$pc != "invalid"} $gdb_test_name } } set iter 0 gdb_test_multiple "si" "step until exception" { -re -wrap "Thread $::decimal \[^\r\n]*received signal SIGFPE, Arithmetic exception\..*" { pass $gdb_test_name } -re -wrap ".*pc = ($::hex).*" { incr iter set pc $expect_out(1,string) if {$iter < 150} { send_gdb "si\n" exp_continue } else { fail $gdb_test_name } } } gdb_test "x/2i $pc" \ [multi_line \ " $pc \[^\r\n\]*" \ "=> $::hex \[^\r\n\]*"] \ "stopped after fault" # Capture where we are in the shader program, so we can later ensure # that when the program runs free (i.e. not single stepping) and precise # ALU exceptions reporting is enabled, the stop location is the same. gdb_test_multiple "x/i \$pc" "capture exception_location" { -re -wrap "=> $::hex <(\[a-zA-Z_+0-9\]*)>:.*" { set location_where_excp_reported $expect_out(1,string) pass $gdb_test_name } } test_passing_exception } } if {!$precise_alu_exceptions_supported} { unsupported "$exception_name, precise=on" return } # Re run the test, but this time do not single step through the program. # Instead continue and check that we stopped at the same point. with_test_prefix "$exception_name, precise=on" { clean_restart $::binfile with_rocm_gpu_lock { gdb_test_no_output "set args $exception_name" gdb_test_no_output "set amdgpu precise-alu-exceptions on" if ![runto_main] { return } gdb_breakpoint "enable_alu_exceptions" "allow-pending" gdb_continue_to_breakpoint "enable_alu_exceptions" enable_alu_exception $exception_name gdb_test "continue" "Thread $::decimal \[^\r\n]*received signal SIGFPE, Arithmetic exception\..*" gdb_test "x/i \$pc" "=> $::hex <[string_to_regexp $location_where_excp_reported]>:.*" "precise location" test_passing_exception } } } set precise_alu_exceptions_supported false with_test_prefix "check_precise_alu_support" { clean_restart $::binfile with_rocm_gpu_lock { gdb_test_no_output "set amdgpu precise-alu-exceptions on" if ![runto_main] { return } gdb_test_multiple "show amdgpu precise-alu-exceptions" "" { -re -wrap "AMDGPU precise ALU exceptions reporting is on \\(currently (enabled|disabled)\\).*" { if {$expect_out(1,string) == "enabled"} { set precise_alu_exceptions_supported true } pass $gdb_test_name } } } } foreach test {invalid denorm overflow underflow inexact float_div0 int_div0} { do_test $test $precise_alu_exceptions_supported }