summaryrefslogtreecommitdiff
path: root/gcc/ada
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2008-04-08 18:12:53 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2008-04-08 18:12:53 +0000
commit1edcfc9493ee4e6ca205437d0950c709fff0bc81 (patch)
treee042a3438f9aaea3565ebd713196dfa9f19c8e53 /gcc/ada
parenta9f6414b86eabf9965e30282fae98653974c175a (diff)
downloadgcc-1edcfc9493ee4e6ca205437d0950c709fff0bc81.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@134101 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada')
-rw-r--r--gcc/ada/ChangeLog21
-rw-r--r--gcc/ada/decl.c16
-rw-r--r--gcc/ada/gigi.h10
-rw-r--r--gcc/ada/trans.c61
-rw-r--r--gcc/ada/utils.c21
5 files changed, 126 insertions, 3 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 4121fe7023e..716f1bd37df 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,5 +1,26 @@
2008-04-08 Eric Botcazou <ebotcazou@adacore.com>
+ * 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.
+
+2008-04-08 Eric Botcazou <ebotcazou@adacore.com>
+
* decl.c (prepend_attributes): Fix typo.
* trans.c (Pragma_to_gnu): Likewise.
* utils.c (gnat_genericize): Likewise.
diff --git a/gcc/ada/decl.c b/gcc/ada/decl.c
index 545730b0465..aca69ff84a3 100644
--- a/gcc/ada/decl.c
+++ b/gcc/ada/decl.c
@@ -3089,6 +3089,22 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
break;
case E_Access_Subprogram_Type:
+ /* Use the special descriptor type for dispatch tables if needed,
+ that is to say for the Prim_Ptr of a-tags.ads and its clones.
+ Note that we are only required to do so for static tables in
+ order to be compatible with the C++ ABI, but Ada 2005 allows
+ to extend library level tagged types at the local level so
+ we do it in the non-static case as well. */
+ if (TARGET_VTABLE_USES_DESCRIPTORS
+ && Is_Dispatch_Table_Entity (gnat_entity))
+ {
+ gnu_type = fdesc_type_node;
+ gnu_size = TYPE_SIZE (gnu_type);
+ break;
+ }
+
+ /* ... fall through ... */
+
case E_Anonymous_Access_Subprogram_Type:
/* If we are not defining this entity, and we have incomplete
entities being processed above us, make a dummy type and
diff --git a/gcc/ada/gigi.h b/gcc/ada/gigi.h
index b35604447e1..59a17ab66af 100644
--- a/gcc/ada/gigi.h
+++ b/gcc/ada/gigi.h
@@ -373,8 +373,12 @@ enum standard_datatypes
/* Type declaration node <==> typedef void *T() */
ADT_ptr_void_ftype,
- /* A function declaration node for a run-time function for allocating memory.
- Ada allocators cause calls to this function to be generated. */
+ /* Type declaration node <==> typedef virtual void *T() */
+ ADT_fdesc_type,
+
+ /* Null pointer for above type */
+ ADT_null_fdesc,
+
ADT_malloc_decl,
/* Likewise for freeing memory. */
@@ -406,6 +410,8 @@ extern GTY(()) tree gnat_raise_decls[(int) LAST_REASON_CODE + 1];
#define ptr_void_type_node gnat_std_decls[(int) ADT_ptr_void_type]
#define void_ftype gnat_std_decls[(int) ADT_void_ftype]
#define ptr_void_ftype gnat_std_decls[(int) ADT_ptr_void_ftype]
+#define fdesc_type_node gnat_std_decls[(int) ADT_fdesc_type]
+#define null_fdesc_node gnat_std_decls[(int) ADT_null_fdesc]
#define malloc_decl gnat_std_decls[(int) ADT_malloc_decl]
#define free_decl gnat_std_decls[(int) ADT_free_decl]
#define jmpbuf_type gnat_std_decls[(int) ADT_jmpbuf_type]
diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c
index a6440d58b73..4dc5202f17c 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;
diff --git a/gcc/ada/utils.c b/gcc/ada/utils.c
index 1625484b6aa..76f4aabbb26 100644
--- a/gcc/ada/utils.c
+++ b/gcc/ada/utils.c
@@ -548,6 +548,27 @@ init_gigi_decls (tree long_long_float_type, tree exception_type)
void_ftype = build_function_type (void_type_node, NULL_TREE);
ptr_void_ftype = build_pointer_type (void_ftype);
+ /* Build the special descriptor type and its null node if needed. */
+ if (TARGET_VTABLE_USES_DESCRIPTORS)
+ {
+ tree field_list = NULL_TREE, null_list = NULL_TREE;
+ int j;
+
+ fdesc_type_node = make_node (RECORD_TYPE);
+
+ for (j = 0; j < TARGET_VTABLE_USES_DESCRIPTORS; j++)
+ {
+ tree field = create_field_decl (NULL_TREE, ptr_void_ftype,
+ fdesc_type_node, 0, 0, 0, 1);
+ TREE_CHAIN (field) = field_list;
+ field_list = field;
+ null_list = tree_cons (field, null_pointer_node, null_list);
+ }
+
+ finish_record_type (fdesc_type_node, nreverse (field_list), 0, false);
+ null_fdesc_node = gnat_build_constructor (fdesc_type_node, null_list);
+ }
+
/* Now declare runtime functions. */
endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);