Hi all, Jakub,

I need to implement DWARF for local variables that exist in an alternative address space. This happens for OpenACC gang-private variables (or will when the patches are committed) on AMD GCN, at least.

This is distinct from pointer variables that reference other address spaces, and is currently not supported by either GCC or standard DWARF, I think. It is, apparently, not sufficient or appropriate to add DW_OP_address_class to the DWARF after the variable location definition as that is exclusively for pointers.

There is also the issue that GDB will attempt to relocate all symbols defined with DW_OP_addr, but this is inappropriate for symbols in alternative address spaces as the binary's load address is meaningless there.

AMD have created some DWARF extensions to handle address spaces, and they are already implemented in LLVM. A GDB implementation is in progress.

https://llvm.org/docs/AMDGPUDwarfExtensionsForHeterogeneousDebugging.html#amdgpu-dwarf-segment-addresses

A conformant DWARF representation look like this:

DW_TAG_variable
  DW_AT_abstract_origin (0x0000000000000048 "w")
  DW_AT_location (DW_OP_const8u 0x0, DW_OP_constu 0x3,
                  DW_OP_LLVM_form_aspace_address)

That is, at address 0, in address space 3.

The attached patch is clearly not perfect, but does work. It emits the above format for any variable with an address space. For this prototype, I have (ab)used the DTPREL feature to prevent the symbol being relocated. (This port does not use DTPrel for anything else.)

How should I implement this feature to make it acceptable to commit?

Thanks very much

Andrew
DWARF address spaces for local variables


diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c
index f0e4636c06a..0c601bf2d0a 100644
--- a/gcc/config/gcn/gcn.c
+++ b/gcc/config/gcn/gcn.c
@@ -6387,6 +6387,30 @@ gcn_dwarf_register_span (rtx rtl)
   return p;
 }
 
+/* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL hook.
+ 
+   We don't actually use the DTPREL feature, but this is a convienient place
+   to prevent GDB relocating addresses in non-default address spaces.  */
+
+void
+gcn_output_dwarf_dtprel (FILE *file, int size, rtx x)
+{
+  tree decl = SYMBOL_REF_P (x) ? SYMBOL_REF_DECL (x) : NULL_TREE;
+  tree type = decl ? TREE_TYPE (decl) : NULL_TREE;
+  addr_space_t as = type ? TYPE_ADDR_SPACE (type) : ADDR_SPACE_GENERIC;
+  int dbg_as = (ADDR_SPACE_GENERIC_P (as)
+		? -1 : gcn_addr_space_debug (as));
+
+  /* Ensure that we're not trying to use the hook for its true purpose!  */
+  gcc_assert (decl && type);
+  gcc_assert (dbg_as >= 0);
+
+  /* Use an absolute relocation.  dwarf2out will have used DW_OP_const8u, not
+     DW_OP_addr, so this is enough.  */
+  fputs ("\t.8byte\t", file);
+  assemble_name (file, XSTR (x, 0));
+}
+
 /* }}}  */
 /* {{{ TARGET hook overrides.  */
 
@@ -6437,6 +6461,8 @@ gcn_dwarf_register_span (rtx rtl)
 #define TARGET_CONSTANT_ALIGNMENT gcn_constant_alignment
 #undef  TARGET_DEBUG_UNWIND_INFO
 #define TARGET_DEBUG_UNWIND_INFO gcn_debug_unwind_info
+#undef  TARGET_ASM_OUTPUT_DWARF_DTPREL
+#define TARGET_ASM_OUTPUT_DWARF_DTPREL gcn_output_dwarf_dtprel
 #undef  TARGET_DWARF_REGISTER_SPAN
 #define TARGET_DWARF_REGISTER_SPAN gcn_dwarf_register_span
 #undef  TARGET_EMUTLS_VAR_INIT
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 61d8a3f574c..856e8d3fd58 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -15853,9 +15853,30 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	}
 
     symref:
-      mem_loc_result = new_addr_loc_descr (rtl, dtprel_false);
-      vec_safe_push (used_rtx_array, rtl);
-      break;
+      {
+	tree decl = SYMBOL_REF_P (rtl) ? SYMBOL_REF_DECL (rtl) : NULL_TREE;
+	tree type = decl ? TREE_TYPE (decl) : NULL_TREE;
+        addr_space_t as = type ? TYPE_ADDR_SPACE (type) : ADDR_SPACE_GENERIC;
+	int dbg_as = (ADDR_SPACE_GENERIC_P (as)
+		      ? -1 : targetm.addr_space.debug (as));
+
+	mem_loc_result = new_addr_loc_descr (rtl, (dbg_as < 0
+						   ? dtprel_false
+						   : dtprel_true));
+
+	/* Don't relocate symbol references into other address spaces.  */
+	if (dbg_as >= 0)
+	  {
+	    add_loc_descr (&mem_loc_result,
+			   new_loc_descr (DW_OP_constu, dbg_as, 0));
+	    add_loc_descr (&mem_loc_result,
+			   new_loc_descr (DW_OP_LLVM_form_aspace_address,
+					  0, 0));
+	  }
+
+	vec_safe_push (used_rtx_array, rtl);
+	break;
+      }
 
     case CONCAT:
     case CONCATN:
@@ -20294,15 +20315,6 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p)
   if (list)
     {
       add_AT_location_description (die, DW_AT_location, list);
-
-      addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
-      if (!ADDR_SPACE_GENERIC_P (as))
-	{
-	  int action = targetm.addr_space.debug (as);
-	  /* Positive values indicate an address_class.  */
-	  if (action >= 0)
-	    add_AT_unsigned (die, DW_AT_address_class, action);
-	}
       return true;
     }
   /* None of that worked, so it must not really have a location;
diff --git a/include/dwarf2.def b/include/dwarf2.def
index eb9f1a09455..cdcc6efb0fe 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -710,6 +710,8 @@ DW_OP (DW_OP_AARCH64_operation, 0xea)
 // This clashes with DW_OP_AARCH64_operation, so use an alias instead
 // DW_OP (DW_OP_LLVM_piece_end, 0xea)
 #define DW_OP_LLVM_piece_end DW_OP_AARCH64_operation
+
+#define DW_OP_LLVM_form_aspace_address  DW_OP_HP_is_value
 DW_END_OP
 
 DW_FIRST_ATE (DW_ATE_void, 0x0)

Reply via email to