@@ -1988,32 +1988,41 @@ tp_array_compar_descending (const thread_info_ref &a, const thread_info_ref &b)
1988
1988
/* See gdbthread.h. */
1989
1989
1990
1990
void
1991
- thread_try_catch_cmd ( thread_info * thr , std :: optional < int > ada_task ,
1992
- const char * cmd , int from_tty ,
1993
- const qcs_flags & flags )
1991
+ thr_lane_try_catch_cmd ( bool lane_mode , thread_info * thr , int lane ,
1992
+ std :: optional < int > ada_task , const char * cmd ,
1993
+ int from_tty , const qcs_flags & flags )
1994
1994
{
1995
1995
gdb_assert (is_current_thread (thr ));
1996
1996
1997
1997
/* The thread header is computed before running the command since
1998
- the command can change the inferior, which is not permitted
1999
- by thread_target_id_str. */
2000
- std ::string thr_header ;
2001
- if (ada_task .has_value ())
2002
- thr_header = string_printf (_ ("\nTask ID %d:\n" ), * ada_task );
1998
+ the command can change the inferior, which is not permitted by
1999
+ thread_target_id_str. */
2000
+ std ::string header ;
2001
+
2002
+ if (lane_mode )
2003
+ header
2004
+ = string_printf (_ ("\nLane %d (%s):\n" ), lane ,
2005
+ target_lane_to_str (thr , lane ).c_str ());
2006
+ else if (ada_task .has_value ())
2007
+ header = string_printf (_ ("\nTask ID %d:\n" ), * ada_task );
2003
2008
else
2004
- thr_header = string_printf ( _ ( "\nThread %s (%s):\n" ),
2005
- print_thread_id (thr ),
2006
- thread_target_id_str (thr ).c_str ());
2009
+ header
2010
+ = string_printf ( _ ( "\nThread %s (%s):\n" ), print_thread_id (thr ),
2011
+ thread_target_id_str (thr ).c_str ());
2007
2012
2008
2013
try
2009
2014
{
2015
+ /* Switch to the lane on which the command is executed. */
2016
+ thr -> set_current_simd_lane (lane );
2017
+
2010
2018
std ::string cmd_result ;
2011
2019
execute_command_to_string
2012
2020
(cmd_result , cmd , from_tty , gdb_stdout -> term_out ());
2021
+
2013
2022
if (!flags .silent || cmd_result .length () > 0 )
2014
2023
{
2015
2024
if (!flags .quiet )
2016
- gdb_printf ( "%s" , thr_header .c_str ());
2025
+ gdb_puts ( header .c_str ());
2017
2026
gdb_printf ("%s" , cmd_result .c_str ());
2018
2027
}
2019
2028
}
@@ -2022,7 +2031,8 @@ thread_try_catch_cmd (thread_info *thr, std::optional<int> ada_task,
2022
2031
if (!flags .silent )
2023
2032
{
2024
2033
if (!flags .quiet )
2025
- gdb_printf ("%s" , thr_header .c_str ());
2034
+ gdb_puts (header .c_str ());
2035
+
2026
2036
if (flags .cont )
2027
2037
gdb_printf ("%s\n" , ex .what ());
2028
2038
else
@@ -2049,7 +2059,7 @@ using qcs_flag_option_def
2049
2059
static const gdb ::option ::option_def thr_qcs_flags_option_defs [] = {
2050
2060
qcs_flag_option_def {
2051
2061
"q" , [] (qcs_flags * opt ) { return & opt -> quiet ; },
2052
- N_ ("Disables printing the thread information." ),
2062
+ N_ ("Disables printing the thread or lane information." ),
2053
2063
},
2054
2064
2055
2065
qcs_flag_option_def {
@@ -2135,7 +2145,8 @@ thread_apply_all_command (const char *cmd, int from_tty)
2135
2145
2136
2146
for (thread_info_ref & thr : thr_list_cpy )
2137
2147
if (switch_to_thread_if_alive (thr .get ()))
2138
- thread_try_catch_cmd (thr .get (), {}, cmd , from_tty , flags );
2148
+ thr_lane_try_catch_cmd (false, thr .get (), 0 , {}, cmd , from_tty ,
2149
+ flags );
2139
2150
}
2140
2151
}
2141
2152
@@ -2297,10 +2308,205 @@ thread_apply_command (const char *tidlist, int from_tty)
2297
2308
continue ;
2298
2309
}
2299
2310
2300
- thread_try_catch_cmd (tp , {}, cmd , from_tty , flags );
2311
+ thr_lane_try_catch_cmd (false, tp , 0 , {}, cmd , from_tty , flags );
2312
+ }
2313
+ }
2314
+
2315
+ /* Create an option_def_group for the "lane apply" / "lane apply all"
2316
+ options, with FLAGS and IL as context. */
2317
+
2318
+ static inline std ::array < gdb ::option ::option_def_group , 2 >
2319
+ make_lane_apply_options_def_group (qcs_flags * flags ,
2320
+ info_lanes_opts * il )
2321
+ {
2322
+ return {{
2323
+ { {thr_qcs_flags_option_defs }, flags },
2324
+ { {info_lanes_option_defs }, il },
2325
+ }};
2326
+ }
2327
+
2328
+ /* Apply a GDB command to a list of lanes of the current thread. List
2329
+ syntax is a whitespace separated list of numbers, or ranges, or the
2330
+ keyword `all'. Ranges consist of two numbers separated by a
2331
+ hyphen. Examples:
2332
+
2333
+ lane apply 1 2 7 4 backtrace Apply 'backtrace' cmd to lanes 1,2,7,4
2334
+ lane apply 2-7 9 p foo Apply 'p foo' cmd to lanes 2->7 & 9
2335
+ lane apply all x/i $lane_pc Apply 'x/i $lane_pc' cmd to all lanes.
2336
+ */
2337
+
2338
+ static void
2339
+ lane_apply_all_command (const char * cmd , int from_tty )
2340
+ {
2341
+ qcs_flags flags ;
2342
+ info_lanes_opts il_opts ;
2343
+
2344
+ auto group = make_lane_apply_options_def_group (& flags , & il_opts );
2345
+ gdb ::option ::process_options
2346
+ (& cmd , gdb ::option ::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND , group );
2347
+
2348
+ validate_flags_qcs ("lane apply all" , & flags );
2349
+
2350
+ if (cmd == NULL || * cmd == '\000' )
2351
+ error (_ ("Please specify a command at the end of 'lane apply all'" ));
2352
+
2353
+ if (inferior_ptid == null_ptid )
2354
+ return ;
2355
+
2356
+ thread_info * thr = inferior_thread ();
2357
+ scoped_restore_current_simd_lane restore_lane (thr );
2358
+ scoped_restore_selected_frame restore_frame ;
2359
+
2360
+ gdbarch * arch = target_thread_architecture (thr -> ptid );
2361
+ int lane_count = gdbarch_supported_lanes_count (arch , thr );
2362
+ int lane_used_count = gdbarch_used_lanes_count (arch , thr );
2363
+
2364
+ for (int lane = 0 ; lane < lane_count ; ++ lane )
2365
+ {
2366
+ if (!should_print_lane ("" , thr , lane , il_opts , lane_used_count ))
2367
+ continue ;
2368
+
2369
+ frame_info_ptr curr_frame = get_current_frame ();
2370
+ select_frame (curr_frame );
2371
+
2372
+ thr_lane_try_catch_cmd (true, thr , lane , {}, cmd , from_tty , flags );
2373
+ }
2374
+ }
2375
+
2376
+ /* Completer for the "lane apply ..." commands. */
2377
+
2378
+ static void
2379
+ lane_apply_completer (completion_tracker & tracker , const char * text )
2380
+ {
2381
+ const auto group = make_lane_apply_options_def_group (nullptr , nullptr );
2382
+ if (gdb ::option ::complete_options
2383
+ (tracker , & text , gdb ::option ::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND , group ))
2384
+ return ;
2385
+
2386
+ complete_nested_command_line (tracker , text );
2387
+ }
2388
+
2389
+ /* Completer for "lane apply [ID list]". */
2390
+
2391
+ static void
2392
+ lane_apply_command_completer (cmd_list_element * ignore ,
2393
+ completion_tracker & tracker ,
2394
+ const char * text , const char * /*word*/ )
2395
+ {
2396
+ /* Don't leave this to complete_options because there's an early
2397
+ return below. */
2398
+ tracker .set_use_custom_word_point (true);
2399
+
2400
+ number_or_range_parser parser (text );
2401
+
2402
+ try
2403
+ {
2404
+ while (!parser .finished ())
2405
+ {
2406
+ /* Call for effect. */
2407
+ parser .get_number ();
2408
+
2409
+ if (parser .in_range ())
2410
+ parser .skip_range ();
2411
+ }
2412
+ }
2413
+ catch (const gdb_exception_error & ex )
2414
+ {
2415
+ /* get_number throws if it parses a negative number, for
2416
+ example. But a seemingly negative number may be the start of
2417
+ an option instead. */
2418
+ }
2419
+
2420
+ const char * cmd = parser .cur_tok ();
2421
+
2422
+ if (cmd == text )
2423
+ {
2424
+ /* No lane ID list yet. */
2425
+ return ;
2301
2426
}
2427
+
2428
+ /* Check if we're past a valid lane ID already. */
2429
+ if (parser .finished ()
2430
+ && cmd > text && !isspace (cmd [-1 ]))
2431
+ return ;
2432
+
2433
+ /* We're past the lane ID list, advance word point. */
2434
+ tracker .advance_custom_word_point_by (cmd - text );
2435
+ text = cmd ;
2436
+
2437
+ lane_apply_completer (tracker , text );
2302
2438
}
2303
2439
2440
+ /* Completer for "lane apply all". */
2441
+
2442
+ static void
2443
+ lane_apply_all_command_completer (cmd_list_element * ignore ,
2444
+ completion_tracker & tracker ,
2445
+ const char * text , const char * word )
2446
+ {
2447
+ lane_apply_completer (tracker , text );
2448
+ }
2449
+
2450
+ /* Implementation of the "lane apply" command. */
2451
+
2452
+ static void
2453
+ lane_apply_command (const char * id_list , int from_tty )
2454
+ {
2455
+ qcs_flags flags ;
2456
+ info_lanes_opts il_opts ;
2457
+ const char * cmd = nullptr ;
2458
+ number_or_range_parser parser ;
2459
+
2460
+ if (id_list == nullptr || * id_list == '\000' )
2461
+ error (_ ("Please specify a lane ID list" ));
2462
+
2463
+ parser .init (id_list );
2464
+ while (!parser .finished ())
2465
+ parser .get_number ();
2466
+
2467
+ cmd = parser .cur_tok ();
2468
+
2469
+ auto group = make_lane_apply_options_def_group (& flags , & il_opts );
2470
+ gdb ::option ::process_options
2471
+ (& cmd , gdb ::option ::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND , group );
2472
+
2473
+ validate_flags_qcs ("lane apply" , & flags );
2474
+
2475
+ if (* cmd == '\0' )
2476
+ error (_ ("Please specify a command following the lane ID list" ));
2477
+
2478
+ if (id_list == cmd || isdigit (cmd [0 ]))
2479
+ invalid_thread_id_error (cmd );
2480
+
2481
+ thread_info * thr = inferior_thread ();
2482
+ scoped_restore_current_simd_lane restore_lane (thr );
2483
+ scoped_restore_selected_frame restore_frame ;
2484
+
2485
+ gdbarch * arch = target_thread_architecture (thr -> ptid );
2486
+ int lane_count = gdbarch_supported_lanes_count (arch , thr );
2487
+ int lane_used_count = gdbarch_used_lanes_count (arch , thr );
2488
+
2489
+ parser .init (id_list );
2490
+ while (!parser .finished ())
2491
+ {
2492
+ int lane = parser .get_number ();
2493
+
2494
+ if (lane >= lane_count )
2495
+ {
2496
+ /* Be consistent with "thread apply" and warn. */
2497
+ warning (_ ("Lane %d does not exist on this thread." ), lane );
2498
+ continue ;
2499
+ }
2500
+
2501
+ if (!should_print_lane ("" , thr , lane , il_opts , lane_used_count ))
2502
+ continue ;
2503
+
2504
+ frame_info_ptr curr_frame = get_current_frame ();
2505
+ select_frame (curr_frame );
2506
+
2507
+ thr_lane_try_catch_cmd (true, thr , lane , {}, cmd , from_tty , flags );
2508
+ }
2509
+ }
2304
2510
2305
2511
/* Implementation of the "taas" command. */
2306
2512
@@ -2779,6 +2985,7 @@ void
2779
2985
_initialize_thread ()
2780
2986
{
2781
2987
static struct cmd_list_element * thread_apply_list = NULL ;
2988
+ static struct cmd_list_element * lane_apply_list = NULL ;
2782
2989
cmd_list_element * c ;
2783
2990
2784
2991
const auto info_threads_opts = make_info_threads_options_def_group (nullptr );
@@ -2871,6 +3078,48 @@ THREAD_APPLY_OPTION_HELP),
2871
3078
& thread_apply_list );
2872
3079
set_cmd_completer_handle_brkchars (c , thread_apply_all_command_completer );
2873
3080
3081
+ /* lane apply ... commands. */
3082
+ {
3083
+ #define LANE_APPLY_OPTION_HELP "\
3084
+ Prints lane number and target system's lane id\n\
3085
+ followed by COMMAND output.\n\
3086
+ \n\
3087
+ By default, an error raised during the execution of COMMAND\n\
3088
+ aborts \"lane apply\".\n\
3089
+ \n\
3090
+ Options:\n\
3091
+ %OPTIONS%"
3092
+
3093
+ const auto lane_apply_opts = make_lane_apply_options_def_group (nullptr ,
3094
+ nullptr );
3095
+
3096
+ static std ::string lane_apply_help
3097
+ = gdb ::option ::build_help (_ ("\
3098
+ Apply a command to a list of lanes.\n\
3099
+ Usage: lane apply ID... [OPTION]... COMMAND\n\
3100
+ ID is a space-separated list of IDs of lanes to apply COMMAND on.\n"
3101
+ LANE_APPLY_OPTION_HELP ),
3102
+ lane_apply_opts );
3103
+
3104
+ c = add_prefix_cmd ("apply" , class_run , lane_apply_command ,
3105
+ lane_apply_help .c_str (),
3106
+ & lane_apply_list , 1 , & lane_cmd_list );
3107
+ set_cmd_completer_handle_brkchars (c , lane_apply_command_completer );
3108
+
3109
+ static std ::string lane_apply_all_help
3110
+ = gdb ::option ::build_help (_ ("\
3111
+ Apply a command to all lanes.\n\
3112
+ \n\
3113
+ Usage: lane apply all [OPTION]... COMMAND\n"
3114
+ LANE_APPLY_OPTION_HELP ),
3115
+ lane_apply_opts );
3116
+
3117
+ c = add_cmd ("all" , class_run , lane_apply_all_command ,
3118
+ lane_apply_all_help .c_str (),
3119
+ & lane_apply_list );
3120
+ set_cmd_completer_handle_brkchars (c , lane_apply_all_command_completer );
3121
+ }
3122
+
2874
3123
c = add_com ("taas" , class_run , taas_command , _ ("\
2875
3124
Apply a command to all threads (ignoring errors and empty output).\n\
2876
3125
Usage: taas [OPTION]... COMMAND\n\
0 commit comments