diff mbox

[D] Add support for printing D types.

Message ID CABOHX+ddgQfb-0w5cY8Nrt8vvFM1nnTnn1yGJWiWz5sAtnv5zQ@mail.gmail.com
State New
Headers show

Commit Message

Iain Buclaw Jan. 30, 2016, 4:29 p.m. UTC
Hi,

This adds support for printing types as they would appear in D code.

Tests cover pointers, function pointers, delegates, static arrays,
dynamic arrays, associative arrays, strings (utf-8, 16 and 32),
vectors and modules.

Named types such as structs, unions, classes and enums will need some
fudging of the compiler to not write out RTTI, however I have not had
problems over the last months using them with this applied.

Iain.

Comments

Pedro Alves Feb. 17, 2016, 4:12 p.m. UTC | #1
Hi Iain,

On 01/30/2016 04:29 PM, Iain Buclaw wrote:

> gdb/ChangeLog:
> 

> 	* d-lang.c (d_language_defn): Change c_print_type to d_print_type.
> 	* d-lang.h (d_print_type): New declaration.
> 	* d-typeprint.c: New file.
>

These bits you can clearly self approve.


> 	* Makefile.in (SFILES): Add d-typeprint.c
> 	(COMMON_OBJS): Add d-typeprint.o
> 	* dwarf2read.c (read_structure_type): Set TYPE_DECLARED_CLASS also for
> 	classes in D language.

FAOD, these bits are OK.


> gdb/testsuite/ChangeLog:
> 
> 	* typeprint.S: New file.
> 	* typeprint.exp: New file.

But these can be written in D now, right?

Thanks,
Pedro Alves
Iain Buclaw Feb. 18, 2016, 9:10 p.m. UTC | #2
On 17 February 2016 at 17:12, Pedro Alves <palves@redhat.com> wrote:
> Hi Iain,
>
> On 01/30/2016 04:29 PM, Iain Buclaw wrote:
>
>> gdb/ChangeLog:
>>
>
>>       * d-lang.c (d_language_defn): Change c_print_type to d_print_type.
>>       * d-lang.h (d_print_type): New declaration.
>>       * d-typeprint.c: New file.
>>
>
> These bits you can clearly self approve.
>

OK, however, I do try to hold back on bigger changes, as there may
have been something i overlooked.

>
>>       * Makefile.in (SFILES): Add d-typeprint.c
>>       (COMMON_OBJS): Add d-typeprint.o
>>       * dwarf2read.c (read_structure_type): Set TYPE_DECLARED_CLASS also for
>>       classes in D language.
>
> FAOD, these bits are OK.
>

Thanks.

>
>> gdb/testsuite/ChangeLog:
>>
>>       * typeprint.S: New file.
>>       * typeprint.exp: New file.
>
> But these can be written in D now, right?
>

I guess so, would this be the preferred method for tests that use simple code?

I will redo this patch anyway, I noticed it's an old version with a
FIXME that I forgot to remove.

Regards,
Iain.
Pedro Alves Feb. 18, 2016, 10:48 p.m. UTC | #3
On 02/18/2016 09:10 PM, Iain Buclaw wrote:

>>> gdb/testsuite/ChangeLog:
>>>
>>>       * typeprint.S: New file.
>>>       * typeprint.exp: New file.
>>
>> But these can be written in D now, right?
>>
> 
> I guess so, would this be the preferred method for tests that use simple code?

Right.  We prefer writing tests in their natural language, unless the
test is exercising some dwarf-specific issue where we truly need to
capture a stable dwarf snapshot.  And even then, we prefer using the
testsuite's dwarf assembler, in order to make the test arch-independent
(grep for "Dwarf" in testsuite/gdb.dwarf2).

> I will redo this patch anyway, I noticed it's an old version with a
> FIXME that I forgot to remove.

Thanks,
Pedro Alves
diff mbox

Patch

gdb/ChangeLog:

	* Makefile.in (SFILES): Add d-typeprint.c
	(COMMON_OBJS): Add d-typeprint.o
	* d-lang.c (d_language_defn): Change c_print_type to d_print_type.
	* d-lang.h (d_print_type): New declaration.
	* d-typeprint.c: New file.
	* dwarf2read.c (read_structure_type): Set TYPE_DECLARED_CLASS also for
	classes in D language.

gdb/testsuite/ChangeLog:

	* typeprint.S: New file.
	* typeprint.exp: New file.

---
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 5e8eb9a..3900029 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -838,7 +838,7 @@  SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	charset.c common/cleanups.c cli-out.c coffread.c coff-pe-read.c \
 	complaints.c completer.c continuations.c corefile.c corelow.c \
 	cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
-	d-exp.y d-lang.c d-namespace.c d-valprint.c \
+	d-exp.y d-lang.c d-namespace.c d-typeprint.c d-valprint.c \
 	cp-name-parser.y \
 	dbxread.c demangle.c dictionary.c disasm.c doublest.c \
 	dtrace-probe.c dummy-frame.c \
@@ -1063,7 +1063,8 @@  COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	m2-lang.o opencl-lang.o p-lang.o p-typeprint.o p-valprint.o \
 	sentinel-frame.o \
 	complaints.o typeprint.o \
-	ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
+	ada-typeprint.o c-typeprint.o d-typeprint.o f-typeprint.o \
+	m2-typeprint.o \
 	ada-valprint.o c-valprint.o cp-valprint.o d-valprint.o f-valprint.o \
 	m2-valprint.o \
 	serial.o mdebugread.o top.o utils.o \
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index e8a08e1..409199b 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -206,7 +206,7 @@  static const struct language_defn d_language_defn =
   c_printchar,			/* Print a character constant.  */
   c_printstr,			/* Function to print string constant.  */
   c_emit_char,			/* Print a single char.  */
