aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/trans.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2005-07-04 15:27:21 +0200
committerArnaud Charlet <charlet@gcc.gnu.org>2005-07-04 15:27:21 +0200
commitd9e0a58787285a0753791dd83a5d831bbbc92117 (patch)
tree617e7a72024f1df19ef1395e2e890a2461922a3f /gcc/ada/trans.c
parentc73ae90f23fab6c872b09e02b0d1e34727883056 (diff)
downloadgcc-d9e0a58787285a0753791dd83a5d831bbbc92117.zip
gcc-d9e0a58787285a0753791dd83a5d831bbbc92117.tar.gz
gcc-d9e0a58787285a0753791dd83a5d831bbbc92117.tar.bz2
decl.c (prepend_attributes): New case.
2005-07-04 Eric Botcazou <ebotcazou@adacore.com> * decl.c (prepend_attributes) <Pragma_Linker_Constructor>: New case. <Pragma_Linker_Destructor>: Likewise. * einfo.ads (Has_Gigi_Rep_Item): Document Pragma_Linker_Constructor and Pragma_Linker_Destructor. * gigi.h (attr_type): Add ATTR_LINK_CONSTRUCTOR and ATTR_LINK_DESTRUCTOR. (static_ctors, static_dtors): New variables. * misc.c (gnat_expand_body): Output current function as constructor and destructor if requested. * par-prag.adb: Add processing for pragma Linker_Constructor and Linker_Destructor. * sem_prag.adb (Find_Unique_Parameterless_Procedure): New function extracted from Check_Interrupt_Or_Attach_Handler. (Check_Interrupt_Or_Attach_Handler): Invoke it. Implement pragma Linker_Constructor and Linker_Destructor with the help of Find_Unique_Parameterless_Procedure. Replace Name_Alias with Name_Target for pragma Linker_Alias. * snames.h, snames.ads, snames.adb: Add Name_Linker_Constructor and Name_Linker_Destructor. Add Pragma_Linker_Constructor and Pragma_Linker_Destructor. * snames.adb: Remove Name_Alias. * trans.c: Include cgraph.h. (build_global_cdtor): New function. (Compilation_Unit_to_gnu): Build global constructor and destructor if needed. (tree_transform) <N_Identifier>: Substitute renaming of view-conversions of objects too. (addressable_p) <COMPONENT_REF>: Unconditionally test DECL_NONADDRESSABLE_P on STRICT_ALIGNMENT platforms. * utils.c (process_attributes) <ATTR_LINK_ALIAS>: Do not assemble the variable if it is external. (static_ctors, static_dtors): New global variables. (process_attributes) <ATTR_LINK_CONSTRUCTOR>: New case. <ATTR_LINK_DESTRUCTOR>: Likewise. (end_subprog_body): Chain function as constructor and destructor if requested. * exp_util.adb (Force_Evaluation): Unconditionally invoke Remove_Side_Effects with Variable_Ref set to true. (Remove_Side_Effects): Handle scalar types first. Use a renaming for non-scalar types even if Variable_Ref is true and for class-wide expressions. From-SVN: r101576
Diffstat (limited to 'gcc/ada/trans.c')
-rw-r--r--gcc/ada/trans.c45
1 files changed, 41 insertions, 4 deletions
diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c
index cdb5506..3a3327a 100644
--- a/gcc/ada/trans.c
+++ b/gcc/ada/trans.c
@@ -35,6 +35,7 @@
#include "rtl.h"
#include "expr.h"
#include "ggc.h"
+#include "cgraph.h"
#include "function.h"
#include "except.h"
#include "debug.h"
@@ -164,6 +165,7 @@ static tree pos_to_constructor (Node_Id, tree, Entity_Id);
static tree maybe_implicit_deref (tree);
static tree gnat_stabilize_reference_1 (tree, bool);
static void annotate_with_node (tree, Node_Id);
+static void build_global_cdtor (int, tree *);
/* This is the main program of the back-end. It sets up all the table
@@ -410,7 +412,11 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
&& (! DECL_RENAMING_GLOBAL_P (gnu_result)
|| global_bindings_p ())
/* Make sure it's an lvalue like INDIRECT_REF. */
- && (DECL_P (renamed_obj) || REFERENCE_CLASS_P (renamed_obj)))
+ && (DECL_P (renamed_obj)
+ || REFERENCE_CLASS_P (renamed_obj)
+ || (TREE_CODE (renamed_obj) == VIEW_CONVERT_EXPR
+ && (DECL_P (TREE_OPERAND (renamed_obj, 0))
+ || REFERENCE_CLASS_P (TREE_OPERAND (renamed_obj,0))))))
gnu_result = renamed_obj;
else
gnu_result = build_unary_op (INDIRECT_REF, NULL_TREE,
@@ -2405,7 +2411,7 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
Sloc_to_locus (Sloc (gnat_unit_entity), &cfun->function_end_locus);
cfun = 0;
- /* For a body, first process the spec if there is one. */
+ /* For a body, first process the spec if there is one. */
if (Nkind (Unit (gnat_node)) == N_Package_Body
|| (Nkind (Unit (gnat_node)) == N_Subprogram_Body
&& !Acts_As_Spec (gnat_node)))
@@ -2445,6 +2451,15 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
/* Generate elaboration code for this unit, if necessary, and say whether
we did or not. */
pop_stack (&gnu_elab_proc_stack);
+
+ /* Generate functions to call static constructors and destructors
+ for targets that do not support .ctors/.dtors sections. These
+ functions have magic names which are detected by collect2. */
+ if (static_ctors)
+ build_global_cdtor ('I', &static_ctors);
+
+ if (static_dtors)
+ build_global_cdtor ('D', &static_dtors);
}
/* This function is the driver of the GNAT to GCC tree transformation
@@ -5353,8 +5368,8 @@ addressable_p (tree gnu_expr)
case COMPONENT_REF:
return (!DECL_BIT_FIELD (TREE_OPERAND (gnu_expr, 1))
- && (!DECL_NONADDRESSABLE_P (TREE_OPERAND (gnu_expr, 1))
- || !flag_strict_aliasing)
+ && !(STRICT_ALIGNMENT
+ && DECL_NONADDRESSABLE_P (TREE_OPERAND (gnu_expr, 1)))
&& addressable_p (TREE_OPERAND (gnu_expr, 0)));
case ARRAY_REF: case ARRAY_RANGE_REF:
@@ -5859,6 +5874,28 @@ gnat_stabilize_reference_1 (tree e, bool force)
TREE_SIDE_EFFECTS (result) |= TREE_SIDE_EFFECTS (e);
return result;
}
+
+/* Build a global constructor or destructor function. METHOD_TYPE gives
+ the type of the function and CDTORS points to the list of constructor
+ or destructor functions to be invoked. FIXME: Migrate into cgraph. */
+
+static void
+build_global_cdtor (int method_type, tree *cdtors)
+{
+ tree body = 0;
+
+ for (; *cdtors; *cdtors = TREE_CHAIN (*cdtors))
+ {
+ tree fn = TREE_VALUE (*cdtors);
+ tree fntype = TREE_TYPE (fn);
+ tree fnaddr = build1 (ADDR_EXPR, build_pointer_type (fntype), fn);
+ tree fncall = build3 (CALL_EXPR, TREE_TYPE (fntype), fnaddr, NULL_TREE,
+ NULL_TREE);
+ append_to_statement_list (fncall, &body);
+ }
+
+ cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY);
+}
extern char *__gnat_to_canonical_file_spec (char *);