Commit 57ab0915 by Dominik Vogt Committed by Ian Lance Taylor

godump.c (go_format_type): Rewrite RECORD_TYPE nad UNION_TYPE support with -fdump-go-spec.

gcc/:
	* godump.c (go_format_type): Rewrite RECORD_TYPE nad UNION_TYPE support
	with -fdump-go-spec.  Anonymous substructures are now flattened and
	replaced by their fields (record) or the first named, non-bitfield
	field (union).
gcc/testsuite/:
	* build-go/gcc/testsuite/gcc/godump-1.out: Update godump tests.

From-SVN: r217058
parent e1f0c178
2014-11-03 Dominik Vogt <vogt@linux.vnet.ibm.com>
* godump.c (go_format_type): Rewrite RECORD_TYPE nad UNION_TYPE support
with -fdump-go-spec. Anonymous substructures are now flattened and
replaced by their fields (record) or the first named, non-bitfield
field (union).
2014-11-04 Manuel López-Ibáñez <manu@gcc.gnu.org> 2014-11-04 Manuel López-Ibáñez <manu@gcc.gnu.org>
* input.c (expand_location_to_spelling_point): Fix typo. * input.c (expand_location_to_spelling_point): Fix typo.
...@@ -678,11 +678,13 @@ go_force_record_alignment (struct obstack *ob, const char *type_string, ...@@ -678,11 +678,13 @@ go_force_record_alignment (struct obstack *ob, const char *type_string,
static bool static bool
go_format_type (struct godump_container *container, tree type, go_format_type (struct godump_container *container, tree type,
bool use_type_name, bool is_func_ok, unsigned int *p_art_i) bool use_type_name, bool is_func_ok, unsigned int *p_art_i,
bool is_anon_record_or_union)
{ {
bool ret; bool ret;
struct obstack *ob; struct obstack *ob;
unsigned int art_i_dummy; unsigned int art_i_dummy;
bool is_union = false;
if (p_art_i == NULL) if (p_art_i == NULL)
{ {
...@@ -856,7 +858,7 @@ go_format_type (struct godump_container *container, tree type, ...@@ -856,7 +858,7 @@ go_format_type (struct godump_container *container, tree type,
else else
{ {
if (!go_format_type (container, TREE_TYPE (type), use_type_name, if (!go_format_type (container, TREE_TYPE (type), use_type_name,
true, NULL)) true, NULL, false))
ret = false; ret = false;
} }
break; break;
...@@ -882,15 +884,19 @@ go_format_type (struct godump_container *container, tree type, ...@@ -882,15 +884,19 @@ go_format_type (struct godump_container *container, tree type,
obstack_1grow (ob, '0'); obstack_1grow (ob, '0');
obstack_1grow (ob, ']'); obstack_1grow (ob, ']');
if (!go_format_type (container, TREE_TYPE (type), use_type_name, false, if (!go_format_type (container, TREE_TYPE (type), use_type_name, false,
NULL)) NULL, false))
ret = false; ret = false;
break; break;
case UNION_TYPE:
is_union = true;
/* Fall through to RECORD_TYPE case. */
case RECORD_TYPE: case RECORD_TYPE:
{ {
unsigned int prev_field_end; unsigned int prev_field_end;
unsigned int most_strict_known_alignment; unsigned int known_alignment;
tree field; tree field;
bool emitted_a_field;
/* FIXME: Why is this necessary? Without it we can get a core /* FIXME: Why is this necessary? Without it we can get a core
dump on the s390x headers, or from a file containing simply dump on the s390x headers, or from a file containing simply
...@@ -898,51 +904,77 @@ go_format_type (struct godump_container *container, tree type, ...@@ -898,51 +904,77 @@ go_format_type (struct godump_container *container, tree type,
layout_type (type); layout_type (type);
prev_field_end = 0; prev_field_end = 0;
most_strict_known_alignment = 1; known_alignment = 1;
obstack_grow (ob, "struct { ", 9); /* Anonymous records and unions are flattened, i.e. they are not put
for (field = TYPE_FIELDS (type); into "struct { ... }". */
if (!is_anon_record_or_union)
obstack_grow (ob, "struct { ", 9);
for (field = TYPE_FIELDS (type), emitted_a_field = false;
field != NULL_TREE; field != NULL_TREE;
field = TREE_CHAIN (field)) field = TREE_CHAIN (field))
{ {
bool field_ok;
if (TREE_CODE (field) != FIELD_DECL) if (TREE_CODE (field) != FIELD_DECL)
continue; continue;
field_ok = true;
if (DECL_BIT_FIELD (field)) if (DECL_BIT_FIELD (field))
/* Bit fields are replaced by padding. */
continue; continue;
else /* Only the first non-bitfield field is emitted for unions. */
{ if (!is_union || !emitted_a_field)
{
/* Emit the field. */
bool field_ok;
bool is_anon_substructure;
unsigned int decl_align_unit;
unsigned int decl_offset;
field_ok = true;
emitted_a_field = true;
is_anon_substructure =
(DECL_NAME (field) == NULL
&& (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE));
/* Keep track of the alignment of named substructures, either
of the whole record, or the alignment of the emitted field
(for unions). */
decl_align_unit = DECL_ALIGN_UNIT (field);
if (!is_anon_substructure && decl_align_unit > known_alignment)
known_alignment = decl_align_unit;
/* Pad to start of field. */
decl_offset =
TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
+ precision_to_units
(TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)));
{ {
unsigned int decl_align_unit; unsigned int align_unit;
unsigned int decl_offset;
/* For anonymous records and unions there is no automatic
decl_align_unit = DECL_ALIGN_UNIT (field); structure alignment, so use 1 as the alignment. */
decl_offset = align_unit = (is_anon_substructure) ? 1 : decl_align_unit;
TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
+ precision_to_units
(TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)));
if (decl_align_unit > most_strict_known_alignment)
most_strict_known_alignment = decl_align_unit;
*p_art_i = go_append_padding *p_art_i = go_append_padding
(ob, prev_field_end, decl_offset, decl_align_unit, *p_art_i, (ob, prev_field_end, decl_offset, align_unit, *p_art_i,
&prev_field_end); &prev_field_end);
if (DECL_SIZE_UNIT (field))
prev_field_end += TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
} }
if (DECL_NAME (field) == NULL) if (DECL_SIZE_UNIT (field))
*p_art_i = go_append_artificial_name (ob, *p_art_i); prev_field_end +=
else TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
go_append_decl_name (ob, field, container->keyword_hash); /* Emit the field name, but not for anonymous records and
obstack_1grow (ob, ' '); unions. */
if (!is_anon_substructure)
/* Do not expand type if a record or union type or a {
function pointer. */ if ((DECL_NAME (field) == NULL))
*p_art_i = go_append_artificial_name (ob, *p_art_i);
else
go_append_decl_name
(ob, field, container->keyword_hash);
obstack_1grow (ob, ' ');
}
/* Do not expand type if a record or union type or a function
pointer. */
if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
&& (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)) && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
|| (POINTER_TYPE_P (TREE_TYPE (field)) || (POINTER_TYPE_P (TREE_TYPE (field))
&& (TREE_CODE (TREE_TYPE (TREE_TYPE (field))) && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
== FUNCTION_TYPE)))) == FUNCTION_TYPE))))
{ {
tree name; tree name;
void **slot; void **slot;
...@@ -961,24 +993,27 @@ go_format_type (struct godump_container *container, tree type, ...@@ -961,24 +993,27 @@ go_format_type (struct godump_container *container, tree type,
else else
{ {
if (!go_format_type (container, TREE_TYPE (field), true, if (!go_format_type (container, TREE_TYPE (field), true,
false, p_art_i)) false, p_art_i, is_anon_substructure))
field_ok = false; field_ok = false;
} }
obstack_grow (ob, "; ", 2); if (!is_anon_substructure)
} obstack_grow (ob, "; ", 2);
if (!field_ok) if (!field_ok)
ret = false; ret = false;
}
} }
/* Alignment and padding as necessary. */ /* Padding. */
{ {
unsigned int type_align_unit; unsigned int align_unit;
type_align_unit = TYPE_ALIGN_UNIT (type); align_unit = (is_anon_record_or_union) ? 1 : TYPE_ALIGN_UNIT (type);
/* Padding. */
*p_art_i = go_append_padding *p_art_i = go_append_padding
(ob, prev_field_end, TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type)), (ob, prev_field_end, TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type)),
type_align_unit, *p_art_i, &prev_field_end); align_unit, *p_art_i, &prev_field_end);
if (most_strict_known_alignment < type_align_unit) }
/* Alignment. */
if (!is_anon_record_or_union
&& known_alignment < TYPE_ALIGN_UNIT (type))
{ {
const char *s; const char *s;
char buf[100]; char buf[100];
...@@ -995,46 +1030,10 @@ go_format_type (struct godump_container *container, tree type, ...@@ -995,46 +1030,10 @@ go_format_type (struct godump_container *container, tree type,
} }
*p_art_i = go_force_record_alignment (ob, s, *p_art_i, buf); *p_art_i = go_force_record_alignment (ob, s, *p_art_i, buf);
} }
} if (!is_anon_record_or_union)
obstack_1grow (ob, '}'); obstack_1grow (ob, '}');
} }
break; break;
case UNION_TYPE:
{
const char *s;
unsigned int sz_units;
layout_type (type);
sz_units = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
s = go_get_uinttype_for_precision (TYPE_ALIGN (type), true);
obstack_grow (ob, "struct { ", 9);
if (s == NULL)
{
ret = false;
s = "INVALID-union-alignment";
obstack_grow (ob, s, strlen (s));
}
else
{
char buf[100];
tree field;
field = TYPE_FIELDS (type);
/* Use the same index as the byte field's artificial name for
padding. */
if (field != NULL_TREE && DECL_NAME (field) != NULL)
go_append_decl_name (ob, field, container->keyword_hash);
else
*p_art_i = go_append_artificial_name (ob, *p_art_i);
snprintf (buf, sizeof buf, " [%u]byte; ", sz_units);
obstack_grow (ob, buf, strlen (buf));
if (TYPE_ALIGN_UNIT (type) > 1)
*p_art_i = go_force_record_alignment (ob, s, *p_art_i, NULL);
}
obstack_1grow (ob, '}');
}
break;
case FUNCTION_TYPE: case FUNCTION_TYPE:
{ {
...@@ -1061,7 +1060,7 @@ go_format_type (struct godump_container *container, tree type, ...@@ -1061,7 +1060,7 @@ go_format_type (struct godump_container *container, tree type,
break; break;
if (seen_arg) if (seen_arg)
obstack_grow (ob, ", ", 2); obstack_grow (ob, ", ", 2);
if (!go_format_type (container, arg_type, true, false, NULL)) if (!go_format_type (container, arg_type, true, false, NULL, false))
ret = false; ret = false;
seen_arg = true; seen_arg = true;
} }
...@@ -1077,7 +1076,8 @@ go_format_type (struct godump_container *container, tree type, ...@@ -1077,7 +1076,8 @@ go_format_type (struct godump_container *container, tree type,
if (!VOID_TYPE_P (result)) if (!VOID_TYPE_P (result))
{ {
obstack_1grow (ob, ' '); obstack_1grow (ob, ' ');
if (!go_format_type (container, result, use_type_name, false, NULL)) if (!go_format_type (container, result, use_type_name, false, NULL,
false))
ret = false; ret = false;
} }
} }
...@@ -1111,7 +1111,7 @@ go_output_type (struct godump_container *container) ...@@ -1111,7 +1111,7 @@ go_output_type (struct godump_container *container)
static void static void
go_output_fndecl (struct godump_container *container, tree decl) go_output_fndecl (struct godump_container *container, tree decl)
{ {
if (!go_format_type (container, TREE_TYPE (decl), false, true, NULL)) if (!go_format_type (container, TREE_TYPE (decl), false, true, NULL, false))
fprintf (go_dump_file, "// "); fprintf (go_dump_file, "// ");
fprintf (go_dump_file, "func _%s ", fprintf (go_dump_file, "func _%s ",
IDENTIFIER_POINTER (DECL_NAME (decl))); IDENTIFIER_POINTER (DECL_NAME (decl)));
...@@ -1186,7 +1186,8 @@ go_output_typedef (struct godump_container *container, tree decl) ...@@ -1186,7 +1186,8 @@ go_output_typedef (struct godump_container *container, tree decl)
return; return;
*slot = CONST_CAST (void *, (const void *) type); *slot = CONST_CAST (void *, (const void *) type);
if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL)) if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL,
false))
{ {
fprintf (go_dump_file, "// "); fprintf (go_dump_file, "// ");
slot = htab_find_slot (container->invalid_hash, type, INSERT); slot = htab_find_slot (container->invalid_hash, type, INSERT);
...@@ -1222,7 +1223,8 @@ go_output_typedef (struct godump_container *container, tree decl) ...@@ -1222,7 +1223,8 @@ go_output_typedef (struct godump_container *container, tree decl)
return; return;
*slot = CONST_CAST (void *, (const void *) type); *slot = CONST_CAST (void *, (const void *) type);
if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL)) if (!go_format_type (container, TREE_TYPE (decl), false, false, NULL,
false))
{ {
fprintf (go_dump_file, "// "); fprintf (go_dump_file, "// ");
slot = htab_find_slot (container->invalid_hash, type, INSERT); slot = htab_find_slot (container->invalid_hash, type, INSERT);
...@@ -1285,7 +1287,8 @@ go_output_var (struct godump_container *container, tree decl) ...@@ -1285,7 +1287,8 @@ go_output_var (struct godump_container *container, tree decl)
NO_INSERT) != NULL; NO_INSERT) != NULL;
} }
else else
is_valid = go_format_type (container, TREE_TYPE (decl), true, false, NULL); is_valid = go_format_type (container, TREE_TYPE (decl), true, false, NULL,
false);
if (is_valid if (is_valid
&& htab_find_slot (container->type_hash, && htab_find_slot (container->type_hash,
IDENTIFIER_POINTER (DECL_NAME (decl)), IDENTIFIER_POINTER (DECL_NAME (decl)),
......
2014-11-03 Dominik Vogt <vogt@linux.vnet.ibm.com>
* build-go/gcc/testsuite/gcc/godump-1.out: Update godump tests.
2014-11-03 Tobias Burnus <burnus@net-b.de> 2014-11-03 Tobias Burnus <burnus@net-b.de>
* gfortran.dg/coarray_collectives_14.f90: Fix testcase. * gfortran.dg/coarray_collectives_14.f90: Fix testcase.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment