Home | History | Annotate | Line # | Download | only in d
runtime.cc revision 1.1.1.1
      1  1.1  mrg /* runtime.cc -- D runtime functions called by generated code.
      2  1.1  mrg    Copyright (C) 2006-2019 Free Software Foundation, Inc.
      3  1.1  mrg 
      4  1.1  mrg GCC is free software; you can redistribute it and/or modify
      5  1.1  mrg it under the terms of the GNU General Public License as published by
      6  1.1  mrg the Free Software Foundation; either version 3, or (at your option)
      7  1.1  mrg any later version.
      8  1.1  mrg 
      9  1.1  mrg GCC is distributed in the hope that it will be useful,
     10  1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  1.1  mrg GNU General Public License for more details.
     13  1.1  mrg 
     14  1.1  mrg You should have received a copy of the GNU General Public License
     15  1.1  mrg along with GCC; see the file COPYING3.  If not see
     16  1.1  mrg <http://www.gnu.org/licenses/>.  */
     17  1.1  mrg 
     18  1.1  mrg #include "config.h"
     19  1.1  mrg #include "system.h"
     20  1.1  mrg #include "coretypes.h"
     21  1.1  mrg 
     22  1.1  mrg #include "dmd/aggregate.h"
     23  1.1  mrg #include "dmd/mtype.h"
     24  1.1  mrg 
     25  1.1  mrg #include "tree.h"
     26  1.1  mrg #include "fold-const.h"
     27  1.1  mrg #include "stringpool.h"
     28  1.1  mrg 
     29  1.1  mrg #include "d-tree.h"
     30  1.1  mrg 
     31  1.1  mrg 
     32  1.1  mrg /* During the codegen pass, the compiler may do lowering of expressions to call
     33  1.1  mrg    various runtime library functions.  Most are implemented in the `rt' package.
     34  1.1  mrg    We represent them in the frontend here, however there's no guarantee that
     35  1.1  mrg    the compiler implementation actually matches the actual implementation.  */
     36  1.1  mrg 
     37  1.1  mrg enum libcall_type
     38  1.1  mrg {
     39  1.1  mrg   LCT_VOID,		    /* void		    */
     40  1.1  mrg   LCT_BYTE,		    /* byte		    */
     41  1.1  mrg   LCT_INT,		    /* int		    */
     42  1.1  mrg   LCT_UINT,		    /* uint		    */
     43  1.1  mrg   LCT_BOOL,		    /* bool		    */
     44  1.1  mrg   LCT_DCHAR,		    /* dchar		    */
     45  1.1  mrg   LCT_VOIDPTR,		    /* void*		    */
     46  1.1  mrg   LCT_STRING,		    /* string		    */
     47  1.1  mrg   LCT_WSTRING,		    /* wstring		    */
     48  1.1  mrg   LCT_DSTRING,		    /* dstring		    */
     49  1.1  mrg   LCT_SIZE_T,		    /* size_t		    */
     50  1.1  mrg   LCT_ASSOCARRAY,	    /* void[void]	    */
     51  1.1  mrg   LCT_ARRAY_VOID,	    /* void[]		    */
     52  1.1  mrg   LCT_ARRAY_SIZE_T,	    /* size_t[]		    */
     53  1.1  mrg   LCT_ARRAY_BYTE,	    /* byte[]		    */
     54  1.1  mrg   LCT_ARRAY_STRING,	    /* string[]		    */
     55  1.1  mrg   LCT_ARRAY_WSTRING,	    /* wstring[]	    */
     56  1.1  mrg   LCT_ARRAY_DSTRING,	    /* dstring[]	    */
     57  1.1  mrg   LCT_ARRAYARRAY_BYTE,	    /* byte[][]		    */
     58  1.1  mrg   LCT_POINTER_ASSOCARRAY,   /* void[void]*	    */
     59  1.1  mrg   LCT_POINTER_VOIDPTR,	    /* void**		    */
     60  1.1  mrg   LCT_ARRAYPTR_VOID,	    /* void[]*		    */
     61  1.1  mrg   LCT_ARRAYPTR_BYTE,	    /* byte[]*		    */
     62  1.1  mrg   LCT_TYPEINFO,		    /* TypeInfo		    */
     63  1.1  mrg   LCT_CLASSINFO,	    /* TypeInfo_Class	    */
     64  1.1  mrg   LCT_OBJECT,		    /* Object		    */
     65  1.1  mrg   LCT_CONST_TYPEINFO,	    /* const(TypeInfo)	    */
     66  1.1  mrg   LCT_CONST_CLASSINFO,	    /* const(ClassInfo)	    */
     67  1.1  mrg   LCT_END
     68  1.1  mrg };
     69  1.1  mrg 
     70  1.1  mrg /* An array of all types that are used by the runtime functions we need.  */
     71  1.1  mrg 
     72  1.1  mrg static Type *libcall_types[LCT_END];
     73  1.1  mrg 
     74  1.1  mrg /* Our internal list of library functions.  */
     75  1.1  mrg 
     76  1.1  mrg static tree libcall_decls[LIBCALL_LAST];
     77  1.1  mrg 
     78  1.1  mrg 
     79  1.1  mrg /* Return the frontend Type that is described by TYPE.  Most are readily cached
     80  1.1  mrg    by the frontend proper, and likewise the use of pointerTo(), constOf(), and
     81  1.1  mrg    arrayOf() will return cached types if they have been requested before.  */
     82  1.1  mrg 
     83  1.1  mrg static Type *
     84  1.1  mrg get_libcall_type (libcall_type type)
     85  1.1  mrg {
     86  1.1  mrg   if (libcall_types[type])
     87  1.1  mrg     return libcall_types[type];
     88  1.1  mrg 
     89  1.1  mrg   switch (type)
     90  1.1  mrg     {
     91  1.1  mrg     case LCT_VOID:
     92  1.1  mrg       libcall_types[type] = Type::tvoid;
     93  1.1  mrg       break;
     94  1.1  mrg 
     95  1.1  mrg     case LCT_BYTE:
     96  1.1  mrg       libcall_types[type] = Type::tint8;
     97  1.1  mrg       break;
     98  1.1  mrg 
     99  1.1  mrg     case LCT_INT:
    100  1.1  mrg       libcall_types[type] = Type::tint32;
    101  1.1  mrg       break;
    102  1.1  mrg 
    103  1.1  mrg     case LCT_UINT:
    104  1.1  mrg       libcall_types[type] = Type::tuns32;
    105  1.1  mrg       break;
    106  1.1  mrg 
    107  1.1  mrg     case LCT_BOOL:
    108  1.1  mrg       libcall_types[type] = Type::tbool;
    109  1.1  mrg       break;
    110  1.1  mrg 
    111  1.1  mrg     case LCT_DCHAR:
    112  1.1  mrg       libcall_types[type] = Type::tdchar;
    113  1.1  mrg       break;
    114  1.1  mrg 
    115  1.1  mrg     case LCT_VOIDPTR:
    116  1.1  mrg       libcall_types[type] = Type::tvoidptr;
    117  1.1  mrg       break;
    118  1.1  mrg 
    119  1.1  mrg     case LCT_STRING:
    120  1.1  mrg       libcall_types[type] = Type::tstring;
    121  1.1  mrg       break;
    122  1.1  mrg 
    123  1.1  mrg     case LCT_WSTRING:
    124  1.1  mrg       libcall_types[type] = Type::twstring;
    125  1.1  mrg       break;
    126  1.1  mrg 
    127  1.1  mrg     case LCT_DSTRING:
    128  1.1  mrg       libcall_types[type] = Type::tdstring;
    129  1.1  mrg       break;
    130  1.1  mrg 
    131  1.1  mrg     case LCT_SIZE_T:
    132  1.1  mrg       libcall_types[type] = Type::tsize_t;
    133  1.1  mrg       break;
    134  1.1  mrg 
    135  1.1  mrg     case LCT_ASSOCARRAY:
    136  1.1  mrg       libcall_types[type] = TypeAArray::create (Type::tvoid, Type::tvoid);
    137  1.1  mrg       break;
    138  1.1  mrg 
    139  1.1  mrg     case LCT_TYPEINFO:
    140  1.1  mrg       libcall_types[type] = Type::dtypeinfo->type;
    141  1.1  mrg       break;
    142  1.1  mrg 
    143  1.1  mrg     case LCT_CLASSINFO:
    144  1.1  mrg       libcall_types[type] = Type::typeinfoclass->type;
    145  1.1  mrg       break;
    146  1.1  mrg 
    147  1.1  mrg     case LCT_OBJECT:
    148  1.1  mrg       libcall_types[type] = get_object_type ();
    149  1.1  mrg       break;
    150  1.1  mrg 
    151  1.1  mrg     case LCT_CONST_TYPEINFO:
    152  1.1  mrg       libcall_types[type] = Type::dtypeinfo->type->constOf ();
    153  1.1  mrg       break;
    154  1.1  mrg 
    155  1.1  mrg     case LCT_CONST_CLASSINFO:
    156  1.1  mrg       libcall_types[type] = Type::typeinfoclass->type->constOf ();
    157  1.1  mrg       break;
    158  1.1  mrg 
    159  1.1  mrg     case LCT_ARRAY_VOID:
    160  1.1  mrg       libcall_types[type] = Type::tvoid->arrayOf ();
    161  1.1  mrg       break;
    162  1.1  mrg 
    163  1.1  mrg     case LCT_ARRAY_SIZE_T:
    164  1.1  mrg       libcall_types[type] = Type::tsize_t->arrayOf ();
    165  1.1  mrg       break;
    166  1.1  mrg 
    167  1.1  mrg     case LCT_ARRAY_BYTE:
    168  1.1  mrg       libcall_types[type] = Type::tint8->arrayOf ();
    169  1.1  mrg       break;
    170  1.1  mrg 
    171  1.1  mrg     case LCT_ARRAY_STRING:
    172  1.1  mrg       libcall_types[type] = Type::tstring->arrayOf ();
    173  1.1  mrg       break;
    174  1.1  mrg 
    175  1.1  mrg     case LCT_ARRAY_WSTRING:
    176  1.1  mrg       libcall_types[type] = Type::twstring->arrayOf ();
    177  1.1  mrg       break;
    178  1.1  mrg 
    179  1.1  mrg     case LCT_ARRAY_DSTRING:
    180  1.1  mrg       libcall_types[type] = Type::tdstring->arrayOf ();
    181  1.1  mrg       break;
    182  1.1  mrg 
    183  1.1  mrg     case LCT_ARRAYARRAY_BYTE:
    184  1.1  mrg       libcall_types[type] = Type::tint8->arrayOf ()->arrayOf ();
    185  1.1  mrg       break;
    186  1.1  mrg 
    187  1.1  mrg     case LCT_POINTER_ASSOCARRAY:
    188  1.1  mrg       libcall_types[type] = get_libcall_type (LCT_ASSOCARRAY)->pointerTo ();
    189  1.1  mrg       break;
    190  1.1  mrg 
    191  1.1  mrg     case LCT_POINTER_VOIDPTR:
    192  1.1  mrg       libcall_types[type] = Type::tvoidptr->arrayOf ();
    193  1.1  mrg       break;
    194  1.1  mrg 
    195  1.1  mrg     case LCT_ARRAYPTR_VOID:
    196  1.1  mrg       libcall_types[type] = Type::tvoid->arrayOf ()->pointerTo ();
    197  1.1  mrg       break;
    198  1.1  mrg 
    199  1.1  mrg     case LCT_ARRAYPTR_BYTE:
    200  1.1  mrg       libcall_types[type] = Type::tint8->arrayOf ()->pointerTo ();
    201  1.1  mrg       break;
    202  1.1  mrg 
    203  1.1  mrg     default:
    204  1.1  mrg       gcc_unreachable ();
    205  1.1  mrg     }
    206  1.1  mrg 
    207  1.1  mrg   return libcall_types[type];
    208  1.1  mrg }
    209  1.1  mrg 
    210  1.1  mrg /* Builds and returns function declaration named NAME.  The RETURN_TYPE is
    211  1.1  mrg    the type returned, FLAGS are the expression call flags, and NPARAMS is
    212  1.1  mrg    the number of arguments, the types of which are provided in `...'.  */
    213  1.1  mrg 
    214  1.1  mrg static tree
    215  1.1  mrg build_libcall_decl (const char *name, libcall_type return_type,
    216  1.1  mrg 		    int flags, int nparams, ...)
    217  1.1  mrg {
    218  1.1  mrg   tree *args = XALLOCAVEC (tree, nparams);
    219  1.1  mrg   bool varargs = false;
    220  1.1  mrg   tree fntype;
    221  1.1  mrg 
    222  1.1  mrg   /* Add parameter types, using 'void' as the last parameter type
    223  1.1  mrg      to mean this function accepts a variable list of arguments.  */
    224  1.1  mrg   va_list ap;
    225  1.1  mrg   va_start (ap, nparams);
    226  1.1  mrg 
    227  1.1  mrg   for (int i = 0; i < nparams; i++)
    228  1.1  mrg     {
    229  1.1  mrg       libcall_type ptype = (libcall_type) va_arg (ap, int);
    230  1.1  mrg       Type *type = get_libcall_type (ptype);
    231  1.1  mrg 
    232  1.1  mrg       if (type == Type::tvoid)
    233  1.1  mrg 	{
    234  1.1  mrg 	  varargs = true;
    235  1.1  mrg 	  nparams = i;
    236  1.1  mrg 	}
    237  1.1  mrg       else
    238  1.1  mrg 	args[i] = build_ctype (type);
    239  1.1  mrg     }
    240  1.1  mrg 
    241  1.1  mrg   va_end (ap);
    242  1.1  mrg 
    243  1.1  mrg   /* Build the function.  */
    244  1.1  mrg   tree tret = build_ctype (get_libcall_type (return_type));
    245  1.1  mrg   if (varargs)
    246  1.1  mrg     fntype = build_varargs_function_type_array (tret, nparams, args);
    247  1.1  mrg   else
    248  1.1  mrg     fntype = build_function_type_array (tret, nparams, args);
    249  1.1  mrg 
    250  1.1  mrg   tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
    251  1.1  mrg 			  get_identifier (name), fntype);
    252  1.1  mrg   DECL_EXTERNAL (decl) = 1;
    253  1.1  mrg   TREE_PUBLIC (decl) = 1;
    254  1.1  mrg   DECL_ARTIFICIAL (decl) = 1;
    255  1.1  mrg   DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
    256  1.1  mrg   DECL_VISIBILITY_SPECIFIED (decl) = 1;
    257  1.1  mrg 
    258  1.1  mrg   /* Set any attributes on the function, such as malloc or noreturn.  */
    259  1.1  mrg   set_call_expr_flags (decl, flags);
    260  1.1  mrg 
    261  1.1  mrg   return decl;
    262  1.1  mrg }
    263  1.1  mrg 
    264  1.1  mrg /* Return or create the runtime library function declaration for LIBCALL.
    265  1.1  mrg    Library functions are generated as needed.  This could probably be changed in
    266  1.1  mrg    the future to be done in the compiler init stage, like GCC builtin trees are,
    267  1.1  mrg    however we depend on run-time initialization of types whose definitions are
    268  1.1  mrg    in the library such as `Object' or `TypeInfo'.  */
    269  1.1  mrg 
    270  1.1  mrg static tree
    271  1.1  mrg get_libcall (libcall_fn libcall)
    272  1.1  mrg {
    273  1.1  mrg   if (libcall_decls[libcall])
    274  1.1  mrg     return libcall_decls[libcall];
    275  1.1  mrg 
    276  1.1  mrg   switch (libcall)
    277  1.1  mrg     {
    278  1.1  mrg #define DEF_D_RUNTIME(CODE, NAME, TYPE, PARAMS, FLAGS) \
    279  1.1  mrg     case LIBCALL_ ## CODE:	\
    280  1.1  mrg       libcall_decls[libcall] = build_libcall_decl (NAME, TYPE, FLAGS, PARAMS); \
    281  1.1  mrg       break;
    282  1.1  mrg 
    283  1.1  mrg #include "runtime.def"
    284  1.1  mrg 
    285  1.1  mrg #undef DEF_D_RUNTIME
    286  1.1  mrg 
    287  1.1  mrg     default:
    288  1.1  mrg       gcc_unreachable ();
    289  1.1  mrg     }
    290  1.1  mrg 
    291  1.1  mrg   return libcall_decls[libcall];
    292  1.1  mrg }
    293  1.1  mrg 
    294  1.1  mrg /* Generate a call to LIBCALL, returning the result as TYPE.  NARGS is the
    295  1.1  mrg    number of call arguments, the expressions of which are provided in `...'.
    296  1.1  mrg    This does not perform conversions or promotions on the arguments.  */
    297  1.1  mrg 
    298  1.1  mrg tree
    299  1.1  mrg build_libcall (libcall_fn libcall, Type *type, int nargs, ...)
    300  1.1  mrg {
    301  1.1  mrg   /* Build the call expression to the runtime function.  */
    302  1.1  mrg   tree decl = get_libcall (libcall);
    303  1.1  mrg   tree *args = XALLOCAVEC (tree, nargs);
    304  1.1  mrg   va_list ap;
    305  1.1  mrg 
    306  1.1  mrg   va_start (ap, nargs);
    307  1.1  mrg   for (int i = 0; i < nargs; i++)
    308  1.1  mrg     args[i] = va_arg (ap, tree);
    309  1.1  mrg   va_end (ap);
    310  1.1  mrg 
    311  1.1  mrg   tree result = build_call_expr_loc_array (input_location, decl, nargs, args);
    312  1.1  mrg 
    313  1.1  mrg   /* Assumes caller knows what it is doing.  */
    314  1.1  mrg   return convert (build_ctype (type), result);
    315  1.1  mrg }
    316