Home | History | Annotate | Line # | Download | only in d
d-codegen.cc revision 1.1
      1  1.1  mrg /* d-codegen.cc --  Code generation and routines for manipulation of GCC trees.
      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/ctfe.h"
     24  1.1  mrg #include "dmd/declaration.h"
     25  1.1  mrg #include "dmd/identifier.h"
     26  1.1  mrg #include "dmd/target.h"
     27  1.1  mrg #include "dmd/template.h"
     28  1.1  mrg 
     29  1.1  mrg #include "tree.h"
     30  1.1  mrg #include "tree-iterator.h"
     31  1.1  mrg #include "fold-const.h"
     32  1.1  mrg #include "diagnostic.h"
     33  1.1  mrg #include "langhooks.h"
     34  1.1  mrg #include "target.h"
     35  1.1  mrg #include "stringpool.h"
     36  1.1  mrg #include "varasm.h"
     37  1.1  mrg #include "stor-layout.h"
     38  1.1  mrg #include "attribs.h"
     39  1.1  mrg #include "function.h"
     40  1.1  mrg 
     41  1.1  mrg #include "d-tree.h"
     42  1.1  mrg 
     43  1.1  mrg 
     44  1.1  mrg /* Return the GCC location for the D frontend location LOC.  */
     45  1.1  mrg 
     46  1.1  mrg location_t
     47  1.1  mrg make_location_t (const Loc& loc)
     48  1.1  mrg {
     49  1.1  mrg   location_t gcc_location = input_location;
     50  1.1  mrg 
     51  1.1  mrg   if (loc.filename)
     52  1.1  mrg     {
     53  1.1  mrg       linemap_add (line_table, LC_ENTER, 0, loc.filename, loc.linnum);
     54  1.1  mrg       linemap_line_start (line_table, loc.linnum, 0);
     55  1.1  mrg       gcc_location = linemap_position_for_column (line_table, loc.charnum);
     56  1.1  mrg       linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
     57  1.1  mrg     }
     58  1.1  mrg 
     59  1.1  mrg   return gcc_location;
     60  1.1  mrg }
     61  1.1  mrg 
     62  1.1  mrg /* Return the DECL_CONTEXT for symbol DSYM.  */
     63  1.1  mrg 
     64  1.1  mrg tree
     65  1.1  mrg d_decl_context (Dsymbol *dsym)
     66  1.1  mrg {
     67  1.1  mrg   Dsymbol *parent = dsym;
     68  1.1  mrg   Declaration *decl = dsym->isDeclaration ();
     69  1.1  mrg 
     70  1.1  mrg   while ((parent = parent->toParent2 ()))
     71  1.1  mrg     {
     72  1.1  mrg       /* We've reached the top-level module namespace.
     73  1.1  mrg 	 Set DECL_CONTEXT as the NAMESPACE_DECL of the enclosing module,
     74  1.1  mrg 	 but only for extern(D) symbols.  */
     75  1.1  mrg       if (parent->isModule ())
     76  1.1  mrg 	{
     77  1.1  mrg 	  if (decl != NULL && decl->linkage != LINKd)
     78  1.1  mrg 	    return NULL_TREE;
     79  1.1  mrg 
     80  1.1  mrg 	  return build_import_decl (parent);
     81  1.1  mrg 	}
     82  1.1  mrg 
     83  1.1  mrg       /* Declarations marked as 'static' or '__gshared' are never
     84  1.1  mrg 	 part of any context except at module level.  */
     85  1.1  mrg       if (decl != NULL && decl->isDataseg ())
     86  1.1  mrg 	continue;
     87  1.1  mrg 
     88  1.1  mrg       /* Nested functions.  */
     89  1.1  mrg       FuncDeclaration *fd = parent->isFuncDeclaration ();
     90  1.1  mrg       if (fd != NULL)
     91  1.1  mrg 	return get_symbol_decl (fd);
     92  1.1  mrg 
     93  1.1  mrg       /* Methods of classes or structs.  */
     94  1.1  mrg       AggregateDeclaration *ad = parent->isAggregateDeclaration ();
     95  1.1  mrg       if (ad != NULL)
     96  1.1  mrg 	{
     97  1.1  mrg 	  tree context = build_ctype (ad->type);
     98  1.1  mrg 	  /* Want the underlying RECORD_TYPE.  */
     99  1.1  mrg 	  if (ad->isClassDeclaration ())
    100  1.1  mrg 	    context = TREE_TYPE (context);
    101  1.1  mrg 
    102  1.1  mrg 	  return context;
    103  1.1  mrg 	}
    104  1.1  mrg     }
    105  1.1  mrg 
    106  1.1  mrg   return NULL_TREE;
    107  1.1  mrg }
    108  1.1  mrg 
    109  1.1  mrg /* Return a copy of record TYPE but safe to modify in any way.  */
    110  1.1  mrg 
    111  1.1  mrg tree
    112  1.1  mrg copy_aggregate_type (tree type)
    113  1.1  mrg {
    114  1.1  mrg   tree newtype = build_distinct_type_copy (type);
    115  1.1  mrg   TYPE_FIELDS (newtype) = copy_list (TYPE_FIELDS (type));
    116  1.1  mrg 
    117  1.1  mrg   for (tree f = TYPE_FIELDS (newtype); f; f = DECL_CHAIN (f))
    118  1.1  mrg     DECL_FIELD_CONTEXT (f) = newtype;
    119  1.1  mrg 
    120  1.1  mrg   return newtype;
    121  1.1  mrg }
    122  1.1  mrg 
    123  1.1  mrg /* Return TRUE if declaration DECL is a reference type.  */
    124  1.1  mrg 
    125  1.1  mrg bool
    126  1.1  mrg declaration_reference_p (Declaration *decl)
    127  1.1  mrg {
    128  1.1  mrg   Type *tb = decl->type->toBasetype ();
    129  1.1  mrg 
    130  1.1  mrg   /* Declaration is a reference type.  */
    131  1.1  mrg   if (tb->ty == Treference || decl->storage_class & (STCout | STCref))
    132  1.1  mrg     return true;
    133  1.1  mrg 
    134  1.1  mrg   return false;
    135  1.1  mrg }
    136  1.1  mrg 
    137  1.1  mrg /* Returns the real type for declaration DECL.  */
    138  1.1  mrg 
    139  1.1  mrg tree
    140  1.1  mrg declaration_type (Declaration *decl)
    141  1.1  mrg {
    142  1.1  mrg   /* Lazy declarations are converted to delegates.  */
    143  1.1  mrg   if (decl->storage_class & STClazy)
    144  1.1  mrg     {
    145  1.1  mrg       TypeFunction *tf = TypeFunction::create (NULL, decl->type, false, LINKd);
    146  1.1  mrg       TypeDelegate *t = TypeDelegate::create (tf);
    147  1.1  mrg       return build_ctype (t->merge2 ());
    148  1.1  mrg     }
    149  1.1  mrg 
    150  1.1  mrg   /* Static array va_list have array->pointer conversions applied.  */
    151  1.1  mrg   if (decl->isParameter () && valist_array_p (decl->type))
    152  1.1  mrg     {
    153  1.1  mrg       Type *valist = decl->type->nextOf ()->pointerTo ();
    154  1.1  mrg       valist = valist->castMod (decl->type->mod);
    155  1.1  mrg       return build_ctype (valist);
    156  1.1  mrg     }
    157  1.1  mrg 
    158  1.1  mrg   tree type = build_ctype (decl->type);
    159  1.1  mrg 
    160  1.1  mrg   /* Parameter is passed by reference.  */
    161  1.1  mrg   if (declaration_reference_p (decl))
    162  1.1  mrg     return build_reference_type (type);
    163  1.1  mrg 
    164  1.1  mrg   /* The 'this' parameter is always const.  */
    165  1.1  mrg   if (decl->isThisDeclaration ())
    166  1.1  mrg     return insert_type_modifiers (type, MODconst);
    167  1.1  mrg 
    168  1.1  mrg   return type;
    169  1.1  mrg }
    170  1.1  mrg 
    171  1.1  mrg /* These should match the Declaration versions above
    172  1.1  mrg    Return TRUE if parameter ARG is a reference type.  */
    173  1.1  mrg 
    174  1.1  mrg bool
    175  1.1  mrg argument_reference_p (Parameter *arg)
    176  1.1  mrg {
    177  1.1  mrg   Type *tb = arg->type->toBasetype ();
    178  1.1  mrg 
    179  1.1  mrg   /* Parameter is a reference type.  */
    180  1.1  mrg   if (tb->ty == Treference || arg->storageClass & (STCout | STCref))
    181  1.1  mrg     return true;
    182  1.1  mrg 
    183  1.1  mrg   tree type = build_ctype (arg->type);
    184  1.1  mrg   if (TREE_ADDRESSABLE (type))
    185  1.1  mrg     return true;
    186  1.1  mrg 
    187  1.1  mrg   return false;
    188  1.1  mrg }
    189  1.1  mrg 
    190  1.1  mrg /* Returns the real type for parameter ARG.  */
    191  1.1  mrg 
    192  1.1  mrg tree
    193  1.1  mrg type_passed_as (Parameter *arg)
    194  1.1  mrg {
    195  1.1  mrg   /* Lazy parameters are converted to delegates.  */
    196  1.1  mrg   if (arg->storageClass & STClazy)
    197  1.1  mrg     {
    198  1.1  mrg       TypeFunction *tf = TypeFunction::create (NULL, arg->type, false, LINKd);
    199  1.1  mrg       TypeDelegate *t = TypeDelegate::create (tf);
    200  1.1  mrg       return build_ctype (t->merge2 ());
    201  1.1  mrg     }
    202  1.1  mrg 
    203  1.1  mrg   /* Static array va_list have array->pointer conversions applied.  */
    204  1.1  mrg   if (valist_array_p (arg->type))
    205  1.1  mrg     {
    206  1.1  mrg       Type *valist = arg->type->nextOf ()->pointerTo ();
    207  1.1  mrg       valist = valist->castMod (arg->type->mod);
    208  1.1  mrg       return build_ctype (valist);
    209  1.1  mrg     }
    210  1.1  mrg 
    211  1.1  mrg   tree type = build_ctype (arg->type);
    212  1.1  mrg 
    213  1.1  mrg   /* Parameter is passed by reference.  */
    214  1.1  mrg   if (argument_reference_p (arg))
    215  1.1  mrg     return build_reference_type (type);
    216  1.1  mrg 
    217  1.1  mrg   return type;
    218  1.1  mrg }
    219  1.1  mrg 
    220  1.1  mrg /* Build INTEGER_CST of type TYPE with the value VALUE.  */
    221  1.1  mrg 
    222  1.1  mrg tree
    223  1.1  mrg build_integer_cst (dinteger_t value, tree type)
    224  1.1  mrg {
    225  1.1  mrg   /* The type is error_mark_node, we can't do anything.  */
    226  1.1  mrg   if (error_operand_p (type))
    227  1.1  mrg     return type;
    228  1.1  mrg 
    229  1.1  mrg   return build_int_cst_type (type, value);
    230  1.1  mrg }
    231  1.1  mrg 
    232  1.1  mrg /* Build REAL_CST of type TOTYPE with the value VALUE.  */
    233  1.1  mrg 
    234  1.1  mrg tree
    235  1.1  mrg build_float_cst (const real_t& value, Type *totype)
    236  1.1  mrg {
    237  1.1  mrg   real_t new_value;
    238  1.1  mrg   TypeBasic *tb = totype->isTypeBasic ();
    239  1.1  mrg 
    240  1.1  mrg   gcc_assert (tb != NULL);
    241  1.1  mrg 
    242  1.1  mrg   tree type_node = build_ctype (tb);
    243  1.1  mrg   real_convert (&new_value.rv (), TYPE_MODE (type_node), &value.rv ());
    244  1.1  mrg 
    245  1.1  mrg   return build_real (type_node, new_value.rv ());
    246  1.1  mrg }
    247  1.1  mrg 
    248  1.1  mrg /* Returns the .length component from the D dynamic array EXP.  */
    249  1.1  mrg 
    250  1.1  mrg tree
    251  1.1  mrg d_array_length (tree exp)
    252  1.1  mrg {
    253  1.1  mrg   if (error_operand_p (exp))
    254  1.1  mrg     return exp;
    255  1.1  mrg 
    256  1.1  mrg   gcc_assert (TYPE_DYNAMIC_ARRAY (TREE_TYPE (exp)));
    257  1.1  mrg 
    258  1.1  mrg   /* Get the back-end type for the array and pick out the array
    259  1.1  mrg      length field (assumed to be the first field).  */
    260  1.1  mrg   tree len_field = TYPE_FIELDS (TREE_TYPE (exp));
    261  1.1  mrg   return component_ref (exp, len_field);
    262  1.1  mrg }
    263  1.1  mrg 
    264  1.1  mrg /* Returns the .ptr component from the D dynamic array EXP.  */
    265  1.1  mrg 
    266  1.1  mrg tree
    267  1.1  mrg d_array_ptr (tree exp)
    268  1.1  mrg {
    269  1.1  mrg   if (error_operand_p (exp))
    270  1.1  mrg     return exp;
    271  1.1  mrg 
    272  1.1  mrg   gcc_assert (TYPE_DYNAMIC_ARRAY (TREE_TYPE (exp)));
    273  1.1  mrg 
    274  1.1  mrg   /* Get the back-end type for the array and pick out the array
    275  1.1  mrg      data pointer field (assumed to be the second field).  */
    276  1.1  mrg   tree ptr_field = TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (exp)));
    277  1.1  mrg   return component_ref (exp, ptr_field);
    278  1.1  mrg }
    279  1.1  mrg 
    280  1.1  mrg /* Returns a constructor for D dynamic array type TYPE of .length LEN
    281  1.1  mrg    and .ptr pointing to DATA.  */
    282  1.1  mrg 
    283  1.1  mrg tree
    284  1.1  mrg d_array_value (tree type, tree len, tree data)
    285  1.1  mrg {
    286  1.1  mrg   tree len_field, ptr_field;
    287  1.1  mrg   vec<constructor_elt, va_gc> *ce = NULL;
    288  1.1  mrg 
    289  1.1  mrg   gcc_assert (TYPE_DYNAMIC_ARRAY (type));
    290  1.1  mrg   len_field = TYPE_FIELDS (type);
    291  1.1  mrg   ptr_field = TREE_CHAIN (len_field);
    292  1.1  mrg 
    293  1.1  mrg   len = convert (TREE_TYPE (len_field), len);
    294  1.1  mrg   data = convert (TREE_TYPE (ptr_field), data);
    295  1.1  mrg 
    296  1.1  mrg   CONSTRUCTOR_APPEND_ELT (ce, len_field, len);
    297  1.1  mrg   CONSTRUCTOR_APPEND_ELT (ce, ptr_field, data);
    298  1.1  mrg 
    299  1.1  mrg   return build_constructor (type, ce);
    300  1.1  mrg }
    301  1.1  mrg 
    302  1.1  mrg /* Returns value representing the array length of expression EXP.
    303  1.1  mrg    TYPE could be a dynamic or static array.  */
    304  1.1  mrg 
    305  1.1  mrg tree
    306  1.1  mrg get_array_length (tree exp, Type *type)
    307  1.1  mrg {
    308  1.1  mrg   Type *tb = type->toBasetype ();
    309  1.1  mrg 
    310  1.1  mrg   switch (tb->ty)
    311  1.1  mrg     {
    312  1.1  mrg     case Tsarray:
    313  1.1  mrg       return size_int (((TypeSArray *) tb)->dim->toUInteger ());
    314  1.1  mrg 
    315  1.1  mrg     case Tarray:
    316  1.1  mrg       return d_array_length (exp);
    317  1.1  mrg 
    318  1.1  mrg     default:
    319  1.1  mrg       error ("can't determine the length of a %qs", type->toChars ());
    320  1.1  mrg       return error_mark_node;
    321  1.1  mrg     }
    322  1.1  mrg }
    323  1.1  mrg 
    324  1.1  mrg /* Create BINFO for a ClassDeclaration's inheritance tree.
    325  1.1  mrg    InterfaceDeclaration's are not included.  */
    326  1.1  mrg 
    327  1.1  mrg tree
    328  1.1  mrg build_class_binfo (tree super, ClassDeclaration *cd)
    329  1.1  mrg {
    330  1.1  mrg   tree binfo = make_tree_binfo (1);
    331  1.1  mrg   tree ctype = build_ctype (cd->type);
    332  1.1  mrg 
    333  1.1  mrg   /* Want RECORD_TYPE, not POINTER_TYPE.  */
    334  1.1  mrg   BINFO_TYPE (binfo) = TREE_TYPE (ctype);
    335  1.1  mrg   BINFO_INHERITANCE_CHAIN (binfo) = super;
    336  1.1  mrg   BINFO_OFFSET (binfo) = integer_zero_node;
    337  1.1  mrg 
    338  1.1  mrg   if (cd->baseClass)
    339  1.1  mrg     BINFO_BASE_APPEND (binfo, build_class_binfo (binfo, cd->baseClass));
    340  1.1  mrg 
    341  1.1  mrg   return binfo;
    342  1.1  mrg }
    343  1.1  mrg 
    344  1.1  mrg /* Create BINFO for an InterfaceDeclaration's inheritance tree.
    345  1.1  mrg    In order to access all inherited methods in the debugger,
    346  1.1  mrg    the entire tree must be described.
    347  1.1  mrg    This function makes assumptions about interface layout.  */
    348  1.1  mrg 
    349  1.1  mrg tree
    350  1.1  mrg build_interface_binfo (tree super, ClassDeclaration *cd, unsigned& offset)
    351  1.1  mrg {
    352  1.1  mrg   tree binfo = make_tree_binfo (cd->baseclasses->dim);
    353  1.1  mrg   tree ctype = build_ctype (cd->type);
    354  1.1  mrg 
    355  1.1  mrg   /* Want RECORD_TYPE, not POINTER_TYPE.  */
    356  1.1  mrg   BINFO_TYPE (binfo) = TREE_TYPE (ctype);
    357  1.1  mrg   BINFO_INHERITANCE_CHAIN (binfo) = super;
    358  1.1  mrg   BINFO_OFFSET (binfo) = size_int (offset * Target::ptrsize);
    359  1.1  mrg   BINFO_VIRTUAL_P (binfo) = 1;
    360  1.1  mrg 
    361  1.1  mrg   for (size_t i = 0; i < cd->baseclasses->dim; i++, offset++)
    362  1.1  mrg     {
    363  1.1  mrg       BaseClass *bc = (*cd->baseclasses)[i];
    364  1.1  mrg       BINFO_BASE_APPEND (binfo, build_interface_binfo (binfo, bc->sym, offset));
    365  1.1  mrg     }
    366  1.1  mrg 
    367  1.1  mrg   return binfo;
    368  1.1  mrg }
    369  1.1  mrg 
    370  1.1  mrg /* Returns the .funcptr component from the D delegate EXP.  */
    371  1.1  mrg 
    372  1.1  mrg tree
    373  1.1  mrg delegate_method (tree exp)
    374  1.1  mrg {
    375  1.1  mrg   /* Get the back-end type for the delegate and pick out the funcptr field
    376  1.1  mrg      (assumed to be the second field).  */
    377  1.1  mrg   gcc_assert (TYPE_DELEGATE (TREE_TYPE (exp)));
    378  1.1  mrg   tree method_field = TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (exp)));
    379  1.1  mrg   return component_ref (exp, method_field);
    380  1.1  mrg }
    381  1.1  mrg 
    382  1.1  mrg /* Returns the .object component from the delegate EXP.  */
    383  1.1  mrg 
    384  1.1  mrg tree
    385  1.1  mrg delegate_object (tree exp)
    386  1.1  mrg {
    387  1.1  mrg   /* Get the back-end type for the delegate and pick out the object field
    388  1.1  mrg      (assumed to be the first field).  */
    389  1.1  mrg   gcc_assert (TYPE_DELEGATE (TREE_TYPE (exp)));
    390  1.1  mrg   tree obj_field = TYPE_FIELDS (TREE_TYPE (exp));
    391  1.1  mrg   return component_ref (exp, obj_field);
    392  1.1  mrg }
    393  1.1  mrg 
    394  1.1  mrg /* Build a delegate literal of type TYPE whose pointer function is
    395  1.1  mrg    METHOD, and hidden object is OBJECT.  */
    396  1.1  mrg 
    397  1.1  mrg tree
    398  1.1  mrg build_delegate_cst (tree method, tree object, Type *type)
    399  1.1  mrg {
    400  1.1  mrg   tree ctor = make_node (CONSTRUCTOR);
    401  1.1  mrg   tree ctype;
    402  1.1  mrg 
    403  1.1  mrg   Type *tb = type->toBasetype ();
    404  1.1  mrg   if (tb->ty == Tdelegate)
    405  1.1  mrg     ctype = build_ctype (type);
    406  1.1  mrg   else
    407  1.1  mrg     {
    408  1.1  mrg       /* Convert a function method into an anonymous delegate.  */
    409  1.1  mrg       ctype = make_struct_type ("delegate()", 2,
    410  1.1  mrg 				get_identifier ("object"), TREE_TYPE (object),
    411  1.1  mrg 				get_identifier ("func"), TREE_TYPE (method));
    412  1.1  mrg       TYPE_DELEGATE (ctype) = 1;
    413  1.1  mrg     }
    414  1.1  mrg 
    415  1.1  mrg   vec<constructor_elt, va_gc> *ce = NULL;
    416  1.1  mrg   CONSTRUCTOR_APPEND_ELT (ce, TYPE_FIELDS (ctype), object);
    417  1.1  mrg   CONSTRUCTOR_APPEND_ELT (ce, TREE_CHAIN (TYPE_FIELDS (ctype)), method);
    418  1.1  mrg 
    419  1.1  mrg   CONSTRUCTOR_ELTS (ctor) = ce;
    420  1.1  mrg   TREE_TYPE (ctor) = ctype;
    421  1.1  mrg 
    422  1.1  mrg   return ctor;
    423  1.1  mrg }
    424  1.1  mrg 
    425  1.1  mrg /* Builds a temporary tree to store the CALLEE and OBJECT
    426  1.1  mrg    of a method call expression of type TYPE.  */
    427  1.1  mrg 
    428  1.1  mrg tree
    429  1.1  mrg build_method_call (tree callee, tree object, Type *type)
    430  1.1  mrg {
    431  1.1  mrg   tree t = build_delegate_cst (callee, object, type);
    432  1.1  mrg   METHOD_CALL_EXPR (t) = 1;
    433  1.1  mrg   return t;
    434  1.1  mrg }
    435  1.1  mrg 
    436  1.1  mrg /* Extract callee and object from T and return in to CALLEE and OBJECT.  */
    437  1.1  mrg 
    438  1.1  mrg void
    439  1.1  mrg extract_from_method_call (tree t, tree& callee, tree& object)
    440  1.1  mrg {
    441  1.1  mrg   gcc_assert (METHOD_CALL_EXPR (t));
    442  1.1  mrg   object = CONSTRUCTOR_ELT (t, 0)->value;
    443  1.1  mrg   callee = CONSTRUCTOR_ELT (t, 1)->value;
    444  1.1  mrg }
    445  1.1  mrg 
    446  1.1  mrg /* Build a typeof(null) constant of type TYPE.  Handles certain special case
    447  1.1  mrg    conversions, where the underlying type is an aggregate with a nullable
    448  1.1  mrg    interior pointer.  */
    449  1.1  mrg 
    450  1.1  mrg tree
    451  1.1  mrg build_typeof_null_value (Type *type)
    452  1.1  mrg {
    453  1.1  mrg   Type *tb = type->toBasetype ();
    454  1.1  mrg   tree value;
    455  1.1  mrg 
    456  1.1  mrg   /* For dynamic arrays, set length and pointer fields to zero.  */
    457  1.1  mrg   if (tb->ty == Tarray)
    458  1.1  mrg     value = d_array_value (build_ctype (type), size_int (0), null_pointer_node);
    459  1.1  mrg 
    460  1.1  mrg   /* For associative arrays, set the pointer field to null.  */
    461  1.1  mrg   else if (tb->ty == Taarray)
    462  1.1  mrg     {
    463  1.1  mrg       tree ctype = build_ctype (type);
    464  1.1  mrg       gcc_assert (TYPE_ASSOCIATIVE_ARRAY (ctype));
    465  1.1  mrg 
    466  1.1  mrg       value = build_constructor_single (ctype, TYPE_FIELDS (ctype),
    467  1.1  mrg 					null_pointer_node);
    468  1.1  mrg     }
    469  1.1  mrg 
    470  1.1  mrg   /* For delegates, set the frame and function pointer fields to null.  */
    471  1.1  mrg   else if (tb->ty == Tdelegate)
    472  1.1  mrg     value = build_delegate_cst (null_pointer_node, null_pointer_node, type);
    473  1.1  mrg 
    474  1.1  mrg   /* Simple zero constant for all other types.  */
    475  1.1  mrg   else
    476  1.1  mrg     value = build_zero_cst (build_ctype (type));
    477  1.1  mrg 
    478  1.1  mrg   TREE_CONSTANT (value) = 1;
    479  1.1  mrg   return value;
    480  1.1  mrg }
    481  1.1  mrg 
    482  1.1  mrg /* Build a dereference into the virtual table for OBJECT to retrieve
    483  1.1  mrg    a function pointer of type FNTYPE at position INDEX.  */
    484  1.1  mrg 
    485  1.1  mrg tree
    486  1.1  mrg build_vindex_ref (tree object, tree fntype, size_t index)
    487  1.1  mrg {
    488  1.1  mrg   /* The vtable is the first field.  Interface methods are also in the class's
    489  1.1  mrg      vtable, so we don't need to convert from a class to an interface.  */
    490  1.1  mrg   tree result = build_deref (object);
    491  1.1  mrg   result = component_ref (result, TYPE_FIELDS (TREE_TYPE (result)));
    492  1.1  mrg 
    493  1.1  mrg   gcc_assert (POINTER_TYPE_P (fntype));
    494  1.1  mrg 
    495  1.1  mrg   return build_memref (fntype, result, size_int (Target::ptrsize * index));
    496  1.1  mrg }
    497  1.1  mrg 
    498  1.1  mrg /* Return TRUE if EXP is a valid lvalue.  Lvalue references cannot be
    499  1.1  mrg    made into temporaries, otherwise any assignments will be lost.  */
    500  1.1  mrg 
    501  1.1  mrg static bool
    502  1.1  mrg lvalue_p (tree exp)
    503  1.1  mrg {
    504  1.1  mrg   const enum tree_code code = TREE_CODE (exp);
    505  1.1  mrg 
    506  1.1  mrg   switch (code)
    507  1.1  mrg     {
    508  1.1  mrg     case SAVE_EXPR:
    509  1.1  mrg       return false;
    510  1.1  mrg 
    511  1.1  mrg     case ARRAY_REF:
    512  1.1  mrg     case INDIRECT_REF:
    513  1.1  mrg     case VAR_DECL:
    514  1.1  mrg     case PARM_DECL:
    515  1.1  mrg     case RESULT_DECL:
    516  1.1  mrg       return !FUNC_OR_METHOD_TYPE_P (TREE_TYPE (exp));
    517  1.1  mrg 
    518  1.1  mrg     case IMAGPART_EXPR:
    519  1.1  mrg     case REALPART_EXPR:
    520  1.1  mrg     case COMPONENT_REF:
    521  1.1  mrg     CASE_CONVERT:
    522  1.1  mrg       return lvalue_p (TREE_OPERAND (exp, 0));
    523  1.1  mrg 
    524  1.1  mrg     case COND_EXPR:
    525  1.1  mrg       return (lvalue_p (TREE_OPERAND (exp, 1)
    526  1.1  mrg 			? TREE_OPERAND (exp, 1)
    527  1.1  mrg 			: TREE_OPERAND (exp, 0))
    528  1.1  mrg 	      && lvalue_p (TREE_OPERAND (exp, 2)));
    529  1.1  mrg 
    530  1.1  mrg     case TARGET_EXPR:
    531  1.1  mrg       return true;
    532  1.1  mrg 
    533  1.1  mrg     case COMPOUND_EXPR:
    534  1.1  mrg       return lvalue_p (TREE_OPERAND (exp, 1));
    535  1.1  mrg 
    536  1.1  mrg     default:
    537  1.1  mrg       return false;
    538  1.1  mrg     }
    539  1.1  mrg }
    540  1.1  mrg 
    541  1.1  mrg /* Create a SAVE_EXPR if EXP might have unwanted side effects if referenced
    542  1.1  mrg    more than once in an expression.  */
    543  1.1  mrg 
    544  1.1  mrg tree
    545  1.1  mrg d_save_expr (tree exp)
    546  1.1  mrg {
    547  1.1  mrg   if (TREE_SIDE_EFFECTS (exp))
    548  1.1  mrg     {
    549  1.1  mrg       if (lvalue_p (exp))
    550  1.1  mrg 	return stabilize_reference (exp);
    551  1.1  mrg 
    552  1.1  mrg       return save_expr (exp);
    553  1.1  mrg     }
    554  1.1  mrg 
    555  1.1  mrg   return exp;
    556  1.1  mrg }
    557  1.1  mrg 
    558  1.1  mrg /* VALUEP is an expression we want to pre-evaluate or perform a computation on.
    559  1.1  mrg    The expression returned by this function is the part whose value we don't
    560  1.1  mrg    care about, storing the value in VALUEP.  Callers must ensure that the
    561  1.1  mrg    returned expression is evaluated before VALUEP.  */
    562  1.1  mrg 
    563  1.1  mrg tree
    564  1.1  mrg stabilize_expr (tree *valuep)
    565  1.1  mrg {
    566  1.1  mrg   tree expr = *valuep;
    567  1.1  mrg   const enum tree_code code = TREE_CODE (expr);
    568  1.1  mrg   tree lhs;
    569  1.1  mrg   tree rhs;
    570  1.1  mrg 
    571  1.1  mrg   switch (code)
    572  1.1  mrg     {
    573  1.1  mrg     case COMPOUND_EXPR:
    574  1.1  mrg       /* Given ((e1, ...), eN):
    575  1.1  mrg 	 Store the last RHS 'eN' expression in VALUEP.  */
    576  1.1  mrg       lhs = TREE_OPERAND (expr, 0);
    577  1.1  mrg       rhs = TREE_OPERAND (expr, 1);
    578  1.1  mrg       lhs = compound_expr (lhs, stabilize_expr (&rhs));
    579  1.1  mrg       *valuep = rhs;
    580  1.1  mrg       return lhs;
    581  1.1  mrg 
    582  1.1  mrg     default:
    583  1.1  mrg       return NULL_TREE;
    584  1.1  mrg     }
    585  1.1  mrg }
    586  1.1  mrg 
    587  1.1  mrg /* Return a TARGET_EXPR, initializing the DECL with EXP.  */
    588  1.1  mrg 
    589  1.1  mrg tree
    590  1.1  mrg build_target_expr (tree decl, tree exp)
    591  1.1  mrg {
    592  1.1  mrg   tree type = TREE_TYPE (decl);
    593  1.1  mrg   tree result = build4 (TARGET_EXPR, type, decl, exp, NULL_TREE, NULL_TREE);
    594  1.1  mrg 
    595  1.1  mrg   if (EXPR_HAS_LOCATION (exp))
    596  1.1  mrg     SET_EXPR_LOCATION (result, EXPR_LOCATION (exp));
    597  1.1  mrg 
    598  1.1  mrg   /* If decl must always reside in memory.  */
    599  1.1  mrg   if (TREE_ADDRESSABLE (type))
    600  1.1  mrg     d_mark_addressable (decl);
    601  1.1  mrg 
    602  1.1  mrg   /* Always set TREE_SIDE_EFFECTS so that expand_expr does not ignore the
    603  1.1  mrg      TARGET_EXPR.  If there really turn out to be no side effects, then the
    604  1.1  mrg      optimizer should be able to remove it.  */
    605  1.1  mrg   TREE_SIDE_EFFECTS (result) = 1;
    606  1.1  mrg 
    607  1.1  mrg   return result;
    608  1.1  mrg }
    609  1.1  mrg 
    610  1.1  mrg /* Like the above function, but initializes a new temporary.  */
    611  1.1  mrg 
    612  1.1  mrg tree
    613  1.1  mrg force_target_expr (tree exp)
    614  1.1  mrg {
    615  1.1  mrg   tree decl = create_temporary_var (TREE_TYPE (exp));
    616  1.1  mrg 
    617  1.1  mrg   return build_target_expr (decl, exp);
    618  1.1  mrg }
    619  1.1  mrg 
    620  1.1  mrg /* Returns the address of the expression EXP.  */
    621  1.1  mrg 
    622  1.1  mrg tree
    623  1.1  mrg build_address (tree exp)
    624  1.1  mrg {
    625  1.1  mrg   if (error_operand_p (exp))
    626  1.1  mrg     return exp;
    627  1.1  mrg 
    628  1.1  mrg   tree ptrtype;
    629  1.1  mrg   tree type = TREE_TYPE (exp);
    630  1.1  mrg 
    631  1.1  mrg   if (TREE_CODE (exp) == STRING_CST)
    632  1.1  mrg     {
    633  1.1  mrg       /* Just convert string literals (char[]) to C-style strings (char *),
    634  1.1  mrg 	 otherwise the latter method (char[]*) causes conversion problems
    635  1.1  mrg 	 during gimplification.  */
    636  1.1  mrg       ptrtype = build_pointer_type (TREE_TYPE (type));
    637  1.1  mrg     }
    638  1.1  mrg   else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node)
    639  1.1  mrg 	   && TREE_CODE (TYPE_MAIN_VARIANT (type)) == ARRAY_TYPE)
    640  1.1  mrg     {
    641  1.1  mrg       /* Special case for va_list, allow arrays to decay to a pointer.  */
    642  1.1  mrg       ptrtype = build_pointer_type (TREE_TYPE (type));
    643  1.1  mrg     }
    644  1.1  mrg   else
    645  1.1  mrg     ptrtype = build_pointer_type (type);
    646  1.1  mrg 
    647  1.1  mrg   /* Maybe rewrite: &(e1, e2) => (e1, &e2).  */
    648  1.1  mrg   tree init = stabilize_expr (&exp);
    649  1.1  mrg 
    650  1.1  mrg   /* Can't take the address of a manifest constant, instead use its value.  */
    651  1.1  mrg   if (TREE_CODE (exp) == CONST_DECL)
    652  1.1  mrg     exp = DECL_INITIAL (exp);
    653  1.1  mrg 
    654  1.1  mrg   /* Some expression lowering may request an address of a compile-time constant.
    655  1.1  mrg      Make sure it is assigned to a location we can reference.  */
    656  1.1  mrg   if (CONSTANT_CLASS_P (exp) && TREE_CODE (exp) != STRING_CST)
    657  1.1  mrg     exp = force_target_expr (exp);
    658  1.1  mrg 
    659  1.1  mrg   d_mark_addressable (exp);
    660  1.1  mrg   exp = build_fold_addr_expr_with_type_loc (input_location, exp, ptrtype);
    661  1.1  mrg 
    662  1.1  mrg   if (TREE_CODE (exp) == ADDR_EXPR)
    663  1.1  mrg     TREE_NO_TRAMPOLINE (exp) = 1;
    664  1.1  mrg 
    665  1.1  mrg   return compound_expr (init, exp);
    666  1.1  mrg }
    667  1.1  mrg 
    668  1.1  mrg /* Mark EXP saying that we need to be able to take the
    669  1.1  mrg    address of it; it should not be allocated in a register.  */
    670  1.1  mrg 
    671  1.1  mrg tree
    672  1.1  mrg d_mark_addressable (tree exp)
    673  1.1  mrg {
    674  1.1  mrg   switch (TREE_CODE (exp))
    675  1.1  mrg     {
    676  1.1  mrg     case ADDR_EXPR:
    677  1.1  mrg     case COMPONENT_REF:
    678  1.1  mrg     case ARRAY_REF:
    679  1.1  mrg     case REALPART_EXPR:
    680  1.1  mrg     case IMAGPART_EXPR:
    681  1.1  mrg       d_mark_addressable (TREE_OPERAND (exp, 0));
    682  1.1  mrg       break;
    683  1.1  mrg 
    684  1.1  mrg     case PARM_DECL:
    685  1.1  mrg     case VAR_DECL:
    686  1.1  mrg     case RESULT_DECL:
    687  1.1  mrg     case CONST_DECL:
    688  1.1  mrg     case FUNCTION_DECL:
    689  1.1  mrg       TREE_ADDRESSABLE (exp) = 1;
    690  1.1  mrg       break;
    691  1.1  mrg 
    692  1.1  mrg     case CONSTRUCTOR:
    693  1.1  mrg       TREE_ADDRESSABLE (exp) = 1;
    694  1.1  mrg       break;
    695  1.1  mrg 
    696  1.1  mrg     case TARGET_EXPR:
    697  1.1  mrg       TREE_ADDRESSABLE (exp) = 1;
    698  1.1  mrg       d_mark_addressable (TREE_OPERAND (exp, 0));
    699  1.1  mrg       break;
    700  1.1  mrg 
    701  1.1  mrg     default:
    702  1.1  mrg       break;
    703  1.1  mrg     }
    704  1.1  mrg 
    705  1.1  mrg   return exp;
    706  1.1  mrg }
    707  1.1  mrg 
    708  1.1  mrg /* Mark EXP as "used" in the program for the benefit of
    709  1.1  mrg    -Wunused warning purposes.  */
    710  1.1  mrg 
    711  1.1  mrg tree
    712  1.1  mrg d_mark_used (tree exp)
    713  1.1  mrg {
    714  1.1  mrg   switch (TREE_CODE (exp))
    715  1.1  mrg     {
    716  1.1  mrg     case VAR_DECL:
    717  1.1  mrg     case CONST_DECL:
    718  1.1  mrg     case PARM_DECL:
    719  1.1  mrg     case RESULT_DECL:
    720  1.1  mrg     case FUNCTION_DECL:
    721  1.1  mrg       TREE_USED (exp) = 1;
    722  1.1  mrg       break;
    723  1.1  mrg 
    724  1.1  mrg     case ARRAY_REF:
    725  1.1  mrg     case COMPONENT_REF:
    726  1.1  mrg     case MODIFY_EXPR:
    727  1.1  mrg     case REALPART_EXPR:
    728  1.1  mrg     case IMAGPART_EXPR:
    729  1.1  mrg     case NOP_EXPR:
    730  1.1  mrg     case CONVERT_EXPR:
    731  1.1  mrg     case ADDR_EXPR:
    732  1.1  mrg       d_mark_used (TREE_OPERAND (exp, 0));
    733  1.1  mrg       break;
    734  1.1  mrg 
    735  1.1  mrg     case COMPOUND_EXPR:
    736  1.1  mrg       d_mark_used (TREE_OPERAND (exp, 0));
    737  1.1  mrg       d_mark_used (TREE_OPERAND (exp, 1));
    738  1.1  mrg       break;
    739  1.1  mrg 
    740  1.1  mrg     default:
    741  1.1  mrg       break;
    742  1.1  mrg     }
    743  1.1  mrg   return exp;
    744  1.1  mrg }
    745  1.1  mrg 
    746  1.1  mrg /* Mark EXP as read, not just set, for set but not used -Wunused
    747  1.1  mrg    warning purposes.  */
    748  1.1  mrg 
    749  1.1  mrg tree
    750  1.1  mrg d_mark_read (tree exp)
    751  1.1  mrg {
    752  1.1  mrg   switch (TREE_CODE (exp))
    753  1.1  mrg     {
    754  1.1  mrg     case VAR_DECL:
    755  1.1  mrg     case PARM_DECL:
    756  1.1  mrg       TREE_USED (exp) = 1;
    757  1.1  mrg       DECL_READ_P (exp) = 1;
    758  1.1  mrg       break;
    759  1.1  mrg 
    760  1.1  mrg     case ARRAY_REF:
    761  1.1  mrg     case COMPONENT_REF:
    762  1.1  mrg     case MODIFY_EXPR:
    763  1.1  mrg     case REALPART_EXPR:
    764  1.1  mrg     case IMAGPART_EXPR:
    765  1.1  mrg     case NOP_EXPR:
    766  1.1  mrg     case CONVERT_EXPR:
    767  1.1  mrg     case ADDR_EXPR:
    768  1.1  mrg       d_mark_read (TREE_OPERAND (exp, 0));
    769  1.1  mrg       break;
    770  1.1  mrg 
    771  1.1  mrg     case COMPOUND_EXPR:
    772  1.1  mrg       d_mark_read (TREE_OPERAND (exp, 1));
    773  1.1  mrg       break;
    774  1.1  mrg 
    775  1.1  mrg     default:
    776  1.1  mrg       break;
    777  1.1  mrg     }
    778  1.1  mrg   return exp;
    779  1.1  mrg }
    780  1.1  mrg 
    781  1.1  mrg /* Return TRUE if the struct SD is suitable for comparison using memcmp.
    782  1.1  mrg    This is because we don't guarantee that padding is zero-initialized for
    783  1.1  mrg    a stack variable, so we can't use memcmp to compare struct values.  */
    784  1.1  mrg 
    785  1.1  mrg bool
    786  1.1  mrg identity_compare_p (StructDeclaration *sd)
    787  1.1  mrg {
    788  1.1  mrg   if (sd->isUnionDeclaration ())
    789  1.1  mrg     return true;
    790  1.1  mrg 
    791  1.1  mrg   unsigned offset = 0;
    792  1.1  mrg 
    793  1.1  mrg   for (size_t i = 0; i < sd->fields.dim; i++)
    794  1.1  mrg     {
    795  1.1  mrg       VarDeclaration *vd = sd->fields[i];
    796  1.1  mrg       Type *tb = vd->type->toBasetype ();
    797  1.1  mrg 
    798  1.1  mrg       /* Check inner data structures.  */
    799  1.1  mrg       if (tb->ty == Tstruct)
    800  1.1  mrg 	{
    801  1.1  mrg 	  TypeStruct *ts = (TypeStruct *) tb;
    802  1.1  mrg 	  if (!identity_compare_p (ts->sym))
    803  1.1  mrg 	    return false;
    804  1.1  mrg 	}
    805  1.1  mrg 
    806  1.1  mrg       /* Check for types that may have padding.  */
    807  1.1  mrg       if ((tb->ty == Tcomplex80 || tb->ty == Tfloat80 || tb->ty == Timaginary80)
    808  1.1  mrg 	  && Target::realpad != 0)
    809  1.1  mrg 	return false;
    810  1.1  mrg 
    811  1.1  mrg       if (offset <= vd->offset)
    812  1.1  mrg 	{
    813  1.1  mrg 	  /* There's a hole in the struct.  */
    814  1.1  mrg 	  if (offset != vd->offset)
    815  1.1  mrg 	    return false;
    816  1.1  mrg 
    817  1.1  mrg 	  offset += vd->type->size ();
    818  1.1  mrg 	}
    819  1.1  mrg     }
    820  1.1  mrg 
    821  1.1  mrg   /* Any trailing padding may not be zero.  */
    822  1.1  mrg   if (offset < sd->structsize)
    823  1.1  mrg     return false;
    824  1.1  mrg 
    825  1.1  mrg   return true;
    826  1.1  mrg }
    827  1.1  mrg 
    828  1.1  mrg /* Build a floating-point identity comparison between T1 and T2, ignoring any
    829  1.1  mrg    excessive padding in the type.  CODE is EQ_EXPR or NE_EXPR comparison.  */
    830  1.1  mrg 
    831  1.1  mrg tree
    832  1.1  mrg build_float_identity (tree_code code, tree t1, tree t2)
    833  1.1  mrg {
    834  1.1  mrg   tree tmemcmp = builtin_decl_explicit (BUILT_IN_MEMCMP);
    835  1.1  mrg   tree size = size_int (TYPE_PRECISION (TREE_TYPE (t1)) / BITS_PER_UNIT);
    836  1.1  mrg 
    837  1.1  mrg   tree result = build_call_expr (tmemcmp, 3, build_address (t1),
    838  1.1  mrg 				 build_address (t2), size);
    839  1.1  mrg   return build_boolop (code, result, integer_zero_node);
    840  1.1  mrg }
    841  1.1  mrg 
    842  1.1  mrg /* Lower a field-by-field equality expression between T1 and T2 of type SD.
    843  1.1  mrg    CODE is the EQ_EXPR or NE_EXPR comparison.  */
    844  1.1  mrg 
    845  1.1  mrg static tree
    846  1.1  mrg lower_struct_comparison (tree_code code, StructDeclaration *sd,
    847  1.1  mrg 			 tree t1, tree t2)
    848  1.1  mrg {
    849  1.1  mrg   tree_code tcode = (code == EQ_EXPR) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
    850  1.1  mrg   tree tmemcmp = NULL_TREE;
    851  1.1  mrg 
    852  1.1  mrg   /* We can skip the compare if the structs are empty.  */
    853  1.1  mrg   if (sd->fields.dim == 0)
    854  1.1  mrg     {
    855  1.1  mrg       tmemcmp = build_boolop (code, integer_zero_node, integer_zero_node);
    856  1.1  mrg       if (TREE_SIDE_EFFECTS (t2))
    857  1.1  mrg 	tmemcmp = compound_expr (t2, tmemcmp);
    858  1.1  mrg       if (TREE_SIDE_EFFECTS (t1))
    859  1.1  mrg 	tmemcmp = compound_expr (t1, tmemcmp);
    860  1.1  mrg 
    861  1.1  mrg       return tmemcmp;
    862  1.1  mrg     }
    863  1.1  mrg 
    864  1.1  mrg   /* Let back-end take care of union comparisons.  */
    865  1.1  mrg   if (sd->isUnionDeclaration ())
    866  1.1  mrg     {
    867  1.1  mrg       tmemcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP), 3,
    868  1.1  mrg 				 build_address (t1), build_address (t2),
    869  1.1  mrg 				 size_int (sd->structsize));
    870  1.1  mrg 
    871  1.1  mrg       return build_boolop (code, tmemcmp, integer_zero_node);
    872  1.1  mrg     }
    873  1.1  mrg 
    874  1.1  mrg   for (size_t i = 0; i < sd->fields.dim; i++)
    875  1.1  mrg     {
    876  1.1  mrg       VarDeclaration *vd = sd->fields[i];
    877  1.1  mrg       Type *type = vd->type->toBasetype ();
    878  1.1  mrg       tree sfield = get_symbol_decl (vd);
    879  1.1  mrg 
    880  1.1  mrg       tree t1ref = component_ref (t1, sfield);
    881  1.1  mrg       tree t2ref = component_ref (t2, sfield);
    882  1.1  mrg       tree tcmp;
    883  1.1  mrg 
    884  1.1  mrg       if (type->ty == Tstruct)
    885  1.1  mrg 	{
    886  1.1  mrg 	  /* Compare inner data structures.  */
    887  1.1  mrg 	  StructDeclaration *decl = ((TypeStruct *) type)->sym;
    888  1.1  mrg 	  tcmp = lower_struct_comparison (code, decl, t1ref, t2ref);
    889  1.1  mrg 	}
    890  1.1  mrg       else if (type->ty != Tvector && type->isintegral ())
    891  1.1  mrg 	{
    892  1.1  mrg 	  /* Integer comparison, no special handling required.  */
    893  1.1  mrg 	  tcmp = build_boolop (code, t1ref, t2ref);
    894  1.1  mrg 	}
    895  1.1  mrg       else if (type->ty != Tvector && type->isfloating ())
    896  1.1  mrg 	{
    897  1.1  mrg 	  /* Floating-point comparison, don't compare padding in type.  */
    898  1.1  mrg 	  if (!type->iscomplex ())
    899  1.1  mrg 	    tcmp = build_float_identity (code, t1ref, t2ref);
    900  1.1  mrg 	  else
    901  1.1  mrg 	    {
    902  1.1  mrg 	      tree req = build_float_identity (code, real_part (t1ref),
    903  1.1  mrg 					       real_part (t2ref));
    904  1.1  mrg 	      tree ieq = build_float_identity (code, imaginary_part (t1ref),
    905  1.1  mrg 					       imaginary_part (t2ref));
    906  1.1  mrg 
    907  1.1  mrg 	      tcmp = build_boolop (tcode, req, ieq);
    908  1.1  mrg 	    }
    909  1.1  mrg 	}
    910  1.1  mrg       else
    911  1.1  mrg 	{
    912  1.1  mrg 	  tree stype = build_ctype (type);
    913  1.1  mrg 	  opt_scalar_int_mode mode = int_mode_for_mode (TYPE_MODE (stype));
    914  1.1  mrg 
    915  1.1  mrg 	  if (mode.exists ())
    916  1.1  mrg 	    {
    917  1.1  mrg 	      /* Compare field bits as their corresponding integer type.
    918  1.1  mrg 		    *((T*) &t1) == *((T*) &t2)  */
    919  1.1  mrg 	      tree tmode = lang_hooks.types.type_for_mode (mode.require (), 1);
    920  1.1  mrg 
    921  1.1  mrg 	      if (tmode == NULL_TREE)
    922  1.1  mrg 		tmode = make_unsigned_type (GET_MODE_BITSIZE (mode.require ()));
    923  1.1  mrg 
    924  1.1  mrg 	      t1ref = build_vconvert (tmode, t1ref);
    925  1.1  mrg 	      t2ref = build_vconvert (tmode, t2ref);
    926  1.1  mrg 
    927  1.1  mrg 	      tcmp = build_boolop (code, t1ref, t2ref);
    928  1.1  mrg 	    }
    929  1.1  mrg 	  else
    930  1.1  mrg 	    {
    931  1.1  mrg 	      /* Simple memcmp between types.  */
    932  1.1  mrg 	      tcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP),
    933  1.1  mrg 				      3, build_address (t1ref),
    934  1.1  mrg 				      build_address (t2ref),
    935  1.1  mrg 				      TYPE_SIZE_UNIT (stype));
    936  1.1  mrg 
    937  1.1  mrg 	      tcmp = build_boolop (code, tcmp, integer_zero_node);
    938  1.1  mrg 	    }
    939  1.1  mrg 	}
    940  1.1  mrg 
    941  1.1  mrg       tmemcmp = (tmemcmp) ? build_boolop (tcode, tmemcmp, tcmp) : tcmp;
    942  1.1  mrg     }
    943  1.1  mrg 
    944  1.1  mrg   return tmemcmp;
    945  1.1  mrg }
    946  1.1  mrg 
    947  1.1  mrg 
    948  1.1  mrg /* Build an equality expression between two RECORD_TYPES T1 and T2 of type SD.
    949  1.1  mrg    If possible, use memcmp, otherwise field-by-field comparison is done.
    950  1.1  mrg    CODE is the EQ_EXPR or NE_EXPR comparison.  */
    951  1.1  mrg 
    952  1.1  mrg tree
    953  1.1  mrg build_struct_comparison (tree_code code, StructDeclaration *sd,
    954  1.1  mrg 			 tree t1, tree t2)
    955  1.1  mrg {
    956  1.1  mrg   /* We can skip the compare if the structs are empty.  */
    957  1.1  mrg   if (sd->fields.dim == 0)
    958  1.1  mrg     {
    959  1.1  mrg       tree exp = build_boolop (code, integer_zero_node, integer_zero_node);
    960  1.1  mrg       if (TREE_SIDE_EFFECTS (t2))
    961  1.1  mrg 	exp = compound_expr (t2, exp);
    962  1.1  mrg       if (TREE_SIDE_EFFECTS (t1))
    963  1.1  mrg 	exp = compound_expr (t1, exp);
    964  1.1  mrg 
    965  1.1  mrg       return exp;
    966  1.1  mrg     }
    967  1.1  mrg 
    968  1.1  mrg   /* Make temporaries to prevent multiple evaluations.  */
    969  1.1  mrg   tree t1init = stabilize_expr (&t1);
    970  1.1  mrg   tree t2init = stabilize_expr (&t2);
    971  1.1  mrg   tree result;
    972  1.1  mrg 
    973  1.1  mrg   t1 = d_save_expr (t1);
    974  1.1  mrg   t2 = d_save_expr (t2);
    975  1.1  mrg 
    976  1.1  mrg   /* Bitwise comparison of structs not returned in memory may not work
    977  1.1  mrg      due to data holes loosing its zero padding upon return.
    978  1.1  mrg      As a heuristic, small structs are not compared using memcmp either.  */
    979  1.1  mrg   if (TYPE_MODE (TREE_TYPE (t1)) != BLKmode || !identity_compare_p (sd))
    980  1.1  mrg     result = lower_struct_comparison (code, sd, t1, t2);
    981  1.1  mrg   else
    982  1.1  mrg     {
    983  1.1  mrg       /* Do bit compare of structs.  */
    984  1.1  mrg       tree size = size_int (sd->structsize);
    985  1.1  mrg       tree tmemcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP),
    986  1.1  mrg 				      3, build_address (t1),
    987  1.1  mrg 				      build_address (t2), size);
    988  1.1  mrg 
    989  1.1  mrg       result = build_boolop (code, tmemcmp, integer_zero_node);
    990  1.1  mrg     }
    991  1.1  mrg 
    992  1.1  mrg   return compound_expr (compound_expr (t1init, t2init), result);
    993  1.1  mrg }
    994  1.1  mrg 
    995  1.1  mrg /* Build an equality expression between two ARRAY_TYPES of size LENGTH.
    996  1.1  mrg    The pointer references are T1 and T2, and the element type is SD.
    997  1.1  mrg    CODE is the EQ_EXPR or NE_EXPR comparison.  */
    998  1.1  mrg 
    999  1.1  mrg tree
   1000  1.1  mrg build_array_struct_comparison (tree_code code, StructDeclaration *sd,
   1001  1.1  mrg 			       tree length, tree t1, tree t2)
   1002  1.1  mrg {
   1003  1.1  mrg   tree_code tcode = (code == EQ_EXPR) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
   1004  1.1  mrg 
   1005  1.1  mrg   /* Build temporary for the result of the comparison.
   1006  1.1  mrg      Initialize as either 0 or 1 depending on operation.  */
   1007  1.1  mrg   tree result = build_local_temp (d_bool_type);
   1008  1.1  mrg   tree init = build_boolop (code, integer_zero_node, integer_zero_node);
   1009  1.1  mrg   add_stmt (build_assign (INIT_EXPR, result, init));
   1010  1.1  mrg 
   1011  1.1  mrg   /* Cast pointer-to-array to pointer-to-struct.  */
   1012  1.1  mrg   tree ptrtype = build_ctype (sd->type->pointerTo ());
   1013  1.1  mrg   tree lentype = TREE_TYPE (length);
   1014  1.1  mrg 
   1015  1.1  mrg   push_binding_level (level_block);
   1016  1.1  mrg   push_stmt_list ();
   1017  1.1  mrg 
   1018  1.1  mrg   /* Build temporary locals for length and pointers.  */
   1019  1.1  mrg   tree t = build_local_temp (size_type_node);
   1020  1.1  mrg   add_stmt (build_assign (INIT_EXPR, t, length));
   1021  1.1  mrg   length = t;
   1022  1.1  mrg 
   1023  1.1  mrg   t = build_local_temp (ptrtype);
   1024  1.1  mrg   add_stmt (build_assign (INIT_EXPR, t, d_convert (ptrtype, t1)));
   1025  1.1  mrg   t1 = t;
   1026  1.1  mrg 
   1027  1.1  mrg   t = build_local_temp (ptrtype);
   1028  1.1  mrg   add_stmt (build_assign (INIT_EXPR, t, d_convert (ptrtype, t2)));
   1029  1.1  mrg   t2 = t;
   1030  1.1  mrg 
   1031  1.1  mrg   /* Build loop for comparing each element.  */
   1032  1.1  mrg   push_stmt_list ();
   1033  1.1  mrg 
   1034  1.1  mrg   /* Exit logic for the loop.
   1035  1.1  mrg 	if (length == 0 || result OP 0) break;  */
   1036  1.1  mrg   t = build_boolop (EQ_EXPR, length, d_convert (lentype, integer_zero_node));
   1037  1.1  mrg   t = build_boolop (TRUTH_ORIF_EXPR, t, build_boolop (code, result,
   1038  1.1  mrg 						      boolean_false_node));
   1039  1.1  mrg   t = build1 (EXIT_EXPR, void_type_node, t);
   1040  1.1  mrg   add_stmt (t);
   1041  1.1  mrg 
   1042  1.1  mrg   /* Do comparison, caching the value.
   1043  1.1  mrg 	result = result OP (*t1 == *t2);  */
   1044  1.1  mrg   t = build_struct_comparison (code, sd, build_deref (t1), build_deref (t2));
   1045  1.1  mrg   t = build_boolop (tcode, result, t);
   1046  1.1  mrg   t = modify_expr (result, t);
   1047  1.1  mrg   add_stmt (t);
   1048  1.1  mrg 
   1049  1.1  mrg   /* Move both pointers to next element position.
   1050  1.1  mrg 	t1++, t2++;  */
   1051  1.1  mrg   tree size = d_convert (ptrtype, TYPE_SIZE_UNIT (TREE_TYPE (ptrtype)));
   1052  1.1  mrg   t = build2 (POSTINCREMENT_EXPR, ptrtype, t1, size);
   1053  1.1  mrg   add_stmt (t);
   1054  1.1  mrg   t = build2 (POSTINCREMENT_EXPR, ptrtype, t2, size);
   1055  1.1  mrg   add_stmt (t);
   1056  1.1  mrg 
   1057  1.1  mrg   /* Decrease loop counter.
   1058  1.1  mrg 	length -= 1;  */
   1059  1.1  mrg   t = build2 (POSTDECREMENT_EXPR, lentype, length,
   1060  1.1  mrg 	     d_convert (lentype, integer_one_node));
   1061  1.1  mrg   add_stmt (t);
   1062  1.1  mrg 
   1063  1.1  mrg   /* Pop statements and finish loop.  */
   1064  1.1  mrg   tree body = pop_stmt_list ();
   1065  1.1  mrg   add_stmt (build1 (LOOP_EXPR, void_type_node, body));
   1066  1.1  mrg 
   1067  1.1  mrg   /* Wrap it up into a bind expression.  */
   1068  1.1  mrg   tree stmt_list = pop_stmt_list ();
   1069  1.1  mrg   tree block = pop_binding_level ();
   1070  1.1  mrg 
   1071  1.1  mrg   body = build3 (BIND_EXPR, void_type_node,
   1072  1.1  mrg 		 BLOCK_VARS (block), stmt_list, block);
   1073  1.1  mrg 
   1074  1.1  mrg   return compound_expr (body, result);
   1075  1.1  mrg }
   1076  1.1  mrg 
   1077  1.1  mrg /* Create an anonymous field of type ubyte[T] at OFFSET to fill
   1078  1.1  mrg    the alignment hole between OFFSET and FIELDPOS.  */
   1079  1.1  mrg 
   1080  1.1  mrg static tree
   1081  1.1  mrg build_alignment_field (tree type, HOST_WIDE_INT offset, HOST_WIDE_INT fieldpos)
   1082  1.1  mrg {
   1083  1.1  mrg   tree atype = make_array_type (Type::tuns8, fieldpos - offset);
   1084  1.1  mrg   tree field = create_field_decl (atype, NULL, 1, 1);
   1085  1.1  mrg 
   1086  1.1  mrg   SET_DECL_OFFSET_ALIGN (field, TYPE_ALIGN (atype));
   1087  1.1  mrg   DECL_FIELD_OFFSET (field) = size_int (offset);
   1088  1.1  mrg   DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
   1089  1.1  mrg   DECL_FIELD_CONTEXT (field) = type;
   1090  1.1  mrg   DECL_PADDING_P (field) = 1;
   1091  1.1  mrg 
   1092  1.1  mrg   layout_decl (field, 0);
   1093  1.1  mrg 
   1094  1.1  mrg   return field;
   1095  1.1  mrg }
   1096  1.1  mrg 
   1097  1.1  mrg /* Build a constructor for a variable of aggregate type TYPE using the
   1098  1.1  mrg    initializer INIT, an ordered flat list of fields and values provided
   1099  1.1  mrg    by the frontend.  The returned constructor should be a value that
   1100  1.1  mrg    matches the layout of TYPE.  */
   1101  1.1  mrg 
   1102  1.1  mrg tree
   1103  1.1  mrg build_struct_literal (tree type, vec<constructor_elt, va_gc> *init)
   1104  1.1  mrg {
   1105  1.1  mrg   /* If the initializer was empty, use default zero initialization.  */
   1106  1.1  mrg   if (vec_safe_is_empty (init))
   1107  1.1  mrg     return build_constructor (type, NULL);
   1108  1.1  mrg 
   1109  1.1  mrg   vec<constructor_elt, va_gc> *ve = NULL;
   1110  1.1  mrg   HOST_WIDE_INT offset = 0;
   1111  1.1  mrg   bool constant_p = true;
   1112  1.1  mrg   bool fillholes = true;
   1113  1.1  mrg   bool finished = false;
   1114  1.1  mrg 
   1115  1.1  mrg   /* Filling alignment holes this only applies to structs.  */
   1116  1.1  mrg   if (TREE_CODE (type) != RECORD_TYPE
   1117  1.1  mrg       || CLASS_TYPE_P (type) || TYPE_PACKED (type))
   1118  1.1  mrg     fillholes = false;
   1119  1.1  mrg 
   1120  1.1  mrg   /* Walk through each field, matching our initializer list.  */
   1121  1.1  mrg   for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
   1122  1.1  mrg     {
   1123  1.1  mrg       bool is_initialized = false;
   1124  1.1  mrg       tree value;
   1125  1.1  mrg 
   1126  1.1  mrg       if (DECL_NAME (field) == NULL_TREE
   1127  1.1  mrg 	  && RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
   1128  1.1  mrg 	  && ANON_AGGR_TYPE_P (TREE_TYPE (field)))
   1129  1.1  mrg 	{
   1130  1.1  mrg 	  /* Search all nesting aggregates, if nothing is found, then
   1131  1.1  mrg 	     this will return an empty initializer to fill the hole.  */
   1132  1.1  mrg 	  value = build_struct_literal (TREE_TYPE (field), init);
   1133  1.1  mrg 
   1134  1.1  mrg 	  if (!initializer_zerop (value))
   1135  1.1  mrg 	    is_initialized = true;
   1136  1.1  mrg 	}
   1137  1.1  mrg       else
   1138  1.1  mrg 	{
   1139  1.1  mrg 	  /* Search for the value to initialize the next field.  Once found,
   1140  1.1  mrg 	     pop it from the init list so we don't look at it again.  */
   1141  1.1  mrg 	  unsigned HOST_WIDE_INT idx;
   1142  1.1  mrg 	  tree index;
   1143  1.1  mrg 
   1144  1.1  mrg 	  FOR_EACH_CONSTRUCTOR_ELT (init, idx, index, value)
   1145  1.1  mrg 	    {
   1146  1.1  mrg 	      /* If the index is NULL, then just assign it to the next field.
   1147  1.1  mrg 		 This comes from layout_typeinfo(), which generates a flat
   1148  1.1  mrg 		 list of values that we must shape into the record type.  */
   1149  1.1  mrg 	      if (index == field || index == NULL_TREE)
   1150  1.1  mrg 		{
   1151  1.1  mrg 		  init->ordered_remove (idx);
   1152  1.1  mrg 		  if (!finished)
   1153  1.1  mrg 		    is_initialized = true;
   1154  1.1  mrg 		  break;
   1155  1.1  mrg 		}
   1156  1.1  mrg 	    }
   1157  1.1  mrg 	}
   1158  1.1  mrg 
   1159  1.1  mrg       if (is_initialized)
   1160  1.1  mrg 	{
   1161  1.1  mrg 	  HOST_WIDE_INT fieldpos = int_byte_position (field);
   1162  1.1  mrg 	  gcc_assert (value != NULL_TREE);
   1163  1.1  mrg 
   1164  1.1  mrg 	  /* Insert anonymous fields in the constructor for padding out
   1165  1.1  mrg 	     alignment holes in-place between fields.  */
   1166  1.1  mrg 	  if (fillholes && offset < fieldpos)
   1167  1.1  mrg 	    {
   1168  1.1  mrg 	      tree pfield = build_alignment_field (type, offset, fieldpos);
   1169  1.1  mrg 	      tree pvalue = build_zero_cst (TREE_TYPE (pfield));
   1170  1.1  mrg 	      CONSTRUCTOR_APPEND_ELT (ve, pfield, pvalue);
   1171  1.1  mrg 	    }
   1172  1.1  mrg 
   1173  1.1  mrg 	  /* Must not initialize fields that overlap.  */
   1174  1.1  mrg 	  if (fieldpos < offset)
   1175  1.1  mrg 	    {
   1176  1.1  mrg 	      /* Find the nearest user defined type and field.  */
   1177  1.1  mrg 	      tree vtype = type;
   1178  1.1  mrg 	      while (ANON_AGGR_TYPE_P (vtype))
   1179  1.1  mrg 		vtype = TYPE_CONTEXT (vtype);
   1180  1.1  mrg 
   1181  1.1  mrg 	      tree vfield = field;
   1182  1.1  mrg 	      if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (vfield))
   1183  1.1  mrg 		  && ANON_AGGR_TYPE_P (TREE_TYPE (vfield)))
   1184  1.1  mrg 		vfield = TYPE_FIELDS (TREE_TYPE (vfield));
   1185  1.1  mrg 
   1186  1.1  mrg 	      /* Must not generate errors for compiler generated fields.  */
   1187  1.1  mrg 	      gcc_assert (TYPE_NAME (vtype) && DECL_NAME (vfield));
   1188  1.1  mrg 	      error ("overlapping initializer for field %qT.%qD",
   1189  1.1  mrg 		     TYPE_NAME (vtype), DECL_NAME (vfield));
   1190  1.1  mrg 	    }
   1191  1.1  mrg 
   1192  1.1  mrg 	  if (!TREE_CONSTANT (value))
   1193  1.1  mrg 	    constant_p = false;
   1194  1.1  mrg 
   1195  1.1  mrg 	  CONSTRUCTOR_APPEND_ELT (ve, field, value);
   1196  1.1  mrg 
   1197  1.1  mrg 	  /* For unions, only the first field is initialized, any other field
   1198  1.1  mrg 	     initializers found for this union are drained and ignored.  */
   1199  1.1  mrg 	  if (TREE_CODE (type) == UNION_TYPE)
   1200  1.1  mrg 	    finished = true;
   1201  1.1  mrg 	}
   1202  1.1  mrg 
   1203  1.1  mrg       /* Move offset to the next position in the struct.  */
   1204  1.1  mrg       if (TREE_CODE (type) == RECORD_TYPE)
   1205  1.1  mrg 	{
   1206  1.1  mrg 	  offset = int_byte_position (field)
   1207  1.1  mrg 	    + int_size_in_bytes (TREE_TYPE (field));
   1208  1.1  mrg 	}
   1209  1.1  mrg 
   1210  1.1  mrg       /* If all initializers have been assigned, there's nothing else to do.  */
   1211  1.1  mrg       if (vec_safe_is_empty (init))
   1212  1.1  mrg 	break;
   1213  1.1  mrg     }
   1214  1.1  mrg 
   1215  1.1  mrg   /* Finally pad out the end of the record.  */
   1216  1.1  mrg   if (fillholes && offset < int_size_in_bytes (type))
   1217  1.1  mrg     {
   1218  1.1  mrg       tree pfield = build_alignment_field (type, offset,
   1219  1.1  mrg 					   int_size_in_bytes (type));
   1220  1.1  mrg       tree pvalue = build_zero_cst (TREE_TYPE (pfield));
   1221  1.1  mrg       CONSTRUCTOR_APPEND_ELT (ve, pfield, pvalue);
   1222  1.1  mrg     }
   1223  1.1  mrg 
   1224  1.1  mrg   /* Ensure that we have consumed all values.  */
   1225  1.1  mrg   gcc_assert (vec_safe_is_empty (init) || ANON_AGGR_TYPE_P (type));
   1226  1.1  mrg 
   1227  1.1  mrg   tree ctor = build_constructor (type, ve);
   1228  1.1  mrg 
   1229  1.1  mrg   if (constant_p)
   1230  1.1  mrg     TREE_CONSTANT (ctor) = 1;
   1231  1.1  mrg 
   1232  1.1  mrg   return ctor;
   1233  1.1  mrg }
   1234  1.1  mrg 
   1235  1.1  mrg /* Given the TYPE of an anonymous field inside T, return the
   1236  1.1  mrg    FIELD_DECL for the field.  If not found return NULL_TREE.
   1237  1.1  mrg    Because anonymous types can nest, we must also search all
   1238  1.1  mrg    anonymous fields that are directly reachable.  */
   1239  1.1  mrg 
   1240  1.1  mrg static tree
   1241  1.1  mrg lookup_anon_field (tree t, tree type)
   1242  1.1  mrg {
   1243  1.1  mrg   t = TYPE_MAIN_VARIANT (t);
   1244  1.1  mrg 
   1245  1.1  mrg   for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
   1246  1.1  mrg     {
   1247  1.1  mrg       if (DECL_NAME (field) == NULL_TREE)
   1248  1.1  mrg 	{
   1249  1.1  mrg 	  /* If we find it directly, return the field.  */
   1250  1.1  mrg 	  if (type == TYPE_MAIN_VARIANT (TREE_TYPE (field)))
   1251  1.1  mrg 	    return field;
   1252  1.1  mrg 
   1253  1.1  mrg 	  /* Otherwise, it could be nested, search harder.  */
   1254  1.1  mrg 	  if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
   1255  1.1  mrg 	      && ANON_AGGR_TYPE_P (TREE_TYPE (field)))
   1256  1.1  mrg 	    {
   1257  1.1  mrg 	      tree subfield = lookup_anon_field (TREE_TYPE (field), type);
   1258  1.1  mrg 	      if (subfield)
   1259  1.1  mrg 		return subfield;
   1260  1.1  mrg 	    }
   1261  1.1  mrg 	}
   1262  1.1  mrg     }
   1263  1.1  mrg 
   1264  1.1  mrg   return NULL_TREE;
   1265  1.1  mrg }
   1266  1.1  mrg 
   1267  1.1  mrg /* Builds OBJECT.FIELD component reference.  */
   1268  1.1  mrg 
   1269  1.1  mrg tree
   1270  1.1  mrg component_ref (tree object, tree field)
   1271  1.1  mrg {
   1272  1.1  mrg   if (error_operand_p (object) || error_operand_p (field))
   1273  1.1  mrg     return error_mark_node;
   1274  1.1  mrg 
   1275  1.1  mrg   gcc_assert (TREE_CODE (field) == FIELD_DECL);
   1276  1.1  mrg 
   1277  1.1  mrg   /* Maybe rewrite: (e1, e2).field => (e1, e2.field)  */
   1278  1.1  mrg   tree init = stabilize_expr (&object);
   1279  1.1  mrg 
   1280  1.1  mrg   /* If the FIELD is from an anonymous aggregate, generate a reference
   1281  1.1  mrg      to the anonymous data member, and recur to find FIELD.  */
   1282  1.1  mrg   if (ANON_AGGR_TYPE_P (DECL_CONTEXT (field)))
   1283  1.1  mrg     {
   1284  1.1  mrg       tree anonymous_field = lookup_anon_field (TREE_TYPE (object),
   1285  1.1  mrg 						DECL_CONTEXT (field));
   1286  1.1  mrg       object = component_ref (object, anonymous_field);
   1287  1.1  mrg     }
   1288  1.1  mrg 
   1289  1.1  mrg   tree result = fold_build3_loc (input_location, COMPONENT_REF,
   1290  1.1  mrg 				 TREE_TYPE (field), object, field, NULL_TREE);
   1291  1.1  mrg 
   1292  1.1  mrg   return compound_expr (init, result);
   1293  1.1  mrg }
   1294  1.1  mrg 
   1295  1.1  mrg /* Build an assignment expression of lvalue LHS from value RHS.
   1296  1.1  mrg    CODE is the code for a binary operator that we use to combine
   1297  1.1  mrg    the old value of LHS with RHS to get the new value.  */
   1298  1.1  mrg 
   1299  1.1  mrg tree
   1300  1.1  mrg build_assign (tree_code code, tree lhs, tree rhs)
   1301  1.1  mrg {
   1302  1.1  mrg   tree init = stabilize_expr (&lhs);
   1303  1.1  mrg   init = compound_expr (init, stabilize_expr (&rhs));
   1304  1.1  mrg 
   1305  1.1  mrg   /* If initializing the LHS using a function that returns via NRVO.  */
   1306  1.1  mrg   if (code == INIT_EXPR && TREE_CODE (rhs) == CALL_EXPR
   1307  1.1  mrg       && AGGREGATE_TYPE_P (TREE_TYPE (rhs))
   1308  1.1  mrg       && aggregate_value_p (TREE_TYPE (rhs), rhs))
   1309  1.1  mrg     {
   1310  1.1  mrg       /* Mark as addressable here, which should ensure the return slot is the
   1311  1.1  mrg 	 address of the LHS expression, taken care of by back-end.  */
   1312  1.1  mrg       d_mark_addressable (lhs);
   1313  1.1  mrg       CALL_EXPR_RETURN_SLOT_OPT (rhs) = true;
   1314  1.1  mrg     }
   1315  1.1  mrg 
   1316  1.1  mrg   /* The LHS assignment replaces the temporary in TARGET_EXPR_SLOT.  */
   1317  1.1  mrg   if (TREE_CODE (rhs) == TARGET_EXPR)
   1318  1.1  mrg     {
   1319  1.1  mrg       /* If CODE is not INIT_EXPR, can't initialize LHS directly,
   1320  1.1  mrg 	 since that would cause the LHS to be constructed twice.
   1321  1.1  mrg 	 So we force the TARGET_EXPR to be expanded without a target.  */
   1322  1.1  mrg       if (code != INIT_EXPR)
   1323  1.1  mrg 	rhs = compound_expr (rhs, TARGET_EXPR_SLOT (rhs));
   1324  1.1  mrg       else
   1325  1.1  mrg 	{
   1326  1.1  mrg 	  d_mark_addressable (lhs);
   1327  1.1  mrg 	  rhs = TARGET_EXPR_INITIAL (rhs);
   1328  1.1  mrg 	}
   1329  1.1  mrg     }
   1330  1.1  mrg 
   1331  1.1  mrg   tree result = fold_build2_loc (input_location, code,
   1332  1.1  mrg 				 TREE_TYPE (lhs), lhs, rhs);
   1333  1.1  mrg   return compound_expr (init, result);
   1334  1.1  mrg }
   1335  1.1  mrg 
   1336  1.1  mrg /* Build an assignment expression of lvalue LHS from value RHS.  */
   1337  1.1  mrg 
   1338  1.1  mrg tree
   1339  1.1  mrg modify_expr (tree lhs, tree rhs)
   1340  1.1  mrg {
   1341  1.1  mrg   return build_assign (MODIFY_EXPR, lhs, rhs);
   1342  1.1  mrg }
   1343  1.1  mrg 
   1344  1.1  mrg /* Return EXP represented as TYPE.  */
   1345  1.1  mrg 
   1346  1.1  mrg tree
   1347  1.1  mrg build_nop (tree type, tree exp)
   1348  1.1  mrg {
   1349  1.1  mrg   if (error_operand_p (exp))
   1350  1.1  mrg     return exp;
   1351  1.1  mrg 
   1352  1.1  mrg   /* Maybe rewrite: cast(TYPE)(e1, e2) => (e1, cast(TYPE) e2)  */
   1353  1.1  mrg   tree init = stabilize_expr (&exp);
   1354  1.1  mrg   exp = fold_build1_loc (input_location, NOP_EXPR, type, exp);
   1355  1.1  mrg 
   1356  1.1  mrg   return compound_expr (init, exp);
   1357  1.1  mrg }
   1358  1.1  mrg 
   1359  1.1  mrg /* Return EXP to be viewed as being another type TYPE.  Same as build_nop,
   1360  1.1  mrg    except that EXP is type-punned, rather than a straight-forward cast.  */
   1361  1.1  mrg 
   1362  1.1  mrg tree
   1363  1.1  mrg build_vconvert (tree type, tree exp)
   1364  1.1  mrg {
   1365  1.1  mrg   /* Building *(cast(TYPE *)&e1) directly rather then using VIEW_CONVERT_EXPR
   1366  1.1  mrg      makes sure this works for vector-to-array viewing, or if EXP ends up being
   1367  1.1  mrg      used as the LHS of a MODIFY_EXPR.  */
   1368  1.1  mrg   return indirect_ref (type, build_address (exp));
   1369  1.1  mrg }
   1370  1.1  mrg 
   1371  1.1  mrg /* Maybe warn about ARG being an address that can never be null.  */
   1372  1.1  mrg 
   1373  1.1  mrg static void
   1374  1.1  mrg warn_for_null_address (tree arg)
   1375  1.1  mrg {
   1376  1.1  mrg   if (TREE_CODE (arg) == ADDR_EXPR
   1377  1.1  mrg       && decl_with_nonnull_addr_p (TREE_OPERAND (arg, 0)))
   1378  1.1  mrg     warning (OPT_Waddress,
   1379  1.1  mrg 	     "the address of %qD will never be %<null%>",
   1380  1.1  mrg 	     TREE_OPERAND (arg, 0));
   1381  1.1  mrg }
   1382  1.1  mrg 
   1383  1.1  mrg /* Build a boolean ARG0 op ARG1 expression.  */
   1384  1.1  mrg 
   1385  1.1  mrg tree
   1386  1.1  mrg build_boolop (tree_code code, tree arg0, tree arg1)
   1387  1.1  mrg {
   1388  1.1  mrg   /* Aggregate comparisons may get lowered to a call to builtin memcmp,
   1389  1.1  mrg      so need to remove all side effects incase its address is taken.  */
   1390  1.1  mrg   if (AGGREGATE_TYPE_P (TREE_TYPE (arg0)))
   1391  1.1  mrg     arg0 = d_save_expr (arg0);
   1392  1.1  mrg   if (AGGREGATE_TYPE_P (TREE_TYPE (arg1)))
   1393  1.1  mrg     arg1 = d_save_expr (arg1);
   1394  1.1  mrg 
   1395  1.1  mrg   if (VECTOR_TYPE_P (TREE_TYPE (arg0)) && VECTOR_TYPE_P (TREE_TYPE (arg1)))
   1396  1.1  mrg     {
   1397  1.1  mrg       /* Build a vector comparison.
   1398  1.1  mrg 	 VEC_COND_EXPR <e1 op e2, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>; */
   1399  1.1  mrg       tree type = TREE_TYPE (arg0);
   1400  1.1  mrg       tree cmptype = build_same_sized_truth_vector_type (type);
   1401  1.1  mrg       tree cmp = fold_build2_loc (input_location, code, cmptype, arg0, arg1);
   1402  1.1  mrg 
   1403  1.1  mrg       return fold_build3_loc (input_location, VEC_COND_EXPR, type, cmp,
   1404  1.1  mrg 			      build_minus_one_cst (type),
   1405  1.1  mrg 			      build_zero_cst (type));
   1406  1.1  mrg     }
   1407  1.1  mrg 
   1408  1.1  mrg   if (code == EQ_EXPR || code == NE_EXPR)
   1409  1.1  mrg     {
   1410  1.1  mrg       /* Check if comparing the address of a variable to null.  */
   1411  1.1  mrg       if (POINTER_TYPE_P (TREE_TYPE (arg0)) && integer_zerop (arg1))
   1412  1.1  mrg 	warn_for_null_address (arg0);
   1413  1.1  mrg       if (POINTER_TYPE_P (TREE_TYPE (arg1)) && integer_zerop (arg0))
   1414  1.1  mrg 	warn_for_null_address (arg1);
   1415  1.1  mrg     }
   1416  1.1  mrg 
   1417  1.1  mrg   return fold_build2_loc (input_location, code, d_bool_type,
   1418  1.1  mrg 			  arg0, d_convert (TREE_TYPE (arg0), arg1));
   1419  1.1  mrg }
   1420  1.1  mrg 
   1421  1.1  mrg /* Return a COND_EXPR.  ARG0, ARG1, and ARG2 are the three
   1422  1.1  mrg    arguments to the conditional expression.  */
   1423  1.1  mrg 
   1424  1.1  mrg tree
   1425  1.1  mrg build_condition (tree type, tree arg0, tree arg1, tree arg2)
   1426  1.1  mrg {
   1427  1.1  mrg   if (arg1 == void_node)
   1428  1.1  mrg     arg1 = build_empty_stmt (input_location);
   1429  1.1  mrg 
   1430  1.1  mrg   if (arg2 == void_node)
   1431  1.1  mrg     arg2 = build_empty_stmt (input_location);
   1432  1.1  mrg 
   1433  1.1  mrg   return fold_build3_loc (input_location, COND_EXPR,
   1434  1.1  mrg 			  type, arg0, arg1, arg2);
   1435  1.1  mrg }
   1436  1.1  mrg 
   1437  1.1  mrg tree
   1438  1.1  mrg build_vcondition (tree arg0, tree arg1, tree arg2)
   1439  1.1  mrg {
   1440  1.1  mrg   return build_condition (void_type_node, arg0, arg1, arg2);
   1441  1.1  mrg }
   1442  1.1  mrg 
   1443  1.1  mrg /* Build a compound expr to join ARG0 and ARG1 together.  */
   1444  1.1  mrg 
   1445  1.1  mrg tree
   1446  1.1  mrg compound_expr (tree arg0, tree arg1)
   1447  1.1  mrg {
   1448  1.1  mrg   if (arg1 == NULL_TREE)
   1449  1.1  mrg     return arg0;
   1450  1.1  mrg 
   1451  1.1  mrg   if (arg0 == NULL_TREE || !TREE_SIDE_EFFECTS (arg0))
   1452  1.1  mrg     return arg1;
   1453  1.1  mrg 
   1454  1.1  mrg   if (TREE_CODE (arg1) == TARGET_EXPR)
   1455  1.1  mrg     {
   1456  1.1  mrg       /* If the rhs is a TARGET_EXPR, then build the compound expression
   1457  1.1  mrg 	 inside the target_expr's initializer.  This helps the compiler
   1458  1.1  mrg 	 to eliminate unnecessary temporaries.  */
   1459  1.1  mrg       tree init = compound_expr (arg0, TARGET_EXPR_INITIAL (arg1));
   1460  1.1  mrg       TARGET_EXPR_INITIAL (arg1) = init;
   1461  1.1  mrg 
   1462  1.1  mrg       return arg1;
   1463  1.1  mrg     }
   1464  1.1  mrg 
   1465  1.1  mrg   return fold_build2_loc (input_location, COMPOUND_EXPR,
   1466  1.1  mrg 			  TREE_TYPE (arg1), arg0, arg1);
   1467  1.1  mrg }
   1468  1.1  mrg 
   1469  1.1  mrg /* Build a return expression.  */
   1470  1.1  mrg 
   1471  1.1  mrg tree
   1472  1.1  mrg return_expr (tree ret)
   1473  1.1  mrg {
   1474  1.1  mrg   return fold_build1_loc (input_location, RETURN_EXPR,
   1475  1.1  mrg 			  void_type_node, ret);
   1476  1.1  mrg }
   1477  1.1  mrg 
   1478  1.1  mrg /* Return the product of ARG0 and ARG1 as a size_type_node.  */
   1479  1.1  mrg 
   1480  1.1  mrg tree
   1481  1.1  mrg size_mult_expr (tree arg0, tree arg1)
   1482  1.1  mrg {
   1483  1.1  mrg   return fold_build2_loc (input_location, MULT_EXPR, size_type_node,
   1484  1.1  mrg 			  d_convert (size_type_node, arg0),
   1485  1.1  mrg 			  d_convert (size_type_node, arg1));
   1486  1.1  mrg 
   1487  1.1  mrg }
   1488  1.1  mrg 
   1489  1.1  mrg /* Return the real part of CE, which should be a complex expression.  */
   1490  1.1  mrg 
   1491  1.1  mrg tree
   1492  1.1  mrg real_part (tree ce)
   1493  1.1  mrg {
   1494  1.1  mrg   return fold_build1_loc (input_location, REALPART_EXPR,
   1495  1.1  mrg 			  TREE_TYPE (TREE_TYPE (ce)), ce);
   1496  1.1  mrg }
   1497  1.1  mrg 
   1498  1.1  mrg /* Return the imaginary part of CE, which should be a complex expression.  */
   1499  1.1  mrg 
   1500  1.1  mrg tree
   1501  1.1  mrg imaginary_part (tree ce)
   1502  1.1  mrg {
   1503  1.1  mrg   return fold_build1_loc (input_location, IMAGPART_EXPR,
   1504  1.1  mrg 			  TREE_TYPE (TREE_TYPE (ce)), ce);
   1505  1.1  mrg }
   1506  1.1  mrg 
   1507  1.1  mrg /* Build a complex expression of type TYPE using RE and IM.  */
   1508  1.1  mrg 
   1509  1.1  mrg tree
   1510  1.1  mrg complex_expr (tree type, tree re, tree im)
   1511  1.1  mrg {
   1512  1.1  mrg   return fold_build2_loc (input_location, COMPLEX_EXPR,
   1513  1.1  mrg 			  type, re, im);
   1514  1.1  mrg }
   1515  1.1  mrg 
   1516  1.1  mrg /* Cast EXP (which should be a pointer) to TYPE* and then indirect.
   1517  1.1  mrg    The back-end requires this cast in many cases.  */
   1518  1.1  mrg 
   1519  1.1  mrg tree
   1520  1.1  mrg indirect_ref (tree type, tree exp)
   1521  1.1  mrg {
   1522  1.1  mrg   if (error_operand_p (exp))
   1523  1.1  mrg     return exp;
   1524  1.1  mrg 
   1525  1.1  mrg   /* Maybe rewrite: *(e1, e2) => (e1, *e2)  */
   1526  1.1  mrg   tree init = stabilize_expr (&exp);
   1527  1.1  mrg 
   1528  1.1  mrg   if (TREE_CODE (TREE_TYPE (exp)) == REFERENCE_TYPE)
   1529  1.1  mrg     exp = fold_build1 (INDIRECT_REF, type, exp);
   1530  1.1  mrg   else
   1531  1.1  mrg     {
   1532  1.1  mrg       exp = build_nop (build_pointer_type (type), exp);
   1533  1.1  mrg       exp = build_deref (exp);
   1534  1.1  mrg     }
   1535  1.1  mrg 
   1536  1.1  mrg   return compound_expr (init, exp);
   1537  1.1  mrg }
   1538  1.1  mrg 
   1539  1.1  mrg /* Returns indirect reference of EXP, which must be a pointer type.  */
   1540  1.1  mrg 
   1541  1.1  mrg tree
   1542  1.1  mrg build_deref (tree exp)
   1543  1.1  mrg {
   1544  1.1  mrg   if (error_operand_p (exp))
   1545  1.1  mrg     return exp;
   1546  1.1  mrg 
   1547  1.1  mrg   /* Maybe rewrite: *(e1, e2) => (e1, *e2)  */
   1548  1.1  mrg   tree init = stabilize_expr (&exp);
   1549  1.1  mrg 
   1550  1.1  mrg   gcc_assert (POINTER_TYPE_P (TREE_TYPE (exp)));
   1551  1.1  mrg 
   1552  1.1  mrg   if (TREE_CODE (exp) == ADDR_EXPR)
   1553  1.1  mrg     exp = TREE_OPERAND (exp, 0);
   1554  1.1  mrg   else
   1555  1.1  mrg     exp = build_fold_indirect_ref (exp);
   1556  1.1  mrg 
   1557  1.1  mrg   return compound_expr (init, exp);
   1558  1.1  mrg }
   1559  1.1  mrg 
   1560  1.1  mrg /* Builds pointer offset expression PTR[INDEX].  */
   1561  1.1  mrg 
   1562  1.1  mrg tree
   1563  1.1  mrg build_array_index (tree ptr, tree index)
   1564  1.1  mrg {
   1565  1.1  mrg   if (error_operand_p (ptr) || error_operand_p (index))
   1566  1.1  mrg     return error_mark_node;
   1567  1.1  mrg 
   1568  1.1  mrg   tree ptr_type = TREE_TYPE (ptr);
   1569  1.1  mrg   tree target_type = TREE_TYPE (ptr_type);
   1570  1.1  mrg 
   1571  1.1  mrg   tree type = lang_hooks.types.type_for_size (TYPE_PRECISION (sizetype),
   1572  1.1  mrg 					      TYPE_UNSIGNED (sizetype));
   1573  1.1  mrg 
   1574  1.1  mrg   /* Array element size.  */
   1575  1.1  mrg   tree size_exp = size_in_bytes (target_type);
   1576  1.1  mrg 
   1577  1.1  mrg   if (integer_zerop (size_exp))
   1578  1.1  mrg     {
   1579  1.1  mrg       /* Test for array of void.  */
   1580  1.1  mrg       if (TYPE_MODE (target_type) == TYPE_MODE (void_type_node))
   1581  1.1  mrg 	index = fold_convert (type, index);
   1582  1.1  mrg       else
   1583  1.1  mrg 	{
   1584  1.1  mrg 	  /* Should catch this earlier.  */
   1585  1.1  mrg 	  error ("invalid use of incomplete type %qD", TYPE_NAME (target_type));
   1586  1.1  mrg 	  ptr_type = error_mark_node;
   1587  1.1  mrg 	}
   1588  1.1  mrg     }
   1589  1.1  mrg   else if (integer_onep (size_exp))
   1590  1.1  mrg     {
   1591  1.1  mrg       /* Array of bytes -- No need to multiply.  */
   1592  1.1  mrg       index = fold_convert (type, index);
   1593  1.1  mrg     }
   1594  1.1  mrg   else
   1595  1.1  mrg     {
   1596  1.1  mrg       index = d_convert (type, index);
   1597  1.1  mrg       index = fold_build2 (MULT_EXPR, TREE_TYPE (index),
   1598  1.1  mrg 			   index, d_convert (TREE_TYPE (index), size_exp));
   1599  1.1  mrg       index = fold_convert (type, index);
   1600  1.1  mrg     }
   1601  1.1  mrg 
   1602  1.1  mrg   if (integer_zerop (index))
   1603  1.1  mrg     return ptr;
   1604  1.1  mrg 
   1605  1.1  mrg   return fold_build2 (POINTER_PLUS_EXPR, ptr_type, ptr, index);
   1606  1.1  mrg }
   1607  1.1  mrg 
   1608  1.1  mrg /* Builds pointer offset expression *(PTR OP OFFSET)
   1609  1.1  mrg    OP could be a plus or minus expression.  */
   1610  1.1  mrg 
   1611  1.1  mrg tree
   1612  1.1  mrg build_offset_op (tree_code op, tree ptr, tree offset)
   1613  1.1  mrg {
   1614  1.1  mrg   gcc_assert (op == MINUS_EXPR || op == PLUS_EXPR);
   1615  1.1  mrg 
   1616  1.1  mrg   tree type = lang_hooks.types.type_for_size (TYPE_PRECISION (sizetype),
   1617  1.1  mrg 					      TYPE_UNSIGNED (sizetype));
   1618  1.1  mrg   offset = fold_convert (type, offset);
   1619  1.1  mrg 
   1620  1.1  mrg   if (op == MINUS_EXPR)
   1621  1.1  mrg     offset = fold_build1 (NEGATE_EXPR, type, offset);
   1622  1.1  mrg 
   1623  1.1  mrg   return fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr, offset);
   1624  1.1  mrg }
   1625  1.1  mrg 
   1626  1.1  mrg /* Builds pointer offset expression *(PTR + OFFSET).  */
   1627  1.1  mrg 
   1628  1.1  mrg tree
   1629  1.1  mrg build_offset (tree ptr, tree offset)
   1630  1.1  mrg {
   1631  1.1  mrg   return build_offset_op (PLUS_EXPR, ptr, offset);
   1632  1.1  mrg }
   1633  1.1  mrg 
   1634  1.1  mrg tree
   1635  1.1  mrg build_memref (tree type, tree ptr, tree offset)
   1636  1.1  mrg {
   1637  1.1  mrg   return fold_build2 (MEM_REF, type, ptr, fold_convert (type, offset));
   1638  1.1  mrg }
   1639  1.1  mrg 
   1640  1.1  mrg /* Create a tree node to set multiple elements to a single value.  */
   1641  1.1  mrg 
   1642  1.1  mrg tree
   1643  1.1  mrg build_array_set (tree ptr, tree length, tree value)
   1644  1.1  mrg {
   1645  1.1  mrg   tree ptrtype = TREE_TYPE (ptr);
   1646  1.1  mrg   tree lentype = TREE_TYPE (length);
   1647  1.1  mrg 
   1648  1.1  mrg   push_binding_level (level_block);
   1649  1.1  mrg   push_stmt_list ();
   1650  1.1  mrg 
   1651  1.1  mrg   /* Build temporary locals for length and ptr, and maybe value.  */
   1652  1.1  mrg   tree t = build_local_temp (size_type_node);
   1653  1.1  mrg   add_stmt (build_assign (INIT_EXPR, t, length));
   1654  1.1  mrg   length = t;
   1655  1.1  mrg 
   1656  1.1  mrg   t = build_local_temp (ptrtype);
   1657  1.1  mrg   add_stmt (build_assign (INIT_EXPR, t, ptr));
   1658  1.1  mrg   ptr = t;
   1659  1.1  mrg 
   1660  1.1  mrg   if (TREE_SIDE_EFFECTS (value))
   1661  1.1  mrg     {
   1662  1.1  mrg       t = build_local_temp (TREE_TYPE (value));
   1663  1.1  mrg       add_stmt (build_assign (INIT_EXPR, t, value));
   1664  1.1  mrg       value = t;
   1665  1.1  mrg     }
   1666  1.1  mrg 
   1667  1.1  mrg   /* Build loop to initialize { .length=length, .ptr=ptr } with value.  */
   1668  1.1  mrg   push_stmt_list ();
   1669  1.1  mrg 
   1670  1.1  mrg   /* Exit logic for the loop.
   1671  1.1  mrg 	if (length == 0) break;  */
   1672  1.1  mrg   t = build_boolop (EQ_EXPR, length, d_convert (lentype, integer_zero_node));
   1673  1.1  mrg   t = build1 (EXIT_EXPR, void_type_node, t);
   1674  1.1  mrg   add_stmt (t);
   1675  1.1  mrg 
   1676  1.1  mrg   /* Assign value to the current pointer position.
   1677  1.1  mrg 	*ptr = value;  */
   1678  1.1  mrg   t = modify_expr (build_deref (ptr), value);
   1679  1.1  mrg   add_stmt (t);
   1680  1.1  mrg 
   1681  1.1  mrg   /* Move pointer to next element position.
   1682  1.1  mrg 	ptr++;  */
   1683  1.1  mrg   tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptrtype));
   1684  1.1  mrg   t = build2 (POSTINCREMENT_EXPR, ptrtype, ptr, d_convert (ptrtype, size));
   1685  1.1  mrg   add_stmt (t);
   1686  1.1  mrg 
   1687  1.1  mrg   /* Decrease loop counter.
   1688  1.1  mrg 	length -= 1;  */
   1689  1.1  mrg   t = build2 (POSTDECREMENT_EXPR, lentype, length,
   1690  1.1  mrg 	      d_convert (lentype, integer_one_node));
   1691  1.1  mrg   add_stmt (t);
   1692  1.1  mrg 
   1693  1.1  mrg   /* Pop statements and finish loop.  */
   1694  1.1  mrg   tree loop_body = pop_stmt_list ();
   1695  1.1  mrg   add_stmt (build1 (LOOP_EXPR, void_type_node, loop_body));
   1696  1.1  mrg 
   1697  1.1  mrg   /* Wrap it up into a bind expression.  */
   1698  1.1  mrg   tree stmt_list = pop_stmt_list ();
   1699  1.1  mrg   tree block = pop_binding_level ();
   1700  1.1  mrg 
   1701  1.1  mrg   return build3 (BIND_EXPR, void_type_node,
   1702  1.1  mrg 		 BLOCK_VARS (block), stmt_list, block);
   1703  1.1  mrg }
   1704  1.1  mrg 
   1705  1.1  mrg 
   1706  1.1  mrg /* Build an array of type TYPE where all the elements are VAL.  */
   1707  1.1  mrg 
   1708  1.1  mrg tree
   1709  1.1  mrg build_array_from_val (Type *type, tree val)
   1710  1.1  mrg {
   1711  1.1  mrg   gcc_assert (type->ty == Tsarray);
   1712  1.1  mrg 
   1713  1.1  mrg   tree etype = build_ctype (type->nextOf ());
   1714  1.1  mrg 
   1715  1.1  mrg   /* Initializing a multidimensional array.  */
   1716  1.1  mrg   if (TREE_CODE (etype) == ARRAY_TYPE && TREE_TYPE (val) != etype)
   1717  1.1  mrg     val = build_array_from_val (type->nextOf (), val);
   1718  1.1  mrg 
   1719  1.1  mrg   size_t dims = ((TypeSArray *) type)->dim->toInteger ();
   1720  1.1  mrg   vec<constructor_elt, va_gc> *elms = NULL;
   1721  1.1  mrg   vec_safe_reserve (elms, dims);
   1722  1.1  mrg 
   1723  1.1  mrg   val = d_convert (etype, val);
   1724  1.1  mrg 
   1725  1.1  mrg   for (size_t i = 0; i < dims; i++)
   1726  1.1  mrg     CONSTRUCTOR_APPEND_ELT (elms, size_int (i), val);
   1727  1.1  mrg 
   1728  1.1  mrg   return build_constructor (build_ctype (type), elms);
   1729  1.1  mrg }
   1730  1.1  mrg 
   1731  1.1  mrg /* Implicitly converts void* T to byte* as D allows { void[] a; &a[3]; }  */
   1732  1.1  mrg 
   1733  1.1  mrg tree
   1734  1.1  mrg void_okay_p (tree t)
   1735  1.1  mrg {
   1736  1.1  mrg   tree type = TREE_TYPE (t);
   1737  1.1  mrg 
   1738  1.1  mrg   if (VOID_TYPE_P (TREE_TYPE (type)))
   1739  1.1  mrg     {
   1740  1.1  mrg       tree totype = build_ctype (Type::tuns8->pointerTo ());
   1741  1.1  mrg       return fold_convert (totype, t);
   1742  1.1  mrg     }
   1743  1.1  mrg 
   1744  1.1  mrg   return t;
   1745  1.1  mrg }
   1746  1.1  mrg 
   1747  1.1  mrg /* Builds a bounds condition checking that INDEX is between 0 and LEN.
   1748  1.1  mrg    The condition returns the INDEX if true, or throws a RangeError.
   1749  1.1  mrg    If INCLUSIVE, we allow INDEX == LEN to return true also.  */
   1750  1.1  mrg 
   1751  1.1  mrg tree
   1752  1.1  mrg build_bounds_condition (const Loc& loc, tree index, tree len, bool inclusive)
   1753  1.1  mrg {
   1754  1.1  mrg   if (!array_bounds_check ())
   1755  1.1  mrg     return index;
   1756  1.1  mrg 
   1757  1.1  mrg   /* Prevent multiple evaluations of the index.  */
   1758  1.1  mrg   index = d_save_expr (index);
   1759  1.1  mrg 
   1760  1.1  mrg   /* Generate INDEX >= LEN && throw RangeError.
   1761  1.1  mrg      No need to check whether INDEX >= 0 as the front-end should
   1762  1.1  mrg      have already taken care of implicit casts to unsigned.  */
   1763  1.1  mrg   tree condition = fold_build2 (inclusive ? GT_EXPR : GE_EXPR,
   1764  1.1  mrg 				d_bool_type, index, len);
   1765  1.1  mrg   /* Terminate the program with a trap if no D runtime present.  */
   1766  1.1  mrg   tree boundserr = (global.params.checkAction == CHECKACTION_D)
   1767  1.1  mrg     ? d_assert_call (loc, LIBCALL_ARRAY_BOUNDS)
   1768  1.1  mrg     : build_call_expr (builtin_decl_explicit (BUILT_IN_TRAP), 0);
   1769  1.1  mrg 
   1770  1.1  mrg   return build_condition (TREE_TYPE (index), condition, boundserr, index);
   1771  1.1  mrg }
   1772  1.1  mrg 
   1773  1.1  mrg /* Returns TRUE if array bounds checking code generation is turned on.  */
   1774  1.1  mrg 
   1775  1.1  mrg bool
   1776  1.1  mrg array_bounds_check (void)
   1777  1.1  mrg {
   1778  1.1  mrg   FuncDeclaration *fd;
   1779  1.1  mrg 
   1780  1.1  mrg   switch (global.params.useArrayBounds)
   1781  1.1  mrg     {
   1782  1.1  mrg     case BOUNDSCHECKoff:
   1783  1.1  mrg       return false;
   1784  1.1  mrg 
   1785  1.1  mrg     case BOUNDSCHECKon:
   1786  1.1  mrg       return true;
   1787  1.1  mrg 
   1788  1.1  mrg     case BOUNDSCHECKsafeonly:
   1789  1.1  mrg       /* For D2 safe functions only.  */
   1790  1.1  mrg       fd = d_function_chain->function;
   1791  1.1  mrg       if (fd && fd->type->ty == Tfunction)
   1792  1.1  mrg 	{
   1793  1.1  mrg 	  TypeFunction *tf = (TypeFunction *) fd->type;
   1794  1.1  mrg 	  if (tf->trust == TRUSTsafe)
   1795  1.1  mrg 	    return true;
   1796  1.1  mrg 	}
   1797  1.1  mrg       return false;
   1798  1.1  mrg 
   1799  1.1  mrg     default:
   1800  1.1  mrg       gcc_unreachable ();
   1801  1.1  mrg     }
   1802  1.1  mrg }
   1803  1.1  mrg 
   1804  1.1  mrg /* Return an undeclared local temporary of type TYPE
   1805  1.1  mrg    for use with BIND_EXPR.  */
   1806  1.1  mrg 
   1807  1.1  mrg tree
   1808  1.1  mrg create_temporary_var (tree type)
   1809  1.1  mrg {
   1810  1.1  mrg   tree decl = build_decl (input_location, VAR_DECL, NULL_TREE, type);
   1811  1.1  mrg 
   1812  1.1  mrg   DECL_CONTEXT (decl) = current_function_decl;
   1813  1.1  mrg   DECL_ARTIFICIAL (decl) = 1;
   1814  1.1  mrg   DECL_IGNORED_P (decl) = 1;
   1815  1.1  mrg   layout_decl (decl, 0);
   1816  1.1  mrg 
   1817  1.1  mrg   return decl;
   1818  1.1  mrg }
   1819  1.1  mrg 
   1820  1.1  mrg /* Return an undeclared local temporary OUT_VAR initialized
   1821  1.1  mrg    with result of expression EXP.  */
   1822  1.1  mrg 
   1823  1.1  mrg tree
   1824  1.1  mrg maybe_temporary_var (tree exp, tree *out_var)
   1825  1.1  mrg {
   1826  1.1  mrg   tree t = exp;
   1827  1.1  mrg 
   1828  1.1  mrg   /* Get the base component.  */
   1829  1.1  mrg   while (TREE_CODE (t) == COMPONENT_REF)
   1830  1.1  mrg     t = TREE_OPERAND (t, 0);
   1831  1.1  mrg 
   1832  1.1  mrg   if (!DECL_P (t) && !REFERENCE_CLASS_P (t))
   1833  1.1  mrg     {
   1834  1.1  mrg       *out_var = create_temporary_var (TREE_TYPE (exp));
   1835  1.1  mrg       DECL_INITIAL (*out_var) = exp;
   1836  1.1  mrg       return *out_var;
   1837  1.1  mrg     }
   1838  1.1  mrg   else
   1839  1.1  mrg     {
   1840  1.1  mrg       *out_var = NULL_TREE;
   1841  1.1  mrg       return exp;
   1842  1.1  mrg     }
   1843  1.1  mrg }
   1844  1.1  mrg 
   1845  1.1  mrg /* Builds a BIND_EXPR around BODY for the variables VAR_CHAIN.  */
   1846  1.1  mrg 
   1847  1.1  mrg tree
   1848  1.1  mrg bind_expr (tree var_chain, tree body)
   1849  1.1  mrg {
   1850  1.1  mrg   /* Only handles one var.  */
   1851  1.1  mrg   gcc_assert (TREE_CHAIN (var_chain) == NULL_TREE);
   1852  1.1  mrg 
   1853  1.1  mrg   if (DECL_INITIAL (var_chain))
   1854  1.1  mrg     {
   1855  1.1  mrg       tree ini = build_assign (INIT_EXPR, var_chain, DECL_INITIAL (var_chain));
   1856  1.1  mrg       DECL_INITIAL (var_chain) = NULL_TREE;
   1857  1.1  mrg       body = compound_expr (ini, body);
   1858  1.1  mrg     }
   1859  1.1  mrg 
   1860  1.1  mrg   return d_save_expr (build3 (BIND_EXPR, TREE_TYPE (body),
   1861  1.1  mrg 			      var_chain, body, NULL_TREE));
   1862  1.1  mrg }
   1863  1.1  mrg 
   1864  1.1  mrg /* Returns the TypeFunction class for Type T.
   1865  1.1  mrg    Assumes T is already ->toBasetype().  */
   1866  1.1  mrg 
   1867  1.1  mrg TypeFunction *
   1868  1.1  mrg get_function_type (Type *t)
   1869  1.1  mrg {
   1870  1.1  mrg   TypeFunction *tf = NULL;
   1871  1.1  mrg   if (t->ty == Tpointer)
   1872  1.1  mrg     t = t->nextOf ()->toBasetype ();
   1873  1.1  mrg   if (t->ty == Tfunction)
   1874  1.1  mrg     tf = (TypeFunction *) t;
   1875  1.1  mrg   else if (t->ty == Tdelegate)
   1876  1.1  mrg     tf = (TypeFunction *) ((TypeDelegate *) t)->next;
   1877  1.1  mrg   return tf;
   1878  1.1  mrg }
   1879  1.1  mrg 
   1880  1.1  mrg /* Returns TRUE if CALLEE is a plain nested function outside the scope of
   1881  1.1  mrg    CALLER.  In which case, CALLEE is being called through an alias that was
   1882  1.1  mrg    passed to CALLER.  */
   1883  1.1  mrg 
   1884  1.1  mrg bool
   1885  1.1  mrg call_by_alias_p (FuncDeclaration *caller, FuncDeclaration *callee)
   1886  1.1  mrg {
   1887  1.1  mrg   if (!callee->isNested ())
   1888  1.1  mrg     return false;
   1889  1.1  mrg 
   1890  1.1  mrg   if (caller->toParent () == callee->toParent ())
   1891  1.1  mrg     return false;
   1892  1.1  mrg 
   1893  1.1  mrg   Dsymbol *dsym = callee;
   1894  1.1  mrg 
   1895  1.1  mrg   while (dsym)
   1896  1.1  mrg     {
   1897  1.1  mrg       if (dsym->isTemplateInstance ())
   1898  1.1  mrg 	return false;
   1899  1.1  mrg       else if (dsym->isFuncDeclaration () == caller)
   1900  1.1  mrg 	return false;
   1901  1.1  mrg       dsym = dsym->toParent ();
   1902  1.1  mrg     }
   1903  1.1  mrg 
   1904  1.1  mrg   return true;
   1905  1.1  mrg }
   1906  1.1  mrg 
   1907  1.1  mrg /* Entry point for call routines.  Builds a function call to FD.
   1908  1.1  mrg    OBJECT is the 'this' reference passed and ARGS are the arguments to FD.  */
   1909  1.1  mrg 
   1910  1.1  mrg tree
   1911  1.1  mrg d_build_call_expr (FuncDeclaration *fd, tree object, Expressions *arguments)
   1912  1.1  mrg {
   1913  1.1  mrg   return d_build_call (get_function_type (fd->type),
   1914  1.1  mrg 		       build_address (get_symbol_decl (fd)), object, arguments);
   1915  1.1  mrg }
   1916  1.1  mrg 
   1917  1.1  mrg /* Builds a CALL_EXPR of type TF to CALLABLE.  OBJECT holds the 'this' pointer,
   1918  1.1  mrg    ARGUMENTS are evaluated in left to right order, saved and promoted
   1919  1.1  mrg    before passing.  */
   1920  1.1  mrg 
   1921  1.1  mrg tree
   1922  1.1  mrg d_build_call (TypeFunction *tf, tree callable, tree object,
   1923  1.1  mrg 	      Expressions *arguments)
   1924  1.1  mrg {
   1925  1.1  mrg   tree ctype = TREE_TYPE (callable);
   1926  1.1  mrg   tree callee = callable;
   1927  1.1  mrg 
   1928  1.1  mrg   if (POINTER_TYPE_P (ctype))
   1929  1.1  mrg     ctype = TREE_TYPE (ctype);
   1930  1.1  mrg   else
   1931  1.1  mrg     callee = build_address (callable);
   1932  1.1  mrg 
   1933  1.1  mrg   gcc_assert (FUNC_OR_METHOD_TYPE_P (ctype));
   1934  1.1  mrg   gcc_assert (tf != NULL);
   1935  1.1  mrg   gcc_assert (tf->ty == Tfunction);
   1936  1.1  mrg 
   1937  1.1  mrg   if (TREE_CODE (ctype) != FUNCTION_TYPE && object == NULL_TREE)
   1938  1.1  mrg     {
   1939  1.1  mrg       /* Front-end apparently doesn't check this.  */
   1940  1.1  mrg       if (TREE_CODE (callable) == FUNCTION_DECL)
   1941  1.1  mrg 	{
   1942  1.1  mrg 	  error ("need %<this%> to access member %qE", DECL_NAME (callable));
   1943  1.1  mrg 	  return error_mark_node;
   1944  1.1  mrg 	}
   1945  1.1  mrg 
   1946  1.1  mrg       /* Probably an internal error.  */
   1947  1.1  mrg       gcc_unreachable ();
   1948  1.1  mrg     }
   1949  1.1  mrg 
   1950  1.1  mrg   /* Build the argument list for the call.  */
   1951  1.1  mrg   vec<tree, va_gc> *args = NULL;
   1952  1.1  mrg   tree saved_args = NULL_TREE;
   1953  1.1  mrg 
   1954  1.1  mrg   /* If this is a delegate call or a nested function being called as
   1955  1.1  mrg      a delegate, the object should not be NULL.  */
   1956  1.1  mrg   if (object != NULL_TREE)
   1957  1.1  mrg     vec_safe_push (args, object);
   1958  1.1  mrg 
   1959  1.1  mrg   if (arguments)
   1960  1.1  mrg     {
   1961  1.1  mrg       /* First pass, evaluated expanded tuples in function arguments.  */
   1962  1.1  mrg       for (size_t i = 0; i < arguments->dim; ++i)
   1963  1.1  mrg 	{
   1964  1.1  mrg 	Lagain:
   1965  1.1  mrg 	  Expression *arg = (*arguments)[i];
   1966  1.1  mrg 	  gcc_assert (arg->op != TOKtuple);
   1967  1.1  mrg 
   1968  1.1  mrg 	  if (arg->op == TOKcomma)
   1969  1.1  mrg 	    {
   1970  1.1  mrg 	      CommaExp *ce = (CommaExp *) arg;
   1971  1.1  mrg 	      tree tce = build_expr (ce->e1);
   1972  1.1  mrg 	      saved_args = compound_expr (saved_args, tce);
   1973  1.1  mrg 	      (*arguments)[i] = ce->e2;
   1974  1.1  mrg 	      goto Lagain;
   1975  1.1  mrg 	    }
   1976  1.1  mrg 	}
   1977  1.1  mrg 
   1978  1.1  mrg       size_t nparams = Parameter::dim (tf->parameters);
   1979  1.1  mrg       /* if _arguments[] is the first argument.  */
   1980  1.1  mrg       size_t varargs = (tf->linkage == LINKd && tf->varargs == 1);
   1981  1.1  mrg 
   1982  1.1  mrg       /* Assumes arguments->dim <= formal_args->dim if (!tf->varargs).  */
   1983  1.1  mrg       for (size_t i = 0; i < arguments->dim; ++i)
   1984  1.1  mrg 	{
   1985  1.1  mrg 	  Expression *arg = (*arguments)[i];
   1986  1.1  mrg 	  tree targ = build_expr (arg);
   1987  1.1  mrg 
   1988  1.1  mrg 	  if (i - varargs < nparams && i >= varargs)
   1989  1.1  mrg 	    {
   1990  1.1  mrg 	      /* Actual arguments for declared formal arguments.  */
   1991  1.1  mrg 	      Parameter *parg = Parameter::getNth (tf->parameters, i - varargs);
   1992  1.1  mrg 	      targ = convert_for_argument (targ, parg);
   1993  1.1  mrg 	    }
   1994  1.1  mrg 
   1995  1.1  mrg 	  /* Don't pass empty aggregates by value.  */
   1996  1.1  mrg 	  if (empty_aggregate_p (TREE_TYPE (targ)) && !TREE_ADDRESSABLE (targ)
   1997  1.1  mrg 	      && TREE_CODE (targ) != CONSTRUCTOR)
   1998  1.1  mrg 	    {
   1999  1.1  mrg 	      tree t = build_constructor (TREE_TYPE (targ), NULL);
   2000  1.1  mrg 	      targ = build2 (COMPOUND_EXPR, TREE_TYPE (t), targ, t);
   2001  1.1  mrg 	    }
   2002  1.1  mrg 
   2003  1.1  mrg 	  vec_safe_push (args, targ);
   2004  1.1  mrg 	}
   2005  1.1  mrg     }
   2006  1.1  mrg 
   2007  1.1  mrg   /* Evaluate the callee before calling it.  */
   2008  1.1  mrg   if (TREE_SIDE_EFFECTS (callee))
   2009  1.1  mrg     {
   2010  1.1  mrg       callee = d_save_expr (callee);
   2011  1.1  mrg       saved_args = compound_expr (callee, saved_args);
   2012  1.1  mrg     }
   2013  1.1  mrg 
   2014  1.1  mrg   tree result = build_call_vec (TREE_TYPE (ctype), callee, args);
   2015  1.1  mrg 
   2016  1.1  mrg   /* Enforce left to right evaluation.  */
   2017  1.1  mrg   if (tf->linkage == LINKd)
   2018  1.1  mrg     CALL_EXPR_ARGS_ORDERED (result) = 1;
   2019  1.1  mrg 
   2020  1.1  mrg   result = maybe_expand_intrinsic (result);
   2021  1.1  mrg 
   2022  1.1  mrg   /* Return the value in a temporary slot so that it can be evaluated
   2023  1.1  mrg      multiple times by the caller.  */
   2024  1.1  mrg   if (TREE_CODE (result) == CALL_EXPR
   2025  1.1  mrg       && AGGREGATE_TYPE_P (TREE_TYPE (result))
   2026  1.1  mrg       && TREE_ADDRESSABLE (TREE_TYPE (result)))
   2027  1.1  mrg     {
   2028  1.1  mrg       CALL_EXPR_RETURN_SLOT_OPT (result) = true;
   2029  1.1  mrg       result = force_target_expr (result);
   2030  1.1  mrg     }
   2031  1.1  mrg 
   2032  1.1  mrg   return compound_expr (saved_args, result);
   2033  1.1  mrg }
   2034  1.1  mrg 
   2035  1.1  mrg /* Builds a call to AssertError or AssertErrorMsg.  */
   2036  1.1  mrg 
   2037  1.1  mrg tree
   2038  1.1  mrg d_assert_call (const Loc& loc, libcall_fn libcall, tree msg)
   2039  1.1  mrg {
   2040  1.1  mrg   tree file;
   2041  1.1  mrg   tree line = size_int (loc.linnum);
   2042  1.1  mrg 
   2043  1.1  mrg   /* File location is passed as a D string.  */
   2044  1.1  mrg   if (loc.filename)
   2045  1.1  mrg     {
   2046  1.1  mrg       unsigned len = strlen (loc.filename);
   2047  1.1  mrg       tree str = build_string (len, loc.filename);
   2048  1.1  mrg       TREE_TYPE (str) = make_array_type (Type::tchar, len);
   2049  1.1  mrg 
   2050  1.1  mrg       file = d_array_value (build_ctype (Type::tchar->arrayOf ()),
   2051  1.1  mrg 			    size_int (len), build_address (str));
   2052  1.1  mrg     }
   2053  1.1  mrg   else
   2054  1.1  mrg     file = null_array_node;
   2055  1.1  mrg 
   2056  1.1  mrg   if (msg != NULL)
   2057  1.1  mrg     return build_libcall (libcall, Type::tvoid, 3, msg, file, line);
   2058  1.1  mrg   else
   2059  1.1  mrg     return build_libcall (libcall, Type::tvoid, 2, file, line);
   2060  1.1  mrg }
   2061  1.1  mrg 
   2062  1.1  mrg /* Build and return the correct call to fmod depending on TYPE.
   2063  1.1  mrg    ARG0 and ARG1 are the arguments pass to the function.  */
   2064  1.1  mrg 
   2065  1.1  mrg tree
   2066  1.1  mrg build_float_modulus (tree type, tree arg0, tree arg1)
   2067  1.1  mrg {
   2068  1.1  mrg   tree fmodfn = NULL_TREE;
   2069  1.1  mrg   tree basetype = type;
   2070  1.1  mrg 
   2071  1.1  mrg   if (COMPLEX_FLOAT_TYPE_P (basetype))
   2072  1.1  mrg     basetype = TREE_TYPE (basetype);
   2073  1.1  mrg 
   2074  1.1  mrg   if (TYPE_MAIN_VARIANT (basetype) == double_type_node
   2075  1.1  mrg       || TYPE_MAIN_VARIANT (basetype) == idouble_type_node)
   2076  1.1  mrg     fmodfn = builtin_decl_explicit (BUILT_IN_FMOD);
   2077  1.1  mrg   else if (TYPE_MAIN_VARIANT (basetype) == float_type_node
   2078  1.1  mrg 	   || TYPE_MAIN_VARIANT (basetype) == ifloat_type_node)
   2079  1.1  mrg     fmodfn = builtin_decl_explicit (BUILT_IN_FMODF);
   2080  1.1  mrg   else if (TYPE_MAIN_VARIANT (basetype) == long_double_type_node
   2081  1.1  mrg 	   || TYPE_MAIN_VARIANT (basetype) == ireal_type_node)
   2082  1.1  mrg     fmodfn = builtin_decl_explicit (BUILT_IN_FMODL);
   2083  1.1  mrg 
   2084  1.1  mrg   if (!fmodfn)
   2085  1.1  mrg     {
   2086  1.1  mrg       error ("tried to perform floating-point modulo division on %qT", type);
   2087  1.1  mrg       return error_mark_node;
   2088  1.1  mrg     }
   2089  1.1  mrg 
   2090  1.1  mrg   if (COMPLEX_FLOAT_TYPE_P (type))
   2091  1.1  mrg     {
   2092  1.1  mrg       tree re = build_call_expr (fmodfn, 2, real_part (arg0), arg1);
   2093  1.1  mrg       tree im = build_call_expr (fmodfn, 2, imaginary_part (arg0), arg1);
   2094  1.1  mrg 
   2095  1.1  mrg       return complex_expr (type, re, im);
   2096  1.1  mrg     }
   2097  1.1  mrg 
   2098  1.1  mrg   if (SCALAR_FLOAT_TYPE_P (type))
   2099  1.1  mrg     return build_call_expr (fmodfn, 2, arg0, arg1);
   2100  1.1  mrg 
   2101  1.1  mrg   /* Should have caught this above.  */
   2102  1.1  mrg   gcc_unreachable ();
   2103  1.1  mrg }
   2104  1.1  mrg 
   2105  1.1  mrg /* Build a function type whose first argument is a pointer to BASETYPE,
   2106  1.1  mrg    which is to be used for the 'vthis' context parameter for TYPE.
   2107  1.1  mrg    The base type may be a record for member functions, or a void for
   2108  1.1  mrg    nested functions and delegates.  */
   2109  1.1  mrg 
   2110  1.1  mrg tree
   2111  1.1  mrg build_vthis_function (tree basetype, tree type)
   2112  1.1  mrg {
   2113  1.1  mrg   gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
   2114  1.1  mrg 
   2115  1.1  mrg   tree argtypes = tree_cons (NULL_TREE, build_pointer_type (basetype),
   2116  1.1  mrg 			     TYPE_ARG_TYPES (type));
   2117  1.1  mrg   tree fntype = build_function_type (TREE_TYPE (type), argtypes);
   2118  1.1  mrg 
   2119  1.1  mrg   if (RECORD_OR_UNION_TYPE_P (basetype))
   2120  1.1  mrg     TYPE_METHOD_BASETYPE (fntype) = TYPE_MAIN_VARIANT (basetype);
   2121  1.1  mrg   else
   2122  1.1  mrg     gcc_assert (VOID_TYPE_P (basetype));
   2123  1.1  mrg 
   2124  1.1  mrg   return fntype;
   2125  1.1  mrg }
   2126  1.1  mrg 
   2127  1.1  mrg /* If SYM is a nested function, return the static chain to be
   2128  1.1  mrg    used when calling that function from the current function.
   2129  1.1  mrg 
   2130  1.1  mrg    If SYM is a nested class or struct, return the static chain
   2131  1.1  mrg    to be used when creating an instance of the class from CFUN.  */
   2132  1.1  mrg 
   2133  1.1  mrg tree
   2134  1.1  mrg get_frame_for_symbol (Dsymbol *sym)
   2135  1.1  mrg {
   2136  1.1  mrg   FuncDeclaration *thisfd
   2137  1.1  mrg     = d_function_chain ? d_function_chain->function : NULL;
   2138  1.1  mrg   FuncDeclaration *fd = sym->isFuncDeclaration ();
   2139  1.1  mrg   FuncDeclaration *fdparent = NULL;
   2140  1.1  mrg   FuncDeclaration *fdoverride = NULL;
   2141  1.1  mrg 
   2142  1.1  mrg   if (fd != NULL)
   2143  1.1  mrg     {
   2144  1.1  mrg       /* Check that the nested function is properly defined.  */
   2145  1.1  mrg       if (!fd->fbody)
   2146  1.1  mrg 	{
   2147  1.1  mrg 	  /* Should instead error on line that references 'fd'.  */
   2148  1.1  mrg 	  error_at (make_location_t (fd->loc), "nested function missing body");
   2149  1.1  mrg 	  return null_pointer_node;
   2150  1.1  mrg 	}
   2151  1.1  mrg 
   2152  1.1  mrg       fdparent = fd->toParent2 ()->isFuncDeclaration ();
   2153  1.1  mrg 
   2154  1.1  mrg       /* Special case for __ensure and __require.  */
   2155  1.1  mrg       if ((fd->ident == Identifier::idPool ("__ensure")
   2156  1.1  mrg 	   || fd->ident == Identifier::idPool ("__require"))
   2157  1.1  mrg 	  && fdparent != thisfd)
   2158  1.1  mrg 	{
   2159  1.1  mrg 	  fdoverride = fdparent;
   2160  1.1  mrg 	  fdparent = thisfd;
   2161  1.1  mrg 	}
   2162  1.1  mrg     }
   2163  1.1  mrg   else
   2164  1.1  mrg     {
   2165  1.1  mrg       /* It's a class (or struct).  NewExp codegen has already determined its
   2166  1.1  mrg 	 outer scope is not another class, so it must be a function.  */
   2167  1.1  mrg       while (sym && !sym->isFuncDeclaration ())
   2168  1.1  mrg 	sym = sym->toParent2 ();
   2169  1.1  mrg 
   2170  1.1  mrg       fdparent = (FuncDeclaration *) sym;
   2171  1.1  mrg     }
   2172  1.1  mrg 
   2173  1.1  mrg   /* Not a nested function, there is no frame pointer to pass.  */
   2174  1.1  mrg   if (fdparent == NULL)
   2175  1.1  mrg     {
   2176  1.1  mrg       /* Only delegate literals report as being nested, even if they are in
   2177  1.1  mrg 	 global scope.  */
   2178  1.1  mrg       gcc_assert (fd && fd->isFuncLiteralDeclaration ());
   2179  1.1  mrg       return null_pointer_node;
   2180  1.1  mrg     }
   2181  1.1  mrg 
   2182  1.1  mrg   gcc_assert (thisfd != NULL);
   2183  1.1  mrg 
   2184  1.1  mrg   if (thisfd != fdparent)
   2185  1.1  mrg     {
   2186  1.1  mrg       /* If no frame pointer for this function.  */
   2187  1.1  mrg       if (!thisfd->vthis)
   2188  1.1  mrg 	{
   2189  1.1  mrg 	  error_at (make_location_t (sym->loc),
   2190  1.1  mrg 		    "%qs is a nested function and cannot be accessed from %qs",
   2191  1.1  mrg 		    fd->toPrettyChars (), thisfd->toPrettyChars ());
   2192  1.1  mrg 	  return null_pointer_node;
   2193  1.1  mrg 	}
   2194  1.1  mrg 
   2195  1.1  mrg       /* Make sure we can get the frame pointer to the outer function.
   2196  1.1  mrg 	 Go up each nesting level until we find the enclosing function.  */
   2197  1.1  mrg       Dsymbol *dsym = thisfd;
   2198  1.1  mrg 
   2199  1.1  mrg       while (fd != dsym)
   2200  1.1  mrg 	{
   2201  1.1  mrg 	  /* Check if enclosing function is a function.  */
   2202  1.1  mrg 	  FuncDeclaration *fd = dsym->isFuncDeclaration ();
   2203  1.1  mrg 
   2204  1.1  mrg 	  if (fd != NULL)
   2205  1.1  mrg 	    {
   2206  1.1  mrg 	      if (fdparent == fd->toParent2 ())
   2207  1.1  mrg 		break;
   2208  1.1  mrg 
   2209  1.1  mrg 	      gcc_assert (fd->isNested () || fd->vthis);
   2210  1.1  mrg 	      dsym = dsym->toParent2 ();
   2211  1.1  mrg 	      continue;
   2212  1.1  mrg 	    }
   2213  1.1  mrg 
   2214  1.1  mrg 	  /* Check if enclosed by an aggregate.  That means the current
   2215  1.1  mrg 	     function must be a member function of that aggregate.  */
   2216  1.1  mrg 	  AggregateDeclaration *ad = dsym->isAggregateDeclaration ();
   2217  1.1  mrg 
   2218  1.1  mrg 	  if (ad == NULL)
   2219  1.1  mrg 	    goto Lnoframe;
   2220  1.1  mrg 	  if (ad->isClassDeclaration () && fdparent == ad->toParent2 ())
   2221  1.1  mrg 	    break;
   2222  1.1  mrg 	  if (ad->isStructDeclaration () && fdparent == ad->toParent2 ())
   2223  1.1  mrg 	    break;
   2224  1.1  mrg 
   2225  1.1  mrg 	  if (!ad->isNested () || !ad->vthis)
   2226  1.1  mrg 	    {
   2227  1.1  mrg 	    Lnoframe:
   2228  1.1  mrg 	      error_at (make_location_t (thisfd->loc),
   2229  1.1  mrg 			"cannot get frame pointer to %qs",
   2230  1.1  mrg 			sym->toPrettyChars ());
   2231  1.1  mrg 	      return null_pointer_node;
   2232  1.1  mrg 	    }
   2233  1.1  mrg 
   2234  1.1  mrg 	  dsym = dsym->toParent2 ();
   2235  1.1  mrg 	}
   2236  1.1  mrg     }
   2237  1.1  mrg 
   2238  1.1  mrg   tree ffo = get_frameinfo (fdparent);
   2239  1.1  mrg   if (FRAMEINFO_CREATES_FRAME (ffo) || FRAMEINFO_STATIC_CHAIN (ffo))
   2240  1.1  mrg     {
   2241  1.1  mrg       tree frame_ref = get_framedecl (thisfd, fdparent);
   2242  1.1  mrg 
   2243  1.1  mrg       /* If 'thisfd' is a derived member function, then 'fdparent' is the
   2244  1.1  mrg 	 overridden member function in the base class.  Even if there's a
   2245  1.1  mrg 	 closure environment, we should give the original stack data as the
   2246  1.1  mrg 	 nested function frame.  */
   2247  1.1  mrg       if (fdoverride)
   2248  1.1  mrg 	{
   2249  1.1  mrg 	  ClassDeclaration *cdo = fdoverride->isThis ()->isClassDeclaration ();
   2250  1.1  mrg 	  ClassDeclaration *cd = thisfd->isThis ()->isClassDeclaration ();
   2251  1.1  mrg 	  gcc_assert (cdo && cd);
   2252  1.1  mrg 
   2253  1.1  mrg 	  int offset;
   2254  1.1  mrg 	  if (cdo->isBaseOf (cd, &offset) && offset != 0)
   2255  1.1  mrg 	    {
   2256  1.1  mrg 	      /* Generate a new frame to pass to the overriden function that
   2257  1.1  mrg 		 has the 'this' pointer adjusted.  */
   2258  1.1  mrg 	      gcc_assert (offset != OFFSET_RUNTIME);
   2259  1.1  mrg 
   2260  1.1  mrg 	      tree type = FRAMEINFO_TYPE (get_frameinfo (fdoverride));
   2261  1.1  mrg 	      tree fields = TYPE_FIELDS (type);
   2262  1.1  mrg 	      /* The 'this' field comes immediately after the '__chain'.  */
   2263  1.1  mrg 	      tree thisfield = chain_index (1, fields);
   2264  1.1  mrg 	      vec<constructor_elt, va_gc> *ve = NULL;
   2265  1.1  mrg 
   2266  1.1  mrg 	      tree framefields = TYPE_FIELDS (FRAMEINFO_TYPE (ffo));
   2267  1.1  mrg 	      frame_ref = build_deref (frame_ref);
   2268  1.1  mrg 
   2269  1.1  mrg 	      for (tree field = fields; field; field = DECL_CHAIN (field))
   2270  1.1  mrg 		{
   2271  1.1  mrg 		  tree value = component_ref (frame_ref, framefields);
   2272  1.1  mrg 		  if (field == thisfield)
   2273  1.1  mrg 		    value = build_offset (value, size_int (offset));
   2274  1.1  mrg 
   2275  1.1  mrg 		  CONSTRUCTOR_APPEND_ELT (ve, field, value);
   2276  1.1  mrg 		  framefields = DECL_CHAIN (framefields);
   2277  1.1  mrg 		}
   2278  1.1  mrg 
   2279  1.1  mrg 	      frame_ref = build_address (build_constructor (type, ve));
   2280  1.1  mrg 	    }
   2281  1.1  mrg 	}
   2282  1.1  mrg 
   2283  1.1  mrg       return frame_ref;
   2284  1.1  mrg     }
   2285  1.1  mrg 
   2286  1.1  mrg   return null_pointer_node;
   2287  1.1  mrg }
   2288  1.1  mrg 
   2289  1.1  mrg /* Return the parent function of a nested class CD.  */
   2290  1.1  mrg 
   2291  1.1  mrg static FuncDeclaration *
   2292  1.1  mrg d_nested_class (ClassDeclaration *cd)
   2293  1.1  mrg {
   2294  1.1  mrg   FuncDeclaration *fd = NULL;
   2295  1.1  mrg   while (cd && cd->isNested ())
   2296  1.1  mrg     {
   2297  1.1  mrg       Dsymbol *dsym = cd->toParent2 ();
   2298  1.1  mrg       if ((fd = dsym->isFuncDeclaration ()))
   2299  1.1  mrg 	return fd;
   2300  1.1  mrg       else
   2301  1.1  mrg 	cd = dsym->isClassDeclaration ();
   2302  1.1  mrg     }
   2303  1.1  mrg   return NULL;
   2304  1.1  mrg }
   2305  1.1  mrg 
   2306  1.1  mrg /* Return the parent function of a nested struct SD.  */
   2307  1.1  mrg 
   2308  1.1  mrg static FuncDeclaration *
   2309  1.1  mrg d_nested_struct (StructDeclaration *sd)
   2310  1.1  mrg {
   2311  1.1  mrg   FuncDeclaration *fd = NULL;
   2312  1.1  mrg   while (sd && sd->isNested ())
   2313  1.1  mrg     {
   2314  1.1  mrg       Dsymbol *dsym = sd->toParent2 ();
   2315  1.1  mrg       if ((fd = dsym->isFuncDeclaration ()))
   2316  1.1  mrg 	return fd;
   2317  1.1  mrg       else
   2318  1.1  mrg 	sd = dsym->isStructDeclaration ();
   2319  1.1  mrg     }
   2320  1.1  mrg   return NULL;
   2321  1.1  mrg }
   2322  1.1  mrg 
   2323  1.1  mrg 
   2324  1.1  mrg /* Starting from the current function FD, try to find a suitable value of
   2325  1.1  mrg    'this' in nested function instances.  A suitable 'this' value is an
   2326  1.1  mrg    instance of OCD or a class that has OCD as a base.  */
   2327  1.1  mrg 
   2328  1.1  mrg static tree
   2329  1.1  mrg find_this_tree (ClassDeclaration *ocd)
   2330  1.1  mrg {
   2331  1.1  mrg   FuncDeclaration *fd = d_function_chain ? d_function_chain->function : NULL;
   2332  1.1  mrg 
   2333  1.1  mrg   while (fd)
   2334  1.1  mrg     {
   2335  1.1  mrg       AggregateDeclaration *ad = fd->isThis ();
   2336  1.1  mrg       ClassDeclaration *cd = ad ? ad->isClassDeclaration () : NULL;
   2337  1.1  mrg 
   2338  1.1  mrg       if (cd != NULL)
   2339  1.1  mrg 	{
   2340  1.1  mrg 	  if (ocd == cd)
   2341  1.1  mrg 	    return get_decl_tree (fd->vthis);
   2342  1.1  mrg 	  else if (ocd->isBaseOf (cd, NULL))
   2343  1.1  mrg 	    return convert_expr (get_decl_tree (fd->vthis),
   2344  1.1  mrg 				 cd->type, ocd->type);
   2345  1.1  mrg 
   2346  1.1  mrg 	  fd = d_nested_class (cd);
   2347  1.1  mrg 	}
   2348  1.1  mrg       else
   2349  1.1  mrg 	{
   2350  1.1  mrg 	  if (fd->isNested ())
   2351  1.1  mrg 	    {
   2352  1.1  mrg 	      fd = fd->toParent2 ()->isFuncDeclaration ();
   2353  1.1  mrg 	      continue;
   2354  1.1  mrg 	    }
   2355  1.1  mrg 
   2356  1.1  mrg 	  fd = NULL;
   2357  1.1  mrg 	}
   2358  1.1  mrg     }
   2359  1.1  mrg 
   2360  1.1  mrg   return NULL_TREE;
   2361  1.1  mrg }
   2362  1.1  mrg 
   2363  1.1  mrg /* Retrieve the outer class/struct 'this' value of DECL from
   2364  1.1  mrg    the current function.  */
   2365  1.1  mrg 
   2366  1.1  mrg tree
   2367  1.1  mrg build_vthis (AggregateDeclaration *decl)
   2368  1.1  mrg {
   2369  1.1  mrg   ClassDeclaration *cd = decl->isClassDeclaration ();
   2370  1.1  mrg   StructDeclaration *sd = decl->isStructDeclaration ();
   2371  1.1  mrg 
   2372  1.1  mrg   /* If an aggregate nested in a function has no methods and there are no
   2373  1.1  mrg      other nested functions, any static chain created here will never be
   2374  1.1  mrg      translated.  Use a null pointer for the link in this case.  */
   2375  1.1  mrg   tree vthis_value = null_pointer_node;
   2376  1.1  mrg 
   2377  1.1  mrg   if (cd != NULL || sd != NULL)
   2378  1.1  mrg     {
   2379  1.1  mrg       Dsymbol *outer = decl->toParent2 ();
   2380  1.1  mrg 
   2381  1.1  mrg       /* If the parent is a templated struct, the outer context is instead
   2382  1.1  mrg 	 the enclosing symbol of where the instantiation happened.  */
   2383  1.1  mrg       if (outer->isStructDeclaration ())
   2384  1.1  mrg 	{
   2385  1.1  mrg 	  gcc_assert (outer->parent && outer->parent->isTemplateInstance ());
   2386  1.1  mrg 	  outer = ((TemplateInstance *) outer->parent)->enclosing;
   2387  1.1  mrg 	}
   2388  1.1  mrg 
   2389  1.1  mrg       /* For outer classes, get a suitable 'this' value.
   2390  1.1  mrg 	 For outer functions, get a suitable frame/closure pointer.  */
   2391  1.1  mrg       ClassDeclaration *cdo = outer->isClassDeclaration ();
   2392  1.1  mrg       FuncDeclaration *fdo = outer->isFuncDeclaration ();
   2393  1.1  mrg 
   2394  1.1  mrg       if (cdo)
   2395  1.1  mrg 	{
   2396  1.1  mrg 	  vthis_value = find_this_tree (cdo);
   2397  1.1  mrg 	  gcc_assert (vthis_value != NULL_TREE);
   2398  1.1  mrg 	}
   2399  1.1  mrg       else if (fdo)
   2400  1.1  mrg 	{
   2401  1.1  mrg 	  tree ffo = get_frameinfo (fdo);
   2402  1.1  mrg 	  if (FRAMEINFO_CREATES_FRAME (ffo) || FRAMEINFO_STATIC_CHAIN (ffo)
   2403  1.1  mrg 	      || fdo->hasNestedFrameRefs ())
   2404  1.1  mrg 	    vthis_value = get_frame_for_symbol (decl);
   2405  1.1  mrg 	  else if (cd != NULL)
   2406  1.1  mrg 	    {
   2407  1.1  mrg 	      /* Classes nested in methods are allowed to access any outer
   2408  1.1  mrg 		 class fields, use the function chain in this case.  */
   2409  1.1  mrg 	      if (fdo->vthis && fdo->vthis->type != Type::tvoidptr)
   2410  1.1  mrg 		vthis_value = get_decl_tree (fdo->vthis);
   2411  1.1  mrg 	    }
   2412  1.1  mrg 	}
   2413  1.1  mrg       else
   2414  1.1  mrg 	gcc_unreachable ();
   2415  1.1  mrg     }
   2416  1.1  mrg 
   2417  1.1  mrg   return vthis_value;
   2418  1.1  mrg }
   2419  1.1  mrg 
   2420  1.1  mrg /* Build the RECORD_TYPE that describes the function frame or closure type for
   2421  1.1  mrg    the function FD.  FFI is the tree holding all frame information.  */
   2422  1.1  mrg 
   2423  1.1  mrg static tree
   2424  1.1  mrg build_frame_type (tree ffi, FuncDeclaration *fd)
   2425  1.1  mrg {
   2426  1.1  mrg   if (FRAMEINFO_TYPE (ffi))
   2427  1.1  mrg     return FRAMEINFO_TYPE (ffi);
   2428  1.1  mrg 
   2429  1.1  mrg   tree frame_rec_type = make_node (RECORD_TYPE);
   2430  1.1  mrg   char *name = concat (FRAMEINFO_IS_CLOSURE (ffi) ? "CLOSURE." : "FRAME.",
   2431  1.1  mrg 		       fd->toPrettyChars (), NULL);
   2432  1.1  mrg   TYPE_NAME (frame_rec_type) = get_identifier (name);
   2433  1.1  mrg   free (name);
   2434  1.1  mrg 
   2435  1.1  mrg   tree fields = NULL_TREE;
   2436  1.1  mrg 
   2437  1.1  mrg   /* Function is a member or nested, so must have field for outer context.  */
   2438  1.1  mrg   if (fd->vthis)
   2439  1.1  mrg     {
   2440  1.1  mrg       tree ptr_field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
   2441  1.1  mrg 				   get_identifier ("__chain"), ptr_type_node);
   2442  1.1  mrg       DECL_FIELD_CONTEXT (ptr_field) = frame_rec_type;
   2443  1.1  mrg       fields = chainon (NULL_TREE, ptr_field);
   2444  1.1  mrg       DECL_NONADDRESSABLE_P (ptr_field) = 1;
   2445  1.1  mrg     }
   2446  1.1  mrg 
   2447  1.1  mrg   /* The __ensure and __require are called directly, so never make the outer
   2448  1.1  mrg      functions closure, but nevertheless could still be referencing parameters
   2449  1.1  mrg      of the calling function non-locally.  So we add all parameters with nested
   2450  1.1  mrg      refs to the function frame, this should also mean overriding methods will
   2451  1.1  mrg      have the same frame layout when inheriting a contract.  */
   2452  1.1  mrg   if ((global.params.useIn && fd->frequire)
   2453  1.1  mrg       || (global.params.useOut && fd->fensure))
   2454  1.1  mrg     {
   2455  1.1  mrg       if (fd->parameters)
   2456  1.1  mrg 	{
   2457  1.1  mrg 	  for (size_t i = 0; fd->parameters && i < fd->parameters->dim; i++)
   2458  1.1  mrg 	    {
   2459  1.1  mrg 	      VarDeclaration *v = (*fd->parameters)[i];
   2460  1.1  mrg 	      /* Remove if already in closureVars so can push to front.  */
   2461  1.1  mrg 	      for (size_t j = i; j < fd->closureVars.dim; j++)
   2462  1.1  mrg 		{
   2463  1.1  mrg 		  Dsymbol *s = fd->closureVars[j];
   2464  1.1  mrg 		  if (s == v)
   2465  1.1  mrg 		    {
   2466  1.1  mrg 		      fd->closureVars.remove (j);
   2467  1.1  mrg 		      break;
   2468  1.1  mrg 		    }
   2469  1.1  mrg 		}
   2470  1.1  mrg 	      fd->closureVars.insert (i, v);
   2471  1.1  mrg 	    }
   2472  1.1  mrg 	}
   2473  1.1  mrg 
   2474  1.1  mrg       /* Also add hidden 'this' to outer context.  */
   2475  1.1  mrg       if (fd->vthis)
   2476  1.1  mrg 	{
   2477  1.1  mrg 	  for (size_t i = 0; i < fd->closureVars.dim; i++)
   2478  1.1  mrg 	    {
   2479  1.1  mrg 	      Dsymbol *s = fd->closureVars[i];
   2480  1.1  mrg 	      if (s == fd->vthis)
   2481  1.1  mrg 		{
   2482  1.1  mrg 		  fd->closureVars.remove (i);
   2483  1.1  mrg 		  break;
   2484  1.1  mrg 		}
   2485  1.1  mrg 	    }
   2486  1.1  mrg 	  fd->closureVars.insert (0, fd->vthis);
   2487  1.1  mrg 	}
   2488  1.1  mrg     }
   2489  1.1  mrg 
   2490  1.1  mrg   for (size_t i = 0; i < fd->closureVars.dim; i++)
   2491  1.1  mrg     {
   2492  1.1  mrg       VarDeclaration *v = fd->closureVars[i];
   2493  1.1  mrg       tree vsym = get_symbol_decl (v);
   2494  1.1  mrg       tree ident = v->ident
   2495  1.1  mrg 	? get_identifier (v->ident->toChars ()) : NULL_TREE;
   2496  1.1  mrg 
   2497  1.1  mrg       tree field = build_decl (make_location_t (v->loc), FIELD_DECL, ident,
   2498  1.1  mrg 			       TREE_TYPE (vsym));
   2499  1.1  mrg       SET_DECL_LANG_FRAME_FIELD (vsym, field);
   2500  1.1  mrg       DECL_FIELD_CONTEXT (field) = frame_rec_type;
   2501  1.1  mrg       fields = chainon (fields, field);
   2502  1.1  mrg       TREE_USED (vsym) = 1;
   2503  1.1  mrg 
   2504  1.1  mrg       TREE_ADDRESSABLE (field) = TREE_ADDRESSABLE (vsym);
   2505  1.1  mrg       DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (vsym);
   2506  1.1  mrg       TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (vsym);
   2507  1.1  mrg 
   2508  1.1  mrg       /* Can't do nrvo if the variable is put in a frame.  */
   2509  1.1  mrg       if (fd->nrvo_can && fd->nrvo_var == v)
   2510  1.1  mrg 	fd->nrvo_can = 0;
   2511  1.1  mrg 
   2512  1.1  mrg       if (FRAMEINFO_IS_CLOSURE (ffi))
   2513  1.1  mrg 	{
   2514  1.1  mrg 	  /* Because the value needs to survive the end of the scope.  */
   2515  1.1  mrg 	  if ((v->edtor && (v->storage_class & STCparameter))
   2516  1.1  mrg 	      || v->needsScopeDtor ())
   2517  1.1  mrg 	    error_at (make_location_t (v->loc),
   2518  1.1  mrg 		      "has scoped destruction, cannot build closure");
   2519  1.1  mrg 	}
   2520  1.1  mrg     }
   2521  1.1  mrg 
   2522  1.1  mrg   TYPE_FIELDS (frame_rec_type) = fields;
   2523  1.1  mrg   TYPE_READONLY (frame_rec_type) = 1;
   2524  1.1  mrg   layout_type (frame_rec_type);
   2525  1.1  mrg   d_keep (frame_rec_type);
   2526  1.1  mrg 
   2527  1.1  mrg   return frame_rec_type;
   2528  1.1  mrg }
   2529  1.1  mrg 
   2530  1.1  mrg /* Closures are implemented by taking the local variables that
   2531  1.1  mrg    need to survive the scope of the function, and copying them
   2532  1.1  mrg    into a GC allocated chuck of memory.  That chunk, called the
   2533  1.1  mrg    closure here, is inserted into the linked list of stack
   2534  1.1  mrg    frames instead of the usual stack frame.
   2535  1.1  mrg 
   2536  1.1  mrg    If a closure is not required, but FD still needs a frame to lower
   2537  1.1  mrg    nested refs, then instead build custom static chain decl on stack.  */
   2538  1.1  mrg 
   2539  1.1  mrg void
   2540  1.1  mrg build_closure (FuncDeclaration *fd)
   2541  1.1  mrg {
   2542  1.1  mrg   tree ffi = get_frameinfo (fd);
   2543  1.1  mrg 
   2544  1.1  mrg   if (!FRAMEINFO_CREATES_FRAME (ffi))
   2545  1.1  mrg     return;
   2546  1.1  mrg 
   2547  1.1  mrg   tree type = FRAMEINFO_TYPE (ffi);
   2548  1.1  mrg   gcc_assert (COMPLETE_TYPE_P (type));
   2549  1.1  mrg 
   2550  1.1  mrg   tree decl, decl_ref;
   2551  1.1  mrg 
   2552  1.1  mrg   if (FRAMEINFO_IS_CLOSURE (ffi))
   2553  1.1  mrg     {
   2554  1.1  mrg       decl = build_local_temp (build_pointer_type (type));
   2555  1.1  mrg       DECL_NAME (decl) = get_identifier ("__closptr");
   2556  1.1  mrg       decl_ref = build_deref (decl);
   2557  1.1  mrg 
   2558  1.1  mrg       /* Allocate memory for closure.  */
   2559  1.1  mrg       tree arg = convert (build_ctype (Type::tsize_t), TYPE_SIZE_UNIT (type));
   2560  1.1  mrg       tree init = build_libcall (LIBCALL_ALLOCMEMORY, Type::tvoidptr, 1, arg);
   2561  1.1  mrg 
   2562  1.1  mrg       tree init_exp = build_assign (INIT_EXPR, decl,
   2563  1.1  mrg 				    build_nop (TREE_TYPE (decl), init));
   2564  1.1  mrg       add_stmt (init_exp);
   2565  1.1  mrg     }
   2566  1.1  mrg   else
   2567  1.1  mrg     {
   2568  1.1  mrg       decl = build_local_temp (type);
   2569  1.1  mrg       DECL_NAME (decl) = get_identifier ("__frame");
   2570  1.1  mrg       decl_ref = decl;
   2571  1.1  mrg     }
   2572  1.1  mrg 
   2573  1.1  mrg   /* Set the first entry to the parent closure/frame, if any.  */
   2574  1.1  mrg   if (fd->vthis)
   2575  1.1  mrg     {
   2576  1.1  mrg       tree chain_field = component_ref (decl_ref, TYPE_FIELDS (type));
   2577  1.1  mrg       tree chain_expr = modify_expr (chain_field,
   2578  1.1  mrg 				     d_function_chain->static_chain);
   2579  1.1  mrg       add_stmt (chain_expr);
   2580  1.1  mrg     }
   2581  1.1  mrg 
   2582  1.1  mrg   /* Copy parameters that are referenced nonlocally.  */
   2583  1.1  mrg   for (size_t i = 0; i < fd->closureVars.dim; i++)
   2584  1.1  mrg     {
   2585  1.1  mrg       VarDeclaration *v = fd->closureVars[i];
   2586  1.1  mrg 
   2587  1.1  mrg       if (!v->isParameter ())
   2588  1.1  mrg 	continue;
   2589  1.1  mrg 
   2590  1.1  mrg       tree vsym = get_symbol_decl (v);
   2591  1.1  mrg 
   2592  1.1  mrg       tree field = component_ref (decl_ref, DECL_LANG_FRAME_FIELD (vsym));
   2593  1.1  mrg       tree expr = modify_expr (field, vsym);
   2594  1.1  mrg       add_stmt (expr);
   2595  1.1  mrg     }
   2596  1.1  mrg 
   2597  1.1  mrg   if (!FRAMEINFO_IS_CLOSURE (ffi))
   2598  1.1  mrg     decl = build_address (decl);
   2599  1.1  mrg 
   2600  1.1  mrg   d_function_chain->static_chain = decl;
   2601  1.1  mrg }
   2602  1.1  mrg 
   2603  1.1  mrg /* Return the frame of FD.  This could be a static chain or a closure
   2604  1.1  mrg    passed via the hidden 'this' pointer.  */
   2605  1.1  mrg 
   2606  1.1  mrg tree
   2607  1.1  mrg get_frameinfo (FuncDeclaration *fd)
   2608  1.1  mrg {
   2609  1.1  mrg   tree fds = get_symbol_decl (fd);
   2610  1.1  mrg   if (DECL_LANG_FRAMEINFO (fds))
   2611  1.1  mrg     return DECL_LANG_FRAMEINFO (fds);
   2612  1.1  mrg 
   2613  1.1  mrg   tree ffi = make_node (FUNCFRAME_INFO);
   2614  1.1  mrg 
   2615  1.1  mrg   DECL_LANG_FRAMEINFO (fds) = ffi;
   2616  1.1  mrg 
   2617  1.1  mrg   if (fd->needsClosure ())
   2618  1.1  mrg     {
   2619  1.1  mrg       /* Set-up a closure frame, this will be allocated on the heap.  */
   2620  1.1  mrg       FRAMEINFO_CREATES_FRAME (ffi) = 1;
   2621  1.1  mrg       FRAMEINFO_IS_CLOSURE (ffi) = 1;
   2622  1.1  mrg     }
   2623  1.1  mrg   else if (fd->hasNestedFrameRefs ())
   2624  1.1  mrg     {
   2625  1.1  mrg       /* Functions with nested refs must create a static frame for local
   2626  1.1  mrg 	 variables to be referenced from.  */
   2627  1.1  mrg       FRAMEINFO_CREATES_FRAME (ffi) = 1;
   2628  1.1  mrg     }
   2629  1.1  mrg   else
   2630  1.1  mrg     {
   2631  1.1  mrg       /* For nested functions, default to creating a frame.  Even if there are
   2632  1.1  mrg 	 no fields to populate the frame, create it anyway, as this will be
   2633  1.1  mrg 	 used as the record type instead of `void*` for the this parameter.  */
   2634  1.1  mrg       if (fd->vthis && fd->vthis->type == Type::tvoidptr)
   2635  1.1  mrg 	FRAMEINFO_CREATES_FRAME (ffi) = 1;
   2636  1.1  mrg 
   2637  1.1  mrg       /* In checkNestedReference, references from contracts are not added to the
   2638  1.1  mrg 	 closureVars array, so assume all parameters referenced.  */
   2639  1.1  mrg       if ((global.params.useIn && fd->frequire)
   2640  1.1  mrg 	  || (global.params.useOut && fd->fensure))
   2641  1.1  mrg 	FRAMEINFO_CREATES_FRAME (ffi) = 1;
   2642  1.1  mrg 
   2643  1.1  mrg       /* If however `fd` is nested (deeply) in a function that creates a
   2644  1.1  mrg 	 closure, then `fd` instead inherits that closure via hidden vthis
   2645  1.1  mrg 	 pointer, and doesn't create a stack frame at all.  */
   2646  1.1  mrg       FuncDeclaration *ff = fd;
   2647  1.1  mrg 
   2648  1.1  mrg       while (ff)
   2649  1.1  mrg 	{
   2650  1.1  mrg 	  tree ffo = get_frameinfo (ff);
   2651  1.1  mrg 
   2652  1.1  mrg 	  if (ff != fd && FRAMEINFO_CREATES_FRAME (ffo))
   2653  1.1  mrg 	    {
   2654  1.1  mrg 	      gcc_assert (FRAMEINFO_TYPE (ffo));
   2655  1.1  mrg 	      FRAMEINFO_CREATES_FRAME (ffi) = 0;
   2656  1.1  mrg 	      FRAMEINFO_STATIC_CHAIN (ffi) = 1;
   2657  1.1  mrg 	      FRAMEINFO_IS_CLOSURE (ffi) = FRAMEINFO_IS_CLOSURE (ffo);
   2658  1.1  mrg 	      gcc_assert (COMPLETE_TYPE_P (FRAMEINFO_TYPE (ffo)));
   2659  1.1  mrg 	      FRAMEINFO_TYPE (ffi) = FRAMEINFO_TYPE (ffo);
   2660  1.1  mrg 	      break;
   2661  1.1  mrg 	    }
   2662  1.1  mrg 
   2663  1.1  mrg 	  /* Stop looking if no frame pointer for this function.  */
   2664  1.1  mrg 	  if (ff->vthis == NULL)
   2665  1.1  mrg 	    break;
   2666  1.1  mrg 
   2667  1.1  mrg 	  AggregateDeclaration *ad = ff->isThis ();
   2668  1.1  mrg 	  if (ad && ad->isNested ())
   2669  1.1  mrg 	    {
   2670  1.1  mrg 	      while (ad->isNested ())
   2671  1.1  mrg 		{
   2672  1.1  mrg 		  Dsymbol *d = ad->toParent2 ();
   2673  1.1  mrg 		  ad = d->isAggregateDeclaration ();
   2674  1.1  mrg 		  ff = d->isFuncDeclaration ();
   2675  1.1  mrg 
   2676  1.1  mrg 		  if (ad == NULL)
   2677  1.1  mrg 		    break;
   2678  1.1  mrg 		}
   2679  1.1  mrg 	    }
   2680  1.1  mrg 	  else
   2681  1.1  mrg 	    ff = ff->toParent2 ()->isFuncDeclaration ();
   2682  1.1  mrg 	}
   2683  1.1  mrg     }
   2684  1.1  mrg 
   2685  1.1  mrg   /* Build type now as may be referenced from another module.  */
   2686  1.1  mrg   if (FRAMEINFO_CREATES_FRAME (ffi))
   2687  1.1  mrg     FRAMEINFO_TYPE (ffi) = build_frame_type (ffi, fd);
   2688  1.1  mrg 
   2689  1.1  mrg   return ffi;
   2690  1.1  mrg }
   2691  1.1  mrg 
   2692  1.1  mrg /* Return a pointer to the frame/closure block of OUTER
   2693  1.1  mrg    so can be accessed from the function INNER.  */
   2694  1.1  mrg 
   2695  1.1  mrg tree
   2696  1.1  mrg get_framedecl (FuncDeclaration *inner, FuncDeclaration *outer)
   2697  1.1  mrg {
   2698  1.1  mrg   tree result = d_function_chain->static_chain;
   2699  1.1  mrg   FuncDeclaration *fd = inner;
   2700  1.1  mrg 
   2701  1.1  mrg   while (fd && fd != outer)
   2702  1.1  mrg     {
   2703  1.1  mrg       AggregateDeclaration *ad;
   2704  1.1  mrg       ClassDeclaration *cd;
   2705  1.1  mrg       StructDeclaration *sd;
   2706  1.1  mrg 
   2707  1.1  mrg       /* Parent frame link is the first field.  */
   2708  1.1  mrg       if (FRAMEINFO_CREATES_FRAME (get_frameinfo (fd)))
   2709  1.1  mrg 	result = indirect_ref (ptr_type_node, result);
   2710  1.1  mrg 
   2711  1.1  mrg       if (fd->isNested ())
   2712  1.1  mrg 	fd = fd->toParent2 ()->isFuncDeclaration ();
   2713  1.1  mrg       /* The frame/closure record always points to the outer function's
   2714  1.1  mrg 	 frame, even if there are intervening nested classes or structs.
   2715  1.1  mrg 	 So, we can just skip over these.  */
   2716  1.1  mrg       else if ((ad = fd->isThis ()) && (cd = ad->isClassDeclaration ()))
   2717  1.1  mrg 	fd = d_nested_class (cd);
   2718  1.1  mrg       else if ((ad = fd->isThis ()) && (sd = ad->isStructDeclaration ()))
   2719  1.1  mrg 	fd = d_nested_struct (sd);
   2720  1.1  mrg       else
   2721  1.1  mrg 	break;
   2722  1.1  mrg     }
   2723  1.1  mrg 
   2724  1.1  mrg   /* Go get our frame record.  */
   2725  1.1  mrg   gcc_assert (fd == outer);
   2726  1.1  mrg   tree frame_type = FRAMEINFO_TYPE (get_frameinfo (outer));
   2727  1.1  mrg 
   2728  1.1  mrg   if (frame_type != NULL_TREE)
   2729  1.1  mrg     {
   2730  1.1  mrg       result = build_nop (build_pointer_type (frame_type), result);
   2731  1.1  mrg       return result;
   2732  1.1  mrg     }
   2733  1.1  mrg   else
   2734  1.1  mrg     {
   2735  1.1  mrg       error_at (make_location_t (inner->loc),
   2736  1.1  mrg 		"forward reference to frame of %qs", outer->toChars ());
   2737  1.1  mrg       return null_pointer_node;
   2738  1.1  mrg     }
   2739  1.1  mrg }
   2740