[llvm-commits] [llvm-gcc-4.2] r45521 - /llvm-gcc-4.2/trunk/gcc/ada/utils.c
Duncan Sands
baldrick at free.fr
Wed Jan 2 16:22:43 PST 2008
Author: baldrick
Date: Wed Jan 2 18:22:43 2008
New Revision: 45521
URL: http://llvm.org/viewvc/llvm-project?rev=45521&view=rev
Log:
The struct type conversion code and the abi
pass-by-copy logic assume that the fields in
a gcc record type are ordered by their offset
from the start of the record (even though the
gcc docs explicitly warn against assuming this).
The Ada front-end sometimes produces records
with "misordered" fields. This patch fixes the
problem by sorting fields in the Ada f-e. Once
the pass-by-copy logic has been removed, probably
this should be fixed in the llvm type conversion
code instead.
Modified:
llvm-gcc-4.2/trunk/gcc/ada/utils.c
Modified: llvm-gcc-4.2/trunk/gcc/ada/utils.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/ada/utils.c?rev=45521&r1=45520&r2=45521&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/ada/utils.c (original)
+++ llvm-gcc-4.2/trunk/gcc/ada/utils.c Wed Jan 2 18:22:43 2008
@@ -662,6 +662,45 @@
main_identifier_node = get_identifier ("main");
}
+/* LLVM local begin */
+/* Called via qsort from the below. Returns -1, 1, depending on the
+ bit positions and ordinals of the two fields. Use DECL_UID to ensure
+ a stable sort. */
+
+static int
+compare_field_bitpos (const PTR rt1, const PTR rt2)
+{
+ tree *t1 = (tree *) rt1;
+ tree *t2 = (tree *) rt2;
+ tree bp1 = bit_position (*t1);
+ tree bp2 = bit_position (*t2);
+ bool var1 = TREE_CODE (bp1) != INTEGER_CST;
+ bool var2 = TREE_CODE (bp2) != INTEGER_CST;
+ int uid_cmp;
+
+ if (DECL_UID (*t1) < DECL_UID (*t2))
+ uid_cmp = -1;
+ else if (DECL_UID (*t1) == DECL_UID (*t2))
+ uid_cmp = 0;
+ else
+ uid_cmp = 1;
+
+ /* Fields with a variable offset go after fields at a constant offset. */
+ if (var1 && var2)
+ return uid_cmp;
+ else if (var1)
+ return 1;
+ else if (var2)
+ return -1;
+ else if (tree_int_cst_equal (bp1, bp2))
+ return uid_cmp;
+ else if (tree_int_cst_lt (bp1, bp2))
+ return -1;
+ else
+ return 1;
+}
+
+/* LLVM local end */
/* Given a record type (RECORD_TYPE) and a chain of FIELD_DECL nodes
(FIELDLIST), finish constructing the record or union type. If HAS_REP is
true, this record has a rep clause; don't call layout_type but merely set
@@ -680,6 +719,33 @@
bool had_size_unit = TYPE_SIZE_UNIT (record_type) != 0;
tree field;
+ /* LLVM local begin */
+ if (has_rep) {
+ /* The gcc-to-llvm logic assumes in several places that record fields are
+ ordered by offset, even though the gcc documentation explicitly states
+ that no assumptions should be made about field ordering. Sort fields
+ by bitposition as a workaround. TODO: Fix the gcc-to-llvm logic and
+ remove this workaround. */
+ int len = list_length (fieldlist);
+ tree *gnu_arr = (tree *) alloca (sizeof (tree) * len);
+ int i;
+
+ for (i = 0, field = fieldlist; field; field = TREE_CHAIN (field), i++)
+ gnu_arr[i] = field;
+
+ qsort (gnu_arr, len, sizeof (tree), compare_field_bitpos);
+
+ /* Put the fields in the list in order of increasing position, which
+ means we start from the end. */
+ fieldlist = NULL_TREE;
+ for (i = len - 1; i >= 0; i--)
+ {
+ TREE_CHAIN (gnu_arr[i]) = fieldlist;
+ fieldlist = gnu_arr[i];
+ }
+ }
+
+ /* LLVM local end */
TYPE_FIELDS (record_type) = fieldlist;
TYPE_STUB_DECL (record_type)
= build_decl (TYPE_DECL, NULL_TREE, record_type);
More information about the llvm-commits
mailing list