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