+2014-07-31 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_util.adb (Is_Effectively_Volatile): New routine.
+
+2014-07-31 Fedor Rybin <frybin@adacore.com>
+
+ * gnat_ugn.texi: Document --test-duration option for gnattest.
+
+2014-07-31 Javier Miranda <miranda@adacore.com>
+
+ * opt.ads (Back_End_Inlining): New variable which controls
+ activation of inlining by back-end expansion.
+ * gnat1drv.adb (Adjust_Global_Switches): Initialize Back_End_Inlining
+ * sem_ch6.adb (Analyze_Subprogram_Body_Helper): Do not build
+ the body to be inlined by the frontend if Back_End_Inlining
+ is enabled.
+ * exp_ch6.adb (Register_Backend_Call): Moved to inline.adb.
+ (Expand_Call): If backend inlining is enabled let the backend to
+ handle inlined subprograms.
+ * inline.ads (Register_Backend_Call): Moved here from exp_ch6
+ * inline.adb (Register_Backend_Call): Moved here from exp_ch6.
+ (Add_Inlined_Subprogram): Add subprograms when Back_End_Inlining is set.
+ (Must_Inline): Do not return Inline_Call if Back_End_Inlining is
+ enabled.
+ * debug.adb Document -gnatd.z
+ * fe.h Import Back_End_Inlining variable.
+ * gcc-interface/utils.c (create_subprog_decl): If Back_End_Inlining is
+ enabled then declare attribute "always inline"
+
+2014-07-31 Robert Dewar <dewar@adacore.com>
+
+ * a-ngelfu.ads: Minor comment fix.
+
2014-07-31 Hristian Kirtchev <kirtchev@adacore.com>
* freeze.adb (Freeze_Record_Type): Replace all calls to
-- and the sqrt of numbers less than 1 is greater than the argument).
-- This property is useful in particular for static analysis. The
- -- property that X is positive is not expressed as (X > 0), as
+ -- property that X is positive is not expressed as (X > 0.0), as
-- the value X may be held in registers that have larger range and
-- precision on some architecture (for example, on x86 using x387
-- FPU, as opposed to SSE2). So, it might be possible for X to be
-- d.w Do not check for infinite loops
-- d.x No exception handlers
-- d.y
- -- d.z
+ -- d.z Enable new support for backend inlining
-- d.A Read/write Aspect_Specifications hash table to tree
-- d.B
-- fully compiled and analyzed, they just get eliminated from the
-- code generation step.
+ -- d.z Need documentation of this flag ???
+
-- d.A There seems to be a problem with ASIS if we activate the circuit
-- for reading and writing the aspect specification hash table, so
-- for now, this is controlled by the debug flag d.A. The hash table
-- then register the enclosing unit of Subp to Inlined_Bodies so that
-- the body of Subp can be retrieved and analyzed by the backend.
- procedure Register_Backend_Call (N : Node_Id);
- -- Append N to the list Backend_Calls
-
-----------------------
-- Do_Backend_Inline --
-----------------------
end if;
end Do_Backend_Inline;
- ---------------------------
- -- Register_Backend_Call --
- ---------------------------
-
- procedure Register_Backend_Call (N : Node_Id) is
- begin
- if Backend_Calls = No_Elist then
- Backend_Calls := New_Elmt_List;
- end if;
-
- Append_Elmt (N, To => Backend_Calls);
- end Register_Backend_Call;
-
-- Start of processing for Do_Inline
begin
return;
end if;
+ -- Back end inlining: let the back end handle it
+
+ if Back_End_Inlining
+ and then Is_Inlined (Subp)
+ then
+ Add_Inlined_Body (Subp);
+ Register_Backend_Call (Call_Node);
+
-- Handle inlining (old semantics)
- if Is_Inlined (Subp) and then not Debug_Flag_Dot_K then
+ elsif Is_Inlined (Subp) and then not Debug_Flag_Dot_K then
Inlined_Subprogram : declare
Bod : Node_Id;
Must_Inline : Boolean := False;
/* opt: */
+#define Back_End_Inlining opt__back_end_inlining
#define Exception_Extra_Info opt__exception_extra_info
#define Exception_Locations_Suppressed opt__exception_locations_suppressed
#define Exception_Mechanism opt__exception_mechanism
typedef enum {Setjmp_Longjmp, Back_End_Exceptions} Exception_Mechanism_Type;
+extern Boolean Back_End_Inlining;
extern Boolean Exception_Extra_Info;
extern Boolean Exception_Locations_Suppressed;
extern Exception_Mechanism_Type Exception_Mechanism;
/* No inlining is requested for the subprogram. */
is_disabled,
/* Inlining is requested for the subprogram. */
- is_enabled
+ is_enabled,
+ /* Inlining is required for the subprogram. */
+ is_required
};
extern GTY(()) tree gnat_std_decls[(int) ADT_LAST];
static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
+static tree handle_always_inline_attribute (tree *, tree, tree, int, bool *);
static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
static tree handle_vector_size_attribute (tree *, tree, tree, int, bool *);
false },
{ "leaf", 0, 0, true, false, false, handle_leaf_attribute,
false },
+ { "always_inline",0, 0, true, false, false, handle_always_inline_attribute,
+ false },
{ "malloc", 0, 0, true, false, false, handle_malloc_attribute,
false },
{ "type generic", 0, 0, false, true, true, handle_type_generic_attribute,
case is_disabled:
break;
+ case is_required:
+ if (Back_End_Inlining)
+ decl_attributes (&subprog_decl,
+ tree_cons (get_identifier ("always_inline"),
+ NULL_TREE, NULL_TREE),
+ ATTR_FLAG_TYPE_IN_PLACE);
+ /* ... fall through ... */
+
case is_enabled:
DECL_DECLARED_INLINE_P (subprog_decl) = 1;
DECL_NO_INLINE_WARNING_P (subprog_decl) = artificial_flag;
TREE_STATIC (dummy_global) = 1;
node = varpool_node::get_create (dummy_global);
node->definition = 1;
+ node->definition = 1;
node->force_output = 1;
while (!types_used_by_cur_var_decl->is_empty ())
struct attribute_spec.handler. */
static tree
-handle_leaf_attribute (tree *node, tree name,
- tree ARG_UNUSED (args),
+handle_leaf_attribute (tree *node, tree name, tree ARG_UNUSED (args),
int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) != FUNCTION_DECL)
return NULL_TREE;
}
+/* Handle a "always_inline" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_always_inline_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ {
+ /* Set the attribute and mark it for disregarding inline limits. */
+ DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
+ }
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Handle a "malloc" attribute; arguments as in
struct attribute_spec.handler. */
end if;
end if;
+ -- No backend inlining for AAMP, VM. Turn off inlining under GNATprove
+ -- mode which would confuse formal verification output. Turn off backend
+ -- inlining if the frontend inlining is enabled.
+
+ Back_End_Inlining :=
+ VM_Target = No_VM
+ and then not AAMP_On_Target
+ and then not GNATprove_Mode
+ and then not Front_End_Inlining
+ and then Debug_Flag_Dot_Z;
+
-- Output warning if -gnateE specified and cannot be supported
if Exception_Extra_Info
Suppresses comment line containing file name and line number of corresponding
subprograms in test skeletons.
+@item --test-duration
+@cindex @option{--test-duration} (@command{gnattest})
+Adds time measurements for each test in generated test driver.
+
@end table
@option{--tests_root}, @option{--subdir} and @option{--tests-dir} switches are
Set_Is_Inlined (Pack);
Inlined_Bodies.Increment_Last;
Inlined_Bodies.Table (Inlined_Bodies.Last) := Pack;
+
+ -- If the backend takes care of inlining the call then we must
+ -- ensure that it has available the body of the subprogram.
+
+ elsif Level = Inline_Call
+ and then Back_End_Inlining
+ then
+ Inlined_Bodies.Increment_Last;
+ Inlined_Bodies.Table (Inlined_Bodies.Last) := Pack;
end if;
end if;
end;
-- subprogram has been generated by the compiler, and if it is declared
-- at the library level not in the main unit, and if it can be inlined
-- by the back-end, then insert it in the list of inlined subprograms.
+ -- We also add it when its unit is not inlined but we are compiling with
+ -- Back_End_Inlining since at this stage we know that Add_Inlined_Body
+ -- forced loading its unit to allow the backend to inline single calls
+ -- at -gnatn1
if Is_Inlined (E)
and then (Is_Inlined (Pack)
or else Is_Generic_Instance (Pack)
- or else Is_Internal (E))
+ or else Is_Internal (E)
+ or else Back_End_Inlining)
and then not In_Main_Unit_Or_Subunit (E)
and then not Is_Nested (E)
and then not Has_Initialized_Type (E)
Inlined.Release;
end Lock;
+ ---------------------------
+ -- Register_Backend_Call --
+ ---------------------------
+
+ procedure Register_Backend_Call (N : Node_Id) is
+ begin
+ if Backend_Calls = No_Elist then
+ Backend_Calls := New_Elmt_List;
+ end if;
+
+ Append_Elmt (N, To => Backend_Calls);
+ end Register_Backend_Call;
+
--------------------------
-- Remove_Dead_Instance --
--------------------------
-- expressions in the body must be converted to the desired type (which
-- is simply not noted in the tree without inline expansion).
+ procedure Register_Backend_Call (N : Node_Id);
+ -- Append N to the list Backend_Calls
+
procedure Remove_Dead_Instance (N : Node_Id);
-- If an instantiation appears in unreachable code, delete the pending
-- body instance.
-- default can be modified using -gnatd.L (sets the flag True). This is
-- used to test the possibility of having the backend handle this.
+ Back_End_Inlining : Boolean := False;
+ -- GNAT
+ -- Set True to activate inlining by back-end expansion
+
Bind_Alternate_Main_Name : Boolean := False;
-- GNATBIND
-- True if main should be called Alternate_Main_Name.all.
-- Old semantics
if not Debug_Flag_Dot_K then
+
+ -- If the backend inlining is available then at this stage we only
+ -- have to mark the subprogram as inlined. The expander will take
+ -- care of registering it in the table of subprograms inlined by
+ -- the backend a part of processing calls to it (cf. Expand_Call)
+
if Present (Spec_Id)
+ and then Expander_Active
+ and then Back_End_Inlining
+ then
+ Set_Is_Inlined (Spec_Id);
+
+ elsif Present (Spec_Id)
and then Expander_Active
and then
(Has_Pragma_Inline_Always (Spec_Id)
-- Otherwise Id denotes an object
else
- return Is_Volatile (Id) or else Is_Effectively_Volatile (Etype (Id));
+ return
+ Is_Volatile (Id)
+ or else Has_Volatile_Components (Id)
+ or else Is_Effectively_Volatile (Etype (Id));
end if;
end Is_Effectively_Volatile;