-  c_print_type,			/* Print a type using appropriate syntax.  */
+  d_print_type,			/* Print a type using appropriate syntax.  */
   c_print_typedef,		/* Print a typedef using appropriate
 				   syntax.  */
   d_val_print,			/* Print a value using appropriate syntax.  */
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
index 8f63f51..015fd93 100644
--- a/gdb/d-lang.h
+++ b/gdb/d-lang.h
@@ -20,6 +20,8 @@ 
 #if !defined (D_LANG_H)
 #define D_LANG_H 1
 
+struct type_print_options;
+
 #include "symtab.h"
 
 /* Language specific builtin types for D.  Any additional types added
@@ -78,6 +80,12 @@  extern struct block_symbol d_lookup_symbol_nonlocal (const struct language_defn
 extern struct block_symbol d_lookup_nested_symbol (struct type *, const char *,
 						   const struct block *);
 
+/* Defined in d-typeprint.c.  */
+
+extern void d_print_type (struct type *type, const char *varstring,
+			  struct ui_file *stream, int show, int level,
+			  const struct type_print_options *flags);
+
 /* Defined in d-valprint.c  */
 
 extern void d_val_print (struct type *type, const gdb_byte *valaddr,
diff --git a/gdb/d-typeprint.c b/gdb/d-typeprint.c
new file mode 100644
index 0000000..e94daed
--- /dev/null
+++ b/gdb/d-typeprint.c
@@ -0,0 +1,384 @@ 
+/* Support for printing D types for GDB, the GNU debugger.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   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/>.  */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "demangle.h"
+#include "typeprint.h"
+#include "c-lang.h"
+#include "cp-support.h"
+#include "d-lang.h"
+
+/* Print the name of the type (or the ultimate pointer target,
+   function value or array element), or the description of a
+   structure or union.
+
+   SHOW positive means print details about the type (e.g. enum
+   values), and print structure elements passing SHOW - 1 for show.
+
+   SHOW negative means just print the type name or struct tag if there
+   is one.  If there is no name, print something sensible but concise
+   like "struct {...}".
+
+   SHOW zero means just print the type name or struct tag if there is
+   one.  If there is no name, print something sensible but not as
+   concise like "struct {int x; int y;}".
+
+   LEVEL is the number of spaces to indent by.
+   We increase it for some recursive calls.  */
+
+static void
+d_type_print_base (struct type *type, struct ui_file *stream, int show,
+		   int level, const struct type_print_options *flags)
+{
+  QUIT;
+  wrap_here ("    ");
+
+  if (type == NULL)
+    {
+      fputs_filtered ("<type unknown>", stream);
+      return;
+    }
+
+  /* When SHOW is zero or less, and there is a valid type name, then always
+     just print the type name directly from the type.  */
+  if ((show <= 0) && (TYPE_NAME (type) != NULL))
+    {
+      fputs_filtered (TYPE_NAME (type), stream);
+      return;
+    }
+
+  if (TYPE_CODE (type) != TYPE_CODE_TYPEDEF)
+    type = check_typedef (type);
+
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_TYPEDEF:
+      d_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level, flags);
+      break;
+
+    case TYPE_CODE_ARRAY:
+      {
+	LONGEST low_bound, high_bound;
+	int is_vector = TYPE_VECTOR (type);
+
+	if (is_vector)
+	  fputs_filtered ("__vector(", stream);
+
+	d_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level, flags);
+	fputs_filtered ("[", stream);
+	/* Bounds are not yet resolved, print a bounds placeholder instead.  */
+	if (TYPE_HIGH_BOUND_KIND (TYPE_INDEX_TYPE (type)) == PROP_LOCEXPR
+	    || TYPE_HIGH_BOUND_KIND (TYPE_INDEX_TYPE (type)) == PROP_LOCLIST)
+	  fputs_filtered ("variable length", stream);
+	else if (get_array_bounds (type, &low_bound, &high_bound))
+	  fprintf_filtered (stream, "%s",
+			    plongest (high_bound - low_bound + 1));
+	fputs_filtered ("]", stream);
+
+	if (is_vector)
+	  fputs_filtered (")", stream);
+      }
+      break;
+
+    case TYPE_CODE_PTR:
+      {
+	struct type *target = TYPE_TARGET_TYPE (type);
+	int is_funcptr = (target != NULL
+			  && TYPE_CODE (target) == TYPE_CODE_FUNC);
+	int is_class = (target != NULL
+			&& TYPE_CODE (target) == TYPE_CODE_STRUCT
+			&& TYPE_DECLARED_CLASS (target));
+
+	/* Want to show the contents of top-level class pointers.  */
+	if (show > 0 && !is_class)
+	  show = 0;
+
+	d_type_print_base (target, stream, show, level, flags);
+
+	/* Function pointers have their own syntax.  */
+	if (is_funcptr)
+	  {
+	    int i;
+
+	    fputs_filtered (" function(", stream);
+	    for (i = 0; i < TYPE_NFIELDS (target); i++)
+	      {
+		struct field f = TYPE_FIELDS (target)[i];
+
+		if (i > 0)
+		  fputs_filtered (", ", stream);
+
+		d_type_print_base (FIELD_TYPE (f), stream, 0, level, flags);
+	      }
+	    fputs_filtered (")", stream);
+	  }
+	else
+	  {
+	    /* Skip emitting the '*' for classes, as they are all represented
+	       as pointer types in D.  */
+	    if (!is_class)
+	      fprintf_filtered (stream, "*");
+	  }
+      }
+      break;
+
+    case TYPE_CODE_REF:
+      {
+	fputs_filtered ("ref ", stream);
+	d_type_print_base (TYPE_TARGET_TYPE (type), stream,
+			   show, level, flags);
+      }
+      break;
+
+    case TYPE_CODE_FUNC:
+      d_type_print_base (TYPE_TARGET_TYPE (type), stream,
+			 show, level, flags);
+      break;
+
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+      {
+	const char *tagname = TYPE_TAG_NAME (type);
+
+	if (tagname != NULL)
+	  {
+	    char lastchar = tagname[strlen (tagname) - 1];
+
+	    fputs_filtered (tagname, stream);
+	    /* If it's a dynamic or associative array, or a delegate function,
+	       don't print the underlying type structure.  */
+	    if (lastchar == ']' || lastchar == ')')
+	      break;
+
+	    /* String types in D are aliases to dynamic arrays, however their
+	       aliases are written to debug instead of the underlying type.  */
+	    if ((strcmp (tagname, "string") == 0
+		 || strcmp (tagname, "wstring") == 0
+		 || strcmp (tagname, "dstring") == 0)
+		&& TYPE_NFIELDS (type) == 2
+		&& strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
+		&& strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0)
+	      break;
+
+	    if (show > 0)
+	      fputs_filtered (" ", stream);
+	  }
+	else
+	  {
+	    /* Anonymous class/struct/union.  */
+	    if (TYPE_CODE (type) == TYPE_CODE_UNION)
+	      fputs_filtered ("union ", stream);
+	    else if (TYPE_DECLARED_CLASS (type))
+	      fputs_filtered ("class ", stream);
+	    else
+	      fputs_filtered ("struct ", stream);
+	  }
+
+	wrap_here ("    ");
+
+	if (show < 0)
+	  {
+	    /* If we just printed a tag name, no need to print anything else.  */
+	    if (tagname == NULL)
+	      fprintf_filtered (stream, "{...}");
+	  }
+	else if (show > 0 || TYPE_TAG_NAME (type) == NULL)
+	  {
+	    int len;
+	    int i, j;
+
+	    // FIXME: print inheritance / interfaces
+
+	    fputs_filtered ("{\n", stream);
+	    if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0))
+	      {
+		if (TYPE_STUB (type))
+		  fprintfi_filtered (level + 4, stream, "<incomplete type>\n");
+		else
+		  fprintfi_filtered (level + 4, stream, "<no data fields>\n");
+	      }
+
+	    QUIT;
+
+	    /* If there is a base class for this type,
+	       do not print the field that it occupies.  */
+	    len = TYPE_NFIELDS (type);
+	    for (i = TYPE_N_BASECLASSES (type); i < len; i++)
+	      {
+		QUIT;
+		/* Don't print out virtual function table or monitor.
+		   These are the first two fields placed in the class,
+		   and should be marked as artificial.  */
+		if (i < 2 && TYPE_DECLARED_CLASS (type))
+		  {
+		    if (TYPE_FIELD_ARTIFICIAL (type, i))
+		      continue;
+		    else if (startswith (TYPE_FIELD_NAME (type, i), "__vptr"))
+		      continue;
+		    else if (startswith (TYPE_FIELD_NAME (type, i), "__monitor"))
+		      continue;
+		  }
+
+		print_spaces_filtered (level + 4, stream);
+
+		if (TYPE_FIELD_PROTECTED (type, i))
+		  fputs_filtered ("protected ", stream);
+		else if (TYPE_FIELD_PRIVATE (type, i))
+		  fputs_filtered ("private ", stream);
+
+		if (field_is_static (&TYPE_FIELD (type, i)))
+		  fputs_filtered ("static ", stream);
+
+		d_print_type (TYPE_FIELD_TYPE (type, i),
+			      TYPE_FIELD_NAME (type, i),
+			      stream, show - 1, level + 4, flags);
+		fputs_filtered (";\n", stream);
+	      }
+
+	    /* Print out the methods, artificial methods will be hidden.  */
+	    len = TYPE_NFN_FIELDS (type);
+	    if (!flags->print_methods)
+	      len = 0;
+
+	    for (i = 0; i < len; i++)
+	      {
+		for (j = 0; j < TYPE_FN_FIELDLIST_LENGTH (type, i); j++)
+		  {
+		    struct fn_field *fields = TYPE_FN_FIELDLIST1 (type, i);
+		    const char *method_name;
+		    char *mangled_name;
+		    char *demangled_name;
+		    struct type *target;
+
+		    /* Do not print out artificial methods.  */
+		    if (TYPE_FN_FIELD_ARTIFICIAL (fields, j))
+		      continue;
+
+		    method_name = TYPE_FN_FIELDLIST_NAME (type, i);
+
+		    /* Build something we can demangle.  */
+		    if (TYPE_FN_FIELD_STUB (fields, j))
+		      mangled_name = gdb_mangle_name (type, i, j);
+		    else
+		      {
+			const char *physname;
+			int physname_len;
+
+			physname = TYPE_FN_FIELD_PHYSNAME (fields, j);
+			physname_len = strlen(physname);
+
+			mangled_name = alloca (physname_len + 1);
+			memcpy (mangled_name, physname, physname_len);
+			mangled_name[physname_len] = '\0';
+		      }
+
+		    QUIT;
+		    print_spaces_filtered (level + 4, stream);
+
+		    if (TYPE_FN_FIELD_PROTECTED (fields, j))
+		      fputs_filtered ("protected ", stream);
+		    else if (TYPE_FN_FIELD_PRIVATE (fields, j))
+		      fputs_filtered ("private ", stream);
+
+		    if (TYPE_FN_FIELD_ABSTRACT (fields, j))
+		      fputs_filtered ("abstract ", stream);
+		    if (TYPE_FN_FIELD_STATIC (fields, j))
+		      fputs_filtered ("static ", stream);
+		    if (TYPE_FN_FIELD_FINAL (fields, j))
+		      fputs_filtered ("final ", stream);
+		    if (TYPE_FN_FIELD_SYNCHRONIZED (fields, j))
+		      fputs_filtered ("synchronized ", stream);
+
+		    target = TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (fields, j));
+		    if (target == NULL)
+		      {
+			/* Keep GDB from crashing here.  */
+			fprintf_filtered (stream, "<undefined type> %s;\n",
+					  TYPE_FN_FIELD_PHYSNAME (fields, j));
+			break;
+		      }
+		    else if (strcmp (method_name, "__ctor") != 0
+			     && strcmp (method_name, "__dtor") != 0
+			     && strcmp (method_name, "__postblit") != 0)
+		      {
+			d_print_type (target, "", stream, -1, 0, flags);
+			fputs_filtered (" ", stream);
+		      }
+
+		    demangled_name = gdb_demangle (mangled_name, DMGL_DLANG);
+
+		    if (demangled_name != NULL)
+		      {
+			/* Skip to the base name of the demangled symbol.  */
+			char *p = strchr (demangled_name, '(');
+			gdb_assert (p != NULL);
+			while (p > demangled_name && p[-1] != '.')
+			  p--;
+
+			fputs_filtered (p, stream);
+			xfree (demangled_name);
+		      }
+		    else
+		      fputs_filtered (mangled_name, stream);
+
+		    if (TYPE_FN_FIELD_STUB (fields, j))
+		      xfree (mangled_name);
+
+		    fputs_filtered (";\n", stream);
+		  }
+	      }
+
+	    fprintfi_filtered (level, stream, "}");
+	  }
+      }
+      break;
+
+    case TYPE_CODE_MODULE:
+      fprintf_filtered (stream, "module %s", TYPE_TAG_NAME (type));
+      break;
+
+    default:
+      /* Handle types not explicitly handled by the other cases,
+         such as fundamental types.  For these, just print whatever
+         the type name is, as recorded in the type itself.  If there
+         is no type name, then hand it down to c_type_print_base.  */
+      if (TYPE_NAME (type) != NULL)
+	fprintfi_filtered (level, stream, "%s", TYPE_NAME (type));
+      else
+	c_type_print_base (type, stream, show, level, flags);
+      break;
+    }
+}
+
+/* LEVEL is the depth to indent lines by.  */
+
+void
+d_print_type (struct type *type, const char *varstring,
+	      struct ui_file *stream, int show, int level,
+	      const struct type_print_options *flags)
+{
+  d_type_print_base (type, stream, show, level, flags);
+
+  if (varstring != NULL && *varstring != '\0')
+    {
+      fputs_filtered (" ", stream);
+      fputs_filtered (varstring, stream);
+    }
+}
+
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 1020c12..6be6115 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -13199,7 +13199,8 @@  read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
       TYPE_CODE (type) = TYPE_CODE_STRUCT;
     }
 
