CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
283 lines
9.6 KiB
Plaintext
283 lines
9.6 KiB
Plaintext
# Copyright (C) 2025 Free Software Foundation, Inc.
|
|
# Copyright (C) 2025 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 <http://www.gnu.org/licenses/>.
|
|
|
|
# Check the GDB support for HIP built-in variables.
|
|
|
|
load_lib rocm.exp
|
|
|
|
require allow_hip_tests
|
|
# The debug behavior this test checks is not reliable with
|
|
# link-time optimization, so skip it for -flto builds.
|
|
require no_lto
|
|
|
|
standard_testfile .cpp
|
|
|
|
if {[prepare_for_testing "failed to prepare ${testfile}" \
|
|
$testfile $srcfile {debug hip}]} {
|
|
return -1
|
|
}
|
|
|
|
# A mapping from built-in variable names to reference variable names
|
|
# in the test program that hold the correct values.
|
|
set reference_for(threadIdx) thread_idx
|
|
set reference_for(blockIdx) group_idx
|
|
set reference_for(blockDim) group_size
|
|
set reference_for(gridDim) grid_size
|
|
|
|
# These globals will have the reference values from the test
|
|
# program captured. See "record_reference_values" procedure.
|
|
set thread_idx_x ""
|
|
set thread_idx_y ""
|
|
set thread_idx_z ""
|
|
set group_idx_x ""
|
|
set group_idx_y ""
|
|
set group_idx_z ""
|
|
set group_size_x ""
|
|
set group_size_y ""
|
|
set group_size_z ""
|
|
set grid_size_x ""
|
|
set grid_size_y ""
|
|
set grid_size_z ""
|
|
set wave_size ""
|
|
|
|
# Record the reference variables values into the corresponding
|
|
# global variables.
|
|
proc record_reference_values {} {
|
|
global reference_for
|
|
foreach var3d {threadIdx blockIdx blockDim gridDim} {
|
|
set ref $reference_for($var3d)
|
|
global ${ref}_x
|
|
global ${ref}_y
|
|
global ${ref}_z
|
|
set ${ref}_x [get_integer_valueof ${ref}_x INVALID]
|
|
set ${ref}_y [get_integer_valueof ${ref}_y INVALID]
|
|
set ${ref}_z [get_integer_valueof ${ref}_z INVALID]
|
|
}
|
|
global wave_size
|
|
set wave_size [get_integer_valueof wave_size INVALID]
|
|
}
|
|
|
|
# Compare the value of built-in variables against the recorded
|
|
# reference values from the program.
|
|
proc check_builtin_variables_values {} {
|
|
global reference_for
|
|
foreach var3d {threadIdx blockIdx blockDim gridDim} {
|
|
set ref $reference_for($var3d)
|
|
global ${ref}_x
|
|
global ${ref}_y
|
|
global ${ref}_z
|
|
|
|
# Evaluate values held in ${ref}_* names.
|
|
set num_x [set ${ref}_x]
|
|
set num_y [set ${ref}_y]
|
|
set num_z [set ${ref}_z]
|
|
|
|
gdb_test "p $var3d" "= {x = $num_x, y = $num_y, z = $num_z}" \
|
|
"$var3d == $ref"
|
|
gdb_test "p ${var3d}.x" "$num_x" "${var3d}.x == $num_x"
|
|
gdb_test "p ${var3d}.y" "$num_y" "${var3d}.y == $num_y"
|
|
gdb_test "p ${var3d}.z" "$num_z" "${var3d}.z == $num_z"
|
|
}
|
|
global wave_size
|
|
gdb_test "p warpSize" "= $wave_size" "warpSize == $wave_size"
|
|
}
|
|
|
|
# Check the definitions, sizes, and alignments of the built-in variables.
|
|
proc check_builtin_variables_definitions {} {
|
|
# type = struct __gdb_hip_builtin_vec {
|
|
# uint32_t x;
|
|
# uint32_t y;
|
|
# uint32_t z;
|
|
# }
|
|
set header "struct __gdb_hip_builtin_vec \\{\r\n"
|
|
set x_def "\[ \t\]+uint32_t x;\r\n"
|
|
set y_def "\[ \t\]+uint32_t y;\r\n"
|
|
set z_def "\[ \t\]+uint32_t z;\r\n"
|
|
set trailer "\\}"
|
|
foreach var3d {threadIdx blockIdx blockDim gridDim} {
|
|
gdb_test "ptype $var3d" \
|
|
"${header}${x_def}${y_def}${z_def}${trailer}" \
|
|
"type of $var3d"
|
|
}
|
|
gdb_test "ptype warpSize" "unsigned int" "type of warpSize"
|
|
|
|
foreach var {threadIdx blockIdx blockDim gridDim warpSize} {
|
|
gdb_test "p sizeof($var)" " = 12" "size of $var"
|
|
}
|
|
|
|
foreach var {threadIdx blockIdx blockDim gridDim warpSize} {
|
|
gdb_test "p alignof(decltype($var))" " = 4" "alignment of $var"
|
|
}
|
|
}
|
|
|
|
# Check if the built-in variables are unavailable.
|
|
proc check_builtin_variables_unavailable {} {
|
|
foreach var {threadIdx blockIdx blockDim gridDim warpSize} {
|
|
gdb_test "p $var" " = <unavailable>" "$var not available yet"
|
|
}
|
|
}
|
|
|
|
# Check if the built-in variables cannot be found.
|
|
proc check_builtin_variables_notfound {} {
|
|
foreach var {threadIdx blockIdx blockDim gridDim warpSize} {
|
|
gdb_test "p $var" "No symbol \"$var\" in current context\." \
|
|
"$var not found"
|
|
}
|
|
}
|
|
|
|
# Tests cases:
|
|
#
|
|
# - No built-in must be found when host side lang is c++.
|
|
# - No built-in must be available when host side lang is hip.
|
|
#
|
|
# - Setting conditional breakpoint in device code based on built-ins,
|
|
# while still debugging on the host side, must work when lang=hip.
|
|
#
|
|
# Rest of the cases are happening when debugging the device code.
|
|
#
|
|
# - The definitions and values of the built-ins must be available when:
|
|
# - with debug info, lang=hip, at kern() level that references the built-ins.
|
|
# - with debug info, lang=hip, at inner_func1() level without any references
|
|
# to the built-ins.
|
|
#
|
|
# - The value of a shadowed built-in, at innfer_func2() level, must reflect
|
|
# the local value (with debug info, lang=hip)
|
|
# - without debug info, lang=hip, the shadowed variable shall go away and once
|
|
# again all the built-in definitions and values must be available.
|
|
#
|
|
# - The definitions and values of the built-ins must be available when:
|
|
# - without debug info, lang=hip, at kern() level that references the
|
|
# built-ins.
|
|
# - without debug info, lang=hip, at inner_func1() level without any
|
|
# references to the built-ins.
|
|
#
|
|
# - The built-ins mustn't be found when lang=c++, even if debugging the
|
|
# device code.
|
|
|
|
with_rocm_gpu_lock {
|
|
if ![runto_main] {
|
|
return -1
|
|
}
|
|
|
|
set dw_lang [compiler_dwarf_language]
|
|
if {$dw_lang != "hip" && $dw_lang != "cpp"} {
|
|
return -1
|
|
}
|
|
|
|
with_test_prefix "before running program" {
|
|
if {$dw_lang == "cpp"} {
|
|
check_builtin_variables_notfound
|
|
|
|
# Set the language to HIP. This guarantees that the
|
|
# conditions of (pending) breakpoints in the device code
|
|
# will be parsed and evaluated in HIP context.
|
|
gdb_test "set language hip" \
|
|
"Warning: the current language does not match this frame\." \
|
|
"change the language to HIP"
|
|
}
|
|
|
|
# Now that the language is HIP, but we're on CPU side,
|
|
# the HIP variables must be "unavailable".
|
|
check_builtin_variables_unavailable
|
|
}
|
|
|
|
# Set a breakpoint in device code, and set a condition to select a wave
|
|
# with coordinates != (0, 0, 0).
|
|
set bp_line [gdb_get_line_number "Break here."]
|
|
gdb_breakpoint \
|
|
[concat "$bp_line if " \
|
|
"threadIdx.x == 7 && threadIdx.y == 3 && threadIdx.z == 1 " \
|
|
"&& blockIdx.x == 2 && blockIdx.y == 1 && blockIdx.z == 3" ] \
|
|
"allow-pending"
|
|
gdb_continue_to_breakpoint "kern"
|
|
|
|
# After hitting the breakpoint, record the reference values.
|
|
record_reference_values
|
|
|
|
with_test_prefix "with debug info" {
|
|
with_test_prefix "kernel()" {
|
|
check_builtin_variables_definitions
|
|
check_builtin_variables_values
|
|
}
|
|
|
|
# Check again after stepping into inner_func1(), with debug info.
|
|
gdb_test "step" "inner_func1 \\(\\) at.*" \
|
|
"step into inner_func1() for the first time"
|
|
with_test_prefix "inner_func1()" {
|
|
check_builtin_variables_definitions
|
|
check_builtin_variables_values
|
|
}
|
|
# Get out of the inner_func1(), right onto the verge of another call.
|
|
gdb_test "next" "kern \\(\\) at\[^\r\n\]*\r\n.*inner_func2 \\(\\).*" \
|
|
"step out of inner_func1()"
|
|
|
|
# Get into inner_func2() with its own local blockIdx variable.
|
|
gdb_test "step" "inner_func2 \\(\\) at.*" \
|
|
"step into inner_func2() with its own blockIdx"
|
|
# Accept landing on either the "return;" statement or the
|
|
# closing brace. At -O0 Clang emits a separate line entry
|
|
# for the explicit "return;", so "next" lands there. Under
|
|
# __attribute__((optnone)) (which we use to keep the local
|
|
# blockIdx observable at -O1/-O2/-O3) Clang merges the line
|
|
# entry of the "return;" with the function's closing brace,
|
|
# so "next" lands on the brace instead. Either is fine for
|
|
# this test -- the point is just to step past the local
|
|
# initialization before reading blockIdx.
|
|
gdb_test "next" "$::decimal\[ \t\]+(return;|\})" \
|
|
"let the initialization happen"
|
|
gdb_test "p/x blockIdx" "0x42424242" \
|
|
"local blockIdx shadowing the built-in"
|
|
}
|
|
|
|
# Now remove the debug info and check everything.
|
|
gdb_test_no_output "nosharedlibrary" "no debug info in inner_func2()"
|
|
with_test_prefix "without debug info" {
|
|
with_test_prefix "inner_func2()" {
|
|
check_builtin_variables_definitions
|
|
check_builtin_variables_values
|
|
}
|
|
|
|
# Put the debug info back, so we can "next" out of this function.
|
|
gdb_test "sharedlibrary" ".*" "put debug info back in inner_func2()"
|
|
# Get out of the inner_func2(), right onto the verge of another call.
|
|
gdb_test "next" "kern \\(\\) at\[^\r\n\]*\r\n.*inner_func1 \\(\\).*" \
|
|
"step out of inner_func2()"
|
|
|
|
# Remove the debug info again and repeat the checks for "kern()".
|
|
gdb_test_no_output "nosharedlibrary" "no debug info at kern() level"
|
|
with_test_prefix "kernel()" {
|
|
check_builtin_variables_definitions
|
|
check_builtin_variables_values
|
|
}
|
|
|
|
# Check again after stepping into inner_func1(), without debug info.
|
|
gdb_test "step" "Cannot find bounds of current function" \
|
|
"step into inner_func1() for the second time"
|
|
with_test_prefix "inner_func1()" {
|
|
check_builtin_variables_definitions
|
|
check_builtin_variables_values
|
|
}
|
|
|
|
gdb_test_no_output "set language c++" \
|
|
"change the language to other than HIP"
|
|
with_test_prefix "another language (c++)" {
|
|
check_builtin_variables_notfound
|
|
}
|
|
}
|
|
}
|