Subversion Repositories Open64

[/] [trunk/] [osprey/] [wgen/] [wgen_spin_symbol.cxx] - Diff between revs 2360 and 2694

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 2360 Rev 2694
/*
/*
 * Copyright (C) 2009 Advanced Micro Devices, Inc.  All Rights Reserved.
 * Copyright (C) 2009 Advanced Micro Devices, Inc.  All Rights Reserved.
 */
 */
/*
/*
 * Copyright (C) 2007 Pathscale, LLC.  All Rights Reserved.
 * Copyright (C) 2007 Pathscale, LLC.  All Rights Reserved.
 */
 */
/*
/*
 * Copyright (C) 2006, 2007. QLogic Corporation. All Rights Reserved.
 * Copyright (C) 2006, 2007. QLogic Corporation. All Rights Reserved.
 */
 */
/*
/*
   Copyright 2003, 2004, 2005, 2006 PathScale, Inc.  All Rights Reserved.
   Copyright 2003, 2004, 2005, 2006 PathScale, Inc.  All Rights Reserved.
   File modified October 9, 2003 by PathScale, Inc. to update Open64 C/C++
   File modified October 9, 2003 by PathScale, Inc. to update Open64 C/C++
   front-ends to GNU 3.3.1 release.
   front-ends to GNU 3.3.1 release.
 */
 */
/*
/*
   Copyright (C) 2002 Tensilica, Inc.  All Rights Reserved.
   Copyright (C) 2002 Tensilica, Inc.  All Rights Reserved.
   Revised to support Tensilica processors and to improve overall performance
   Revised to support Tensilica processors and to improve overall performance
 */
 */
/*
/*
  Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
  Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
  This program is free software; you can redistribute it and/or modify it
  This program is free software; you can redistribute it and/or modify it
  under the terms of version 2 of the GNU General Public License as
  under the terms of version 2 of the GNU General Public License as
  published by the Free Software Foundation.
  published by the Free Software Foundation.
  This program is distributed in the hope that it would be useful, but
  This program is distributed in the hope that it would be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  Further, this software is distributed without any warranty that it is
  Further, this software is distributed without any warranty that it is
  free of the rightful claim of any third person regarding infringement
  free of the rightful claim of any third person regarding infringement
  or the like.  Any license provided herein, whether implied or
  or the like.  Any license provided herein, whether implied or
  otherwise, applies only to this software file.  Patent licenses, if
  otherwise, applies only to this software file.  Patent licenses, if
  any, provided herein do not apply to combinations of this program with
  any, provided herein do not apply to combinations of this program with
  other software, or any other product whatsoever.
  other software, or any other product whatsoever.
  You should have received a copy of the GNU General Public License along
  You should have received a copy of the GNU General Public License along
  with this program; if not, write the Free Software Foundation, Inc., 59
  with this program; if not, write the Free Software Foundation, Inc., 59
  Temple Place - Suite 330, Boston MA 02111-1307, USA.
  Temple Place - Suite 330, Boston MA 02111-1307, USA.
  Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
  Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
  Mountain View, CA 94043, or:
  Mountain View, CA 94043, or:
  http://www.sgi.com
  http://www.sgi.com
  For further information regarding this notice, see:
  For further information regarding this notice, see:
  http://oss.sgi.com/projects/GenInfo/NoticeExplan
  http://oss.sgi.com/projects/GenInfo/NoticeExplan
*/
*/
/* translate gnu decl trees to symtab references */
/* translate gnu decl trees to symtab references */
extern "C"{
extern "C"{
#include "gspin-wgen-interface.h"
#include "gspin-wgen-interface.h"
}
}
#if defined(BUILD_OS_DARWIN)
#if defined(BUILD_OS_DARWIN)
#include <limits.h>
#include <limits.h>
#else /* defined(BUILD_OS_DARWIN) */
#else /* defined(BUILD_OS_DARWIN) */
#include <values.h>
#include <values.h>
#endif /* defined(BUILD_OS_DARWIN) */
#endif /* defined(BUILD_OS_DARWIN) */
#include "pathscale_defs.h"
#include "pathscale_defs.h"
#include "defs.h"
#include "defs.h"
#include "errors.h"
#include "errors.h"
#include "symtab.h"
#include "symtab.h"
#include "strtab.h"
#include "strtab.h"
#include "wn.h"
#include "wn.h"
#include "wgen_expr.h"
#include "wgen_expr.h"
#include "wgen_decl.h"
#include "wgen_decl.h"
#include "wgen_misc.h"
#include "wgen_misc.h"
#include "wgen_dst.h"
#include "wgen_dst.h"
#include "ir_reader.h"
#include "ir_reader.h"
#include "wgen_spin_symbol.h"
#include "wgen_spin_symbol.h"
#include "wgen_stmt.h"
#include "wgen_stmt.h"
#include <map>
#include <map>
#include "erfe.h"
#include "erfe.h"
#ifdef TARG_X8664
#ifdef TARG_X8664
#include <ctype.h>
#include <ctype.h>
#endif
#endif
//#include "tree_cmp.h"
//#include "tree_cmp.h"
 
#include <erglob.h>
#include <ext/hash_set>
#include <ext/hash_set>
using __gnu_cxx::hash_set;
using __gnu_cxx::hash_set;
typedef struct {
typedef struct {
    size_t operator()(void* p) const { return reinterpret_cast<size_t>(p); }
    size_t operator()(void* p) const { return reinterpret_cast<size_t>(p); }
} void_ptr_hash;
} void_ptr_hash;
extern int pstatic_as_global;
extern int pstatic_as_global;
extern BOOL flag_no_common;
extern BOOL flag_no_common;
extern gs_t decl_arguments;
extern gs_t decl_arguments;
extern void Push_Deferred_Function(gs_t);
extern void Push_Deferred_Function(gs_t);
extern char *WGEN_Tree_Node_Name(gs_t op);
extern char *WGEN_Tree_Node_Name(gs_t op);
 
#if defined(TARG_SL)
 
extern char *Orig_Src_File_Name, *Src_File_Name;
 
