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