/* This testcase is part of GDB, the GNU debugger.
 
-   Copyright 1993-2022 Free Software Foundation, Inc.
+   Copyright 2022 Free Software Foundation, Inc.
 
    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
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#if defined __x86_64__
-# define ASM_REG "rax"
-#elif defined __i386__
-# define ASM_REG "eax"
-#elif defined __powerpc64__
-# define ASM_REG "r9"
-#else
-# error "port me"
-#endif
-
-/* A class small enough that it fits in a register.  */
-struct small
-{
-  int x;
-  int method ();
-};
-
-int
-small::method ()
-{
-  return x + 5;
-}
-
-int
-register_class ()
-{
-  /* Given the use of the GNU register-asm local variables extension,
-     the compiler puts this variable in a register.  This means that
-     GDB can't call any methods for this variable, which is what we
-     want to test.  */
-  register small v asm (ASM_REG);
-
-  int i;
-
-  /* Perform a computation sufficiently complicated that optimizing
-     compilers won't optimize out the variable.  If some compiler
-     constant-folds this whole loop, maybe using a parameter to this
-     function here would help.  */
-  v.x = 0;
-  for (i = 0; i < 13; ++i)
-    v.x += i;
-  --v.x; /* v.x is now 77 */
-  return v.x + 5; /* set breakpoint here */
-}
-
 int
 main ()
 {
-  register_class ();
+  asm ("main_label: .globl main_label");
   return 0;
 }
 
 if { [skip_cplus_tests] } { continue }
 
 load_lib "cp-support.exp"
+load_lib dwarf.exp
 
-standard_testfile .cc
+standard_testfile .cc -dw.S
 
-if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} {
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile \
+        {debug c++}]} {
     return -1
 }
 
-if {![test_compiler_info gcc-*-* c++]} {
-    untested "test relies on a gcc extension"
-    return
-}
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+
+    set main_result \
+       [function_range main ${::srcdir}/${::subdir}/${::srcfile}]
+    set main_start [lindex $main_result 0]
+    set main_length [lindex $main_result 1]
+
+    cu {} {
+       compile_unit {
+           {DW_AT_language @DW_LANG_C_plus_plus}
+           {DW_AT_name     $::srcfile}
+           {DW_AT_comp_dir /tmp}
+       } {
+           declare_labels int_type_label struct_type_label \
+               struct_ptr_type_label
+           set ptr_size [get_sizeof "void *" 96]
+
+           DW_TAG_subprogram {
+               {name main}
+               {low_pc $main_start addr}
+               {high_pc $main_length data8}
+               {DW_AT_type :$int_type_label}
+           }
+
+           int_type_label: DW_TAG_base_type {
+               {DW_AT_byte_size 4 DW_FORM_sdata}
+               {DW_AT_encoding @DW_ATE_signed}
+               {DW_AT_name int}
+           }
+
+           struct_type_label: DW_TAG_structure_type {
+               {DW_AT_byte_size 4 DW_FORM_sdata}
+               {DW_AT_name small}
+           } {
+               member {
+                   {name xxx}
+                   {type :$int_type_label}
+                   {data_member_location 0 data1}
+               }
+               subprogram {
+                   {name yyy}
+                   {type :$int_type_label}
+               } {
+                   formal_parameter {
+                       {type :$struct_ptr_type_label}
+                       {artificial 1 flag_present}
+                   }
+               }
+           }
 
-proc test_call_register_class {} {
-    global gdb_prompt
+           struct_ptr_type_label: DW_TAG_pointer_type {
+               {DW_AT_byte_size $ptr_size DW_FORM_data1}
+               {type :$struct_type_label}
+           }
 
-    if ![runto_main] {
-       return
+           DW_TAG_variable {
+               {DW_AT_name global_var}
+               {DW_AT_type :$struct_type_label}
+               {DW_AT_location {
+                   DW_OP_reg0
+               } SPECIAL_expr}
+               {external 1 flag}
+           }
+       }
     }
+}
 
-    set bp_location [gdb_get_line_number "set breakpoint here"]
-    gdb_breakpoint $bp_location
-    gdb_continue_to_breakpoint "break here"
-
-    # This class is so small that an instance of it can fit in a register.
-    # When gdb tries to call a method, it gets embarrassed about taking
-    # the address of a register.
-    #
-    # That message is a PASS, not an XFAIL, because gdb prints an
-    # informative message and declines to do something impossible.
-    #
-    # The method call actually succeeds if the compiler allocates very
-    # small classes in memory instead of registers.  If that happens,
-    # it's a FAIL, because the testcase is written in a form such that
-    # it should not happen.
-    gdb_test "print v.method ()" \
-       "Address requested for identifier \"v\" which is in register .*" \
-       "call method on register local"
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+         [list $srcfile $asm_file] {nodebug}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
 }
 
-test_call_register_class
+gdb_test "print global_var.yyy ()" \
+    "Address requested for identifier \"global_var\" which is in register .*" \
+    "call method on register local"