#endif
#ifdef KEY
#ifdef KEY
// =====================================================================
// =====================================================================
// bug 8346: A function's VLA argument types should only be expanded
// bug 8346: A function's VLA argument types should only be expanded
// when necessary, to prevent size-expression-whirl from landing in an
// when necessary, to prevent size-expression-whirl from landing in an
// unintended location. If we attempt to expand such a type while
// unintended location. If we attempt to expand such a type while
// generating a function's argument types, but are not expanding that
// generating a function's argument types, but are not expanding that
// specific function body, then we mark the TY as incomplete, to expand
// specific function body, then we mark the TY as incomplete, to expand
// it later when we actually expand that function body.
// it later when we actually expand that function body.
// "expanding_function_definition" denotes when it is safe to process a
// "expanding_function_definition" denotes when it is safe to process a
// function's VLA argument types.
// function's VLA argument types.
// "processing_function_prototype" indicates when we are expanding
// "processing_function_prototype" indicates when we are expanding
// function arguments (as opposed to other VLA variable occurrences).
// function arguments (as opposed to other VLA variable occurrences).
// =====================================================================
// =====================================================================
BOOL processing_function_prototype = FALSE;
BOOL processing_function_prototype = FALSE;
#endif
#endif
// Map duplicate gcc nodes that refer to the same function.
// Map duplicate gcc nodes that refer to the same function.
std::multimap<gs_t, gs_t> duplicate_of;
std::multimap<gs_t, gs_t> duplicate_of;
void
void
add_duplicates (gs_t newdecl, gs_t olddecl)
add_duplicates (gs_t newdecl, gs_t olddecl)
{
{
  duplicate_of.insert (pair<gs_t, gs_t>(newdecl, olddecl));
  duplicate_of.insert (pair<gs_t, gs_t>(newdecl, olddecl));
  duplicate_of.insert (pair<gs_t, gs_t>(olddecl, newdecl));
  duplicate_of.insert (pair<gs_t, gs_t>(olddecl, newdecl));
}
}
// Remove all references to DECL from the map.
// Remove all references to DECL from the map.
void
void
erase_duplicates (gs_t decl)
erase_duplicates (gs_t decl)
{
{
  int i, j;
  int i, j;
  int count = duplicate_of.count (decl);
  int count = duplicate_of.count (decl);
  for (i=0; i<count; i++) {
  for (i=0; i<count; i++) {
    std::multimap<gs_t, gs_t>::iterator iter = duplicate_of.find(decl);
    std::multimap<gs_t, gs_t>::iterator iter = duplicate_of.find(decl);
    gs_t t = (*iter).second;
    gs_t t = (*iter).second;
    // Erase entries with DECL as the data, i.e., <..., DECL>.
    // Erase entries with DECL as the data, i.e., <..., DECL>.
    int count2 = duplicate_of.count(t);
    int count2 = duplicate_of.count(t);
    for (j=0; j<count2; j++) {
    for (j=0; j<count2; j++) {
      std::multimap<gs_t, gs_t>::iterator iter2 = duplicate_of.find(t);
      std::multimap<gs_t, gs_t>::iterator iter2 = duplicate_of.find(t);
      gs_t t2 = (*iter2).second;
      gs_t t2 = (*iter2).second;
      if (t2 == decl) {
      if (t2 == decl) {
  duplicate_of.erase (iter2);
  duplicate_of.erase (iter2);
      }
      }
    }
    }
    // Erase entry with DECL as the key, i.e., <DECL, ...>.
    // Erase entry with DECL as the key, i.e., <DECL, ...>.
    duplicate_of.erase (iter);
    duplicate_of.erase (iter);
  }
  }
}
}
static ST*
static ST*
get_duplicate_st (gs_t decl)
get_duplicate_st (gs_t decl)
{
{
  int count = duplicate_of.count (decl);
  int count = duplicate_of.count (decl);
  for (int i=0; i<count; ++i) {
  for (int i=0; i<count; ++i) {
    std::multimap<gs_t, gs_t>::iterator iter = duplicate_of.find(decl);
    std::multimap<gs_t, gs_t>::iterator iter = duplicate_of.find(decl);
    gs_t t = (*iter).second;
    gs_t t = (*iter).second;
    // The node t could have been garbage-collected by gcc.  This is a crude
    // The node t could have been garbage-collected by gcc.  This is a crude
    // test to see if t is still valid.
    // test to see if t is still valid.
    if (gs_tree_code(t) == GS_FUNCTION_DECL &&
    if (gs_tree_code(t) == GS_FUNCTION_DECL &&
  gs_decl_name(t) == gs_decl_name(decl) &&
  gs_decl_name(t) == gs_decl_name(decl) &&
  gs_decl_assembler_name_set_p(t) == gs_decl_assembler_name_set_p(decl) &&
  gs_decl_assembler_name_set_p(t) == gs_decl_assembler_name_set_p(decl) &&
  (!gs_decl_assembler_name_set_p(t) ||
  (!gs_decl_assembler_name_set_p(t) ||
   gs_decl_assembler_name(t) == gs_decl_assembler_name(decl))) {
   gs_decl_assembler_name(t) == gs_decl_assembler_name(decl))) {
      // Return the ST previously allocated, if any.
      // Return the ST previously allocated, if any.
      ST *st = DECL_ST(t);
      ST *st = DECL_ST(t);
      if (st != NULL)
      if (st != NULL)
        return st;
        return st;
    }
    }
    duplicate_of.erase (iter);
    duplicate_of.erase (iter);
  }
  }
  return NULL;
  return NULL;
}
}
static char*
static char*
Get_Name (gs_t node)
Get_Name (gs_t node)
{
{
  static UINT anon_num = 0;
  static UINT anon_num = 0;
  static char buf[64];
  static char buf[64];
  if (node == NULL) {
  if (node == NULL) {
    ++anon_num;
    ++anon_num;
    sprintf(buf, ".anonymous.%d", anon_num);
    sprintf(buf, ".anonymous.%d", anon_num);
    return buf;
    return buf;
  }
  }
  else if (gs_tree_code (node) == GS_IDENTIFIER_NODE)
  else if (gs_tree_code (node) == GS_IDENTIFIER_NODE)
    return ((char *) gs_identifier_pointer (node));
    return ((char *) gs_identifier_pointer (node));
  else if (gs_tree_code (node) == GS_TYPE_DECL)
  else if (gs_tree_code (node) == GS_TYPE_DECL)
    // If type has a typedef-name, the TYPE_NAME is a TYPE_DECL.
    // If type has a typedef-name, the TYPE_NAME is a TYPE_DECL.
#ifdef FE_GNU_4_2_0 // bug 14137
#ifdef FE_GNU_4_2_0 // bug 14137
    if (gs_decl_name(node) == NULL) {
    if (gs_decl_name(node) == NULL) {
      ++anon_num;
      ++anon_num;
      sprintf(buf, ".anonymous.%d", anon_num);
      sprintf(buf, ".anonymous.%d", anon_num);
      return buf;
      return buf;
    }
    }
    else
    else
#endif
#endif
    return ((char *) gs_identifier_pointer (gs_decl_name (node)));
    return ((char *) gs_identifier_pointer (gs_decl_name (node)));
  else
  else
    FmtAssert(FALSE, ("Get_Name unexpected tree"));
    FmtAssert(FALSE, ("Get_Name unexpected tree"));
    return NULL;
    return NULL;
}
}
static void
static void
dump_field(gs_t field)
dump_field(gs_t field)
{
{
  printf("%s:  ", Get_Name(gs_decl_name(field)));
  printf("%s:  ", Get_Name(gs_decl_name(field)));
  printf("%d\n", DECL_FIELD_ID(field));
  printf("%d\n", DECL_FIELD_ID(field));
}
}
// =================================================================
// =================================================================
// KEY: If there is a vtable pointer, then number it as the first
// KEY: If there is a vtable pointer, then number it as the first
// field in the record. GNU 4.x provides the same field for a vptr
// field in the record. GNU 4.x provides the same field for a vptr
// to a base class, and its inherited classes. So we consistenly
// to a base class, and its inherited classes. So we consistenly
// number the vptr as field_id 1.
// number the vptr as field_id 1.
// =================================================================
// =================================================================
gs_t
gs_t
get_first_real_or_virtual_field (gs_t type_tree)
get_first_real_or_virtual_field (gs_t type_tree)
{
{
  // return vfield only if the type contains fields (bug 10787)
  // return vfield only if the type contains fields (bug 10787)
  // bug 11227: C_TYPE_INCOMPLETE_VARS for C is the same as TYPE_VFIELD,
  // bug 11227: C_TYPE_INCOMPLETE_VARS for C is the same as TYPE_VFIELD,
  //            make sure we do not use it for C.
  //            make sure we do not use it for C.
  if (lang_cplus && gs_type_fields(type_tree) && gs_type_vfield(type_tree))
  if (lang_cplus && gs_type_fields(type_tree) && gs_type_vfield(type_tree))
    return gs_type_vfield(type_tree);
    return gs_type_vfield(type_tree);
  return gs_type_fields(type_tree);
  return gs_type_fields(type_tree);
}
}
gs_t
gs_t
get_virtual_field (gs_t type_tree)
get_virtual_field (gs_t type_tree)
{
{
  gs_t vfield;
  gs_t vfield;
  // return vfield only if the type contains fields (bug 10787)
  // return vfield only if the type contains fields (bug 10787)
  if (lang_cplus &&
  if (lang_cplus &&
      gs_type_fields(type_tree) &&
      gs_type_fields(type_tree) &&
      (vfield = gs_type_vfield(type_tree)) != NULL)
      (vfield = gs_type_vfield(type_tree)) != NULL)
    return vfield;
    return vfield;
  return NULL;
  return NULL;
}
}
gs_t
gs_t
get_first_real_field (gs_t type_tree)
get_first_real_field (gs_t type_tree)
{
{
  gs_t field = gs_type_fields(type_tree);
  gs_t field = gs_type_fields(type_tree);
  if (!field)
  if (!field)
    return NULL;
    return NULL;
  // If there is a pointer to the virtual function table, it is always at the
  // If there is a pointer to the virtual function table, it is always at the
  // first field.
  // first field.
  if (field == gs_type_vfield(type_tree))
  if (field == gs_type_vfield(type_tree))
  {
  {
    Is_True (lang_cplus, ("get_first_real_field: TYPE_VFIELD used for C"));
    Is_True (lang_cplus, ("get_first_real_field: TYPE_VFIELD used for C"));
    return gs_tree_chain(field);
    return gs_tree_chain(field);
  }
  }
  return field;
  return field;
}
}
gs_t
gs_t
next_real_field (gs_t type_tree, gs_t field)
next_real_field (gs_t type_tree, gs_t field)
{
{
  BOOL first_real_field = FALSE;
  BOOL first_real_field = FALSE;
  if (field == gs_type_vfield(type_tree))
  if (field == gs_type_vfield(type_tree))
  {
  {
#if 0 // bug 13102
#if 0 // bug 13102
    Is_True (lang_cplus, ("next_real_field: TYPE_VFIELD used for C"));
    Is_True (lang_cplus, ("next_real_field: TYPE_VFIELD used for C"));
#endif
#endif
    first_real_field = TRUE; // return first real field
    first_real_field = TRUE; // return first real field
  }
  }
  // If vptr is not in the list of fields, then return the first field
  // If vptr is not in the list of fields, then return the first field
  if (first_real_field && field != gs_type_fields (type_tree))
  if (first_real_field && field != gs_type_fields (type_tree))
    return gs_type_fields (type_tree);
    return gs_type_fields (type_tree);
  // Else return the next field.
  // Else return the next field.
  return gs_tree_chain (field);
  return gs_tree_chain (field);
}
}
static void
static void
Do_Base_Types (gs_t type_tree)
Do_Base_Types (gs_t type_tree)
{
{
  gs_t binfo = gs_type_binfo(type_tree);
  gs_t binfo = gs_type_binfo(type_tree);
  gs_t basetypes = binfo ? gs_binfo_base_binfos(binfo) : 0;
  gs_t basetypes = binfo ? gs_binfo_base_binfos(binfo) : 0;
  gs_t list;
  gs_t list;
  if (basetypes) {
  if (basetypes) {
    for (list = basetypes; gs_code(list) != EMPTY; list = gs_operand(list, 1))
    for (list = basetypes; gs_code(list) != EMPTY; list = gs_operand(list, 1))
      (void) Get_TY (gs_binfo_type(gs_operand(list, 0)));
      (void) Get_TY (gs_binfo_type(gs_operand(list, 0)));
  }
  }
}
}
size_t
size_t
Roundup (size_t offset, int alignment)
Roundup (size_t offset, int alignment)
{
{
  return (offset % alignment) ? offset + alignment - offset % alignment
  return (offset % alignment) ? offset + alignment - offset % alignment
            : offset;
            : offset;
}
}
size_t
size_t
Type_Size_Without_Vbases (gs_t type_tree)
Type_Size_Without_Vbases (gs_t type_tree)
{
{
  gs_t field;
  gs_t field;
  gs_t last_field_decl = 0;
  gs_t last_field_decl = 0;
  for (field = get_first_real_or_virtual_field(type_tree);
  for (field = get_first_real_or_virtual_field(type_tree);
       field;
       field;
       field = next_real_field (type_tree, field)) {
       field = next_real_field (type_tree, field)) {
    if (gs_tree_code(field) == GS_FIELD_DECL)
    if (gs_tree_code(field) == GS_FIELD_DECL)
      last_field_decl = field;
      last_field_decl = field;
  }
  }
  if (last_field_decl == 0)
  if (last_field_decl == 0)
    return 0;
    return 0;
  return
  return
    gs_get_integer_value (gs_decl_field_offset(last_field_decl)) +
    gs_get_integer_value (gs_decl_field_offset(last_field_decl)) +
    gs_get_integer_value (gs_decl_field_bit_offset(last_field_decl)) / BITSPERBYTE +
    gs_get_integer_value (gs_decl_field_bit_offset(last_field_decl)) / BITSPERBYTE +
    gs_get_integer_value (gs_decl_size(last_field_decl)) / BITSPERBYTE;
    gs_get_integer_value (gs_decl_size(last_field_decl)) / BITSPERBYTE;
}
}
bool
bool
is_empty_base_class (gs_t type_tree)
is_empty_base_class (gs_t type_tree)
{
{
  gs_t field = gs_type_fields(type_tree);
  gs_t field = gs_type_fields(type_tree);
  return gs_tree_code(field) == GS_TYPE_DECL && gs_tree_chain(field) == 0;
  return gs_tree_code(field) == GS_TYPE_DECL && gs_tree_chain(field) == 0;
}
}
// look up the attribute given by attr_name in the attribute list
// look up the attribute given by attr_name in the attribute list
gs_t
gs_t
lookup_attribute(char *attr_name, gs_t attr_list)
lookup_attribute(char *attr_name, gs_t attr_list)
{
{
  gs_t nd;
  gs_t nd;
  for (nd = attr_list; nd; nd = gs_tree_chain(nd)) {
  for (nd = attr_list; nd; nd = gs_tree_chain(nd)) {
    Is_True(gs_tree_code(nd) == GS_TREE_LIST,
    Is_True(gs_tree_code(nd) == GS_TREE_LIST,
      ("lookup_attributes: TREE_LIST node not found"));
      ("lookup_attributes: TREE_LIST node not found"));
    gs_t attr = gs_tree_purpose(nd);
    gs_t attr = gs_tree_purpose(nd);
    if (is_attribute(attr_name, attr))
    if (is_attribute(attr_name, attr))
      return nd;
      return nd;
  }
  }
  return NULL;
  return NULL;
}
}
// idx is non-zero only for RECORD and UNION, when there is forward declaration
// idx is non-zero only for RECORD and UNION, when there is forward declaration
extern TY_IDX
extern TY_IDX
Create_TY_For_Tree (gs_t type_tree, TY_IDX idx)
Create_TY_For_Tree (gs_t type_tree, TY_IDX idx)
{
{
  if(gs_tree_code(type_tree) == GS_ERROR_MARK)
  if(gs_tree_code(type_tree) == GS_ERROR_MARK)
     return idx;
     return idx;
  TY_IDX orig_idx = idx;
  TY_IDX orig_idx = idx;
  if(gs_tree_code_class(type_tree) != GS_TCC_TYPE) {
  if(gs_tree_code_class(type_tree) != GS_TCC_TYPE) {
    DevWarn("Bad tree class passed to Create_TY_For_Tree %c",
    DevWarn("Bad tree class passed to Create_TY_For_Tree %c",
    gs_tree_code_class(type_tree));
    gs_tree_code_class(type_tree));
          return idx;
          return idx;
  }
  }
#ifdef KEY
#ifdef KEY
  UINT align = gs_type_align(type_tree) / BITSPERBYTE;
  UINT align = gs_type_align(type_tree) / BITSPERBYTE;
#endif
#endif
  // for typedefs get the information from the base type
  // for typedefs get the information from the base type
  if (gs_type_name(type_tree) &&
  if (gs_type_name(type_tree) &&
      idx == 0 &&
      idx == 0 &&
      (gs_tree_code(type_tree) == GS_RECORD_TYPE ||
      (gs_tree_code(type_tree) == GS_RECORD_TYPE ||
       gs_tree_code(type_tree) == GS_UNION_TYPE) &&
       gs_tree_code(type_tree) == GS_UNION_TYPE) &&
      gs_tree_code(gs_type_name(type_tree)) == GS_TYPE_DECL &&
      gs_tree_code(gs_type_name(type_tree)) == GS_TYPE_DECL &&
      gs_type_main_variant(type_tree) != type_tree) {
      gs_type_main_variant(type_tree) != type_tree) {
    idx = Get_TY (gs_type_main_variant(type_tree));
    idx = Get_TY (gs_type_main_variant(type_tree));
    if (gs_type_readonly(type_tree))
    if (gs_type_readonly(type_tree))
      Set_TY_is_const (idx);
      Set_TY_is_const (idx);
    if (gs_type_volatile(type_tree))
    if (gs_type_volatile(type_tree))
      Set_TY_is_volatile (idx);
      Set_TY_is_volatile (idx);
#ifdef KEY
#ifdef KEY
    if (gs_type_restrict(type_tree))
    if (gs_type_restrict(type_tree))
      Set_TY_is_restrict (idx);
      Set_TY_is_restrict (idx);
    Set_TY_align (idx, align); // bug 10533
    Set_TY_align (idx, align); // bug 10533
#endif
#endif
    TYPE_TY_IDX(type_tree) = idx;
    TYPE_TY_IDX(type_tree) = idx;
    if(Debug_Level >= 2) {
    if(Debug_Level >= 2) {
#ifdef KEY // bug 11782
#ifdef KEY // bug 11782
      defer_DST_type(type_tree, idx, orig_idx);
      defer_DST_type(type_tree, idx, orig_idx);
#else
#else
      DST_INFO_IDX dst = Create_DST_type_For_Tree(type_tree,
      DST_INFO_IDX dst = Create_DST_type_For_Tree(type_tree,
      idx,orig_idx);
      idx,orig_idx);
      TYPE_DST_IDX(type_tree) = dst;
      TYPE_DST_IDX(type_tree) = dst;
#endif
#endif
          }
          }
    TYPE_FIELD_IDS_USED(type_tree) =
    TYPE_FIELD_IDS_USED(type_tree) =
      TYPE_FIELD_IDS_USED(gs_type_main_variant(type_tree));
      TYPE_FIELD_IDS_USED(gs_type_main_variant(type_tree));
    return idx;
    return idx;
  }
  }
  TYPE_ID mtype;
  TYPE_ID mtype;
  INT64 tsize;
  INT64 tsize;
  BOOL variable_size = FALSE;
  BOOL variable_size = FALSE;
  gs_t type_size = gs_type_size(type_tree);
  gs_t type_size = gs_type_size(type_tree);
#ifndef KEY
#ifndef KEY
  UINT align = gs_type_align(type_tree) / BITSPERBYTE;
  UINT align = gs_type_align(type_tree) / BITSPERBYTE;
#endif
#endif
  if (type_size == NULL) {
  if (type_size == NULL) {
    // incomplete structs have 0 size.  Similarly, 'void' is
    // incomplete structs have 0 size.  Similarly, 'void' is
                // an incomplete type that can never be completed.
                // an incomplete type that can never be completed.
    FmtAssert(gs_tree_code(type_tree) == GS_ARRAY_TYPE
    FmtAssert(gs_tree_code(type_tree) == GS_ARRAY_TYPE
      || gs_tree_code(type_tree) == GS_ENUMERAL_TYPE
      || gs_tree_code(type_tree) == GS_ENUMERAL_TYPE
      || gs_tree_code(type_tree) == GS_UNION_TYPE
      || gs_tree_code(type_tree) == GS_UNION_TYPE
      || gs_tree_code(type_tree) == GS_RECORD_TYPE
      || gs_tree_code(type_tree) == GS_RECORD_TYPE
      || gs_tree_code(type_tree) == GS_LANG_TYPE
      || gs_tree_code(type_tree) == GS_LANG_TYPE
      || gs_tree_code(type_tree) == GS_FUNCTION_TYPE
      || gs_tree_code(type_tree) == GS_FUNCTION_TYPE
      || gs_tree_code(type_tree) == GS_VOID_TYPE,
      || gs_tree_code(type_tree) == GS_VOID_TYPE,
        ("Create_TY_For_Tree: type_size NULL for non ARRAY/RECORD/VOID, type is %d",
        ("Create_TY_For_Tree: type_size NULL for non ARRAY/RECORD/VOID, type is %d",
                           (int) gs_tree_code(type_tree)));
                           (int) gs_tree_code(type_tree)));
    tsize = 0;
    tsize = 0;
  }
  }
  else {
  else {
    if (gs_tree_code(type_size) != GS_INTEGER_CST) {
    if (gs_tree_code(type_size) != GS_INTEGER_CST) {
      if (gs_tree_code(type_tree) == GS_ARRAY_TYPE)
      if (gs_tree_code(type_tree) == GS_ARRAY_TYPE)
        DevWarn ("Encountered VLA at line %d", lineno);
        DevWarn ("Encountered VLA at line %d", lineno);
      else
      else
#ifndef KEY
#ifndef KEY
        Fail_FmtAssertion ("VLA at line %d not currently implemented", lineno);
        Fail_FmtAssertion ("VLA at line %d not currently implemented", lineno);
#else
#else
      // bugs 943, 11277, 10506
      // bugs 943, 11277, 10506
      {
#if defined(TARG_SL)
        // Should use ErrMsg (or something similar) instead.
        ErrMsg(EC_Unimplemented_Feature, "variable-length structure",
        printf(OPEN64_NAME_PREFIX "cc: variable-length structure not yet implemented\n");
          Orig_Src_File_Name?Orig_Src_File_Name:Src_File_Name, lineno);
        exit(2);
#else
      }
        ErrMsg(EC_Unimplemented_Feature, "variable-length structure");
 
#endif
#endif
#endif
      variable_size = TRUE;
      variable_size = TRUE;
      tsize = 0;
      tsize = 0;
    }
    }
    else
    else
#ifdef KEY    // bug 3045
#ifdef KEY    // bug 3045
      tsize = (gs_get_integer_value(type_size) + BITSPERBYTE - 1)
      tsize = (gs_get_integer_value(type_size) + BITSPERBYTE - 1)
          / BITSPERBYTE;
          / BITSPERBYTE;
#else
#else
      tsize = gs_get_integer_value(type_size) / BITSPERBYTE;
      tsize = gs_get_integer_value(type_size) / BITSPERBYTE;
#endif
#endif
  }
  }
  switch (gs_tree_code(type_tree)) {
  switch (gs_tree_code(type_tree)) {
  case GS_VOID_TYPE:
  case GS_VOID_TYPE:
  case GS_LANG_TYPE: // unknown type
  case GS_LANG_TYPE: // unknown type
    idx = MTYPE_To_TY (MTYPE_V);  // use predefined type
    idx = MTYPE_To_TY (MTYPE_V);  // use predefined type
    break;
    break;
  case GS_BOOLEAN_TYPE:
  case GS_BOOLEAN_TYPE:
  case GS_INTEGER_TYPE:
  case GS_INTEGER_TYPE:
  case GS_OFFSET_TYPE:
  case GS_OFFSET_TYPE:
    switch (tsize) {
    switch (tsize) {
    case 1:  mtype = MTYPE_I1;  break;
    case 1:  mtype = MTYPE_I1;  break;
    case 2:  mtype = MTYPE_I2;  break;
    case 2:  mtype = MTYPE_I2;  break;
    case 4:  mtype = MTYPE_I4;  break;
    case 4:  mtype = MTYPE_I4;  break;
    case 8:  mtype = MTYPE_I8;  break;
    case 8:  mtype = MTYPE_I8;  break;
#if !defined(TARG_X8664) && !defined(TARG_MIPS)  // Bug 12358
#if !defined(TARG_X8664) && !defined(TARG_MIPS)  // Bug 12358
#ifdef _LP64
#ifdef _LP64
    case 16:  mtype = MTYPE_I8; break;
    case 16:  mtype = MTYPE_I8; break;
#endif /* _LP64 */
#endif /* _LP64 */
#else
#else
          // needed for compiling variable length array
          // needed for compiling variable length array
    // as in gcc.c-torture/execute/920929-1.c
    // as in gcc.c-torture/execute/920929-1.c
    // we need to fix the rest of the compiler
    // we need to fix the rest of the compiler
    // with _LP64 but seems to work fine without.
    // with _LP64 but seems to work fine without.
    case 16:  mtype = MTYPE_I8; break;
    case 16:  mtype = MTYPE_I8; break;
#endif /* KEY */
#endif /* KEY */
    default:  FmtAssert(FALSE,
    default:  FmtAssert(FALSE,
                                    ("Get_TY unexpected size %d", tsize));
                                    ("Get_TY unexpected size %d", tsize));
    }
    }
    if (gs_decl_unsigned(type_tree)) {
    if (gs_decl_unsigned(type_tree)) {
      mtype = MTYPE_complement(mtype);
      mtype = MTYPE_complement(mtype);
    }
    }
#ifdef KEY
#ifdef KEY
    if (lookup_attribute("may_alias",gs_type_attributes(type_tree)))
    if (lookup_attribute("may_alias",gs_type_attributes(type_tree)))
    {
    {
      // bug 9975: Handle may_alias attribute, we need to create
      // bug 9975: Handle may_alias attribute, we need to create
      // a new type to which we can attach the flag.
      // a new type to which we can attach the flag.
      TY &ty = New_TY (idx);
      TY &ty = New_TY (idx);
      TY_Init (ty, tsize, KIND_SCALAR, mtype,
      TY_Init (ty, tsize, KIND_SCALAR, mtype,
               Save_Str(Get_Name(gs_type_name(type_tree))) );
               Save_Str(Get_Name(gs_type_name(type_tree))) );
      Set_TY_no_ansi_alias (ty);
      Set_TY_no_ansi_alias (ty);
 
#if defined(TARG_SL)
 
      // for -m32, it is not the predefined type, alignment shoule be set.
 
      // Corresponding to following code about bug#2932.
 
      if (!TARGET_64BIT)
 
        Set_TY_align (idx, align);
 
#endif
    } else
    } else
#endif
#endif
    idx = MTYPE_To_TY (mtype);  // use predefined type
    idx = MTYPE_To_TY (mtype);  // use predefined type
#ifdef TARG_X8664
#if defined(TARG_X8664) || defined(TARG_SL)
    /* At least for -m32, the alignment is not the same as the data
    /* At least for -m32, the alignment is not the same as the data
       type's natural size. (bug#2932)
       type's natural size. (bug#2932)
    */
    */
    if( TARGET_64BIT )
    if( TARGET_64BIT )
#endif // TARG_X8664
#endif // TARG_X8664
      Set_TY_align (idx, align);
      Set_TY_align (idx, align);
    break;
    break;
  case GS_CHAR_TYPE:
  case GS_CHAR_TYPE:
    mtype = (gs_decl_unsigned(type_tree) ? MTYPE_U1 : MTYPE_I1);
    mtype = (gs_decl_unsigned(type_tree) ? MTYPE_U1 : MTYPE_I1);
    idx = MTYPE_To_TY (mtype);  // use predefined type
    idx = MTYPE_To_TY (mtype);  // use predefined type
    break;
    break;
  case GS_ENUMERAL_TYPE:
  case GS_ENUMERAL_TYPE:
#ifdef KEY
#ifdef KEY
    switch (tsize) {
    switch (tsize) {
      case 1: // bug 14445
      case 1: // bug 14445
            mtype = (gs_decl_unsigned(type_tree) ? MTYPE_U1 :
            mtype = (gs_decl_unsigned(type_tree) ? MTYPE_U1 :
                                                   MTYPE_I1);
                                                   MTYPE_I1);
            break;
            break;
      case 2: // bug 14445
      case 2: // bug 14445
            mtype = (gs_decl_unsigned(type_tree) ? MTYPE_U2 :
            mtype = (gs_decl_unsigned(type_tree) ? MTYPE_U2 :
                                                   MTYPE_I2);
                                                   MTYPE_I2);
            break;
            break;
      case 8: // bug 500
      case 8: // bug 500
            mtype = (gs_decl_unsigned(type_tree) ? MTYPE_U8 :
            mtype = (gs_decl_unsigned(type_tree) ? MTYPE_U8 :
                                                   MTYPE_I8);
                                                   MTYPE_I8);
            break;
            break;
      default:
      default:
            mtype = (gs_decl_unsigned(type_tree) ? MTYPE_U4 :
            mtype = (gs_decl_unsigned(type_tree) ? MTYPE_U4 :
                                                   MTYPE_I4);
                                                   MTYPE_I4);
    }
    }
#else
#else
    mtype = (gs_decl_unsigned(type_tree) ? MTYPE_U4 : MTYPE_I4);
    mtype = (gs_decl_unsigned(type_tree) ? MTYPE_U4 : MTYPE_I4);
#endif
#endif
    idx = MTYPE_To_TY (mtype);  // use predefined type
    idx = MTYPE_To_TY (mtype);  // use predefined type
    break;
    break;
  case GS_REAL_TYPE:
  case GS_REAL_TYPE:
    switch (tsize) {
    switch (tsize) {
    case 4:  mtype = MTYPE_F4; break;
    case 4:  mtype = MTYPE_F4; break;
    case 8:  mtype = MTYPE_F8; break;
    case 8:  mtype = MTYPE_F8; break;
#ifdef TARG_IA64
#ifdef TARG_IA64
    case 12:
    case 12:
    case 16: mtype = MTYPE_F10; break;
    case 16: mtype = MTYPE_F10; break;
#endif
#endif
#ifdef TARG_X8664
#ifdef TARG_X8664
    case 12: mtype = MTYPE_FQ; break;
    case 12: mtype = MTYPE_FQ; break;
#endif
#endif
#if defined(TARG_MIPS) || defined(TARG_IA32) || defined(TARG_X8664)
#if defined(TARG_MIPS) || defined(TARG_IA32) || defined(TARG_X8664)
    case 16: mtype = MTYPE_FQ; break;
    case 16: mtype = MTYPE_FQ; break;
#endif /* TARG_MIPS */
#endif /* TARG_MIPS */
    default:  FmtAssert(FALSE, ("Get_TY unexpected size"));
    default:  FmtAssert(FALSE, ("Get_TY unexpected size"));
    }
    }
    idx = MTYPE_To_TY (mtype);  // use predefined type
    idx = MTYPE_To_TY (mtype);  // use predefined type
    break;
    break;
  case GS_COMPLEX_TYPE:
  case GS_COMPLEX_TYPE:
    switch (tsize) {
    switch (tsize) {
    case 2:
    case 2:
    case 4: ErrMsg (EC_Unsupported_Type, "Complex integer");
    case 4: ErrMsg (EC_Unsupported_Type, "Complex integer");
    case  8:  mtype = MTYPE_C4; break;
    case  8:  mtype = MTYPE_C4; break;
    case 16:  mtype = MTYPE_C8; break;
    case 16:  mtype = MTYPE_C8; break;
#ifdef TARG_IA64
#ifdef TARG_IA64
    case 32: mtype = MTYPE_C10; break;
    case 32: mtype = MTYPE_C10; break;
#endif
#endif
#ifdef TARG_X8664
#ifdef TARG_X8664
    case 24:  mtype = MTYPE_CQ; break;
    case 24:  mtype = MTYPE_CQ; break;
#endif
#endif
#if defined(TARG_MIPS) || defined(TARG_IA32) || defined(TARG_X8664)
#if defined(TARG_MIPS) || defined(TARG_IA32) || defined(TARG_X8664)
    case 32: mtype = MTYPE_CQ; break;
    case 32: mtype = MTYPE_CQ; break;
#endif /* TARG_MIPS */
#endif /* TARG_MIPS */
    default:  FmtAssert(FALSE, ("Get_TY unexpected size"));
    default:  FmtAssert(FALSE, ("Get_TY unexpected size"));
    }
    }
    idx = MTYPE_To_TY (mtype);  // use predefined type
    idx = MTYPE_To_TY (mtype);  // use predefined type
    break;
    break;
  case GS_POINTER_TYPE:
  case GS_POINTER_TYPE:
    if (gs_type_ptrmem_p(type_tree)) {
    if (gs_type_ptrmem_p(type_tree)) {
      // pointer to member
      // pointer to member
      idx = Be_Type_Tbl(Pointer_Size == 8 ? MTYPE_I8 : MTYPE_I4);
      idx = Be_Type_Tbl(Pointer_Size == 8 ? MTYPE_I8 : MTYPE_I4);
      break;
      break;
    }
    }
    /* FALLTHRU */
    /* FALLTHRU */
  case GS_REFERENCE_TYPE:
  case GS_REFERENCE_TYPE:
    idx = Make_Pointer_Type (Get_TY (gs_tree_type(type_tree)));
    idx = Make_Pointer_Type (Get_TY (gs_tree_type(type_tree)));
    Set_TY_align (idx, align);
    Set_TY_align (idx, align);
    break;
    break;
  case GS_ARRAY_TYPE:
  case GS_ARRAY_TYPE:
    { // new scope for local vars
    { // new scope for local vars
#ifdef KEY /* bug 8346 */
#ifdef KEY /* bug 8346 */
    TY &ty = (idx == TY_IDX_ZERO) ? New_TY(idx) : Ty_Table[idx];
    TY &ty = (idx == TY_IDX_ZERO) ? New_TY(idx) : Ty_Table[idx];
    Clear_TY_is_incomplete (idx);
    Clear_TY_is_incomplete (idx);
#else
#else
    TY &ty = New_TY (idx);
    TY &ty = New_TY (idx);
#endif
#endif
    TY_Init (ty, tsize, KIND_ARRAY, MTYPE_M,
    TY_Init (ty, tsize, KIND_ARRAY, MTYPE_M,
      Save_Str(Get_Name(gs_type_name(type_tree))) );
      Save_Str(Get_Name(gs_type_name(type_tree))) );
                // for the anonymoust array
                // for the anonymoust array
                if (gs_type_name(type_tree) == NULL)
                if (gs_type_name(type_tree) == NULL)
                    Set_TY_anonymous(ty);
                    Set_TY_anonymous(ty);
    Set_TY_etype (ty, Get_TY (gs_tree_type(type_tree)));
    Set_TY_etype (ty, Get_TY (gs_tree_type(type_tree)));
    Set_TY_align (idx, TY_align(TY_etype(ty)));
    Set_TY_align (idx, TY_align(TY_etype(ty)));
    // assumes 1 dimension
    // assumes 1 dimension
    // nested arrays are treated as arrays of arrays
    // nested arrays are treated as arrays of arrays
    ARB_HANDLE arb = New_ARB ();
    ARB_HANDLE arb = New_ARB ();
    ARB_Init (arb, 0, 0, 0);
    ARB_Init (arb, 0, 0, 0);
    Set_TY_arb (ty, arb);
    Set_TY_arb (ty, arb);
    Set_ARB_first_dimen (arb);
    Set_ARB_first_dimen (arb);
    Set_ARB_last_dimen (arb);
    Set_ARB_last_dimen (arb);
    Set_ARB_dimension (arb, 1);
    Set_ARB_dimension (arb, 1);
    if (gs_type_size(gs_tree_type(type_tree)) == 0)
    if (gs_type_size(gs_tree_type(type_tree)) == 0)
      break; // anomaly:  type will never be needed
      break; // anomaly:  type will never be needed
    // =================== Array stride ======================
    // =================== Array stride ======================
    if (gs_tree_code(gs_type_size(gs_tree_type(type_tree))) == GS_INTEGER_CST) {
    if (gs_tree_code(gs_type_size(gs_tree_type(type_tree))) == GS_INTEGER_CST) {
      Set_ARB_const_stride (arb);
      Set_ARB_const_stride (arb);
      Set_ARB_stride_val (arb,
      Set_ARB_stride_val (arb,
        gs_get_integer_value (gs_type_size(gs_tree_type(type_tree)))
        gs_get_integer_value (gs_type_size_unit(gs_tree_type(type_tree))));
        / BITSPERBYTE);
 
    }
    }
#ifdef KEY /* bug 8346 */
#ifdef KEY /* bug 8346 */
    else if (!expanding_function_definition &&
    else if (!expanding_function_definition &&
             processing_function_prototype)
             processing_function_prototype)
    {
    {
      Set_ARB_const_stride (arb);
      Set_ARB_const_stride (arb);
      // dummy stride val 4
      // dummy stride val 4
      Set_ARB_stride_val (arb, 4);
      Set_ARB_stride_val (arb, 4);
      Set_TY_is_incomplete (idx);
      Set_TY_is_incomplete (idx);
    }
    }
#endif
#endif
    else {
    else {
      WN *swn;
      WN *swn;
      swn = WGEN_Expand_Expr (gs_type_size(gs_tree_type(type_tree)));
      swn = WGEN_Expand_Expr (gs_type_size_unit(gs_tree_type(type_tree)));
      if (WN_opcode (swn) == OPC_U4I4CVT ||
      if (WN_opcode (swn) == OPC_U4I4CVT ||
          WN_opcode (swn) == OPC_U8I8CVT) {
          WN_opcode (swn) == OPC_U8I8CVT) {
        swn = WN_kid0 (swn);
        swn = WN_kid0 (swn);
      }
      }
#ifdef KEY
#ifdef KEY
      // In the event that swn operator is not
      // In the event that swn operator is not
      // OPR_LDID, save expr node swn
      // OPR_LDID, save expr node swn
      // and use LDID of that stored address as swn.
      // and use LDID of that stored address as swn.
      // Copied from Wfe_Save_Expr in wfe_expr.cxx
      // Copied from Wfe_Save_Expr in wfe_expr.cxx
      if (WN_operator (swn) != OPR_LDID) {
      if (WN_operator (swn) != OPR_LDID) {
        TY_IDX    ty_idx  =
 
          Get_TY (gs_tree_type (type_size));
        TYPE_ID   mtype   = WN_rtype(swn);
        TYPE_ID   mtype   = TY_mtype (ty_idx);
        TY_IDX    ty_idx  = MTYPE_To_TY(mtype);
        ST       *st;
        ST       *st;
        st = Gen_Temp_Symbol (ty_idx, "__save_expr");
        st = Gen_Temp_Symbol (ty_idx, "__save_expr");
#ifdef FE_GNU_4_2_0
#ifdef FE_GNU_4_2_0
        WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
        WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
#endif
#endif
        WGEN_Set_ST_Addr_Saved (swn);
        WGEN_Set_ST_Addr_Saved (swn);
        swn = WN_Stid (mtype, 0, st, ty_idx, swn);
        swn = WN_Stid (mtype, 0, st, ty_idx, swn);
        WGEN_Stmt_Append (swn, Get_Srcpos());
        WGEN_Stmt_Append (swn, Get_Srcpos());
        swn = WN_Ldid (mtype, 0, st, ty_idx);
        swn = WN_Ldid (mtype, 0, st, ty_idx);
      }
      }
#endif /* KEY */
#endif /* KEY */
      FmtAssert (WN_operator (swn) == OPR_LDID,
      FmtAssert (WN_operator (swn) == OPR_LDID,
        ("stride operator for VLA not LDID"));
        ("stride operator for VLA not LDID"));
      ST *st = WN_st (swn);
      ST *st = WN_st (swn);
      TY_IDX ty_idx = ST_type (st);
      TY_IDX ty_idx = ST_type (st);
      WN *wn = WN_CreateXpragma (WN_PRAGMA_COPYIN_BOUND,
      WN *wn = WN_CreateXpragma (WN_PRAGMA_COPYIN_BOUND,
               (ST_IDX) NULL, 1);
               (ST_IDX) NULL, 1);
      WN_kid0 (wn) = WN_Ldid (TY_mtype (ty_idx), 0, st, ty_idx);
      WN_kid0 (wn) = WN_Ldid (TY_mtype (ty_idx), 0, st, ty_idx);
      WGEN_Stmt_Append (wn, Get_Srcpos());
      WGEN_Stmt_Append (wn, Get_Srcpos());
      Clear_ARB_const_stride (arb);
      Clear_ARB_const_stride (arb);
      Set_ARB_stride_var (arb, (ST_IDX) ST_st_idx (st));
      Set_ARB_stride_var (arb, (ST_IDX) ST_st_idx (st));
#ifdef KEY /* bug 8346 */
#ifdef KEY /* bug 8346 */
      Clear_TY_is_incomplete (idx);
      Clear_TY_is_incomplete (idx);
#endif
#endif
    }
    }
    // ================= Array lower bound =================
    // ================= Array lower bound =================
    Set_ARB_const_lbnd (arb);
    Set_ARB_const_lbnd (arb);
    Set_ARB_lbnd_val (arb, 0);
    Set_ARB_lbnd_val (arb, 0);
    // ================= Array upper bound =================
    // ================= Array upper bound =================
    if (type_size) {
    if (type_size) {
#ifdef KEY
#ifdef KEY
        // For Zero-length arrays, TYPE_MAX_VALUE tree is NULL
        // For Zero-length arrays, TYPE_MAX_VALUE tree is NULL
        if (!gs_type_max_value (gs_type_domain (type_tree))) {
        if (!gs_type_max_value (gs_type_domain (type_tree))) {
      Set_ARB_const_ubnd (arb);
      Set_ARB_const_ubnd (arb);
      Set_ARB_ubnd_val (arb, 0xffffffff);
      Set_ARB_ubnd_val (arb, 0xffffffff);
        } else
        } else
#endif /* KEY */
#endif /* KEY */
        if (gs_tree_code(gs_type_max_value (gs_type_domain (type_tree))) ==
        if (gs_tree_code(gs_type_max_value (gs_type_domain (type_tree))) ==
      GS_INTEGER_CST) {
      GS_INTEGER_CST) {
      Set_ARB_const_ubnd (arb);
      Set_ARB_const_ubnd (arb);
      Set_ARB_ubnd_val (arb, gs_get_integer_value (
      Set_ARB_ubnd_val (arb, gs_get_integer_value (
        gs_type_max_value (gs_type_domain (type_tree)) ));
        gs_type_max_value (gs_type_domain (type_tree)) ));
        }
        }
#ifdef KEY /* bug 8346 */
#ifdef KEY /* bug 8346 */
        else if (!expanding_function_definition &&
        else if (!expanding_function_definition &&
                 processing_function_prototype) {
                 processing_function_prototype) {
      Set_ARB_const_ubnd (arb);
      Set_ARB_const_ubnd (arb);
      // dummy upper bound 8
      // dummy upper bound 8
      Set_ARB_ubnd_val (arb, 8);
      Set_ARB_ubnd_val (arb, 8);
      Set_TY_is_incomplete (idx);
      Set_TY_is_incomplete (idx);
        }
        }
#endif
#endif
        else {
        else {
      WN *uwn = WGEN_Expand_Expr (gs_type_max_value (gs_type_domain (type_tree)) );
      WN *uwn = WGEN_Expand_Expr (gs_type_max_value (gs_type_domain (type_tree)) );
      if (WN_opcode (uwn) == OPC_U4I4CVT ||
      if (WN_opcode (uwn) == OPC_U4I4CVT ||
          WN_opcode (uwn) == OPC_U8I8CVT) {
          WN_opcode (uwn) == OPC_U8I8CVT) {
        uwn = WN_kid0 (uwn);
        uwn = WN_kid0 (uwn);
      }
      }
      ST *st;
      ST *st;
      TY_IDX ty_idx;
      TY_IDX ty_idx;
      WN *wn;
      WN *wn;
      if (WN_operator (uwn) != OPR_LDID) {
      if (WN_operator (uwn) != OPR_LDID) {
        ty_idx = Get_TY (gs_tree_type (gs_type_max_value (gs_type_domain (type_tree)) ) );
        ty_idx  = MTYPE_To_TY(WN_rtype(uwn));
        st = Gen_Temp_Symbol (ty_idx, "__vla_bound");
        st = Gen_Temp_Symbol (ty_idx, "__vla_bound");
#ifdef FE_GNU_4_2_0
#ifdef FE_GNU_4_2_0
          WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
          WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
#endif
#endif
        wn = WN_Stid (TY_mtype (ty_idx), 0, st, ty_idx, uwn);
        wn = WN_Stid (TY_mtype (ty_idx), 0, st, ty_idx, uwn);
        WGEN_Stmt_Append (wn, Get_Srcpos());
        WGEN_Stmt_Append (wn, Get_Srcpos());
      }
      }
      else {
      else {
        st = WN_st (uwn);
        st = WN_st (uwn);
        ty_idx = ST_type (st);
        ty_idx = ST_type (st);
      }
      }
      wn = WN_CreateXpragma (WN_PRAGMA_COPYIN_BOUND, (ST_IDX) NULL, 1);
      wn = WN_CreateXpragma (WN_PRAGMA_COPYIN_BOUND, (ST_IDX) NULL, 1);
      WN_kid0 (wn) = WN_Ldid (TY_mtype (ty_idx), 0, st, ty_idx);
      WN_kid0 (wn) = WN_Ldid (TY_mtype (ty_idx), 0, st, ty_idx);
      WGEN_Stmt_Append (wn, Get_Srcpos());
      WGEN_Stmt_Append (wn, Get_Srcpos());
      Clear_ARB_const_ubnd (arb);
      Clear_ARB_const_ubnd (arb);
      Set_ARB_ubnd_var (arb, ST_st_idx (st));
      Set_ARB_ubnd_var (arb, ST_st_idx (st));
#ifdef KEY /* bug 8346 */
#ifdef KEY /* bug 8346 */
      Clear_TY_is_incomplete (idx);
      Clear_TY_is_incomplete (idx);
#endif
#endif
        }
        }
    }
    }
    else {
    else {
      Clear_ARB_const_ubnd (arb);
      Clear_ARB_const_ubnd (arb);
      Set_ARB_ubnd_val (arb, 0);
      Set_ARB_ubnd_val (arb, 0);
    }
    }
    // ==================== Array size ====================
    // ==================== Array size ====================
    if (variable_size) {
    if (variable_size) {
#ifdef KEY /* bug 8346 */
#ifdef KEY /* bug 8346 */
       if (!expanding_function_definition &&
       if (!expanding_function_definition &&
           processing_function_prototype) {
           processing_function_prototype) {
         Set_TY_is_incomplete (idx);
         Set_TY_is_incomplete (idx);
       }
       }
       else
       else
#endif
#endif
       {
       {
      WN *swn, *wn;
      WN *swn, *wn;
      swn = WGEN_Expand_Expr (type_size);
      swn = WGEN_Expand_Expr (gs_type_size_unit(type_tree));
      if (TY_size(TY_etype(ty))) {
      if (TY_size(TY_etype(ty))) {
        if (WN_opcode (swn) == OPC_U4I4CVT ||
        if (WN_opcode (swn) == OPC_U4I4CVT ||
            WN_opcode (swn) == OPC_U8I8CVT) {
            WN_opcode (swn) == OPC_U8I8CVT) {
          swn = WN_kid0 (swn);
          swn = WN_kid0 (swn);
        }
        }
#ifdef KEY
#ifdef KEY
        // In the event that swn operator is not
        // In the event that swn operator is not
        // OPR_LDID, save expr node swn
        // OPR_LDID, save expr node swn
        // and use LDID of that stored address as swn.
        // and use LDID of that stored address as swn.
        // Copied from Wfe_Save_Expr in wfe_expr.cxx
        // Copied from Wfe_Save_Expr in wfe_expr.cxx
        if (WN_operator (swn) != OPR_LDID) {
        if (WN_operator (swn) != OPR_LDID) {
          TY_IDX    ty_idx  =
          TYPE_ID   mtype   = WN_rtype(swn);
            Get_TY (gs_tree_type (type_size));
          TY_IDX    ty_idx  = MTYPE_To_TY(mtype);
          TYPE_ID   mtype   = TY_mtype (ty_idx);
 
          ST       *st;
          ST       *st;
          st = Gen_Temp_Symbol (ty_idx, "__save_expr");
          st = Gen_Temp_Symbol (ty_idx, "__save_expr");
#ifdef FE_GNU_4_2_0
#ifdef FE_GNU_4_2_0
            WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
            WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
#endif
#endif
          WGEN_Set_ST_Addr_Saved (swn);
          WGEN_Set_ST_Addr_Saved (swn);
          swn = WN_Stid (mtype, 0, st, ty_idx, swn);
          swn = WN_Stid (mtype, 0, st, ty_idx, swn);
          WGEN_Stmt_Append (swn, Get_Srcpos());
          WGEN_Stmt_Append (swn, Get_Srcpos());
          swn = WN_Ldid (mtype, 0, st, ty_idx);
          swn = WN_Ldid (mtype, 0, st, ty_idx);
        }
        }
#endif /* KEY */
#endif /* KEY */
        FmtAssert (WN_operator (swn) == OPR_LDID,
        FmtAssert (WN_operator (swn) == OPR_LDID,
          ("size operator for VLA not LDID"));
          ("size operator for VLA not LDID"));
        ST *st = WN_st (swn);
        ST *st = WN_st (swn);
        TY_IDX ty_idx = ST_type (st);
        TY_IDX ty_idx = ST_type (st);
        TYPE_ID mtype = TY_mtype (ty_idx);
        TYPE_ID mtype = TY_mtype (ty_idx);
        swn = WN_Div (mtype, swn, WN_Intconst (mtype, BITSPERBYTE));
 
        wn = WN_Stid (mtype, 0, st, ty_idx, swn);
        wn = WN_Stid (mtype, 0, st, ty_idx, swn);
        WGEN_Stmt_Append (wn, Get_Srcpos());
        WGEN_Stmt_Append (wn, Get_Srcpos());
      }
      }
#ifdef KEY /* bug 8346 */
#ifdef KEY /* bug 8346 */
      Clear_TY_is_incomplete (idx);
      Clear_TY_is_incomplete (idx);
#endif
#endif
       }
       }
    }
    }
    } // end array scope
    } // end array scope
    break;
    break;
  case GS_RECORD_TYPE:
  case GS_RECORD_TYPE:
  case GS_UNION_TYPE:
  case GS_UNION_TYPE:
    { // new scope for local vars
    { // new scope for local vars
    TY &ty = (idx == TY_IDX_ZERO) ? New_TY(idx) : Ty_Table[idx];
    TY &ty = (idx == TY_IDX_ZERO) ? New_TY(idx) : Ty_Table[idx];
#ifdef KEY
#ifdef KEY
    // Must create DSTs in the order that the records are declared,
    // Must create DSTs in the order that the records are declared,
    // in order to preserve their scope.  Bug 4168.
    // in order to preserve their scope.  Bug 4168.
    if (Debug_Level >= 2)
    if (Debug_Level >= 2)
      defer_DST_type(type_tree, idx, orig_idx);
      defer_DST_type(type_tree, idx, orig_idx);
    // GCC 3.2 pads empty structures with a fake 1-byte field.
    // GCC 3.2 pads empty structures with a fake 1-byte field.
    // These structures should have tsize = 0.
    // These structures should have tsize = 0.
    if (tsize != 0 &&
    if (tsize != 0 &&
        // is_empty_class assumes non-null CLASSTYPE_SIZE
        // is_empty_class assumes non-null CLASSTYPE_SIZE
        // check if it has lang-specific data
        // check if it has lang-specific data
        gs_type_lang_specific(type_tree) &&
        gs_type_lang_specific(type_tree) &&
        // check if it has its base version set
        // check if it has its base version set
        gs_classtype_as_base(type_tree) &&
        gs_classtype_as_base(type_tree) &&
        gs_classtype_size(type_tree) &&
        gs_classtype_size(type_tree) &&
        gs_is_empty_class(type_tree))
        gs_is_empty_class(type_tree))
      tsize = 0;
      tsize = 0;
#endif  // KEY
#endif  // KEY
    TY_Init (ty, tsize, KIND_STRUCT, MTYPE_M,
    TY_Init (ty, tsize, KIND_STRUCT, MTYPE_M,
      Save_Str(Get_Name(gs_type_name(type_tree))) );
      Save_Str(Get_Name(gs_type_name(type_tree))) );
                if (gs_type_name(type_tree) == NULL)
                if (gs_type_name(type_tree) == NULL)
                    Set_TY_anonymous(ty);
                    Set_TY_anonymous(ty);
    if (gs_tree_code(type_tree) == GS_UNION_TYPE) {
    if (gs_tree_code(type_tree) == GS_UNION_TYPE) {
      Set_TY_is_union(idx);
      Set_TY_is_union(idx);
    }
    }
#ifdef KEY
#ifdef KEY
    if (gs_aggregate_value_p(type_tree)) {
    if (gs_aggregate_value_p(type_tree)) {
      Set_TY_return_in_mem(idx);
      Set_TY_return_in_mem(idx);
    }
    }
#endif
#endif
    if (align == 0) align = 1;  // in case incomplete type
    if (align == 0) align = 1;  // in case incomplete type
    Set_TY_align (idx, align);
    Set_TY_align (idx, align);
    // set idx now in case recurse thru fields
    // set idx now in case recurse thru fields
    TYPE_TY_IDX(type_tree) = idx;
    TYPE_TY_IDX(type_tree) = idx;
    Do_Base_Types (type_tree);
    Do_Base_Types (type_tree);
    // Process nested structs and static data members first
    // Process nested structs and static data members first
                for (gs_t field =  get_first_real_or_virtual_field (type_tree);
                for (gs_t field =  get_first_real_or_virtual_field (type_tree);
                          field;
                          field;
                          field = next_real_field(type_tree, field)) {
                          field = next_real_field(type_tree, field)) {
        Set_TY_content_seen(idx); // bug 10851
        Set_TY_content_seen(idx); // bug 10851
                        if (gs_tree_code(field) == GS_TYPE_DECL ||
                        if (gs_tree_code(field) == GS_TYPE_DECL ||
          gs_tree_code(field) == GS_FIELD_DECL) {
          gs_tree_code(field) == GS_FIELD_DECL) {
                                gs_t field_type = gs_tree_type(field);
                                gs_t field_type = gs_tree_type(field);
        if ((gs_tree_code(field_type) == GS_RECORD_TYPE ||
        if ((gs_tree_code(field_type) == GS_RECORD_TYPE ||
             gs_tree_code(field_type) == GS_UNION_TYPE) &&
             gs_tree_code(field_type) == GS_UNION_TYPE) &&
                                    field_type != type_tree) {
                                    field_type != type_tree) {
#ifdef KEY
#ifdef KEY
          // Defer typedefs within class
          // Defer typedefs within class
          // declarations to avoid circular
          // declarations to avoid circular
          // declaration dependences.  See
          // declaration dependences.  See
          // example in bug 5134.
          // example in bug 5134.
                                        if (gs_tree_code(field) == GS_TYPE_DECL)
                                        if (gs_tree_code(field) == GS_TYPE_DECL)
            defer_decl(field_type);
            defer_decl(field_type);
                                        else
                                        else
#endif
#endif
                                        Get_TY(field_type);
                                        Get_TY(field_type);
        }
        }
                        }
                        }
#ifdef KEY  // Defer expansion of static vars until all the fields in
#ifdef KEY  // Defer expansion of static vars until all the fields in
    // _every_ struct are laid out.  Consider this code (see
    // _every_ struct are laid out.  Consider this code (see
    // bug 3044):
    // bug 3044):
    //  struct A
    //  struct A
    //    struct B *p
    //    struct B *p
    //  struct B
    //  struct B
    //    static struct A *q = ...  // static data member with
    //    static struct A *q = ...  // static data member with
    //                              // initializer
    //                              // initializer
    // We cannot expand static member vars while expanding the
    // We cannot expand static member vars while expanding the
    // enclosing stuct, for the following reason:  Expansion of
    // enclosing stuct, for the following reason:  Expansion of
    // struct A leads to expansion of p, which leads to the
    // struct A leads to expansion of p, which leads to the
    // expansion of struct B, which leads to the expansion of q and
    // expansion of struct B, which leads to the expansion of q and
    // q's initializer.  The code that expands the initializer goes
    // q's initializer.  The code that expands the initializer goes
    // through the fields of struct A, but these fields are not yet
    // through the fields of struct A, but these fields are not yet
    // completely defined, and this will cause kg++fe to die.
    // completely defined, and this will cause kg++fe to die.
    //
    //
    // The solution is the delay all static var expansions until
    // The solution is the delay all static var expansions until
    // the very end.
    // the very end.
      else if (gs_tree_code(field) == GS_VAR_DECL)
      else if (gs_tree_code(field) == GS_VAR_DECL)
        defer_decl(field);
        defer_decl(field);
#else
#else
      else if (gs_tree_code(field) == GS_VAR_DECL)
      else if (gs_tree_code(field) == GS_VAR_DECL)
        WGEN_Expand_Decl(field, TRUE);
        WGEN_Expand_Decl(field, TRUE);
#endif
#endif
      else if (gs_tree_code(field) == GS_TEMPLATE_DECL)
      else if (gs_tree_code(field) == GS_TEMPLATE_DECL)
        WGEN_Expand_Decl(field, TRUE);
        WGEN_Expand_Decl(field, TRUE);
          }
          }
      Set_TY_fld (ty, FLD_HANDLE());
      Set_TY_fld (ty, FLD_HANDLE());
    FLD_IDX first_field_idx = Fld_Table.Size ();
    FLD_IDX first_field_idx = Fld_Table.Size ();
    gs_t field;
    gs_t field;
    gs_t method = gs_type_methods(type_tree);
    gs_t method = gs_type_methods(type_tree);
    FLD_HANDLE fld;
    FLD_HANDLE fld;
    INT32 next_field_id = 1;
    INT32 next_field_id = 1;
#ifdef KEY
#ifdef KEY
    // In GCC 4, the same tree node representing a vtable ptr field
    // In GCC 4, the same tree node representing a vtable ptr field
    // can appear in different derived classes.  As a result,
    // can appear in different derived classes.  As a result,
    // DECL_FIELD_ID(field) can't be used to map its field ID.  As
    // DECL_FIELD_ID(field) can't be used to map its field ID.  As
    // a fix, always allocate field ID 1 to the vtable ptr field.
    // a fix, always allocate field ID 1 to the vtable ptr field.
    // Do this before allocating IDs to any other field.
    // Do this before allocating IDs to any other field.
    gs_t vfield = get_virtual_field(type_tree);
    gs_t vfield = get_virtual_field(type_tree);
    if (vfield) {
    if (vfield) {
      Is_True(gs_tree_code(vfield) == GS_FIELD_DECL,
      Is_True(gs_tree_code(vfield) == GS_FIELD_DECL,
        ("Create_TY_For_Tree: bad vfield code"));
        ("Create_TY_For_Tree: bad vfield code"));
      Is_True(gs_decl_name(vfield) &&
      Is_True(gs_decl_name(vfield) &&
        !strncmp(Get_Name(gs_decl_name(vfield)),"_vptr", 5),
        !strncmp(Get_Name(gs_decl_name(vfield)),"_vptr", 5),
        ("Create_TY_For_Tree: bad vfield name"));
        ("Create_TY_For_Tree: bad vfield name"));
      // The vfield field ID is either not set, or was set to 1.
      // The vfield field ID is either not set, or was set to 1.
      Is_True(DECL_FIELD_ID(vfield) <= 1,
      Is_True(DECL_FIELD_ID(vfield) <= 1,
        ("Create_TY_For_Tree: invalid vfield field ID"));
        ("Create_TY_For_Tree: invalid vfield field ID"));
      DECL_FIELD_ID(vfield) = next_field_id;  // must be 1
      DECL_FIELD_ID(vfield) = next_field_id;  // must be 1
      next_field_id += TYPE_FIELD_IDS_USED(gs_tree_type(vfield)) +1;
      next_field_id += TYPE_FIELD_IDS_USED(gs_tree_type(vfield)) +1;
      fld = New_FLD ();
      fld = New_FLD ();
      FLD_Init(fld, Save_Str(Get_Name(gs_decl_name(vfield))),
      FLD_Init(fld, Save_Str(Get_Name(gs_decl_name(vfield))),
         0, // type
         0, // type
         gs_get_integer_value(gs_decl_field_offset(vfield))
         gs_get_integer_value(gs_decl_field_offset(vfield))
          + gs_get_integer_value(gs_decl_field_bit_offset(vfield))
          + gs_get_integer_value(gs_decl_field_bit_offset(vfield))
          / BITSPERBYTE);
          / BITSPERBYTE);
    }
    }
#endif
#endif
    // Generate an anonymous field for every direct, nonempty,
    // Generate an anonymous field for every direct, nonempty,
    // nonvirtual base class.
    // nonvirtual base class.
    INT32 offset = 0;
    INT32 offset = 0;
    INT32 anonymous_fields = 0;
    INT32 anonymous_fields = 0;
#ifndef KEY // g++'s class.c already laid out the base types.  Bug 11622.
#ifndef KEY // g++'s class.c already laid out the base types.  Bug 11622.
    gs_t type_binfo, basetypes;
    gs_t type_binfo, basetypes;
    if ((type_binfo = gs_type_binfo(type_tree)) != NULL &&
    if ((type_binfo = gs_type_binfo(type_tree)) != NULL &&
        (basetypes = gs_binfo_base_binfos(type_binfo)) != NULL) {
        (basetypes = gs_binfo_base_binfos(type_binfo)) != NULL) {
      gs_t list;
      gs_t list;
      for (list = basetypes; gs_code(list) != EMPTY;
      for (list = basetypes; gs_code(list) != EMPTY;
           list = gs_operand(list, 1)) {
           list = gs_operand(list, 1)) {
        gs_t binfo = gs_operand(list, 0);
        gs_t binfo = gs_operand(list, 0);
        gs_t basetype = gs_binfo_type(binfo);
        gs_t basetype = gs_binfo_type(binfo);
        offset = Roundup (offset,
        offset = Roundup (offset,
            gs_type_align(basetype) / BITSPERBYTE);
            gs_type_align(basetype) / BITSPERBYTE);
        if (!is_empty_base_class(basetype) ||
        if (!is_empty_base_class(basetype) ||
      !gs_binfo_virtual_p(binfo)) {
      !gs_binfo_virtual_p(binfo)) {
          ++next_field_id;
          ++next_field_id;
          ++anonymous_fields;
          ++anonymous_fields;
          next_field_id += TYPE_FIELD_IDS_USED(basetype);
          next_field_id += TYPE_FIELD_IDS_USED(basetype);
          fld = New_FLD();
          fld = New_FLD();
          FLD_Init (fld, Save_Str(Get_Name(0)),
          FLD_Init (fld, Save_Str(Get_Name(0)),
        Get_TY(basetype), offset);
        Get_TY(basetype), offset);
          offset += Type_Size_Without_Vbases (basetype);
          offset += Type_Size_Without_Vbases (basetype);
                      Set_FLD_is_anonymous(fld);
                      Set_FLD_is_anonymous(fld);
#ifdef KEY
#ifdef KEY
// temporary hack for a bug in gcc
// temporary hack for a bug in gcc
// Details: From layout_class_type(), it turns out that for this
// Details: From layout_class_type(), it turns out that for this
// type, gcc is apparently sending wrong type info, they have 2 fields
// type, gcc is apparently sending wrong type info, they have 2 fields
// each 8 bytes in a 'record', with the type size == 8 bytes also!
// each 8 bytes in a 'record', with the type size == 8 bytes also!
// So we take care of it here...
// So we take care of it here...
          if (offset > tsize)
          if (offset > tsize)
      {
      {
          tsize = offset;
          tsize = offset;
          Set_TY_size (ty, tsize);
          Set_TY_size (ty, tsize);
      }
      }
#endif // KEY
#endif // KEY
        }
        }
      }
      }
    }
    }
#endif // KEY
#endif // KEY
                hash_set <gs_t, void_ptr_hash> anonymous_base;
                hash_set <gs_t, void_ptr_hash> anonymous_base;
                gs_t type_binfo, basetypes;
                gs_t type_binfo, basetypes;
                // find all base classes
                // find all base classes
                if ((type_binfo = gs_type_binfo(type_tree)) != NULL &&
                if ((type_binfo = gs_type_binfo(type_tree)) != NULL &&
                    (basetypes = gs_binfo_base_binfos(type_binfo)) != NULL) {
                    (basetypes = gs_binfo_base_binfos(type_binfo)) != NULL) {
                  gs_t list;
                  gs_t list;
                  for (list = basetypes; gs_code(list) != EMPTY;
                  for (list = basetypes; gs_code(list) != EMPTY;
                       list = gs_operand(list, 1)) {
                       list = gs_operand(list, 1)) {
                    gs_t binfo = gs_operand(list, 0);
                    gs_t binfo = gs_operand(list, 0);
                    gs_t basetype = gs_binfo_type(binfo);
                    gs_t basetype = gs_binfo_type(binfo);
                    anonymous_base.insert(basetype);
                    anonymous_base.insert(basetype);
                  }
                  }
                }
                }
    // Assign IDs to real fields.  The vtable ptr field is already
    // Assign IDs to real fields.  The vtable ptr field is already
    // assigned ID 1.
    // assigned ID 1.
    for (field = get_first_real_field(type_tree);
    for (field = get_first_real_field(type_tree);
      field;
      field;
      field = next_real_field(type_tree, field) )
      field = next_real_field(type_tree, field) )
    {
    {
      if (gs_tree_code(field) == GS_TYPE_DECL) {
      if (gs_tree_code(field) == GS_TYPE_DECL) {
        continue;
        continue;
      }
      }
      if (gs_tree_code(field) == GS_CONST_DECL) {
      if (gs_tree_code(field) == GS_CONST_DECL) {
        DevWarn ("got CONST_DECL in field list");
        DevWarn ("got CONST_DECL in field list");
        continue;
        continue;
      }
      }
      if (gs_tree_code(field) == GS_VAR_DECL) {
      if (gs_tree_code(field) == GS_VAR_DECL) {
        continue;
        continue;
      }
      }
      if (gs_tree_code(field) == GS_TEMPLATE_DECL) {
      if (gs_tree_code(field) == GS_TEMPLATE_DECL) {
        continue;
        continue;
      }
      }
      // Either the DECL_FIELD_ID is not yet set, or is
      // Either the DECL_FIELD_ID is not yet set, or is
      // already set to the same field ID.  The latter
      // already set to the same field ID.  The latter
      // happens when GCC 4 duplicates the type tree and the
      // happens when GCC 4 duplicates the type tree and the
      // same field node appears in both type nodes.
      // same field node appears in both type nodes.
      Is_True(DECL_FIELD_ID(field) == 0 ||
      Is_True(DECL_FIELD_ID(field) == 0 ||
        DECL_FIELD_ID(field) == next_field_id,
        DECL_FIELD_ID(field) == next_field_id,
        ("Create_TY_For_Tree: field ID already set"));
        ("Create_TY_For_Tree: field ID already set"));
      DECL_FIELD_ID(field) = next_field_id;
      DECL_FIELD_ID(field) = next_field_id;
      next_field_id +=
      next_field_id +=
        TYPE_FIELD_IDS_USED(gs_tree_type(field)) + 1;
        TYPE_FIELD_IDS_USED(gs_tree_type(field)) + 1;
      fld = New_FLD ();
      fld = New_FLD ();
      FLD_Init (fld, Save_Str(Get_Name(gs_decl_name(field))),
      FLD_Init (fld, Save_Str(Get_Name(gs_decl_name(field))),
        0, // type
        0, // type
        gs_get_integer_value(gs_decl_field_offset(field)) +
        gs_get_integer_value(gs_decl_field_offset(field)) +
        gs_get_integer_value(gs_decl_field_bit_offset(field))
        gs_get_integer_value(gs_decl_field_bit_offset(field))
          / BITSPERBYTE);
          / BITSPERBYTE);
                        if (gs_decl_name(field) == NULL)
                        if (gs_decl_name(field) == NULL)
                            Set_FLD_is_anonymous(fld);
                            Set_FLD_is_anonymous(fld);
                        if (anonymous_base.find(gs_tree_type(field)) != anonymous_base.end())
                        if (anonymous_base.find(gs_tree_type(field)) != anonymous_base.end())
                            Set_FLD_is_base_class(fld);
                            Set_FLD_is_base_class(fld);
    }
    }
    TYPE_FIELD_IDS_USED(type_tree) = next_field_id - 1;
    TYPE_FIELD_IDS_USED(type_tree) = next_field_id - 1;
      FLD_IDX last_field_idx = Fld_Table.Size () - 1;
      FLD_IDX last_field_idx = Fld_Table.Size () - 1;
    if (last_field_idx >= first_field_idx) {
    if (last_field_idx >= first_field_idx) {
      Set_TY_fld (ty, FLD_HANDLE (first_field_idx));
      Set_TY_fld (ty, FLD_HANDLE (first_field_idx));
      Set_FLD_last_field (FLD_HANDLE (last_field_idx));
      Set_FLD_last_field (FLD_HANDLE (last_field_idx));
    }
    }
    // now set the fld types.
    // now set the fld types.
    fld = TY_fld(ty);
    fld = TY_fld(ty);
#ifdef KEY
#ifdef KEY
    // Handle the vtable ptr field if it exists.
    // Handle the vtable ptr field if it exists.
    if (vfield) {
    if (vfield) {
      Is_True(gs_tree_code(gs_tree_type(vfield)) == GS_POINTER_TYPE,
      Is_True(gs_tree_code(gs_tree_type(vfield)) == GS_POINTER_TYPE,
      ("Create_TY_For_Tree: vtable ptr should be GS_POINTER_TYPE"));
      ("Create_TY_For_Tree: vtable ptr should be GS_POINTER_TYPE"));
      // As mentioned below, don't expand pointer-type fields to
      // As mentioned below, don't expand pointer-type fields to
      // avoid circular dependences.  Defer expanding the field
      // avoid circular dependences.  Defer expanding the field
      // type.
      // type.
      fld = TY_fld(ty);
      fld = TY_fld(ty);
      TY_IDX p_idx = Make_Pointer_Type(MTYPE_To_TY(MTYPE_U8),FALSE);
      TY_IDX p_idx = Make_Pointer_Type(MTYPE_To_TY(MTYPE_U8),FALSE);
      Set_FLD_type(fld, p_idx);
      Set_FLD_type(fld, p_idx);
      defer_field(vfield, fld);
      defer_field(vfield, fld);
      fld = FLD_next(fld);
      fld = FLD_next(fld);
    }
    }
#endif
#endif
    // first skip the anonymous fields, whose types are already
    // first skip the anonymous fields, whose types are already
    // set.
    // set.
    while (anonymous_fields--)
    while (anonymous_fields--)
      fld = FLD_next(fld);
      fld = FLD_next(fld);
    for (field = get_first_real_field(type_tree);
    for (field = get_first_real_field(type_tree);
         /* ugly hack follows; traversing the fields isn't
         /* ugly hack follows; traversing the fields isn't
                        the same from run-to-run. fwa? */
                        the same from run-to-run. fwa? */
      field && fld.Entry();
      field && fld.Entry();
      field = next_real_field(type_tree, field))
      field = next_real_field(type_tree, field))
    {
    {
#ifdef KEY
#ifdef KEY
      const  int FLD_BIT_FIELD_SIZE   = 64;
      const  int FLD_BIT_FIELD_SIZE   = 64;
#endif
#endif
      if (gs_tree_code(field) == GS_TYPE_DECL)
      if (gs_tree_code(field) == GS_TYPE_DECL)
        continue;
        continue;
      if (gs_tree_code(field) == GS_CONST_DECL)
      if (gs_tree_code(field) == GS_CONST_DECL)
        continue;
        continue;
      if (gs_tree_code(field) == GS_VAR_DECL)
      if (gs_tree_code(field) == GS_VAR_DECL)
        continue;
        continue;
      if (gs_tree_code(field) == GS_TEMPLATE_DECL)
      if (gs_tree_code(field) == GS_TEMPLATE_DECL)
        continue;
        continue;
#ifdef KEY
#ifdef KEY
      // Don't expand the field's type if it's a pointer
      // Don't expand the field's type if it's a pointer
      // type, in order to avoid circular dependences
      // type, in order to avoid circular dependences
      // involving member object types and base types.  See
      // involving member object types and base types.  See
      // example in bug 4954.
      // example in bug 4954.
      if (gs_tree_code(gs_tree_type(field)) == GS_POINTER_TYPE) {
      if (gs_tree_code(gs_tree_type(field)) == GS_POINTER_TYPE) {
        // Defer expanding the field's type.  Put in a
        // Defer expanding the field's type.  Put in a
        // generic pointer type for now.
        // generic pointer type for now.
        TY_IDX p_idx =
        TY_IDX p_idx =
          Make_Pointer_Type(MTYPE_To_TY(MTYPE_U8),
          Make_Pointer_Type(MTYPE_To_TY(MTYPE_U8),
                FALSE);
                FALSE);
        Set_FLD_type(fld, p_idx);
        Set_FLD_type(fld, p_idx);
        defer_field(field, fld);
        defer_field(field, fld);
        fld = FLD_next(fld);
        fld = FLD_next(fld);
        continue;
        continue;
      }
      }
#endif
#endif
      TY_IDX fty_idx = Get_TY(gs_tree_type(field));
      TY_IDX fty_idx = Get_TY(gs_tree_type(field));
      if ((TY_align (fty_idx) > align) || (TY_is_packed (fty_idx)))
      if ((TY_align (fty_idx) > align) || (TY_is_packed (fty_idx)))
        Set_TY_is_packed (ty);
        Set_TY_is_packed (ty);
#if 1 // wgen bug 10470
#if 1 // wgen bug 10470
      if (! gs_tree_this_volatile(field))
      if (! gs_tree_this_volatile(field))
        Clear_TY_is_volatile (fty_idx);
        Clear_TY_is_volatile (fty_idx);
#endif
#endif
      Set_FLD_type(fld, fty_idx);
      Set_FLD_type(fld, fty_idx);
      if ( ! gs_decl_bit_field(field)
      if ( ! gs_decl_bit_field(field)
#if 1 // wgen bug 10901
#if 1 // wgen bug 10901
          && gs_tree_code(gs_tree_type(field)) != GS_RECORD_TYPE
          && gs_tree_code(gs_tree_type(field)) != GS_RECORD_TYPE
          && gs_tree_code(gs_tree_type(field)) != GS_UNION_TYPE
          && gs_tree_code(gs_tree_type(field)) != GS_UNION_TYPE
#endif
#endif
          && gs_decl_size(field) // bug 10305
          && gs_decl_size(field) // bug 10305
        && gs_get_integer_value(gs_decl_size(field)) > 0
        && gs_get_integer_value(gs_decl_size(field)) > 0
#ifdef KEY
#ifdef KEY
// We don't handle bit-fields > 64 bits. For an INT field of 128 bits, we
// We don't handle bit-fields > 64 bits. For an INT field of 128 bits, we
// make it 64 bits. But then don't set it as FLD_IS_BIT_FIELD.
// make it 64 bits. But then don't set it as FLD_IS_BIT_FIELD.
        && gs_get_integer_value(gs_decl_size(field)) <=
        && gs_get_integer_value(gs_decl_size(field)) <=
           FLD_BIT_FIELD_SIZE
           FLD_BIT_FIELD_SIZE
        // bug 2401
        // bug 2401
        && TY_size(Get_TY(gs_tree_type(field))) != 0
        && TY_size(Get_TY(gs_tree_type(field))) != 0
#endif
#endif
        && gs_get_integer_value(gs_decl_size(field))
        && gs_get_integer_value(gs_decl_size(field))
          != (TY_size(Get_TY(gs_tree_type(field)))
          != (TY_size(Get_TY(gs_tree_type(field)))
          * BITSPERBYTE) )
          * BITSPERBYTE) )
      {
      {
#ifdef KEY
#ifdef KEY
              FmtAssert( gs_get_integer_value(gs_decl_size(field)) <=
              FmtAssert( gs_get_integer_value(gs_decl_size(field)) <=
             FLD_BIT_FIELD_SIZE,
             FLD_BIT_FIELD_SIZE,
             ("field size too big") );
             ("field size too big") );
#endif
#endif
        // for some reason gnu doesn't set bit field
        // for some reason gnu doesn't set bit field
        // when have bit-field of standard size
        // when have bit-field of standard size
        // (e.g. int f: 16;).  But we need it set
        // (e.g. int f: 16;).  But we need it set
        // so we know how to pack it, because
        // so we know how to pack it, because
        // otherwise the field type is wrong.
        // otherwise the field type is wrong.
        DevWarn("field size %lld doesn't match type size %lld",
        DevWarn("field size %lld doesn't match type size %lld",
          gs_get_integer_value(gs_decl_size(field)),
          gs_get_integer_value(gs_decl_size(field)),
          TY_size(Get_TY(gs_tree_type(field)))
          TY_size(Get_TY(gs_tree_type(field)))
            * BITSPERBYTE );
            * BITSPERBYTE );
        gs_set_decl_bit_field(field, 1);
        gs_set_decl_bit_field(field, 1);
      }
      }
      if (gs_decl_bit_field(field)) {
      if (gs_decl_bit_field(field)) {
        Set_FLD_is_bit_field (fld);
        Set_FLD_is_bit_field (fld);
        // bofst is remaining bits from byte offset
        // bofst is remaining bits from byte offset
        Set_FLD_bofst (fld,
        Set_FLD_bofst (fld,
          gs_get_integer_value(
          gs_get_integer_value(
            gs_decl_field_bit_offset(field))
            gs_decl_field_bit_offset(field))
            % BITSPERBYTE);
            % BITSPERBYTE);
        Set_FLD_bsize (fld, gs_get_integer_value(
        Set_FLD_bsize (fld, gs_get_integer_value(
                                                           gs_decl_size(field)));
                                                           gs_decl_size(field)));
      }
      }
      fld = FLD_next(fld);
      fld = FLD_next(fld);
    }
    }
#ifndef KEY // Don't expand methods by going through TYPE_METHODS,
#ifndef KEY // Don't expand methods by going through TYPE_METHODS,
    // because:
    // because:
    //   1) It is incorrect to translate all methods in
    //   1) It is incorrect to translate all methods in
    //      TYPE_METHODS to WHIRL because some of the methods are
    //      TYPE_METHODS to WHIRL because some of the methods are
    //      never used, and generating the assembly code for them
    //      never used, and generating the assembly code for them
    //      might lead to undefined symbol references.  Instead,
    //      might lead to undefined symbol references.  Instead,
    //      consult the gxx_emitted_decls list, which has all the
    //      consult the gxx_emitted_decls list, which has all the
    //      functions (including methods) that g++ has ever emitted
    //      functions (including methods) that g++ has ever emitted
    //      to assembly.
    //      to assembly.
    //   2) Expanding the methods here will cause error when the
    //   2) Expanding the methods here will cause error when the
    //      methods are for a class B that appears as a field in an
    //      methods are for a class B that appears as a field in an
    //      enclosing class A.  When Get_TY is run for A, it will
    //      enclosing class A.  When Get_TY is run for A, it will
    //      call Get_TY for B in order to calculate A's field ID's.
    //      call Get_TY for B in order to calculate A's field ID's.
    //      (Need Get_TY to find B's TYPE_FIELD_IDS_USED.)  If
    //      (Need Get_TY to find B's TYPE_FIELD_IDS_USED.)  If
    //      Get_TY uses the code below to expand B's methods, it
    //      Get_TY uses the code below to expand B's methods, it
    //      will lead to error because the expansion requires the
    //      will lead to error because the expansion requires the
    //      field ID's of the enclosing record (A), and these field
    //      field ID's of the enclosing record (A), and these field
    //      ID's are not yet defined.
    //      ID's are not yet defined.
    // process methods
    // process methods
    if (!Enable_WGEN_DFE) {
    if (!Enable_WGEN_DFE) {
    if (cp_type_quals(type_tree) == TYPE_UNQUALIFIED) {
    if (cp_type_quals(type_tree) == TYPE_UNQUALIFIED) {
      while (method != NULL_TREE) {
      while (method != NULL_TREE) {
        WGEN_Expand_Decl (method, TRUE);
        WGEN_Expand_Decl (method, TRUE);
        method = TREE_CHAIN(method);
        method = TREE_CHAIN(method);
      }
      }
    }
    }
    }
    }
#endif  // KEY
#endif  // KEY
    } //end record scope
    } //end record scope
    break;
    break;
  case GS_METHOD_TYPE:
  case GS_METHOD_TYPE:
    //DevWarn ("Encountered METHOD_TYPE at line %d", lineno);
    //DevWarn ("Encountered METHOD_TYPE at line %d", lineno);
  case GS_FUNCTION_TYPE:
  case GS_FUNCTION_TYPE:
    { // new scope for local vars
    { // new scope for local vars
    gs_t arg;
    gs_t arg;
    INT32 num_args, i;
    INT32 num_args, i;
#ifdef KEY /* bug 8346 */
#ifdef KEY /* bug 8346 */
    TY &ty = (idx == TY_IDX_ZERO) ? New_TY(idx) : Ty_Table[idx];
    TY &ty = (idx == TY_IDX_ZERO) ? New_TY(idx) : Ty_Table[idx];
    Clear_TY_is_incomplete (idx);
    Clear_TY_is_incomplete (idx);
#else
#else
    TY &ty = New_TY (idx);
    TY &ty = New_TY (idx);
#endif
#endif
    TY_Init (ty, 0, KIND_FUNCTION, MTYPE_UNKNOWN, 0);
    TY_Init (ty, 0, KIND_FUNCTION, MTYPE_UNKNOWN, 0);
    Set_TY_align (idx, 1);
    Set_TY_align (idx, 1);
    TY_IDX ret_ty_idx;
    TY_IDX ret_ty_idx;
    TY_IDX arg_ty_idx;
    TY_IDX arg_ty_idx;
    TYLIST tylist_idx;
    TYLIST tylist_idx;
    // allocate TYs for return as well as parameters
    // allocate TYs for return as well as parameters
    // this is needed to avoid mixing TYLISTs if one
    // this is needed to avoid mixing TYLISTs if one
    // of the parameters is a pointer to a function
    // of the parameters is a pointer to a function
    ret_ty_idx = Get_TY(gs_tree_type(type_tree));
    ret_ty_idx = Get_TY(gs_tree_type(type_tree));
    for (arg = gs_type_arg_types(type_tree);
    for (arg = gs_type_arg_types(type_tree);
         arg;
         arg;
         arg = gs_tree_chain(arg))
         arg = gs_tree_chain(arg))
    {
    {
      arg_ty_idx = Get_TY(gs_tree_value(arg));
      arg_ty_idx = Get_TY(gs_tree_value(arg));
#ifdef KEY /* bug 8346 */
#ifdef KEY /* bug 8346 */
      if (TY_is_incomplete (arg_ty_idx) ||
      if (TY_is_incomplete (arg_ty_idx) ||
          (TY_kind(arg_ty_idx) == KIND_POINTER &&
          (TY_kind(arg_ty_idx) == KIND_POINTER &&
           TY_is_incomplete(TY_pointed(arg_ty_idx))))
           TY_is_incomplete(TY_pointed(arg_ty_idx))))
        Set_TY_is_incomplete (idx);
        Set_TY_is_incomplete (idx);
#endif
#endif
    }
    }
    // if return type is pointer to a zero length struct
    // if return type is pointer to a zero length struct
    // convert it to void
    // convert it to void
    if (!WGEN_Keep_Zero_Length_Structs    &&
    if (!WGEN_Keep_Zero_Length_Structs    &&
        TY_mtype (ret_ty_idx) == MTYPE_M &&
        TY_mtype (ret_ty_idx) == MTYPE_M &&
        TY_size (ret_ty_idx) == 0) {
        TY_size (ret_ty_idx) == 0) {
      // zero length struct being returned
      // zero length struct being returned
        DevWarn ("function returning zero length struct at line %d", lineno);
        DevWarn ("function returning zero length struct at line %d", lineno);
      ret_ty_idx = Be_Type_Tbl (MTYPE_V);
      ret_ty_idx = Be_Type_Tbl (MTYPE_V);
    }
    }
#ifdef KEY
#ifdef KEY
    // If the front-end adds the fake first param, then convert the
    // If the front-end adds the fake first param, then convert the
    // function to return void.
    // function to return void.
    if (TY_return_in_mem(ret_ty_idx)) {
    if (TY_return_in_mem(ret_ty_idx)) {
      ret_ty_idx = Be_Type_Tbl (MTYPE_V);
      ret_ty_idx = Be_Type_Tbl (MTYPE_V);
      Set_TY_return_to_param(idx);    // bugs 2423 2424
      Set_TY_return_to_param(idx);    // bugs 2423 2424
    }
    }
#endif
#endif
    Set_TYLIST_type (New_TYLIST (tylist_idx), ret_ty_idx);
    Set_TYLIST_type (New_TYLIST (tylist_idx), ret_ty_idx);
    Set_TY_tylist (ty, tylist_idx);
    Set_TY_tylist (ty, tylist_idx);
    for (num_args = 0, arg = gs_type_arg_types(type_tree);
    for (num_args = 0, arg = gs_type_arg_types(type_tree);
         arg;
         arg;
         num_args++, arg = gs_tree_chain(arg))
         num_args++, arg = gs_tree_chain(arg))
    {
    {
      arg_ty_idx = Get_TY(gs_tree_value(arg));
      arg_ty_idx = Get_TY(gs_tree_value(arg));
      Is_True (!TY_is_incomplete (arg_ty_idx) ||
      Is_True (!TY_is_incomplete (arg_ty_idx) ||
                TY_is_incomplete (idx),
                TY_is_incomplete (idx),
          ("Create_TY_For_Tree: unexpected TY flag"));
          ("Create_TY_For_Tree: unexpected TY flag"));
      if (!WGEN_Keep_Zero_Length_Structs    &&
      if (!WGEN_Keep_Zero_Length_Structs    &&
          TY_mtype (arg_ty_idx) == MTYPE_M &&
          TY_mtype (arg_ty_idx) == MTYPE_M &&
          TY_size (arg_ty_idx) == 0) {
          TY_size (arg_ty_idx) == 0) {
        // zero length struct passed as parameter
        // zero length struct passed as parameter
        DevWarn ("zero length struct encountered in function prototype at line %d", lineno);
        DevWarn ("zero length struct encountered in function prototype at line %d", lineno);
      }
      }
      else
      else
        Set_TYLIST_type (New_TYLIST (tylist_idx), arg_ty_idx);
        Set_TYLIST_type (New_TYLIST (tylist_idx), arg_ty_idx);
    }
    }
    if (num_args)
    if (num_args)
    {
    {
      Set_TY_has_prototype(idx);
      Set_TY_has_prototype(idx);
      if (arg_ty_idx != Be_Type_Tbl(MTYPE_V))
      if (arg_ty_idx != Be_Type_Tbl(MTYPE_V))
      {
      {
        Set_TYLIST_type (New_TYLIST (tylist_idx), 0);
        Set_TYLIST_type (New_TYLIST (tylist_idx), 0);
        Set_TY_is_varargs(idx);
        Set_TY_is_varargs(idx);
      }
      }
      else
      else
        Set_TYLIST_type (Tylist_Table [tylist_idx], 0);
        Set_TYLIST_type (Tylist_Table [tylist_idx], 0);
    }
    }
    else
    else
      Set_TYLIST_type (New_TYLIST (tylist_idx), 0);
      Set_TYLIST_type (New_TYLIST (tylist_idx), 0);
#ifdef TARG_X8664
#ifdef TARG_X8664
    if (!TARGET_64BIT && !TY_is_varargs(idx))
    if (!TARGET_64BIT && !TY_is_varargs(idx))
    {
    {
      // Ignore m{sse}regparm and corresponding attributes at -m64.
      // Ignore m{sse}regparm and corresponding attributes at -m64.
      if (SSE_Reg_Parm ||
      if (SSE_Reg_Parm ||
          lookup_attribute("sseregparm",
          lookup_attribute("sseregparm",
                           gs_type_attributes(type_tree)))
                           gs_type_attributes(type_tree)))
        Set_TY_has_sseregister_parm (idx);
        Set_TY_has_sseregister_parm (idx);
      if (gs_t attr = lookup_attribute("regparm",
      if (gs_t attr = lookup_attribute("regparm",
          gs_type_attributes(type_tree)))
          gs_type_attributes(type_tree)))
      {
      {
        gs_t value = gs_tree_value (attr);
        gs_t value = gs_tree_value (attr);
        Is_True (gs_tree_code(value) == GS_TREE_LIST,
        Is_True (gs_tree_code(value) == GS_TREE_LIST,
                 ("Expected TREE_LIST"));
                 ("Expected TREE_LIST"));
        value = gs_tree_value (value);
        value = gs_tree_value (value);
        if (gs_tree_code(value) == GS_INTEGER_CST)
        if (gs_tree_code(value) == GS_INTEGER_CST)
          Set_TY_register_parm (idx, gs_get_integer_value (value));
          Set_TY_register_parm (idx, gs_get_integer_value (value));
      }
      }
      else if (Reg_Parm_Count)
      else if (Reg_Parm_Count)
        Set_TY_register_parm (idx, Reg_Parm_Count);
        Set_TY_register_parm (idx, Reg_Parm_Count);
    }
    }
#endif
#endif
    } // end FUNCTION_TYPE scope
    } // end FUNCTION_TYPE scope
    break;
    break;
#ifdef TARG_X8664
#ifdef TARG_X8664
        // x86 gcc vector types
        // x86 gcc vector types
        case GS_VECTOR_TYPE:
        case GS_VECTOR_TYPE:
                {
                {
    char *p = gs_type_mode(type_tree);
    char *p = gs_type_mode(type_tree);
    idx = 0;
    idx = 0;
    if (strcmp(p, "BLK") == 0) {
    if (strcmp(p, "BLK") == 0) {
      TY_IDX elem_ty = Get_TY(gs_tree_type(type_tree));
      TY_IDX elem_ty = Get_TY(gs_tree_type(type_tree));
      TYPE_ID elem_mtype = TY_mtype(elem_ty);
      TYPE_ID elem_mtype = TY_mtype(elem_ty);
      switch (gs_n(gs_type_precision(type_tree))) {
      switch (gs_n(gs_type_precision(type_tree))) {
        case 2: if (elem_mtype == MTYPE_I4)
        case 2: if (elem_mtype == MTYPE_I4)
                idx = MTYPE_To_TY(MTYPE_V8I4);
                idx = MTYPE_To_TY(MTYPE_V8I4);
          else if (elem_mtype == MTYPE_F4)
          else if (elem_mtype == MTYPE_F4)
                idx = MTYPE_To_TY(MTYPE_V8F4);
                idx = MTYPE_To_TY(MTYPE_V8F4);
              else if (elem_mtype == MTYPE_I8)
              else if (elem_mtype == MTYPE_I8)
                idx = MTYPE_To_TY(MTYPE_V16I8);
                idx = MTYPE_To_TY(MTYPE_V16I8);
          else if (elem_mtype == MTYPE_F8)
          else if (elem_mtype == MTYPE_F8)
                idx = MTYPE_To_TY(MTYPE_V16F8);
                idx = MTYPE_To_TY(MTYPE_V16F8);
          break;
          break;
        case 4: if (elem_mtype == MTYPE_I4)
        case 4: if (elem_mtype == MTYPE_I4)
                idx = MTYPE_To_TY(MTYPE_V16I4);
                idx = MTYPE_To_TY(MTYPE_V16I4);
          else if (elem_mtype == MTYPE_F4)
          else if (elem_mtype == MTYPE_F4)
                idx = MTYPE_To_TY(MTYPE_V16F4);
                idx = MTYPE_To_TY(MTYPE_V16F4);
              else if (elem_mtype == MTYPE_I2)
              else if (elem_mtype == MTYPE_I2)
                idx = MTYPE_To_TY(MTYPE_M8I2);
                idx = MTYPE_To_TY(MTYPE_M8I2);
          break;
          break;
        case 8: if (elem_mtype == MTYPE_I1)
        case 8: if (elem_mtype == MTYPE_I1)
                idx = MTYPE_To_TY(MTYPE_M8I1);
                idx = MTYPE_To_TY(MTYPE_M8I1);
              else if (elem_mtype == MTYPE_I2)
              else if (elem_mtype == MTYPE_I2)
                idx = MTYPE_To_TY(MTYPE_V16I2);
                idx = MTYPE_To_TY(MTYPE_V16I2);
          break;
          break;
        case 16: if (elem_mtype == MTYPE_I1)
        case 16: if (elem_mtype == MTYPE_I1)
                 idx = MTYPE_To_TY(MTYPE_V16I1);
                 idx = MTYPE_To_TY(MTYPE_V16I1);
           break;
           break;
        default:
        default:
          Fail_FmtAssertion ("Get_TY: unexpected vector type element count");
          Fail_FmtAssertion ("Get_TY: unexpected vector type element count");
      }
      }
    }
    }
    else { // use string emcoded in TYPE_MODE
    else { // use string emcoded in TYPE_MODE
      if (toupper(*p++) != 'V') {
      if (toupper(*p++) != 'V') {
        if (gs_type_name(type_tree)) {
        if (gs_type_name(type_tree)) {
          p = gs_identifier_pointer(gs_decl_name(gs_type_name(type_tree)));
          p = gs_identifier_pointer(gs_decl_name(gs_type_name(type_tree)));
          if (toupper(*p++) != 'V')
          if (toupper(*p++) != 'V')
      Fail_FmtAssertion("Get_TY: NYI");
      Fail_FmtAssertion("Get_TY: NYI");
        }
        }
        else Fail_FmtAssertion("Get_TY: NYI");
        else Fail_FmtAssertion("Get_TY: NYI");
      }
      }
      int num_elems = strtol(p, &p, 10);
      int num_elems = strtol(p, &p, 10);
      if (strncasecmp(p, "DI", 2) == 0)
      if (strncasecmp(p, "DI", 2) == 0)
        idx = MTYPE_To_TY(MTYPE_V16I8);
        idx = MTYPE_To_TY(MTYPE_V16I8);
      else if (strncasecmp(p, "DF", 2) == 0)
      else if (strncasecmp(p, "DF", 2) == 0)
        idx = MTYPE_To_TY(MTYPE_V16F8);
        idx = MTYPE_To_TY(MTYPE_V16F8);
      else if (strncasecmp(p, "SI", 2) == 0) {
      else if (strncasecmp(p, "SI", 2) == 0) {
        if (num_elems == 2)
        if (num_elems == 2)
          if ( Is_Target_64bit())
          if ( Is_Target_64bit())
      idx = MTYPE_To_TY(MTYPE_V8I4);
      idx = MTYPE_To_TY(MTYPE_V8I4);
          else
          else
      idx = MTYPE_To_TY(MTYPE_M8I4);
      idx = MTYPE_To_TY(MTYPE_M8I4);
        else if (num_elems == 4)
        else if (num_elems == 4)
          idx = MTYPE_To_TY(MTYPE_V16I4);
          idx = MTYPE_To_TY(MTYPE_V16I4);
      }
      }
      else if (strncasecmp(p, "SF", 2) == 0) {
      else if (strncasecmp(p, "SF", 2) == 0) {
        if (num_elems == 2)
        if (num_elems == 2)
          if ( Is_Target_64bit())
          if ( Is_Target_64bit())
      idx = MTYPE_To_TY(MTYPE_V8F4);
      idx = MTYPE_To_TY(MTYPE_V8F4);
          else
          else
      idx = MTYPE_To_TY(MTYPE_M8F4);
      idx = MTYPE_To_TY(MTYPE_M8F4);
        else if (num_elems == 4)
        else if (num_elems == 4)
          idx = MTYPE_To_TY(MTYPE_V16F4);
          idx = MTYPE_To_TY(MTYPE_V16F4);
      }
      }
      else if (strncasecmp(p, "HI", 2) == 0) {
      else if (strncasecmp(p, "HI", 2) == 0) {
        if (num_elems == 4)
        if (num_elems == 4)
          idx = MTYPE_To_TY(MTYPE_M8I2);
          idx = MTYPE_To_TY(MTYPE_M8I2);
        else if (num_elems == 8)
        else if (num_elems == 8)
          idx = MTYPE_To_TY(MTYPE_V16I2);
          idx = MTYPE_To_TY(MTYPE_V16I2);
      }
      }
      else if (strncasecmp(p, "QI", 2) == 0) {
      else if (strncasecmp(p, "QI", 2) == 0) {
        if (num_elems == 8)
        if (num_elems == 8)
          idx = MTYPE_To_TY(MTYPE_M8I1);
          idx = MTYPE_To_TY(MTYPE_M8I1);
        else if (num_elems == 16)
        else if (num_elems == 16)
          idx = MTYPE_To_TY(MTYPE_V16I1);
          idx = MTYPE_To_TY(MTYPE_V16I1);
      }
      }
    }
    }
    if (idx == 0)
    if (idx == 0)
      Fail_FmtAssertion ("Get_TY: unexpected vector type");
      Fail_FmtAssertion ("Get_TY: unexpected vector type");
                }
                }
                break;
                break;
#endif // TARG_X8664
#endif // TARG_X8664
  default:
  default:
    FmtAssert(FALSE, ("Get_TY unexpected tree_type"));
    FmtAssert(FALSE, ("Get_TY unexpected tree_type"));
  }
  }
  if (gs_type_readonly(type_tree))
  if (gs_type_readonly(type_tree))
    Set_TY_is_const (idx);
    Set_TY_is_const (idx);
  if (gs_type_volatile(type_tree))
  if (gs_type_volatile(type_tree))
    Set_TY_is_volatile (idx);
    Set_TY_is_volatile (idx);
#ifdef KEY
#ifdef KEY
  if (gs_type_restrict(type_tree))
  if (gs_type_restrict(type_tree))
    Set_TY_is_restrict (idx);
    Set_TY_is_restrict (idx);
#endif
#endif
  TYPE_TY_IDX(type_tree) = idx;
  TYPE_TY_IDX(type_tree) = idx;
        if(Debug_Level >= 2) {
        if(Debug_Level >= 2) {
#ifdef KEY
#ifdef KEY
    // DSTs for records were entered into the defer list in the order
    // DSTs for records were entered into the defer list in the order
    // that the records are declared, in order to preserve their scope.
    // that the records are declared, in order to preserve their scope.
    // Bug 4168.
    // Bug 4168.
    if (gs_tree_code(type_tree) != GS_RECORD_TYPE &&
    if (gs_tree_code(type_tree) != GS_RECORD_TYPE &&
        gs_tree_code(type_tree) != GS_UNION_TYPE &&
        gs_tree_code(type_tree) != GS_UNION_TYPE &&
        // Bugs 8346, 11819: Insert a TY for DST processing only
        // Bugs 8346, 11819: Insert a TY for DST processing only
        // when the TY is complete to ensure that when the DST info
        // when the TY is complete to ensure that when the DST info
        // are created, the TY will be valid.
        // are created, the TY will be valid.
        !TY_is_incomplete(idx) &&
        !TY_is_incomplete(idx) &&
        !(TY_kind(idx) == KIND_POINTER &&
        !(TY_kind(idx) == KIND_POINTER &&
          TY_is_incomplete(TY_pointed(idx)))) {
          TY_is_incomplete(TY_pointed(idx)))) {
      // Defer creating DST info until there are no partially constructed
      // Defer creating DST info until there are no partially constructed
      // types, in order to prevent Create_DST_type_For_Tree from calling
      // types, in order to prevent Create_DST_type_For_Tree from calling
      // Get_TY, which in turn may use field IDs from partially created
      // Get_TY, which in turn may use field IDs from partially created
      // structs.  Such fields IDs are wrong.  Bug 5658.
      // structs.  Such fields IDs are wrong.  Bug 5658.
      defer_DST_type(type_tree, idx, orig_idx);
      defer_DST_type(type_tree, idx, orig_idx);
    }
    }
#else
#else
          DST_INFO_IDX dst =
          DST_INFO_IDX dst =
            Create_DST_type_For_Tree(type_tree,
            Create_DST_type_For_Tree(type_tree,
              idx,orig_idx);
              idx,orig_idx);
          TYPE_DST_IDX(type_tree) = dst;
          TYPE_DST_IDX(type_tree) = dst;
#endif
#endif
        }
        }
  return idx;
  return idx;
}
}
void
void
Create_DST_For_Tree (gs_t decl_node, ST* st)
Create_DST_For_Tree (gs_t decl_node, ST* st)
{
{
  DST_INFO_IDX dst =
  DST_INFO_IDX dst =
    Create_DST_decl_For_Tree(decl_node,st);
    Create_DST_decl_For_Tree(decl_node,st);
  DECL_DST_IDX(decl_node) = dst;
  DECL_DST_IDX(decl_node) = dst;
  return;
  return;
}
}
#if 1 // wgen
#if 1 // wgen
// if there is a PARM_DECL with the same name (as opposed to same node),
// if there is a PARM_DECL with the same name (as opposed to same node),
// use the ST created for it
// use the ST created for it
ST *
ST *
Search_decl_arguments(char *name)
Search_decl_arguments(char *name)
{
{
  gs_t p;
  gs_t p;
  if (name) {
  if (name) {
    for (p = decl_arguments; p; p = gs_tree_chain(p)) {
    for (p = decl_arguments; p; p = gs_tree_chain(p)) {
      if (gs_decl_name(p) == NULL) // matches with any parm with null name (sanity32.C)
      if (gs_decl_name(p) == NULL) // matches with any parm with null name (sanity32.C)
  return DECL_ST(p);
  return DECL_ST(p);
      if (strcmp(name, (char *) gs_identifier_pointer(gs_decl_name(p))) == 0)
      if (strcmp(name, (char *) gs_identifier_pointer(gs_decl_name(p))) == 0)
  return DECL_ST(p);
  return DECL_ST(p);
    }
    }
  }
  }
  else { // search for an argument with no name
  else { // search for an argument with no name
    for (p = decl_arguments; p; p = gs_tree_chain(p)) {
    for (p = decl_arguments; p; p = gs_tree_chain(p)) {
      if (gs_decl_name(p) == NULL)
      if (gs_decl_name(p) == NULL)
  return DECL_ST(p);
  return DECL_ST(p);
    }
    }
  }
  }
  return NULL;
  return NULL;
}
}
#endif
#endif
#ifdef KEY // bug 12668
#ifdef KEY // bug 12668
static BOOL
static BOOL
Has_label_decl(gs_t init)
Has_label_decl(gs_t init)
{
{
  if (gs_tree_code(init) == GS_LABEL_DECL)
  if (gs_tree_code(init) == GS_LABEL_DECL)
    return TRUE;
    return TRUE;
  if (gs_tree_code(init) == GS_ADDR_EXPR)
  if (gs_tree_code(init) == GS_ADDR_EXPR)
    return Has_label_decl(gs_tree_operand(init,0));
    return Has_label_decl(gs_tree_operand(init,0));
#ifdef FE_GNU_4_2_0 // bug 12699
#ifdef FE_GNU_4_2_0 // bug 12699
  if (gs_tree_code(init) == GS_NOP_EXPR)
  if (gs_tree_code(init) == GS_NOP_EXPR)
    return Has_label_decl(gs_tree_operand(init,0));
    return Has_label_decl(gs_tree_operand(init,0));
#endif
#endif
  if (gs_tree_code(init) == GS_CONSTRUCTOR) {
  if (gs_tree_code(init) == GS_CONSTRUCTOR) {
#ifdef FE_GNU_4_2_0
#ifdef FE_GNU_4_2_0
    INT length = gs_constructor_length(init);
    INT length = gs_constructor_length(init);
    gs_t element_value;
    gs_t element_value;
    for (INT idx = 0; idx < length; idx++) {
    for (INT idx = 0; idx < length; idx++) {
      element_value = gs_constructor_elts_value(init, idx);
      element_value = gs_constructor_elts_value(init, idx);
      if (Has_label_decl(element_value))
      if (Has_label_decl(element_value))
  return TRUE;
  return TRUE;
    }
    }
#else
#else
    gs_t nd;
    gs_t nd;
    for (nd = gs_constructor_elts(init); nd; nd = gs_tree_chain(nd)) {
    for (nd = gs_constructor_elts(init); nd; nd = gs_tree_chain(nd)) {
      if (Has_label_decl(gs_tree_value(nd)))
      if (Has_label_decl(gs_tree_value(nd)))
  return TRUE;
  return TRUE;
    }
    }
#endif
#endif
  }
  }
  return FALSE;
  return FALSE;
}
}
#endif
#endif
ST*
ST*
Create_ST_For_Tree (gs_t decl_node)
Create_ST_For_Tree (gs_t decl_node)
{
{
  TY_IDX     ty_idx;
  TY_IDX     ty_idx;
  ST*        st = NULL;
  ST*        st = NULL;
  char      *name;
  char      *name;
  char      tempname[32];
  char      tempname[32];
  ST_SCLASS  sclass;
  ST_SCLASS  sclass;
  ST_EXPORT  eclass;
  ST_EXPORT  eclass;
  SYMTAB_IDX level;
  SYMTAB_IDX level;
  static INT anon_count = 0;
  static INT anon_count = 0;
  BOOL anon_st = FALSE;
  BOOL anon_st = FALSE;
  // If the decl is a function decl, and there are duplicate decls for the
  // If the decl is a function decl, and there are duplicate decls for the
  // function, then use a ST already allocated for the function, if such ST
  // function, then use a ST already allocated for the function, if such ST
  // exists.
  // exists.
  if (gs_tree_code(decl_node) == GS_FUNCTION_DECL) {
  if (gs_tree_code(decl_node) == GS_FUNCTION_DECL) {
    st = get_duplicate_st (decl_node);
    st = get_duplicate_st (decl_node);
    if (st) {
    if (st) {
      set_DECL_ST(decl_node, st);
      set_DECL_ST(decl_node, st);
      return st;
      return st;
    }
    }
  }
  }
  // For variables with asm register assignments, don't use the assembler
  // For variables with asm register assignments, don't use the assembler
  // names because they are of the form "%rbx".
  // names because they are of the form "%rbx".
  if (gs_tree_code(decl_node) == GS_RESULT_DECL) {
  if (gs_tree_code(decl_node) == GS_RESULT_DECL) {
    sprintf(tempname, ".result_decl_%d", gs_decl_uid(decl_node));
    sprintf(tempname, ".result_decl_%d", gs_decl_uid(decl_node));
    name = tempname;
    name = tempname;
    anon_st = TRUE;
    anon_st = TRUE;
  }
  }
  else if ((gs_tree_code(decl_node) == GS_FUNCTION_DECL ||
  else if ((gs_tree_code(decl_node) == GS_FUNCTION_DECL ||
            gs_tree_code(decl_node) == GS_PARM_DECL ||
            gs_tree_code(decl_node) == GS_PARM_DECL ||
            (gs_tree_code(decl_node) == GS_VAR_DECL &&
            (gs_tree_code(decl_node) == GS_VAR_DECL &&
             gs_decl_asmreg(decl_node) >= 0)) &&
             gs_decl_asmreg(decl_node) >= 0)) &&
           gs_decl_name(decl_node) != 0)
           gs_decl_name(decl_node) != 0)
    name = (char *) gs_identifier_pointer (gs_decl_name (decl_node));
    name = (char *) gs_identifier_pointer (gs_decl_name (decl_node));
  else if (gs_decl_assembler_name (decl_node) && gs_decl_name (decl_node))
  else if (gs_decl_assembler_name (decl_node) && gs_decl_name (decl_node))
    name = (char *) gs_identifier_pointer (gs_decl_assembler_name (decl_node));
    name = (char *) gs_identifier_pointer (gs_decl_assembler_name (decl_node));
  else if (gs_decl_name (decl_node))
  else if (gs_decl_name (decl_node))
    name = (char *) gs_identifier_pointer (gs_decl_name (decl_node));
    name = (char *) gs_identifier_pointer (gs_decl_name (decl_node));
  else {
  else {
    sprintf(tempname, "anon%d", ++anon_count);
    sprintf(tempname, "anon%d", ++anon_count);
    name = tempname;
    name = tempname;
    anon_st = TRUE;
    anon_st = TRUE;
  }
  }
#ifdef KEY
#ifdef KEY
  BOOL guard_var = FALSE;
  BOOL guard_var = FALSE;
  // See if variable is a guard variable.
  // See if variable is a guard variable.
  if (strncmp("_ZGV", name, 4) == 0) {
  if (strncmp("_ZGV", name, 4) == 0) {
    guard_var = TRUE;
    guard_var = TRUE;
  }
  }
#endif
#endif
  switch (gs_tree_code(decl_node)) {
  switch (gs_tree_code(decl_node)) {
    case GS_FUNCTION_DECL:
    case GS_FUNCTION_DECL:
      {
      {
        if (Enable_WFE_DFE) {
        if (Enable_WFE_DFE) {
          gs_t body = gs_decl_saved_tree(decl_node);
          gs_t body = gs_decl_saved_tree(decl_node);
          if (gs_decl_thunk_p(decl_node) &&
          if (gs_decl_thunk_p(decl_node) &&
              gs_tree_code(gs_cp_decl_context(decl_node)) != GS_NAMESPACE_DECL)
              gs_tree_code(gs_cp_decl_context(decl_node)) != GS_NAMESPACE_DECL)
            Push_Deferred_Function (decl_node);
            Push_Deferred_Function (decl_node);
/*
/*
          else
          else
          if (DECL_TINFO_FN_P(decl_node))
          if (DECL_TINFO_FN_P(decl_node))
            Push_Deferred_Function (decl_node);
            Push_Deferred_Function (decl_node);
*/
*/
          else
          else
          if (body != NULL && !gs_decl_external(decl_node) &&
          if (body != NULL && !gs_decl_external(decl_node) &&
              (gs_decl_template_info(decl_node) == NULL              ||
              (gs_decl_template_info(decl_node) == NULL              ||
               gs_decl_friend_pseudo_template_instantiation(decl_node) ||
               gs_decl_friend_pseudo_template_instantiation(decl_node) ||
               gs_decl_template_instantiated(decl_node)              ||
               gs_decl_template_instantiated(decl_node)              ||
               gs_decl_template_specialization(decl_node))) {
               gs_decl_template_specialization(decl_node))) {
            Push_Deferred_Function (decl_node);
            Push_Deferred_Function (decl_node);
          }
          }
        }
        }
#ifdef KEY /* bug 8346 */
#ifdef KEY /* bug 8346 */
        Is_True (!processing_function_prototype,
        Is_True (!processing_function_prototype,
                 ("Create_ST_For_Tree: processing another function prototype?"));
                 ("Create_ST_For_Tree: processing another function prototype?"));
        processing_function_prototype = TRUE;
        processing_function_prototype = TRUE;
        TY_IDX func_ty_idx = Get_TY(gs_tree_type(decl_node));
        TY_IDX func_ty_idx = Get_TY(gs_tree_type(decl_node));
        processing_function_prototype = FALSE;
        processing_function_prototype = FALSE;
#else
#else
        TY_IDX func_ty_idx = Get_TY(gs_tree_type(decl_node));
        TY_IDX func_ty_idx = Get_TY(gs_tree_type(decl_node));
#endif
#endif
        sclass = SCLASS_EXTERN;
        sclass = SCLASS_EXTERN;
        eclass = gs_tree_public(decl_node) || gs_decl_weak(decl_node) ?
        eclass = gs_tree_public(decl_node) || gs_decl_weak(decl_node) ?
       EXPORT_PREEMPTIBLE       :
       EXPORT_PREEMPTIBLE       :
       EXPORT_LOCAL;
       EXPORT_LOCAL;
        level  = GLOBAL_SYMTAB+1;
        level  = GLOBAL_SYMTAB+1;
        PU_IDX pu_idx;
        PU_IDX pu_idx;
        PU&    pu = New_PU (pu_idx);
        PU&    pu = New_PU (pu_idx);
        PU_Init (pu, func_ty_idx, level);
        PU_Init (pu, func_ty_idx, level);
#ifdef KEY
#ifdef KEY
        st = New_ST (level - 1);
        st = New_ST (level - 1);
#else
#else
        st = New_ST (GLOBAL_SYMTAB);
        st = New_ST (GLOBAL_SYMTAB);
#endif
#endif
        // Fix bug # 34, 3356
        // Fix bug # 34, 3356
// gcc sometimes adds a '*' and itself handles it this way while outputing
// gcc sometimes adds a '*' and itself handles it this way while outputing
  char *p;
  char *p;
  if (gs_decl_assembler_name(decl_node) == NULL)
  if (gs_decl_assembler_name(decl_node) == NULL)
    p = name;
    p = name;
  else p  = gs_identifier_pointer (gs_decl_assembler_name (decl_node));
  else p  = gs_identifier_pointer (gs_decl_assembler_name (decl_node));
  if (*p == '*')
  if (*p == '*')
    p++;
    p++;
        ST_Init (st, Save_Str(p),
        ST_Init (st, Save_Str(p),
                 CLASS_FUNC, sclass, eclass, TY_IDX (pu_idx));
                 CLASS_FUNC, sclass, eclass, TY_IDX (pu_idx));
        // St is a constructor
        // St is a constructor
        if (gs_decl_complete_constructor_p(decl_node) && !gs_decl_copy_constructor_p(decl_node))
        if (gs_decl_complete_constructor_p(decl_node) && !gs_decl_copy_constructor_p(decl_node))
            Set_PU_is_constructor(pu);
            Set_PU_is_constructor(pu);
        // St is a pure virual function
        // St is a pure virual function
        if (gs_decl_pure_virtual_p(decl_node) || strncmp(p, "__cxa_pure_virtual", 18) == 0)
        if (gs_decl_pure_virtual_p(decl_node) || strncmp(p, "__cxa_pure_virtual", 18) == 0)
            Set_ST_is_pure_vfunc(st);
            Set_ST_is_pure_vfunc(st);
        if (gs_tree_code(gs_tree_type(decl_node)) == GS_METHOD_TYPE) {
        if (gs_tree_code(gs_tree_type(decl_node)) == GS_METHOD_TYPE) {
            TY_IDX base = Get_TY(gs_type_method_basetype(gs_tree_type(decl_node)));
            TY_IDX base = Get_TY(gs_type_method_basetype(gs_tree_type(decl_node)));
            Set_PU_base_class(pu, base);
            Set_PU_base_class(pu, base);
        }
        }
  if (gs_decl_thunk_p(decl_node) &&
  if (gs_decl_thunk_p(decl_node) &&
            gs_tree_code(gs_cp_decl_context(decl_node)) != GS_NAMESPACE_DECL &&
            gs_tree_code(gs_cp_decl_context(decl_node)) != GS_NAMESPACE_DECL &&
            eclass != EXPORT_LOCAL &&
            eclass != EXPORT_LOCAL &&
            eclass != EXPORT_LOCAL_INTERNAL)
            eclass != EXPORT_LOCAL_INTERNAL)
    Set_ST_is_weak_symbol(st);
    Set_ST_is_weak_symbol(st);
      }
      }
      break;
      break;
#ifdef KEY
#ifdef KEY
    case GS_RESULT_DECL: // bug 3878
    case GS_RESULT_DECL: // bug 3878
#if 0
#if 0
    // wgen clean-up: These codes, needed to handle gimplified GNU tree
    // wgen clean-up: These codes, needed to handle gimplified GNU tree
       should not be needed any more.
       should not be needed any more.
      if (TY_return_in_mem
      if (TY_return_in_mem
          (Get_TY
          (Get_TY
           (gs_tree_type
           (gs_tree_type
            (gs_tree_type
            (gs_tree_type
             (Current_Function_Decl()) ) ) ) )
             (Current_Function_Decl()) ) ) ) )
      {
      {
        // We should have already set up the first formal for holding
        // We should have already set up the first formal for holding
        // the return object.
        // the return object.
        WN *first_formal = WN_formal(Current_Entry_WN(), 0);
        WN *first_formal = WN_formal(Current_Entry_WN(), 0);
        if (!get_DECL_ST(decl_node))
        if (!get_DECL_ST(decl_node))
          set_DECL_ST(decl_node, WN_st(first_formal));
          set_DECL_ST(decl_node, WN_st(first_formal));
        return get_DECL_ST(decl_node);
        return get_DECL_ST(decl_node);
      }
      }
      // fall through
      // fall through
#endif
#endif
#endif
#endif
    case GS_PARM_DECL:
    case GS_PARM_DECL:
    case GS_VAR_DECL:
    case GS_VAR_DECL:
      {
      {
        if (gs_tree_code(decl_node) == GS_PARM_DECL) {
        if (gs_tree_code(decl_node) == GS_PARM_DECL) {
#ifdef KEY
#ifdef KEY
    // wgen fix for C++ and also for C, as in bug 8346.
    // wgen fix for C++ and also for C, as in bug 8346.
    if (decl_arguments) {
    if (decl_arguments) {
      st = Search_decl_arguments(gs_decl_name(decl_node) ? name : NULL);
      st = Search_decl_arguments(gs_decl_name(decl_node) ? name : NULL);
      if (st) {
      if (st) {
        set_DECL_ST(decl_node, st); // created now
        set_DECL_ST(decl_node, st); // created now
        return st;
        return st;
      }
      }
    }
    }
#endif
#endif
          sclass = SCLASS_FORMAL;
          sclass = SCLASS_FORMAL;
          eclass = EXPORT_LOCAL;
          eclass = EXPORT_LOCAL;
          level = CURRENT_SYMTAB;
          level = CURRENT_SYMTAB;
        }
        }
        else {
        else {
          if (gs_decl_context (decl_node) == 0           ||
          if (gs_decl_context (decl_node) == 0           ||
        gs_tree_code (gs_decl_context (decl_node)) == GS_NAMESPACE_DECL ||
        gs_tree_code (gs_decl_context (decl_node)) == GS_NAMESPACE_DECL ||
        gs_tree_code (gs_decl_context (decl_node)) == GS_RECORD_TYPE ) {
        gs_tree_code (gs_decl_context (decl_node)) == GS_RECORD_TYPE ) {
            if (gs_tree_public (decl_node)) {
            if (gs_tree_public (decl_node)) {
        // GCC 3.2
        // GCC 3.2
        if (gs_decl_external(decl_node) ||
        if (gs_decl_external(decl_node) ||
      (gs_decl_lang_specific(decl_node) &&
      (gs_decl_lang_specific(decl_node) &&
       gs_decl_really_extern(decl_node)))
       gs_decl_really_extern(decl_node)))
    sclass = SCLASS_EXTERN;
    sclass = SCLASS_EXTERN;
        else
        else
        if (gs_decl_initial(decl_node))
        if (gs_decl_initial(decl_node))
    sclass = SCLASS_UGLOBAL;
    sclass = SCLASS_UGLOBAL;
        else if (gs_tree_static(decl_node)) {
        else if (gs_tree_static(decl_node)) {
#ifdef KEY
#ifdef KEY
// bugs 340, 3717
// bugs 340, 3717
    if (flag_no_common || !gs_decl_common (decl_node) ||
    if (flag_no_common || !gs_decl_common (decl_node) ||
        (!lang_cplus /* bug 14187 */ &&
        (!lang_cplus /* bug 14187 */ &&
         gs_decl_section_name (decl_node) /* bug 14181 */))
         gs_decl_section_name (decl_node) /* bug 14181 */))
#else
#else
    if (flag_no_common)
    if (flag_no_common)
#endif
#endif
      sclass = SCLASS_UGLOBAL;
      sclass = SCLASS_UGLOBAL;
    else
    else
      sclass = SCLASS_COMMON;
      sclass = SCLASS_COMMON;
        }
        }
        else
        else
                sclass = SCLASS_EXTERN;
                sclass = SCLASS_EXTERN;
              eclass = EXPORT_PREEMPTIBLE;
              eclass = EXPORT_PREEMPTIBLE;
            }
            }
            else {
            else {
                sclass = SCLASS_FSTATIC;
                sclass = SCLASS_FSTATIC;
    eclass = EXPORT_LOCAL;
    eclass = EXPORT_LOCAL;
            }
            }
            level = GLOBAL_SYMTAB;
            level = GLOBAL_SYMTAB;
          }
          }
          else {
          else {
#ifdef KEY
#ifdef KEY
      // .gnu.linkonce.b is .bss with DECL_ONE_ONLY set.  Bug 10876.
      // .gnu.linkonce.b is .bss with DECL_ONE_ONLY set.  Bug 10876.
      gs_t section_name = gs_decl_section_name(decl_node);
      gs_t section_name = gs_decl_section_name(decl_node);
      if (section_name &&
      if (section_name &&
    !strncmp(gs_tree_string_pointer(section_name),
    !strncmp(gs_tree_string_pointer(section_name),
       ".gnu.linkonce.", 14)) {
       ".gnu.linkonce.", 14)) {
        if (!strncmp(gs_tree_string_pointer(section_name),
        if (!strncmp(gs_tree_string_pointer(section_name),
         ".gnu.linkonce.b.", 16)
         ".gnu.linkonce.b.", 16)
            // bug 13054
            // bug 13054
            || !strncmp(gs_tree_string_pointer(section_name),
            || !strncmp(gs_tree_string_pointer(section_name),
                        ".gnu.linkonce.sb.", 17)) {
                        ".gnu.linkonce.sb.", 17)) {
    sclass = SCLASS_UGLOBAL;
    sclass = SCLASS_UGLOBAL;
    level  = GLOBAL_SYMTAB;
    level  = GLOBAL_SYMTAB;
    eclass = EXPORT_PREEMPTIBLE;
    eclass = EXPORT_PREEMPTIBLE;
        } else {
        } else {
    // Add support as needed.
    // Add support as needed.
    Fail_FmtAssertion("Create_ST_For_Tree: %s section NYI",
    Fail_FmtAssertion("Create_ST_For_Tree: %s section NYI",
          gs_tree_string_pointer(section_name));
          gs_tree_string_pointer(section_name));
        }
        }
      }
      }
      // bug 13090 and 13245
      // bug 13090 and 13245
      // Bug 13047 shows that the gnu42 front-end (specifically
      // Bug 13047 shows that the gnu42 front-end (specifically
      // the gcc/g++ part) behaves differently when built on a gnu3
      // the gcc/g++ part) behaves differently when built on a gnu3
      // system, than when built on a gnu4 system. If the compiler
      // system, than when built on a gnu4 system. If the compiler
      // is built on a gnu4 system, default_unique_section() in
      // is built on a gnu4 system, default_unique_section() in
      // varasm.c will never generate a linkonce section because
      // varasm.c will never generate a linkonce section because
      // starting GNU42, this also depends on whether the host
      // starting GNU42, this also depends on whether the host
      // compiling system has COMDAT groups.
      // compiling system has COMDAT groups.
      else if (section_name &&
      else if (section_name &&
               (!strncmp(gs_tree_string_pointer(section_name),
               (!strncmp(gs_tree_string_pointer(section_name),
             ".sbss.", 6) ||
             ".sbss.", 6) ||
          !strncmp(gs_tree_string_pointer(section_name),
          !strncmp(gs_tree_string_pointer(section_name),
             ".bss.", 5))) {
             ".bss.", 5))) {
        sclass = SCLASS_UGLOBAL;
        sclass = SCLASS_UGLOBAL;
        level  = GLOBAL_SYMTAB;
        level  = GLOBAL_SYMTAB;
        eclass = EXPORT_PREEMPTIBLE;
        eclass = EXPORT_PREEMPTIBLE;
      }
      }
      else
      else
#endif
#endif
            if (gs_decl_external(decl_node) || gs_decl_weak(decl_node)) {
            if (gs_decl_external(decl_node) || gs_decl_weak(decl_node)) {
        // OSP_255
        // OSP_255
        // Not all weak symbols are EXTERN: COMMON&WEAK, STATIC&WEAK
        // Not all weak symbols are EXTERN: COMMON&WEAK, STATIC&WEAK
        if (!flag_no_common && gs_decl_common (decl_node)) {
        if (!flag_no_common && gs_decl_common (decl_node)) {
    // COMMON & WEAK:
    // COMMON & WEAK:
    //   static vars in exported inline/template functions(IA64)
    //   static vars in exported inline/template functions(IA64)
    sclass = SCLASS_COMMON;
    sclass = SCLASS_COMMON;
        }
        }
        else if (gs_tree_static (decl_node)) {
        else if (gs_tree_static (decl_node)) {
    // STATIC & WEAK:
    // STATIC & WEAK:
    //   static vars in exported inline/template function(X8664)
    //   static vars in exported inline/template function(X8664)
    sclass = SCLASS_UGLOBAL;
    sclass = SCLASS_UGLOBAL;
        }
        }
        else {
        else {
    // OTHERS:
    // OTHERS:
    //   treat it EXTERN ( will not allocate space )
    //   treat it EXTERN ( will not allocate space )
          sclass = SCLASS_EXTERN;
          sclass = SCLASS_EXTERN;
        }
        }
        level  = GLOBAL_SYMTAB;
        level  = GLOBAL_SYMTAB;
              eclass = EXPORT_PREEMPTIBLE;
              eclass = EXPORT_PREEMPTIBLE;
            }
            }
#ifdef KEY
#ifdef KEY
      // Bug 8652: If GNU marks it as COMMON, we should the same.
      // Bug 8652: If GNU marks it as COMMON, we should the same.
      else if (!flag_no_common &&
      else if (!flag_no_common &&
         gs_tree_static (decl_node) &&
         gs_tree_static (decl_node) &&
               gs_decl_common (decl_node) &&
               gs_decl_common (decl_node) &&
         gs_tree_public (decl_node)) {
         gs_tree_public (decl_node)) {
        sclass = SCLASS_COMMON;
        sclass = SCLASS_COMMON;
        level = GLOBAL_SYMTAB;
        level = GLOBAL_SYMTAB;
        eclass = EXPORT_PREEMPTIBLE;
        eclass = EXPORT_PREEMPTIBLE;
      }
      }
#endif
#endif
            else {
            else {
        if (gs_tree_static (decl_node)) {
        if (gs_tree_static (decl_node)) {
    sclass = SCLASS_PSTATIC;
    sclass = SCLASS_PSTATIC;
               if (pstatic_as_global
               if (pstatic_as_global
#ifdef KEY // bug 12668
#ifdef KEY // bug 12668
                   && ! (gs_decl_initial(decl_node) &&
                   && ! (gs_decl_initial(decl_node) &&
                         !gs_decl_external(decl_node) &&
                         !gs_decl_external(decl_node) &&
                         Has_label_decl(gs_decl_initial(decl_node)))
                         Has_label_decl(gs_decl_initial(decl_node)))
#endif
#endif
                 )
                 )
      level = GLOBAL_SYMTAB;
      level = GLOBAL_SYMTAB;
    else
    else
      level = CURRENT_SYMTAB;
      level = CURRENT_SYMTAB;
              }
              }
              else {
              else {
    sclass = SCLASS_AUTO;
    sclass = SCLASS_AUTO;
    level = DECL_SYMTAB_IDX(decl_node) ?
    level = DECL_SYMTAB_IDX(decl_node) ?
      DECL_SYMTAB_IDX(decl_node) : CURRENT_SYMTAB;
      DECL_SYMTAB_IDX(decl_node) : CURRENT_SYMTAB;
              }
              }
              eclass = EXPORT_LOCAL;
              eclass = EXPORT_LOCAL;
            }
            }
          }
          }
        }
        }
        // Make g++ guard variables local unless it's weak.
        // Make g++ guard variables local unless it's weak.
  if (guard_var) {
  if (guard_var) {
    level = GLOBAL_SYMTAB;
    level = GLOBAL_SYMTAB;
          if ( gs_decl_weak(decl_node) ) {
          if ( gs_decl_weak(decl_node) ) {
      sclass = SCLASS_UGLOBAL;
      sclass = SCLASS_UGLOBAL;
      eclass = EXPORT_PREEMPTIBLE;
      eclass = EXPORT_PREEMPTIBLE;
          }
          }
          else {
          else {
            sclass = SCLASS_PSTATIC;
            sclass = SCLASS_PSTATIC;
            eclass = EXPORT_LOCAL;
            eclass = EXPORT_LOCAL;
          }
          }
  }
  }
  // The tree under DECL_ARG_TYPE(decl_node) could reference decl_node.
  // The tree under DECL_ARG_TYPE(decl_node) could reference decl_node.
  // If that's the case, the Get_TY would create the ST for decl_node.
  // If that's the case, the Get_TY would create the ST for decl_node.
  // As a result, call GET_TY first, then check if the ST is already
  // As a result, call GET_TY first, then check if the ST is already
  // created, and create ST only if it isn't created.
  // created, and create ST only if it isn't created.
        ty_idx = Get_TY (gs_tree_type(decl_node));
        ty_idx = Get_TY (gs_tree_type(decl_node));
  st = DECL_ST(decl_node);
  st = DECL_ST(decl_node);
  if (st)
  if (st)
    return st;
    return st;
        st = New_ST (level);
        st = New_ST (level);
        if (TY_kind (ty_idx) == KIND_ARRAY &&
        if (TY_kind (ty_idx) == KIND_ARRAY &&
            gs_tree_static (decl_node) &&
            gs_tree_static (decl_node) &&
            gs_decl_initial (decl_node) == FALSE &&
            gs_decl_initial (decl_node) == FALSE &&
            TY_size (ty_idx) == 0) {
            TY_size (ty_idx) == 0) {
    Set_TY_size (ty_idx, TY_size (Get_TY (gs_tree_type (gs_tree_type (decl_node)))));
    Set_TY_size (ty_idx, TY_size (Get_TY (gs_tree_type (gs_tree_type (decl_node)))));
        }
        }
#ifndef KEY
#ifndef KEY
// bug 3735: the compiler cannot arbitrarily change the alignment of
// bug 3735: the compiler cannot arbitrarily change the alignment of
// individual structures
// individual structures
  if (TY_mtype (ty_idx) == MTYPE_M &&
  if (TY_mtype (ty_idx) == MTYPE_M &&
      Aggregate_Alignment > 0 &&
      Aggregate_Alignment > 0 &&
      Aggregate_Alignment > TY_align (ty_idx))
      Aggregate_Alignment > TY_align (ty_idx))
    Set_TY_align (ty_idx, Aggregate_Alignment);
    Set_TY_align (ty_idx, Aggregate_Alignment);
#endif // !KEY
#endif // !KEY
  // qualifiers are set on decl nodes
  // qualifiers are set on decl nodes
  if (gs_tree_readonly(decl_node))
  if (gs_tree_readonly(decl_node))
    Set_TY_is_const (ty_idx);
    Set_TY_is_const (ty_idx);
  if (gs_tree_this_volatile(decl_node))
  if (gs_tree_this_volatile(decl_node))
    Set_TY_is_volatile (ty_idx);
    Set_TY_is_volatile (ty_idx);
#if 1 // wgen bug 10470
#if 1 // wgen bug 10470
  else Clear_TY_is_volatile (ty_idx);
  else Clear_TY_is_volatile (ty_idx);
#endif
#endif
#ifdef KEY
#ifdef KEY
        // Handle aligned attribute (bug 7331)
        // Handle aligned attribute (bug 7331)
        if (gs_decl_user_align (decl_node))
        if (gs_decl_user_align (decl_node))
          Set_TY_align (ty_idx, gs_decl_align_unit(decl_node));
          Set_TY_align (ty_idx, gs_decl_align_unit(decl_node));
        // NOTE: we do not update the ty_idx value in the TYPE_TREE. So
        // NOTE: we do not update the ty_idx value in the TYPE_TREE. So
        // if any of the above properties are set, the next time we get into
        // if any of the above properties are set, the next time we get into
        // Get_ST, the ty_idx in the TYPE_TREE != ty_idx in st. The solution
        // Get_ST, the ty_idx in the TYPE_TREE != ty_idx in st. The solution
        // is either to update TYPE_TREE now, or compare the ty_idx_index
        // is either to update TYPE_TREE now, or compare the ty_idx_index
        // in Get_ST (instead of ty_idx). Currently we do the latter
        // in Get_ST (instead of ty_idx). Currently we do the latter
#endif // KEY
#endif // KEY
  // bug 34 3356 10892: gcc sometimes adds a '*' and itself handles it
  // bug 34 3356 10892: gcc sometimes adds a '*' and itself handles it
  //   this way while outputing
  //   this way while outputing
  char *p = name;
  char *p = name;
  if (*p == '*')
  if (*p == '*')
    p++;
    p++;
        ST_Init (st, Save_Str(p), CLASS_VAR, sclass, eclass, ty_idx);
        ST_Init (st, Save_Str(p), CLASS_VAR, sclass, eclass, ty_idx);
#ifdef KEY
#ifdef KEY
#ifdef FE_GNU_4_2_0
#ifdef FE_GNU_4_2_0
  if (gs_tree_code (decl_node) == GS_VAR_DECL &&
  if (gs_tree_code (decl_node) == GS_VAR_DECL &&
      // Bug 12968: just checking for threadprivate flag is not
      // Bug 12968: just checking for threadprivate flag is not
      // sufficient, because for C the flag is basically
      // sufficient, because for C the flag is basically
      // gs_decl_lang_flag_3.
      // gs_decl_lang_flag_3.
      gs_decl_thread_local (decl_node) &&
      gs_decl_thread_local (decl_node) &&
      ((!lang_cplus && gs_c_decl_threadprivate_p (decl_node)) ||
      ((!lang_cplus && gs_c_decl_threadprivate_p (decl_node)) ||
       (lang_cplus && gs_cp_decl_threadprivate_p (decl_node))))
       (lang_cplus && gs_cp_decl_threadprivate_p (decl_node))))
    Set_ST_is_thread_private (st);
    Set_ST_is_thread_private (st);
  if (gs_tree_code (decl_node) == GS_VAR_DECL && anon_st)
  if (gs_tree_code (decl_node) == GS_VAR_DECL && anon_st)
    WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
    WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
#endif
#endif
        if (gs_decl_size_unit (decl_node) &&
        if (gs_decl_size_unit (decl_node) &&
            gs_tree_code (gs_decl_size_unit (decl_node)) != GS_INTEGER_CST)
            gs_tree_code (gs_decl_size_unit (decl_node)) != GS_INTEGER_CST)
        {
        {
            // if this is the first alloca, save sp.
            // if this is the first alloca, save sp.
            int idx;
            int idx;
            if (!Set_Current_Scope_Has_Alloca (idx))
            if (!Set_Current_Scope_Has_Alloca (idx))
            {
            {
              ST * save_st = WGEN_Alloca_0 ();
              ST * save_st = WGEN_Alloca_0 ();
              Set_Current_Scope_Alloca_St (save_st, idx);
              Set_Current_Scope_Alloca_St (save_st, idx);
            }
            }
            WN * size = WGEN_Expand_Expr (gs_decl_size_unit (decl_node));
            WN * size = WGEN_Expand_Expr (gs_decl_size_unit (decl_node));
            // mimic WGEN_Alloca_ST
            // mimic WGEN_Alloca_ST
            ST * alloca_st = New_ST (CURRENT_SYMTAB);
            ST * alloca_st = New_ST (CURRENT_SYMTAB);
            ST_Init (alloca_st, Save_Str (name),
            ST_Init (alloca_st, Save_Str (name),
                       CLASS_VAR, SCLASS_AUTO, EXPORT_LOCAL,
                       CLASS_VAR, SCLASS_AUTO, EXPORT_LOCAL,
                                  Make_Pointer_Type (ty_idx, FALSE));
                                  Make_Pointer_Type (ty_idx, FALSE));
            Set_ST_is_temp_var (alloca_st);
            Set_ST_is_temp_var (alloca_st);
            Set_ST_pt_to_unique_mem (alloca_st);
            Set_ST_pt_to_unique_mem (alloca_st);
            Set_ST_base_idx (st, ST_st_idx (alloca_st));
            Set_ST_base_idx (st, ST_st_idx (alloca_st));
            WN *wn  = WN_CreateAlloca (size);
            WN *wn  = WN_CreateAlloca (size);
            wn = WN_Stid (Pointer_Mtype, 0, alloca_st, ST_type (alloca_st), wn);
            wn = WN_Stid (Pointer_Mtype, 0, alloca_st, ST_type (alloca_st), wn);
            WGEN_Stmt_Append (wn, Get_Srcpos());
            WGEN_Stmt_Append (wn, Get_Srcpos());
            Set_PU_has_alloca (Get_Current_PU());
            Set_PU_has_alloca (Get_Current_PU());
      // For kids 1..n of DEALLOCA
      // For kids 1..n of DEALLOCA
            Add_Current_Scope_Alloca_St (alloca_st, idx);
            Add_Current_Scope_Alloca_St (alloca_st, idx);
        }
        }
#endif // KEY
#endif // KEY
        if (gs_tree_code(decl_node) == GS_PARM_DECL) {
        if (gs_tree_code(decl_node) == GS_PARM_DECL) {
    Set_ST_is_value_parm(st);
    Set_ST_is_value_parm(st);
        }
        }
      }
      }
      break;
      break;
    default:
    default:
      {
      {
        Fail_FmtAssertion ("Create_ST_For_Tree: unexpected tree type %s",
        Fail_FmtAssertion ("Create_ST_For_Tree: unexpected tree type %s",
         WGEN_Tree_Node_Name(decl_node));
         WGEN_Tree_Node_Name(decl_node));
      }
      }
      break;
      break;
  }
  }
  set_DECL_ST(decl_node, st); // created now
  set_DECL_ST(decl_node, st); // created now
  // If VAR_DECL has a non-zero DECL_ASMREG, then DECL_ASMREG-1 is the register
  // If VAR_DECL has a non-zero DECL_ASMREG, then DECL_ASMREG-1 is the register
  // number assigned by an "asm".
  // number assigned by an "asm".
  if (gs_tree_code(decl_node) == GS_VAR_DECL && gs_decl_register(decl_node) &&
  if (gs_tree_code(decl_node) == GS_VAR_DECL && gs_decl_register(decl_node) &&
      gs_decl_asmreg(decl_node) >= 0) {
      gs_decl_asmreg(decl_node) >= 0) {
    extern PREG_NUM Map_Reg_To_Preg []; // defined in common/com/arch/config_targ.cxx
    extern PREG_NUM Map_Reg_To_Preg []; // defined in common/com/arch/config_targ.cxx
    int reg = gs_decl_asmreg(decl_node);
    int reg = gs_decl_asmreg(decl_node);
    PREG_NUM preg = Map_Reg_To_Preg [reg];
    PREG_NUM preg = Map_Reg_To_Preg [reg];
 
#if defined(TARG_SL)
 
    if (preg < 0 || preg > 31)
 
      ErrMsg (EC_Unimplemented_Feature, "Variable in Special register",
 
        Orig_Src_File_Name?Orig_Src_File_Name:Src_File_Name, lineno);
 
#endif
 
 
    FmtAssert (preg >= 0,
    FmtAssert (preg >= 0,
               ("mapping register %d to preg failed\n", reg));
               ("mapping register %d to preg failed\n", reg));
    TY_IDX ty_idx = ST_type (st);
    TY_IDX ty_idx = ST_type (st);
    Set_TY_is_volatile (ty_idx);
    Set_TY_is_volatile (ty_idx);
    Set_ST_type (st, ty_idx);
    Set_ST_type (st, ty_idx);
    Set_ST_assigned_to_dedicated_preg (st);
    Set_ST_assigned_to_dedicated_preg (st);
    ST_ATTR_IDX st_attr_idx;
    ST_ATTR_IDX st_attr_idx;
    // OSP_325, change CURRENT_SYMTAB to level to
    // OSP_325, change CURRENT_SYMTAB to level to
    //   make the level of the ST and ST_ATTR the same.
    //   make the level of the ST and ST_ATTR the same.
    ST_ATTR&    st_attr = New_ST_ATTR (level, st_attr_idx);
    ST_ATTR&    st_attr = New_ST_ATTR (level, st_attr_idx);
    ST_ATTR_Init (st_attr, ST_st_idx (st), ST_ATTR_DEDICATED_REGISTER, preg);
    ST_ATTR_Init (st_attr, ST_st_idx (st), ST_ATTR_DEDICATED_REGISTER, preg);
  }
  }
  if (gs_tree_code(decl_node) == GS_VAR_DECL) {
  if (gs_tree_code(decl_node) == GS_VAR_DECL) {
    if (gs_decl_context(decl_node) &&
    if (gs_decl_context(decl_node) &&
  gs_tree_code(gs_decl_context(decl_node)) == GS_RECORD_TYPE) {
  gs_tree_code(gs_decl_context(decl_node)) == GS_RECORD_TYPE) {
      Get_TY(gs_decl_context(decl_node));
      Get_TY(gs_decl_context(decl_node));
    }
    }
    if (gs_decl_thread_local(decl_node)
    if (gs_decl_thread_local(decl_node)
#ifdef FE_GNU_4_2_0
#ifdef FE_GNU_4_2_0
        // Bug 12891: threadprivate variables are also marked thread-local
        // Bug 12891: threadprivate variables are also marked thread-local
        // by GNU, but we don't want to tell our backend such variables are
        // by GNU, but we don't want to tell our backend such variables are
        // thread-local.
        // thread-local.
        &&  ((!lang_cplus && !gs_c_decl_threadprivate_p(decl_node)) ||
        &&  ((!lang_cplus && !gs_c_decl_threadprivate_p(decl_node)) ||
             (lang_cplus && !gs_cp_decl_threadprivate_p(decl_node)))
             (lang_cplus && !gs_cp_decl_threadprivate_p(decl_node)))
#endif
#endif
       ) {
       ) {
      Set_ST_is_thread_local(st);
      Set_ST_is_thread_local(st);
    }
    }
  }
  }
  if (Enable_WFE_DFE) {
  if (Enable_WFE_DFE) {
    if (gs_tree_code(decl_node) == GS_VAR_DECL &&
    if (gs_tree_code(decl_node) == GS_VAR_DECL &&
        level == GLOBAL_SYMTAB &&
        level == GLOBAL_SYMTAB &&
        !gs_decl_external (decl_node) &&
        !gs_decl_external (decl_node) &&
        gs_decl_initial (decl_node)) {
        gs_decl_initial (decl_node)) {
      Push_Deferred_Function (decl_node);
      Push_Deferred_Function (decl_node);
    }
    }
  }
  }
  if (gs_decl_weak      (decl_node) &&
  if (gs_decl_weak      (decl_node) &&
      (!gs_decl_external (decl_node)
      (!gs_decl_external (decl_node)
#ifdef KEY
#ifdef KEY
       // Make weak symbols for:
       // Make weak symbols for:
       //   extern "C" int bar() __attribute__ ((weak, alias("foo")))
       //   extern "C" int bar() __attribute__ ((weak, alias("foo")))
       // Bug 3841.
       // Bug 3841.
       || gs_decl_alias_target(decl_node))
       || gs_decl_alias_target(decl_node))
#endif
#endif
      ) {
      ) {
    Set_ST_is_weak_symbol (st);
    Set_ST_is_weak_symbol (st);
  }
  }
#ifdef KEY
#ifdef KEY
  // Make all symbols referenced in cleanup code and try handler code weak.
  // Make all symbols referenced in cleanup code and try handler code weak.
  // This is to work around an implementation issue where kg++fe always emit
  // This is to work around an implementation issue where kg++fe always emit
  // the code in a cleanup or try handler, regardless of whether such code is
  // the code in a cleanup or try handler, regardless of whether such code is
  // emitted by g++.  If the code calls a function foo that isn't emitted by
  // emitted by g++.  If the code calls a function foo that isn't emitted by
  // g++ into the RTL, then foo won't be tagged as needed, and the WHIRL for
  // g++ into the RTL, then foo won't be tagged as needed, and the WHIRL for
  // foo won't be genterated.  This leads to undefined symbol at link-time.
  // foo won't be genterated.  This leads to undefined symbol at link-time.
  //
  //
  // The correct solution is to mimick g++ and generate the cleanup/handler
  // The correct solution is to mimick g++ and generate the cleanup/handler
  // code only if the region can generate an exception.  g++ does this in
  // code only if the region can generate an exception.  g++ does this in
  // except.c by checking for "(flag_non_call_exceptions ||
  // except.c by checking for "(flag_non_call_exceptions ||
  // region->may_contain_throw)".  This checking isn't done in kg++fe because
  // region->may_contain_throw)".  This checking isn't done in kg++fe because
  // the equivalent of "region->may_contain_throw" isn't (yet) implemented.
  // the equivalent of "region->may_contain_throw" isn't (yet) implemented.
  // For now, work around the problem by making all symbols refereced in
  // For now, work around the problem by making all symbols refereced in
  // cleanups and try handlers as weak.
  // cleanups and try handlers as weak.
  if (make_symbols_weak) {
  if (make_symbols_weak) {
    if (eclass != EXPORT_LOCAL &&
    if (eclass != EXPORT_LOCAL &&
  eclass != EXPORT_LOCAL_INTERNAL &&
  eclass != EXPORT_LOCAL_INTERNAL &&
  // Don't make symbol weak if it is defined in current file.  Workaround
  // Don't make symbol weak if it is defined in current file.  Workaround
  // for SLES 8 linker.  Bug 3758.
  // for SLES 8 linker.  Bug 3758.
  WEAK_WORKAROUND(st) != WEAK_WORKAROUND_dont_make_weak &&
  WEAK_WORKAROUND(st) != WEAK_WORKAROUND_dont_make_weak &&
  // Don't make builtin functions weak.  Bug 9534.
  // Don't make builtin functions weak.  Bug 9534.
  !(gs_tree_code(decl_node) == GS_FUNCTION_DECL &&
  !(gs_tree_code(decl_node) == GS_FUNCTION_DECL &&
    gs_decl_built_in(decl_node))) {
    gs_decl_built_in(decl_node))) {
      Set_ST_is_weak_symbol (st);
      Set_ST_is_weak_symbol (st);
      WEAK_WORKAROUND(st) = WEAK_WORKAROUND_made_weak;
      WEAK_WORKAROUND(st) = WEAK_WORKAROUND_made_weak;
    }
    }
  }
  }
  // See comment above about guard variables.
  // See comment above about guard variables.
  else if (guard_var) {
  else if (guard_var) {
    if ( gs_decl_weak(decl_node) ) {
    if ( gs_decl_weak(decl_node) ) {
      Set_ST_is_weak_symbol (st);
      Set_ST_is_weak_symbol (st);
    }
    }
    Set_ST_init_value_zero (st);
    Set_ST_init_value_zero (st);
    Set_ST_is_initialized (st);
    Set_ST_is_initialized (st);
  }
  }
#endif
#endif
  if (gs_decl_section_name (decl_node)) {
  if (gs_decl_section_name (decl_node)) {
    if (strncmp(gs_tree_string_pointer (gs_decl_section_name (decl_node)),
    if (strncmp(gs_tree_string_pointer (gs_decl_section_name (decl_node)),
                ".gnu.linkonce.",
                ".gnu.linkonce.",
                14) != 0 ) {
                14) != 0 ) {
      // OSP. only handle non-.gnu.linkonce.* section name
      // OSP. only handle non-.gnu.linkonce.* section name
    DevWarn ("section %s specified for %s",
    DevWarn ("section %s specified for %s",
             gs_tree_string_pointer (gs_decl_section_name (decl_node)),
             gs_tree_string_pointer (gs_decl_section_name (decl_node)),
             ST_name (st));
             ST_name (st));
    if (gs_tree_code (decl_node) == GS_FUNCTION_DECL)
    if (gs_tree_code (decl_node) == GS_FUNCTION_DECL)
      level = GLOBAL_SYMTAB;
      level = GLOBAL_SYMTAB;
    ST_ATTR_IDX st_attr_idx;
    ST_ATTR_IDX st_attr_idx;
    ST_ATTR&    st_attr = New_ST_ATTR (level, st_attr_idx);
    ST_ATTR&    st_attr = New_ST_ATTR (level, st_attr_idx);
    ST_ATTR_Init (st_attr, ST_st_idx (st), ST_ATTR_SECTION_NAME,
    ST_ATTR_Init (st_attr, ST_st_idx (st), ST_ATTR_SECTION_NAME,
                  Save_Str (gs_tree_string_pointer (gs_decl_section_name (decl_node))));
                  Save_Str (gs_tree_string_pointer (gs_decl_section_name (decl_node))));
    if (!lang_cplus) // bug 14187
    if (!lang_cplus) // bug 14187
      Set_ST_has_named_section (st);
      Set_ST_has_named_section (st);
    }
    }
    else {
    else {
      // OSP. Ignore .gnu.linkonce.* section name
      // OSP. Ignore .gnu.linkonce.* section name
      DevWarn ("Ignore section %s specified for %s",
      DevWarn ("Ignore section %s specified for %s",
               gs_tree_string_pointer (gs_decl_section_name (decl_node)),
               gs_tree_string_pointer (gs_decl_section_name (decl_node)),
               ST_name (st));
               ST_name (st));
    }
    }
  }
  }
#if defined(TARG_IA64)
#if defined(TARG_IA64)
  //lookup syscall_linkage attribute for FUNCTION_DECL
  //lookup syscall_linkage attribute for FUNCTION_DECL
  if (gs_tree_code (decl_node) == GS_FUNCTION_DECL)
  if (gs_tree_code (decl_node) == GS_FUNCTION_DECL)
  {
  {
    // Iterate the attributes of the type of the decl
    // Iterate the attributes of the type of the decl
    gs_t type_attr_list = gs_type_attributes(gs_tree_type(decl_node));
    gs_t type_attr_list = gs_type_attributes(gs_tree_type(decl_node));
    gs_t type_attr;
    gs_t type_attr;
    for ( type_attr = type_attr_list; type_attr; type_attr = gs_tree_chain(type_attr)) {
    for ( type_attr = type_attr_list; type_attr; type_attr = gs_tree_chain(type_attr)) {
      if (gs_tree_purpose(type_attr) != NULL &&
      if (gs_tree_purpose(type_attr) != NULL &&
          gs_code(gs_tree_purpose(type_attr)) == GS_IDENTIFIER_NODE ) {
          gs_code(gs_tree_purpose(type_attr)) == GS_IDENTIFIER_NODE ) {
        const char * attr_name = gs_tree_string_pointer(gs_tree_purpose(type_attr));
        const char * attr_name = gs_tree_string_pointer(gs_tree_purpose(type_attr));
        if( strcmp("syscall_linkage", attr_name) == 0 ) {
        if( strcmp("syscall_linkage", attr_name) == 0 ) {
          // this function has attribute "syscall_linkage"
          // this function has attribute "syscall_linkage"
          DevWarn("Encounter syscall_linkage attribute!!!");
          DevWarn("Encounter syscall_linkage attribute!!!");
          Set_PU_has_syscall_linkage (Pu_Table [ST_pu(st)]);
          Set_PU_has_syscall_linkage (Pu_Table [ST_pu(st)]);
          // We only handle the "syscall_linkage" so far
          // We only handle the "syscall_linkage" so far
          break;
          break;
        }
        }
      }
      }
    }
    }
  }
  }
#endif
#endif
  if (gs_tree_code (decl_node) == GS_VAR_DECL)
  if (gs_tree_code (decl_node) == GS_VAR_DECL)
  {
  {
#if !defined(TARG_NVISA)
#if !defined(TARG_NVISA)
    gs_tls_model_kind_t tlsk =
    gs_tls_model_kind_t tlsk =
      (gs_tls_model_kind_t) gs_decl_tls_model(decl_node);
      (gs_tls_model_kind_t) gs_decl_tls_model(decl_node);
    enum ST_TLS_MODEL tls_model = TLS_NONE;
    enum ST_TLS_MODEL tls_model = TLS_NONE;
    switch (tlsk) {
    switch (tlsk) {
      case GS_TLS_MODEL_GLOBAL_DYNAMIC:
      case GS_TLS_MODEL_GLOBAL_DYNAMIC:
        tls_model = TLS_GLOBAL_DYNAMIC;
        tls_model = TLS_GLOBAL_DYNAMIC;
        break;
        break;
      case GS_TLS_MODEL_LOCAL_DYNAMIC:
      case GS_TLS_MODEL_LOCAL_DYNAMIC:
        tls_model = TLS_LOCAL_DYNAMIC;
        tls_model = TLS_LOCAL_DYNAMIC;
        break;
        break;
      case GS_TLS_MODEL_INITIAL_EXEC:
      case GS_TLS_MODEL_INITIAL_EXEC:
        tls_model = TLS_INITIAL_EXEC;
        tls_model = TLS_INITIAL_EXEC;
        break;
        break;
      case GS_TLS_MODEL_LOCAL_EXEC:
      case GS_TLS_MODEL_LOCAL_EXEC:
        tls_model = TLS_LOCAL_EXEC;
        tls_model = TLS_LOCAL_EXEC;
        break;
        break;
    }
    }
    Set_ST_tls_model(st, tls_model);
    Set_ST_tls_model(st, tls_model);
#endif
#endif
  }
  }
  if(Debug_Level >= 2) {
  if(Debug_Level >= 2) {
    // Bug 559
    // Bug 559
    if (ST_sclass(st) != SCLASS_EXTERN) {
    if (ST_sclass(st) != SCLASS_EXTERN) {
      // Add DSTs for all types seen so far.
      // Add DSTs for all types seen so far.
      add_deferred_DST_types();
      add_deferred_DST_types();
      DST_INFO_IDX dst = Create_DST_decl_For_Tree(decl_node,st);
      DST_INFO_IDX dst = Create_DST_decl_For_Tree(decl_node,st);
      DECL_DST_IDX(decl_node) = dst;
      DECL_DST_IDX(decl_node) = dst;
    }
    }
  }
  }
#ifdef KEY
#ifdef KEY
  // Bug 11352: For C++, expand any initializations decl_node may have,
  // Bug 11352: For C++, expand any initializations decl_node may have,
  // after the ST is fully formed. The decl may be in gxx_emitted_decls
  // after the ST is fully formed. The decl may be in gxx_emitted_decls
  // list, and WGEN_Process_Var_Decl may have decided not to expand it.
  // list, and WGEN_Process_Var_Decl may have decided not to expand it.
  // Now that we are here, we are sure to need any initialization it
  // Now that we are here, we are sure to need any initialization it
  // may have.
  // may have.
  if (lang_cplus && gs_tree_code(decl_node) == GS_VAR_DECL &&
  if (lang_cplus && gs_tree_code(decl_node) == GS_VAR_DECL &&
      !expanded_decl(decl_node))
      !expanded_decl(decl_node))
    WGEN_Expand_Decl(decl_node, TRUE);
    WGEN_Expand_Decl(decl_node, TRUE);
#endif
#endif
  return st;
  return st;
}
}
#include <ext/hash_map>
#include <ext/hash_map>
namespace {
namespace {
  using __gnu_cxx::hash_map;
  using __gnu_cxx::hash_map;
  struct ptrhash {
  struct ptrhash {
    size_t operator()(void* p) const { return reinterpret_cast<size_t>(p); }
    size_t operator()(void* p) const { return reinterpret_cast<size_t>(p); }
  };
  };
  hash_map<gs_t, TY_IDX,     ptrhash>     ty_idx_map;
  hash_map<gs_t, TY_IDX,     ptrhash>     ty_idx_map;
  hash_map<gs_t, ST*,        ptrhash>     st_map;
  hash_map<gs_t, ST*,        ptrhash>     st_map;
  hash_map<gs_t, SYMTAB_IDX, ptrhash>     symtab_idx_map;
  hash_map<gs_t, SYMTAB_IDX, ptrhash>     symtab_idx_map;
  hash_map<gs_t, LABEL_IDX,  ptrhash>     label_idx_map;
  hash_map<gs_t, LABEL_IDX,  ptrhash>     label_idx_map;
  hash_map<gs_t, ST*,        ptrhash>     string_st_map;
  hash_map<gs_t, ST*,        ptrhash>     string_st_map;
  hash_map<gs_t, BOOL,       ptrhash>     bool_map;
  hash_map<gs_t, BOOL,       ptrhash>     bool_map;
  hash_map<gs_t, INT32,      ptrhash>     field_id_map;
  hash_map<gs_t, INT32,      ptrhash>     field_id_map;
  hash_map<gs_t, INT32,   ptrhash>     type_field_ids_used_map;
  hash_map<gs_t, INT32,   ptrhash>     type_field_ids_used_map;
  hash_map<gs_t, INT32,      ptrhash>     scope_number_map;
  hash_map<gs_t, INT32,      ptrhash>     scope_number_map;
  hash_map<gs_t, gs_t,       ptrhash>     label_scope_map;
  hash_map<gs_t, gs_t,       ptrhash>     label_scope_map;
  hash_map<gs_t, DST_INFO_IDX,ptrhash>    decl_idx_map;
  hash_map<gs_t, DST_INFO_IDX,ptrhash>    decl_idx_map;
  hash_map<gs_t, DST_INFO_IDX,ptrhash>    decl_field_idx_map;
  hash_map<gs_t, DST_INFO_IDX,ptrhash>    decl_field_idx_map;
  hash_map<gs_t, DST_INFO_IDX,ptrhash>    decl_specification_idx_map;
  hash_map<gs_t, DST_INFO_IDX,ptrhash>    decl_specification_idx_map;
  hash_map<gs_t, DST_INFO_IDX,ptrhash>    type_idx_map;
  hash_map<gs_t, DST_INFO_IDX,ptrhash>    type_idx_map;
  hash_map<gs_t, LABEL_IDX,  ptrhash>     handler_label_map;
  hash_map<gs_t, LABEL_IDX,  ptrhash>     handler_label_map;
  hash_map<gs_t, DST_INFO_IDX,ptrhash>    abstract_root_map;
  hash_map<gs_t, DST_INFO_IDX,ptrhash>    abstract_root_map;
#ifdef KEY
#ifdef KEY
  // Map PU to the PU-specific st_map.
  // Map PU to the PU-specific st_map.
  hash_map<PU*, hash_map<gs_t, ST*, ptrhash>*, ptrhash>     pu_map;
  hash_map<PU*, hash_map<gs_t, ST*, ptrhash>*, ptrhash>     pu_map;
  // TRUE if ST is a decl that is being/already been expanded.
  // TRUE if ST is a decl that is being/already been expanded.
  hash_map<gs_t, BOOL,        ptrhash>     expanded_decl_map;
  hash_map<gs_t, BOOL,        ptrhash>     expanded_decl_map;
  // TRUE if TREE is a DECL_FUNCTION whose PU should have PU_uplevel set.
  // TRUE if TREE is a DECL_FUNCTION whose PU should have PU_uplevel set.
  hash_map<gs_t, BOOL,        ptrhash>     func_PU_uplevel_map;
  hash_map<gs_t, BOOL,        ptrhash>     func_PU_uplevel_map;
  hash_map<gs_t, gs_t,        ptrhash>     parent_scope_map;
  hash_map<gs_t, gs_t,        ptrhash>     parent_scope_map;
  // Record whether a symbol referenced in a cleanup should be marked weak as a
  // Record whether a symbol referenced in a cleanup should be marked weak as a
  // workaround to the fact that kg++fe may emit cleanups that g++ won't emit
  // workaround to the fact that kg++fe may emit cleanups that g++ won't emit
  // because g++ knows that are not needed.  The linker will complain if these
  // because g++ knows that are not needed.  The linker will complain if these
  // symbols are not defined.
  // symbols are not defined.
  hash_map<ST*, INT32,        ptrhash>     weak_workaround_map;
  hash_map<ST*, INT32,        ptrhash>     weak_workaround_map;
#endif
#endif
  hash_map<gs_t, ST*,       ptrhash>     decl_st2_map;
  hash_map<gs_t, ST*,       ptrhash>     decl_st2_map;
}
}
TY_IDX& TYPE_TY_IDX(gs_t t)         { return ty_idx_map[t]; }
TY_IDX& TYPE_TY_IDX(gs_t t)         { return ty_idx_map[t]; }
BOOL& expanded_decl(gs_t t) {
BOOL& expanded_decl(gs_t t) {
  FmtAssert (t, ("func_expanded: not a decl"));
  FmtAssert (t, ("func_expanded: not a decl"));
  return expanded_decl_map[t];
  return expanded_decl_map[t];
}
}
// Put ST in a map based on the tree node T and the current PU.
// Put ST in a map based on the tree node T and the current PU.
void
void
set_DECL_ST(gs_t t, ST* st) {
set_DECL_ST(gs_t t, ST* st) {
  // Find the tree node to use as index into st_map.
  // Find the tree node to use as index into st_map.
  gs_t t_index;
  gs_t t_index;
  if (gs_tree_code(t) == GS_VAR_DECL &&
  if (gs_tree_code(t) == GS_VAR_DECL &&
      (gs_decl_context(t) == 0 ||
      (gs_decl_context(t) == 0 ||
       gs_tree_code(gs_decl_context(t)) == GS_NAMESPACE_DECL) &&
       gs_tree_code(gs_decl_context(t)) == GS_NAMESPACE_DECL) &&
     gs_decl_name (t) && gs_decl_assembler_name(t))
     gs_decl_name (t) && gs_decl_assembler_name(t))
    t_index = gs_decl_assembler_name(t);
    t_index = gs_decl_assembler_name(t);
  else
  else
    t_index = t;
    t_index = t;
  // If ST is 1, then the caller only wants to pretend that there is a symbol
  // If ST is 1, then the caller only wants to pretend that there is a symbol
  // for T.  Later on, the caller will reset the ST to NULL and assign a real
  // for T.  Later on, the caller will reset the ST to NULL and assign a real
  // symbol to T.
  // symbol to T.
  if (st == (ST *) 1) {
  if (st == (ST *) 1) {
    st_map[t_index] = st;
    st_map[t_index] = st;
    return;
    return;
  }
  }
  // If ST is a symbol that should be shared across functions, then put ST in
  // If ST is a symbol that should be shared across functions, then put ST in
  // the st_map, which maps T directly to ST.  Otherwise, put ST in the
  // the st_map, which maps T directly to ST.  Otherwise, put ST in the
  // PU-specific st_map.
  // PU-specific st_map.
  //
  //
  // It is observed that g++ uses the same tree for different functions, such
  // It is observed that g++ uses the same tree for different functions, such
  // as inline functions.  As a result, we cannot attach PU-specific ST's
  // as inline functions.  As a result, we cannot attach PU-specific ST's
  // directly to the tree nodes.
  // directly to the tree nodes.
  //
  //
  // If Current_scope is 0, then the symbol table has not been initialized, and
  // If Current_scope is 0, then the symbol table has not been initialized, and
  // we are being called by WFE_Add_Weak to handle a weak symbol.  In that
  // we are being called by WFE_Add_Weak to handle a weak symbol.  In that
  // case, use the non-PU-specific st_map.
  // case, use the non-PU-specific st_map.
  if (Current_scope != 0 &&
  if (Current_scope != 0 &&
      (gs_tree_code(t) == GS_PARM_DECL ||
      (gs_tree_code(t) == GS_PARM_DECL ||
       (gs_tree_code(t) == GS_VAR_DECL &&
       (gs_tree_code(t) == GS_VAR_DECL &&
        (ST_sclass(st) == SCLASS_AUTO ||
        (ST_sclass(st) == SCLASS_AUTO ||
         (! pstatic_as_global &&
         (! pstatic_as_global &&
    ST_sclass(st) == SCLASS_PSTATIC))))) {
    ST_sclass(st) == SCLASS_PSTATIC))))) {
    // ST is PU-specific.  Use pu_map[pu] to get the PU-specific st_map, then
    // ST is PU-specific.  Use pu_map[pu] to get the PU-specific st_map, then
    // use st_map[t] to get the ST for the tree node t.
    // use st_map[t] to get the ST for the tree node t.
    //
    //
    // We can access pu_map[pu] only if Scope_tab[Current_scope].st is valid
    // We can access pu_map[pu] only if Scope_tab[Current_scope].st is valid
    // because we need to get the current PU, but Get_Current_PU requires a
    // because we need to get the current PU, but Get_Current_PU requires a
    // valid Scope_tab[Current_scope].st.  If Scope_tab[Current_scope].st is
    // valid Scope_tab[Current_scope].st.  If Scope_tab[Current_scope].st is
    // not set, then this means the caller is trying to create the ST for the
    // not set, then this means the caller is trying to create the ST for the
    // function symbol.
    // function symbol.
    if (Scope_tab[Current_scope].st != NULL) {
    if (Scope_tab[Current_scope].st != NULL) {
      // ok to call Get_Current_PU.
      // ok to call Get_Current_PU.
      PU *pu = &Get_Current_PU();
      PU *pu = &Get_Current_PU();
      hash_map<PU*, hash_map<gs_t, ST*, ptrhash>*, ptrhash>::iterator it =
      hash_map<PU*, hash_map<gs_t, ST*, ptrhash>*, ptrhash>::iterator it =
  pu_map.find(pu);
  pu_map.find(pu);
      if (it == pu_map.end()) {
      if (it == pu_map.end()) {
  // Create new PU-specific map.
  // Create new PU-specific map.
  pu_map[pu] = new hash_map<gs_t, ST*, ptrhash>;
  pu_map[pu] = new hash_map<gs_t, ST*, ptrhash>;
      }
      }
      // Put the ST in the PU-specific st_map.
      // Put the ST in the PU-specific st_map.
      (*(pu_map[pu]))[t_index] = st;
      (*(pu_map[pu]))[t_index] = st;
    }
    }
  } else {
  } else {
#ifdef Is_True_On
#ifdef Is_True_On
    if (st_map[t_index]) {
    if (st_map[t_index]) {
      // The st_map is already set.  This is ok only for weak ST.
      // The st_map is already set.  This is ok only for weak ST.
      FmtAssert (ST_is_weak_symbol(st_map[t_index]),
      FmtAssert (ST_is_weak_symbol(st_map[t_index]),
     ("set_DECL_ST: st_map already set"));
     ("set_DECL_ST: st_map already set"));
    }
    }
#endif
#endif
    // Put the ST in the non-PU-specific st_map.
    // Put the ST in the non-PU-specific st_map.
    st_map[t_index] = st;
    st_map[t_index] = st;
  }
  }
}
}
// Get ST associated with the tree node T.
// Get ST associated with the tree node T.
ST*&
ST*&
get_DECL_ST(gs_t t) {
get_DECL_ST(gs_t t) {
  static ST *null_ST = (ST *) NULL;
  static ST *null_ST = (ST *) NULL;
  // Find the tree node to use as index into st_map.
  // Find the tree node to use as index into st_map.
  gs_t t_index;
  gs_t t_index;
  if (gs_tree_code(t) == GS_VAR_DECL &&
  if (gs_tree_code(t) == GS_VAR_DECL &&
      (gs_decl_context(t) == 0 ||
      (gs_decl_context(t) == 0 ||
       gs_tree_code(gs_decl_context(t)) == GS_NAMESPACE_DECL) &&
       gs_tree_code(gs_decl_context(t)) == GS_NAMESPACE_DECL) &&
     gs_decl_name (t) && gs_decl_assembler_name(t))
     gs_decl_name (t) && gs_decl_assembler_name(t))
    t_index = gs_decl_assembler_name(t);
    t_index = gs_decl_assembler_name(t);
  else
  else
    t_index = t;
    t_index = t;
  // If Current_scope is 0, then the symbol table has not been initialized, and
  // If Current_scope is 0, then the symbol table has not been initialized, and
  // we are being called by WFE_Add_Weak to handle a weak symbol.  Use the
  // we are being called by WFE_Add_Weak to handle a weak symbol.  Use the
  // non-PU-specific st_map.
  // non-PU-specific st_map.
  if (Current_scope == 0)
  if (Current_scope == 0)
    return st_map[t_index];
    return st_map[t_index];
  // See if the ST is in the non-PU-specific st_map.
  // See if the ST is in the non-PU-specific st_map.
  if (st_map[t_index]) {
  if (st_map[t_index]) {
    return st_map[t_index];
    return st_map[t_index];
  }
  }
  // The ST is not in the non-PU-specific map.  Look in the PU-specific maps.
  // The ST is not in the non-PU-specific map.  Look in the PU-specific maps.
  INT scope = Current_scope;
  INT scope = Current_scope;
  do {
  do {
    // If Scope_tab[scope].st is NULL, then the function ST has not
    // If Scope_tab[scope].st is NULL, then the function ST has not
    // been set yet, and there is no PU-specific map.
    // been set yet, and there is no PU-specific map.
    if (Scope_tab[scope].st != NULL) {
    if (Scope_tab[scope].st != NULL) {
      // See if there is a PU-specific map.
      // See if there is a PU-specific map.
      PU *pu = &Get_Scope_PU(scope);
      PU *pu = &Get_Scope_PU(scope);
      hash_map<PU*, hash_map<gs_t, ST*, ptrhash>*, ptrhash>::iterator pu_map_it =
      hash_map<PU*, hash_map<gs_t, ST*, ptrhash>*, ptrhash>::iterator pu_map_it =
  pu_map.find(pu);
  pu_map.find(pu);
      if (pu_map_it != pu_map.end()) {
      if (pu_map_it != pu_map.end()) {
  // There is a PU-specific map.  Get the ST from the map.
  // There is a PU-specific map.  Get the ST from the map.
  hash_map<gs_t, ST*, ptrhash> *st_map2 = pu_map[pu];
  hash_map<gs_t, ST*, ptrhash> *st_map2 = pu_map[pu];
  if ((*st_map2)[t_index])
  if ((*st_map2)[t_index])
    return (*st_map2)[t_index];
    return (*st_map2)[t_index];
      }
      }
    }
    }
    scope--;
    scope--;
  } while (scope > 1);
  } while (scope > 1);
  return null_ST;
  return null_ST;
}
}
BOOL&
BOOL&
func_PU_uplevel(gs_t t) {
func_PU_uplevel(gs_t t) {
  FmtAssert (gs_tree_code(t) == GS_FUNCTION_DECL,
  FmtAssert (gs_tree_code(t) == GS_FUNCTION_DECL,
       ("func_PU_uplevel: not a FUNCTION_DECL tree node"));
       ("func_PU_uplevel: not a FUNCTION_DECL tree node"));
  return func_PU_uplevel_map[t];
  return func_PU_uplevel_map[t];
}
}
INT32& WEAK_WORKAROUND(ST *st)         { return weak_workaround_map[st]; }
INT32& WEAK_WORKAROUND(ST *st)         { return weak_workaround_map[st]; }
SYMTAB_IDX& DECL_SYMTAB_IDX(gs_t t) { return symtab_idx_map[t]; }
SYMTAB_IDX& DECL_SYMTAB_IDX(gs_t t) { return symtab_idx_map[t]; }
LABEL_IDX& DECL_LABEL_IDX(gs_t t)   { return label_idx_map[t]; }
LABEL_IDX& DECL_LABEL_IDX(gs_t t)   { return label_idx_map[t]; }
ST*& TREE_STRING_ST(gs_t t)         { return string_st_map[t]; }
ST*& TREE_STRING_ST(gs_t t)         { return string_st_map[t]; }
BOOL& DECL_LABEL_DEFINED(gs_t t)    { return bool_map[t]; }
BOOL& DECL_LABEL_DEFINED(gs_t t)    { return bool_map[t]; }
INT32& DECL_FIELD_ID(gs_t t)        { return field_id_map[t]; }
INT32& DECL_FIELD_ID(gs_t t)        { return field_id_map[t]; }
INT32 & TYPE_FIELD_IDS_USED(gs_t t) { return type_field_ids_used_map[t]; }
INT32 & TYPE_FIELD_IDS_USED(gs_t t) { return type_field_ids_used_map[t]; }
INT32 & SCOPE_NUMBER(gs_t t)        { return scope_number_map[t]; }
INT32 & SCOPE_NUMBER(gs_t t)        { return scope_number_map[t]; }
#ifdef KEY
#ifdef KEY
gs_t & PARENT_SCOPE(gs_t t)     { return parent_scope_map[t]; }
gs_t & PARENT_SCOPE(gs_t t)     { return parent_scope_map[t]; }
#endif
#endif
gs_t & LABEL_SCOPE(gs_t t)      { return label_scope_map[t]; }
gs_t & LABEL_SCOPE(gs_t t)      { return label_scope_map[t]; }
ST* & DECL_ST2(gs_t t)        { return decl_st2_map[t]; }
ST* & DECL_ST2(gs_t t)        { return decl_st2_map[t]; }
// This is for normal declarations.
// This is for normal declarations.
// We do not know if the DST entry is filled in.
// We do not know if the DST entry is filled in.
// So check and ensure a real entry exists.
// So check and ensure a real entry exists.
DST_INFO_IDX & DECL_DST_IDX(gs_t t)
DST_INFO_IDX & DECL_DST_IDX(gs_t t)
{
{
  hash_map<gs_t, DST_INFO_IDX,ptrhash>::iterator it =
  hash_map<gs_t, DST_INFO_IDX,ptrhash>::iterator it =
    decl_idx_map.find(t);
    decl_idx_map.find(t);
  if(it == decl_idx_map.end()) {
  if(it == decl_idx_map.end()) {
    // substitute for lack of default constructor
    // substitute for lack of default constructor
    DST_INFO_IDX dsti = DST_INVALID_IDX;
    DST_INFO_IDX dsti = DST_INVALID_IDX;
    decl_idx_map[t] = dsti;
    decl_idx_map[t] = dsti;
  }
  }
  return decl_idx_map[t];
  return decl_idx_map[t];
}
}
// This is for static class members and member functions.
// This is for static class members and member functions.
// We need a distinct DST record for a single ST.
// We need a distinct DST record for a single ST.
// Note that only the main record actually need be linked
// Note that only the main record actually need be linked
// to ST as only that one gets an address/location.
// to ST as only that one gets an address/location.
// We do not know if the DST entry is filled in.
// We do not know if the DST entry is filled in.
// So check and ensure a real entry exists.
// So check and ensure a real entry exists.
DST_INFO_IDX & DECL_DST_SPECIFICATION_IDX(gs_t t)
DST_INFO_IDX & DECL_DST_SPECIFICATION_IDX(gs_t t)
{
{
  hash_map<gs_t, DST_INFO_IDX,ptrhash>::iterator it =
  hash_map<gs_t, DST_INFO_IDX,ptrhash>::iterator it =
    decl_specification_idx_map.find(t);
    decl_specification_idx_map.find(t);
  if(it == decl_specification_idx_map.end()) {
  if(it == decl_specification_idx_map.end()) {
    // substitute for lack of default constructor
    // substitute for lack of default constructor
    DST_INFO_IDX dsti = DST_INVALID_IDX;
    DST_INFO_IDX dsti = DST_INVALID_IDX;
    decl_specification_idx_map[t] = dsti;
    decl_specification_idx_map[t] = dsti;
  }
  }
  return decl_specification_idx_map[t];
  return decl_specification_idx_map[t];
}
}
// This is for static class members and member functions.
// This is for static class members and member functions.
// We need a distinct DST record for a single ST.
// We need a distinct DST record for a single ST.
// Note that only the main record actually need be linked
// Note that only the main record actually need be linked
// to ST as only that one gets an address/location.
// to ST as only that one gets an address/location.
// We do not know if the DST entry is filled in.
// We do not know if the DST entry is filled in.
// So check and ensure a real entry exists.
// So check and ensure a real entry exists.
DST_INFO_IDX & DECL_DST_FIELD_IDX(gs_t t)
DST_INFO_IDX & DECL_DST_FIELD_IDX(gs_t t)
{
{
  hash_map<gs_t, DST_INFO_IDX,ptrhash>::iterator it =
  hash_map<gs_t, DST_INFO_IDX,ptrhash>::iterator it =
    decl_field_idx_map.find(t);
    decl_field_idx_map.find(t);
  if(it == decl_idx_map.end()) {
  if(it == decl_idx_map.end()) {
    // substitute for lack of default constructor
    // substitute for lack of default constructor
    DST_INFO_IDX dsti = DST_INVALID_IDX;
    DST_INFO_IDX dsti = DST_INVALID_IDX;
    decl_field_idx_map[t] = dsti;
    decl_field_idx_map[t] = dsti;
  }
  }
  return decl_field_idx_map[t];
  return decl_field_idx_map[t];
}
}
// We do not know if the DST entry is filled in.
// We do not know if the DST entry is filled in.
// So check and ensure a real entry exists.
// So check and ensure a real entry exists.
DST_INFO_IDX & TYPE_DST_IDX(gs_t t)
DST_INFO_IDX & TYPE_DST_IDX(gs_t t)
{
{
  hash_map<gs_t, DST_INFO_IDX,ptrhash>::iterator it =
  hash_map<gs_t, DST_INFO_IDX,ptrhash>::iterator it =
    type_idx_map.find(t);
    type_idx_map.find(t);
  if(it == type_idx_map.end()) {
  if(it == type_idx_map.end()) {
    // substitute for lack of default constructor
    // substitute for lack of default constructor
    DST_INFO_IDX dsti = DST_INVALID_IDX;
    DST_INFO_IDX dsti = DST_INVALID_IDX;
    type_idx_map[t] = dsti;
    type_idx_map[t] = dsti;
  }
  }
  return type_idx_map[t];
  return type_idx_map[t];
}
}
// We do not know if the DST entry is filled in.
// We do not know if the DST entry is filled in.
// So check and ensure a real entry exists.
// So check and ensure a real entry exists.
DST_INFO_IDX & DECL_DST_ABSTRACT_ROOT_IDX(gs_t t)
DST_INFO_IDX & DECL_DST_ABSTRACT_ROOT_IDX(gs_t t)
{
{
  hash_map<gs_t, DST_INFO_IDX,ptrhash>::iterator it =
  hash_map<gs_t, DST_INFO_IDX,ptrhash>::iterator it =
    abstract_root_map.find(t);
    abstract_root_map.find(t);
  if(it == abstract_root_map.end()) {
  if(it == abstract_root_map.end()) {
    // substitute for lack of default constructor
    // substitute for lack of default constructor
    DST_INFO_IDX dsti = DST_INVALID_IDX;
    DST_INFO_IDX dsti = DST_INVALID_IDX;
    abstract_root_map[t] = dsti;
    abstract_root_map[t] = dsti;
  }
  }
  return abstract_root_map[t];
  return abstract_root_map[t];
}
}
LABEL_IDX& HANDLER_LABEL(gs_t t)    { return handler_label_map[t]; }
LABEL_IDX& HANDLER_LABEL(gs_t t)    { return handler_label_map[t]; }