xref: /dflybsd-src/contrib/gcc-4.7/gcc/godump.c (revision 81fc95a5293ee307c688a350a3feb4734aaddbb4)
1e4b17023SJohn Marino /* Output Go language descriptions of types.
2*5ce9237cSJohn Marino    Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
3e4b17023SJohn Marino    Written by Ian Lance Taylor <iant@google.com>.
4e4b17023SJohn Marino 
5e4b17023SJohn Marino This file is part of GCC.
6e4b17023SJohn Marino 
7e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
8e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
9e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
10e4b17023SJohn Marino version.
11e4b17023SJohn Marino 
12e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
14e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15e4b17023SJohn Marino for more details.
16e4b17023SJohn Marino 
17e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
19e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
20e4b17023SJohn Marino 
21e4b17023SJohn Marino /* This file is used during the build process to emit Go language
22e4b17023SJohn Marino    descriptions of declarations from C header files.  It uses the
23e4b17023SJohn Marino    debug info hooks to emit the descriptions.  The Go language
24e4b17023SJohn Marino    descriptions then become part of the Go runtime support
25e4b17023SJohn Marino    library.
26e4b17023SJohn Marino 
27e4b17023SJohn Marino    All global names are output with a leading underscore, so that they
28e4b17023SJohn Marino    are all hidden in Go.  */
29e4b17023SJohn Marino 
30e4b17023SJohn Marino #include "config.h"
31e4b17023SJohn Marino #include "system.h"
32e4b17023SJohn Marino #include "coretypes.h"
33e4b17023SJohn Marino #include "diagnostic-core.h"
34e4b17023SJohn Marino #include "tree.h"
35e4b17023SJohn Marino #include "ggc.h"
36e4b17023SJohn Marino #include "pointer-set.h"
37e4b17023SJohn Marino #include "obstack.h"
38e4b17023SJohn Marino #include "debug.h"
39e4b17023SJohn Marino 
40e4b17023SJohn Marino /* We dump this information from the debug hooks.  This gives us a
41e4b17023SJohn Marino    stable and maintainable API to hook into.  In order to work
42e4b17023SJohn Marino    correctly when -g is used, we build our own hooks structure which
43e4b17023SJohn Marino    wraps the hooks we need to change.  */
44e4b17023SJohn Marino 
45e4b17023SJohn Marino /* Our debug hooks.  This is initialized by dump_go_spec_init.  */
46e4b17023SJohn Marino 
47e4b17023SJohn Marino static struct gcc_debug_hooks go_debug_hooks;
48e4b17023SJohn Marino 
49e4b17023SJohn Marino /* The real debug hooks.  */
50e4b17023SJohn Marino 
51e4b17023SJohn Marino static const struct gcc_debug_hooks *real_debug_hooks;
52e4b17023SJohn Marino 
53e4b17023SJohn Marino /* The file where we should write information.  */
54e4b17023SJohn Marino 
55e4b17023SJohn Marino static FILE *go_dump_file;
56e4b17023SJohn Marino 
57e4b17023SJohn Marino /* A queue of decls to output.  */
58e4b17023SJohn Marino 
59e4b17023SJohn Marino static GTY(()) VEC(tree,gc) *queue;
60e4b17023SJohn Marino 
61e4b17023SJohn Marino /* A hash table of macros we have seen.  */
62e4b17023SJohn Marino 
63e4b17023SJohn Marino static htab_t macro_hash;
64e4b17023SJohn Marino 
65e4b17023SJohn Marino /* The type of a value in macro_hash.  */
66e4b17023SJohn Marino 
67e4b17023SJohn Marino struct macro_hash_value
68e4b17023SJohn Marino {
69e4b17023SJohn Marino   /* The name stored in the hash table.  */
70e4b17023SJohn Marino   char *name;
71e4b17023SJohn Marino   /* The value of the macro.  */
72e4b17023SJohn Marino   char *value;
73e4b17023SJohn Marino };
74e4b17023SJohn Marino 
75e4b17023SJohn Marino /* Calculate the hash value for an entry in the macro hash table.  */
76e4b17023SJohn Marino 
77e4b17023SJohn Marino static hashval_t
macro_hash_hashval(const void * val)78e4b17023SJohn Marino macro_hash_hashval (const void *val)
79e4b17023SJohn Marino {
80e4b17023SJohn Marino   const struct macro_hash_value *mhval = (const struct macro_hash_value *) val;
81e4b17023SJohn Marino   return htab_hash_string (mhval->name);
82e4b17023SJohn Marino }
83e4b17023SJohn Marino 
84e4b17023SJohn Marino /* Compare values in the macro hash table for equality.  */
85e4b17023SJohn Marino 
86e4b17023SJohn Marino static int
macro_hash_eq(const void * v1,const void * v2)87e4b17023SJohn Marino macro_hash_eq (const void *v1, const void *v2)
88e4b17023SJohn Marino {
89e4b17023SJohn Marino   const struct macro_hash_value *mhv1 = (const struct macro_hash_value *) v1;
90e4b17023SJohn Marino   const struct macro_hash_value *mhv2 = (const struct macro_hash_value *) v2;
91e4b17023SJohn Marino   return strcmp (mhv1->name, mhv2->name) == 0;
92e4b17023SJohn Marino }
93e4b17023SJohn Marino 
94e4b17023SJohn Marino /* Free values deleted from the macro hash table.  */
95e4b17023SJohn Marino 
96e4b17023SJohn Marino static void
macro_hash_del(void * v)97e4b17023SJohn Marino macro_hash_del (void *v)
98e4b17023SJohn Marino {
99e4b17023SJohn Marino   struct macro_hash_value *mhv = (struct macro_hash_value *) v;
100e4b17023SJohn Marino   XDELETEVEC (mhv->name);
101e4b17023SJohn Marino   XDELETEVEC (mhv->value);
102e4b17023SJohn Marino   XDELETE (mhv);
103e4b17023SJohn Marino }
104e4b17023SJohn Marino 
105e4b17023SJohn Marino /* For the string hash tables.  */
106e4b17023SJohn Marino 
107e4b17023SJohn Marino static int
string_hash_eq(const void * y1,const void * y2)108e4b17023SJohn Marino string_hash_eq (const void *y1, const void *y2)
109e4b17023SJohn Marino {
110e4b17023SJohn Marino   return strcmp ((const char *) y1, (const char *) y2) == 0;
111e4b17023SJohn Marino }
112e4b17023SJohn Marino 
113e4b17023SJohn Marino /* A macro definition.  */
114e4b17023SJohn Marino 
115e4b17023SJohn Marino static void
go_define(unsigned int lineno,const char * buffer)116e4b17023SJohn Marino go_define (unsigned int lineno, const char *buffer)
117e4b17023SJohn Marino {
118e4b17023SJohn Marino   const char *p;
119e4b17023SJohn Marino   const char *name_end;
120e4b17023SJohn Marino   size_t out_len;
121e4b17023SJohn Marino   char *out_buffer;
122e4b17023SJohn Marino   char *q;
123e4b17023SJohn Marino   bool saw_operand;
124e4b17023SJohn Marino   bool need_operand;
125e4b17023SJohn Marino   struct macro_hash_value *mhval;
126e4b17023SJohn Marino   char *copy;
127e4b17023SJohn Marino   hashval_t hashval;
128e4b17023SJohn Marino   void **slot;
129e4b17023SJohn Marino 
130e4b17023SJohn Marino   real_debug_hooks->define (lineno, buffer);
131e4b17023SJohn Marino 
132e4b17023SJohn Marino   /* Skip macro functions.  */
133e4b17023SJohn Marino   for (p = buffer; *p != '\0' && *p != ' '; ++p)
134e4b17023SJohn Marino     if (*p == '(')
135e4b17023SJohn Marino       return;
136e4b17023SJohn Marino 
137e4b17023SJohn Marino   if (*p == '\0')
138e4b17023SJohn Marino     return;
139e4b17023SJohn Marino 
140e4b17023SJohn Marino   name_end = p;
141e4b17023SJohn Marino 
142e4b17023SJohn Marino   ++p;
143e4b17023SJohn Marino   if (*p == '\0')
144e4b17023SJohn Marino     return;
145e4b17023SJohn Marino 
146e4b17023SJohn Marino   copy = XNEWVEC (char, name_end - buffer + 1);
147e4b17023SJohn Marino   memcpy (copy, buffer, name_end - buffer);
148e4b17023SJohn Marino   copy[name_end - buffer] = '\0';
149e4b17023SJohn Marino 
150e4b17023SJohn Marino   mhval = XNEW (struct macro_hash_value);
151e4b17023SJohn Marino   mhval->name = copy;
152e4b17023SJohn Marino   mhval->value = NULL;
153e4b17023SJohn Marino 
154e4b17023SJohn Marino   hashval = htab_hash_string (copy);
155e4b17023SJohn Marino   slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, NO_INSERT);
156e4b17023SJohn Marino 
157e4b17023SJohn Marino   /* For simplicity, we force all names to be hidden by adding an
158e4b17023SJohn Marino      initial underscore, and let the user undo this as needed.  */
159e4b17023SJohn Marino   out_len = strlen (p) * 2 + 1;
160e4b17023SJohn Marino   out_buffer = XNEWVEC (char, out_len);
161e4b17023SJohn Marino   q = out_buffer;
162e4b17023SJohn Marino   saw_operand = false;
163e4b17023SJohn Marino   need_operand = false;
164e4b17023SJohn Marino   while (*p != '\0')
165e4b17023SJohn Marino     {
166e4b17023SJohn Marino       switch (*p)
167e4b17023SJohn Marino 	{
168e4b17023SJohn Marino 	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
169e4b17023SJohn Marino 	case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
170e4b17023SJohn Marino 	case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
171e4b17023SJohn Marino 	case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
172e4b17023SJohn Marino 	case 'Y': case 'Z':
173e4b17023SJohn Marino 	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
174e4b17023SJohn Marino 	case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
175e4b17023SJohn Marino 	case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
176e4b17023SJohn Marino 	case 's': case 't': case 'u': case 'v': case 'w': case 'x':
177e4b17023SJohn Marino 	case 'y': case 'z':
178e4b17023SJohn Marino 	case '_':
179e4b17023SJohn Marino 	  {
180e4b17023SJohn Marino 	    /* The start of an identifier.  Technically we should also
181e4b17023SJohn Marino 	       worry about UTF-8 identifiers, but they are not a
182e4b17023SJohn Marino 	       problem for practical uses of -fdump-go-spec so we
183e4b17023SJohn Marino 	       don't worry about them.  */
184e4b17023SJohn Marino 	    const char *start;
185e4b17023SJohn Marino 	    char *n;
186e4b17023SJohn Marino 	    struct macro_hash_value idval;
187e4b17023SJohn Marino 
188e4b17023SJohn Marino 	    if (saw_operand)
189e4b17023SJohn Marino 	      goto unknown;
190e4b17023SJohn Marino 
191e4b17023SJohn Marino 	    start = p;
192e4b17023SJohn Marino 	    while (ISALNUM (*p) || *p == '_')
193e4b17023SJohn Marino 	      ++p;
194e4b17023SJohn Marino 	    n = XALLOCAVEC (char, p - start + 1);
195e4b17023SJohn Marino 	    memcpy (n, start, p - start);
196e4b17023SJohn Marino 	    n[p - start] = '\0';
197e4b17023SJohn Marino 	    idval.name = n;
198e4b17023SJohn Marino 	    idval.value = NULL;
199e4b17023SJohn Marino 	    if (htab_find (macro_hash, &idval) == NULL)
200e4b17023SJohn Marino 	      {
201e4b17023SJohn Marino 		/* This is a reference to a name which was not defined
202e4b17023SJohn Marino 		   as a macro.  */
203e4b17023SJohn Marino 		goto unknown;
204e4b17023SJohn Marino 	      }
205e4b17023SJohn Marino 
206e4b17023SJohn Marino 	    *q++ = '_';
207e4b17023SJohn Marino 	    memcpy (q, start, p - start);
208e4b17023SJohn Marino 	    q += p - start;
209e4b17023SJohn Marino 
210e4b17023SJohn Marino 	    saw_operand = true;
211e4b17023SJohn Marino 	    need_operand = false;
212e4b17023SJohn Marino 	  }
213e4b17023SJohn Marino 	  break;
214e4b17023SJohn Marino 
215e4b17023SJohn Marino 	case '.':
216e4b17023SJohn Marino 	  if (!ISDIGIT (p[1]))
217e4b17023SJohn Marino 	    goto unknown;
218e4b17023SJohn Marino 	  /* Fall through.  */
219e4b17023SJohn Marino 	case '0': case '1': case '2': case '3': case '4':
220e4b17023SJohn Marino 	case '5': case '6': case '7': case '8': case '9':
221e4b17023SJohn Marino 	  {
222e4b17023SJohn Marino 	    const char *start;
223e4b17023SJohn Marino 	    bool is_hex;
224e4b17023SJohn Marino 
225e4b17023SJohn Marino 	    start = p;
226e4b17023SJohn Marino 	    is_hex = false;
227e4b17023SJohn Marino 	    if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
228e4b17023SJohn Marino 	      {
229e4b17023SJohn Marino 		p += 2;
230e4b17023SJohn Marino 		is_hex = true;
231e4b17023SJohn Marino 	      }
232e4b17023SJohn Marino 	    while (ISDIGIT (*p) || *p == '.' || *p == 'e' || *p == 'E'
233e4b17023SJohn Marino 		   || (is_hex
234e4b17023SJohn Marino 		       && ((*p >= 'a' && *p <= 'f')
235e4b17023SJohn Marino 			   || (*p >= 'A' && *p <= 'F'))))
236e4b17023SJohn Marino 	      ++p;
237e4b17023SJohn Marino 	    memcpy (q, start, p - start);
238e4b17023SJohn Marino 	    q += p - start;
239e4b17023SJohn Marino 	    while (*p == 'u' || *p == 'U' || *p == 'l' || *p == 'L'
240e4b17023SJohn Marino 		   || *p == 'f' || *p == 'F'
241e4b17023SJohn Marino 		   || *p == 'd' || *p == 'D')
242e4b17023SJohn Marino 	      {
243e4b17023SJohn Marino 		/* Go doesn't use any of these trailing type
244e4b17023SJohn Marino 		   modifiers.  */
245e4b17023SJohn Marino 		++p;
246e4b17023SJohn Marino 	      }
247e4b17023SJohn Marino 
248e4b17023SJohn Marino 	    /* We'll pick up the exponent, if any, as an
249e4b17023SJohn Marino 	       expression.  */
250e4b17023SJohn Marino 
251e4b17023SJohn Marino 	    saw_operand = true;
252e4b17023SJohn Marino 	    need_operand = false;
253e4b17023SJohn Marino 	  }
254e4b17023SJohn Marino 	  break;
255e4b17023SJohn Marino 
256e4b17023SJohn Marino 	case ' ': case '\t':
257e4b17023SJohn Marino 	  *q++ = *p++;
258e4b17023SJohn Marino 	  break;
259e4b17023SJohn Marino 
260e4b17023SJohn Marino 	case '(':
261e4b17023SJohn Marino 	  /* Always OK, not part of an operand, presumed to start an
262e4b17023SJohn Marino 	     operand.  */
263e4b17023SJohn Marino 	  *q++ = *p++;
264e4b17023SJohn Marino 	  saw_operand = false;
265e4b17023SJohn Marino 	  need_operand = false;
266e4b17023SJohn Marino 	  break;
267e4b17023SJohn Marino 
268e4b17023SJohn Marino 	case ')':
269e4b17023SJohn Marino 	  /* OK if we don't need an operand, and presumed to indicate
270e4b17023SJohn Marino 	     an operand.  */
271e4b17023SJohn Marino 	  if (need_operand)
272e4b17023SJohn Marino 	    goto unknown;
273e4b17023SJohn Marino 	  *q++ = *p++;
274e4b17023SJohn Marino 	  saw_operand = true;
275e4b17023SJohn Marino 	  break;
276e4b17023SJohn Marino 
277e4b17023SJohn Marino 	case '+': case '-':
278e4b17023SJohn Marino 	  /* Always OK, but not part of an operand.  */
279e4b17023SJohn Marino 	  *q++ = *p++;
280e4b17023SJohn Marino 	  saw_operand = false;
281e4b17023SJohn Marino 	  break;
282e4b17023SJohn Marino 
283e4b17023SJohn Marino 	case '*': case '/': case '%': case '|': case '&': case '^':
284e4b17023SJohn Marino 	  /* Must be a binary operator.  */
285e4b17023SJohn Marino 	  if (!saw_operand)
286e4b17023SJohn Marino 	    goto unknown;
287e4b17023SJohn Marino 	  *q++ = *p++;
288e4b17023SJohn Marino 	  saw_operand = false;
289e4b17023SJohn Marino 	  need_operand = true;
290e4b17023SJohn Marino 	  break;
291e4b17023SJohn Marino 
292e4b17023SJohn Marino 	case '=':
293e4b17023SJohn Marino 	  *q++ = *p++;
294e4b17023SJohn Marino 	  if (*p != '=')
295e4b17023SJohn Marino 	    goto unknown;
296e4b17023SJohn Marino 	  /* Must be a binary operator.  */
297e4b17023SJohn Marino 	  if (!saw_operand)
298e4b17023SJohn Marino 	    goto unknown;
299e4b17023SJohn Marino 	  *q++ = *p++;
300e4b17023SJohn Marino 	  saw_operand = false;
301e4b17023SJohn Marino 	  need_operand = true;
302e4b17023SJohn Marino 	  break;
303e4b17023SJohn Marino 
304e4b17023SJohn Marino 	case '!':
305e4b17023SJohn Marino 	  *q++ = *p++;
306e4b17023SJohn Marino 	  if (*p == '=')
307e4b17023SJohn Marino 	    {
308e4b17023SJohn Marino 	      /* Must be a binary operator.  */
309e4b17023SJohn Marino 	      if (!saw_operand)
310e4b17023SJohn Marino 		goto unknown;
311e4b17023SJohn Marino 	      *q++ = *p++;
312e4b17023SJohn Marino 	      saw_operand = false;
313e4b17023SJohn Marino 	      need_operand = true;
314e4b17023SJohn Marino 	    }
315e4b17023SJohn Marino 	  else
316e4b17023SJohn Marino 	    {
317e4b17023SJohn Marino 	      /* Must be a unary operator.  */
318e4b17023SJohn Marino 	      if (saw_operand)
319e4b17023SJohn Marino 		goto unknown;
320e4b17023SJohn Marino 	      need_operand = true;
321e4b17023SJohn Marino 	    }
322e4b17023SJohn Marino 	  break;
323e4b17023SJohn Marino 
324e4b17023SJohn Marino 	case '<': case '>':
325e4b17023SJohn Marino 	  /* Must be a binary operand, may be << or >> or <= or >=.  */
326e4b17023SJohn Marino 	  if (!saw_operand)
327e4b17023SJohn Marino 	    goto unknown;
328e4b17023SJohn Marino 	  *q++ = *p++;
329e4b17023SJohn Marino 	  if (*p == *(p - 1) || *p == '=')
330e4b17023SJohn Marino 	    *q++ = *p++;
331e4b17023SJohn Marino 	  saw_operand = false;
332e4b17023SJohn Marino 	  need_operand = true;
333e4b17023SJohn Marino 	  break;
334e4b17023SJohn Marino 
335e4b17023SJohn Marino 	case '~':
336e4b17023SJohn Marino 	  /* Must be a unary operand, must be translated for Go.  */
337e4b17023SJohn Marino 	  if (saw_operand)
338e4b17023SJohn Marino 	    goto unknown;
339e4b17023SJohn Marino 	  *q++ = '^';
340e4b17023SJohn Marino 	  p++;
341e4b17023SJohn Marino 	  need_operand = true;
342e4b17023SJohn Marino 	  break;
343e4b17023SJohn Marino 
344e4b17023SJohn Marino 	case '"':
345e4b17023SJohn Marino 	case '\'':
346e4b17023SJohn Marino 	  {
347e4b17023SJohn Marino 	    char quote;
348e4b17023SJohn Marino 	    int count;
349e4b17023SJohn Marino 
350e4b17023SJohn Marino 	    if (saw_operand)
351e4b17023SJohn Marino 	      goto unknown;
352e4b17023SJohn Marino 	    quote = *p;
353e4b17023SJohn Marino 	    *q++ = *p++;
354e4b17023SJohn Marino 	    count = 0;
355e4b17023SJohn Marino 	    while (*p != quote)
356e4b17023SJohn Marino 	      {
357e4b17023SJohn Marino 		int c;
358e4b17023SJohn Marino 
359e4b17023SJohn Marino 		if (*p == '\0')
360e4b17023SJohn Marino 		  goto unknown;
361e4b17023SJohn Marino 
362e4b17023SJohn Marino 		++count;
363e4b17023SJohn Marino 
364e4b17023SJohn Marino 		if (*p != '\\')
365e4b17023SJohn Marino 		  {
366e4b17023SJohn Marino 		    *q++ = *p++;
367e4b17023SJohn Marino 		    continue;
368e4b17023SJohn Marino 		  }
369e4b17023SJohn Marino 
370e4b17023SJohn Marino 		*q++ = *p++;
371e4b17023SJohn Marino 		switch (*p)
372e4b17023SJohn Marino 		  {
373e4b17023SJohn Marino 		  case '0': case '1': case '2': case '3':
374e4b17023SJohn Marino 		  case '4': case '5': case '6': case '7':
375e4b17023SJohn Marino 		    c = 0;
376e4b17023SJohn Marino 		    while (*p >= '0' && *p <= '7')
377e4b17023SJohn Marino 		      {
378e4b17023SJohn Marino 			*q++ = *p++;
379e4b17023SJohn Marino 			++c;
380e4b17023SJohn Marino 		      }
381e4b17023SJohn Marino 		    /* Go octal characters are always 3
382e4b17023SJohn Marino 		       digits.  */
383e4b17023SJohn Marino 		    if (c != 3)
384e4b17023SJohn Marino 		      goto unknown;
385e4b17023SJohn Marino 		    break;
386e4b17023SJohn Marino 
387e4b17023SJohn Marino 		  case 'x':
388e4b17023SJohn Marino 		    *q++ = *p++;
389e4b17023SJohn Marino 		    c = 0;
390e4b17023SJohn Marino 		    while (ISXDIGIT (*p))
391e4b17023SJohn Marino 		      {
392e4b17023SJohn Marino 			*q++ = *p++;
393e4b17023SJohn Marino 			++c;
394e4b17023SJohn Marino 		      }
395e4b17023SJohn Marino 		    /* Go hex characters are always 2 digits.  */
396e4b17023SJohn Marino 		    if (c != 2)
397e4b17023SJohn Marino 		      goto unknown;
398e4b17023SJohn Marino 		    break;
399e4b17023SJohn Marino 
400e4b17023SJohn Marino 		  case 'a': case 'b': case 'f': case 'n': case 'r':
401e4b17023SJohn Marino 		  case 't': case 'v': case '\\': case '\'': case '"':
402e4b17023SJohn Marino 		    *q++ = *p++;
403e4b17023SJohn Marino 		    break;
404e4b17023SJohn Marino 
405e4b17023SJohn Marino 		  default:
406e4b17023SJohn Marino 		    goto unknown;
407e4b17023SJohn Marino 		  }
408e4b17023SJohn Marino 	      }
409e4b17023SJohn Marino 
410e4b17023SJohn Marino 	    *q++ = *p++;
411e4b17023SJohn Marino 
412e4b17023SJohn Marino 	    if (quote == '\'' && count != 1)
413e4b17023SJohn Marino 	      goto unknown;
414e4b17023SJohn Marino 
415e4b17023SJohn Marino 	    saw_operand = true;
416e4b17023SJohn Marino 	    need_operand = false;
417e4b17023SJohn Marino 
418e4b17023SJohn Marino 	    break;
419e4b17023SJohn Marino 	  }
420e4b17023SJohn Marino 
421e4b17023SJohn Marino 	default:
422e4b17023SJohn Marino 	  goto unknown;
423e4b17023SJohn Marino 	}
424e4b17023SJohn Marino     }
425e4b17023SJohn Marino 
426e4b17023SJohn Marino   if (need_operand)
427e4b17023SJohn Marino     goto unknown;
428e4b17023SJohn Marino 
429e4b17023SJohn Marino   gcc_assert ((size_t) (q - out_buffer) < out_len);
430e4b17023SJohn Marino   *q = '\0';
431e4b17023SJohn Marino 
432e4b17023SJohn Marino   mhval->value = out_buffer;
433e4b17023SJohn Marino 
434e4b17023SJohn Marino   if (slot == NULL)
435e4b17023SJohn Marino     {
436e4b17023SJohn Marino       slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, INSERT);
437e4b17023SJohn Marino       gcc_assert (slot != NULL && *slot == NULL);
438e4b17023SJohn Marino     }
439e4b17023SJohn Marino   else
440e4b17023SJohn Marino     {
441e4b17023SJohn Marino       if (*slot != NULL)
442e4b17023SJohn Marino 	macro_hash_del (*slot);
443e4b17023SJohn Marino     }
444e4b17023SJohn Marino 
445e4b17023SJohn Marino   *slot = mhval;
446e4b17023SJohn Marino 
447e4b17023SJohn Marino   return;
448e4b17023SJohn Marino 
449e4b17023SJohn Marino  unknown:
450e4b17023SJohn Marino   fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
451e4b17023SJohn Marino   if (slot != NULL)
452e4b17023SJohn Marino     htab_clear_slot (macro_hash, slot);
453e4b17023SJohn Marino   XDELETEVEC (out_buffer);
454e4b17023SJohn Marino   XDELETEVEC (copy);
455e4b17023SJohn Marino }
456e4b17023SJohn Marino 
457e4b17023SJohn Marino /* A macro undef.  */
458e4b17023SJohn Marino 
459e4b17023SJohn Marino static void
go_undef(unsigned int lineno,const char * buffer)460e4b17023SJohn Marino go_undef (unsigned int lineno, const char *buffer)
461e4b17023SJohn Marino {
462e4b17023SJohn Marino   struct macro_hash_value mhval;
463e4b17023SJohn Marino   void **slot;
464e4b17023SJohn Marino 
465e4b17023SJohn Marino   real_debug_hooks->undef (lineno, buffer);
466e4b17023SJohn Marino 
467e4b17023SJohn Marino   mhval.name = CONST_CAST (char *, buffer);
468e4b17023SJohn Marino   mhval.value = NULL;
469e4b17023SJohn Marino   slot = htab_find_slot (macro_hash, &mhval, NO_INSERT);
470e4b17023SJohn Marino   if (slot != NULL)
471e4b17023SJohn Marino     htab_clear_slot (macro_hash, slot);
472e4b17023SJohn Marino }
473e4b17023SJohn Marino 
474e4b17023SJohn Marino /* A function or variable decl.  */
475e4b17023SJohn Marino 
476e4b17023SJohn Marino static void
go_decl(tree decl)477e4b17023SJohn Marino go_decl (tree decl)
478e4b17023SJohn Marino {
479e4b17023SJohn Marino   if (!TREE_PUBLIC (decl)
480e4b17023SJohn Marino       || DECL_IS_BUILTIN (decl)
481e4b17023SJohn Marino       || DECL_NAME (decl) == NULL_TREE)
482e4b17023SJohn Marino     return;
483e4b17023SJohn Marino   VEC_safe_push (tree, gc, queue, decl);
484e4b17023SJohn Marino }
485e4b17023SJohn Marino 
486e4b17023SJohn Marino /* A function decl.  */
487e4b17023SJohn Marino 
488e4b17023SJohn Marino static void
go_function_decl(tree decl)489e4b17023SJohn Marino go_function_decl (tree decl)
490e4b17023SJohn Marino {
491e4b17023SJohn Marino   real_debug_hooks->function_decl (decl);
492e4b17023SJohn Marino   go_decl (decl);
493e4b17023SJohn Marino }
494e4b17023SJohn Marino 
495e4b17023SJohn Marino /* A global variable decl.  */
496e4b17023SJohn Marino 
497e4b17023SJohn Marino static void
go_global_decl(tree decl)498e4b17023SJohn Marino go_global_decl (tree decl)
499e4b17023SJohn Marino {
500e4b17023SJohn Marino   real_debug_hooks->global_decl (decl);
501e4b17023SJohn Marino   go_decl (decl);
502e4b17023SJohn Marino }
503e4b17023SJohn Marino 
504e4b17023SJohn Marino /* A type declaration.  */
505e4b17023SJohn Marino 
506e4b17023SJohn Marino static void
go_type_decl(tree decl,int local)507e4b17023SJohn Marino go_type_decl (tree decl, int local)
508e4b17023SJohn Marino {
509e4b17023SJohn Marino   real_debug_hooks->type_decl (decl, local);
510e4b17023SJohn Marino 
511e4b17023SJohn Marino   if (local || DECL_IS_BUILTIN (decl))
512e4b17023SJohn Marino     return;
513e4b17023SJohn Marino   if (DECL_NAME (decl) == NULL_TREE
514e4b17023SJohn Marino       && (TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE
515e4b17023SJohn Marino 	  || TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) != IDENTIFIER_NODE)
516e4b17023SJohn Marino       && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
517e4b17023SJohn Marino     return;
518e4b17023SJohn Marino   VEC_safe_push (tree, gc, queue, decl);
519e4b17023SJohn Marino }
520e4b17023SJohn Marino 
521e4b17023SJohn Marino /* A container for the data we pass around when generating information
522e4b17023SJohn Marino    at the end of the compilation.  */
523e4b17023SJohn Marino 
524e4b17023SJohn Marino struct godump_container
525e4b17023SJohn Marino {
526e4b17023SJohn Marino   /* DECLs that we have already seen.  */
527e4b17023SJohn Marino   struct pointer_set_t *decls_seen;
528e4b17023SJohn Marino 
529e4b17023SJohn Marino   /* Types which may potentially have to be defined as dummy
530e4b17023SJohn Marino      types.  */
531e4b17023SJohn Marino   struct pointer_set_t *pot_dummy_types;
532e4b17023SJohn Marino 
533e4b17023SJohn Marino   /* Go keywords.  */
534e4b17023SJohn Marino   htab_t keyword_hash;
535e4b17023SJohn Marino 
536e4b17023SJohn Marino   /* Global type definitions.  */
537e4b17023SJohn Marino   htab_t type_hash;
538e4b17023SJohn Marino 
539e4b17023SJohn Marino   /* Invalid types.  */
540e4b17023SJohn Marino   htab_t invalid_hash;
541e4b17023SJohn Marino 
542e4b17023SJohn Marino   /* Obstack used to write out a type definition.  */
543e4b17023SJohn Marino   struct obstack type_obstack;
544e4b17023SJohn Marino };
545e4b17023SJohn Marino 
546e4b17023SJohn Marino /* Append an IDENTIFIER_NODE to OB.  */
547e4b17023SJohn Marino 
548e4b17023SJohn Marino static void
go_append_string(struct obstack * ob,tree id)549e4b17023SJohn Marino go_append_string (struct obstack *ob, tree id)
550e4b17023SJohn Marino {
551e4b17023SJohn Marino   obstack_grow (ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
552e4b17023SJohn Marino }
553e4b17023SJohn Marino 
554e4b17023SJohn Marino /* Write the Go version of TYPE to CONTAINER->TYPE_OBSTACK.
555e4b17023SJohn Marino    USE_TYPE_NAME is true if we can simply use a type name here without
556e4b17023SJohn Marino    needing to define it.  IS_FUNC_OK is true if we can output a func
557e4b17023SJohn Marino    type here; the "func" keyword will already have been added.  Return
558e4b17023SJohn Marino    true if the type can be represented in Go, false otherwise.  */
559e4b17023SJohn Marino 
560e4b17023SJohn Marino static bool
go_format_type(struct godump_container * container,tree type,bool use_type_name,bool is_func_ok)561e4b17023SJohn Marino go_format_type (struct godump_container *container, tree type,
562e4b17023SJohn Marino 		bool use_type_name, bool is_func_ok)
563e4b17023SJohn Marino {
564e4b17023SJohn Marino   bool ret;
565e4b17023SJohn Marino   struct obstack *ob;
566e4b17023SJohn Marino 
567e4b17023SJohn Marino   ret = true;
568e4b17023SJohn Marino   ob = &container->type_obstack;
569e4b17023SJohn Marino 
570e4b17023SJohn Marino   if (TYPE_NAME (type) != NULL_TREE
571e4b17023SJohn Marino       && (pointer_set_contains (container->decls_seen, type)
572e4b17023SJohn Marino 	  || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
573e4b17023SJohn Marino       && (AGGREGATE_TYPE_P (type)
574e4b17023SJohn Marino 	  || POINTER_TYPE_P (type)
575e4b17023SJohn Marino 	  || TREE_CODE (type) == FUNCTION_TYPE))
576e4b17023SJohn Marino     {
577e4b17023SJohn Marino       tree name;
578e4b17023SJohn Marino       void **slot;
579e4b17023SJohn Marino 
580e4b17023SJohn Marino       name = TYPE_NAME (type);
581e4b17023SJohn Marino       if (TREE_CODE (name) == TYPE_DECL)
582e4b17023SJohn Marino 	name = DECL_NAME (name);
583e4b17023SJohn Marino 
584e4b17023SJohn Marino       slot = htab_find_slot (container->invalid_hash, IDENTIFIER_POINTER (name),
585e4b17023SJohn Marino 			     NO_INSERT);
586e4b17023SJohn Marino       if (slot != NULL)
587e4b17023SJohn Marino 	ret = false;
588e4b17023SJohn Marino 
589e4b17023SJohn Marino       obstack_1grow (ob, '_');
590e4b17023SJohn Marino       go_append_string (ob, name);
591e4b17023SJohn Marino       return ret;
592e4b17023SJohn Marino     }
593e4b17023SJohn Marino 
594e4b17023SJohn Marino   pointer_set_insert (container->decls_seen, type);
595e4b17023SJohn Marino 
596e4b17023SJohn Marino   switch (TREE_CODE (type))
597e4b17023SJohn Marino     {
598e4b17023SJohn Marino     case ENUMERAL_TYPE:
599e4b17023SJohn Marino       obstack_grow (ob, "int", 3);
600e4b17023SJohn Marino       break;
601e4b17023SJohn Marino 
602e4b17023SJohn Marino     case TYPE_DECL:
603e4b17023SJohn Marino       {
604e4b17023SJohn Marino 	void **slot;
605e4b17023SJohn Marino 
606e4b17023SJohn Marino 	slot = htab_find_slot (container->invalid_hash,
607e4b17023SJohn Marino 			       IDENTIFIER_POINTER (DECL_NAME (type)),
608e4b17023SJohn Marino 			       NO_INSERT);
609e4b17023SJohn Marino 	if (slot != NULL)
610e4b17023SJohn Marino 	  ret = false;
611e4b17023SJohn Marino 
612e4b17023SJohn Marino 	obstack_1grow (ob, '_');
613e4b17023SJohn Marino 	go_append_string (ob, DECL_NAME (type));
614e4b17023SJohn Marino       }
615e4b17023SJohn Marino       break;
616e4b17023SJohn Marino 
617e4b17023SJohn Marino     case INTEGER_TYPE:
618e4b17023SJohn Marino       {
619e4b17023SJohn Marino 	const char *s;
620e4b17023SJohn Marino 	char buf[100];
621e4b17023SJohn Marino 
622e4b17023SJohn Marino 	switch (TYPE_PRECISION (type))
623e4b17023SJohn Marino 	  {
624e4b17023SJohn Marino 	  case 8:
625e4b17023SJohn Marino 	    s = TYPE_UNSIGNED (type) ? "uint8" : "int8";
626e4b17023SJohn Marino 	    break;
627e4b17023SJohn Marino 	  case 16:
628e4b17023SJohn Marino 	    s = TYPE_UNSIGNED (type) ? "uint16" : "int16";
629e4b17023SJohn Marino 	    break;
630e4b17023SJohn Marino 	  case 32:
631e4b17023SJohn Marino 	    s = TYPE_UNSIGNED (type) ? "uint32" : "int32";
632e4b17023SJohn Marino 	    break;
633e4b17023SJohn Marino 	  case 64:
634e4b17023SJohn Marino 	    s = TYPE_UNSIGNED (type) ? "uint64" : "int64";
635e4b17023SJohn Marino 	    break;
636e4b17023SJohn Marino 	  default:
637e4b17023SJohn Marino 	    snprintf (buf, sizeof buf, "INVALID-int-%u%s",
638e4b17023SJohn Marino 		      TYPE_PRECISION (type),
639e4b17023SJohn Marino 		      TYPE_UNSIGNED (type) ? "u" : "");
640e4b17023SJohn Marino 	    s = buf;
641e4b17023SJohn Marino 	    ret = false;
642e4b17023SJohn Marino 	    break;
643e4b17023SJohn Marino 	  }
644e4b17023SJohn Marino 	obstack_grow (ob, s, strlen (s));
645e4b17023SJohn Marino       }
646e4b17023SJohn Marino       break;
647e4b17023SJohn Marino 
648e4b17023SJohn Marino     case REAL_TYPE:
649e4b17023SJohn Marino       {
650e4b17023SJohn Marino 	const char *s;
651e4b17023SJohn Marino 	char buf[100];
652e4b17023SJohn Marino 
653e4b17023SJohn Marino 	switch (TYPE_PRECISION (type))
654e4b17023SJohn Marino 	  {
655e4b17023SJohn Marino 	  case 32:
656e4b17023SJohn Marino 	    s = "float32";
657e4b17023SJohn Marino 	    break;
658e4b17023SJohn Marino 	  case 64:
659e4b17023SJohn Marino 	    s = "float64";
660e4b17023SJohn Marino 	    break;
661e4b17023SJohn Marino 	  default:
662e4b17023SJohn Marino 	    snprintf (buf, sizeof buf, "INVALID-float-%u",
663e4b17023SJohn Marino 		      TYPE_PRECISION (type));
664e4b17023SJohn Marino 	    s = buf;
665e4b17023SJohn Marino 	    ret = false;
666e4b17023SJohn Marino 	    break;
667e4b17023SJohn Marino 	  }
668e4b17023SJohn Marino 	obstack_grow (ob, s, strlen (s));
669e4b17023SJohn Marino       }
670e4b17023SJohn Marino       break;
671e4b17023SJohn Marino 
672e4b17023SJohn Marino     case BOOLEAN_TYPE:
673e4b17023SJohn Marino       obstack_grow (ob, "bool", 4);
674e4b17023SJohn Marino       break;
675e4b17023SJohn Marino 
676e4b17023SJohn Marino     case POINTER_TYPE:
677e4b17023SJohn Marino       if (use_type_name
678e4b17023SJohn Marino           && TYPE_NAME (TREE_TYPE (type)) != NULL_TREE
679e4b17023SJohn Marino           && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))
680e4b17023SJohn Marino 	      || (POINTER_TYPE_P (TREE_TYPE (type))
681e4b17023SJohn Marino                   && (TREE_CODE (TREE_TYPE (TREE_TYPE (type)))
682e4b17023SJohn Marino 		      == FUNCTION_TYPE))))
683e4b17023SJohn Marino         {
684e4b17023SJohn Marino 	  tree name;
685e4b17023SJohn Marino 	  void **slot;
686e4b17023SJohn Marino 
687e4b17023SJohn Marino 	  name = TYPE_NAME (TREE_TYPE (type));
688e4b17023SJohn Marino 	  if (TREE_CODE (name) == TYPE_DECL)
689e4b17023SJohn Marino 	    name = DECL_NAME (name);
690e4b17023SJohn Marino 
691e4b17023SJohn Marino 	  slot = htab_find_slot (container->invalid_hash,
692e4b17023SJohn Marino 				 IDENTIFIER_POINTER (name), NO_INSERT);
693e4b17023SJohn Marino 	  if (slot != NULL)
694e4b17023SJohn Marino 	    ret = false;
695e4b17023SJohn Marino 
696e4b17023SJohn Marino 	  obstack_grow (ob, "*_", 2);
697e4b17023SJohn Marino 	  go_append_string (ob, name);
698e4b17023SJohn Marino 
699e4b17023SJohn Marino 	  /* The pointer here can be used without the struct or union
700e4b17023SJohn Marino 	     definition.  So this struct or union is a potential dummy
701e4b17023SJohn Marino 	     type.  */
702e4b17023SJohn Marino 	  if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
703e4b17023SJohn Marino 	    pointer_set_insert (container->pot_dummy_types,
704e4b17023SJohn Marino 				IDENTIFIER_POINTER (name));
705e4b17023SJohn Marino 
706e4b17023SJohn Marino 	  return ret;
707e4b17023SJohn Marino         }
708e4b17023SJohn Marino       if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
709e4b17023SJohn Marino 	obstack_grow (ob, "func", 4);
710e4b17023SJohn Marino       else
711e4b17023SJohn Marino 	obstack_1grow (ob, '*');
712e4b17023SJohn Marino       if (VOID_TYPE_P (TREE_TYPE (type)))
713e4b17023SJohn Marino 	obstack_grow (ob, "byte", 4);
714e4b17023SJohn Marino       else
715e4b17023SJohn Marino 	{
716e4b17023SJohn Marino 	  if (!go_format_type (container, TREE_TYPE (type), use_type_name,
717e4b17023SJohn Marino 			       true))
718e4b17023SJohn Marino 	    ret = false;
719e4b17023SJohn Marino 	}
720e4b17023SJohn Marino       break;
721e4b17023SJohn Marino 
722e4b17023SJohn Marino     case ARRAY_TYPE:
723e4b17023SJohn Marino       obstack_1grow (ob, '[');
724e4b17023SJohn Marino       if (TYPE_DOMAIN (type) != NULL_TREE
725e4b17023SJohn Marino 	  && TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
726e4b17023SJohn Marino 	  && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
727e4b17023SJohn Marino 	  && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
728e4b17023SJohn Marino 	  && tree_int_cst_sgn (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == 0
729e4b17023SJohn Marino 	  && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
730e4b17023SJohn Marino 	  && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
731e4b17023SJohn Marino 	  && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0))
732e4b17023SJohn Marino 	{
733e4b17023SJohn Marino 	  char buf[100];
734e4b17023SJohn Marino 
735e4b17023SJohn Marino 	  snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC "+1",
736e4b17023SJohn Marino 		    tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0));
737e4b17023SJohn Marino 	  obstack_grow (ob, buf, strlen (buf));
738e4b17023SJohn Marino 	}
739e4b17023SJohn Marino       obstack_1grow (ob, ']');
740e4b17023SJohn Marino       if (!go_format_type (container, TREE_TYPE (type), use_type_name, false))
741e4b17023SJohn Marino 	ret = false;
742e4b17023SJohn Marino       break;
743e4b17023SJohn Marino 
744e4b17023SJohn Marino     case UNION_TYPE:
745e4b17023SJohn Marino     case RECORD_TYPE:
746e4b17023SJohn Marino       {
747e4b17023SJohn Marino 	tree field;
748e4b17023SJohn Marino 	int i;
749e4b17023SJohn Marino 
750e4b17023SJohn Marino 	obstack_grow (ob, "struct { ", 9);
751e4b17023SJohn Marino 	i = 0;
752e4b17023SJohn Marino 	for (field = TYPE_FIELDS (type);
753e4b17023SJohn Marino 	     field != NULL_TREE;
754e4b17023SJohn Marino 	     field = TREE_CHAIN (field))
755e4b17023SJohn Marino 	  {
756e4b17023SJohn Marino 	    struct obstack hold_type_obstack;
757e4b17023SJohn Marino 	    bool field_ok;
758e4b17023SJohn Marino 
759e4b17023SJohn Marino 	    if (TREE_CODE (type) == UNION_TYPE)
760e4b17023SJohn Marino 	      {
761e4b17023SJohn Marino 		hold_type_obstack = container->type_obstack;
762e4b17023SJohn Marino 		obstack_init (&container->type_obstack);
763e4b17023SJohn Marino 	      }
764e4b17023SJohn Marino 
765e4b17023SJohn Marino 	    field_ok = true;
766e4b17023SJohn Marino 
767e4b17023SJohn Marino 	    if (DECL_NAME (field) == NULL)
768e4b17023SJohn Marino 	      {
769e4b17023SJohn Marino 		char buf[100];
770e4b17023SJohn Marino 
771e4b17023SJohn Marino 		obstack_grow (ob, "Godump_", 7);
772e4b17023SJohn Marino 		snprintf (buf, sizeof buf, "%d", i);
773e4b17023SJohn Marino 		obstack_grow (ob, buf, strlen (buf));
774e4b17023SJohn Marino 		i++;
775e4b17023SJohn Marino 	      }
776e4b17023SJohn Marino 	    else
777e4b17023SJohn Marino               {
778e4b17023SJohn Marino 		const char *var_name;
779e4b17023SJohn Marino 		void **slot;
780e4b17023SJohn Marino 
781e4b17023SJohn Marino 		/* Start variable name with an underscore if a keyword.  */
782e4b17023SJohn Marino 		var_name = IDENTIFIER_POINTER (DECL_NAME (field));
783e4b17023SJohn Marino 		slot = htab_find_slot (container->keyword_hash, var_name,
784e4b17023SJohn Marino 				       NO_INSERT);
785e4b17023SJohn Marino 		if (slot != NULL)
786e4b17023SJohn Marino 		  obstack_1grow (ob, '_');
787e4b17023SJohn Marino 		go_append_string (ob, DECL_NAME (field));
788e4b17023SJohn Marino 	      }
789e4b17023SJohn Marino 	    obstack_1grow (ob, ' ');
790e4b17023SJohn Marino 	    if (DECL_BIT_FIELD (field))
791e4b17023SJohn Marino 	      {
792e4b17023SJohn Marino 		obstack_grow (ob, "INVALID-bit-field", 17);
793e4b17023SJohn Marino 		field_ok = false;
794e4b17023SJohn Marino 	      }
795e4b17023SJohn Marino 	    else
796e4b17023SJohn Marino               {
797e4b17023SJohn Marino 		/* Do not expand type if a record or union type or a
798e4b17023SJohn Marino 		   function pointer.  */
799e4b17023SJohn Marino 		if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
800e4b17023SJohn Marino 		    && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
801e4b17023SJohn Marino 			|| (POINTER_TYPE_P (TREE_TYPE (field))
802e4b17023SJohn Marino 			    && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
803e4b17023SJohn Marino                                 == FUNCTION_TYPE))))
804e4b17023SJohn Marino 		  {
805e4b17023SJohn Marino 		    tree name;
806e4b17023SJohn Marino 		    void **slot;
807e4b17023SJohn Marino 
808e4b17023SJohn Marino 		    name = TYPE_NAME (TREE_TYPE (field));
809e4b17023SJohn Marino 		    if (TREE_CODE (name) == TYPE_DECL)
810e4b17023SJohn Marino 		      name = DECL_NAME (name);
811e4b17023SJohn Marino 
812e4b17023SJohn Marino 		    slot = htab_find_slot (container->invalid_hash,
813e4b17023SJohn Marino 					   IDENTIFIER_POINTER (name),
814e4b17023SJohn Marino 					   NO_INSERT);
815e4b17023SJohn Marino 		    if (slot != NULL)
816e4b17023SJohn Marino 		      field_ok = false;
817e4b17023SJohn Marino 
818e4b17023SJohn Marino 		    obstack_1grow (ob, '_');
819e4b17023SJohn Marino 		    go_append_string (ob, name);
820e4b17023SJohn Marino 		  }
821e4b17023SJohn Marino 		else
822e4b17023SJohn Marino 		  {
823e4b17023SJohn Marino 		    if (!go_format_type (container, TREE_TYPE (field), true,
824e4b17023SJohn Marino 					 false))
825e4b17023SJohn Marino 		      field_ok = false;
826e4b17023SJohn Marino 		  }
827e4b17023SJohn Marino               }
828e4b17023SJohn Marino 	    obstack_grow (ob, "; ", 2);
829e4b17023SJohn Marino 
830e4b17023SJohn Marino 	    /* Only output the first successful field of a union, and
831e4b17023SJohn Marino 	       hope for the best.  */
832e4b17023SJohn Marino 	    if (TREE_CODE (type) == UNION_TYPE)
833e4b17023SJohn Marino 	      {
834e4b17023SJohn Marino 		if (!field_ok && TREE_CHAIN (field) == NULL_TREE)
835e4b17023SJohn Marino 		  {
836e4b17023SJohn Marino 		    field_ok = true;
837e4b17023SJohn Marino 		    ret = false;
838e4b17023SJohn Marino 		  }
839e4b17023SJohn Marino 		if (field_ok)
840e4b17023SJohn Marino 		  {
841e4b17023SJohn Marino 		    unsigned int sz;
842e4b17023SJohn Marino 
843e4b17023SJohn Marino 		    sz = obstack_object_size (&container->type_obstack);
844e4b17023SJohn Marino 		    obstack_grow (&hold_type_obstack,
845e4b17023SJohn Marino 				  obstack_base (&container->type_obstack),
846e4b17023SJohn Marino 				  sz);
847e4b17023SJohn Marino 		  }
848e4b17023SJohn Marino 		obstack_free (&container->type_obstack, NULL);
849e4b17023SJohn Marino 		container->type_obstack = hold_type_obstack;
850e4b17023SJohn Marino 		if (field_ok)
851e4b17023SJohn Marino 		  break;
852e4b17023SJohn Marino 	      }
853e4b17023SJohn Marino 	    else
854e4b17023SJohn Marino 	      {
855e4b17023SJohn Marino 		if (!field_ok)
856e4b17023SJohn Marino 		  ret = false;
857e4b17023SJohn Marino 	      }
858e4b17023SJohn Marino 	  }
859e4b17023SJohn Marino 	obstack_1grow (ob, '}');
860e4b17023SJohn Marino       }
861e4b17023SJohn Marino       break;
862e4b17023SJohn Marino 
863e4b17023SJohn Marino     case FUNCTION_TYPE:
864e4b17023SJohn Marino       {
865e4b17023SJohn Marino 	tree arg_type;
866e4b17023SJohn Marino 	bool is_varargs;
867e4b17023SJohn Marino 	tree result;
868e4b17023SJohn Marino 	function_args_iterator iter;
869e4b17023SJohn Marino 	bool seen_arg;
870e4b17023SJohn Marino 
871e4b17023SJohn Marino 	/* Go has no way to write a type which is a function but not a
872e4b17023SJohn Marino 	   pointer to a function.  */
873e4b17023SJohn Marino 	if (!is_func_ok)
874e4b17023SJohn Marino 	  {
875e4b17023SJohn Marino 	    obstack_grow (ob, "func*", 5);
876e4b17023SJohn Marino 	    ret = false;
877e4b17023SJohn Marino 	  }
878e4b17023SJohn Marino 
879e4b17023SJohn Marino 	obstack_1grow (ob, '(');
880e4b17023SJohn Marino 	is_varargs = stdarg_p (type);
881e4b17023SJohn Marino 	seen_arg = false;
882e4b17023SJohn Marino 	FOREACH_FUNCTION_ARGS (type, arg_type, iter)
883e4b17023SJohn Marino 	  {
884e4b17023SJohn Marino 	    if (VOID_TYPE_P (arg_type))
885e4b17023SJohn Marino 	      break;
886e4b17023SJohn Marino 	    if (seen_arg)
887e4b17023SJohn Marino 	      obstack_grow (ob, ", ", 2);
888e4b17023SJohn Marino 	    if (!go_format_type (container, arg_type, true, false))
889e4b17023SJohn Marino 	      ret = false;
890e4b17023SJohn Marino 	    seen_arg = true;
891e4b17023SJohn Marino 	  }
892e4b17023SJohn Marino 	if (is_varargs)
893e4b17023SJohn Marino 	  {
894e4b17023SJohn Marino 	    if (prototype_p (type))
895e4b17023SJohn Marino 	      obstack_grow (ob, ", ", 2);
896e4b17023SJohn Marino 	    obstack_grow (ob, "...interface{}", 14);
897e4b17023SJohn Marino 	  }
898e4b17023SJohn Marino 	obstack_1grow (ob, ')');
899e4b17023SJohn Marino 
900e4b17023SJohn Marino 	result = TREE_TYPE (type);
901e4b17023SJohn Marino 	if (!VOID_TYPE_P (result))
902e4b17023SJohn Marino 	  {
903e4b17023SJohn Marino 	    obstack_1grow (ob, ' ');
904e4b17023SJohn Marino 	    if (!go_format_type (container, result, use_type_name, false))
905e4b17023SJohn Marino 	      ret = false;
906e4b17023SJohn Marino 	  }
907e4b17023SJohn Marino       }
908e4b17023SJohn Marino       break;
909e4b17023SJohn Marino 
910e4b17023SJohn Marino     default:
911e4b17023SJohn Marino       obstack_grow (ob, "INVALID-type", 12);
912e4b17023SJohn Marino       ret = false;
913e4b17023SJohn Marino       break;
914e4b17023SJohn Marino     }
915e4b17023SJohn Marino 
916e4b17023SJohn Marino   return ret;
917e4b17023SJohn Marino }
918e4b17023SJohn Marino 
919e4b17023SJohn Marino /* Output the type which was built on the type obstack, and then free
920e4b17023SJohn Marino    it.  */
921e4b17023SJohn Marino 
922e4b17023SJohn Marino static void
go_output_type(struct godump_container * container)923e4b17023SJohn Marino go_output_type (struct godump_container *container)
924e4b17023SJohn Marino {
925e4b17023SJohn Marino   struct obstack *ob;
926e4b17023SJohn Marino 
927e4b17023SJohn Marino   ob = &container->type_obstack;
928e4b17023SJohn Marino   obstack_1grow (ob, '\0');
929e4b17023SJohn Marino   fputs (obstack_base (ob), go_dump_file);
930e4b17023SJohn Marino   obstack_free (ob, obstack_base (ob));
931e4b17023SJohn Marino }
932e4b17023SJohn Marino 
933e4b17023SJohn Marino /* Output a function declaration.  */
934e4b17023SJohn Marino 
935e4b17023SJohn Marino static void
go_output_fndecl(struct godump_container * container,tree decl)936e4b17023SJohn Marino go_output_fndecl (struct godump_container *container, tree decl)
937e4b17023SJohn Marino {
938e4b17023SJohn Marino   if (!go_format_type (container, TREE_TYPE (decl), false, true))
939e4b17023SJohn Marino     fprintf (go_dump_file, "// ");
940e4b17023SJohn Marino   fprintf (go_dump_file, "func _%s ",
941e4b17023SJohn Marino 	   IDENTIFIER_POINTER (DECL_NAME (decl)));
942e4b17023SJohn Marino   go_output_type (container);
943e4b17023SJohn Marino   fprintf (go_dump_file, " __asm__(\"%s\")\n",
944e4b17023SJohn Marino 	   IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
945e4b17023SJohn Marino }
946e4b17023SJohn Marino 
947e4b17023SJohn Marino /* Output a typedef or something like a struct definition.  */
948e4b17023SJohn Marino 
949e4b17023SJohn Marino static void
go_output_typedef(struct godump_container * container,tree decl)950e4b17023SJohn Marino go_output_typedef (struct godump_container *container, tree decl)
951e4b17023SJohn Marino {
952e4b17023SJohn Marino   /* If we have an enum type, output the enum constants
953e4b17023SJohn Marino      separately.  */
954e4b17023SJohn Marino   if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
955e4b17023SJohn Marino       && TYPE_SIZE (TREE_TYPE (decl)) != 0
956e4b17023SJohn Marino       && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
957e4b17023SJohn Marino       && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
958e4b17023SJohn Marino 	  || !pointer_set_contains (container->decls_seen,
959e4b17023SJohn Marino 				    TYPE_CANONICAL (TREE_TYPE (decl)))))
960e4b17023SJohn Marino     {
961e4b17023SJohn Marino       tree element;
962e4b17023SJohn Marino 
963e4b17023SJohn Marino       for (element = TYPE_VALUES (TREE_TYPE (decl));
964e4b17023SJohn Marino 	   element != NULL_TREE;
965e4b17023SJohn Marino 	   element = TREE_CHAIN (element))
966e4b17023SJohn Marino 	{
967e4b17023SJohn Marino 	  const char *name;
968e4b17023SJohn Marino 	  struct macro_hash_value *mhval;
969e4b17023SJohn Marino 	  void **slot;
970e4b17023SJohn Marino 	  char buf[100];
971e4b17023SJohn Marino 
972e4b17023SJohn Marino 	  name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
973e4b17023SJohn Marino 
974e4b17023SJohn Marino 	  /* Sometimes a name will be defined as both an enum constant
975e4b17023SJohn Marino 	     and a macro.  Avoid duplicate definition errors by
976e4b17023SJohn Marino 	     treating enum constants as macros.  */
977e4b17023SJohn Marino 	  mhval = XNEW (struct macro_hash_value);
978e4b17023SJohn Marino 	  mhval->name = xstrdup (name);
979e4b17023SJohn Marino 	  mhval->value = NULL;
980e4b17023SJohn Marino 	  slot = htab_find_slot (macro_hash, mhval, INSERT);
981e4b17023SJohn Marino 	  if (*slot != NULL)
982e4b17023SJohn Marino 	    macro_hash_del (*slot);
983e4b17023SJohn Marino 
984e4b17023SJohn Marino 	  if (host_integerp (TREE_VALUE (element), 0))
985e4b17023SJohn Marino 	    snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC,
986e4b17023SJohn Marino 		     tree_low_cst (TREE_VALUE (element), 0));
987e4b17023SJohn Marino 	  else if (host_integerp (TREE_VALUE (element), 1))
988e4b17023SJohn Marino 	    snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
989e4b17023SJohn Marino 		     ((unsigned HOST_WIDE_INT)
990e4b17023SJohn Marino 		      tree_low_cst (TREE_VALUE (element), 1)));
991e4b17023SJohn Marino 	  else
992e4b17023SJohn Marino 	    snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
993e4b17023SJohn Marino 		     ((unsigned HOST_WIDE_INT)
994e4b17023SJohn Marino 		      TREE_INT_CST_HIGH (TREE_VALUE (element))),
995e4b17023SJohn Marino 		     TREE_INT_CST_LOW (TREE_VALUE (element)));
996e4b17023SJohn Marino 
997e4b17023SJohn Marino 	  mhval->value = xstrdup (buf);
998e4b17023SJohn Marino 	  *slot = mhval;
999e4b17023SJohn Marino 	}
1000e4b17023SJohn Marino       pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
1001e4b17023SJohn Marino       if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
1002e4b17023SJohn Marino 	pointer_set_insert (container->decls_seen,
1003e4b17023SJohn Marino 			    TYPE_CANONICAL (TREE_TYPE (decl)));
1004e4b17023SJohn Marino     }
1005e4b17023SJohn Marino 
1006e4b17023SJohn Marino   if (DECL_NAME (decl) != NULL_TREE)
1007e4b17023SJohn Marino     {
1008e4b17023SJohn Marino       void **slot;
1009e4b17023SJohn Marino       const char *type;
1010e4b17023SJohn Marino 
1011e4b17023SJohn Marino       type = IDENTIFIER_POINTER (DECL_NAME (decl));
1012e4b17023SJohn Marino       /* If type defined already, skip.  */
1013e4b17023SJohn Marino       slot = htab_find_slot (container->type_hash, type, INSERT);
1014e4b17023SJohn Marino       if (*slot != NULL)
1015e4b17023SJohn Marino 	return;
1016e4b17023SJohn Marino       *slot = CONST_CAST (void *, (const void *) type);
1017e4b17023SJohn Marino 
1018e4b17023SJohn Marino       if (!go_format_type (container, TREE_TYPE (decl), false, false))
1019e4b17023SJohn Marino 	{
1020e4b17023SJohn Marino 	  fprintf (go_dump_file, "// ");
1021e4b17023SJohn Marino 	  slot = htab_find_slot (container->invalid_hash, type, INSERT);
1022e4b17023SJohn Marino 	  *slot = CONST_CAST (void *, (const void *) type);
1023e4b17023SJohn Marino 	}
1024e4b17023SJohn Marino       fprintf (go_dump_file, "type _%s ",
1025e4b17023SJohn Marino 	       IDENTIFIER_POINTER (DECL_NAME (decl)));
1026e4b17023SJohn Marino       go_output_type (container);
1027e4b17023SJohn Marino 
1028e4b17023SJohn Marino       if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1029e4b17023SJohn Marino 	{
1030e4b17023SJohn Marino 	  HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
1031e4b17023SJohn Marino 
1032e4b17023SJohn Marino 	  if (size > 0)
1033e4b17023SJohn Marino 	    fprintf (go_dump_file,
1034e4b17023SJohn Marino 		     "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1035e4b17023SJohn Marino 		     IDENTIFIER_POINTER (DECL_NAME (decl)),
1036e4b17023SJohn Marino 		     size);
1037e4b17023SJohn Marino 	}
1038e4b17023SJohn Marino 
1039e4b17023SJohn Marino       pointer_set_insert (container->decls_seen, decl);
1040e4b17023SJohn Marino     }
1041e4b17023SJohn Marino   else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1042e4b17023SJohn Marino     {
1043e4b17023SJohn Marino        void **slot;
1044e4b17023SJohn Marino        const char *type;
1045e4b17023SJohn Marino        HOST_WIDE_INT size;
1046e4b17023SJohn Marino 
1047e4b17023SJohn Marino        type = IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE ((decl))));
1048e4b17023SJohn Marino        /* If type defined already, skip.  */
1049e4b17023SJohn Marino        slot = htab_find_slot (container->type_hash, type, INSERT);
1050e4b17023SJohn Marino        if (*slot != NULL)
1051e4b17023SJohn Marino          return;
1052e4b17023SJohn Marino        *slot = CONST_CAST (void *, (const void *) type);
1053e4b17023SJohn Marino 
1054e4b17023SJohn Marino        if (!go_format_type (container, TREE_TYPE (decl), false, false))
1055e4b17023SJohn Marino 	 {
1056e4b17023SJohn Marino 	   fprintf (go_dump_file, "// ");
1057e4b17023SJohn Marino 	   slot = htab_find_slot (container->invalid_hash, type, INSERT);
1058e4b17023SJohn Marino 	   *slot = CONST_CAST (void *, (const void *) type);
1059e4b17023SJohn Marino 	 }
1060e4b17023SJohn Marino        fprintf (go_dump_file, "type _%s ",
1061e4b17023SJohn Marino 	       IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))));
1062e4b17023SJohn Marino        go_output_type (container);
1063e4b17023SJohn Marino 
1064e4b17023SJohn Marino        size = int_size_in_bytes (TREE_TYPE (decl));
1065e4b17023SJohn Marino        if (size > 0)
1066e4b17023SJohn Marino 	 fprintf (go_dump_file,
1067e4b17023SJohn Marino 		  "\nconst _sizeof_%s = " HOST_WIDE_INT_PRINT_DEC,
1068e4b17023SJohn Marino 		  IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (decl))),
1069e4b17023SJohn Marino 		  size);
1070e4b17023SJohn Marino     }
1071e4b17023SJohn Marino   else
1072e4b17023SJohn Marino     return;
1073e4b17023SJohn Marino 
1074e4b17023SJohn Marino   fprintf (go_dump_file, "\n");
1075e4b17023SJohn Marino }
1076e4b17023SJohn Marino 
1077e4b17023SJohn Marino /* Output a variable.  */
1078e4b17023SJohn Marino 
1079e4b17023SJohn Marino static void
go_output_var(struct godump_container * container,tree decl)1080e4b17023SJohn Marino go_output_var (struct godump_container *container, tree decl)
1081e4b17023SJohn Marino {
1082e4b17023SJohn Marino   bool is_valid;
1083e4b17023SJohn Marino 
1084e4b17023SJohn Marino   if (pointer_set_contains (container->decls_seen, decl)
1085e4b17023SJohn Marino       || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
1086e4b17023SJohn Marino     return;
1087e4b17023SJohn Marino   pointer_set_insert (container->decls_seen, decl);
1088e4b17023SJohn Marino   pointer_set_insert (container->decls_seen, DECL_NAME (decl));
1089e4b17023SJohn Marino 
1090e4b17023SJohn Marino   is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
1091e4b17023SJohn Marino   if (is_valid
1092e4b17023SJohn Marino       && htab_find_slot (container->type_hash,
1093e4b17023SJohn Marino 			 IDENTIFIER_POINTER (DECL_NAME (decl)),
1094e4b17023SJohn Marino 			 NO_INSERT) != NULL)
1095e4b17023SJohn Marino     {
1096e4b17023SJohn Marino       /* There is already a type with this name, probably from a
1097e4b17023SJohn Marino 	 struct tag.  Prefer the type to the variable.  */
1098e4b17023SJohn Marino       is_valid = false;
1099e4b17023SJohn Marino     }
1100e4b17023SJohn Marino   if (!is_valid)
1101e4b17023SJohn Marino     fprintf (go_dump_file, "// ");
1102e4b17023SJohn Marino 
1103e4b17023SJohn Marino   fprintf (go_dump_file, "var _%s ",
1104e4b17023SJohn Marino 	   IDENTIFIER_POINTER (DECL_NAME (decl)));
1105e4b17023SJohn Marino   go_output_type (container);
1106e4b17023SJohn Marino   fprintf (go_dump_file, "\n");
1107e4b17023SJohn Marino 
1108e4b17023SJohn Marino   /* Sometimes an extern variable is declared with an unknown struct
1109e4b17023SJohn Marino      type.  */
1110e4b17023SJohn Marino   if (TYPE_NAME (TREE_TYPE (decl)) != NULL_TREE
1111e4b17023SJohn Marino       && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1112e4b17023SJohn Marino     {
1113e4b17023SJohn Marino       tree type_name = TYPE_NAME (TREE_TYPE (decl));
1114e4b17023SJohn Marino       if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1115e4b17023SJohn Marino 	pointer_set_insert (container->pot_dummy_types,
1116e4b17023SJohn Marino 			    IDENTIFIER_POINTER (type_name));
1117e4b17023SJohn Marino       else if (TREE_CODE (type_name) == TYPE_DECL)
1118e4b17023SJohn Marino 	pointer_set_insert (container->pot_dummy_types,
1119e4b17023SJohn Marino 			    IDENTIFIER_POINTER (DECL_NAME (type_name)));
1120e4b17023SJohn Marino     }
1121e4b17023SJohn Marino }
1122e4b17023SJohn Marino 
1123e4b17023SJohn Marino /* Output the final value of a preprocessor macro or enum constant.
1124e4b17023SJohn Marino    This is called via htab_traverse_noresize.  */
1125e4b17023SJohn Marino 
1126e4b17023SJohn Marino static int
go_print_macro(void ** slot,void * arg ATTRIBUTE_UNUSED)1127e4b17023SJohn Marino go_print_macro (void **slot, void *arg ATTRIBUTE_UNUSED)
1128e4b17023SJohn Marino {
1129e4b17023SJohn Marino   struct macro_hash_value *mhval = (struct macro_hash_value *) *slot;
1130e4b17023SJohn Marino   fprintf (go_dump_file, "const _%s = %s\n", mhval->name, mhval->value);
1131e4b17023SJohn Marino   return 1;
1132e4b17023SJohn Marino }
1133e4b17023SJohn Marino 
1134e4b17023SJohn Marino /* Build a hash table with the Go keywords.  */
1135e4b17023SJohn Marino 
1136e4b17023SJohn Marino static const char * const keywords[] = {
1137e4b17023SJohn Marino   "__asm__", "break", "case", "chan", "const", "continue", "default",
1138e4b17023SJohn Marino   "defer", "else", "fallthrough", "for", "func", "go", "goto", "if",
1139e4b17023SJohn Marino   "import", "interface", "map", "package", "range", "return", "select",
1140e4b17023SJohn Marino   "struct", "switch", "type", "var"
1141e4b17023SJohn Marino };
1142e4b17023SJohn Marino 
1143e4b17023SJohn Marino static void
keyword_hash_init(struct godump_container * container)1144e4b17023SJohn Marino keyword_hash_init (struct godump_container *container)
1145e4b17023SJohn Marino {
1146e4b17023SJohn Marino   size_t i;
1147e4b17023SJohn Marino   size_t count = sizeof (keywords) / sizeof (keywords[0]);
1148e4b17023SJohn Marino   void **slot;
1149e4b17023SJohn Marino 
1150e4b17023SJohn Marino   for (i = 0; i < count; i++)
1151e4b17023SJohn Marino     {
1152e4b17023SJohn Marino       slot = htab_find_slot (container->keyword_hash, keywords[i], INSERT);
1153e4b17023SJohn Marino       *slot = CONST_CAST (void *, (const void *) keywords[i]);
1154e4b17023SJohn Marino     }
1155e4b17023SJohn Marino }
1156e4b17023SJohn Marino 
1157e4b17023SJohn Marino /* Traversing the pot_dummy_types and seeing which types are present
1158e4b17023SJohn Marino    in the global types hash table and creating dummy definitions if
1159e4b17023SJohn Marino    not found.  This function is invoked by pointer_set_traverse.  */
1160e4b17023SJohn Marino 
1161e4b17023SJohn Marino static bool
find_dummy_types(const void * ptr,void * adata)1162e4b17023SJohn Marino find_dummy_types (const void *ptr, void *adata)
1163e4b17023SJohn Marino {
1164e4b17023SJohn Marino   struct godump_container *data = (struct godump_container *) adata;
1165e4b17023SJohn Marino   const char *type = (const char *) ptr;
1166e4b17023SJohn Marino   void **slot;
1167*5ce9237cSJohn Marino   void **islot;
1168e4b17023SJohn Marino 
1169e4b17023SJohn Marino   slot = htab_find_slot (data->type_hash, type, NO_INSERT);
1170*5ce9237cSJohn Marino   islot = htab_find_slot (data->invalid_hash, type, NO_INSERT);
1171*5ce9237cSJohn Marino   if (slot == NULL || islot != NULL)
1172e4b17023SJohn Marino     fprintf (go_dump_file, "type _%s struct {}\n", type);
1173e4b17023SJohn Marino   return true;
1174e4b17023SJohn Marino }
1175e4b17023SJohn Marino 
1176e4b17023SJohn Marino /* Output symbols.  */
1177e4b17023SJohn Marino 
1178e4b17023SJohn Marino static void
go_finish(const char * filename)1179e4b17023SJohn Marino go_finish (const char *filename)
1180e4b17023SJohn Marino {
1181e4b17023SJohn Marino   struct godump_container container;
1182e4b17023SJohn Marino   unsigned int ix;
1183e4b17023SJohn Marino   tree decl;
1184e4b17023SJohn Marino 
1185e4b17023SJohn Marino   real_debug_hooks->finish (filename);
1186e4b17023SJohn Marino 
1187e4b17023SJohn Marino   container.decls_seen = pointer_set_create ();
1188e4b17023SJohn Marino   container.pot_dummy_types = pointer_set_create ();
1189e4b17023SJohn Marino   container.type_hash = htab_create (100, htab_hash_string,
1190e4b17023SJohn Marino                                      string_hash_eq, NULL);
1191e4b17023SJohn Marino   container.invalid_hash = htab_create (10, htab_hash_string,
1192e4b17023SJohn Marino 					string_hash_eq, NULL);
1193e4b17023SJohn Marino   container.keyword_hash = htab_create (50, htab_hash_string,
1194e4b17023SJohn Marino                                         string_hash_eq, NULL);
1195e4b17023SJohn Marino   obstack_init (&container.type_obstack);
1196e4b17023SJohn Marino 
1197e4b17023SJohn Marino   keyword_hash_init (&container);
1198e4b17023SJohn Marino 
1199e4b17023SJohn Marino   FOR_EACH_VEC_ELT (tree, queue, ix, decl)
1200e4b17023SJohn Marino     {
1201e4b17023SJohn Marino       switch (TREE_CODE (decl))
1202e4b17023SJohn Marino 	{
1203e4b17023SJohn Marino 	case FUNCTION_DECL:
1204e4b17023SJohn Marino 	  go_output_fndecl (&container, decl);
1205e4b17023SJohn Marino 	  break;
1206e4b17023SJohn Marino 
1207e4b17023SJohn Marino 	case TYPE_DECL:
1208e4b17023SJohn Marino 	  go_output_typedef (&container, decl);
1209e4b17023SJohn Marino 	  break;
1210e4b17023SJohn Marino 
1211e4b17023SJohn Marino 	case VAR_DECL:
1212e4b17023SJohn Marino 	  go_output_var (&container, decl);
1213e4b17023SJohn Marino 	  break;
1214e4b17023SJohn Marino 
1215e4b17023SJohn Marino 	default:
1216e4b17023SJohn Marino 	  gcc_unreachable();
1217e4b17023SJohn Marino 	}
1218e4b17023SJohn Marino     }
1219e4b17023SJohn Marino 
1220e4b17023SJohn Marino   htab_traverse_noresize (macro_hash, go_print_macro, NULL);
1221e4b17023SJohn Marino 
1222e4b17023SJohn Marino   /* To emit dummy definitions.  */
1223e4b17023SJohn Marino   pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
1224e4b17023SJohn Marino                         (void *) &container);
1225e4b17023SJohn Marino 
1226e4b17023SJohn Marino   pointer_set_destroy (container.decls_seen);
1227e4b17023SJohn Marino   pointer_set_destroy (container.pot_dummy_types);
1228e4b17023SJohn Marino   htab_delete (container.type_hash);
1229e4b17023SJohn Marino   htab_delete (container.invalid_hash);
1230e4b17023SJohn Marino   htab_delete (container.keyword_hash);
1231e4b17023SJohn Marino   obstack_free (&container.type_obstack, NULL);
1232e4b17023SJohn Marino 
1233e4b17023SJohn Marino   queue = NULL;
1234e4b17023SJohn Marino 
1235e4b17023SJohn Marino   if (fclose (go_dump_file) != 0)
1236e4b17023SJohn Marino     error ("could not close Go dump file: %m");
1237e4b17023SJohn Marino   go_dump_file = NULL;
1238e4b17023SJohn Marino }
1239e4b17023SJohn Marino 
1240e4b17023SJohn Marino /* Set up our hooks.  */
1241e4b17023SJohn Marino 
1242e4b17023SJohn Marino const struct gcc_debug_hooks *
dump_go_spec_init(const char * filename,const struct gcc_debug_hooks * hooks)1243e4b17023SJohn Marino dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
1244e4b17023SJohn Marino {
1245e4b17023SJohn Marino   go_dump_file = fopen (filename, "w");
1246e4b17023SJohn Marino   if (go_dump_file == NULL)
1247e4b17023SJohn Marino     {
1248e4b17023SJohn Marino       error ("could not open Go dump file %qs: %m", filename);
1249e4b17023SJohn Marino       return hooks;
1250e4b17023SJohn Marino     }
1251e4b17023SJohn Marino 
1252e4b17023SJohn Marino   go_debug_hooks = *hooks;
1253e4b17023SJohn Marino   real_debug_hooks = hooks;
1254e4b17023SJohn Marino 
1255e4b17023SJohn Marino   go_debug_hooks.finish = go_finish;
1256e4b17023SJohn Marino   go_debug_hooks.define = go_define;
1257e4b17023SJohn Marino   go_debug_hooks.undef = go_undef;
1258e4b17023SJohn Marino   go_debug_hooks.function_decl = go_function_decl;
1259e4b17023SJohn Marino   go_debug_hooks.global_decl = go_global_decl;
1260e4b17023SJohn Marino   go_debug_hooks.type_decl = go_type_decl;
1261e4b17023SJohn Marino 
1262e4b17023SJohn Marino   macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
1263e4b17023SJohn Marino 			    macro_hash_del);
1264e4b17023SJohn Marino 
1265e4b17023SJohn Marino   return &go_debug_hooks;
1266e4b17023SJohn Marino }
1267e4b17023SJohn Marino 
1268e4b17023SJohn Marino #include "gt-godump.h"
1269