LCOV - code coverage report
Current view: top level - gcc/m2/gm2-gcc - m2statement.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 77.8 % 338 263
Test Date: 2026-04-20 14:57:17 Functions: 73.8 % 42 31
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* m2statement.cc provides an interface to GCC statement trees.
       2              : 
       3              : Copyright (C) 2012-2026 Free Software Foundation, Inc.
       4              : Contributed by Gaius Mulley <gaius@glam.ac.uk>.
       5              : 
       6              : This file is part of GNU Modula-2.
       7              : 
       8              : GNU Modula-2 is free software; you can redistribute it and/or modify
       9              : it under the terms of the GNU General Public License as published by
      10              : the Free Software Foundation; either version 3, or (at your option)
      11              : any later version.
      12              : 
      13              : GNU Modula-2 is distributed in the hope that it will be useful, but
      14              : WITHOUT ANY WARRANTY; without even the implied warranty of
      15              : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16              : General Public License for more details.
      17              : 
      18              : You should have received a copy of the GNU General Public License
      19              : along with GNU Modula-2; see the file COPYING3.  If not see
      20              : <http://www.gnu.org/licenses/>.  */
      21              : 
      22              : #include "gcc-consolidation.h"
      23              : 
      24              : #include "../gm2-lang.h"
      25              : #include "../m2-tree.h"
      26              : 
      27              : /* Prototypes.  */
      28              : 
      29              : #define m2statement_c
      30              : #include "m2assert.h"
      31              : #include "m2block.h"
      32              : #include "m2decl.h"
      33              : #include "m2expr.h"
      34              : #include "m2statement.h"
      35              : #include "m2tree.h"
      36              : #include "m2treelib.h"
      37              : #include "m2type.h"
      38              : #include "m2convert.h"
      39              : #include "m2builtins.h"
      40              : #include "m2pp.h"
      41              : 
      42              : static GTY (()) tree param_list = NULL_TREE; /* Ready for the next time we
      43              :                                                 call/define a function.  */
      44              : static GTY (()) tree last_function = NULL_TREE;
      45              : 
      46              : 
      47              : /* BuildStartFunctionCode generate function entry code.  */
      48              : 
      49              : void
      50       110259 : m2statement_BuildStartFunctionCode (location_t location, tree fndecl,
      51              :                                     bool isexported, bool isinline)
      52              : {
      53       110259 :   tree param_decl;
      54              : 
      55       110259 :   ASSERT_BOOL (isexported);
      56       110259 :   ASSERT_BOOL (isinline);
      57              :   /* Announce we are compiling this function.  */
      58       110259 :   announce_function (fndecl);
      59              : 
      60              :   /* Set up to compile the function and enter it.  */
      61              : 
      62       110259 :   DECL_INITIAL (fndecl) = NULL_TREE;
      63              : 
      64       110259 :   current_function_decl = fndecl;
      65       110259 :   m2block_pushFunctionScope (fndecl);
      66       110259 :   m2statement_SetBeginLocation (location);
      67              : 
      68       110259 :   ASSERT_BOOL ((cfun != NULL));
      69              :   /* Initialize the RTL code for the function.  */
      70       110259 :   allocate_struct_function (fndecl, false);
      71              :   /* Begin the statement tree for this function.  */
      72       110259 :   DECL_SAVED_TREE (fndecl) = NULL_TREE;
      73              : 
      74              :   /* Set the context of these parameters to this function.  */
      75       293736 :   for (param_decl = DECL_ARGUMENTS (fndecl); param_decl;
      76       183477 :        param_decl = TREE_CHAIN (param_decl))
      77       183477 :     DECL_CONTEXT (param_decl) = fndecl;
      78              : 
      79              :   /* This function exists in static storage.  (This does not mean
      80              :   `static' in the C sense!) */
      81       110259 :   TREE_STATIC (fndecl) = 1;
      82       110259 :   TREE_PUBLIC (fndecl) = isexported;
      83              :   /* We could do better here by detecting ADR
      84              :      or type PROC used on this function.  --fixme--  */
      85       110259 :   TREE_ADDRESSABLE (fndecl) = 1;
      86       110259 :   DECL_DECLARED_INLINE_P (fndecl) = 0; /* isinline;  */
      87       110259 : }
      88              : 
      89              : /* BuildEndFunctionCode generates the function epilogue.  */
      90              : 
      91              : void
      92       110247 : m2statement_BuildEndFunctionCode (location_t location, tree fndecl, bool nested)
      93              : {
      94       110247 :   tree block = DECL_INITIAL (fndecl);
      95              : 
      96       110247 :   BLOCK_SUPERCONTEXT (block) = fndecl;
      97              : 
      98              :   /* Must mark the RESULT_DECL as being in this function.  */
      99       110247 :   DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
     100              : 
     101              :   /* And attach it to the function.  */
     102       110247 :   DECL_INITIAL (fndecl) = block;
     103              : 
     104       110247 :   m2block_finishFunctionCode (fndecl);
     105       110247 :   m2statement_SetEndLocation (location);
     106              : 
     107       110247 :   m2pp_dump_gimple (M2PP_DUMP_PRE_GENERICIZE, fndecl);
     108       110247 :   gm2_genericize (fndecl);
     109       110247 :   if (nested)
     110          744 :     (void)cgraph_node::get_create (fndecl);
     111              :   else
     112              :     {
     113       109503 :       m2pp_dump_gimple (M2PP_DUMP_POST_GENERICIZE, fndecl);
     114       109503 :       cgraph_node::finalize_function (fndecl, false);
     115              :     }
     116              : 
     117       110247 :   m2block_popFunctionScope ();
     118              : 
     119              :   /* We're leaving the context of this function, so zap cfun.  It's
     120              :      still in DECL_STRUCT_FUNCTION, and we'll restore it in
     121              :      tree_rest_of_compilation.  */
     122       110247 :   set_cfun (NULL);
     123       110247 :   current_function_decl = NULL;
     124       110247 : }
     125              : 
     126              : /* BuildPushFunctionContext pushes the current function context.
     127              :    Maps onto push_function_context in ../function.cc.  */
     128              : 
     129              : void
     130        79597 : m2statement_BuildPushFunctionContext (void)
     131              : {
     132        79597 :   push_function_context ();
     133        79597 : }
     134              : 
     135              : /* BuildPopFunctionContext pops the current function context.  Maps
     136              :    onto pop_function_context in ../function.cc.  */
     137              : 
     138              : void
     139        79597 : m2statement_BuildPopFunctionContext (void)
     140              : {
     141        79597 :   pop_function_context ();
     142        79597 : }
     143              : 
     144              : void
     145       189856 : m2statement_SetBeginLocation (location_t location)
     146              : {
     147       189856 :   if (cfun != NULL)
     148            0 :     cfun->function_start_locus = location;
     149       189856 : }
     150              : 
     151              : void
     152       110247 : m2statement_SetEndLocation (location_t location)
     153              : {
     154       110247 :   if (cfun != NULL)
     155       110247 :     cfun->function_end_locus = location;
     156       110247 : }
     157              : 
     158              : /* copy_record_fields copy each record field from right to left.  */
     159              : 
     160              : static
     161              : void
     162           72 : copy_record_fields (location_t location, tree left, tree right)
     163              : {
     164           72 :   unsigned int i;
     165           72 :   tree right_value;
     166           72 :   tree left_type = TREE_TYPE (left);
     167           72 :   vec<constructor_elt, va_gc> *values = CONSTRUCTOR_ELTS (right);
     168          204 :   FOR_EACH_CONSTRUCTOR_VALUE (values, i, right_value)
     169              :     {
     170          132 :       tree left_field = m2treelib_get_field_no (left_type, NULL_TREE, false, i);
     171          132 :       tree left_ref = m2expr_BuildComponentRef (location, left, left_field);
     172          132 :       m2statement_CopyByField (location, left_ref, right_value);
     173              :     }
     174           72 : }
     175              : 
     176              : /* copy_array copy each element of an array from array right to array left.  */
     177              : 
     178              : static
     179              : void
     180            0 : copy_array (location_t location, tree left, tree right)
     181              : {
     182            0 :   unsigned int i;
     183            0 :   tree value;
     184            0 :   vec<constructor_elt, va_gc> *values = CONSTRUCTOR_ELTS (right);
     185            0 :   tree array_type = TREE_TYPE (left);
     186            0 :   tree index_type = TYPE_DOMAIN (array_type);
     187            0 :   tree elt_type = TREE_TYPE (array_type);
     188            0 :   tree low_indice = TYPE_MIN_VALUE (index_type);
     189            0 :   low_indice
     190            0 :       = m2convert_BuildConvert (location, index_type, low_indice, false);
     191            0 :   FOR_EACH_CONSTRUCTOR_VALUE (values, i, value)
     192              :     {
     193            0 :       tree idx = m2decl_BuildIntegerConstant (i);
     194            0 :       idx = m2convert_BuildConvert (location, index_type, idx, false);
     195            0 :       tree array_ref = build4_loc (location, ARRAY_REF, elt_type, left,
     196              :                                    idx, low_indice, NULL_TREE);
     197            0 :       m2statement_CopyByField (location, array_ref, value);
     198              :     }
     199            0 : }
     200              : 
     201              : /* copy_array cst into left using strncpy.  */
     202              : 
     203              : static
     204              : void
     205           84 : copy_strncpy (location_t location, tree left, tree cst)
     206              : {
     207           84 :   tree result = m2builtins_BuiltinStrNCopy (location,
     208              :                                             m2expr_BuildAddr (location, left, false),
     209              :                                             m2expr_BuildAddr (location, cst, false),
     210           84 :                                             m2decl_BuildIntegerConstant (m2expr_StringLength (cst)));
     211           84 :   TREE_SIDE_EFFECTS (result) = true;
     212           84 :   TREE_USED (left) = true;
     213           84 :   TREE_USED (cst) = true;
     214           84 :   add_stmt (location, result);
     215           84 : }
     216              : 
     217              : /* CopyMemcpy copy bytes from src into dest using builtin_memcpy.  */
     218              : 
     219              : void
     220         2434 : m2statement_CopyMemcpy (location_t location, tree dest, tree src, tree bytes)
     221              : {
     222         2434 :   tree addr_dest = m2expr_BuildAddr (location, dest, false);
     223         2434 :   tree result = m2builtins_BuiltinMemCopy (location,
     224              :                                            addr_dest,
     225              :                                            m2expr_BuildAddr (location, src, false),
     226              :                                            bytes);
     227         2434 :   TREE_SIDE_EFFECTS (result) = true;
     228         2434 :   TREE_USED (dest) = true;
     229         2434 :   TREE_USED (src) = true;
     230         2434 :   add_stmt (location, result);
     231         2434 : }
     232              : 
     233              : /* CopyByField_Lower copy right to left using memcpy for unions,
     234              :    strncpy for string cst, field assignment for records,
     235              :    array element assignment for array constructors.  For all
     236              :    other types it uses BuildAssignmentStatement.  */
     237              : 
     238              : static
     239              : void
     240          156 : CopyByField_Lower (location_t location,
     241              :                    tree left, tree right)
     242              : {
     243          156 :   tree left_type = TREE_TYPE (left);
     244          156 :   enum tree_code right_code = TREE_CODE (right);
     245          156 :   enum tree_code left_code = TREE_CODE (left_type);
     246              : 
     247          156 :   if (left_code == RECORD_TYPE && right_code == CONSTRUCTOR)
     248           72 :     copy_record_fields (location, left, right);
     249           84 :   else if (left_code == ARRAY_TYPE && right_code == CONSTRUCTOR)
     250            0 :     copy_array (location, left, right);
     251           84 :   else if (left_code == UNION_TYPE && right_code == CONSTRUCTOR)
     252            0 :     m2statement_CopyMemcpy (location, left, right,
     253              :                             m2expr_GetSizeOf (location, left));
     254           84 :   else if (right_code == STRING_CST)
     255           84 :     copy_strncpy (location, left, right);
     256              :   else
     257            0 :     m2statement_BuildAssignmentStatement (location, left, right);
     258          156 : }
     259              : 
     260              : /* CopyByField recursively checks each field to ensure GCC
     261              :    type equivalence and if so it uses assignment.
     262              :    Otherwise use strncpy or memcpy depending upon type.  */
     263              : 
     264              : void
     265          204 : m2statement_CopyByField (location_t location, tree des, tree expr)
     266              : {
     267          204 :   if (m2type_IsGccStrictTypeEquivalent (des, expr))
     268           48 :     m2statement_BuildAssignmentStatement (location, des, expr);
     269              :   else
     270          156 :     CopyByField_Lower (location, des, expr);
     271          204 : }
     272              : 
     273              : /* BuildAssignmentTree builds the assignment of des and expr.
     274              :    It returns des.  */
     275              : 
     276              : void
     277       703050 : m2statement_BuildAssignmentTree (location_t location, tree des, tree expr)
     278              : {
     279       703050 :   tree result;
     280              : 
     281       703050 :   m2assert_AssertLocation (location);
     282      1417298 :   STRIP_TYPE_NOPS (expr);
     283              : 
     284       703050 :   if (TREE_CODE (expr) == FUNCTION_DECL)
     285          672 :     result = build2 (MODIFY_EXPR, TREE_TYPE (des), des,
     286              :                      m2expr_BuildAddr (location, expr, false));
     287              :   else
     288              :     {
     289       702378 :       gcc_assert (TREE_CODE (TREE_TYPE (des)) != TYPE_DECL);
     290       702378 :       if ((TREE_CODE (expr) == CONSTRUCTOR)
     291       702378 :           && (TREE_CODE (TREE_TYPE (des)) == ARRAY_TYPE))
     292              :         {
     293         1502 :           m2statement_CopyMemcpy (location, des, expr,
     294              :                                   m2expr_GetSizeOf (location,
     295              :                                                     m2type_GetTreeType (des)));
     296         1502 :           return;
     297              :         }
     298       700876 :       else if (TREE_TYPE (expr) == TREE_TYPE (des))
     299       420431 :         result = build2 (MODIFY_EXPR, TREE_TYPE (des), des, expr);
     300              :       else
     301       560890 :         result = build2 (
     302       280445 :             MODIFY_EXPR, TREE_TYPE (des), des,
     303       280445 :             m2convert_BuildConvert (location, TREE_TYPE (des), expr, false));
     304              :     }
     305              : 
     306       701548 :   TREE_SIDE_EFFECTS (result) = true;
     307       701548 :   TREE_USED (des) = true;
     308       701548 :   TREE_USED (expr) = true;
     309       701548 :   add_stmt (location, result);
     310              : }
     311              : 
     312              : /* BuildAssignmentStatement builds the assignment of des and expr.  */
     313              : 
     314              : void
     315       702006 : m2statement_BuildAssignmentStatement (location_t location, tree des, tree expr)
     316              : {
     317       702006 :   m2statement_BuildAssignmentTree (location, des, expr);
     318       702006 : }
     319              : 
     320              : /* BuildGoto builds a goto operation.  */
     321              : 
     322              : void
     323       126638 : m2statement_BuildGoto (location_t location, char *name)
     324              : {
     325       126638 :   tree label = m2block_getLabel (location, name);
     326              : 
     327       126638 :   m2assert_AssertLocation (location);
     328       126638 :   TREE_USED (label) = true;
     329       126638 :   add_stmt (location, build1 (GOTO_EXPR, void_type_node, label));
     330       126638 : }
     331              : 
     332              : /* DeclareLabel create a label, name.  */
     333              : 
     334              : void
     335       106576 : m2statement_DeclareLabel (location_t location, char *name)
     336              : {
     337       106576 :   tree label = m2block_getLabel (location, name);
     338              : 
     339       106576 :   m2assert_AssertLocation (location);
     340       106576 :   add_stmt (location, build1 (LABEL_EXPR, void_type_node, label));
     341       106576 : }
     342              : 
     343              : /* BuildParam build a list of parameters, ready for a subsequent
     344              :    procedure call.  */
     345              : 
     346              : void
     347       628610 : m2statement_BuildParam (location_t location, tree param)
     348              : {
     349       628610 :   m2assert_AssertLocation (location);
     350              : 
     351       628610 :   TREE_USED (param) = true;
     352       628610 :   if (TREE_CODE (param) == FUNCTION_DECL)
     353        45882 :     param = m2expr_BuildAddr (location, param, false);
     354              : 
     355       628610 :   param_list = chainon (build_tree_list (NULL_TREE, param), param_list);
     356       628610 : }
     357              : 
     358              : /* nCount return the number of chained tree nodes in list, t.  */
     359              : 
     360              : static int
     361       237982 : nCount (tree t)
     362              : {
     363       237982 :   int i = 0;
     364              : 
     365       864938 :   while (t != NULL)
     366              :     {
     367       626956 :       i++;
     368       626956 :       t = TREE_CHAIN (t);
     369              :     }
     370       237982 :   return i;
     371              : }
     372              : 
     373              : /* BuildProcedureCallTree creates a procedure call from a procedure
     374              :    and parameter list and the return type, rettype.  */
     375              : 
     376              : tree
     377       237258 : m2statement_BuildProcedureCallTree (location_t location, tree procedure,
     378              :                                     tree rettype)
     379              : {
     380       237258 :   tree functype = TREE_TYPE (procedure);
     381       237258 :   tree funcptr = build1 (ADDR_EXPR, build_pointer_type (functype), procedure);
     382       237258 :   tree call;
     383       237258 :   int n = nCount (param_list);
     384       237258 :   tree *argarray = XALLOCAVEC (tree, n);
     385       237258 :   tree t = param_list;
     386       237258 :   int i;
     387              : 
     388       237258 :   m2assert_AssertLocation (location);
     389       237258 :   ASSERT_CONDITION (
     390              :       last_function
     391       237258 :       == NULL_TREE); /* Previous function value has not been collected.  */
     392       237258 :   TREE_USED (procedure) = true;
     393              : 
     394       863048 :   for (i = 0; i < n; i++)
     395              :     {
     396       625790 :       argarray[i] = TREE_VALUE (t);
     397       625790 :       t = TREE_CHAIN (t);
     398              :     }
     399              : 
     400       237258 :   if (rettype == NULL_TREE)
     401              :     {
     402       162877 :       rettype = void_type_node;
     403       162877 :       call = build_call_array_loc (location, rettype, funcptr, n, argarray);
     404       162877 :       TREE_USED (call) = true;
     405       162877 :       TREE_SIDE_EFFECTS (call) = true;
     406              : 
     407              : #if defined(DEBUG_PROCEDURE_CALLS)
     408              :       fprintf (stderr, "built the modula-2 call, here is the tree\n");
     409              :       fflush (stderr);
     410              :       debug_tree (call);
     411              : #endif
     412              : 
     413       162877 :       param_list
     414       162877 :           = NULL_TREE; /* Ready for the next time we call a procedure.  */
     415       162877 :       last_function = NULL_TREE;
     416       162877 :       return call;
     417              :     }
     418              :   else
     419              :     {
     420        74381 :       last_function = build_call_array_loc (
     421              :           location, m2tree_skip_type_decl (rettype), funcptr, n, argarray);
     422        74381 :       TREE_USED (last_function) = true;
     423        74381 :       TREE_SIDE_EFFECTS (last_function) = true;
     424        74381 :       param_list
     425        74381 :           = NULL_TREE; /* Ready for the next time we call a procedure.  */
     426        74381 :       return last_function;
     427              :     }
     428              : }
     429              : 
     430              : /* BuildIndirectProcedureCallTree creates a procedure call from a
     431              :    procedure and parameter list and the return type, rettype.  */
     432              : 
     433              : tree
     434          724 : m2statement_BuildIndirectProcedureCallTree (location_t location,
     435              :                                             tree procedure, tree rettype)
     436              : {
     437          724 :   tree call;
     438          724 :   int n = nCount (param_list);
     439          724 :   tree *argarray = XALLOCAVEC (tree, n);
     440          724 :   tree t = param_list;
     441          724 :   int i;
     442              : 
     443          724 :   m2assert_AssertLocation (location);
     444          724 :   TREE_USED (procedure) = true;
     445          724 :   TREE_SIDE_EFFECTS (procedure) = true;
     446              : 
     447         1890 :   for (i = 0; i < n; i++)
     448              :     {
     449         1166 :       argarray[i] = TREE_VALUE (t);
     450         1166 :       t = TREE_CHAIN (t);
     451              :     }
     452              : 
     453          724 :   if (rettype == NULL_TREE)
     454              :     {
     455          636 :       rettype = void_type_node;
     456          636 :       call = build_call_array_loc (location, rettype, procedure, n, argarray);
     457          636 :       TREE_USED (call) = true;
     458          636 :       TREE_SIDE_EFFECTS (call) = true;
     459              : 
     460              : #if defined(DEBUG_PROCEDURE_CALLS)
     461              :       fprintf (stderr, "built the modula-2 call, here is the tree\n");
     462              :       fflush (stderr);
     463              :       debug_tree (call);
     464              : #endif
     465              : 
     466          636 :       last_function = NULL_TREE;
     467          636 :       param_list
     468          636 :           = NULL_TREE; /* Ready for the next time we call a procedure.  */
     469          636 :       return call;
     470              :     }
     471              :   else
     472              :     {
     473           88 :       last_function = build_call_array_loc (
     474              :           location, m2tree_skip_type_decl (rettype), procedure, n, argarray);
     475           88 :       TREE_USED (last_function) = true;
     476           88 :       TREE_SIDE_EFFECTS (last_function) = true;
     477           88 :       param_list
     478           88 :           = NULL_TREE; /* Ready for the next time we call a procedure.  */
     479           88 :       return last_function;
     480              :     }
     481              : }
     482              : 
     483              : 
     484              : /* BuildBuiltinCallTree calls the builtin procedure.  */
     485              : 
     486              : tree
     487         1146 : m2statement_BuildBuiltinCallTree (tree func)
     488              : {
     489         1146 :   TREE_USED (func) = true;
     490         1146 :   TREE_SIDE_EFFECTS (func) = true;
     491         1146 :   param_list
     492         1146 :     = NULL_TREE; /* Ready for the next time we call a procedure.  */
     493         1146 :   return func;
     494              : }
     495              : 
     496              : 
     497              : /* BuildFunctValue generates code for
     498              :    value := last_function (foobar).  */
     499              : 
     500              : tree
     501        86693 : m2statement_BuildFunctValue (location_t location, tree value)
     502              : {
     503        86693 :   tree assign
     504        86693 :       = m2treelib_build_modify_expr (location, value, NOP_EXPR, last_function);
     505              : 
     506        86693 :   m2assert_AssertLocation (location);
     507        86693 :   ASSERT_CONDITION (
     508              :       last_function
     509        86693 :       != NULL_TREE);  /* No value available, possible used before.  */
     510              : 
     511        86693 :   TREE_SIDE_EFFECTS (assign) = true;
     512        86693 :   TREE_USED (assign) = true;
     513        86693 :   TREE_USED (value) = true;
     514        86693 :   last_function = NULL_TREE;
     515        86693 :   return assign;
     516              : }
     517              : 
     518              : /* BuildCall2 builds a tree representing: function (arg1, arg2).  */
     519              : 
     520              : tree
     521            0 : m2statement_BuildCall2 (location_t location, tree function, tree rettype,
     522              :                         tree arg1, tree arg2)
     523              : {
     524            0 :   m2assert_AssertLocation (location);
     525            0 :   ASSERT_CONDITION (param_list == NULL_TREE);
     526              : 
     527            0 :   param_list = chainon (build_tree_list (NULL_TREE, arg2), param_list);
     528            0 :   param_list = chainon (build_tree_list (NULL_TREE, arg1), param_list);
     529            0 :   return m2statement_BuildProcedureCallTree (location, function, rettype);
     530              : }
     531              : 
     532              : /* BuildCall3 builds a tree representing: function (arg1, arg2, arg3).  */
     533              : 
     534              : tree
     535            0 : m2statement_BuildCall3 (location_t location, tree function, tree rettype,
     536              :                         tree arg1, tree arg2, tree arg3)
     537              : {
     538            0 :   m2assert_AssertLocation (location);
     539            0 :   ASSERT_CONDITION (param_list == NULL_TREE);
     540              : 
     541            0 :   param_list = chainon (build_tree_list (NULL_TREE, arg3), param_list);
     542            0 :   param_list = chainon (build_tree_list (NULL_TREE, arg2), param_list);
     543            0 :   param_list = chainon (build_tree_list (NULL_TREE, arg1), param_list);
     544            0 :   return m2statement_BuildProcedureCallTree (location, function, rettype);
     545              : }
     546              : 
     547              : /* BuildFunctionCallTree creates a procedure function call from
     548              :    a procedure and parameter list and the return type, rettype.
     549              :    No tree is returned as the tree is held in the last_function global
     550              :    variable.  It is expected the BuildFunctValue is to be called after
     551              :    a call to BuildFunctionCallTree.  */
     552              : 
     553              : void
     554         5840 : m2statement_BuildFunctionCallTree (location_t location, tree procedure,
     555              :                                    tree rettype)
     556              : {
     557         5840 :   m2statement_BuildProcedureCallTree (location, procedure, rettype);
     558         5840 : }
     559              : 
     560              : /* SetLastFunction assigns last_function to, t.  */
     561              : 
     562              : void
     563       229545 : m2statement_SetLastFunction (tree t)
     564              : {
     565       229545 :   last_function = t;
     566       229545 : }
     567              : 
     568              : /* SetParamList assigns param_list to, t.  */
     569              : 
     570              : void
     571         1152 : m2statement_SetParamList (tree t)
     572              : {
     573         1152 :   param_list = t;
     574         1152 : }
     575              : 
     576              : /* GetLastFunction returns, last_function.  */
     577              : 
     578              : tree
     579            0 : m2statement_GetLastFunction (void)
     580              : {
     581            0 :   return last_function;
     582              : }
     583              : 
     584              : /* GetParamList returns, param_list.  */
     585              : 
     586              : tree
     587         1152 : m2statement_GetParamList (void)
     588              : {
     589         1152 :   return param_list;
     590              : }
     591              : 
     592              : /* GetCurrentFunction returns the current_function.  */
     593              : 
     594              : tree
     595            0 : m2statement_GetCurrentFunction (void)
     596              : {
     597            0 :   return current_function_decl;
     598              : }
     599              : 
     600              : /* GetParamTree return parameter, i.  */
     601              : 
     602              : tree
     603            0 : m2statement_GetParamTree (tree call, unsigned int i)
     604              : {
     605            0 :   return CALL_EXPR_ARG (call, i);
     606              : }
     607              : 
     608              : /* BuildTryFinally returns a TRY_FINALL_EXPR with the call and
     609              :    cleanups attached.  */
     610              : 
     611              : tree
     612            0 : m2statement_BuildTryFinally (location_t location, tree call, tree cleanups)
     613              : {
     614            0 :   return build_stmt (location, TRY_FINALLY_EXPR, call, cleanups);
     615              : }
     616              : 
     617              : /* BuildCleanUp return a CLEANUP_POINT_EXPR which will clobber,
     618              :    param.  */
     619              : 
     620              : tree
     621            0 : m2statement_BuildCleanUp (tree param)
     622              : {
     623            0 :   tree clobber = build_constructor (TREE_TYPE (param), NULL);
     624            0 :   TREE_THIS_VOLATILE (clobber) = 1;
     625            0 :   return build2 (MODIFY_EXPR, TREE_TYPE (param), param, clobber);
     626              : }
     627              : 
     628              : /* BuildAsm generates an inline assembler instruction.  */
     629              : 
     630              : void
     631           27 : m2statement_BuildAsm (location_t location, tree instr, bool isVolatile,
     632              :                       bool isSimple, tree inputs, tree outputs, tree trash,
     633              :                       tree labels)
     634              : {
     635           27 :   tree string = resolve_asm_operand_names (instr, outputs, inputs, labels);
     636           27 :   tree args = build_stmt (location, ASM_EXPR, string, outputs, inputs, trash,
     637              :                           labels);
     638              : 
     639           27 :   m2assert_AssertLocation (location);
     640              : 
     641              :   /* ASM statements without outputs, including simple ones, are treated
     642              :      as volatile.  */
     643           27 :   ASM_BASIC_P (args) = isSimple;
     644           27 :   ASM_VOLATILE_P (args) = isVolatile;
     645              : 
     646           27 :   add_stmt (location, args);
     647           27 : }
     648              : 
     649              : /* BuildStart creates a module initialization function.  We make
     650              :    this function public if it is not an inner module.  The linker
     651              :    will create a call list for all linked modules which determines
     652              :    the initialization sequence for all modules.  */
     653              : 
     654              : tree
     655            0 : m2statement_BuildStart (location_t location, char *name, bool inner_module)
     656              : {
     657            0 :   tree fntype;
     658            0 :   tree fndecl;
     659              : 
     660            0 :   m2assert_AssertLocation (location);
     661              :   /* The function type depends on the return type and type of args.  */
     662            0 :   fntype = build_function_type (integer_type_node, NULL_TREE);
     663            0 :   fndecl = build_decl (location, FUNCTION_DECL, get_identifier (name), fntype);
     664              : 
     665            0 :   DECL_EXTERNAL (fndecl) = 0;
     666            0 :   if (inner_module)
     667            0 :     TREE_PUBLIC (fndecl) = 0;
     668              :   else
     669            0 :     TREE_PUBLIC (fndecl) = 1;
     670              : 
     671            0 :   TREE_STATIC (fndecl) = 1;
     672            0 :   DECL_RESULT (fndecl)
     673            0 :       = build_decl (location, RESULT_DECL, NULL_TREE, integer_type_node);
     674            0 :   DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
     675              : 
     676              :   /* Prevent the optimizer from removing it if it is public.  */
     677            0 :   if (TREE_PUBLIC (fndecl))
     678            0 :     gm2_mark_addressable (fndecl);
     679              : 
     680            0 :   m2statement_BuildStartFunctionCode (location, fndecl, !inner_module,
     681              :                                       inner_module);
     682            0 :   return fndecl;
     683              : }
     684              : 
     685              : /* BuildEnd complete the initialization function for this module.  */
     686              : 
     687              : void
     688            0 : m2statement_BuildEnd (location_t location, tree fndecl, bool nested)
     689              : {
     690            0 :   m2statement_BuildEndFunctionCode (location, fndecl, nested);
     691            0 :   current_function_decl = NULL;
     692            0 :   set_cfun (NULL);
     693            0 : }
     694              : 
     695              : /* BuildCallInner call the inner module function.  It has no
     696              :    parameters and no return value.  */
     697              : 
     698              : void
     699          672 : m2statement_BuildCallInner (location_t location, tree fndecl)
     700              : {
     701          672 :   m2assert_AssertLocation (location);
     702          672 :   param_list = NULL_TREE;
     703          672 :   add_stmt (location,
     704              :             m2statement_BuildProcedureCallTree (location, fndecl, NULL_TREE));
     705          672 : }
     706              : 
     707              : 
     708              : /* BuildIfThenDoEnd returns a tree which will only execute
     709              :    statement, s, if, condition, is true.  */
     710              : 
     711              : tree
     712       121006 : m2statement_BuildIfThenDoEnd (tree condition, tree then_block)
     713              : {
     714       121006 :   if (then_block == NULL_TREE)
     715              :     return NULL_TREE;
     716              :   else
     717        17043 :     return fold_build3 (COND_EXPR, void_type_node, condition, then_block,
     718              :                         alloc_stmt_list ());
     719              : }
     720              : 
     721              : /* BuildIfThenElseEnd returns a tree which will execute then_block
     722              :    or else_block depending upon, condition.  */
     723              : 
     724              : tree
     725         6972 : m2statement_BuildIfThenElseEnd (tree condition, tree then_block,
     726              :                                 tree else_block)
     727              : {
     728         6972 :   if (then_block == NULL_TREE)
     729              :     return NULL_TREE;
     730              :   else
     731         1188 :     return fold_build3 (COND_EXPR, void_type_node, condition, then_block,
     732              :                         else_block);
     733              : }
     734              : 
     735              : /* BuildReturnValueCode generates the code associated with:
     736              :    RETURN ( value ).  */
     737              : 
     738              : void
     739        27853 : m2statement_BuildReturnValueCode (location_t location, tree fndecl, tree value)
     740              : {
     741        27853 :   tree ret_stmt;
     742        27853 :   tree t;
     743              : 
     744        27853 :   m2assert_AssertLocation (location);
     745        83559 :   t = build2 (
     746        27853 :       MODIFY_EXPR, TREE_TYPE (DECL_RESULT (fndecl)), DECL_RESULT (fndecl),
     747              :       m2convert_BuildConvert (
     748        27853 :           location, m2tree_skip_type_decl (TREE_TYPE (DECL_RESULT (fndecl))),
     749              :           value, false));
     750              : 
     751        27853 :   ret_stmt = build_stmt (location, RETURN_EXPR, t);
     752        27853 :   add_stmt (location, ret_stmt);
     753        27853 : }
     754              : 
     755              : /* IfExprJump if expr then jump to the label.  */
     756              : 
     757              : void
     758        79899 : m2statement_IfExprJump (location_t location, tree exp, char *label)
     759              : {
     760        79899 :   tree if_jump;
     761              : 
     762        79899 :   m2assert_AssertLocation (location);
     763        79899 :   if (TREE_CODE (TREE_TYPE (exp)) != BOOLEAN_TYPE)
     764        79881 :     exp = convert_loc (location, m2type_GetBooleanType (), exp);
     765              : 
     766        79899 :   m2block_push_statement_list (m2block_begin_statement_list ());
     767        79899 :   m2statement_BuildGoto (location, label);
     768        79899 :   if_jump = build3 (COND_EXPR, void_type_node, exp,
     769              :                     m2block_pop_statement_list (),
     770              :                     alloc_stmt_list ());
     771        79899 :   add_stmt (location, if_jump);
     772        79899 : }
     773              : 
     774              : 
     775              : /* IfBitInSetJump if bit in set jump to label.  */
     776              : 
     777              : void
     778            0 : m2statement_IfBitInSetJump (location_t location, bool invertCondition,
     779              :                             tree setvalue, tree bit, char *label)
     780              : {
     781            0 :   tree condition;
     782              : 
     783            0 :   condition = m2expr_BuildNotEqualTo (location,
     784              :                                       m2expr_BuildLogicalAnd (location,
     785              :                                                               m2expr_BuildLSL (location,
     786              :                                                                                m2expr_GetWordOne (location),
     787              :                                                                                bit, false),
     788              :                                                               setvalue),
     789              :                                       m2expr_GetWordZero (location)) ;
     790            0 :   if (invertCondition)
     791            0 :     condition = m2expr_BuildEqualTo (location, condition,
     792              :                                      m2type_GetBooleanFalse ());
     793            0 :   m2statement_IfExprJump (location, condition, label);
     794            0 : }
     795              : 
     796              : #include "gt-m2-m2statement.h"
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.