aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/gcc-interface')
-rw-r--r--gcc/ada/gcc-interface/Makefile.in28
-rw-r--r--gcc/ada/gcc-interface/decl.c13
-rw-r--r--gcc/ada/gcc-interface/trans.c8
-rw-r--r--gcc/ada/gcc-interface/utils.c55
4 files changed, 83 insertions, 21 deletions
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index a722a77618f..b1b7e9ac447 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -1475,6 +1475,34 @@ ifeq ($(strip $(filter-out x86_64 kfreebsd%,$(target_cpu) $(target_os))),)
LIBRARY_VERSION := $(LIB_VERSION)
endif
+# aarch64 FreeBSD
+ifeq ($(strip $(filter-out %aarch64 freebsd%,$(target_cpu) $(target_os))),)
+ LIBGNAT_TARGET_PAIRS = \
+ a-intnam.ads<a-intnam-freebsd.ads \
+ s-inmaop.adb<s-inmaop-posix.adb \
+ s-intman.adb<s-intman-posix.adb \
+ s-mudido.adb<s-mudido-affinity.adb \
+ s-osinte.adb<s-osinte-freebsd.adb \
+ s-osinte.ads<s-osinte-freebsd.ads \
+ s-osprim.adb<s-osprim-posix.adb \
+ s-taprop.adb<s-taprop-posix.adb \
+ s-taspri.ads<s-taspri-posix.ads \
+ s-tpopsp.adb<s-tpopsp-posix.adb \
+ $(ATOMICS_TARGET_PAIRS) \
+ $(ATOMICS_BUILTINS_TARGET_PAIRS) \
+ system.ads<system-freebsd-x86_64.ads
+
+ TOOLS_TARGET_PAIRS = \
+ mlib-tgt-specific.adb<mlib-tgt-specific-linux.adb
+ GNATLIB_SHARED = gnatlib-shared-dual
+
+ EH_MECHANISM=-gcc
+ THREADSLIB= -lpthread
+ GMEM_LIB = gmemlib
+ LIBRARY_VERSION := $(LIB_VERSION)
+ MISCLIB = -lutil
+endif
+
# x86 FreeBSD
ifeq ($(strip $(filter-out %86 freebsd%,$(target_cpu) $(target_os))),)
LIBGNAT_TARGET_PAIRS = \
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 4290e9b9a0e..2e57beae2f5 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -6685,6 +6685,7 @@ static tree
gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
bool definition, bool debug_info_p)
{
+ const Entity_Id gnat_record_type = Underlying_Type (Scope (gnat_field));
const Entity_Id gnat_field_type = Etype (gnat_field);
const bool is_aliased
= Is_Aliased (gnat_field);
@@ -6771,8 +6772,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
if (Present (Component_Clause (gnat_field)))
{
Node_Id gnat_clause = Component_Clause (gnat_field);
- Entity_Id gnat_parent
- = Parent_Subtype (Underlying_Type (Scope (gnat_field)));
+ Entity_Id gnat_parent = Parent_Subtype (gnat_record_type);
gnu_pos = UI_To_gnu (Component_Bit_Offset (gnat_field), bitsizetype);
gnu_size = validate_size (Esize (gnat_field), gnu_field_type,
@@ -6891,7 +6891,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
/* If the record has rep clauses and this is the tag field, make a rep
clause for it as well. */
- else if (Has_Specified_Layout (Scope (gnat_field))
+ else if (Has_Specified_Layout (gnat_record_type)
&& Chars (gnat_field) == Name_uTag)
{
gnu_pos = bitsize_zero_node;
@@ -6928,11 +6928,14 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
/* If the field's type is justified modular, we would need to remove
the wrapper to (better) meet the layout requirements. However we
can do so only if the field is not aliased to preserve the unique
- layout and if the prescribed size is not greater than that of the
- packed array to preserve the justification. */
+ layout, if it has the same storage order as the enclosing record
+ and if the prescribed size is not greater than that of the packed
+ array to preserve the justification. */
if (!needs_strict_alignment
&& TREE_CODE (gnu_field_type) == RECORD_TYPE
&& TYPE_JUSTIFIED_MODULAR_P (gnu_field_type)
+ && TYPE_REVERSE_STORAGE_ORDER (gnu_field_type)
+ == Reverse_Storage_Order (gnat_record_type)
&& tree_int_cst_compare (gnu_size, TYPE_ADA_SIZE (gnu_field_type))
<= 0)
gnu_field_type = TREE_TYPE (TYPE_FIELDS (gnu_field_type));
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index cf64d229a5b..5583903b5cd 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -3600,9 +3600,16 @@ return_value_ok_for_nrv_p (tree ret_obj, tree ret_val)
if (TREE_ADDRESSABLE (ret_val))
return false;
+ /* For the constrained case, test for overalignment. */
if (ret_obj && DECL_ALIGN (ret_val) > DECL_ALIGN (ret_obj))
return false;
+ /* For the unconstrained case, test for bogus initialization. */
+ if (!ret_obj
+ && DECL_INITIAL (ret_val)
+ && TREE_CODE (DECL_INITIAL (ret_val)) == NULL_EXPR)
+ return false;
+
return true;
}
@@ -7696,7 +7703,6 @@ gnat_to_gnu (Node_Id gnat_node)
&& (kind == N_Identifier
|| kind == N_Expanded_Name
|| kind == N_Explicit_Dereference
- || kind == N_Function_Call
|| kind == N_Indexed_Component
|| kind == N_Selected_Component)
&& TREE_CODE (get_base_type (gnu_result_type)) == BOOLEAN_TYPE
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index c47be7d2951..86848ac4bc2 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -238,6 +238,7 @@ static GTY ((cache))
hash_table<pad_type_hasher> *pad_type_hash_table;
static tree merge_sizes (tree, tree, tree, bool, bool);
+static tree fold_bit_position (const_tree);
static tree compute_related_constant (tree, tree);
static tree split_plus (tree, tree *);
static tree float_type_for_precision (int, machine_mode);
@@ -2021,15 +2022,11 @@ rest_of_record_type_compilation (tree record_type)
{
tree field_type = TREE_TYPE (old_field);
tree field_name = DECL_NAME (old_field);
- tree curpos = bit_position (old_field);
+ tree curpos = fold_bit_position (old_field);
tree pos, new_field;
bool var = false;
unsigned int align = 0;
- /* We're going to do some pattern matching below so remove as many
- conversions as possible. */
- curpos = remove_conversions (curpos, true);
-
/* See how the position was modified from the last position.
There are two basic cases we support: a value was added
@@ -2126,7 +2123,7 @@ rest_of_record_type_compilation (tree record_type)
is when there are other components at fixed positions after
it (meaning there was a rep clause for every field) and we
want to be able to encode them. */
- last_pos = size_binop (PLUS_EXPR, bit_position (old_field),
+ last_pos = size_binop (PLUS_EXPR, curpos,
(TREE_CODE (TREE_TYPE (old_field))
== QUAL_UNION_TYPE)
? bitsize_zero_node
@@ -2181,23 +2178,51 @@ merge_sizes (tree last_size, tree first_bit, tree size, bool special,
return new_size;
}
+/* Return the bit position of FIELD, in bits from the start of the record,
+ and fold it as much as possible. This is a tree of type bitsizetype. */
+
+static tree
+fold_bit_position (const_tree field)
+{
+ tree offset = DECL_FIELD_OFFSET (field);
+ if (TREE_CODE (offset) == MULT_EXPR || TREE_CODE (offset) == PLUS_EXPR)
+ offset = size_binop (TREE_CODE (offset),
+ fold_convert (bitsizetype, TREE_OPERAND (offset, 0)),
+ fold_convert (bitsizetype, TREE_OPERAND (offset, 1)));
+ else
+ offset = fold_convert (bitsizetype, offset);
+ return size_binop (PLUS_EXPR, DECL_FIELD_BIT_OFFSET (field),
+ size_binop (MULT_EXPR, offset, bitsize_unit_node));
+}
+
/* Utility function of above to see if OP0 and OP1, both of SIZETYPE, are
related by the addition of a constant. Return that constant if so. */
static tree
compute_related_constant (tree op0, tree op1)
{
- tree op0_var, op1_var;
- tree op0_con = split_plus (op0, &op0_var);
- tree op1_con = split_plus (op1, &op1_var);
- tree result = size_binop (MINUS_EXPR, op0_con, op1_con);
+ tree factor, op0_var, op1_var, op0_cst, op1_cst, result;
- if (operand_equal_p (op0_var, op1_var, 0))
- return result;
- else if (operand_equal_p (op0, size_binop (PLUS_EXPR, op1_var, result), 0))
- return result;
+ if (TREE_CODE (op0) == MULT_EXPR
+ && TREE_CODE (op1) == MULT_EXPR
+ && TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST
+ && TREE_OPERAND (op1, 1) == TREE_OPERAND (op0, 1))
+ {
+ factor = TREE_OPERAND (op0, 1);
+ op0 = TREE_OPERAND (op0, 0);
+ op1 = TREE_OPERAND (op1, 0);
+ }
else
- return 0;
+ factor = NULL_TREE;
+
+ op0_cst = split_plus (op0, &op0_var);
+ op1_cst = split_plus (op1, &op1_var);
+ result = size_binop (MINUS_EXPR, op0_cst, op1_cst);
+
+ if (operand_equal_p (op0_var, op1_var, 0))
+ return factor ? size_binop (MULT_EXPR, factor, result) : result;
+
+ return NULL_TREE;
}
/* Utility function of above to split a tree OP which may be a sum, into a