aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/trans.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2008-04-08 18:12:53 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2008-04-08 18:12:53 +0000
commit581edf9260bddd3f0ce13e2f2b6758f6f638b22c (patch)
treee042a3438f9aaea3565ebd713196dfa9f19c8e53 /gcc/ada/trans.c
parent57b9e36755f9459bcb6b6699b12b150037a5adb4 (diff)
downloadgcc-581edf9260bddd3f0ce13e2f2b6758f6f638b22c.zip
gcc-581edf9260bddd3f0ce13e2f2b6758f6f638b22c.tar.gz
gcc-581edf9260bddd3f0ce13e2f2b6758f6f638b22c.tar.bz2
gigi.h (standard_datatypes): Add ADT_fdesc_type and ADT_null_fdesc.
* gigi.h (standard_datatypes): Add ADT_fdesc_type and ADT_null_fdesc. (fdesc_type_node): Define. (null_fdesc_node): Likewise. * decl.c (gnat_to_gnu_entity) <E_Access_Subprogram_Type>: If the target uses descriptors for vtables and the type comes from a dispatch table, return the descriptor type. * trans.c (Attribute_to_gnu) <Attr_Unrestricted_Access>: If the target uses descriptors for vtables and the type comes from a dispatch table, build a descriptor in the static case and copy the existing one in the non-static case. (gnat_to_gnu) <N_Null>: If the target uses descriptors for vtables and the type is a pointer-to-subprogram coming from a dispatch table, return the null descriptor. <N_Unchecked_Type_Conversion>: If the target uses descriptors for vtables, the source type is the descriptor type and the target type is a pointer type, first build the pointer. * utils.c (init_gigi_decls): If the target uses descriptors for vtables build the descriptor type and the null descriptor. From-SVN: r134101
Diffstat (limited to 'gcc/ada/trans.c')
-rw-r--r--gcc/ada/trans.c61
1 files changed, 60 insertions, 1 deletions
diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c
index a6440d5..4dc5202 100644
--- a/gcc/ada/trans.c
+++ b/gcc/ada/trans.c
@@ -852,6 +852,53 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
if (attribute == Attr_Address)
gnu_prefix = maybe_unconstrained_array (gnu_prefix);
+ /* If we are building a static dispatch table, we have to honor
+ TARGET_VTABLE_USES_DESCRIPTORS if we want to be compatible
+ with the C++ ABI. We do it in the non-static case as well,
+ see gnat_to_gnu_entity, case E_Access_Subprogram_Type. */
+ else if (TARGET_VTABLE_USES_DESCRIPTORS
+ && Is_Dispatch_Table_Entity (Etype (gnat_node)))
+ {
+ tree gnu_field, gnu_list = NULL_TREE, t;
+ /* Descriptors can only be built here for top-level functions. */
+ bool build_descriptor = (global_bindings_p () != 0);
+ int i;
+
+ gnu_result_type = get_unpadded_type (Etype (gnat_node));
+
+ /* If we're not going to build the descriptor, we have to retrieve
+ the one which will be built by the linker (or by the compiler
+ later if a static chain is requested). */
+ if (!build_descriptor)
+ {
+ gnu_result = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_prefix);
+ gnu_result = fold_convert (build_pointer_type (gnu_result_type),
+ gnu_result);
+ gnu_result = build1 (INDIRECT_REF, gnu_result_type, gnu_result);
+ }
+
+ for (gnu_field = TYPE_FIELDS (gnu_result_type), i = 0;
+ i < TARGET_VTABLE_USES_DESCRIPTORS;
+ gnu_field = TREE_CHAIN (gnu_field), i++)
+ {
+ if (build_descriptor)
+ {
+ t = build2 (FDESC_EXPR, TREE_TYPE (gnu_field), gnu_prefix,
+ build_int_cst (NULL_TREE, i));
+ TREE_CONSTANT (t) = 1;
+ TREE_INVARIANT (t) = 1;
+ }
+ else
+ t = build3 (COMPONENT_REF, ptr_void_ftype, gnu_result,
+ gnu_field, NULL_TREE);
+
+ gnu_list = tree_cons (gnu_field, t, gnu_list);
+ }
+
+ gnu_result = gnat_build_constructor (gnu_result_type, gnu_list);
+ break;
+ }
+
/* ... fall through ... */
case Attr_Access:
@@ -3649,7 +3696,12 @@ gnat_to_gnu (Node_Id gnat_node)
break;
case N_Null:
- gnu_result = null_pointer_node;
+ if (TARGET_VTABLE_USES_DESCRIPTORS
+ && Ekind (Etype (gnat_node)) == E_Access_Subprogram_Type
+ && Is_Dispatch_Table_Entity (Etype (gnat_node)))
+ gnu_result = null_fdesc_node;
+ else
+ gnu_result = null_pointer_node;
gnu_result_type = get_unpadded_type (Etype (gnat_node));
break;
@@ -3687,6 +3739,13 @@ gnat_to_gnu (Node_Id gnat_node)
size_int (align / BITS_PER_UNIT), oalign / BITS_PER_UNIT);
}
+ /* If we are converting a descriptor to a function pointer, first
+ build the pointer. */
+ if (TARGET_VTABLE_USES_DESCRIPTORS
+ && TREE_TYPE (gnu_result) == fdesc_type_node
+ && POINTER_TYPE_P (gnu_result_type))
+ gnu_result = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_result);
+
gnu_result = unchecked_convert (gnu_result_type, gnu_result,
No_Truncation (gnat_node));
break;