-  if (cu->language == language_cplus && die->tag == DW_TAG_class_type)
+  if ((cu->language == language_cplus || cu->language == language_d)
+      && die->tag == DW_TAG_class_type)
     TYPE_DECLARED_CLASS (type) = 1;
 
   attr = dwarf2_attr (die, DW_AT_byte_size, cu);
diff --git a/gdb/testsuite/gdb.dlang/typeprint.S b/gdb/testsuite/gdb.dlang/typeprint.S
new file mode 100644
index 0000000..e8e1ae4
--- /dev/null
+++ b/gdb/testsuite/gdb.dlang/typeprint.S
@@ -0,0 +1,588 @@ 
+/* Copyright 2016 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
+   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/>.  */
+
+/* This file was generated using:
+
+   $ gdc -g -Og -dA typeprint.d -S -o typeprint.S
+
+  with
+
+  $ gdc -v
+  gcc version 6.0.0 20160123 (experimental) (GCC)
+  Target: x86_64-pc-linux-gnu
+  Thread model: posix
+
+  And then manually cleaned up some debug comments.  */
+	.file	"typeprint.d"
+	.text
+.Ltext0:
+	.globl	main
+	.type	main, @function
+main:
+.LFB0:
+	.file 1 "typeprint.d"
+	# typeprint.d:3
+	.loc 1 3 0
+	.cfi_startproc
+	rep ret
+	.cfi_endproc
+.LFE0:
+	.size	main, .-main
+.Letext0:
+	.file 2 "<built-in>"
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0x235	# Length of Compilation Unit Info
+	.value	0x4	# DWARF version number
+	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
+	.byte	0x8	# Pointer Size (in bytes)
+	.uleb128 0x1	# (DIE (0xb) DW_TAG_compile_unit)
+	.long	.LASF28	# DW_AT_producer: "GNU D 6.0.0 20160123 (experimental)"
+	.byte	0x13	# DW_AT_language
+	.long	.LASF29	# DW_AT_name: "typeprint.d"
+	.long	.LASF30	# DW_AT_comp_dir: "/tmp"
+	.quad	.Ltext0	# DW_AT_low_pc
+	.quad	.Letext0-.Ltext0	# DW_AT_high_pc
+	.long	.Ldebug_line0	# DW_AT_stmt_list
+	.uleb128 0x2	# (DIE (0x2d) DW_TAG_module)
+	.long	.LASF31	# DW_AT_name: "typeprint"
+			# DW_AT_declaration
+	.long	0xbf	# DW_AT_sibling
+	.uleb128 0x3	# (DIE (0x36) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF32	# DW_AT_name: "main"
+	.byte	0x1	# DW_AT_decl_file (typeprint.d)
+	.byte	0x3	# DW_AT_decl_line
+	.quad	.LFB0	# DW_AT_low_pc
+	.quad	.LFE0-.LFB0	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+	.uleb128 0x4	# (DIE (0x4f) DW_TAG_variable)
+	.long	.LASF0	# DW_AT_name: "vectorarray"
+	.byte	0x1	# DW_AT_decl_file (typeprint.d)
+	.byte	0xf	# DW_AT_decl_line
+	.long	0xbf	# DW_AT_type
+	.uleb128 0x4	# (DIE (0x5a) DW_TAG_variable)
+	.long	.LASF1	# DW_AT_name: "dstringvalue"
+	.byte	0x1	# DW_AT_decl_file (typeprint.d)
+	.byte	0xe	# DW_AT_decl_line
+	.long	0xd2	# DW_AT_type
+	.uleb128 0x4	# (DIE (0x65) DW_TAG_variable)
+	.long	.LASF2	# DW_AT_name: "wstringvalue"
+	.byte	0x1	# DW_AT_decl_file (typeprint.d)
+	.byte	0xd	# DW_AT_decl_line
+	.long	0x10e	# DW_AT_type
+	.uleb128 0x4	# (DIE (0x70) DW_TAG_variable)
+	.long	.LASF3	# DW_AT_name: "stringvalue"
+	.byte	0x1	# DW_AT_decl_file (typeprint.d)
+	.byte	0xc	# DW_AT_decl_line
+	.long	0x143	# DW_AT_type
+	.uleb128 0x4	# (DIE (0x7b) DW_TAG_variable)
+	.long	.LASF4	# DW_AT_name: "associativearray"
+	.byte	0x1	# DW_AT_decl_file (typeprint.d)
+	.byte	0xb	# DW_AT_decl_line
+	.long	0x178	# DW_AT_type
+	.uleb128 0x4	# (DIE (0x86) DW_TAG_variable)
+	.long	.LASF5	# DW_AT_name: "dynamicarray"
+	.byte	0x1	# DW_AT_decl_file (typeprint.d)
+	.byte	0xa	# DW_AT_decl_line
+	.long	0x191	# DW_AT_type
+	.uleb128 0x4	# (DIE (0x91) DW_TAG_variable)
+	.long	.LASF6	# DW_AT_name: "delegateptr"
+	.byte	0x1	# DW_AT_decl_file (typeprint.d)
+	.byte	0x9	# DW_AT_decl_line
+	.long	0x1c1	# DW_AT_type
+	.uleb128 0x4	# (DIE (0x9c) DW_TAG_variable)
+	.long	.LASF7	# DW_AT_name: "funcptr"
+	.byte	0x1	# DW_AT_decl_file (typeprint.d)
+	.byte	0x8	# DW_AT_decl_line
+	.long	0x214	# DW_AT_type
+	.uleb128 0x4	# (DIE (0xa7) DW_TAG_variable)
+	.long	.LASF8	# DW_AT_name: "staticarray"
+	.byte	0x1	# DW_AT_decl_file (typeprint.d)
+	.byte	0x7	# DW_AT_decl_line
+	.long	0x21a	# DW_AT_type
+	.uleb128 0x4	# (DIE (0xb2) DW_TAG_variable)
+	.long	.LASF9	# DW_AT_name: "voidptr"
+	.byte	0x1	# DW_AT_decl_file (typeprint.d)
+	.byte	0x6	# DW_AT_decl_line
+	.long	0x18f	# DW_AT_type
+	.byte	0	# end of children of DIE 0x36
+	.byte	0	# end of children of DIE 0x2d
+	.uleb128 0x5	# (DIE (0xbf) DW_TAG_array_type)
+			# DW_AT_GNU_vector
+	.long	0xcb	# DW_AT_type
+	.long	0xcb	# DW_AT_sibling
+	.uleb128 0x6	# (DIE (0xc8) DW_TAG_subrange_type)
+	.byte	0x7	# DW_AT_upper_bound
+	.byte	0	# end of children of DIE 0xbf
+	.uleb128 0x7	# (DIE (0xcb) DW_TAG_base_type)
+	.byte	0x1	# DW_AT_byte_size
+	.byte	0x7	# DW_AT_encoding
+	.long	.LASF11	# DW_AT_name: "ubyte"
+	.uleb128 0x8	# (DIE (0xd2) DW_TAG_structure_type)
+	.long	.LASF14	# DW_AT_name: "dstring"
+	.byte	0x10	# DW_AT_byte_size
+	.long	0xf5	# DW_AT_sibling
+	.uleb128 0x9	# (DIE (0xdc) DW_TAG_member)
+	.long	.LASF10	# DW_AT_name: "length"
+	.byte	0x2	# DW_AT_decl_file (<built-in>)
+	.byte	0	# DW_AT_decl_line
+	.long	0xf5	# DW_AT_type
+	.byte	0	# DW_AT_data_member_location
+	.uleb128 0xa	# (DIE (0xe8) DW_TAG_member)
+	.ascii "ptr\0"	# DW_AT_name
+	.byte	0x2	# DW_AT_decl_file (<built-in>)
+	.byte	0	# DW_AT_decl_line
+	.long	0xfc	# DW_AT_type
+	.byte	0x8	# DW_AT_data_member_location
+	.byte	0	# end of children of DIE 0xd2
+	.uleb128 0x7	# (DIE (0xf5) DW_TAG_base_type)
+	.byte	0x8	# DW_AT_byte_size
+	.byte	0x7	# DW_AT_encoding
+	.long	.LASF12	# DW_AT_name: "ulong"
+	.uleb128 0xb	# (DIE (0xfc) DW_TAG_pointer_type)
+	.byte	0x8	# DW_AT_byte_size
+	.long	0x109	# DW_AT_type
+	.uleb128 0x7	# (DIE (0x102) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x8	# DW_AT_encoding
+	.long	.LASF13	# DW_AT_name: "dchar"
+	.uleb128 0xc	# (DIE (0x109) DW_TAG_const_type)
+	.long	0x102	# DW_AT_type
+	.uleb128 0x8	# (DIE (0x10e) DW_TAG_structure_type)
+	.long	.LASF15	# DW_AT_name: "wstring"
+	.byte	0x10	# DW_AT_byte_size
+	.long	0x131	# DW_AT_sibling
+	.uleb128 0x9	# (DIE (0x118) DW_TAG_member)
+	.long	.LASF10	# DW_AT_name: "length"
+	.byte	0x2	# DW_AT_decl_file (<built-in>)
+	.byte	0	# DW_AT_decl_line
+	.long	0xf5	# DW_AT_type
+	.byte	0	# DW_AT_data_member_location
+	.uleb128 0xa	# (DIE (0x124) DW_TAG_member)
+	.ascii "ptr\0"	# DW_AT_name
+	.byte	0x2	# DW_AT_decl_file (<built-in>)
+	.byte	0	# DW_AT_decl_line
+	.long	0x131	# DW_AT_type
+	.byte	0x8	# DW_AT_data_member_location
+	.byte	0	# end of children of DIE 0x10e
+	.uleb128 0xb	# (DIE (0x131) DW_TAG_pointer_type)
+	.byte	0x8	# DW_AT_byte_size
+	.long	0x13e	# DW_AT_type
+	.uleb128 0x7	# (DIE (0x137) DW_TAG_base_type)
+	.byte	0x2	# DW_AT_byte_size
+	.byte	0x8	# DW_AT_encoding
+	.long	.LASF16	# DW_AT_name: "wchar"
+	.uleb128 0xc	# (DIE (0x13e) DW_TAG_const_type)
+	.long	0x137	# DW_AT_type
+	.uleb128 0x8	# (DIE (0x143) DW_TAG_structure_type)
+	.long	.LASF17	# DW_AT_name: "string"
+	.byte	0x10	# DW_AT_byte_size
+	.long	0x166	# DW_AT_sibling
+	.uleb128 0x9	# (DIE (0x14d) DW_TAG_member)
+	.long	.LASF10	# DW_AT_name: "length"
+	.byte	0x2	# DW_AT_decl_file (<built-in>)
+	.byte	0	# DW_AT_decl_line
+	.long	0xf5	# DW_AT_type
+	.byte	0	# DW_AT_data_member_location
+	.uleb128 0xa	# (DIE (0x159) DW_TAG_member)
+	.ascii "ptr\0"	# DW_AT_name
+	.byte	0x2	# DW_AT_decl_file (<built-in>)
+	.byte	0	# DW_AT_decl_line
+	.long	0x166	# DW_AT_type
+	.byte	0x8	# DW_AT_data_member_location
+	.byte	0	# end of children of DIE 0x143
+	.uleb128 0xb	# (DIE (0x166) DW_TAG_pointer_type)
+	.byte	0x8	# DW_AT_byte_size
+	.long	0x173	# DW_AT_type
+	.uleb128 0x7	# (DIE (0x16c) DW_TAG_base_type)
+	.byte	0x1	# DW_AT_byte_size
+	.byte	0x8	# DW_AT_encoding
+	.long	.LASF18	# DW_AT_name: "char"
+	.uleb128 0xc	# (DIE (0x173) DW_TAG_const_type)
+	.long	0x16c	# DW_AT_type
+	.uleb128 0x8	# (DIE (0x178) DW_TAG_structure_type)
+	.long	.LASF19	# DW_AT_name: "uint[uint]"
+	.byte	0x8	# DW_AT_byte_size
+	.long	0x18f	# DW_AT_sibling
+	.uleb128 0xa	# (DIE (0x182) DW_TAG_member)
+	.ascii "ptr\0"	# DW_AT_name
+	.byte	0x2	# DW_AT_decl_file (<built-in>)
+	.byte	0	# DW_AT_decl_line
+	.long	0x18f	# DW_AT_type
+	.byte	0	# DW_AT_data_member_location
+	.byte	0	# end of children of DIE 0x178
+	.uleb128 0xd	# (DIE (0x18f) DW_TAG_pointer_type)
+	.byte	0x8	# DW_AT_byte_size
+	.uleb128 0x8	# (DIE (0x191) DW_TAG_structure_type)
+	.long	.LASF20	# DW_AT_name: "long[]"
+	.byte	0x10	# DW_AT_byte_size
+	.long	0x1b4	# DW_AT_sibling
+	.uleb128 0x9	# (DIE (0x19b) DW_TAG_member)
+	.long	.LASF10	# DW_AT_name: "length"
+	.byte	0x2	# DW_AT_decl_file (<built-in>)
+	.byte	0	# DW_AT_decl_line
+	.long	0xf5	# DW_AT_type
+	.byte	0	# DW_AT_data_member_location
+	.uleb128 0xa	# (DIE (0x1a7) DW_TAG_member)
+	.ascii "ptr\0"	# DW_AT_name
+	.byte	0x2	# DW_AT_decl_file (<built-in>)
+	.byte	0	# DW_AT_decl_line
+	.long	0x1b4	# DW_AT_type
+	.byte	0x8	# DW_AT_data_member_location
+	.byte	0	# end of children of DIE 0x191
+	.uleb128 0xb	# (DIE (0x1b4) DW_TAG_pointer_type)
+	.byte	0x8	# DW_AT_byte_size
+	.long	0x1ba	# DW_AT_type
+	.uleb128 0x7	# (DIE (0x1ba) DW_TAG_base_type)
+	.byte	0x8	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.long	.LASF21	# DW_AT_name: "long"
+	.uleb128 0x8	# (DIE (0x1c1) DW_TAG_structure_type)
+	.long	.LASF22	# DW_AT_name: "char delegate(byte)"
+	.byte	0x10	# DW_AT_byte_size
+	.long	0x1e4	# DW_AT_sibling
+	.uleb128 0x9	# (DIE (0x1cb) DW_TAG_member)
+	.long	.LASF23	# DW_AT_name: "object"
+	.byte	0x2	# DW_AT_decl_file (<built-in>)
+	.byte	0	# DW_AT_decl_line
+	.long	0x18f	# DW_AT_type
+	.byte	0	# DW_AT_data_member_location
+	.uleb128 0x9	# (DIE (0x1d7) DW_TAG_member)
+	.long	.LASF24	# DW_AT_name: "func"
+	.byte	0x2	# DW_AT_decl_file (<built-in>)
+	.byte	0	# DW_AT_decl_line
+	.long	0x1ff	# DW_AT_type
+	.byte	0x8	# DW_AT_data_member_location
+	.byte	0	# end of children of DIE 0x1c1
+	.uleb128 0xe	# (DIE (0x1e4) DW_TAG_subroutine_type)
+	.long	0x16c	# DW_AT_type
+	.long	0x1f8	# DW_AT_sibling
+	.uleb128 0xf	# (DIE (0x1ed) DW_TAG_formal_parameter)
+	.long	0x18f	# DW_AT_type
+	.uleb128 0xf	# (DIE (0x1f2) DW_TAG_formal_parameter)
+	.long	0x1f8	# DW_AT_type
+	.byte	0	# end of children of DIE 0x1e4
+	.uleb128 0x7	# (DIE (0x1f8) DW_TAG_base_type)
+	.byte	0x1	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.long	.LASF25	# DW_AT_name: "byte"
+	.uleb128 0xb	# (DIE (0x1ff) DW_TAG_pointer_type)
+	.byte	0x8	# DW_AT_byte_size
+	.long	0x1e4	# DW_AT_type
+	.uleb128 0xe	# (DIE (0x205) DW_TAG_subroutine_type)
+	.long	0x16c	# DW_AT_type
+	.long	0x214	# DW_AT_sibling
+	.uleb128 0xf	# (DIE (0x20e) DW_TAG_formal_parameter)
+	.long	0x1f8	# DW_AT_type
+	.byte	0	# end of children of DIE 0x205
+	.uleb128 0xb	# (DIE (0x214) DW_TAG_pointer_type)
+	.byte	0x8	# DW_AT_byte_size
+	.long	0x205	# DW_AT_type
+	.uleb128 0x10	# (DIE (0x21a) DW_TAG_array_type)
+	.long	0x231	# DW_AT_type
+	.long	0x22a	# DW_AT_sibling
+	.uleb128 0x11	# (DIE (0x223) DW_TAG_subrange_type)
+	.long	0x22a	# DW_AT_type
+	.byte	0	# DW_AT_upper_bound
+	.byte	0	# end of children of DIE 0x21a
+	.uleb128 0x7	# (DIE (0x22a) DW_TAG_base_type)
+	.byte	0x8	# DW_AT_byte_size
+	.byte	0x7	# DW_AT_encoding
+	.long	.LASF26	# DW_AT_name: "sizetype"
+	.uleb128 0x7	# (DIE (0x231) DW_TAG_base_type)
+	.byte	0x2	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.long	.LASF27	# DW_AT_name: "short"
+	.byte	0	# end of children of DIE 0xb
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	# (abbrev code)
+	.uleb128 0x11	# (TAG: DW_TAG_compile_unit)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x25	# (DW_AT_producer)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x13	# (DW_AT_language)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x1b	# (DW_AT_comp_dir)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x10	# (DW_AT_stmt_list)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	# (abbrev code)
+	.uleb128 0x1e	# (TAG: DW_TAG_module)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3c	# (DW_AT_declaration)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2117	# (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	# (abbrev code)
+	.uleb128 0x34	# (TAG: DW_TAG_variable)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	# (abbrev code)
+	.uleb128 0x1	# (TAG: DW_TAG_array_type)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x2107	# (DW_AT_GNU_vector)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x6	# (abbrev code)
+	.uleb128 0x21	# (TAG: DW_TAG_subrange_type)
+	.byte	0	# DW_children_no
+	.uleb128 0x2f	# (DW_AT_upper_bound)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0x7	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.byte	0
+	.byte	0
+	.uleb128 0x8	# (abbrev code)
+	.uleb128 0x13	# (TAG: DW_TAG_structure_type)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x9	# (abbrev code)
+	.uleb128 0xd	# (TAG: DW_TAG_member)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x38	# (DW_AT_data_member_location)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0xa	# (abbrev code)
+	.uleb128 0xd	# (TAG: DW_TAG_member)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x38	# (DW_AT_data_member_location)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0xb	# (abbrev code)
+	.uleb128 0xf	# (TAG: DW_TAG_pointer_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0xc	# (abbrev code)
+	.uleb128 0x26	# (TAG: DW_TAG_const_type)
+	.byte	0	# DW_children_no
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0xd	# (abbrev code)
+	.uleb128 0xf	# (TAG: DW_TAG_pointer_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0xe	# (abbrev code)
+	.uleb128 0x15	# (TAG: DW_TAG_subroutine_type)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0xf	# (abbrev code)
+	.uleb128 0x5	# (TAG: DW_TAG_formal_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x10	# (abbrev code)
+	.uleb128 0x1	# (TAG: DW_TAG_array_type)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x11	# (abbrev code)
+	.uleb128 0x21	# (TAG: DW_TAG_subrange_type)
+	.byte	0	# DW_children_no
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2f	# (DW_AT_upper_bound)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x2c	# Length of Address Ranges Info
+	.value	0x2	# DWARF Version
+	.long	.Ldebug_info0	# Offset of Compilation Unit Info
+	.byte	0x8	# Size of Address
+	.byte	0	# Size of Segment Descriptor
+	.value	0	# Pad to 16 byte boundary
+	.value	0
+	.quad	.Ltext0	# Address
+	.quad	.Letext0-.Ltext0	# Length
+	.quad	0
+	.quad	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF14:
+	.string	"dstring"
+.LASF19:
+	.string	"uint[uint]"
+.LASF3:
+	.string	"stringvalue"
+.LASF17:
+	.string	"string"
+.LASF23:
+	.string	"object"
+.LASF5:
+	.string	"dynamicarray"
+.LASF16:
+	.string	"wchar"
+.LASF25:
+	.string	"byte"
+.LASF1:
+	.string	"dstringvalue"
+.LASF10:
+	.string	"length"
+.LASF30:
+	.string	"/tmp"
+.LASF13:
+	.string	"dchar"
+.LASF27:
+	.string	"short"
+.LASF31:
+	.string	"typeprint"
+.LASF2:
+	.string	"wstringvalue"
+.LASF6:
+	.string	"delegateptr"
+.LASF32:
+	.string	"main"
+.LASF4:
+	.string	"associativearray"
+.LASF26:
+	.string	"sizetype"
+.LASF21:
+	.string	"long"
+.LASF29:
+	.string	"typeprint.d"
+.LASF22:
+	.string	"char delegate(byte)"
+.LASF12:
+	.string	"ulong"
+.LASF28:
+	.string	"GNU D 6.0.0 20160123 (experimental)"
+.LASF11:
+	.string	"ubyte"
+.LASF8:
+	.string	"staticarray"
+.LASF7:
+	.string	"funcptr"
+.LASF0:
+	.string	"vectorarray"
+.LASF9:
+	.string	"voidptr"
+.LASF15:
+	.string	"wstring"
+.LASF24:
+	.string	"func"
+.LASF18:
+	.string	"char"
+.LASF20:
+	.string	"long[]"
+	.ident	"GCC: (GNU) 6.0.0 20160123 (experimental)"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.dlang/typeprint.exp b/gdb/testsuite/gdb.dlang/typeprint.exp
new file mode 100644
index 0000000..9e42480
--- /dev/null
+++ b/gdb/testsuite/gdb.dlang/typeprint.exp
@@ -0,0 +1,80 @@ 
+# Copyright (C) 2016 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
+# 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/>.
+
+# Test printing various built-in types.
+
+load_lib "d-support.exp"
+load_lib "dwarf.exp"
+
+if { [skip_d_tests] } { continue }
+
+# This test can only be run on x86-64 targets which support DWARF.
+if {![dwarf2_support] || ![istarget "x86_64-*-*"] || ![is_lp64_target]} {
+    return 0
+}
+
+standard_testfile .S
+
+# Compile and start with a fresh gdb.
+
+if {[prepare_for_testing $testfile.exp $testfile $srcfile {nodebug}]} {
+    return -1
+}
+
+if {![runto_main]} {
+    return -1
+}
+
+# Simple pointer type.
+gdb_test "ptype voidptr" "type = void\\*"
+
+# Simple array type.
+gdb_test "ptype staticarray" "type = short\\\[1\\\]"
+
+# Function types are also pointers, but printed without the asterisk.
+gdb_test "ptype funcptr" "type = char function\\(byte\\)"
+
+# Delegates are two-field record types, but only the name is printed.
+gdb_test "ptype delegateptr" "type = char delegate\\(byte\\)"
+gdb_test "ptype delegateptr.object" "type = void\\*"
+gdb_test "ptype delegateptr.func" "type = char function\\(void\\*, byte\\)"
+
+# Likewise for dynamic arrays.
+gdb_test "ptype dynamicarray" "type = long\\\[\\\]"
+gdb_test "ptype dynamicarray.length" "type = ulong"
+gdb_test "ptype dynamicarray.ptr" "type = long\\*"
+
+# Likewise for associative arrays.
+gdb_test "ptype associativearray" "type = uint\\\[uint\\\]"
+gdb_test "ptype associativearray.ptr" "type = void\\*"
+
+# Strings are really dynamic arrays, but they are given a typename.
+gdb_test "ptype stringvalue" "type = string"
+gdb_test "ptype stringvalue.length" "type = ulong"
+gdb_test "ptype stringvalue.ptr" "type = char\\*"
+
+gdb_test "ptype wstringvalue" "type = wstring"
+gdb_test "ptype wstringvalue.length" "type = ulong"
+gdb_test "ptype wstringvalue.ptr" "type = wchar\\*"
+
+gdb_test "ptype dstringvalue" "type = dstring"
+gdb_test "ptype dstringvalue.length" "type = ulong"
+gdb_test "ptype dstringvalue.ptr" "type = dchar\\*"
+
+# Vectors have their own special syntax.
+gdb_test "ptype vectorarray" "type = __vector\\(ubyte\\\[8\\\]\\)"
+
+# Finally, recognize D modules.
+gdb_test "ptype typeprint" "type = module typeprint"