diff mbox

RFC: [GUPC] UPC-related front-end changes

Message ID 20110701183145.GD6262@intrepid.com
State New
Headers show

Commit Message

Gary Funck July 1, 2011, 6:31 p.m. UTC
This email is a follow-up to an email with a similar title
(posted a year ago).  During that time period, we have worked
on making the changes suggested by Joseph Myers, Tom Tromey,
and other reviewers.  We have also implemented various bug fixes
and improvements.

This RFC focuses mainly on front-end and infrastructure changes.

Our goal with this RFC is to acquaint the reviewers with UPC and
the impact of UPC changes on the GCC front-end, and to gain consensus
that the changes are acceptable for incorporation into the GCC trunk.

Once we make further suggested changes, and have a consensus on this
batch of changes, I will send out RFC's for the "middle end"
(the lowering pass), "debugging" (UPC-specific DWARF extensions),
"runtime" (libupc) and "testing" RFC's.  Those additional RFC's
are likely to be more modular and will have less impact on
the GCC infrastructure.

The main review-related changes are:

* FIXMEs and TODOs were either fixed or cleaned up.

* The copyright and license notices were updated.

* The code was reviewed for conformance to coding standards and updated.

* Diagnostics now use appropriate format strings rather than building
up the strings with sprintf().

* Files in c-family/ no longer include c-tree.h to conform with modularization
improvements.

* Most of the #ifdef conditionals have been removed.  Some target macros
have been defined and documented in tm.texi.  We still have some questions
in this area due to some configuration issues that are unique to UPC
and will discuss those changes in a follow-up email.

* The code was reviewed to verify that it conforms with
current GCC coding practices and that it incorporates cleanups
done in the past several years.

* Comments were added to most new functions, and typos and
spelling errors in comments were fixed.

* Changes that appeared in the diffs that were unrelated to UPC
were removed or incorporated into the trunk.

* Tree node flags that record UPC qualifiers were moved from
their own flag byte into tree_base's "spare" bits.

* The linkage to the libupc library was changed to use the newly
defined method (used in libgomp/libgo for example) of including
library 'spec' files.  This led to a simplification where we no
longer needed to add UPC-specific spec. files in various target-specfic
config. dirs.

thanks,

- Gary

RFC: UPC-related Front-End Changes
----------------------------------

This document describes the UPC-related front-end
changes, and is provided as background for
review of the UPC changes implemented in
the GUPC branch.

The current GUPC branch is based upon a recent
version of the GCC trunk (175584), and has been
bootstrapped on x86_64/i686 Linux and IA64/Altix Linux.
Bootstraps on other platforms are in progress.

The GUPC branch is described here:
  http://gcc.gnu.org/projects/gupc.html

The UPC-related source code differences
are summarized here:
  http://gccupc.org/gupc-changes

In the discussion below, the changes are
excerpted in order to highlight important
aspects of the changes.

UPC's Shared Qualifier and Layout Qualifier
-------------------------------------------

The UPC language specification describes
the language syntax and semantics:
  http://upc.gwu.edu/docs/upc_specs_1.2.pdf

UPC introduces a new qualifier, "shared"
that indicates that the qualified object
is located in a global shared address space
that is accessible by all UPC threads.
Additional qualifiers ("strict" and "relaxed")
further specify the semantics of accesses to
UPC shared objects.

In UPC, a shared qualified array can further
specify a "layout qualifier" that indicates
how the shared data is blocked and distributed.

There are two language pre-defined identifiers
that indicate the number of threads that
will be created when the program starts (THREADS)
and the current (zero-based) thread number
(MYTHREAD).  Typically, a UPC thread is implemented
as an operating system process.  Access to UPC
shared memory may be implemented locally via
OS provided facilities (for example, mmap),
or across nodes via a high speed network
inter-connect (for example, Infiniband).

GUPC provides a runtime (libupc) that targets
an SMP-based system and uses mmap() to implement
global shared memory.  

Optionally, GUPC can use the more general and
more capable Berkeley UPCR runtime:
  http://upc.lbl.gov/download/source.shtml#runtime
The UPCR runtime supports a number of network
topologies, and has been ported to most of the
current High Performance Computing (HPC) systems.

The following example illustrates
the use of the UPC "shared" qualifier
combined with a layout qualifier.

    #define BLKSIZE 5
    #define N_PER_THREAD (4 * BLKSIZE)
    shared [BLKSIZE] double A[N_PER_THREAD*THREADS];

Above the "[BLKSIZE]" construct is the UPC
layout factor; this specifies that the shared
array, A, distributes its elements across
each thread in blocks of 5 elements.  If the
program is run with two threads, then A is
distributed as shown below:

    Thread 0	Thread 1
    --------	---------
    A[ 0.. 4]	A[ 5.. 9]
    A[10..14]	A[15..19]
    A[20..24]	A[25..29]
    A[30..34]	A[35..39]

Above, the elements shown for thread 0
are defined as having "affinity" to thread 0.
Similarly, those elements shown for thread 1
have affinity to thread 1.  In UPC, a pointer
to a shared object can be cast to a thread
local pointer (a "C" pointer), when the
designated shared object has affinity
to the referencing thread.

A UPC "pointer-to-shared" (PTS) is a pointer
that references a UPC shared object.
A UPC pointer-to-shared is a "fat" pointer
with the following logical fields:
   (virt_addr, thread, offset)

The virtual address (virt_addr) field is combined with
the thread number (thread) and offset within the
block (offset), to derive the location of the
referenced object within the UPC shared address space.

GUPC implements pointer-to-shared objects using
either a "packed" representation or a "struct"
representation.  The user can select the
pointer-to-shared representation with a "configure"
parameter.  The packed representation is the default.

The "packed" pointer-to-shared representation
limits the range of the various fields within
the pointer-to-shared in order to gain efficiency.
Packed pointer-to-shared values encode the three
part shared address (described above) as a 64-bit
value (on both 64-bit and 32-bit platforms).

The "struct" representation provides a wider
addressing range at the expense of requiring
twice the number of bits (128) needed to encode
the pointer-to-shared value.

UPC-Related Front-End Changes
-----------------------------

GCC's internal tree representation is
extended to record the UPC "shared",
"strict", "relaxed" qualifiers,
and the layout qualifier.

   tree pointer_to;
   tree reference_to;
+  /* UPC: for block-distributed arrays */
+  tree block_factor;

UPC defines a few additional tree node types:

--- gcc/upc/upc-tree.def	(.../trunk)	(revision 0)
+++ gcc/upc/upc-tree.def	(.../branches/gupc)	(revision 175683)
+/* UPC statements */
+
+/* Used to represent a `upc_forall' statement. The operands are
+   UPC_FORALL_INIT_STMT, UPC_FORALL_COND, UPC_FORALL_EXPR,
+   UPC_FORALL_BODY, and UPC_FORALL_AFFINITY respectively. */
+
+DEFTREECODE (UPC_FORALL_STMT, "upc_forall_stmt", tcc_statement, 5)
+
+/* Used to represent a UPC synchronization statement. The first
+   operand is the synchronization operation, UPC_SYNC_OP:
+   UPC_SYNC_NOTIFY_OP	1	Notify operation
+   UPC_SYNC_WAIT_OP	2	Wait operation
+   UPC_SYNC_BARRIER_OP	3	Barrier operation
+
+   The second operand, UPC_SYNC_ID is the (optional) expression
+   whose value specifies the barrier identifier which is checked
+   by the various synchronization operations. */
+
+DEFTREECODE (UPC_SYNC_STMT, "upc_sync_stmt", tcc_statement, 2)

The "C" parser is extended to recognize UPC's syntactic
extensions.

--- gcc/c-family/c-common.c	(.../trunk)	(revision 175584)
+++ gcc/c-family/c-common.c	(.../branches/gupc)	(revision 175683)
+   UPC is like C except that D_UPC is not set
+   C++ --std=c98: D_CONLY | D_CXXOX | D_OBJC | D_UPC
+   C++ --std=c0x: D_CONLY | D_OBJC | D_UPC
+
[...]
+  /* UPC keywords */
+  { "shared",		RID_SHARED,		D_UPC },
+  { "relaxed",		RID_RELAXED,		D_UPC },
+  { "strict",		RID_STRICT,		D_UPC },
+  { "upc_barrier",	RID_UPC_BARRIER,	D_UPC },
+  { "upc_blocksizeof",	RID_UPC_BLOCKSIZEOF,	D_UPC },
+  { "upc_elemsizeof",	RID_UPC_ELEMSIZEOF,	D_UPC },
+  { "upc_forall",	RID_UPC_FORALL,		D_UPC },
+  { "upc_localsizeof",	RID_UPC_LOCALSIZEOF,	D_UPC },
+  { "upc_notify",	RID_UPC_NOTIFY,		D_UPC },
+  { "upc_wait",		RID_UPC_WAIT,		D_UPC },


-- gcc/c-parser.c	(.../trunk)	(revision 161517)
+++ gcc/c-parser.c	(.../branches/gupc)	(revision 161914)
[...]
+/* These UPC parser functions are only ever called when
+   compiling UPC.  */
+static void c_parser_upc_forall_statement (c_parser *);
+static void c_parser_upc_sync_statement (c_parser *, int);
+static void c_parser_upc_shared_qual (c_parser *, struct c_declspecs *);
[...]
+        /* UPC qualifiers */
+	case RID_SHARED:
+	  attrs_ok = true;
+          c_parser_upc_shared_qual (parser, specs);
+	  break;
+	case RID_STRICT:
+	case RID_RELAXED:
+	  attrs_ok = true;
+	  declspecs_add_qual (specs, c_parser_peek_token (parser)->value);
+	  c_parser_consume_token (parser);
+	  break;
[...]
+  /* Process all #pragma's just after the opening brace.  This
+     handles #pragma upc, which can only appear just after
+     the opening brace, when it appears within a function body.  */
+  push_upc_consistency_mode ();
+  permit_pragma_upc ();
+  while (c_parser_next_token_is (parser, CPP_PRAGMA))
+    {
+      location_t loc ATTRIBUTE_UNUSED = c_parser_peek_token (parser)->location;
+      if (c_parser_pragma (parser, pragma_compound))
+        last_label = false, last_stmt = true;
+      parser->error = false;
+    }
+  deny_pragma_upc ();
[...]
+	case RID_UPC_FORALL:
+          gcc_assert (c_dialect_upc ());
+	  c_parser_upc_forall_statement (parser);
+	  break;
+        case RID_UPC_NOTIFY:
+          gcc_assert (c_dialect_upc ());
+	  c_parser_upc_sync_statement (parser, UPC_SYNC_NOTIFY_OP);
+	  goto expect_semicolon;
+        case RID_UPC_WAIT:
+          gcc_assert (c_dialect_upc ());
+	  c_parser_upc_sync_statement (parser, UPC_SYNC_WAIT_OP);
+	  goto expect_semicolon;
+        case RID_UPC_BARRIER:
+          gcc_assert (c_dialect_upc ());
+	  c_parser_upc_sync_statement (parser, UPC_SYNC_BARRIER_OP);
+	  goto expect_semicolon;
[...]
+	case RID_UPC_BLOCKSIZEOF:
+	case RID_UPC_ELEMSIZEOF:
+	case RID_UPC_LOCALSIZEOF:
+          gcc_assert (c_dialect_upc ());
+	  return c_parser_sizeof_expression (parser);
[...]

--- gcc/c-family/c-pragma.c	(.../trunk)	(revision 175584)
+++ gcc/c-family/c-pragma.c	(.../branches/gupc)	(revision 175683)
[...]
+/*
+ *  #pragma upc strict
+ *  #pragma upc relaxed
+ *  #pragma upc upc_code
+ *  #pragma upc c_code
+ */
+static void
+handle_pragma_upc (cpp_reader * ARG_UNUSED (dummy))
[...]

c-decl.c handles the additional UPC qualifiers
and declspecs.  The layout qualifier is handled here:

--- gcc/c-decl.c	(.../trunk)	(revision 175584)
+++ gcc/c-decl.c	(.../branches/gupc)	(revision 175683)
[...]
+  /* A UPC layout qualifier is encoded as an ARRAY_REF,
+     further, it implies the presence of the 'shared' keyword. */
+  if (TREE_CODE (qual) == ARRAY_REF)
+    {
+      if (specs->upc_layout_qualifier)
+        {
+          error ("two or more layout qualifiers specified");
+	  return specs;
+        }
+      else
+        {
+          specs->upc_layout_qualifier = qual;
+          qual = ridpointers[RID_SHARED];
+        }
+    }

In UPC, a qualifier includes both the traditional
"C" qualifier flags and the UPC "layout qualifier".
Thus, the pointer_quals field of a declarator node
is defined as a struct including both qualifier
flags and the UPC type qualifier, as shown below.
 
 	    /* Process type qualifiers (such as const or volatile)
 	       that were given inside the `*'.  */
-	    type_quals = declarator->u.pointer_quals;
+	    type_quals = declarator->u.pointer.quals;
+	    layout_qualifier = declarator->u.pointer.upc_layout_qual;
+	    sharedp = ((type_quals & TYPE_QUAL_SHARED) != 0);

UPC shared variables are allocated at runtime in the global
memory that is allocated and managed by the UPC runtime.
A separate link section is used as a method of assigning
virtual addresses to UPC shared variables.  The UPC
shared variable section is designated as a "no load"
section on systems that support that facility; in that
case, the linkage section begins at virtual address zero.
The logic below assigns UPC shared variables to
their own linkage section.

+    /* Shared variables are given their own link section on
+       most target platforms, and if compiling in pthreads mode
+       regular local file scope variables are made thread local. */
+    if ((TREE_CODE(decl) == VAR_DECL)
+        && !threadp && (TREE_SHARED (decl) || flag_upc_pthreads))
+      upc_set_decl_section (decl);

Various UPC language related checks and operations
are called in the "C" front-end and middle-end.
To insure that these operations are defined,
when linked with the other language front-ends
and compilers, these functions are stub-ed,
in a fashion similar to Objective C:

--- gcc/c-family/c-upc.h	(.../trunk)	(revision 0)
+++ gcc/c-family/c-upc.h	(.../branches/gupc)	(revision 175683)
[...]
+extern int count_upc_threads_refs (tree);
+extern void deny_pragma_upc (void);
+extern int get_upc_consistency_mode (void);
+extern int get_upc_pupc_mode(void);
+extern int is_multiple_of_upc_threads (tree);
+extern void permit_pragma_upc (void);
+extern void pop_upc_consistency_mode (void);
+extern int pragma_upc_permitted_p (void);
+extern void push_upc_consistency_mode (void);
+extern void set_upc_consistency_mode (int);
+extern void set_upc_threads_refs_to_one (tree *);
+extern tree upc_affinity_test (location_t, tree);
+extern tree upc_blocksizeof (location_t, tree);
+extern tree upc_build_shared_var_addr (location_t, tree, tree);
+extern tree upc_build_sync_stmt (location_t, tree, tree);
+extern int upc_check_decl_init (tree, tree);
+extern void upc_check_decl (tree);
+extern void upc_cpp_builtins (cpp_reader *);
+extern void upc_decl_init (tree, tree);
+extern int upc_diagnose_deprecated_stmt (location_t, tree);
+extern tree upc_elemsizeof (location_t, tree);
+extern tree upc_get_block_factor (const tree);
+extern tree upc_instrument_forall (location_t, int);
+extern int upc_is_null_pts_p (tree);
+extern tree upc_localsizeof (location_t, tree);
+extern tree upc_num_threads (void);
+extern tree upc_pts_diff (tree, tree);
+extern tree upc_pts_increment (location_t, enum tree_code, tree);
+extern tree upc_pts_int_sum (location_t, enum tree_code, tree, tree);
+extern tree upc_rts_forall_depth_var (void);
+extern tree upc_set_block_factor (enum tree_code, tree, tree);
+extern void upc_set_decl_section (tree);
+extern void upc_write_global_declarations (void);

A few command line option flags must also be
stub'ed out in order to link the other
language front-ends.

+++ gcc/c-family/stub-upc.c	(.../branches/gupc)	(revision 175683)
+++ gcc/c-family/stub-upc.c	(.../branches/gupc)	(revision 161914)
[...]
+int compiling_upc;
+int flag_upc;
+int use_upc_dwarf2_extensions;
[...]

The UPC-related front-end "diff's" are attached
for review.  All feedback and suggestions
are appreciated.  The goal is to work
these changes (and the others that will
be posted to this list) into a form that
the GUPC branch can be merged into the GCC trunk.

                                  -- end --
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	(.../trunk)	(revision 175584)
+++ gcc/doc/tm.texi.in	(.../branches/gupc)	(revision 175735)
@@ -56,6 +56,7 @@ through the macros defined in the @file{
 * PCH Target::          Validity checking for precompiled headers.
 * C++ ABI::             Controlling C++ ABI changes.
 * Named Address Spaces:: Adding support for named address spaces
+* UPC Language::	Defining UPC-related configuration items
 * Misc::                Everything else.
 @end menu
 
@@ -10123,6 +10124,86 @@ guaranteed that one of the two address s
 as determined by the @code{TARGET_ADDR_SPACE_SUBSET_P} target hook.
 @end deftypefn
 
+@node UPC Language
+@section UPC Language Support
+@cindex UPC, pointer-to-shared, libupc
+
+@defmac HAVE_UPC_PTS_VADDR_FIRST
+If non-zero, the @var{vaddr} (virtual address) field of the UPC
+pointer-to-shared representation is first.  Typically, this macro
+is set by @command{configure} and is defined in @file{config.in},
+based on the setting of the @option{--with-upc-pts-vaddr-order} option.
+By default, the @var{vaddr} is first.
+@end defmac
+
+@defmac HAVE_UPC_PTS_PACKED_REP
+If defined, the UPC pointer-to-shared representation is a packed
+unsigned 64-bit integer.  This macro is determined by
+@command{configure} and is defined in @file{config.in},
+based on the setting of the @option{--with-upc-pts=packed} option.
+(The default representation is `packed'.)
+@end defmac
+
+@defmac HAVE_UPC_PTS_STRUCT_REP
+If defined, the UPC pointer-to-shared representation is a structure
+with three fields: @var{vaddr} (virtual address), @var{thread}
+(UPC thread number), and @var{phased} (UPC block offset).
+This macro is determined by @command{configure}
+and is defined in @file{config.in}, based on the setting of the
+@option{--with-upc-pts=struct} option.
+@end defmac
+
+@defmac UPC_SHARED_SECTION_NAME
+Name of section used to assign addresses to UPC shared data items.
+@end defmac
+
+@defmac UPC_SHARED_BEGIN_NAME
+Used by @code{upc-crtbegin} to define the beginning of the shared section.
+@end defmac
+
+@defmac UPC_SHARED_END_NAME
+Used by @code{upc-crtend} to define the end of the shared section.
+@end defmac
+
+@defmac UPC_PGM_INFO_SECTION_NAME
+Name of section used to hold info. describing how a UPC source file was compiled.
+@end defmac
+
+@defmac UPC_PGM_INFO_BEGIN_NAME
+Used by @code{upc-crtbegin} to define the beginning of the shared section.
+@end defmac
+
+@defmac UPC_PGM_INFO_END_NAME
+Used by @code{upc-crtend} to define the end of the shared section.
+@end defmac
+
+@defmac UPC_INIT_SECTION_NAME
+Name of section where UPC initialization routines are located.
+@end defmac
+
+@defmac UPC_INIT_BEGIN_NAME
+Used by @code{upc-crtbegin} to define the beginning of init. routines section.
+@end defmac
+
+@defmac UPC_INIT_END_NAME
+Used by @code{upc-crtend} to define the beginning of init. routines section.
+@end defmac
+
+@defmac UPC_INIT_ARRAY_SECTION_NAME
+Name of section that holds an array of addresses that points to 
+the UPC initialization routines.
+@end defmac
+
+@defmac UPC_INIT_ARRAY_BEGIN_NAME
+Used by @code{upc-crtbegin} to define the beginning of UPC initialization
+array section.
+@end defmac
+
+@defmac UPC_INIT_ARRAY_END_NAME
+Used by @code{upc-crtend} to define the beginning of UPC initialization
+array section.
+@end defmac
+
 @node Misc
 @section Miscellaneous Parameters
 @cindex parameters, miscellaneous
Index: gcc/tree-dump.c
===================================================================
--- gcc/tree-dump.c	(.../trunk)	(revision 175584)
+++ gcc/tree-dump.c	(.../branches/gupc)	(revision 175735)
@@ -381,10 +381,13 @@ dequeue_and_dump (dump_info_p di)
 
       if (quals != TYPE_UNQUALIFIED)
 	{
-	  fprintf (di->stream, "qual: %c%c%c     ",
+	  fprintf (di->stream, "qual: %c%c%c%c%c%c  ",
 		   (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
 		   (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
-		   (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
+		   (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ',
+		   (quals & TYPE_QUAL_SHARED) ? 's' : ' ',
+		   (quals & TYPE_QUAL_STRICT) ? 't' : ' ',
+		   (quals & TYPE_QUAL_RELAXED) ? 'x' : ' ');
 	  di->column += 14;
 	}
 
Index: gcc/flags.h
===================================================================
--- gcc/flags.h	(.../trunk)	(revision 175584)
+++ gcc/flags.h	(.../branches/gupc)	(revision 175735)
@@ -34,6 +34,10 @@ extern const char *const debug_type_name
 extern void strip_off_ending (char *, int);
 extern int base_of_path (const char *path, const char **base_out);
 
+/* Nonzero means use UPC extensions in the generated symbolic
+   debugging information (DWARF2 only).  */
+extern int use_upc_dwarf2_extensions;
+
 /* True if this is the LTO front end (lto1).  This is used to disable
    gimple generation and lowering passes that are normally run on the
    output of a front end.  These passes must be bypassed for lto since
Index: gcc/tree-pretty-print.c
===================================================================
--- gcc/tree-pretty-print.c	(.../trunk)	(revision 175584)
+++ gcc/tree-pretty-print.c	(.../branches/gupc)	(revision 175735)
@@ -673,6 +673,8 @@ dump_generic_node (pretty_printer *buffe
 	  pp_string (buffer, "volatile ");
 	else if (quals & TYPE_QUAL_RESTRICT)
 	  pp_string (buffer, "restrict ");
+	else if (upc_shared_type_p (node))
+	  pp_string (buffer, "shared ");
 
 	if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (node)))
 	  {
Index: gcc/c-family/c-pretty-print.c
===================================================================
--- gcc/c-family/c-pretty-print.c	(.../trunk)	(revision 175584)
+++ gcc/c-family/c-pretty-print.c	(.../branches/gupc)	(revision 175735)
@@ -206,7 +206,33 @@ pp_c_cv_qualifiers (c_pretty_printer *pp
       if (previous)
         pp_c_whitespace (pp);
       pp_c_ws_string (pp, flag_isoc99 ? "restrict" : "__restrict__");
+      previous = true;
     }
+
+  if (qualifiers & TYPE_QUAL_RELAXED)
+    {
+      if (previous)
+        pp_c_whitespace (pp);
+      pp_c_ws_string (pp, "relaxed");
+      previous = true;
+    }
+
+  if (qualifiers & TYPE_QUAL_STRICT)
+    {
+      if (previous)
+        pp_c_whitespace (pp);
+      pp_c_ws_string (pp, "strict");
+      previous = true;
+    }
+
+  if (qualifiers & TYPE_QUAL_SHARED)
+    {
+      if (previous)
+        pp_c_whitespace (pp);
+      pp_c_ws_string (pp, "shared");
+      previous = true;
+    }
+
 }
 
 /* Pretty-print T using the type-cast notation '( type-name )'.  */
Index: gcc/c-family/stub-upc.c
===================================================================
--- gcc/c-family/stub-upc.c	(.../trunk)	(revision 0)
+++ gcc/c-family/stub-upc.c	(.../branches/gupc)	(revision 175735)
@@ -0,0 +1,200 @@
+/* Stub functions for UPC routines
+   that are called from within the C front end.
+   respectively.
+   Copyright (C) 1991, 1995, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "c-common.h"
+#include "c-upc.h"
+
+int compiling_upc;
+int flag_upc;
+int use_upc_dwarf2_extensions;
+
+int
+count_upc_threads_refs (tree expr ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+int
+is_multiple_of_upc_threads (tree expr ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+void
+set_upc_threads_refs_to_one (tree *expr ATTRIBUTE_UNUSED)
+{
+  return;
+}
+
+tree
+upc_get_block_factor (tree type ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+tree
+upc_set_block_factor (
+    const enum tree_code decl_kind ATTRIBUTE_UNUSED,
+    tree type ATTRIBUTE_UNUSED,
+    tree layout_specifier ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+void
+upc_check_decl (tree ARG_UNUSED (decl))
+{
+}
+
+int
+upc_check_decl_init (tree ARG_UNUSED (decl),
+                     tree ARG_UNUSED (init))
+{
+  return 0;
+}
+
+void
+upc_decl_init (tree ARG_UNUSED (decl),
+               tree ARG_UNUSED (init))
+{
+}
+
+
+void
+upc_set_decl_section (tree decl ATTRIBUTE_UNUSED)
+{
+}
+
+int
+upc_is_null_pts_p (tree p ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+tree
+upc_build_shared_var_addr (
+    location_t location ATTRIBUTE_UNUSED,
+    tree type ATTRIBUTE_UNUSED,
+    tree var ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+tree
+upc_pts_increment (
+     location_t location ATTRIBUTE_UNUSED,
+     enum tree_code code ATTRIBUTE_UNUSED,
+     tree arg ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+tree
+upc_pts_int_sum (
+    location_t location ATTRIBUTE_UNUSED,
+    enum tree_code resultcode ATTRIBUTE_UNUSED,
+    tree ptrop ATTRIBUTE_UNUSED,
+    tree intop ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+tree
+upc_pts_diff (
+    tree op0 ATTRIBUTE_UNUSED,
+    tree op1 ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+
+tree
+upc_affinity_test (location_t ARG_UNUSED(start_locus),
+                   tree ARG_UNUSED(affinity))
+{
+  return 0;
+}
+
+tree
+upc_rts_forall_depth_var (void)
+{
+  return 0;
+}
+
+tree 
+upc_build_sync_stmt (location_t ARG_UNUSED(loc),
+                     tree ARG_UNUSED (op), tree ARG_UNUSED (exp))
+{
+  return NULL_TREE;
+}
+
+tree
+upc_blocksizeof (location_t ARG_UNUSED(loc), tree ARG_UNUSED (op))
+{
+  return NULL_TREE;
+}
+
+tree
+upc_elemsizeof (location_t ARG_UNUSED(loc), tree ARG_UNUSED (op))
+{
+  return NULL_TREE;
+}
+
+tree
+upc_localsizeof (location_t ARG_UNUSED(loc), tree ARG_UNUSED (op))
+{
+  return NULL_TREE;
+}
+
+tree
+upc_num_threads(void)
+{
+  return NULL_TREE;
+}
+
+int
+upc_diagnose_deprecated_stmt (location_t ARG_UNUSED (loc),
+                              tree ARG_UNUSED (id))
+{
+  return 0;
+}
+
+void
+upc_cpp_builtins (cpp_reader * ARG_UNUSED(pfile))
+{
+}
+
+tree
+upc_instrument_forall (location_t ARG_UNUSED(loc), int ARG_UNUSED(start))
+{
+  return 0;
+}
+
+void
+upc_write_global_declarations (void)
+{
+}
Index: gcc/c-family/c.opt
===================================================================
--- gcc/c-family/c.opt	(.../trunk)	(revision 175584)
+++ gcc/c-family/c.opt	(.../branches/gupc)	(revision 175735)
@@ -29,246 +29,249 @@ Language
 ObjC
 
 Language
+UPC
+
+Language
 C++
 
 Language
 ObjC++
 
 -all-warnings
-C ObjC C++ ObjC++ Warning Alias(Wall)
+C UPC ObjC C++ ObjC++ Warning Alias(Wall)
 
 -ansi
-C ObjC C++ ObjC++ Alias(ansi)
+C UPC ObjC C++ ObjC++ Alias(ansi)
 
 -assert
-C ObjC C++ ObjC++ Separate Alias(A) MissingArgError(assertion missing after %qs)
+C UPC ObjC C++ ObjC++ Separate Alias(A) MissingArgError(assertion missing after %qs)
 
 -assert=
-C ObjC C++ ObjC++ Joined Alias(A) MissingArgError(assertion missing after %qs)
+C UPC ObjC C++ ObjC++ Joined Alias(A) MissingArgError(assertion missing after %qs)
 
 -comments
-C ObjC C++ ObjC++ Alias(C)
+C UPC ObjC C++ ObjC++ Alias(C)
 
 -comments-in-macros
-C ObjC C++ ObjC++ Alias(CC)
+C UPC ObjC C++ ObjC++ Alias(CC)
 
 -define-macro
-C ObjC C++ ObjC++ Separate Alias(D) MissingArgError(macro name missing after %qs)
+C UPC ObjC C++ ObjC++ Separate Alias(D) MissingArgError(macro name missing after %qs)
 
 -define-macro=
-C ObjC C++ ObjC++ Joined Alias(D) MissingArgError(macro name missing after %qs)
+C UPC ObjC C++ ObjC++ Joined Alias(D) MissingArgError(macro name missing after %qs)
 
 -dependencies
-C ObjC C++ ObjC++ Alias(M)
+C UPC ObjC C++ ObjC++ Alias(M)
 
 -dump
-C ObjC C++ ObjC++ Separate Alias(d)
+C UPC ObjC C++ ObjC++ Separate Alias(d)
 
 -dump=
-C ObjC C++ ObjC++ Joined Alias(d)
+C UPC ObjC C++ ObjC++ Joined Alias(d)
 
 -imacros
-C ObjC C++ ObjC++ Separate Alias(imacros) MissingArgError(missing filename after %qs)
+C UPC ObjC C++ ObjC++ Separate Alias(imacros) MissingArgError(missing filename after %qs)
 
 -imacros=
-C ObjC C++ ObjC++ Joined Alias(imacros) MissingArgError(missing filename after %qs)
+C UPC ObjC C++ ObjC++ Joined Alias(imacros) MissingArgError(missing filename after %qs)
 
 -include
-C ObjC C++ ObjC++ Separate Alias(include) MissingArgError(missing filename after %qs)
+C UPC ObjC C++ ObjC++ Separate Alias(include) MissingArgError(missing filename after %qs)
 
 -include=
-C ObjC C++ ObjC++ Joined Alias(include) MissingArgError(missing filename after %qs)
+C UPC ObjC C++ ObjC++ Joined Alias(include) MissingArgError(missing filename after %qs)
 
 -include-barrier
-C ObjC C++ ObjC++ Alias(I, -)
+C UPC ObjC C++ ObjC++ Alias(I, -)
 
 -include-directory
-C ObjC C++ ObjC++ Separate Alias(I) MissingArgError(missing path after %qs)
+C UPC ObjC C++ ObjC++ Separate Alias(I) MissingArgError(missing path after %qs)
 
 -include-directory=
-C ObjC C++ ObjC++ Joined Alias(I) MissingArgError(missing path after %qs)
+C UPC ObjC C++ ObjC++ Joined Alias(I) MissingArgError(missing path after %qs)
 
 -include-directory-after
-C ObjC C++ ObjC++ Separate Alias(idirafter) MissingArgError(missing path after %qs)
+C UPC ObjC C++ ObjC++ Separate Alias(idirafter) MissingArgError(missing path after %qs)
 
 -include-directory-after=
-C ObjC C++ ObjC++ Joined Alias(idirafter) MissingArgError(missing path after %qs)
+C UPC ObjC C++ ObjC++ Joined Alias(idirafter) MissingArgError(missing path after %qs)
 
 -include-prefix
-C ObjC C++ ObjC++ Separate Alias(iprefix)
+C UPC ObjC C++ ObjC++ Separate Alias(iprefix)
 
 -include-prefix=
-C ObjC C++ ObjC++ JoinedOrMissing Alias(iprefix)
+C UPC ObjC C++ ObjC++ JoinedOrMissing Alias(iprefix)
 
 -include-with-prefix
-C ObjC C++ ObjC++ Separate Alias(iwithprefix)
+C UPC ObjC C++ ObjC++ Separate Alias(iwithprefix)
 
 -include-with-prefix=
-C ObjC C++ ObjC++ JoinedOrMissing Alias(iwithprefix)
+C UPC ObjC C++ ObjC++ JoinedOrMissing Alias(iwithprefix)
 
 -include-with-prefix-after
-C ObjC C++ ObjC++ Separate Alias(iwithprefix)
+C UPC ObjC C++ ObjC++ Separate Alias(iwithprefix)
 
 -include-with-prefix-after=
-C ObjC C++ ObjC++ JoinedOrMissing Alias(iwithprefix)
+C UPC ObjC C++ ObjC++ JoinedOrMissing Alias(iwithprefix)
 
 -include-with-prefix-before
-C ObjC C++ ObjC++ Separate Alias(iwithprefixbefore)
+C UPC ObjC C++ ObjC++ Separate Alias(iwithprefixbefore)
 
 -include-with-prefix-before=
-C ObjC C++ ObjC++ JoinedOrMissing Alias(iwithprefixbefore)
+C UPC ObjC C++ ObjC++ JoinedOrMissing Alias(iwithprefixbefore)
 
 -no-integrated-cpp
 Driver Alias(no-integrated-cpp)
 
 -no-line-commands
-C ObjC C++ ObjC++ Alias(P)
+C UPC ObjC C++ ObjC++ Alias(P)
 
 -no-standard-includes
-C ObjC C++ ObjC++ Alias(nostdinc)
+C UPC ObjC C++ ObjC++ Alias(nostdinc)
 
 -no-warnings
-C ObjC C++ ObjC++ Alias(w)
+C UPC ObjC C++ ObjC++ Alias(w)
 
 -output
-C ObjC C++ ObjC++ Separate Alias(o)
+C UPC ObjC C++ ObjC++ Separate Alias(o)
 
 -output=
-C ObjC C++ ObjC++ Joined Alias(o)
+C UPC ObjC C++ ObjC++ Joined Alias(o)
 
 -output-pch=
-C ObjC C++ ObjC++ Joined Separate
+C UPC ObjC C++ ObjC++ Joined Separate
 
 -pedantic
-C ObjC C++ ObjC++ Alias(pedantic)
+C UPC ObjC C++ ObjC++ Alias(pedantic)
 
 -pedantic-errors
-C ObjC C++ ObjC++ Alias(pedantic-errors)
+C UPC ObjC C++ ObjC++ Alias(pedantic-errors)
 
 -preprocess
-C ObjC C++ ObjC++ Undocumented Alias(E)
+C UPC ObjC C++ ObjC++ Undocumented Alias(E)
 
 -print-missing-file-dependencies
-C ObjC C++ ObjC++ Alias(MG)
+C UPC ObjC C++ ObjC++ Alias(MG)
 
 -trace-includes
-C ObjC C++ ObjC++ Alias(H)
+C UPC ObjC C++ ObjC++ Alias(H)
 
 -traditional
 Driver Alias(traditional)
 
 -traditional-cpp
-C ObjC C++ ObjC++ Alias(traditional-cpp)
+C UPC ObjC C++ ObjC++ Alias(traditional-cpp)
 
 -trigraphs
-C ObjC C++ ObjC++ Alias(trigraphs)
+C UPC ObjC C++ ObjC++ Alias(trigraphs)
 
 -undefine-macro
-C ObjC C++ ObjC++ Separate Alias(U) MissingArgError(macro name missing after %qs)
+C UPC ObjC C++ ObjC++ Separate Alias(U) MissingArgError(macro name missing after %qs)
 
 -undefine-macro=
-C ObjC C++ ObjC++ Joined Alias(U) MissingArgError(macro name missing after %qs)
+C UPC ObjC C++ ObjC++ Joined Alias(U) MissingArgError(macro name missing after %qs)
 
 -user-dependencies
-C ObjC C++ ObjC++ Alias(MM)
+C UPC ObjC C++ ObjC++ Alias(MM)
 
 -verbose
-Common C ObjC C++ ObjC++ Alias(v)
+Common C UPC ObjC C++ ObjC++ Alias(v)
 
 -write-dependencies
-C ObjC C++ ObjC++ NoDriverArg Separate Alias(MD) MissingArgError(missing filename after %qs)
+C UPC ObjC C++ ObjC++ NoDriverArg Separate Alias(MD) MissingArgError(missing filename after %qs)
 
 -write-user-dependencies
-C ObjC C++ ObjC++ NoDriverArg Separate Alias(MMD) MissingArgError(missing filename after %qs)
+C UPC ObjC C++ ObjC++ NoDriverArg Separate Alias(MMD) MissingArgError(missing filename after %qs)
 
 A
-C ObjC C++ ObjC++ Joined Separate MissingArgError(assertion missing after %qs)
+C UPC ObjC C++ ObjC++ Joined Separate MissingArgError(assertion missing after %qs)
 -A<question>=<answer>	Assert the <answer> to <question>.  Putting '-' before <question> disables the <answer> to <question>
 
 C
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Do not discard comments
 
 CC
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Do not discard comments in macro expansions
 
 D
-C ObjC C++ ObjC++ Joined Separate MissingArgError(macro name missing after %qs)
+C UPC ObjC C++ ObjC++ Joined Separate MissingArgError(macro name missing after %qs)
 -D<macro>[=<val>]	Define a <macro> with <val> as its value.  If just <macro> is given, <val> is taken to be 1
 
 E
-C ObjC C++ ObjC++ Undocumented Var(flag_preprocess_only)
+C UPC ObjC C++ ObjC++ Undocumented Var(flag_preprocess_only)
 
 F
-Driver C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
+Driver C UPC ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -F <dir>	Add <dir> to the end of the main framework include path
 
 H
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Print the name of header files as they are used
 
 I
-C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
+C UPC ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -I <dir>	Add <dir> to the end of the main include path
 
 M
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Generate make dependencies
 
 MD
-C ObjC C++ ObjC++ NoDriverArg Separate MissingArgError(missing filename after %qs)
+C UPC ObjC C++ ObjC++ NoDriverArg Separate MissingArgError(missing filename after %qs)
 Generate make dependencies and compile
 
 MF
-C ObjC C++ ObjC++ Joined Separate MissingArgError(missing filename after %qs)
+C UPC ObjC C++ ObjC++ Joined Separate MissingArgError(missing filename after %qs)
 -MF <file>	Write dependency output to the given file
 
 MG
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Treat missing header files as generated files
 
 MM
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Like -M but ignore system header files
 
 MMD
-C ObjC C++ ObjC++ NoDriverArg Separate MissingArgError(missing filename after %qs)
+C UPC ObjC C++ ObjC++ NoDriverArg Separate MissingArgError(missing filename after %qs)
 Like -MD but ignore system header files
 
 MP
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Generate phony targets for all headers
 
 MQ
-C ObjC C++ ObjC++ Joined Separate MissingArgError(missing makefile target after %qs)
+C UPC ObjC C++ ObjC++ Joined Separate MissingArgError(missing makefile target after %qs)
 -MQ <target>	Add a MAKE-quoted target
 
 MT
-C ObjC C++ ObjC++ Joined Separate MissingArgError(missing makefile target after %qs)
+C UPC ObjC C++ ObjC++ Joined Separate MissingArgError(missing makefile target after %qs)
 -MT <target>	Add an unquoted target
 
 P
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Do not generate #line directives
 
 U
-C ObjC C++ ObjC++ Joined Separate MissingArgError(macro name missing after %qs)
+C UPC ObjC C++ ObjC++ Joined Separate MissingArgError(macro name missing after %qs)
 -U<macro>	Undefine <macro>
 
 Wabi
-C ObjC C++ ObjC++ LTO Var(warn_abi) Warning
+C UPC ObjC C++ ObjC++ LTO Var(warn_abi) Warning
 Warn about things that will change when compiling with an ABI-compliant compiler
 
 Wpsabi
-C ObjC C++ ObjC++ LTO Var(warn_psabi) Init(1) Undocumented
+C UPC ObjC C++ ObjC++ LTO Var(warn_psabi) Init(1) Undocumented
 
 Waddress
-C ObjC C++ ObjC++ Var(warn_address) Warning
+C UPC ObjC C++ ObjC++ Var(warn_address) Warning
 Warn about suspicious uses of memory addresses
 
 Wall
-C ObjC C++ ObjC++ Warning
+C UPC ObjC C++ ObjC++ Warning
 Enable most warning messages
 
 Wassign-intercept
@@ -276,15 +279,15 @@ ObjC ObjC++ Var(warn_assign_intercept) W
 Warn whenever an Objective-C assignment is being intercepted by the garbage collector
 
 Wbad-function-cast
-C ObjC Var(warn_bad_function_cast) Warning
+C UPC ObjC Var(warn_bad_function_cast) Warning
 Warn about casting functions to incompatible types
 
 Wbuiltin-macro-redefined
-C ObjC C++ ObjC++ Warning
+C UPC ObjC C++ ObjC++ Warning
 Warn when a built-in preprocessor macro is undefined or redefined
 
 Wc++-compat
-C ObjC Var(warn_cxx_compat) Warning
+C UPC ObjC Var(warn_cxx_compat) Warning
 Warn about C constructs that are not in the common subset of C and C++
 
 Wc++0x-compat
@@ -292,27 +295,27 @@ C++ ObjC++ Var(warn_cxx0x_compat) Warnin
 Warn about C++ constructs whose meaning differs between ISO C++ 1998 and ISO C++ 200x
 
 Wcast-qual
-C ObjC C++ ObjC++ Var(warn_cast_qual) Warning
+C UPC ObjC C++ ObjC++ Var(warn_cast_qual) Warning
 Warn about casts which discard qualifiers
 
 Wchar-subscripts
-C ObjC C++ ObjC++ Var(warn_char_subscripts) Warning
+C UPC ObjC C++ ObjC++ Var(warn_char_subscripts) Warning
 Warn about subscripts whose type is \"char\"
 
 Wclobbered
-C ObjC C++ ObjC++ Var(warn_clobbered) Init(-1) Warning
+C UPC ObjC C++ ObjC++ Var(warn_clobbered) Init(-1) Warning
 Warn about variables that might be changed by \"longjmp\" or \"vfork\"
 
 Wcomment
-C ObjC C++ ObjC++ Warning
+C UPC ObjC C++ ObjC++ Warning
 Warn about possibly nested block comments, and C++ comments spanning more than one physical line
 
 Wcomments
-C ObjC C++ ObjC++ Warning Alias(Wcomment)
+C UPC ObjC C++ ObjC++ Warning Alias(Wcomment)
 Synonym for -Wcomment
 
 Wconversion
-C ObjC C++ ObjC++ Var(warn_conversion) Warning
+C UPC ObjC C++ ObjC++ Var(warn_conversion) Warning
 Warn for implicit type conversions that may change a value
 
 Wconversion-null
@@ -320,7 +323,7 @@ C++ ObjC++ Var(warn_conversion_null) Ini
 Warn for converting NULL from/to a non-pointer type
 
 Wsign-conversion
-C ObjC C++ ObjC++ Var(warn_sign_conversion) Init(-1)
+C UPC ObjC C++ ObjC++ Var(warn_sign_conversion) Init(-1)
 Warn for implicit type conversions between signed and unsigned integers
 
 Wctor-dtor-privacy
@@ -328,7 +331,7 @@ C++ ObjC++ Var(warn_ctor_dtor_privacy) W
 Warn when all constructors and destructors are private
 
 Wdeclaration-after-statement
-C ObjC Var(warn_declaration_after_statement) Warning
+C UPC ObjC Var(warn_declaration_after_statement) Warning
 Warn when a declaration is found after a statement
 
 Wdelete-non-virtual-dtor
@@ -336,11 +339,11 @@ C++ ObjC++ Var(warn_delnonvdtor) Warning
 Warn about deleting polymorphic objects with non-virtual destructors
 
 Wdeprecated
-C C++ ObjC ObjC++ Var(warn_deprecated) Init(1) Warning
+C UPC C++ ObjC ObjC++ Var(warn_deprecated) Init(1) Warning
 Warn if a deprecated compiler feature, class, method, or field is used
 
 Wdiv-by-zero
-C ObjC C++ ObjC++ Var(warn_div_by_zero) Init(1) Warning
+C UPC ObjC C++ ObjC++ Var(warn_div_by_zero) Init(1) Warning
 Warn about compile-time integer division by zero
 
 Weffc++
@@ -348,89 +351,89 @@ C++ ObjC++ Var(warn_ecpp) Warning
 Warn about violations of Effective C++ style rules
 
 Wempty-body
-C ObjC C++ ObjC++ Var(warn_empty_body) Init(-1) Warning
+C UPC ObjC C++ ObjC++ Var(warn_empty_body) Init(-1) Warning
 Warn about an empty body in an if or else statement
 
 Wendif-labels
-C ObjC C++ ObjC++ Warning
+C UPC ObjC C++ ObjC++ Warning
 Warn about stray tokens after #elif and #endif
 
 Wenum-compare
-C ObjC C++ ObjC++ Var(warn_enum_compare) Init(-1) Warning
+C UPC ObjC C++ ObjC++ Var(warn_enum_compare) Init(-1) Warning
 Warn about comparison of different enum types
 
 Werror
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 ; Documented in common.opt
 
 Werror-implicit-function-declaration
-C ObjC RejectNegative Warning Alias(Werror=, implicit-function-declaration)
+C UPC ObjC RejectNegative Warning Alias(Werror=, implicit-function-declaration)
 This switch is deprecated; use -Werror=implicit-function-declaration instead
 
 Wfloat-equal
-C ObjC C++ ObjC++ Var(warn_float_equal) Warning
+C UPC ObjC C++ ObjC++ Var(warn_float_equal) Warning
 Warn if testing floating point numbers for equality
 
 Wformat
-C ObjC C++ ObjC++ Warning
+C UPC ObjC C++ ObjC++ Warning
 Warn about printf/scanf/strftime/strfmon format string anomalies
 
 Wformat-extra-args
-C ObjC C++ ObjC++ Var(warn_format_extra_args) Warning
+C UPC ObjC C++ ObjC++ Var(warn_format_extra_args) Warning
 Warn if passing too many arguments to a function for its format string
 
 Wformat-nonliteral
-C ObjC C++ ObjC++ Var(warn_format_nonliteral) Warning
+C UPC ObjC C++ ObjC++ Var(warn_format_nonliteral) Warning
 Warn about format strings that are not literals
 
 Wformat-contains-nul
-C ObjC C++ ObjC++ Var(warn_format_contains_nul) Warning
+C UPC ObjC C++ ObjC++ Var(warn_format_contains_nul) Warning
 Warn about format strings that contain NUL bytes
 
 Wformat-security
-C ObjC C++ ObjC++ Var(warn_format_security) Warning
+C UPC ObjC C++ ObjC++ Var(warn_format_security) Warning
 Warn about possible security problems with format functions
 
 Wformat-y2k
-C ObjC C++ ObjC++ Var(warn_format_y2k) Warning
+C UPC ObjC C++ ObjC++ Var(warn_format_y2k) Warning
 Warn about strftime formats yielding 2-digit years
 
 Wformat-zero-length
-C ObjC Var(warn_format_zero_length) Warning
+C UPC ObjC Var(warn_format_zero_length) Warning
 Warn about zero-length formats
 
 Wformat=
-C ObjC C++ ObjC++ Joined Warning
+C UPC ObjC C++ ObjC++ Joined Warning
 
 Wignored-qualifiers
-C C++ Var(warn_ignored_qualifiers) Init(-1) Warning
+C UPC C++ Var(warn_ignored_qualifiers) Init(-1) Warning
 Warn whenever type qualifiers are ignored.
 
 Winit-self
-C ObjC C++ ObjC++ Var(warn_init_self) Warning
+C UPC ObjC C++ ObjC++ Var(warn_init_self) Warning
 Warn about variables which are initialized to themselves
 
 Wimplicit
-C ObjC Var(warn_implicit) Init(-1) Warning
+C UPC ObjC Var(warn_implicit) Init(-1) Warning
 Warn about implicit declarations
 
 Wdouble-promotion
-C ObjC C++ ObjC++ Var(warn_double_promotion) Warning
+C UPC ObjC C++ ObjC++ Var(warn_double_promotion) Warning
 Warn about implicit conversions from \"float\" to \"double\"
 
 Wimplicit-function-declaration
-C ObjC Var(warn_implicit_function_declaration) Init(-1) Warning
+C UPC ObjC Var(warn_implicit_function_declaration) Init(-1) Warning
 Warn about implicit function declarations
 
 Wimplicit-int
-C ObjC Var(warn_implicit_int) Init(-1) Warning
+C UPC ObjC Var(warn_implicit_int) Init(-1) Warning
 Warn when a declaration does not specify a type
 
 Wimport
-C ObjC C++ ObjC++ Undocumented Ignore
+C UPC ObjC C++ ObjC++ Undocumented Ignore
 
 Wint-to-pointer-cast
-C ObjC C++ ObjC++ Var(warn_int_to_pointer_cast) Init(1) Warning
+C UPC ObjC C++ ObjC++ Var(warn_int_to_pointer_cast) Init(1) Warning
 Warn when there is a cast to a pointer from an integer of a different size
 
 Winvalid-offsetof
@@ -438,59 +441,59 @@ C++ ObjC++ Var(warn_invalid_offsetof) In
 Warn about invalid uses of the \"offsetof\" macro
 
 Winvalid-pch
-C ObjC C++ ObjC++ Warning
+C UPC ObjC C++ ObjC++ Warning
 Warn about PCH files that are found but not used
 
 Wjump-misses-init
-C ObjC Var(warn_jump_misses_init) Init(-1) Warning
+C UPC ObjC Var(warn_jump_misses_init) Init(-1) Warning
 Warn when a jump misses a variable initialization
 
 Wlogical-op
-C ObjC C++ ObjC++ Var(warn_logical_op) Init(0) Warning 
+C UPC ObjC C++ ObjC++ Var(warn_logical_op) Init(0) Warning 
 Warn when a logical operator is suspiciously always evaluating to true or false
 
 Wlong-long
-C ObjC C++ ObjC++ Var(warn_long_long) Init(-1) Warning
+C UPC ObjC C++ ObjC++ Var(warn_long_long) Init(-1) Warning
 Do not warn about using \"long long\" when -pedantic
 
 Wmain
-C ObjC C++ ObjC++ Var(warn_main) Init(-1) Warning
+C UPC ObjC C++ ObjC++ Var(warn_main) Init(-1) Warning
 Warn about suspicious declarations of \"main\"
 
 Wmissing-braces
-C ObjC C++ ObjC++ Var(warn_missing_braces) Warning
+C UPC ObjC C++ ObjC++ Var(warn_missing_braces) Warning
 Warn about possibly missing braces around initializers
 
 Wmissing-declarations
-C ObjC C++ ObjC++ Var(warn_missing_declarations) Warning
+C UPC ObjC C++ ObjC++ Var(warn_missing_declarations) Warning
 Warn about global functions without previous declarations
 
 Wmissing-field-initializers
-C ObjC C++ ObjC++ Var(warn_missing_field_initializers) Init(-1) Warning
+C UPC ObjC C++ ObjC++ Var(warn_missing_field_initializers) Init(-1) Warning
 Warn about missing fields in struct initializers
 
 Wmissing-format-attribute
-C ObjC C++ ObjC++ Var(warn_missing_format_attribute) Warning
+C UPC ObjC C++ ObjC++ Var(warn_missing_format_attribute) Warning
 Warn about functions which might be candidates for format attributes
 
 Wmissing-include-dirs
-C ObjC C++ ObjC++ Warning
+C UPC ObjC C++ ObjC++ Warning
 Warn about user-specified include directories that do not exist
 
 Wmissing-parameter-type
-C ObjC Var(warn_missing_parameter_type) Init(-1) Warning
+C UPC ObjC Var(warn_missing_parameter_type) Init(-1) Warning
 Warn about function parameters declared without a type specifier in K&R-style functions
 
 Wmissing-prototypes
-C ObjC Var(warn_missing_prototypes) Warning
+C UPC ObjC Var(warn_missing_prototypes) Warning
 Warn about global functions without prototypes
 
 Wmultichar
-C ObjC C++ ObjC++ Warning
+C UPC ObjC C++ ObjC++ Warning
 Warn about use of multi-character character constants
 
 Wnested-externs
-C ObjC Var(warn_nested_externs) Warning
+C UPC ObjC Var(warn_nested_externs) Warning
 Warn about \"extern\" declarations not at file scope
 
 Wnoexcept
@@ -506,11 +509,11 @@ C++ ObjC++ Var(warn_nonvdtor) Warning
 Warn about non-virtual destructors
 
 Wnonnull
-C ObjC Var(warn_nonnull) Warning
+C UPC ObjC Var(warn_nonnull) Warning
 Warn about NULL being passed to argument slots marked as requiring non-NULL
 
 Wnormalized=
-C ObjC C++ ObjC++ Joined Warning
+C UPC ObjC C++ ObjC++ Joined Warning
 -Wnormalized=<id|nfc|nfkc>	Warn about non-normalised Unicode strings
 
 Wold-style-cast
@@ -518,15 +521,15 @@ C++ ObjC++ Var(warn_old_style_cast) Warn
 Warn if a C-style cast is used in a program
 
 Wold-style-declaration
-C ObjC Var(warn_old_style_declaration) Init(-1) Warning
+C UPC ObjC Var(warn_old_style_declaration) Init(-1) Warning
 Warn for obsolescent usage in a declaration
 
 Wold-style-definition
-C ObjC Var(warn_old_style_definition) Warning
+C UPC ObjC Var(warn_old_style_definition) Warning
 Warn if an old-style parameter definition is used
 
 Woverlength-strings
-C ObjC C++ ObjC++ Var(warn_overlength_strings) Init(-1) Warning
+C UPC ObjC C++ ObjC++ Var(warn_overlength_strings) Init(-1) Warning
 Warn if a string is longer than the maximum portable length specified by the standard
 
 Woverloaded-virtual
@@ -534,15 +537,15 @@ C++ ObjC++ Var(warn_overloaded_virtual) 
 Warn about overloaded virtual function names
 
 Woverride-init
-C ObjC Var(warn_override_init) Init(-1) Warning
+C UPC ObjC Var(warn_override_init) Init(-1) Warning
 Warn about overriding initializers without side effects
 
 Wpacked-bitfield-compat
-C ObjC C++ ObjC++ Var(warn_packed_bitfield_compat) Init(-1) Warning
+C UPC ObjC C++ ObjC++ Var(warn_packed_bitfield_compat) Init(-1) Warning
 Warn about packed bit-fields whose offset changed in GCC 4.4
 
 Wparentheses
-C ObjC C++ ObjC++ Var(warn_parentheses) Warning
+C UPC ObjC C++ ObjC++ Var(warn_parentheses) Warning
 Warn about possibly missing parentheses
 
 Wpmf-conversions
@@ -550,15 +553,15 @@ C++ ObjC++ Var(warn_pmf2ptr) Init(1) War
 Warn when converting the type of pointers to member functions
 
 Wpointer-arith
-C ObjC C++ ObjC++ Var(warn_pointer_arith) Warning
+C UPC ObjC C++ ObjC++ Var(warn_pointer_arith) Warning
 Warn about function pointer arithmetic
 
 Wpointer-to-int-cast
-C ObjC Var(warn_pointer_to_int_cast) Init(1) Warning
+C UPC ObjC Var(warn_pointer_to_int_cast) Init(1) Warning
 Warn when a pointer is cast to an integer of a different size
 
 Wpragmas
-C ObjC C++ ObjC++ Var(warn_pragmas) Init(1) Warning
+C UPC ObjC C++ ObjC++ Var(warn_pragmas) Init(1) Warning
 Warn about misuses of pragmas
 
 Wproperty-assign-default
@@ -570,7 +573,7 @@ ObjC ObjC++ Var(warn_protocol) Init(1) W
 Warn if inherited methods are unimplemented
 
 Wredundant-decls
-C ObjC C++ ObjC++ Var(warn_redundant_decls) Warning
+C UPC ObjC C++ ObjC++ Var(warn_redundant_decls) Warning
 Warn about multiple declarations of the same object
 
 Wreorder
@@ -578,7 +581,7 @@ C++ ObjC++ Var(warn_reorder) Warning
 Warn when the compiler reorders code
 
 Wreturn-type
-C ObjC C++ ObjC++ Var(warn_return_type) Warning
+C UPC ObjC C++ ObjC++ Var(warn_return_type) Warning
 Warn whenever a function's return type defaults to \"int\" (C), or about inconsistent return types (C++)
 
 Wselector
@@ -586,11 +589,11 @@ ObjC ObjC++ Var(warn_selector) Warning
 Warn if a selector has multiple methods
 
 Wsequence-point
-C ObjC C++ ObjC++ Var(warn_sequence_point) Warning
+C UPC ObjC C++ ObjC++ Var(warn_sequence_point) Warning
 Warn about possible violations of sequence point rules
 
 Wsign-compare
-C ObjC C++ ObjC++ Var(warn_sign_compare) Init(-1) Warning
+C UPC ObjC C++ ObjC++ Var(warn_sign_compare) Init(-1) Warning
 Warn about signed-unsigned comparisons
 
 Wsign-promo
@@ -602,7 +605,7 @@ C++ ObjC++ Warning Var(warn_strict_null_
 Warn about uncasted NULL used as sentinel
 
 Wstrict-prototypes
-C ObjC Var(warn_strict_prototypes) Warning
+C UPC ObjC Var(warn_strict_prototypes) Warning
 Warn about unprototyped function declarations
 
 Wstrict-selector-match
@@ -610,7 +613,7 @@ ObjC ObjC++ Var(warn_strict_selector_mat
 Warn if type signatures of candidate methods do not match exactly
 
 Wsync-nand
-C C++ Var(warn_sync_nand) Init(1) Warning
+C UPC C++ Var(warn_sync_nand) Init(1) Warning
 Warn when __sync_fetch_and_nand and __sync_nand_and_fetch built-in functions are used
 
 Wsynth
@@ -618,19 +621,19 @@ C++ ObjC++ Var(warn_synth) Warning
 Deprecated.  This switch has no effect
 
 Wsystem-headers
-C ObjC C++ ObjC++ Warning
+C UPC ObjC C++ ObjC++ Warning
 ; Documented in common.opt
 
 Wtraditional
-C ObjC Var(warn_traditional) Warning
+C UPC ObjC Var(warn_traditional) Warning
 Warn about features not present in traditional C
 
 Wtraditional-conversion
-C ObjC Var(warn_traditional_conversion) Warning
+C UPC ObjC Var(warn_traditional_conversion) Warning
 Warn of prototypes causing type conversions different from what would happen in the absence of prototype
 
 Wtrigraphs
-C ObjC C++ ObjC++ Warning
+C UPC ObjC C++ ObjC++ Warning
 Warn if trigraphs are encountered that might affect the meaning of the program
 
 Wundeclared-selector
@@ -638,53 +641,57 @@ ObjC ObjC++ Var(warn_undeclared_selector
 Warn about @selector()s without previously declared methods
 
 Wundef
-C ObjC C++ ObjC++ Warning
+C UPC ObjC C++ ObjC++ Warning
 Warn if an undefined macro is used in an #if directive
 
 Wunknown-pragmas
-C ObjC C++ ObjC++ Warning
+C UPC ObjC C++ ObjC++ Warning
 Warn about unrecognized pragmas
 
 Wunsuffixed-float-constants
-C ObjC Var(warn_unsuffixed_float_constants) Warning
+C UPC ObjC Var(warn_unsuffixed_float_constants) Warning
 Warn about unsuffixed float constants
 
 Wunused-macros
-C ObjC C++ ObjC++ Warning
+C UPC ObjC C++ ObjC++ Warning
 Warn about macros defined in the main file that are not used
 
 Wunused-result
-C ObjC C++ ObjC++ Var(warn_unused_result) Init(1) Warning
+C UPC ObjC C++ ObjC++ Var(warn_unused_result) Init(1) Warning
 Warn if a caller of a function, marked with attribute warn_unused_result, does not use its return value
 
 Wvariadic-macros
-C ObjC C++ ObjC++ Warning
+C UPC ObjC C++ ObjC++ Warning
 Do not warn about using variadic macros when -pedantic
 
 Wvla
-C ObjC C++ ObjC++ Var(warn_vla) Init(-1) Warning
+C UPC ObjC C++ ObjC++ Var(warn_vla) Init(-1) Warning
 Warn if a variable length array is used
 
 Wvolatile-register-var
-C ObjC C++ ObjC++ Var(warn_volatile_register_var) Warning
+C UPC ObjC C++ ObjC++ Var(warn_volatile_register_var) Warning
 Warn when a register variable is declared volatile
 
 Wwrite-strings
-C ObjC C++ ObjC++ Var(warn_write_strings) Warning
+C UPC ObjC C++ ObjC++ Var(warn_write_strings) Warning
 In C++, nonzero means warn about deprecated conversion from string literals to 'char *'.  In C, similar warning, except that the conversion is of course not deprecated by the ISO C standard.
 
 Wpointer-sign
-C ObjC Var(warn_pointer_sign) Init(-1) Warning
+C UPC ObjC Var(warn_pointer_sign) Init(-1) Warning
 Warn when a pointer differs in signedness in an assignment
 
 ansi
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 A synonym for -std=c89 (for C) or -std=c++98 (for C++)
 
 d
-C ObjC C++ ObjC++ Joined
+C UPC ObjC C++ ObjC++ Joined
 ; Documented in common.opt.  FIXME - what about -dI, -dD, -dN and -dD?
 
+dwarf-2-upc
+UPC
+Generate DWARF-2 debug info with UPC extensions
+
 faccess-control
 C++ ObjC++ Var(flag_access_control) Init(1)
 Enforce class member access control semantics
@@ -697,26 +704,26 @@ C++ ObjC++ Ignore Warn(switch %qs is no 
 No longer supported
 
 fasm
-C ObjC C++ ObjC++ Var(flag_no_asm, 0)
+C UPC ObjC C++ ObjC++ Var(flag_no_asm, 0)
 Recognize the \"asm\" keyword
 
 ; Define extra predefined macros for use in libgcc.
 fbuilding-libgcc
-C ObjC C++ ObjC++ Undocumented Var(flag_building_libgcc)
+C UPC ObjC C++ ObjC++ Undocumented Var(flag_building_libgcc)
 
 fbuiltin
-C ObjC C++ ObjC++ Var(flag_no_builtin, 0)
+C UPC ObjC C++ ObjC++ Var(flag_no_builtin, 0)
 Recognize built-in functions
 
 fbuiltin-
-C ObjC C++ ObjC++ Joined
+C UPC ObjC C++ ObjC++ Joined
 
 fcheck-new
 C++ ObjC++ Var(flag_check_new)
 Check the return value of new
 
 fcond-mismatch
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Allow the arguments of the '?' operator to have different types
 
 fconserve-space
@@ -740,11 +747,11 @@ C++ ObjC++ Ignore
 Does nothing.  Preserved for backward compatibility.
 
 fdirectives-only
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Preprocess directives only.
 
 fdollars-in-identifiers
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Permit '$' as an identifier character
 
 felide-constructors
@@ -758,15 +765,15 @@ fenum-int-equiv
 C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
 
 fexec-charset=
-C ObjC C++ ObjC++ Joined RejectNegative
+C UPC ObjC C++ ObjC++ Joined RejectNegative
 -fexec-charset=<cset>	Convert all strings and character constants to character set <cset>
 
 fextended-identifiers
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Permit universal character names (\\u and \\U) in identifiers
 
 finput-charset=
-C ObjC C++ ObjC++ Joined RejectNegative
+C UPC ObjC C++ ObjC++ Joined RejectNegative
 -finput-charset=<cset>	Specify the default character set for source files
 
 
@@ -778,7 +785,7 @@ C++ ObjC++ Var(flag_new_for_scope) Init(
 Scope of for-init-statement variables is local to the loop
 
 ffreestanding
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Do not assume that standard C libraries and \"main\" exist
 
 fgnu-keywords
@@ -790,7 +797,7 @@ ObjC ObjC++
 Generate code for GNU runtime environment
 
 fgnu89-inline
-C ObjC Var(flag_gnu89_inline) Init(-1)
+C UPC ObjC Var(flag_gnu89_inline) Init(-1)
 Use traditional GNU semantics for inline functions
 
 fguiding-decls
@@ -803,7 +810,7 @@ fhonor-std
 C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
 
 fhosted
-C ObjC
+C UPC ObjC
 Assume normal C execution environment
 
 fhuge-objects
@@ -827,18 +834,18 @@ C++ ObjC++ Var(flag_friend_injection)
 Inject friend functions into enclosing namespace
 
 fkeep-inline-dllexport
-C C++ ObjC ObjC++ Var(flag_keep_inline_dllexport) Init(1) Report Condition(TARGET_DLLIMPORT_DECL_ATTRIBUTES)
+C UPC C++ ObjC ObjC++ Var(flag_keep_inline_dllexport) Init(1) Report Condition(TARGET_DLLIMPORT_DECL_ATTRIBUTES)
 Don't emit dllexported inline functions unless needed
 
 flabels-ok
 C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
 
 flax-vector-conversions
-C ObjC C++ ObjC++ Var(flag_lax_vector_conversions)
+C UPC ObjC C++ ObjC++ Var(flag_lax_vector_conversions)
 Allow implicit conversions between vectors with differing numbers of subparts and/or differing element types.
 
 fms-extensions
-C ObjC C++ ObjC++ Var(flag_ms_extensions)
+C UPC ObjC C++ ObjC++ Var(flag_ms_extensions)
 Don't warn about uses of Microsoft extensions
 
 fname-mangling-version-
@@ -903,7 +910,7 @@ ObjC ObjC++ Var(flag_objc1_only)
 Conform to the Objective-C 1.0 language as implemented in GCC 4.0
 
 fopenmp
-C ObjC C++ ObjC++ Var(flag_openmp)
+C UPC ObjC C++ ObjC++ Var(flag_openmp)
 Enable OpenMP (implies -frecursive in Fortran)
 
 foperator-names
@@ -915,10 +922,10 @@ C++ ObjC++ Ignore
 Does nothing.  Preserved for backward compatibility.
 
 fpch-deps
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 
 fpch-preprocess
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Look for and use PCH files even when preprocessing
 
 fpermissive
@@ -926,11 +933,11 @@ C++ ObjC++
 Downgrade conformance errors to warnings
 
 fplan9-extensions
-C ObjC Var(flag_plan9_extensions)
+C UPC ObjC Var(flag_plan9_extensions)
 Enable Plan 9 language extensions
 
 fpreprocessed
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Treat the input file as already preprocessed
 
 fpretty-templates
@@ -950,23 +957,23 @@ C++ ObjC++ Optimization Var(flag_rtti) I
 Generate run time type descriptor information
 
 fshort-double
-C ObjC C++ ObjC++ Optimization Var(flag_short_double)
+C UPC ObjC C++ ObjC++ Optimization Var(flag_short_double)
 Use the same size for double as for float
 
 fshort-enums
-C ObjC C++ ObjC++ Optimization Var(flag_short_enums)
+C UPC ObjC C++ ObjC++ Optimization Var(flag_short_enums)
 Use the narrowest integer type possible for enumeration types
 
 fshort-wchar
-C ObjC C++ ObjC++ Optimization Var(flag_short_wchar)
+C UPC ObjC C++ ObjC++ Optimization Var(flag_short_wchar)
 Force the underlying type for \"wchar_t\" to be \"unsigned short\"
 
 fsigned-bitfields
-C ObjC C++ ObjC++ Var(flag_signed_bitfields) Init(1)
+C UPC ObjC C++ ObjC++ Var(flag_signed_bitfields) Init(1)
 When \"signed\" or \"unsigned\" is not given make the bitfield signed
 
 fsigned-char
-C ObjC C++ ObjC++ LTO Var(flag_signed_char)
+C UPC ObjC C++ ObjC++ LTO Var(flag_signed_char)
 Make \"char\" signed by default
 
 fsquangle
@@ -984,7 +991,7 @@ fstrict-prototype
 C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
 
 ftabstop=
-C ObjC C++ ObjC++ Joined RejectNegative UInteger
+C UPC ObjC C++ ObjC++ Joined RejectNegative UInteger
 -ftabstop=<number>	Distance between tab stops for column reporting
 
 ftemplate-depth-
@@ -1002,13 +1009,52 @@ C++ ObjC++ Optimization Var(flag_threads
 -fno-threadsafe-statics	Do not generate thread-safe code for initializing local statics
 
 funsigned-bitfields
-C ObjC C++ ObjC++ Var(flag_signed_bitfields, 0)
+C UPC ObjC C++ ObjC++ Var(flag_signed_bitfields, 0)
 When \"signed\" or \"unsigned\" is not given make the bitfield unsigned
 
 funsigned-char
-C ObjC C++ ObjC++ LTO Var(flag_signed_char, 0)
+C UPC ObjC C++ ObjC++ LTO Var(flag_signed_char, 0)
 Make \"char\" unsigned by default
 
+fupc-debug
+UPC Var(flag_upc_debug) VarExists
+Generate code that provides the UPC runtime with
+the file and line number where the runtime was called.
+
+fupc-inline-lib
+UPC Var(flag_upc_inline_lib) VarExists
+Generate code for inlined UPC runtime library routines.
+Default, at optimization levels greater than 0.
+
+fupc-link
+C UPC C++ 
+Enable UPC linker specs for upc-crtbegin/upc-crtend
+
+fupc-pre-include
+C UPC C++ Init(1)
+Pre-include UPC runtime header file
+
+fupc-pthreads-model-tls
+UPC
+Generate code for a POSIX threads based UPC runtime environment
+with TLS (Thread Local Storage) support
+
+fupc-pthreads-per-process-
+UPC Joined RejectNegative UInteger
+Specify the number of POSIX threads per process that are mapped to UPC threads
+
+fupc-threads-
+UPC Joined RejectNegative UInteger
+Specify the compile-time value of THREADS
+
+fupc-instrument
+C UPC Var(flag_upc_instrument) VarExists
+Instrument UPC shared accesses and library calls, using GASP tool support
+
+fupc-instrument-functions
+C UPC Var(flag_upc_instrument_functions) VarExists
+Instrument functions calls, using GASP tool support (implies -fupc-instrument)
+
 fuse-cxa-atexit
 C++ ObjC++ Var(flag_use_cxa_atexit) Init(DEFAULT_USE_CXA_ATEXIT)
 Use __cxa_atexit to register destructors
@@ -1038,11 +1084,11 @@ C++ ObjC++ Var(flag_weak) Init(1)
 Emit common-like symbols as weak symbols
 
 fwide-exec-charset=
-C ObjC C++ ObjC++ Joined RejectNegative
+C UPC ObjC C++ ObjC++ Joined RejectNegative
 -fwide-exec-charset=<cset>	Convert all wide strings and character constants to character set <cset>
 
 fworking-directory
-C ObjC C++ ObjC++ Var(flag_working_directory) Init(-1)
+C UPC ObjC C++ ObjC++ Var(flag_working_directory) Init(-1)
 Generate a #line directive pointing at the current working directory
 
 fxref
@@ -1058,65 +1104,68 @@ ObjC ObjC++ Var(flag_gen_declaration)
 Dump declarations to a .decl file
 
 femit-struct-debug-baseonly
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 -femit-struct-debug-baseonly	Aggressive reduced debug info for structs
 
 femit-struct-debug-reduced
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 -femit-struct-debug-reduced	Conservative reduced debug info for structs
 
 femit-struct-debug-detailed=
-C ObjC C++ ObjC++ Joined
+C UPC ObjC C++ ObjC++ Joined
 -femit-struct-debug-detailed=<spec-list>	Detailed reduced debug info for structs
 
 idirafter
-C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
+C UPC ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -idirafter <dir>	Add <dir> to the end of the system include path
 
 imacros
-C ObjC C++ ObjC++ Joined Separate MissingArgError(missing filename after %qs)
+C UPC ObjC C++ ObjC++ Joined Separate MissingArgError(missing filename after %qs)
 -imacros <file>	Accept definition of macros in <file>
 
 imultilib
-C ObjC C++ ObjC++ Joined Separate
+C UPC ObjC C++ ObjC++ Joined Separate
 -imultilib <dir>	Set <dir> to be the multilib include subdirectory
 
 include
-C ObjC C++ ObjC++ Joined Separate MissingArgError(missing filename after %qs)
+C UPC ObjC C++ ObjC++ Joined Separate MissingArgError(missing filename after %qs)
 -include <file>	Include the contents of <file> before other files
 
 iprefix
-C ObjC C++ ObjC++ Joined Separate
+C UPC ObjC C++ ObjC++ Joined Separate
 -iprefix <path>	Specify <path> as a prefix for next two options
 
 isysroot
-C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
+C UPC ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -isysroot <dir>	Set <dir> to be the system root directory
 
 isystem
-C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
+C UPC ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -isystem <dir>	Add <dir> to the start of the system include path
 
 iquote
-C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
+C UPC ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -iquote <dir>	Add <dir> to the end of the quote include path
 
 iwithprefix
-C ObjC C++ ObjC++ Joined Separate
+C UPC ObjC C++ ObjC++ Joined Separate
 -iwithprefix <dir>	Add <dir> to the end of the system include path
 
 iwithprefixbefore
-C ObjC C++ ObjC++ Joined Separate
+C UPC ObjC C++ ObjC++ Joined Separate
 -iwithprefixbefore <dir>	Add <dir> to the end of the main include path
 
 lang-asm
 C Undocumented RejectDriver
 
+lang-upc
+C UPC Undocumented
+
 no-integrated-cpp
 Driver
 
 nostdinc
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Do not search standard system include directories (those specified with -isystem will still be used)
 
 nostdinc++
@@ -1124,15 +1173,15 @@ C++ ObjC++
 Do not search standard system include directories for C++
 
 o
-C ObjC C++ ObjC++ Joined Separate
+C UPC ObjC C++ ObjC++ Joined Separate
 ; Documented in common.opt
 
 pedantic
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 ; Documented in common.opt
 
 pedantic-errors
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 ; Documented in common.opt
 
 print-objc-runtime-info
@@ -1140,7 +1189,7 @@ ObjC ObjC++
 Generate C header of platform-specific features
 
 remap
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Remap file names when including files
 
 std=c++98
@@ -1159,23 +1208,23 @@ extensions enabled by this mode are expe
 future releases of GCC.
 
 std=c1x
-C ObjC
+C UPC ObjC
 Conform to the ISO 201X C standard draft (experimental and incomplete support)
 
 std=c89
-C ObjC Alias(std=c90)
+C UPC ObjC Alias(std=c90)
 Conform to the ISO 1990 C standard
 
 std=c90
-C ObjC
+C UPC ObjC
 Conform to the ISO 1990 C standard
 
 std=c99
-C ObjC
+C UPC ObjC
 Conform to the ISO 1999 C standard
 
 std=c9x
-C ObjC Alias(std=c99)
+C UPC ObjC Alias(std=c99)
 Deprecated in favor of -std=c99
 
 std=gnu++98
@@ -1190,62 +1239,62 @@ standard, dubbed C++0x. Note that the ex
 are experimental and may be removed in future releases of GCC.
 
 std=gnu1x
-C ObjC
+C UPC ObjC
 Conform to the ISO 201X C standard draft with GNU extensions (experimental and incomplete support)
 
 std=gnu89
-C ObjC Alias(std=gnu90)
+C UPC ObjC Alias(std=gnu90)
 Conform to the ISO 1990 C standard with GNU extensions
 
 std=gnu90
-C ObjC
+C UPC ObjC
 Conform to the ISO 1990 C standard with GNU extensions
 
 std=gnu99
-C ObjC
+C UPC ObjC
 Conform to the ISO 1999 C standard with GNU extensions
 
 std=gnu9x
-C ObjC Alias(std=gnu99)
+C UPC ObjC Alias(std=gnu99)
 Deprecated in favor of -std=gnu99
 
 std=iso9899:1990
-C ObjC Alias(std=c90)
+C UPC ObjC Alias(std=c90)
 Conform to the ISO 1990 C standard
 
 std=iso9899:199409
-C ObjC
+C UPC ObjC
 Conform to the ISO 1990 C standard as amended in 1994
 
 std=iso9899:1999
-C ObjC Alias(std=c99)
+C UPC ObjC Alias(std=c99)
 Conform to the ISO 1999 C standard
 
 std=iso9899:199x
-C ObjC Alias(std=c99)
+C UPC ObjC Alias(std=c99)
 Deprecated in favor of -std=iso9899:1999
 
 traditional
 Driver
 
 traditional-cpp
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 Enable traditional preprocessing
 
 trigraphs
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 -trigraphs	Support ISO C trigraphs
 
 undef
-C ObjC C++ ObjC++ Var(flag_undef)
+C UPC ObjC C++ ObjC++ Var(flag_undef)
 Do not predefine system-specific and GCC-specific macros
 
 v
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 ; Documented in common.opt
 
 w
-C ObjC C++ ObjC++
+C UPC ObjC C++ ObjC++
 ; Documented in common.opt
 
 ; This comment is to ensure we retain the blank line above.
Index: gcc/c-family/c-opts.c
===================================================================
--- gcc/c-family/c-opts.c	(.../trunk)	(revision 175584)
+++ gcc/c-family/c-opts.c	(.../branches/gupc)	(revision 175735)
@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.  
 #include "tree.h"
 #include "c-common.h"
 #include "c-pragma.h"
+#include "c-upc.h"
 #include "flags.h"
 #include "toplev.h"
 #include "langhooks.h"
@@ -138,7 +139,7 @@ static struct deferred_opt
 
 
 extern const unsigned int 
-c_family_lang_mask = (CL_C | CL_CXX | CL_ObjC | CL_ObjCXX);
+c_family_lang_mask = (CL_C | CL_CXX | CL_UPC | CL_ObjC | CL_ObjCXX);
 
 /* Defer option CODE with argument ARG.  */
 static void
@@ -153,8 +154,8 @@ defer_opt (enum opt_code code, const cha
 unsigned int
 c_common_option_lang_mask (void)
 {
-  static const unsigned int lang_flags[] = {CL_C, CL_ObjC, CL_CXX, CL_ObjCXX};
-
+  static const unsigned int
+  lang_flags[] = {CL_C, CL_ObjC, CL_CXX, CL_ObjCXX, CL_UPC};
   return lang_flags[c_language];
 }
 
@@ -714,6 +715,18 @@ c_common_handle_option (size_t scode, co
       cpp_set_lang (parse_in, CLK_ASM);
       cpp_opts->dollars_in_ident = false;
       break;
+ 
+    case OPT_lang_upc:
+      cpp_set_lang (parse_in, CLK_UPC);
+      break;
+
+    case OPT_fupc_instrument:
+    case OPT_fupc_instrument_functions:
+    case OPT_fupc_pthreads_model_tls:
+    case OPT_fupc_pthreads_per_process_:
+    case OPT_fupc_threads_:
+      /* processed in language-specific routine */
+      break;
 
     case OPT_nostdinc:
       std_inc = false;
@@ -1092,6 +1105,9 @@ c_common_parse_file (void)
       pch_init ();
       push_file_scope ();
       c_parse_file ();
+      /* Generate UPC global initialization code, if required.  */
+      if (c_dialect_upc ())
+        upc_write_global_declarations ();
       pop_file_scope ();
       /* And end the main input file, if the debug writer wants it  */
       if (debug_hooks->start_end_main_source_file)
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(.../trunk)	(revision 175584)
+++ gcc/c-family/c-common.c	(.../branches/gupc)	(revision 175735)
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  
 #include "ggc.h"
 #include "c-common.h"
 #include "c-objc.h"
+#include "c-upc.h"
 #include "tm_p.h"
 #include "obstack.h"
 #include "cpplib.h"
@@ -195,6 +196,24 @@ const char *pch_file;
    user's namespace.  */
 int flag_iso;
 
+/* Nonzero whenever UPC -fupc-threads-N is asserted.
+   The value N gives the number of UPC threads to be
+   defined at compile-time. */
+int flag_upc_threads;
+
+/* Nonzero whenever UPC -fupc-pthreads-model-* is asserted. */
+int flag_upc_pthreads;
+
+/* The -fupc-pthreads-per-process-N switch tells the UPC compiler
+   and runtime to map N UPC threads per process onto
+   N POSIX threads running inside the process. */
+int flag_upc_pthreads_per_process;
+ 
+/* The implementation model for UPC threads that
+   are mapped to POSIX threads, specified at compilation
+   time by the -fupc-pthreads-model-* switch. */
+upc_pthreads_model_kind upc_pthreads_model;
+
 /* Warn about #pragma directives that are not recognized.  */
 
 int warn_unknown_pragmas; /* Tri state variable.  */
@@ -388,8 +407,9 @@ static int resort_field_decl_cmp (const 
    C --std=c89: D_C99 | D_CXXONLY | D_OBJC | D_CXX_OBJC
    C --std=c99: D_CXXONLY | D_OBJC
    ObjC is like C except that D_OBJC and D_CXX_OBJC are not set
-   C++ --std=c98: D_CONLY | D_CXXOX | D_OBJC
-   C++ --std=c0x: D_CONLY | D_OBJC
+   UPC is like C except that D_UPC is not set
+   C++ --std=c98: D_CONLY | D_CXXOX | D_OBJC | D_UPC
+   C++ --std=c0x: D_CONLY | D_OBJC | D_UPC
    ObjC++ is like C++ except that D_OBJC is not set
 
    If -fno-asm is used, D_ASM is added to the mask.  If
@@ -571,6 +591,19 @@ const struct c_common_resword c_common_r
   { "inout",		RID_INOUT,		D_OBJC },
   { "oneway",		RID_ONEWAY,		D_OBJC },
   { "out",		RID_OUT,		D_OBJC },
+
+  /* UPC keywords */
+  { "shared",		RID_SHARED,		D_UPC },
+  { "relaxed",		RID_RELAXED,		D_UPC },
+  { "strict",		RID_STRICT,		D_UPC },
+  { "upc_barrier",	RID_UPC_BARRIER,	D_UPC },
+  { "upc_blocksizeof",	RID_UPC_BLOCKSIZEOF,	D_UPC },
+  { "upc_elemsizeof",	RID_UPC_ELEMSIZEOF,	D_UPC },
+  { "upc_forall",	RID_UPC_FORALL,		D_UPC },
+  { "upc_localsizeof",	RID_UPC_LOCALSIZEOF,	D_UPC },
+  { "upc_notify",	RID_UPC_NOTIFY,		D_UPC },
+  { "upc_wait",		RID_UPC_WAIT,		D_UPC },
+
   /* These are recognized inside a property attribute list */
   { "assign",	        RID_ASSIGN,		D_OBJC }, 
   { "copy",	        RID_COPY,		D_OBJC }, 
@@ -3677,6 +3710,11 @@ pointer_int_sum (location_t loc, enum tr
   /* The result is a pointer of the same type that is being added.  */
   tree result_type = TREE_TYPE (ptrop);
 
+  /* If the pointer lives in UPC shared memory, then
+     drop the 'shared' qualifier.  */
+  if (upc_shared_type_p (result_type))
+    result_type = build_upc_unshared_type (result_type);
+
   if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
     {
       pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
@@ -4083,6 +4121,17 @@ c_apply_type_quals_to_decl (int type_qua
 	  || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))
 	error ("invalid use of %<restrict%>");
     }
+  if (type_quals & TYPE_QUAL_SHARED)
+    {
+      TREE_SHARED (decl) = 1;
+      if (type_quals & TYPE_QUAL_STRICT)
+	TREE_STRICT(decl) = 1;
+      else if (type_quals & TYPE_QUAL_RELAXED)
+	TREE_RELAXED(decl) = 1;
+      /* The declaration's type should have been previously defined
+	 as a UPC shared type.  */
+      gcc_assert (upc_shared_type_p (type));
+    }
 }
 
 /* Hash function for the problem of multiple type definitions in
@@ -4284,11 +4333,17 @@ c_sizeof_or_alignof_type (location_t loc
     }
   else if (type_code == VOID_TYPE || type_code == ERROR_MARK)
     {
-      if (type_code == VOID_TYPE
-	  && complain && (pedantic || warn_pointer_arith))
-	pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
-		 "invalid application of %qs to a void type", op_name);
-      else if (!complain)
+      if (complain)
+        {
+	  if (type_code == VOID_TYPE && upc_shared_type_p (type))
+	    error_at (loc, "invalid application of %qs"
+	                   " to %<shared void%> type", op_name);
+          else if (type_code == VOID_TYPE
+	           && (pedantic || warn_pointer_arith))
+	    pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+		     "invalid application of %qs to a void type", op_name);
+        }
+      else
         return error_mark_node;
       value = size_one_node;
     }
@@ -4310,6 +4365,14 @@ c_sizeof_or_alignof_type (location_t loc
 	value = size_int (TYPE_ALIGN_UNIT (type));
     }
 
+  if (is_sizeof && (TREE_CODE (type) == ARRAY_TYPE)
+      && upc_shared_type_p (type)
+      && UPC_TYPE_HAS_THREADS_FACTOR (type))
+    {
+      const tree n_threads = convert (sizetype, upc_num_threads ());
+      value = size_binop (MULT_EXPR, value, n_threads);
+    }
+
   /* VALUE will have an integer type with TYPE_IS_SIZETYPE set.
      TYPE_IS_SIZETYPE means that certain things (like overflow) will
      never happen.  However, this node should really have type
@@ -8841,6 +8904,13 @@ complete_array_type (tree *ptype, tree i
     }
 
   type = *ptype;
+  if (upc_shared_type_p (type))
+    {
+      /* Force a indefinte layout factor.  */ 
+      const tree layout_qualifier = build4 (ARRAY_REF, NULL_TREE, NULL_TREE,
+                                             size_zero_node, NULL_TREE, NULL_TREE);
+      type = upc_set_block_factor (ARRAY_TYPE, type, layout_qualifier);
+    }
   elt = TREE_TYPE (type);
   quals = TYPE_QUALS (strip_array_types (elt));
   if (quals == 0)
Index: gcc/c-family/c-lex.c
===================================================================
--- gcc/c-family/c-lex.c	(.../trunk)	(revision 175584)
+++ gcc/c-family/c-lex.c	(.../branches/gupc)	(revision 175735)
@@ -42,7 +42,7 @@ static int header_time, body_time;
 static splay_tree file_info_tree;
 
 int pending_lang_change; /* If we need to switch languages - C++ only */
-int c_header_level;	 /* depth in C headers - C++ only */
+int c_header_level;	 /* depth in C headers - C++ and UPC only */
 
 static tree interpret_integer (const cpp_token *, unsigned int);
 static tree interpret_float (const cpp_token *, unsigned int);
@@ -208,27 +208,27 @@ fe_file_change (const struct line_map *n
 
 	  input_location = new_map->start_location;
 	  (*debug_hooks->start_source_file) (line, new_map->to_file);
-#ifndef NO_IMPLICIT_EXTERN_C
 	  if (c_header_level)
 	    ++c_header_level;
 	  else if (new_map->sysp == 2)
 	    {
 	      c_header_level = 1;
+#ifndef NO_IMPLICIT_EXTERN_C
 	      ++pending_lang_change;
-	    }
 #endif
+	    }
 	}
     }
   else if (new_map->reason == LC_LEAVE)
     {
-#ifndef NO_IMPLICIT_EXTERN_C
       if (c_header_level && --c_header_level == 0)
 	{
 	  if (new_map->sysp == 2)
 	    warning (0, "badly nested C headers from preprocessor");
+#ifndef NO_IMPLICIT_EXTERN_C
 	  --pending_lang_change;
-	}
 #endif
+	}
       input_location = new_map->start_location;
 
       (*debug_hooks->end_source_file) (new_map->to_line);
Index: gcc/c-family/c-upc.h
===================================================================
--- gcc/c-family/c-upc.h	(.../trunk)	(revision 0)
+++ gcc/c-family/c-upc.h	(.../branches/gupc)	(revision 175735)
@@ -0,0 +1,70 @@
+/* Definitions of UPC front-end entry points used for C and C++.
+   that are called from within the C front end.
+   respectively.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2010, 2011
+   Free Software Foundation, Inc.
+   Contributed by Gary Funck <gary@intrepid.com>
+     and Nenad Vukicevic <nenad@intrepid.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+#ifndef GCC_C_COMMON_UPC_H
+#define GCC_C_COMMON_UPC_H
+
+
+/* UPC entry points.  */
+
+/* The following UPC functions are called by the C front-end;
+ * they all must have corresponding stubs in stub-upc.c.  */
+
+extern int count_upc_threads_refs (tree);
+extern void deny_pragma_upc (void);
+extern int get_upc_consistency_mode (void);
+extern int get_upc_pupc_mode(void);
+extern int is_multiple_of_upc_threads (tree);
+extern void permit_pragma_upc (void);
+extern void pop_upc_consistency_mode (void);
+extern int pragma_upc_permitted_p (void);
+extern void push_upc_consistency_mode (void);
+extern void set_upc_consistency_mode (int);
+extern void set_upc_threads_refs_to_one (tree *);
+extern tree upc_affinity_test (location_t, tree);
+extern tree upc_blocksizeof (location_t, tree);
+extern tree upc_build_shared_var_addr (location_t, tree, tree);
+extern tree upc_build_sync_stmt (location_t, tree, tree);
+extern int upc_check_decl_init (tree, tree);
+extern void upc_check_decl (tree);
+extern void upc_cpp_builtins (cpp_reader *);
+extern void upc_decl_init (tree, tree);
+extern int upc_diagnose_deprecated_stmt (location_t, tree);
+extern tree upc_elemsizeof (location_t, tree);
+extern tree upc_get_block_factor (const tree);
+extern tree upc_instrument_forall (location_t, int);
+extern int upc_is_null_pts_p (tree);
+extern tree upc_localsizeof (location_t, tree);
+extern tree upc_num_threads (void);
+extern tree upc_pts_diff (tree, tree);
+extern tree upc_pts_increment (location_t, enum tree_code, tree);
+extern tree upc_pts_int_sum (location_t, enum tree_code, tree, tree);
+extern tree upc_rts_forall_depth_var (void);
+extern tree upc_set_block_factor (enum tree_code, tree, tree);
+extern void upc_set_decl_section (tree);
+extern void upc_write_global_declarations (void);
+
+#endif /* ! GCC_C_COMMON_UPC_H */
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(.../trunk)	(revision 175584)
+++ gcc/c-family/c-common.h	(.../branches/gupc)	(revision 175735)
@@ -56,9 +56,9 @@ never after.
 */
 
 /* Reserved identifiers.  This is the union of all the keywords for C,
-   C++, and Objective-C.  All the type modifiers have to be in one
+   C++, Objective-C, and UPC.  All the type modifiers have to be in one
    block at the beginning, because they are used as mask bits.  There
-   are 27 type modifiers; if we add many more we will have to redesign
+   are 30 type modifiers; if we add many more we will have to redesign
    the mask mechanism.  */
 
 enum rid
@@ -70,6 +70,9 @@ enum rid
   RID_REGISTER, RID_TYPEDEF, RID_SHORT, RID_INLINE,
   RID_VOLATILE, RID_SIGNED,  RID_AUTO,  RID_RESTRICT,
 
+  /* UPC type qualifiers */
+  RID_SHARED, RID_RELAXED, RID_STRICT,
+
   /* C extensions */
   RID_COMPLEX, RID_THREAD, RID_SAT,
 
@@ -156,6 +159,11 @@ enum rid
   RID_AT_INTERFACE,
   RID_AT_IMPLEMENTATION,
 
+  /* UPC */
+  RID_UPC_BARRIER, RID_UPC_BLOCKSIZEOF, RID_UPC_ELEMSIZEOF,
+  RID_UPC_FORALL, RID_UPC_LOCALSIZEOF,
+  RID_UPC_NOTIFY, RID_UPC_WAIT,
+
   /* Named address support, mapping the keyword to a particular named address
      number.  Named address space 0 is reserved for the generic address.  If
      there are more than 254 named addresses, the addr_space_t type will need
@@ -334,6 +342,7 @@ struct c_common_resword
 #define D_OBJC		0x080	/* In Objective C and neither C nor C++.  */
 #define D_CXX_OBJC	0x100	/* In Objective C, and C++, but not C.  */
 #define D_CXXWARN	0x200	/* In C warn with -Wcxx-compat.  */
+#define D_UPC		0x400	/* In UPC, and neither C nor C++.  */
 
 /* The reserved keyword table.  */
 extern const struct c_common_resword c_common_reswords[];
@@ -424,7 +433,9 @@ typedef enum c_language_kind
   clk_c		= 0,		/* C90, C94 or C99 */
   clk_objc	= 1,		/* clk_c with ObjC features.  */
   clk_cxx	= 2,		/* ANSI/ISO C++ */
-  clk_objcxx	= 3		/* clk_cxx with ObjC features.  */
+  clk_objcxx	= 3,		/* clk_cxx with ObjC features.  */
+  clk_upc 	= 4,		/* clk_c with UPC features */
+  clk_upcxx 	= 6		/* clk_cxx with UPC features */
 }
 c_language_kind;
 
@@ -434,6 +445,7 @@ extern c_language_kind c_language;
 
 #define c_dialect_cxx()		((c_language & clk_cxx) != 0)
 #define c_dialect_objc()	((c_language & clk_objc) != 0)
+#define c_dialect_upc()		((c_language & clk_upc) != 0)
 
 /* The various name of operator that appears in error messages. */
 typedef enum ref_operator {
@@ -555,6 +567,43 @@ extern const char *pch_file;
 
 extern int flag_iso;
 
+/* Non-zero if the current compilation context is UPC */
+extern int compiling_upc;
+
+/* Non-zero if dwarf2 debugging info. should
+   encode UPC specific information. */
+extern int use_upc_dwarf2_extensions;
+
+/* Nonzero whenever UPC functionality is being used.  */
+extern int flag_upc;
+
+/* Nonzero whenever UPC -fupc-threads-N is asserted.
+   The value N gives the number of UPC threads to be
+   defined at compile-time. */
+extern int flag_upc_threads;
+
+/* Non-zero if the current compilation context is UPC */
+extern int compiling_upc;
+
+/* Nonzero whenever UPC -fupc-pthreads-model-* is asserted. */
+extern int flag_upc_pthreads;
+
+/* The -fupc-pthreads-per-process-N switch tells the UPC compiler
+   and runtime to map N UPC threads per process onto
+   N POSIX threads running inside the process. */
+extern int flag_upc_pthreads_per_process;
+
+typedef enum
+  {
+    upc_pthreads_no_model = 0,
+    upc_pthreads_tls_model = 1
+  } upc_pthreads_model_kind;
+
+/* The implementation model for UPC threads that
+   are mapped to POSIX threads, specified at compilation
+   time by the -fupc-pthreads-model-* switch. */
+extern upc_pthreads_model_kind upc_pthreads_model;
+
 /* Warn about #pragma directives that are not recognized.  */
 
 extern int warn_unknown_pragmas; /* Tri state variable.  */
@@ -969,7 +1018,8 @@ extern VEC(tree,gc) *make_tree_vector_co
 
 /* In c-gimplify.c  */
 extern void c_genericize (tree);
-extern int c_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
+extern int c_gimplify_expr (tree *, gimple_seq *, gimple_seq *,
+	                    bool (*) (tree), int);
 extern tree c_build_bind_expr (location_t, tree, tree);
 
 /* In c-pch.c  */
Index: gcc/c-family/c-pragma.c
===================================================================
--- gcc/c-family/c-pragma.c	(.../trunk)	(revision 175584)
+++ gcc/c-family/c-pragma.c	(.../branches/gupc)	(revision 175735)
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3.  
 #include "c-pragma.h"
 #include "flags.h"
 #include "c-common.h"
+#include "c-upc.h"
 #include "output.h"
 #include "tm_p.h"		/* For REGISTER_TARGET_PRAGMAS (why is
 				   this not a target hook?).  */
@@ -500,6 +501,225 @@ handle_pragma_extern_prefix (cpp_reader 
 	     "#pragma extern_prefix not supported on this target");
 }
 
+/* variables used to implement #pragma upc semantics */
+#ifndef UPC_CMODE_STACK_INCREMENT
+#define UPC_CMODE_STACK_INCREMENT 32
+#endif
+static int pragma_upc_permitted;
+static int upc_cmode;
+static int *upc_cmode_stack;
+static int upc_cmode_stack_in_use;
+static int upc_cmode_stack_allocated;
+
+static void init_pragma_upc (void);
+static void handle_pragma_upc (cpp_reader * ARG_UNUSED (dummy));
+
+/* Initialize the variables used to manage the current UPC consistency
+   mode (strict/relaxed) */
+
+static void
+init_pragma_upc (void)
+{
+  pragma_upc_permitted = 0;
+  upc_cmode = 0;
+  upc_cmode_stack = (int *) xcalloc (UPC_CMODE_STACK_INCREMENT,
+                                     sizeof (int));
+  upc_cmode_stack_allocated = UPC_CMODE_STACK_INCREMENT;
+  upc_cmode_stack_in_use = 0;
+}
+
+/*
+ *  #pragma upc strict
+ *  #pragma upc relaxed
+ *  #pragma upc upc_code
+ *  #pragma upc c_code
+ */
+static void
+handle_pragma_upc (cpp_reader * ARG_UNUSED (dummy))
+{
+  tree x;
+  enum cpp_ttype t;
+  enum upc_pragma_op {p_strict, p_relaxed, p_upc_code,
+        p_c_code, p_detect_upc, p_unknown};
+  enum upc_pragma_op upc_pragma = p_unknown;
+
+  if (!flag_upc)
+    {
+      warning (OPT_Wpragmas, "#pragma upc found in non-UPC source file");
+      return;
+    }
+
+  t = pragma_lex (&x);
+  if (t == CPP_NAME)
+    {
+      const char *op = IDENTIFIER_POINTER (x);
+      if (!strcmp (op, "strict"))
+        upc_pragma = p_strict;
+      else if (!strcmp (op, "relaxed"))
+        upc_pragma = p_relaxed;
+      else if (!strcmp (op, "upc_code"))
+        upc_pragma = p_upc_code;
+      else if (!strcmp (op, "c_code"))
+        upc_pragma = p_c_code;
+      else if (!strcmp (op, "detect_upc"))
+        {
+	  const char *detect_op;
+          upc_pragma = p_detect_upc;
+          t = pragma_lex (&x);
+          if (t != CPP_NAME)
+            GCC_BAD ("missing [suspend_insertion|resume_insertion]"
+	             " after %<#pragma UPC detect_upc%>");
+          detect_op = IDENTIFIER_POINTER (x);
+          if (strcmp (detect_op, "suspend_insertion") == 0)
+	    /* no action */;
+          else if (strcmp (detect_op, "resume_insertion") == 0)
+	    /* no action */;
+          else
+            GCC_BAD ("expected [suspend_insertion|resume_insertion]"
+	             " after %<#pragma UPC detect_upc%>");
+	}
+      else
+	GCC_BAD2 ("unknown action '%s' for '#pragma upc' - ignored", op);
+    }
+  else
+    warning (OPT_Wpragmas, "misssing parameter afer #pragma upc");
+
+  t = pragma_lex (&x);
+  if (t != CPP_EOF)
+    warning (OPT_Wpragmas, "junk at end of #pragma upc");
+
+  if ((upc_pragma == p_strict) || (upc_pragma == p_relaxed))
+    {
+      if (pragma_upc_permitted_p ())
+        {
+          int consistency_mode = (upc_pragma == p_strict);
+          set_upc_consistency_mode (consistency_mode);
+        }
+       else
+         warning (OPT_Wpragmas, "#pragma upc not allowed in this context");
+    }
+  else if ((upc_pragma == p_upc_code) || (upc_pragma == p_c_code))
+    {
+      compiling_upc = (upc_pragma == p_upc_code);
+    }
+  else if (upc_pragma == p_detect_upc)
+    {
+      /* Skip: this is a Berkeley-specific pragma that requires no action.  */
+    }
+}
+
+/* Set the current setting of the UPC consistency mode
+   that is in effect. */
+
+void
+set_upc_consistency_mode (int mode)
+{
+  upc_cmode = mode;
+}
+
+/* Return the current setting of the UPC consistency mode. */
+
+int
+get_upc_consistency_mode (void)
+{
+  return upc_cmode;
+}
+
+/* Called from the parser just after the bracket that opens a compound
+   statement has been parsed. Set the flag that allows the pragma
+   in this context. */
+
+void
+permit_pragma_upc (void)
+{
+  pragma_upc_permitted = 1;
+}
+
+/* Called just before the body of a compound statement is parsed.
+   Clear the flag that allows the pragma. */
+
+void
+deny_pragma_upc (void)
+{
+  pragma_upc_permitted = 0;
+}
+
+/* A #pragma upc is permitted either at the outermost scope,
+   or directly after the bracket that opens a compound statement. */
+
+int
+pragma_upc_permitted_p (void)
+{
+   return !current_function_decl || pragma_upc_permitted;
+}
+
+/* Called at the beginning of every compound statement.
+   Pushes the old value of the current UPC consistency mode
+   onto the stack. */
+
+void
+push_upc_consistency_mode (void)
+{
+  if (upc_cmode_stack_in_use == upc_cmode_stack_allocated)
+    {
+      upc_cmode_stack_allocated += UPC_CMODE_STACK_INCREMENT;
+      upc_cmode_stack = (int *) xrealloc (upc_cmode_stack,
+			 upc_cmode_stack_allocated * sizeof (int));
+    }
+  upc_cmode_stack[upc_cmode_stack_in_use++] = upc_cmode;
+}
+
+/* Called at the end of every compound statement.
+   Sets the current consistenty mode to the previously saved value. */
+
+void
+pop_upc_consistency_mode (void)
+{
+  if (upc_cmode_stack_in_use <= 0)
+    abort ();
+  upc_cmode = upc_cmode_stack[--upc_cmode_stack_in_use];
+}
+
+static int pragma_pupc_on;
+static void init_pragma_pupc (void);
+static void handle_pragma_pupc (cpp_reader *);
+
+/* Pragma pupc defaults to being on */
+static void init_pragma_pupc(void)
+{
+  pragma_pupc_on = 1;
+}
+
+int get_upc_pupc_mode(void)
+{
+  return pragma_pupc_on;
+}
+
+/*
+ *  #pragma pupc on
+ *  #pragma pupc off
+ */
+static void handle_pragma_pupc (cpp_reader *dummy ATTRIBUTE_UNUSED)
+{
+  tree x;
+  enum cpp_ttype t;
+
+  t = pragma_lex(&x);
+  if (t == CPP_NAME) {
+    const char *op = IDENTIFIER_POINTER (x);
+    if (!strcmp (op, "on"))
+      pragma_pupc_on = 1;
+    else if (!strcmp (op, "off"))
+      pragma_pupc_on = 0;
+    else
+	    GCC_BAD2 ("unknown action '%s' for '#pragma pupc' - ignored", op);
+  }
+  
+  t = pragma_lex (&x);
+  if (t != CPP_EOF)
+    warning (OPT_Wpragmas, "junk at end of #pragma pupc");
+}
+
 /* Hook from the front ends to apply the results of one of the preceding
    pragmas that rename variables.  */
 
@@ -1381,6 +1601,14 @@ init_pragma (void)
 
   c_register_pragma_with_expansion (0, "message", handle_pragma_message);
 
+  if (compiling_upc)
+    {
+      c_register_pragma (0, "upc", handle_pragma_upc);
+      init_pragma_upc ();
+      c_register_pragma (0, "pupc", handle_pragma_pupc);
+      init_pragma_pupc ();
+    }
+
 #ifdef REGISTER_TARGET_PRAGMAS
   REGISTER_TARGET_PRAGMAS ();
 #endif
Index: gcc/c-family/c-cppbuiltin.c
===================================================================
--- gcc/c-family/c-cppbuiltin.c	(.../trunk)	(revision 175584)
+++ gcc/c-family/c-cppbuiltin.c	(.../branches/gupc)	(revision 175735)
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  
 #include "flags.h"
 #include "c-common.h"
 #include "c-pragma.h"
+#include "c-upc.h"
 #include "output.h"
 #include "debug.h"		/* For dwarf2out_do_cfi_asm.  */
 #include "tm_p.h"		/* For TARGET_CPU_CPP_BUILTINS & friends.  */
@@ -809,6 +810,10 @@ c_cpp_builtins (cpp_reader *pfile)
   if (flag_openmp)
     cpp_define (pfile, "_OPENMP=200805");
 
+  /* Add UPC defines */
+  if (c_dialect_upc ())
+    upc_cpp_builtins (pfile);
+
   if (int128_integer_type_node != NULL_TREE)
     builtin_define_type_sizeof ("__SIZEOF_INT128__",
 			        int128_integer_type_node);
Index: gcc/libfuncs.h
===================================================================
--- gcc/libfuncs.h	(.../trunk)	(revision 175584)
+++ gcc/libfuncs.h	(.../branches/gupc)	(revision 175735)
@@ -44,6 +44,12 @@ enum libfunc_index
 
   LTI_gcov_flush,
 
+  /* UPC support functions */
+  LTI_upc_barrier,
+  LTI_upc_notify,
+  LTI_upc_wait,
+  LTI_upc_getaddr,
+
   LTI_MAX
 };
 
@@ -93,6 +99,11 @@ extern struct target_libfuncs *this_targ
 
 #define profile_function_entry_libfunc	(libfunc_table[LTI_profile_function_entry])
 #define profile_function_exit_libfunc	(libfunc_table[LTI_profile_function_exit])
+/* UPC support functions */
+#define upc_barrier_libfunc	(libfunc_table[LTI_upc_barrier])
+#define upc_notify_libfunc	(libfunc_table[LTI_upc_notify])
+#define upc_wait_libfunc	(libfunc_table[LTI_upc_wait])
+#define upc_getaddr_libfunc	(libfunc_table[LTI_upc_getaddr])
 
 #define synchronize_libfunc	(libfunc_table[LTI_synchronize])
 
Index: gcc/upc/upc-tree.def
===================================================================
--- gcc/upc/upc-tree.def	(.../trunk)	(revision 0)
+++ gcc/upc/upc-tree.def	(.../branches/gupc)	(revision 175735)
@@ -0,0 +1,44 @@
+/* upc-tree.def: UPC language-specific tree node definitions
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2010, 2011
+   Free Software Foundation, Inc.
+   Contributed by Gary Funck <gary@intrepid.com>
+     and Nenad Vukicevic <nenad@intrepid.com>.
+   Based on original implementation
+     by Jesse M. Draper <jdraper@super.org>
+     and William W. Carlson <wwc@super.org>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+/* UPC statements */
+
+/* Used to represent a `upc_forall' statement. The operands are
+   UPC_FORALL_INIT_STMT, UPC_FORALL_COND, UPC_FORALL_EXPR,
+   UPC_FORALL_BODY, and UPC_FORALL_AFFINITY respectively. */
+
+DEFTREECODE (UPC_FORALL_STMT, "upc_forall_stmt", tcc_statement, 5)
+
+/* Used to represent a UPC synchronization statement. The first
+   operand is the synchonization operation, UPC_SYNC_OP:
+   UPC_SYNC_NOTIFY_OP	1	Notify operation
+   UPC_SYNC_WAIT_OP	2	Wait operation
+   UPC_SYNC_BARRIER_OP	3	Barrier operation
+
+   The second operand, UPC_SYNC_ID is the (optional) expression
+   whose value specifies the barrier identifier which is checked
+   by the various synchronization operations. */
+
+DEFTREECODE (UPC_SYNC_STMT, "upc_sync_stmt", tcc_statement, 2)
Index: gcc/upc/lang-specs.h
===================================================================
--- gcc/upc/lang-specs.h	(.../trunk)	(revision 0)
+++ gcc/upc/lang-specs.h	(.../branches/gupc)	(revision 175735)
@@ -0,0 +1,51 @@
+/* upc/lang-specs.h: UPC-specific specs.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2010, 2011
+   Free Software Foundation, Inc.
+   Contributed by Gary Funck <gary@intrepid.com>
+     and Nenad Vukicevic <nenad@intrepid.com>.
+   Based on original implementation
+     by Jesse M. Draper <jdraper@super.org>
+     and William W. Carlson <wwc@super.org>.
+   Derived from objc/lang-specs.h.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+/* This is the contribution to the `default_compilers' array in gcc.c for
+   upc.  */
+
+  {".upc", "@upc", 0, 0, 0},
+  {"@upc",
+   /* cc1upc has an integrated ISO C preprocessor.  We should invoke the
+      external preprocessor if -save-temps or -traditional is given.  */
+     "%{E|M|MM:cc1upc -E %(upc_options) %(cpp_options) %(cpp_debug_options)}\
+      %{!E:%{!M:%{!MM:\
+	%{traditional|ftraditional|traditional-cpp:\
+              %e UPC does not support traditional compilation}\
+	%{save-temps|no-integrated-cpp:\
+	      cc1upc -E %(upc_options) %(cpp_options)\
+	  %{save-temps:%b.mi} %{!save-temps:%g.mi} \n\
+	      cc1upc -fpreprocessed %{save-temps:%b.mi} %{!save-temps:%g.mi}\
+	             %(upc_options) %(cc1_options)}\
+	%{!save-temps:%{!no-integrated-cpp:\
+	    cc1upc %(cpp_unique_options) %(upc_options) %(cc1_options)}}\
+        %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
+  {".upci", "@upc-cpp-output", 0, 0, 0},
+  {"@upc-cpp-output",
+     "%{!M:%{!MM:%{!E:cc1upc -fpreprocessed %i %(cc1_options)\
+     -lang-upc\
+     %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
Index: gcc/upc/upc-act.h
===================================================================
--- gcc/upc/upc-act.h	(.../trunk)	(revision 0)
+++ gcc/upc/upc-act.h	(.../branches/gupc)	(revision 175735)
@@ -0,0 +1,39 @@
+/* upc-act.h: define interfaces to UPC-related actions
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2010, 2011
+   Free Software Foundation, Inc.
+   Contributed by Gary Funck <gary@intrepid.com>
+     and Nenad Vukicevic <nenad@intrepid.com>.
+   Based on original implementation
+     by Jesse M. Draper <jdraper@super.org>
+     and William W. Carlson <wwc@super.org>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef _UPC_ACT_H_
+#define _UPC_ACT_H_
+
+
+extern bool upc_handle_option (size_t, const char *, int, int, location_t,
+                              const struct cl_option_handlers *);
+extern bool upc_lang_init (void);
+extern void upc_finish (void);
+extern int upc_types_compatible_p (tree, tree);
+extern int upc_inner_shared_ref_p (tree);
+extern int upc_pts_is_valid_p (tree);
+
+#endif /* !_UPC_ACT_H_ */
Index: gcc/upc/upc-lang.c
===================================================================
--- gcc/upc/upc-lang.c	(.../trunk)	(revision 0)
+++ gcc/upc/upc-lang.c	(.../branches/gupc)	(revision 175735)
@@ -0,0 +1,216 @@
+/* upc-lang.c: UPC language-specific hooks
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
+   Contributed by Gary Funck <gary@intrepid.com>
+     and Nenad Vukicevic <nenad@intrepid.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "c-tree.h"
+#include "c-family/c-common.h"
+#include "ggc.h"
+#include "upc-act.h"
+#include "upc-pts.h"
+#include "upc-gimplify.h"
+#include "upc-gasp.h"
+#include "upc-pts.h"
+#include "langhooks.h"
+#include "langhooks-def.h"
+#include "c-objc-common.h"
+#include "toplev.h"
+#include "diagnostic.h"
+#include "c-family/c-pretty-print.h"
+#include "c-family/c-pragma.h"
+#include "c-family/c-upc.h"
+#include "flags.h"
+#include "opts.h"
+#include "options.h"
+
+/* Non-zero if the current compilation context is UPC */
+int compiling_upc;
+
+/* Non-zero if dwarf2 debugging information should
+   encode UPC specific information. */
+int use_upc_dwarf2_extensions;
+
+/* Nonzero whenever UPC functionality is being used.  */
+int flag_upc;
+
+enum c_language_kind c_language = clk_upc;
+
+static void upc_initialize_diagnostics (diagnostic_context *);
+static void upc_init_options (unsigned int, struct cl_decoded_option *);
+static bool upc_post_options (const char **);
+static alias_set_type upc_get_alias_set (tree);
+static void upc_init_ts (void);
+
+/* UPC inherits hook definitions from "c-objc-common.h"
+   and adds to them.  */
+
+#undef LANG_HOOKS_NAME
+#define LANG_HOOKS_NAME "GCC UPC"
+#undef LANG_HOOKS_EXPAND_CONSTANT
+#define LANG_HOOKS_EXPAND_CONSTANT upc_pts_build_constant
+#undef LANG_HOOKS_GET_ALIAS_SET
+#define LANG_HOOKS_GET_ALIAS_SET upc_get_alias_set
+#undef LANG_HOOKS_GENERICIZE
+#define LANG_HOOKS_GENERICIZE upc_genericize
+#undef LANG_HOOKS_GIMPLIFY_EXPR
+#define LANG_HOOKS_GIMPLIFY_EXPR upc_gimplify_expr
+#undef LANG_HOOKS_INSTRUMENT_FUNC
+#define LANG_HOOKS_INSTRUMENT_FUNC upc_instrument_func
+#undef LANG_HOOKS_HANDLE_OPTION
+#define LANG_HOOKS_HANDLE_OPTION upc_handle_option
+#undef LANG_HOOKS_INIT
+#define LANG_HOOKS_INIT upc_lang_init
+#undef LANG_HOOKS_FINISH
+#define LANG_HOOKS_FINISH upc_finish
+#undef LANG_HOOKS_INITIALIZE_DIAGNOSTICS
+#define LANG_HOOKS_INITIALIZE_DIAGNOSTICS upc_initialize_diagnostics
+#undef LANG_HOOKS_INIT_OPTIONS
+#define LANG_HOOKS_INIT_OPTIONS upc_init_options
+#undef LANG_HOOKS_POST_OPTIONS
+#define LANG_HOOKS_POST_OPTIONS upc_post_options
+#undef LANG_HOOKS_TYPES_COMPATIBLE_P
+#define LANG_HOOKS_TYPES_COMPATIBLE_P upc_types_compatible_p
+#undef LANG_HOOKS_INIT_TS
+#define LANG_HOOKS_INIT_TS upc_init_ts
+
+/* Each front end provides its own hooks, for toplev.c.  */
+struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+
+static void
+upc_initialize_diagnostics (diagnostic_context *context)
+{
+  pretty_printer *base = context->printer;
+  c_pretty_printer *pp = (c_pretty_printer *)
+                         xmalloc (sizeof (c_pretty_printer));
+  memcpy (pp_base (pp), base, sizeof (pretty_printer));
+  pp_c_pretty_printer_init (pp);
+  context->printer = (pretty_printer *) pp;
+  /* It is safe to free this object because it was previously malloc()'d.  */
+  free (base);
+}
+
+/* Set the C 99 standard (without GNU extensions if ISO).
+   (borrowed from c-opts.c) */
+
+static void
+set_std_c99 (int iso)
+{
+  cpp_set_lang (parse_in, iso ? CLK_STDC99: CLK_GNUC99);
+  flag_no_asm = iso;
+  flag_no_nonansi_builtin = iso;
+  flag_iso = iso;
+  flag_isoc99 = 1;
+  flag_isoc94 = 1;
+}
+
+static void
+upc_init_options (unsigned int decoded_options_count,
+		  struct cl_decoded_option *decoded_options)
+{
+  struct cl_option_handlers handlers;
+
+  c_common_init_options (decoded_options_count, decoded_options);
+
+  /* UPC is based upon the C99 dialect. Assert it here.
+   * We'll let the user override these options as he/she
+   * sees fit. For example, -traditional will deisable
+   * prototype checking */
+  set_std_c99 ( 0 /* iso=0 */ );
+
+  /* The consensus of the UPC community seems to be that
+     arithmetic on (void *) pointers and sizeof (void)
+     are compilation errors.  Enable this warning-as-error
+     mode by default.  */
+  warn_pointer_arith = 1;
+  set_default_handlers (&handlers);
+  control_warning_option (OPT_Wpointer_arith, (int) DK_ERROR, true,
+			  UNKNOWN_LOCATION, CL_C | CL_ObjC | CL_UPC,
+			  &handlers, &global_options, &global_options_set,
+			  global_dc);
+
+#ifdef ENABLE_UPC_DWARF2_SUPPORT
+  /* Some targets support UPC's DWARF2 extensions by default. */
+  use_upc_dwarf2_extensions = 1;
+#else
+  use_upc_dwarf2_extensions = 0;
+#endif
+
+  flag_upc = 1;
+  flag_upc_threads = 0;
+  flag_upc_pthreads = 0;
+  /* We begin in the state where we assume that we're compiling UPC 
+     The 'compiling_upc' flag is queried when compiling for a
+     pthreads environment to determine whether global static
+     variables should be allocated to thread local storage. */
+  compiling_upc = 1;
+  /* By default, don't map UPC threads to POSIX threads. */
+  flag_upc_pthreads = 0;
+  upc_pthreads_model = upc_pthreads_no_model;
+  flag_upc_pthreads_per_process = 0;
+  /* By default, GASP profiling is off.  */
+  flag_upc_instrument = 0;
+  flag_upc_instrument_functions = 0;
+  /* By default, optimization level > 0 defines shared access routines
+     inlining, otherwise use the user specified flag for unconditional 
+     enable/disable of inlining (0 - disable, 1 - enable) */
+  flag_upc_inline_lib = -1;
+}
+
+static bool upc_post_options (const char **pfilename)
+{
+  return c_common_post_options (pfilename);
+}
+
+static alias_set_type
+upc_get_alias_set (tree t)
+{
+
+  /* For the time being, make UPC pointers-to-shared conflict
+     with everything else. Ideally, UPC pointers-to-shared should
+     only conflict with the internal type used to represent
+     the UPC pointer-to-shared (i.e., upc_pts_rep_type_node).  */
+
+  if (TYPE_P (t) ? (TREE_CODE (t) == POINTER_TYPE
+		    && upc_shared_type_p (TREE_TYPE (t)))
+                 : (TREE_TYPE(t)
+		    && TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE
+		    && upc_shared_type_p (TREE_TYPE (TREE_TYPE (t)))))
+    return 0;
+
+
+  /* Otherwise, do the default thing. */
+
+  return c_common_get_alias_set (t);
+}
+
+static void
+upc_init_ts (void)
+{
+  c_common_init_ts ();
+  MARK_TS_COMMON (UPC_FORALL_STMT);
+  MARK_TS_COMMON (UPC_SYNC_STMT);
+}
+
+#include "gtype-upc.h"
Index: gcc/upc/config-lang.in
===================================================================
--- gcc/upc/config-lang.in	(.../trunk)	(revision 0)
+++ gcc/upc/config-lang.in	(.../branches/gupc)	(revision 175735)
@@ -0,0 +1,71 @@
+# upc/config-lang.in: GNU UPC runtime library top-level configure fragment
+
+# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+# 2009, 2010, 2011
+# Free Software Foundation, Inc.
+# Contributed by Gary Funck <gary@intrepid.com>
+#   and Nenad Vukicevic <nenad@intrepid.com>.
+# Based on original implementation
+#   by Jesse M. Draper <jdraper@super.org>
+#   and William W. Carlson <wwc@super.org>.
+# Derived from objc/config-lang.in
+
+# This file is part of GCC.
+
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Configure looks for the existence of this file to auto-config each language.
+# We define several parameters used by configure:
+#
+# language	- name of language as it would appear in $(LANGUAGES)
+# compilers	- value to add to $(COMPILERS)
+# stagestuff	- files to add to $(STAGESTUFF)
+
+language="upc"
+
+build_by_default="no"
+
+compilers="cc1upc\$(exeext)"
+
+stagestuff="cc1upc\$(exeext)"
+
+target_libs="target-libupc"
+
+gtfiles="\$(srcdir)/c-lang.h \$(srcdir)/c-tree.h \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-upc.h \$(srcdir)/upc/upc-act.h \$(srcdir)/c-decl.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-parser.c \$(srcdir)/upc/upc-act.c"
+
+#
+# UPC specific configuration definitions
+#
+case $build in
+alpha*-*-unicosmk*)
+      ;;
+i[356]86-*-darwin*)
+      ;;
+i[56]86-*-linux*)
+      ;;
+mips-sgi-irix6*)
+      ;;
+ia64-*-linux*)
+      ;;
+x86_64-*-linux*)
+      ;;
+x86_64-*-darwin*)
+      ;;
+*)
+      echo "UPC has not been configured for ${build}." >&2
+      exit 2
+      ;;
+esac 
+extra_parts="${extra_parts} ${upc_extra_parts}"
Index: gcc/upc/Make-lang.in
===================================================================
--- gcc/upc/Make-lang.in	(.../trunk)	(revision 0)
+++ gcc/upc/Make-lang.in	(.../branches/gupc)	(revision 175735)
@@ -0,0 +1,244 @@
+# Top level -*- makefile -*- fragment for GNU UPC
+
+#    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+#    2010, 2011
+#    Free Software Foundation, Inc.
+#    Contributed by Gary Funck <gary@intrepid.com>
+#      and Nenad Vukicevic <nenad@intrepid.com>.
+#    Based on original implementation
+#      by Jesse M. Draper <jdraper@super.org>
+#      and William W. Carlson <wwc@super.org>.
+#    Derived from objc/Make-lang.in
+
+# This file is part of GCC.
+
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# This file provides the language dependent support in the main Makefile.
+# Each language makefile fragment must provide the following targets:
+#
+# foo.all.build, foo.all.cross, foo.start.encap, foo.rest.encap,
+# foo.install-normal, foo.install-common, foo.install-man,
+# foo.uninstall,
+# foo.mostlyclean, foo.clean, foo.distclean,
+# foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4
+#
+# where `foo' is the name of the language.
+#
+# It should also provide rules for:
+#
+# - making any compiler driver (eg: upc)
+# - the compiler proper (eg: cc1upc)
+# - define the names for selecting the language in LANGUAGES.
+
+UPC_EXE = cc1upc$(exeext) xupc$(exeext) upc-cmd$(exeext)
+
+#
+# Define the names for selecting UPC in LANGUAGES.
+UPC Upc upc: $(UPC_EXE)
+
+# Tell GNU make to ignore these if they exist.
+.PHONY: UPC Upc upc
+
+# Use maximal warnings for this front end.
+upc-warn = $(STRICT_WARN)
+
+# UPC PTS representation-dependent support.
+# (Set by the --with-upc-pts={struct,packed} configure switch.)
+UPC_PTS_C = upc-pts-packed.c upc-pts-struct.c
+UPC_PTS_OBJ = upc/upc-pts-packed.o upc/upc-pts-struct.o
+
+# Language-specific object files for UPC.
+UPC_OBJS = c-family/stub-objc.o upc/upc-act.o \
+	   upc/upc-gimplify.o upc/upc-lang.o \
+	   upc/upc-gasp.o $(UPC_PTS_OBJ)
+
+cc1upc-checksum.c : build/genchecksum$(build_exeext) checksum-options \
+        $(UPC_OBJS) $(C_AND_OBJC_OBJS) $(BACKEND) $(LIBDEPS)
+	build/genchecksum$(build_exeext) $(UPC_OBJS) $(C_AND_OBJC_OBJS) \
+        $(BACKEND) $(LIBDEPS) checksum-options > cc1upc-checksum.c.tmp && \
+	$(srcdir)/../move-if-change cc1upc-checksum.c.tmp cc1upc-checksum.c
+
+cc1upc-checksum.o : cc1upc-checksum.c $(CONFIG_H) $(SYSTEM_H)
+
+cc1upc$(exeext): $(UPC_OBJS) $(C_AND_OBJC_OBJS) cc1upc-checksum.o \
+		 $(BACKEND) $(LIBDEPS)
+	$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
+		$(UPC_OBJS) $(C_AND_OBJC_OBJS) cc1upc-checksum.o \
+		$(BACKEND) $(LIBS) $(BACKENDLIBS)
+
+xupc$(exeext): $(srcdir)/upc/upc-cmd.c Makefile cc1upc$(exeext) $(LIBDEPS)
+	thisdir=`pwd` ; \
+	incdir=`cd $(srcdir)/../libupc/include; pwd`; \
+	libdir=`dirname $${thisdir}`/$(target); \
+	$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+	    $(DRIVER_DEFINES) \
+	    "-DCOMPILER=\"xgcc\"" \
+	    "-DCOMPILER_DIR=\"$${thisdir}/\"" \
+	    "-DBIN_PATH=\"$${thisdir}\"" \
+	    "-DLIB_PATH=\"$${libdir}\"" \
+	    "-DINC_PATH=\"$${incdir}\"" \
+	    -c $(srcdir)/upc/upc-cmd.c -o xupc-tmp.o
+	$(CC) xupc-tmp.o -o xupc$(exeext) $(LIBS)
+	rm -f xupc-tmp.o
+
+upc-cmd$(exeext): $(srcdir)/upc/upc-cmd.c Makefile cc1upc$(exeext) $(LIBDEPS)
+	thisdir=`pwd` ; \
+	$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+	    $(DRIVER_DEFINES) \
+	    "-DCOMPILER=\"gcc\"" \
+	    "-DBIN_PATH=\"$(bindir)\"" \
+	    -c $(srcdir)/upc/upc-cmd.c -o upc-cmd-tmp.o
+	$(CC) upc-cmd-tmp.o -o upc-cmd$(exeext) $(LIBS)
+	rm -f upc-cmd-tmp.o
+
+#
+# UPC language specific files.
+#
+upc/upc-lang.o : upc/upc-lang.c \
+   $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+   $(C_TREE_H) upc/upc-tree.h toplev.h \
+   $(C_PRETTY_PRINT_H) $(DIAGNOSTIC_H) \
+   $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(C_COMMON_H) \
+   gtype-upc.h gt-upc-upc-act.h upc/upc-act.h upc/upc-pts.h
+
+upc/upc-act.o : upc/upc-act.c \
+   $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
+   $(TM_P_H) $(EXPR_H) $(TARGET_H) $(C_TREE_H) diagnostic.h toplev.h \
+   flags.h input.h function.h output.h debug.h langhooks.h \
+   $(LANGHOOKS_DEF_H) $(HASHTAB_H) c-family/c-pragma.h \
+   gtype-upc.h gt-upc-upc-act.h upc/upc-act.h upc/upc-pts.h \
+   upc/upc-rts-names.h
+
+upc/upc-gimplify.o : upc/upc-gimplify.c \
+   $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
+   $(TM_P_H) $(EXPR_H) $(TARGET_H) $(C_TREE_H) diagnostic.h \
+   toplev.h flags.h input.h function.h output.h debug.h langhooks.h \
+   $(LANGHOOKS_DEF_H) $(HASHTAB_H) c-family/c-pragma.h \
+   upc/upc-gimplify.h upc/upc-tree.h upc/upc-act.h upc/upc-pts.h \
+   upc/upc-rts-names.h
+
+upc/upc-pts-packed.o: upc/upc-pts-packed.c \
+   $(CONFIG_H) $(SYSTEM_H) $(TARGET_H) $(TM_H) $(TM_P_H) \
+   $(TREE_H) coretypes.h $(LANGHOOKS_DEF_H) langhooks.h \
+   c-family/c-pragma.h $(C_TREE_H) debug.h \
+   diagnostic.h $(EXPR_H) flags.h function.h input.h \
+   output.h $(RTL_H) toplev.h \
+   upc/upc-act.h upc/upc-pts.h upc/upc-rts-names.h
+
+upc/upc-pts-struct.o: upc/upc-pts-struct.c \
+   $(CONFIG_H) $(SYSTEM_H) $(TARGET_H) $(TM_H) $(TM_P_H) \
+   $(TREE_H) coretypes.h $(LANGHOOKS_DEF_H) langhooks.h \
+   c-family/c-pragma.h $(C_TREE_H) debug.h \
+   diagnostic.h $(EXPR_H) flags.h function.h input.h \
+   output.h $(RTL_H) toplev.h \
+   upc/upc-act.h upc/upc-pts.h upc/upc-rts-names.h
+
+upc/upc-gasp.o : upc/upc-gasp.c \
+   $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
+   $(TM_P_H) $(EXPR_H) $(TARGET_H) $(C_TREE_H) diagnostic.h \
+   toplev.h flags.h input.h function.h output.h debug.h langhooks.h \
+   $(LANGHOOKS_DEF_H) $(HASHTAB_H) c-family/c-pragma.h \
+   upc/upc-gasp.h upc/upc-tree.h upc/upc-act.h upc/upc-pts.h \
+   upc/upc-rts-names.h
+
+#
+# Build hooks:
+
+upc.all.build:
+upc.all.cross:
+upc.start.encap:
+upc.rest.encap:
+upc.info:
+upc.man:
+upc.srcinfo:
+upc.srcman:
+upc.srcextra:
+upc.install-info:
+upc.install-pdf:
+upc.install-plugin:
+
+upc.tags: force
+	cd $(srcdir)/upc; etags -o TAGS.sub *.y *.c *.h; \
+	etags --include TAGS.sub --include ../TAGS.sub
+
+lang_checks += check-upc
+
+#
+# Install hooks:
+# cc1upc is installed elsewhere as part of $(COMPILERS).
+
+upc.install-normal:
+
+upc.install-common: cc1upc$(exeext) upc-cmd$(exeext) installdirs
+	-rm -f $(DESTDIR)$(bindir)/upc
+	$(INSTALL_PROGRAM) -m 755 upc-cmd$(exeext) $(DESTDIR)$(bindir)/upc
+
+
+.PHONY: upc.pdf upc.html
+
+upc.pdf:
+
+upc.html: $(build_htmldir)/upc/index.html
+
+$(build_htmldir)/upc/index.html: $(srcdir)/upc/upc-manpage.html
+	$(mkinstalldirs) $(@D)
+	$(INSTALL_DATA) $< $@
+
+# Make sure `installdirs' target (from gcc Makefile) has been
+# run, since we use libsubdir to store our `flag' file, lang-upc.
+upc.install-man: $(srcdir)/upc/upc.1 installdirs
+	case "$(LANGUAGES)" in \
+	  *[Uu][Pp][Cc]*) touch $(DESTDIR)$(libsubdir)/lang-upc;; \
+	  *) rm -f $(DESTDIR)$(libsubdir)/lang-upc;; \
+	esac
+	-if [ -f $(DESTDIR)$(libsubdir)/lang-upc -a -f cc1upc$(exeext) ] ; then \
+	    rm -f $(DESTDIR)$(man1dir)/upc$(man1ext); \
+	    $(INSTALL_DATA) $(srcdir)/upc/upc.1 $(DESTDIR)$(man1dir)/upc$(man1ext); \
+	    chmod a-x $(DESTDIR)$(man1dir)/upc$(man1ext); \
+	else true; fi
+	rm -f $(DESTDIR)$(libsubdir)/lang-upc
+
+upc.uninstall:
+#
+# Clean hooks:
+# A lot of the ancillary files are deleted by the main makefile.
+# We just have to delete files specific to us.
+upc.mostlyclean:
+	-rm -f tmp-upc-prs.y
+	-rm -f upc/*$(objext) upc/xforward upc/fflags
+	-rm -f upc/*$(coverageexts)
+upc.clean: upc.mostlyclean
+	-rm -rf upc-headers
+upc.distclean:
+	-rm -f upc/Makefile upc/Make-host upc/Make-target
+	-rm -f upc/config.status upc/config.cache
+upc.maintainer-clean:
+
+#
+# Stage hooks:
+
+upc.stage1: stage1-start
+	-mv upc/*$(objext) stage1/upc
+upc.stage2: stage2-start
+	-mv upc/*$(objext) stage2/upc
+upc.stage3: stage3-start
+	-mv upc/*$(objext) stage3/upc
+upc.stage4: stage4-start
+	-mv upc/*$(objext) stage4/upc
+upc.stageprofile: stageprofile-start
+	-mv upc/*$(objext) stageprofile/upc
+upc.stagefeedback: stagefeedback-start
+	-mv upc/*$(objext) stagefeedback/upc
Index: gcc/upc/upc-cmd.c
===================================================================
--- gcc/upc/upc-cmd.c	(.../trunk)	(revision 0)
+++ gcc/upc/upc-cmd.c	(.../branches/gupc)	(revision 175735)
@@ -0,0 +1,597 @@
+/* upc-cmd.c: the UPC compiler driver program
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2010, 2011
+   Free Software Foundation, Inc.
+   Contributed by Gary Funck <gary@intrepid.com>
+     and Nenad Vukicevic <nenad@intrepid.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#define USED_FOR_TARGET 1	/* disable inclusion of code gen defs. */
+#include "tm.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/types.h>
+
+/* The UPC driver program invokes the GCC compiler, passing along
+   the switches on the command line. If the user does not supply
+   switches (such -c, -S, or -E) that would disable linking,
+   then add the additional link switches that are required to
+   link a UPC program. */
+
+#ifndef COMPILER
+#error "-DCOMPILER must be supplied when compiling upc.c"
+#endif
+
+#define MULTI_DIR_SWITCH "-print-multi-directory"
+#define FIND_LIBUPC_SWITCH "-print-file-name=libupc.a"
+
+#define GCC_SWITCH_TAKES_ARG(CHAR) \
+  ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
+   || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
+   || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
+   || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \
+   || (CHAR) == 'B' || (CHAR) == 'b')
+
+
+/* This defines which multi-letter switches take arguments.  */
+#define GCC_WORD_SWITCH_TAKES_ARG(STR)		\
+  (  !strcmp (STR, "aux-info") \
+  || !strcmp (STR, "dumpbase") \
+  || !strcmp (STR, "idirafter") \
+  || !strcmp (STR, "imacros") \
+  || !strcmp (STR, "include") \
+  || !strcmp (STR, "iprefix") \
+  || !strcmp (STR, "isystem") \
+  || !strcmp (STR, "iwithprefix") \
+  || !strcmp (STR, "iwithprefixbefore") \
+  || !strcmp (STR, "param") \
+  || !strcmp (STR, "specs") \
+  || !strcmp (STR, "Tbss") \
+  || !strcmp (STR, "Tdata") \
+  || !strcmp (STR, "Ttext") \
+  || !strcmp (STR, "Xlinker"))
+
+#define NO_LINK_SWITCHES(STR) \
+  (!strcmp (STR, "-fsyntax-only") || !strcmp (STR, "-c") \
+  || !strcmp (STR, "-M") || !strcmp (STR, "-MM") \
+  || !strcmp (STR, "-E") || !strcmp (STR, "-S"))
+
+#define GCC_INFO_ONLY_SWITCHES(STR) \
+  (!strcmp (STR, "-v") || !strcmp(STR, "--verbose") \
+  || !strcmp (STR, "--version") \
+  || !strcmp (STR, "--help") \
+  || !strncmp(STR, "-print-", 7) || !strncmp(STR, "--print-", 8))
+
+#ifndef ARG_MAX
+#define ARG_MAX 4096
+#endif
+
+#ifndef GET_ENV_PATH_LIST
+#define GET_ENV_PATH_LIST(VAR,NAME) \
+	do { (VAR) = getenv (NAME); } while (0)
+#endif
+
+#define BINSUFFIX "/bin/"
+#define GCCLIBSUFFIX "/lib/gcc/"
+
+static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
+static const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX;
+
+static char *progname;
+
+static int debug;
+
+static char *substr PARAMS ((const char *s, int len));
+static int match_suffix PARAMS ((const char *s, const char *suffix));
+
+#define END_ARGS ((char *) 0)
+
+/* Concatenate a sequence of strings, returning the result.
+
+   This function is based on the one in libiberty.  */
+
+char *
+concat (const char *first, ...)
+{
+  int length;
+  char *newstr;
+  char *end;
+  const char *arg;
+  va_list args;
+
+  /* First compute the size of the result and get sufficient memory.  */
+
+  va_start (args, first);
+  arg = first;
+  length = 0;
+
+  while (arg != END_ARGS)
+    {
+      length += strlen (arg);
+      arg = va_arg (args, const char *);
+    }
+
+  newstr = (char *) xmalloc (length + 1);
+  va_end (args);
+
+  /* Now copy the individual pieces to the result string.  */
+
+  va_start (args, first);
+  end = newstr;
+  arg = first;
+  while (arg != END_ARGS)
+    {
+      while (*arg)
+	*end++ = *arg++;
+      arg = va_arg (args, const char *);
+    }
+  *end = '\000';
+  va_end (args);
+
+  return newstr;
+}
+
+static char *
+substr (const char *s, int len)
+{
+  char *sub = (char *) xmalloc (len + 1);
+  strncpy (sub, s, len);
+  sub[len] = '\0';
+  return sub;
+}
+
+static int
+match_suffix (const char *s, const char *suffix)
+{
+  int slen = strlen (s);
+  int xlen = strlen (suffix);
+  const char *start = (xlen <= slen) ? s + slen - xlen : 0;
+  return start && !strncmp (start, suffix, xlen);
+}
+
+/* Escape characters that might be harmful to the shell.  */
+
+static char *
+shell_escape (const char *s)
+{
+  const char *meta = "&;`'\\\"|*?~<>^()[]{}$\n\r\f\t ";
+  int needs_escape, needs_quote;
+  char *r;
+  const char *ps;
+  char *result = xstrdup (s);
+  for (needs_quote = 0, needs_escape = 0, ps = s; *ps; ++ps)
+    {
+      if (strchr (meta, (int) *ps))
+	needs_quote = 1;
+      needs_escape += (*ps == '\'');
+    }
+  if (needs_quote)
+    {
+      result = (char *) xmalloc (strlen (s) + 1 + 2 + needs_escape * 5);
+      for (ps = s, r = result, *r++ = '\''; *ps; ++ps)
+	if (*ps == '\'')
+	  {
+	    memcpy (r, "'\"'\"'", 5);
+	    r += 5;
+	  }
+	else
+	  *r++ = *ps;
+      *r++ = '\'';
+      *r = '\0';
+    }
+  return result;
+}
+
+/* Using the argument list we've built up so far, tack on
+   the PRINT_CMD argument, and return the result.  */
+
+static const char *
+get_print_cmd (const char *exec_args[], int n_args, const char *print_cmd)
+{
+  int i, len;
+  char *cmd;
+  char *s;
+  const char *result = NULL;
+  FILE *pipe;
+  for (i = 0, len = strlen (print_cmd) + 1; i < n_args; ++i)
+    len += strlen (shell_escape (exec_args[i])) + 1;
+  cmd = (char *) xmalloc (len);
+  for (i = 0, s = cmd; i < n_args; ++i)
+    {
+      char *p = shell_escape (exec_args[i]);
+      while (*p)
+	*s++ = *p++;
+      *s++ = ' ';
+    }
+  strcpy (s, print_cmd);
+  pipe = popen (cmd, "r");
+  if (pipe)
+    {
+      char buf[256];
+      int slen;
+      (void) fgets (buf, sizeof (buf), pipe);
+      slen = strlen (buf);
+      if (buf[slen - 1] == '\n')
+	buf[slen - 1] = '\0';
+      (void) pclose (pipe);
+      result = (const char *) xstrdup (buf);
+    }
+  return result;
+}
+
+/* Return the path of the library directory,
+   where libupc can be found.  LIB_PATH will be defined
+   when the development version of the 'upc' command is
+   being built; use that path, and add the multilib
+   suffix if required.  Otherwise, for the installed
+   'upc' command, use -print-file-name to find the "libupc.a"
+   library file, and return the containing directory.  */
+
+static const char *
+get_libupc_path (const char *exec_args[], int n_args)
+{
+  const char *libupc_path = NULL;
+#ifdef LIB_PATH
+  {
+    const char *lib_suffix;
+    libupc_path = LIB_PATH;
+    lib_suffix = get_print_cmd (exec_args, n_args, MULTI_DIR_SWITCH);
+    if (debug)
+      fprintf (stderr, "lib suffix = %s\n",
+	       lib_suffix ? lib_suffix : "<none>");
+    if (lib_suffix && *lib_suffix && (strcmp (lib_suffix, ".") != 0))
+      libupc_path = concat (libupc_path, "/", lib_suffix, END_ARGS);
+    libupc_path = concat (libupc_path, "/libupc", END_ARGS);
+  }
+#else
+  {
+    const char *libupc_archive;
+    libupc_archive = get_print_cmd (exec_args, n_args, FIND_LIBUPC_SWITCH);
+    if (debug)
+      fprintf (stderr, "libupc.a path = %s\n",
+	       libupc_archive ? libupc_archive : "<none>");
+    if (libupc_archive[0] == '/')
+      {
+	const char *s, *last_slash;
+	char *path;
+	size_t slen;
+	for (s = libupc_archive; *s; ++s)
+	  if (*s == '/')
+	    last_slash = s;
+	slen = (last_slash - libupc_archive);
+	path = (char *) xmalloc (slen + 1);
+	memcpy (path, libupc_archive, slen);
+	path[slen] = '\0';
+	libupc_path = (const char *) path;
+      }
+  }
+#endif
+  if (debug)
+    fprintf (stderr, "lib path = %s\n", libupc_path ? libupc_path : "<none>");
+  return libupc_path;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int i, nargs;
+  int info_only = 1;
+  int invoke_linker = 1;
+  int no_default_libs = 0;
+  int no_std_inc = 0;
+  int no_upc_pre_inc = 0;
+  int is_x_upc_in_effect = 0;
+  const int is_dev_compiler = !strcmp (COMPILER, "xgcc");
+  const char *cp;
+  const char *compiler = 0;
+  const char *compiler_dir = 0;
+  const char *bin_dir = 0;
+  const char *lib_dir = 0;
+  const char *inc_dir = 0;
+  const char *upc_exec_prefix = 0;
+  const char *exec_args[ARG_MAX];
+  char *exec_arg_list[ARG_MAX];
+
+#ifdef DEBUG
+  debug = 1;
+#endif
+
+  /* Parse command line early for instances of -debug.  This allows
+     the debug flag to be set before functions like find_a_file()
+     are called.  */
+  for (i = 1; i < argc; ++i)
+    if (!strcmp (argv[i], "-debug"))
+      debug = 1;
+
+  /* extract the program's name from the command line. */
+  for (cp = argv[0] + strlen (argv[0]) - 1;
+       cp != argv[0] && *cp != '/'; --cp) /* loop */ ;
+  progname = (char *) xmalloc (strlen (cp + 1) + 1);
+  strcpy (progname, cp + 1);
+
+
+#ifdef COMPILER_DIR
+  compiler_dir = concat (COMPILER_DIR, END_ARGS);
+#endif
+#ifdef BIN_PATH
+  bin_dir = BIN_PATH;
+#endif
+#ifdef INC_PATH
+  inc_dir = INC_PATH;
+#endif
+
+  /* Check to see if any switches are asserted that inhibit linking
+     and record the presence of other switches that may require
+     special handling. */
+  for (i = 1; i < argc; ++i)
+    {
+      const char *const arg = argv[i];
+      if (arg[0] == '-')
+	{
+	  /* skip upc's '-debug' switch */
+	  if (!strcmp (arg, "-debug"))
+	    continue;
+	  else if (!strcmp (arg, "-nodefaultlibs"))
+	    {
+	      no_default_libs = 1;
+	    }
+	  else if (!strcmp (arg, "-nostdinc"))
+	    {
+	      no_std_inc = 1;
+	    }
+	  else if (!strcmp (arg, "-nostdlib"))
+	    {
+	      no_default_libs = 1;
+	    }
+	  else if (!strcmp (arg, "-fno-upc-pre-include"))
+	    {
+	      no_upc_pre_inc = 1;
+	    }
+	  invoke_linker = invoke_linker && !NO_LINK_SWITCHES (arg);
+	  info_only = info_only && GCC_INFO_ONLY_SWITCHES (arg);
+	  if (((arg[2] == '\0') && GCC_SWITCH_TAKES_ARG (arg[1]))
+	      || GCC_WORD_SWITCH_TAKES_ARG (&arg[1])
+	      || ((arg[1] == '-') && GCC_WORD_SWITCH_TAKES_ARG (&arg[2])))
+	    /* skip the following argument */
+	    ++i;
+	}
+      else
+	/* an argument that is not a switch implies that we'll do something. */
+	info_only = FALSE;
+    }
+  invoke_linker = invoke_linker && !info_only;
+  nargs = 0;
+  /* The COMPILER preprocessor variable is passed on the command
+     line to the C compiler when 'upc' is built. It usually has
+     the form "xgcc" for builds in the development directory,
+     and "gcc" for installed upc command. The COMPILER_DIR
+     directory gives the location of where the gcc (or xgcc)
+     binary lives, usually with a "/" appended to the end, so
+     that the result can be passed directly to the "gcc" command,
+     yield an invocation of the form:
+     <full_pathname_of_gcc_or_xgcc> -B<compiler_dir>/
+
+     If the UPC_EXEC_PREFIX environment variable is set, this value overrides
+     the compiled-in COMPILER_DIR setting. */
+
+  GET_ENV_PATH_LIST (upc_exec_prefix, "UPC_EXEC_PREFIX");
+  if (!(compiler_dir || upc_exec_prefix))
+    {
+      upc_exec_prefix =
+	make_relative_prefix (argv[0], standard_bindir_prefix,
+			      standard_exec_prefix);
+    }
+  if (upc_exec_prefix && strcmp (upc_exec_prefix, standard_exec_prefix) != 0)
+    {
+      int len = strlen (upc_exec_prefix);
+
+      if (debug)
+	{
+	  fprintf (stderr, "using UPC_EXEC_PREFIX=%s\n", upc_exec_prefix);
+	}
+      if (match_suffix (upc_exec_prefix, GCCLIBSUFFIX))
+	{
+	  bin_dir = concat (substr (upc_exec_prefix,
+				    len - (sizeof (GCCLIBSUFFIX) - 1)),
+			    "/bin", END_ARGS);
+	  compiler_dir = upc_exec_prefix;
+	}
+      else if (match_suffix (upc_exec_prefix, BINSUFFIX))
+	{
+	  bin_dir = substr (upc_exec_prefix, len - 1);
+	  compiler_dir = concat (substr (upc_exec_prefix,
+					 len - (sizeof (BINSUFFIX) - 1)),
+				 GCCLIBSUFFIX, END_ARGS);
+	}
+      else
+	{
+	  bin_dir = concat (upc_exec_prefix, "bin", END_ARGS);
+	  compiler_dir = concat (upc_exec_prefix, "lib/gcc-lib/", END_ARGS);
+	}
+
+      inc_dir = concat (compiler_dir,
+			DEFAULT_TARGET_MACHINE, "/",
+			DEFAULT_TARGET_VERSION, "/include", END_ARGS);
+    }
+
+  compiler = concat (bin_dir, "/", COMPILER, END_ARGS);
+  exec_args[nargs++] = compiler;
+
+  if (compiler_dir)
+    {
+      exec_args[nargs++] = xstrdup ("-B");
+      exec_args[nargs++] = compiler_dir;
+    }
+
+  if (!info_only)
+    {
+      if (inc_dir && !no_std_inc && !no_upc_pre_inc)
+	{
+	  /* Copy in the -isystem <path> argument */
+	  exec_args[nargs++] = xstrdup ("-isystem");
+	  exec_args[nargs++] = inc_dir;
+	}
+    }
+
+  /* Copy in the arguments as passed to 'upc' */
+  for (i = 1, is_x_upc_in_effect = 0; i < argc; ++i)
+    {
+      const char *const arg = argv[i];
+      const int is_c_file = match_suffix (arg, ".c")
+	|| match_suffix (arg, ".h");
+      const int is_upc_file = match_suffix (arg, ".upc")
+	|| match_suffix (arg, ".uph");
+      int num;
+      /* skip upc's '-debug' switch */
+      if (!strcmp (arg, "-debug"))
+	continue;
+      if (!strcmp (arg, "-n") && ((i + 1) < argc))
+	{
+	  /* rewrite "-n <num>" into "-fupc-threads-<num>" */
+	  exec_args[nargs++] = concat ("-fupc-threads-", argv[++i], END_ARGS);
+	}
+      else if (!strncmp (arg, "-n", 2) && (sscanf (arg + 2, "%d", &num) == 1))
+	{
+	  /* rewrite "-n<num>" into "-fupc-threads-<num>" */
+	  exec_args[nargs++] = concat ("-fupc-threads-", arg + 2, END_ARGS);
+	}
+      else if (!strcmp (arg, "-inst") || !strcmp (arg, "--inst"))
+	{
+	  /* rewrite "-inst" or "--inst" into "-fupc-instrument" */
+	  exec_args[nargs++] = "-fupc-instrument";
+	}
+      else if (!strcmp (arg, "-inst-functions")
+	       || !strcmp (arg, "--inst-functions"))
+	{
+	  /* rewrite "-inst-functions" or "--inst-functions"
+	     into "-fupc-instrument-functions" */
+	  exec_args[nargs++] = "-fupc-instrument-functions";
+	}
+      else if (((arg[2] == '\0') && GCC_SWITCH_TAKES_ARG (arg[1]))
+	       || GCC_WORD_SWITCH_TAKES_ARG (&arg[1])
+	       || ((arg[1] == '-') && GCC_WORD_SWITCH_TAKES_ARG (&arg[2])))
+	{
+	  /* Copy the switch and the following argument.  */
+	  exec_args[nargs++] = arg;
+	  exec_args[nargs++] = argv[++i];
+	}
+      else if (arg[1] == '-')
+	/* Copy the switch and continue.  */
+	exec_args[nargs++] = arg;
+      else
+	{
+	  if (is_c_file && !is_x_upc_in_effect)
+	    {
+	      /* Assume that .c files are in fact UPC source files */
+	      is_x_upc_in_effect = 1;
+	      exec_args[nargs++] = "-x";
+	      exec_args[nargs++] = "upc";
+	    }
+	  else if (!(is_c_file || is_upc_file) && is_x_upc_in_effect)
+	    {
+	      is_x_upc_in_effect = 0;
+	      exec_args[nargs++] = "-x";
+	      exec_args[nargs++] = "none";
+	    }
+	  exec_args[nargs++] = arg;
+	}
+    }
+
+  if (!info_only)
+    {
+      lib_dir = get_libupc_path (exec_args, nargs);
+      if (!lib_dir)
+	{
+	  fprintf (stderr, "Cannot find UPC library directory.\n");
+	  exit (2);
+	}
+      if (!no_std_inc && !no_upc_pre_inc)
+	{
+	  /* Place libdir first so that we can find gcc-upc-lib.h. */
+	  exec_args[nargs++] = xstrdup ("-isystem");
+	  exec_args[nargs++] = lib_dir;
+	}
+      /* add -B <lib_dir>/ so that we can find libupc.spec.  */
+      exec_args[nargs++] = concat ("-B", lib_dir, "/", END_ARGS);
+    }
+
+  if (invoke_linker)
+    {
+      /* The -fupc-link switch triggers per-target libupc compiler specs
+         via %:include(libupc.spec). */
+      exec_args[nargs++] = "-fupc-link";
+      if (!no_default_libs && lib_dir)
+	{
+	  const char *link_lib_dir = lib_dir;
+	  /* If we're building the development version of the UPC
+	     driver ("xupc"), then we need to add the .libs suffix
+	     because that's where libtool hides libupc.a */
+	  if (is_dev_compiler)
+	    link_lib_dir = concat (link_lib_dir, "/.libs", END_ARGS);
+	  /* Add the link library path where libupc.a is located.  */
+	  exec_args[nargs++] =
+	    concat (xstrdup ("-L"), link_lib_dir, END_ARGS);
+	}
+    }
+
+  if (debug)
+    {
+      fprintf (stderr, "upc exec args: ");
+      for (i = 0; i < nargs; ++i)
+	{
+	  if (i != 0)
+	    fprintf (stderr, " ");
+	  fprintf (stderr, "%s", exec_args[i]);
+	}
+      fprintf (stderr, "\n");
+    }
+  exec_args[nargs++] = 0;
+
+  /* The 'execv' prototype indicates that the strings
+     pointed to by the argument pointers are not 'const'
+     qualified.  Make a copy to be on the safe side.  */
+  for (i = 0; i < nargs; ++i)
+    {
+      char *arg_copy = NULL;
+      if (exec_args[i] != NULL)
+	arg_copy = xstrdup (exec_args[i]);
+      exec_arg_list[i] = arg_copy;
+    }
+
+  if (execv (exec_args[0], exec_arg_list) < 0)
+    {
+      perror (exec_args[0]);
+      exit (255);
+    }
+  /* no return */
+  exit (255);
+}
Index: gcc/upc/upc-tree.h
===================================================================
--- gcc/upc/upc-tree.h	(.../trunk)	(revision 0)
+++ gcc/upc/upc-tree.h	(.../branches/gupc)	(revision 175735)
@@ -0,0 +1,48 @@
+/* upc-tree.h: UPC language specific tree node access functions
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
+   Contributed by Gary Funck <gary@intrepid.com>
+     and Nenad Vukicevic <nenad@intrepid.com>.
+   Based on original implementation
+     by Jesse M. Draper <jdraper@super.org>
+     and William W. Carlson <wwc@super.org>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef UPC_TREE_H
+#define UPC_CP_TREE_H
+
+/* Used to represent a UPC synchronization statement. The first
+   operand is the synchonization operation, UPC_SYNC_OP:
+   UPC_SYNC_NOTIFY_OP	1	Notify operation
+   UPC_SYNC_WAIT_OP	2	Wait operation
+   UPC_SYNC_BARRIER_OP	3	Barrier operation
+
+   The second operand, UPC_SYNC_ID is the (optional) expression
+   whose value specifies the barrier identifier which is checked
+   by the various synchronization operations. */
+
+#define UPC_SYNC_OP(NODE)	TREE_OPERAND (UPC_SYNC_STMT_CHECK (NODE), 0)
+#define UPC_SYNC_ID(NODE)	TREE_OPERAND (UPC_SYNC_STMT_CHECK (NODE), 1)
+
+/* Values of the first operand in a UPC_SYNC_STMT */
+
+#define UPC_SYNC_NOTIFY_OP	1	/* Notify operation */
+#define UPC_SYNC_WAIT_OP	2	/* Wait operation */
+#define UPC_SYNC_BARRIER_OP	3	/* Barrier operation */
+
+#endif /* ! UPC_TREE_H */
Index: gcc/upc/upc-act.c
===================================================================
--- gcc/upc/upc-act.c	(.../trunk)	(revision 0)
+++ gcc/upc/upc-act.c	(.../branches/gupc)	(revision 175735)
@@ -0,0 +1,1691 @@
+/* upc-act.c: implement UPC-related actions
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2010, 2011
+   Free Software Foundation, Inc.
+   Contributed by Gary Funck <gary@intrepid.com>
+     and Nenad Vukicevic <nenad@intrepid.com>.
+   Based on original implementation
+     by Jesse M. Draper <jdraper@super.org>
+     and William W. Carlson <wwc@super.org>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "coretypes.h"
+#include "system.h"
+#include "tree.h"
+#include "tree-iterator.h"
+#include "ggc.h"
+#include "hashtab.h"
+#include "input.h"
+#include "c-tree.h"
+#include "langhooks.h"
+#include "flags.h"
+#include "opts.h"
+#include "options.h"
+#include "output.h"
+#include "toplev.h"
+#include "gimple.h"
+#include "tm.h"
+#include "function.h"
+#include "target.h"
+#include "common/common-target.h"
+#include "upc-act.h"
+#include "upc-pts.h"
+#include "upc-rts-names.h"
+#include "cgraph.h"
+#include "c-family/c-common.h"
+#include "c-family/c-pragma.h"
+#include "c-family/c-upc.h"
+/* define decl_default_tls_model() prototype */
+#include "rtl.h"
+
+/* UPC_PTS is a table of functions that implement various
+   operations on expressions which refer to UPC pointers-to-shared,
+   where their implementation varies with the representation
+   of a pointer-to-shared value.  ('packed' or 'struct')  */
+
+upc_pts_ops_t upc_pts;
+
+static int contains_pts_refs_p (tree);
+static int recursive_count_upc_threads_refs (tree);
+static void upc_build_init_func (const tree);
+static int upc_lang_layout_decl_p (tree, tree);
+static void upc_lang_layout_decl (tree, tree);
+static void upc_parse_init (void);
+static int upc_sizeof_type_check (const char *, tree);
+static void upc_write_init_func (void);
+
+/* Given a shared variable's VAR_DECL node, map to another
+   VAR_DECL that has a similar external symbol name, with
+   the "shared" qualifier removed from its type.  This
+   "shadow variable" is used to generate conventional
+   address constants when referring to a shared variable.  */
+
+struct GTY (()) uid_tree_map
+{
+  unsigned int uid;
+  tree to;
+};
+
+/* Hash the UID of a shared variable to its unshared shadow variable.  */
+
+static
+GTY ((param_is (struct uid_tree_map))) htab_t unshared_vars;
+
+static hashval_t uid_tree_map_hash (const void *);
+static int uid_tree_map_eq (const void *, const void *);
+
+static GTY (()) tree upc_init_stmt_list;
+static GTY (()) section *upc_init_array_section;
+
+static tree create_unshared_var (location_t, const tree);
+static tree lookup_unshared_var (const tree);
+static void map_unshared_var (const tree, const tree);
+static tree unshared_var_addr (location_t, const tree);
+static tree unshared_var_name (const tree);
+static void upc_free_unshared_var_table (void);
+
+
+
+/* Process UPC specific command line switches */
+
+bool
+upc_handle_option (size_t scode, const char *arg, int value, int kind,
+		   location_t loc, const struct cl_option_handlers *handlers)
+{
+  enum opt_code code = (enum opt_code) scode;
+  int result = 1;
+  switch (code)
+    {
+    default:
+      result = c_common_handle_option (scode, arg, value, kind, loc,
+				       handlers);
+      break;
+    case OPT_dwarf_2_upc:
+      use_upc_dwarf2_extensions = value;
+      break;
+    case OPT_fupc_debug:
+      if ((value == 1) && (flag_upc_inline_lib == 1))
+	error ("-fupc-debug is incompatible with -fupc-inline-lib");
+      flag_upc_debug = value;
+      break;
+    case OPT_fupc_inline_lib:
+      if ((value == 1) && (flag_upc_instrument == 1))
+	error ("-fupc-inline-lib is incompatible with -fupc-instrument");
+      if ((value == 1) && (flag_upc_debug == 1))
+	error ("-fupc-inline-lib is incompatible with -fupc-debug");
+      flag_upc_inline_lib = value;
+      break;
+    case OPT_fupc_instrument:
+      if ((value == 1) && (flag_upc_inline_lib == 1))
+	error ("-fupc-instrument is incompatible with -fupc-inline-lib");
+      flag_upc_instrument = value;
+      break;
+    case OPT_fupc_instrument_functions:
+      if ((value == 1) && (flag_upc_inline_lib == 1))
+	error
+	  ("-fupc-instrument-functions is incompatible "
+	   "with -fupc-inline-lib");
+      flag_upc_instrument = value;
+      flag_upc_instrument_functions = value;
+      break;
+    case OPT_fupc_pthreads_model_tls:
+      flag_upc_pthreads = 1;
+      upc_pthreads_model = upc_pthreads_tls_model;
+      break;
+    case OPT_fupc_pthreads_per_process_:
+      if (value > UPC_MAX_THREADS)
+	{
+	  error ("THREADS value exceeds UPC implementation limit of %d",
+		 UPC_MAX_THREADS);
+	  value = 1;
+	}
+      flag_upc_pthreads_per_process = value;
+      break;
+    case OPT_fupc_threads_:
+      if (value > UPC_MAX_THREADS)
+	{
+	  error ("THREADS value exceeds UPC implementation limit of %d",
+		 UPC_MAX_THREADS);
+	  value = 1;
+	}
+      flag_upc_threads = value;
+      break;
+    case OPT_lang_upc:
+      flag_upc = value;
+      break;
+    }
+  return result;
+}
+
+/* UPC language-specific initialization ('init' hook).  */
+
+bool
+upc_lang_init (void)
+{
+  if (!targetm_common.have_named_sections)
+    {
+      fatal_error ("UPC is not implemented on this target; "
+		   "the target linker does not support separately "
+		   "linked sections");
+    }
+
+  /* c_obj_common_init is also called from regular 'C'
+     It will return 'false' if we're pre-processing only. */
+
+  if (c_objc_common_init () == false)
+    return false;
+  upc_parse_init ();
+  return true;
+}
+
+/* UPC Language-specific 'finish' hook (currently unused).  */
+
+void
+upc_finish (void)
+{
+}
+
+/* Generate UPC specific pre-defined macros. */
+
+void
+upc_cpp_builtins (cpp_reader * pfile)
+{
+  char def_buf[256];
+  cpp_define (pfile, "__GCC_UPC__=1");
+  cpp_define (pfile, "__UPC__=1");
+  cpp_define (pfile, "__UPC_VERSION__=200505L");
+  (void) sprintf (def_buf, "UPC_MAX_BLOCK_SIZE=%lu",
+		  (unsigned long) UPC_MAX_BLOCK_SIZE);
+  cpp_define (pfile, def_buf);
+#if defined(HAVE_UPC_PTS_PACKED_REP)
+  cpp_define (pfile, "__UPC_PTS_PACKED_REP__=1");
+#elif defined(HAVE_UPC_PTS_STRUCT_REP)
+  cpp_define (pfile, "__UPC_PTS_STRUCT_REP__=1");
+  (void) sprintf (def_buf, "__UPC_VADDR_TYPE__=%s", UPC_PTS_VADDR_TYPE);
+  cpp_define (pfile, def_buf);
+  (void) sprintf (def_buf, "__UPC_THREAD_TYPE__=%s", UPC_PTS_THREAD_TYPE);
+  cpp_define (pfile, def_buf);
+  (void) sprintf (def_buf, "__UPC_PHASE_TYPE__=%s", UPC_PTS_PHASE_TYPE);
+  cpp_define (pfile, def_buf);
+#else
+#error cannot determine UPC pointer-to-shared representation
+#endif
+#ifdef HAVE_UPC_PTS_VADDR_FIRST
+  cpp_define (pfile, "__UPC_VADDR_FIRST__=1");
+#endif
+  (void) sprintf (def_buf, "__UPC_PTS_SIZE__=%d", UPC_PTS_SIZE);
+  cpp_define (pfile, def_buf);
+  (void) sprintf (def_buf, "__UPC_VADDR_SIZE__=%d", UPC_PTS_VADDR_SIZE);
+  cpp_define (pfile, def_buf);
+  (void) sprintf (def_buf, "__UPC_THREAD_SIZE__=%d", UPC_PTS_THREAD_SIZE);
+  cpp_define (pfile, def_buf);
+  (void) sprintf (def_buf, "__UPC_PHASE_SIZE__=%d", UPC_PTS_PHASE_SIZE);
+  cpp_define (pfile, def_buf);
+  if (flag_upc_threads)
+    {
+      cpp_define (pfile, "__UPC_STATIC_THREADS__=1");
+      (void) sprintf (def_buf, "THREADS=%d", flag_upc_threads);
+      cpp_define (pfile, def_buf);
+    }
+  else
+    {
+      cpp_define (pfile, "__UPC_DYNAMIC_THREADS__=1");
+    }
+  if (flag_upc_pthreads && (upc_pthreads_model == upc_pthreads_tls_model))
+    {
+      cpp_define (pfile, "__UPC_PTHREADS_MODEL_TLS__=1");
+      if (flag_upc_pthreads_per_process)
+	{
+	  cpp_define (pfile, "__UPC_STATIC_PTHREADS__=1");
+	  (void) sprintf (def_buf, "PTHREADS=%d",
+			  flag_upc_pthreads_per_process);
+	  cpp_define (pfile, def_buf);
+	}
+      else
+	{
+	  cpp_define (pfile, "__UPC_DYNAMIC_PTHREADS__=1");
+	}
+    }
+  /* Collectives are supported. */
+  cpp_define (parse_in, "__UPC_COLLECTIVE__=1");
+  /* If instrumentation is enabled, then disable inlining of the runtime.  */
+  if (flag_upc_instrument)
+    flag_upc_inline_lib = 0;
+  /* If -f[no-]upc-inline-lib hasn't been asserted, force inlining of the
+     runtime library if optimization is enabled.  */
+  if (flag_upc_inline_lib < 0)
+    flag_upc_inline_lib = (optimize >= 1);
+  if (flag_upc_inline_lib)
+    cpp_define (parse_in, "__UPC_INLINE_LIB__=1");
+  /* UPC profiling capabilities are implemented.  */
+  cpp_define (parse_in, "__UPC_PUPC__=1");
+  /* UPC profiling instrumentation code will be generated.  */
+  if (flag_upc_instrument)
+    {
+      cpp_define (parse_in, "__UPC_PUPC_INST__=1");
+    }
+}
+
+/*  Initialize the handler table for the UPC pointer-to-shared
+    representation that was selected when the compiler
+    was configured.  */
+
+static void
+upc_pts_init (void)
+{
+#if HAVE_UPC_PTS_PACKED_REP
+    upc_pts = upc_pts_packed_ops;
+#elif HAVE_UPC_PTS_STRUCT_REP
+    upc_pts = upc_pts_struct_ops;
+#else
+#  error either HAVE_UPC_PTS_PACKED_REP or HAVE_UPC_PTS_STRUCT_REP must be defined.
+#endif
+  /* Define the various pre-defined types and values, like 'upc_shared_ptr_t'
+     that depend upon the representation of UPC pointer-to-shared type.  */
+  (*upc_pts.init) ();
+}
+
+/* Initialize the UPC-specific parts of the compiler.
+   This is called from upc_lang_init(), which in turn
+   called via the LANG_HOOKS_INIT per-language hook.  */
+
+static void
+upc_parse_init (void)
+{
+  set_lang_layout_decl_p (upc_lang_layout_decl_p);
+  set_lang_layout_decl (upc_lang_layout_decl);
+  upc_pts_init ();
+  unshared_vars =
+    htab_create_ggc (101, uid_tree_map_hash, uid_tree_map_eq, NULL);
+  upc_init_stmt_list = NULL;
+}
+
+/* For the given kind of UPC synchronization statement given
+   by SYNC_KIND (UPC_SYNC_NOTIFY_OP, UPC_SYNC_WAIT_OP,
+   or UPC_SYNC_BARRIER_OP), build a UPC_SYNC_STMT tree node,
+   and add it to the current statement list.  The value of
+   SYNC_EXPR will be non-null if an expression is present
+   in the UPC statement being compiled.  */
+
+tree
+upc_build_sync_stmt (location_t loc, tree sync_kind, tree sync_expr)
+{
+  return add_stmt (build_stmt (loc, UPC_SYNC_STMT, sync_kind, sync_expr));
+}
+
+/* Check the type of the operand passed to a
+   upc_*sizeof () operator.
+   
+   The type must *not* be:
+   - an error mark node
+   - an imcomplete type
+   - a function type
+   - a void type
+
+   The type *must* be a UPC 'shared' type.
+
+   UPC defines the following flavors of sizeof operators:
+   upc_blocksizeof, upc_elemsizeof, and upc_localsizeof.
+   These operations have similar syntax and constraints
+   as the "C" language sizeof operator.  */
+
+static int
+upc_sizeof_type_check (const char *op_name, tree type)
+{
+  enum tree_code code = TREE_CODE (type);
+  if (code == ERROR_MARK)
+    {
+      return 0;
+    }
+  else if (!COMPLETE_TYPE_P (type))
+    {
+      c_incomplete_type_error (NULL_TREE, type);
+      return 0;
+    }
+  else if (code == FUNCTION_TYPE)
+    {
+      error ("UPC operator %s applied to a function type", op_name);
+      return 0;
+    }
+  else if (code == VOID_TYPE)
+    {
+      error ("UPC operator %s applied to a void type", op_name);
+      return 0;
+    }
+  else if (!upc_shared_type_p (type))
+    {
+      error ("UPC operator %s applied to a non-shared type", op_name);
+      return 0;
+    }
+  return 1;
+}
+
+/* Compute the value of the `upc_blocksizeof' operator.
+   The UPC block size is the value of UPC's "layout qualifier".
+   For example:
+
+   Declaration				upc_blocksizef()
+   ----------- 				----------------
+   shared int A[5*THREADS];     	1 (default) 
+   shared [5] int A[5*THREADS];    	5
+   shared [] int A[5*100];      	0 (indefinite)
+   shared [*] int A[5*THREADS];     	5 (distributed by compiler) */
+
+tree
+upc_blocksizeof (location_t ARG_UNUSED (loc), tree type)
+{
+  tree block_factor = size_one_node;
+  if (!type || TREE_CODE (type) == ERROR_MARK)
+    return error_mark_node;
+  if (upc_sizeof_type_check ("upc_blocksizeof", type))
+    block_factor = upc_get_block_factor (type);
+  return block_factor;
+}
+
+/* Compute the value of the `upc_elemsizeof' operator.  */
+
+tree
+upc_elemsizeof (location_t loc, tree type)
+{
+  tree elem_size;
+
+  if (!(type && upc_sizeof_type_check ("upc_elemsizeof", type)))
+    return size_int (1);
+  elem_size = c_sizeof (loc, strip_array_types (type));
+  return elem_size;
+}
+
+/* Compute the value of the `upc_localsizeof' operator.
+   Per the language spec:
+   The upc_localsizeof operator returns the size, in bytes, of the
+   local portion of its operand, which may be a shared object or a
+   shared-qualified type.  It returns the same value on all threads; the
+   value is an upper bound of the size allocated with affinity to any
+   single thread and may include an unspecified amount of padding. The
+   result of upc_localsizeof is an integer constant.  */
+
+tree
+upc_localsizeof (location_t loc, tree type)
+{
+  tree block_factor, local_size, total_size;
+
+  if (!(type && upc_sizeof_type_check ("upc_localsizeof", type)))
+    return size_one_node;
+
+  /* for scalars, return sizeof */
+
+  if (TREE_CODE (type) != ARRAY_TYPE)
+    return c_sizeof (loc, type);
+
+  block_factor = upc_blocksizeof (loc, type);
+  block_factor = convert (bitsizetype, block_factor);
+  total_size = TYPE_SIZE (type);
+
+  if (integer_zerop (block_factor))
+    {
+      /* local size is total size, because the entire
+         object lives on a single thread.  This is the
+	 case for declarations of types with an "indefinite"
+	 layout qualifier.  For example, given:
+	   shared [] int A[100];
+         the value returned for upc_localszieof (A)
+	 will be: 100 * sizeof (int).  */
+      local_size = total_size;
+    }
+  else
+    {
+      tree elt_type, elt_size, n_elts;
+      tree t_factor, n_full_blocks;
+      tree n_full_blocks_per_thread, n_elts_in_full_blocks;
+      tree n_rem_elts, n_local_elts;
+      elt_type = strip_array_types (type);
+      if (!elt_type || TREE_CODE (elt_type) == ERROR_MARK)
+	return size_one_node;
+      elt_size = TYPE_SIZE (elt_type);
+      n_elts = size_binop (EXACT_DIV_EXPR, total_size, elt_size);
+      /* Use the worst case size, if compiling in a dynamic
+         threads environment.  The worst case size can
+         be derived by setting T_FACTOR to 1 in the calculations
+         that follow.  Otherwise T_FACTOR is equal to THREADS. */
+      t_factor = flag_upc_threads ? upc_num_threads () : size_one_node;
+      t_factor = convert (bitsizetype, t_factor);
+      n_full_blocks = size_binop (FLOOR_DIV_EXPR, n_elts, block_factor);
+      n_full_blocks_per_thread = size_binop (FLOOR_DIV_EXPR,
+					     n_full_blocks, t_factor);
+      n_elts_in_full_blocks = size_binop (MULT_EXPR,
+					  size_binop (MULT_EXPR,
+					       n_full_blocks_per_thread,
+					       t_factor),
+					  block_factor);
+      n_rem_elts = size_binop (MINUS_EXPR, n_elts, n_elts_in_full_blocks);
+      n_local_elts = size_binop (MULT_EXPR,
+				 n_full_blocks_per_thread, block_factor);
+      /* If any elements remain, add a full block size.  */
+      if (!integer_zerop (n_rem_elts))
+	n_local_elts = size_binop (PLUS_EXPR, n_local_elts, block_factor);
+      local_size = size_binop (MULT_EXPR, n_local_elts, elt_size);
+    }
+
+  /* Convert local size into bytes, and return result. */
+
+  local_size = convert (sizetype, local_size);
+  local_size = size_binop (CEIL_DIV_EXPR, local_size,
+			   size_int (BITS_PER_UNIT));
+  return local_size;
+}
+
+/****** UPC tree-related checks, and operations **************/
+
+/* Traverse the expression and return the number of times
+   THREADS is referenced.  This is used to check the restriction
+   on UPC shared array declarations, that the predefined THREADS
+   variable can be mentioned only once.  */
+
+static int
+recursive_count_upc_threads_refs (tree expr)
+{
+  enum tree_code code;
+  int i;
+  int count = 0;
+  if (expr == NULL_TREE)
+    return 0;
+  code = TREE_CODE (expr);
+  switch (TREE_CODE_CLASS (code))
+    {
+    case tcc_unary:
+    case tcc_binary:
+    case tcc_comparison:
+    case tcc_expression:
+    case tcc_reference:
+    case tcc_statement:
+      for (i = 0; i < TREE_CODE_LENGTH (code); i++)
+	count += recursive_count_upc_threads_refs (TREE_OPERAND (expr, i));
+      break;
+    case tcc_declaration:
+      if (expr == lookup_name (get_identifier ("THREADS")))
+	count = 1;
+      break;
+    default:
+      break;
+    }
+  return count;
+}
+
+/* Count the number of references to THREADS inside `expr'. */
+
+int
+count_upc_threads_refs (tree expr)
+{
+  return recursive_count_upc_threads_refs (expr);
+}
+
+/* Test that EXPR is an expression tree where THREADS appears on
+   the left or the right hand side of a multiply, in a series
+   of zero or more multiplies.  For proper operation, the caller
+   should ensure that THREADS is referenced only once,
+   by calling count_upc_threads_refs () prior to calling this routine. */
+
+int
+is_multiple_of_upc_threads (tree expr)
+{
+  enum tree_code code;
+  if (expr == NULL_TREE)
+    return 0;
+  if (expr == lookup_name (get_identifier ("THREADS")))
+    return 1;
+  code = TREE_CODE (expr);
+  if (code == MULT_EXPR)
+    return is_multiple_of_upc_threads (TREE_OPERAND (expr, 0))
+      | is_multiple_of_upc_threads (TREE_OPERAND (expr, 1));
+  if ((code == NOP_EXPR) || (code == NON_LVALUE_EXPR)
+      || (code == CONVERT_EXPR))
+    return is_multiple_of_upc_threads (TREE_OPERAND (expr, 0));
+  return 0;
+}
+
+/* Find all references to THREADS and change them into the constant `1'.
+   This is done so that fold () when applied to the dimension of a
+   UPC shared array will yield the local size of the array.  */
+
+void
+set_upc_threads_refs_to_one (tree * expr)
+{
+  enum tree_code code;
+  int i;
+  if (*expr == NULL_TREE)
+    return;
+  code = TREE_CODE (*expr);
+  switch (TREE_CODE_CLASS (code))
+    {
+    case tcc_unary:
+    case tcc_binary:
+    case tcc_comparison:
+    case tcc_expression:
+    case tcc_reference:
+    case tcc_statement:
+      for (i = 0; i < TREE_CODE_LENGTH (code); i++)
+	set_upc_threads_refs_to_one (&TREE_OPERAND (*expr, i));
+      break;
+    case tcc_declaration:
+      if (*expr == lookup_name (get_identifier ("THREADS")))
+	*expr = integer_one_node;
+      break;
+    default:
+      break;
+    }
+  return;
+}
+
+/* Return the blocking factor of the UPC shared type, 'type'.
+   If the blocking factor is NULL, then return the default blocking
+   factor of 1.  */
+
+tree
+upc_get_block_factor (const tree type)
+{
+  tree block_factor = size_one_node;
+  const tree elt_type = strip_array_types (type);
+  if (elt_type && (TREE_CODE (elt_type) != ERROR_MARK)
+      && TYPE_BLOCK_FACTOR (elt_type))
+    block_factor = TYPE_BLOCK_FACTOR (elt_type);
+  return block_factor;
+}
+
+/* Given a UPC layout qualifier, calculate the blocking factor
+   and the TYPE_BLOCK_FACTOR field of `type'.  The caller is responsible
+   for checking that the block factor is being applied to a
+   UPC shared type.  Return the new, augmented type. */
+
+tree
+upc_set_block_factor (const enum tree_code decl_kind,
+		      tree type, tree layout_qualifier)
+{
+  tree block_factor = NULL_TREE;
+
+  if (!type || (TREE_CODE (type) == ERROR_MARK))
+    return error_mark_node;
+
+  if (!layout_qualifier || (TREE_CODE (layout_qualifier) == ERROR_MARK))
+    return type;
+
+  if (TREE_CODE (type) == VOID_TYPE)
+    {
+      error ("UPC layout qualifier cannot be applied to a void type");
+      return type;
+    }
+
+  /* The layout qualifier is given as the subscript operand
+     of an array ref. */
+
+  if (TREE_CODE (layout_qualifier) != ARRAY_REF)
+    abort ();
+  layout_qualifier = TREE_OPERAND (layout_qualifier, 1);
+
+  if (layout_qualifier == NULL_TREE)
+    {
+      /* The layout qualifier is [], which is
+         equivalent to specifying [0].  */
+      block_factor = size_zero_node;
+    }
+  else if ((TREE_CODE (layout_qualifier) == INDIRECT_REF)
+	   && ((TREE_OPERAND (layout_qualifier, 0)) == NULL_TREE))
+    {
+      tree elt_size, elt_type, n_threads;
+      /* The layout qualifier is [*].  The compiler must calculate
+         a blocking factor that evenly distributes the array's
+	 elements over all the UPC threads.  */
+      if (!COMPLETE_TYPE_P (type))
+	{
+	  error
+	    ("UPC layout qualifier of the form [*] cannot be applied "
+	     "to an incomplete type");
+	  return type;
+	}
+      if (decl_kind == POINTER_TYPE)
+	{
+	  error
+	    ("UPC [*] qualifier may not be used in declaration of pointers");
+	  return type;
+	}
+      /* The blocking factor is given by this expression:
+         ( sizeof(a) / upc_elemsizeof(a) + THREADS - 1 ) / THREADS,
+         where 'a' is the array being distributed. */
+      elt_type = strip_array_types (type);
+      elt_size = TYPE_SIZE (elt_type);
+      if (UPC_TYPE_HAS_THREADS_FACTOR (type))
+	block_factor =
+	  size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type), elt_size);
+      else
+	{
+	  n_threads = convert (bitsizetype, upc_num_threads ());
+	  if (TREE_CODE (n_threads) != INTEGER_CST)
+	    {
+	      error ("a UPC layout qualifier of '[*]' requires that "
+		     "the array size is either an integral constant "
+		     "or an integral multiple of THREADS");
+	      block_factor = size_one_node;
+	    }
+	  else
+	    {
+	      block_factor = size_binop (CEIL_DIV_EXPR,
+				 size_binop (FLOOR_DIV_EXPR,
+					     TYPE_SIZE (type),
+					     elt_size),
+				 n_threads);
+	    }
+	}
+    }
+  else
+    {
+      STRIP_NOPS (layout_qualifier);
+      if (TREE_CODE (layout_qualifier) != INTEGER_CST)
+	error ("UPC layout qualifier is not an integral constant");
+      else
+	block_factor = fold (layout_qualifier);
+    }
+
+  if (!block_factor)
+    return type;
+
+  gcc_assert (TREE_CODE (block_factor) == INTEGER_CST);
+
+  /* If the blocking factor is 1, leave TYPE_BLOCK_FACTOR()
+     as NULL to normalize the representation.  The UPC spec
+     says all objects have a blocking factor of 1 if none
+     is specified, so we always represent a blocking factor
+     of 1 as a NULL. */
+
+  if (tree_int_cst_equal (block_factor, size_one_node))
+    return type;
+
+  if (tree_int_cst_compare (block_factor, integer_zero_node) < 0)
+    {
+      error ("UPC layout qualifier must be a non-negative integral constant");
+      return type;
+    }
+
+  if (TREE_OVERFLOW_P (block_factor)
+      || tree_low_cst (block_factor, 1) > (HOST_WIDE_INT) UPC_MAX_BLOCK_SIZE)
+    {
+      error ("the maximum UPC block size in this implementation is %ld",
+	     (long int) UPC_MAX_BLOCK_SIZE);
+      block_factor = size_one_node;
+    }
+
+  block_factor = convert (sizetype, block_factor);
+  type = build_variant_type_copy (type);
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      tree last = type;
+      tree inner;
+      while (TREE_CODE (TREE_TYPE (last)) == ARRAY_TYPE)
+	last = TREE_TYPE (last);
+      inner = build_variant_type_copy (TREE_TYPE (last));
+      /* Push the blocking factor down to the array
+         element type.  */
+      TYPE_BLOCK_FACTOR (inner) = block_factor;
+      TREE_TYPE (last) = inner;
+    }
+  else
+    {
+      TYPE_BLOCK_FACTOR (type) = block_factor;
+    }
+  return type;
+}
+
+/* If DECL is a UPC shared variable, make sure that it ends up
+   in the executable file.  */
+
+void
+upc_check_decl (tree decl)
+{
+  if (decl
+      && TREE_CODE (decl) == VAR_DECL
+      && TREE_TYPE (decl) && upc_shared_type_p (TREE_TYPE (decl)))
+    {
+      TREE_USED (decl) = 1;
+      TREE_ADDRESSABLE (decl) = 1;
+      TREE_STATIC (decl) = 1;
+      /* Work-around a problem where the front-end doesn't
+         properly process the used flags set above, on
+         static variables when flag_unit_at_a_time isn't set. */
+      if ((TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
+	  && !flag_unit_at_a_time
+	  && !lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
+	{
+	  tree used_id = get_identifier ("used");
+	  tree used_attrib = tree_cons (used_id, NULL_TREE, NULL_TREE);
+	  decl_attributes (&decl, used_attrib, 0);
+	}
+    }
+}
+
+/* Return TRUE if TYPE contains any references to UPC pointers-to-shared.  */
+
+static int
+contains_pts_refs_p (tree type)
+{
+  switch (TREE_CODE (type))
+    {
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      return upc_shared_type_p (TREE_TYPE (type));
+
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+      {
+	tree fields;
+	/* For a type that has fields, see if the fields have pointers.  */
+	for (fields = TYPE_FIELDS (type); fields;
+	     fields = TREE_CHAIN (fields))
+	  if (TREE_CODE (fields) == FIELD_DECL
+	      && contains_pts_refs_p (TREE_TYPE (fields)))
+	    return 1;
+	return 0;
+      }
+
+    case ARRAY_TYPE:
+      /* An array type contains pointers if its element type does.  */
+      return contains_pts_refs_p (TREE_TYPE (type));
+
+    default:
+      return 0;
+    }
+}
+
+/* Return TRUE if either DECL's type is a UPC shared type, or if
+   the value on the right-hand-side of the initialization has a
+   type that is a UPC shared type.  Initializations that meet
+   this criteria generally need to be actively initialized
+   at runtime.  */
+
+int
+upc_check_decl_init (tree decl, tree init)
+{
+  tree init_type;
+  int is_shared_var_decl_init;
+  int is_decl_init_with_shared_addr_refs;
+  int is_upc_decl;
+  if (!(decl && init && TREE_TYPE (decl) && TREE_TYPE (init)))
+    return 0;
+  if ((TREE_CODE (decl) == ERROR_MARK)
+      || (TREE_CODE (TREE_TYPE (decl)) == ERROR_MARK)
+      || (TREE_CODE (init) == ERROR_MARK)
+      || (TREE_CODE (TREE_TYPE (init)) == ERROR_MARK))
+    return 0;
+  init_type = TREE_TYPE (init);
+  is_shared_var_decl_init = (TREE_CODE (decl) == VAR_DECL)
+    && TREE_TYPE (decl) && upc_shared_type_p (TREE_TYPE (decl));
+  is_decl_init_with_shared_addr_refs = TREE_STATIC (decl)
+    && contains_pts_refs_p (init_type);
+  is_upc_decl = (is_shared_var_decl_init
+		 || is_decl_init_with_shared_addr_refs);
+  return is_upc_decl;
+}
+
+/* Add the initialization statement:
+     DECL = INIT;
+   onto a list, `upc_init_stmt_list', which collects
+   initializations that must be made at runtime.
+
+   This runtime initialization necessary because, in general, UPC
+   shared addresses are not known, or cannot be easily generated
+   at compile-time.  */
+
+void
+upc_decl_init (tree decl, tree init)
+{
+  tree init_stmt;
+  if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+    {
+      error ("initialization of UPC shared arrays "
+	     "is currently not supported");
+      return;
+    }
+  if (!upc_init_stmt_list)
+    upc_init_stmt_list = alloc_stmt_list ();
+  init_stmt = build2 (INIT_EXPR, void_type_node, decl, init);
+  append_to_statement_list_force (init_stmt, &upc_init_stmt_list);
+}
+
+/* Return TRUE if DECL's size is zero,
+   and DECL is a UPC shared array. */
+
+static int
+upc_lang_layout_decl_p (tree decl, tree type)
+{
+  int need_to_size_shared_array_decl = 0;
+  tree t = type;
+
+  if (decl && DECL_SIZE (decl) == 0)
+    {
+      while (t != NULL && TREE_CODE (t) == ARRAY_TYPE
+	     && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
+	t = TREE_TYPE (t);
+
+      need_to_size_shared_array_decl = t && TREE_CODE (t) == ARRAY_TYPE
+	&& upc_shared_type_p (TREE_TYPE (t));
+    }
+
+  return need_to_size_shared_array_decl;
+}
+
+
+/* Assign DECL to a specific linker section, if required.
+   UPC shared variables are given their own link section on
+   most target platforms, and if compiling in "pthreads mode"
+   regular local file scope variables are made thread local.  */
+
+void
+upc_set_decl_section (tree decl)
+{
+  if (TREE_SHARED (decl))
+    {
+#ifdef UPC_SHARED_SECTION_NAME
+      /* UPC shared variables are placed in their own shared section */
+      int slen = strlen (UPC_SHARED_SECTION_NAME);
+      DECL_SECTION_NAME (decl) = build_string (slen, UPC_SHARED_SECTION_NAME);
+#endif
+    }
+  else if (flag_upc_pthreads
+	   && ((TREE_STATIC (decl) && (DECL_SECTION_NAME (decl) == NULL_TREE))
+	       || DECL_EXTERNAL (decl)))
+    {
+      /* If we're compiling with -fupc-pthreads-model-tls asserted
+         and this is a regular "C" static scoped object which
+         is either declared in a system header file,
+         or is being compiled in a UPC setting,
+         then assign the object to the thread local storage
+	 (TLS) section.  */
+      extern int c_header_level;	/* in c-lex.c */
+      if (compiling_upc && (c_header_level <= 0))
+	{
+	  if (upc_pthreads_model == upc_pthreads_tls_model)
+	    {
+	      DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
+	      DECL_COMMON (decl) = 0;
+	    }
+	  else
+	    /* Only the TLS model is currently implemented. */
+	    gcc_unreachable ();
+	}
+    }
+}
+
+/* Given that TYPE describes a UPC shared array, and that DECL's size hasn't
+   been calculated, calculate the size of the type and adjust the size
+   attributes in DECL.  */
+
+static void
+upc_lang_layout_decl (tree decl, tree type)
+{
+  tree t = type;
+
+  while (TREE_CODE (t) == ARRAY_TYPE
+	 && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
+    t = TREE_TYPE (t);
+
+  if (TREE_CODE (t) == ARRAY_TYPE
+      && TYPE_SIZE (type) != NULL_TREE && upc_shared_type_p (TREE_TYPE (t)))
+    {
+      const tree elt_type = TREE_TYPE (t);
+      const tree elt_size = TYPE_SIZE (elt_type);
+      const tree block_factor = TYPE_BLOCK_FACTOR (elt_type)
+	? convert (bitsizetype, TYPE_BLOCK_FACTOR (elt_type)) : NULL;
+      if (block_factor && integer_zerop (block_factor))
+	{
+	  /* Allocate the entire UPC shared array on thread 0. */
+	  if (UPC_TYPE_HAS_THREADS_FACTOR (type))
+	    {
+	      const tree n_threads =
+		convert (bitsizetype, upc_num_threads ());
+	      DECL_SIZE (decl) = size_binop (MULT_EXPR, elt_size, n_threads);
+	    }
+	  else
+	    DECL_SIZE (decl) = TYPE_SIZE (type);
+	}
+      else
+	{
+	  const tree t_size = TYPE_SIZE (type);
+	  const tree n_elem = size_binop (FLOOR_DIV_EXPR, t_size, elt_size);
+	  const tree n_threads = convert (bitsizetype, upc_num_threads ());
+	  if (UPC_TYPE_HAS_THREADS_FACTOR (type))
+	    {
+	      if (block_factor)
+		{
+		  const tree blk_size = convert (bitsizetype, block_factor);
+		  tree t1, t2;
+		  t1 = size_binop (CEIL_DIV_EXPR, n_elem, blk_size);
+		  t2 = size_binop (MULT_EXPR, t1, blk_size);
+		  DECL_SIZE (decl) = size_binop (MULT_EXPR, t2, elt_size);
+		}
+	      else
+		DECL_SIZE (decl) = t_size;
+	    }
+	  else
+	    {
+	      /* We want to allocate ceiling (N_ELEM / N_THREADS)
+	         elements per thread, where N_ELEM is the total number of
+		 elements in the array.  If the array is blocked,
+		 then we allocate (ceiling (ceiling
+		   (N_ELEM / BLOCK_FACTOR) / N_THREADS)
+		   * block_factor) * N_ELEM_PER_THREAD.  */
+	      tree n_elem_per_thread;
+	      if (block_factor)
+		{
+		  tree block_count, blocks_per_thread;
+		  block_count = size_binop (CEIL_DIV_EXPR,
+					    n_elem, block_factor);
+		  blocks_per_thread = size_binop (CEIL_DIV_EXPR,
+						  block_count, n_threads);
+		  n_elem_per_thread = size_binop (MULT_EXPR,
+						  blocks_per_thread,
+						  block_factor);
+		}
+	      else
+		n_elem_per_thread = size_binop (CEIL_DIV_EXPR,
+						n_elem, n_threads);
+
+	      /* In the special case of an array of size 1, we know that
+	         we want a constant size no matter what N_THREADS is.  Make
+	         the size a constant so that declarations of the form:
+		   shared int x[1];
+	         will work in a dynamic THREADS compilation environment. */
+	      if (integer_onep (n_elem))
+		DECL_SIZE (decl) = elt_size;
+	      else
+		DECL_SIZE (decl) = size_binop (MULT_EXPR, n_elem_per_thread,
+					       elt_size);
+	    }
+	}
+      if (DECL_SIZE_UNIT (decl) == 0)
+	DECL_SIZE_UNIT (decl)
+	  =
+	  fold_convert (sizetype,
+			size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
+				    bitsize_unit_node));
+    }
+  else if (DECL_SIZE (decl) == 0)
+    {
+      DECL_SIZE (decl) = TYPE_SIZE (type);
+      DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);
+    }
+  else if (DECL_SIZE_UNIT (decl) == 0)
+    DECL_SIZE_UNIT (decl)
+      = fold_convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
+					    bitsize_unit_node));
+}
+
+/* Implement UPC's upc_forall 'affinity' test.
+   If the type of AFFINITY is a UPC pointer-to-shared type,
+   rewrite it into:
+     upc_threadof (AFFINITY) == MYTHREAD
+   If AFFINITY is an integer expression, then
+   rewrite it into:
+     (AFFINITY % THREADS) == MYTHREAD   */
+
+tree
+upc_affinity_test (location_t loc, tree affinity)
+{
+  tree mythread;
+  tree affinity_test;
+
+  gcc_assert (affinity != NULL_TREE);
+
+  if (TREE_CODE (TREE_TYPE (affinity)) == POINTER_TYPE
+      && upc_shared_type_p (TREE_TYPE (TREE_TYPE (affinity))))
+    {
+      /* We have a pointer to a UPC shared object and the affinity is
+         determined by the thread component of the address.  */
+      const tree pts_rep = build1 (VIEW_CONVERT_EXPR, upc_pts_rep_type_node,
+				   save_expr (affinity));
+      affinity = (*upc_pts.threadof) (loc, pts_rep);
+    }
+  else if (TREE_CODE (TREE_TYPE (affinity)) == INTEGER_TYPE)
+    {
+      tree n_threads = upc_num_threads ();
+      affinity =
+	build_binary_op (loc, FLOOR_MOD_EXPR, affinity, n_threads, 0);
+    }
+  else
+    {
+      error
+	("UPC affinity expression is neither an integer nor the address of "
+	 "a shared object");
+      return error_mark_node;
+    }
+
+  /* Generate an external reference to the "MYTHREAD" identifier.  */
+
+  mythread = lookup_name (get_identifier ("MYTHREAD"));
+  gcc_assert (mythread != NULL_TREE);
+  assemble_external (mythread);
+  TREE_USED (mythread) = 1;
+
+  /* AFFINITY now contains an integer value that can be compared to MY_THREAD.
+     Create an expression that tests if AFFINITY is equal to MYTHREAD. */
+
+  if (!c_types_compatible_p (TREE_TYPE (affinity), TREE_TYPE (mythread)))
+    affinity = convert (TREE_TYPE (mythread), affinity);
+  affinity_test = c_objc_common_truthvalue_conversion (loc,
+				   build_binary_op (loc, EQ_EXPR,
+						    affinity, mythread, 1));
+  /* Remove any MAYBE_CONST_EXPR's.  */
+
+  affinity_test = c_fully_fold (affinity_test, false, NULL);
+
+  return affinity_test;
+}
+
+/* Return an external reference to an integer variable maintained
+   by the compiler and runtime to track the dynamic nesting
+   of 'upc_forall' statements.  The variable's name is given by
+   UPC_FORALL_DEPTH_NAME.  */
+
+tree
+upc_rts_forall_depth_var (void)
+{
+  tree upc_forall_depth = lookup_name (
+                                  get_identifier (UPC_FORALL_DEPTH_NAME));
+  if (upc_forall_depth == NULL_TREE)
+    internal_error ("the UPC runtime variable '" UPC_FORALL_DEPTH_NAME "' "
+		    "cannot be located; this variable should be defined "
+		    "in a compiler-supplied include file");
+  assemble_external (upc_forall_depth);
+  TREE_USED (upc_forall_depth) = 1;
+  return upc_forall_depth;
+}
+
+/* Check for the possible need to convert UPC-specific types.
+   This routine must return 0, if it isn't absolutely certain
+   that the types are equivalent.  */
+
+int
+upc_types_compatible_p (tree x, tree y)
+{
+  /* If "C" doesn't think they're compatible neither does UPC.  */
+  if (!c_types_compatible_p (x, y))
+    return 0;
+  if (POINTER_TYPE_P (x) && POINTER_TYPE_P (y))
+    {
+      const tree ttx = TREE_TYPE (x);
+      const tree tty = TREE_TYPE (y);
+      if (upc_shared_type_p (ttx) && upc_shared_type_p (tty))
+	{
+	  tree bx, by, sx, sy;
+	  int x_has_zero_phase, y_has_zero_phase;
+	  int result;
+	  /* If both types are generic UPC pointers-to-shared,
+	     then they're compatible.  */
+	  if (VOID_TYPE_P (ttx) && VOID_TYPE_P (tty))
+	    return 1;
+	  /* Intermediate conversions to (shared void *) (defined
+	     to be a "generic pointer-to-shared" the UPC
+	     specification) cannot always be optimized away.
+	     For example,
+	       p1 = (shared void *) p2;
+	     preserves the phase of p2, when assigning to p1.
+	     We need to be conservative, and not consider conversions
+	     involving a generic UPC pointer-to-shared value to be
+	     equivalent.  */
+	  if (VOID_TYPE_P (ttx) != VOID_TYPE_P (tty))
+	    return 0;
+	  bx = upc_get_block_factor (ttx);
+	  by = upc_get_block_factor (tty);
+	  sx = TYPE_SIZE (ttx);
+	  sy = TYPE_SIZE (tty);
+	  x_has_zero_phase = (integer_zerop (bx) || integer_onep (bx));
+	  y_has_zero_phase = (integer_zerop (by) || integer_onep (by));
+	  /* Normalize type size so that 0 => NULL. */
+	  if (sx && integer_zerop (sx))
+	    sx = NULL_TREE;
+	  if (sy && integer_zerop (sy))
+	    sy = NULL_TREE;
+	  /* If the target types have the same UPC block size
+	     (or they both have a phase value of zero) 
+	     and the same size and the target types are
+	     otherwise compatible, then the pointer-to-shared
+	     types are compatible. */
+	  result = (tree_int_cst_equal (bx, by)
+		    || (x_has_zero_phase && y_has_zero_phase))
+	           && tree_int_cst_equal (sx, sy);
+	  return result;
+	}
+      /* If one operand has a UPC shared type,
+         and the other operand's type is not a UPC shared type,
+         then they aren't equivalent.  */
+      else if (upc_shared_type_p (ttx) != upc_shared_type_p (tty))
+	return 0;
+    }
+  else if (upc_shared_type_p (x) || upc_shared_type_p (y))
+    {
+      /* In UPC, blocking factors can be applied to
+         non-pointer objects/types. They're compatible
+         if the block sizes are equal.  */
+      const tree bx = upc_get_block_factor (x);
+      const tree by = upc_get_block_factor (y);
+      return tree_int_cst_equal (bx, by)
+	&& c_types_compatible_p (TYPE_MAIN_VARIANT (x),
+				 TYPE_MAIN_VARIANT (y));
+    }
+  /* C thinks they're compatible, and there are no special
+     UPC exceptions.  */
+  return 1;
+}
+
+/************* UPC SUPPORT *************/
+
+/* Return the value of THREADS.
+
+   UPC defines a reserved variable, THREADS, which returns the
+   number of threads that will be created when the UPC program
+   executes.  The value of threads can be specified at runtime via
+   the -fupc-threads-N switch, where N is an integer specifying
+   the number of threads.  When the value of THREADS is specified
+   at compile-time, this is called the "static threads compilation
+   environment".
+
+   In the static threads compilation environment, THREADS is a
+   pre-defined preprocessor macro with the value, N.
+
+   If no value for threads is given at compile-time, then the value
+   must be specified when the application program is executed.
+   This is method of establishing the value of THREADS is called
+   the "dynamic threads compilation environment".  */
+
+tree
+upc_num_threads (void)
+{
+  tree n;
+  n = flag_upc_threads ? size_int (flag_upc_threads)
+    : lookup_name (get_identifier ("THREADS"));
+  if (!n)
+    {
+      error ("the UPC-required THREADS variable is undefined; "
+	     "when compiling pre-processed source, "
+	     "all -fupc-* switches must be passed on the command line, "
+	     "asserting the same values as supplied when the "
+	     "original source file was preprocessed");
+      abort ();
+    }
+
+  return n;
+}
+
+/* Diagnose instances of UPC statements that were
+   defined in very early UPC language specifications and that
+   have since been deprecated.  */
+
+int
+upc_diagnose_deprecated_stmt (location_t loc, tree id)
+{
+  const char *name = IDENTIFIER_POINTER (id);
+  struct deprecated_stmt_entry
+  {
+    const char *deprecated_id;
+    const char *correct_id;
+  };
+  static const struct deprecated_stmt_entry deprecated_stmts[] =
+    { {"barrier", "upc_barrier"},
+      {"barrier_wait", "upc_wait"},
+      {"barrier_notify", "upc_notify"},
+      {"fence", "upc_fence"},
+      {"forall", "upc_forall"} };
+  const int n_deprecated_stmts = sizeof (deprecated_stmts)
+    / sizeof (struct deprecated_stmt_entry);
+  int i;
+  for (i = 0; i < n_deprecated_stmts; ++i)
+    {
+      if (!strcmp (name, deprecated_stmts[i].deprecated_id))
+	{
+	  error_at (loc, "%qs was supported in version 1.0 of the UPC "
+		    "specification, it has been deprecated, "
+		    "use %qs instead",
+		    name, deprecated_stmts[i].correct_id);
+	  return 1;
+	}
+    }
+  return 0;
+}
+
+/* Return a hash value given the argument P, which
+   is a pointer to a uid_tree_map.  The pointer
+   value is used directly to yield a hash value.  */
+
+static hashval_t
+uid_tree_map_hash (const void *p)
+{
+  const struct uid_tree_map *const map = (const struct uid_tree_map *) p;
+  return map->uid;
+}
+
+/* Return TRUE if the UID fields of two uid_tree_map
+   structures are equal.  This function is called by
+   the `htab_find_with_hash function' to match entries
+   in the `unshared_vars' hash table.  */
+
+static int
+uid_tree_map_eq (const void *va, const void *vb)
+{
+  const struct uid_tree_map *const a = (const struct uid_tree_map *) va;
+  const struct uid_tree_map *const b = (const struct uid_tree_map *) vb;
+  return a->uid == b->uid;
+}
+
+/* Return the "shadow variable" created for VAR that
+   has the same type as VAR, but with the UPC shared
+   qualifiers removed.  */
+
+static tree
+lookup_unshared_var (const tree var)
+{
+  const struct uid_tree_map *h;
+  struct uid_tree_map in;
+  unsigned int uid;
+  gcc_assert (var && TREE_CODE (var) == VAR_DECL);
+  uid = DECL_UID (var);
+  in.uid = uid;
+  in.to = NULL_TREE;
+  h = (struct uid_tree_map *) htab_find_with_hash (unshared_vars, &in, uid);
+  return h ? h->to : NULL_TREE;
+}
+
+#define UNSHARE_PREFIX "_u_"
+
+/* Return an identifier that will be used to declare the "shadow variable"
+   which has the same type as VAR, but with all UPC shared qualfiers
+   removed from the type.  The identifier has the same name as
+   that of VAR, prefixed with the string given by the
+   value of `UNSHARE_PREFIX'.  */
+
+static tree
+unshared_var_name (const tree var)
+{
+  const tree name = DECL_NAME (var);
+  const size_t len = IDENTIFIER_LENGTH (name);
+  char *tmp_name = (char *) alloca (len + sizeof (UNSHARE_PREFIX));
+  strcpy (tmp_name, UNSHARE_PREFIX);
+  strcat (tmp_name, IDENTIFIER_POINTER (name));
+  return get_identifier (tmp_name);
+}
+
+/* Create and return a "shadow variable" that has the same type as VAR,
+   but with all UPC shared qualifiers removed from the type.
+   The assembler name of this shadow variable is the same
+   as that of the original variable, VAR.  */
+
+static tree
+create_unshared_var (location_t loc, const tree var)
+{
+  tree u_name, u_type, u;
+  gcc_assert (var && TREE_CODE (var) == VAR_DECL);
+  u_name = unshared_var_name (var);
+  u_type = build_upc_unshared_type (TREE_TYPE (var));
+  u = build_decl (loc, VAR_DECL, u_name, u_type);
+  TREE_USED (u) = 1;
+  TREE_ADDRESSABLE (u) = 1;
+  TREE_PUBLIC (u) = TREE_PUBLIC (var);
+  TREE_STATIC (u) = TREE_STATIC (var);
+  DECL_ARTIFICIAL (u) = 1;
+  DECL_IGNORED_P (u) = 1;
+  DECL_EXTERNAL (u) = DECL_EXTERNAL (var);
+  DECL_SECTION_NAME (u) = DECL_SECTION_NAME (var);
+  DECL_CONTEXT (u) = DECL_CONTEXT (var);
+
+  /* Alias the unshared variable to the shared variable.  */
+
+  SET_DECL_ASSEMBLER_NAME (u, DECL_ASSEMBLER_NAME (var));
+
+  /* Make sure the variable is referenced.  */
+
+  mark_decl_referenced (var);
+  return u;
+}
+
+static void
+map_unshared_var (const tree var, const tree u_var)
+{
+  struct uid_tree_map *h;
+  unsigned int uid;
+  void **loc;
+  gcc_assert (var && TREE_CODE (var) == VAR_DECL);
+  gcc_assert (u_var && TREE_CODE (u_var) == VAR_DECL);
+  uid = DECL_UID (var);
+  h = ggc_alloc_uid_tree_map ();
+  h->uid = uid;
+  h->to = u_var;
+  loc = htab_find_slot_with_hash (unshared_vars, h, uid, INSERT);
+  *(struct uid_tree_map **) loc = h;
+}
+
+/* Return a tree node that evaluates to the address that the
+   linker assigns to the UPC shared variable, VAR.  This is not
+   the final location of the UPC shared variable.  The linker is
+   used only to lay out a given UPC thread's contribution to the
+   UPC shared global memory region.
+
+   The address expression returned will point to a "shadow
+   variable" declaration that is created from the UPC shared
+   variable declaration, VAR.  This shadow variable has the same
+   type and other attributes as VAR, with the UPS shared type
+   qualifiers removed.  */
+
+static tree
+unshared_var_addr (location_t loc, const tree var)
+{
+  tree unshared_var, addr;
+  unshared_var = lookup_unshared_var (var);
+  if (!unshared_var)
+    {
+      unshared_var = create_unshared_var (loc, var);
+      map_unshared_var (var, unshared_var);
+    }
+  addr = build_fold_addr_expr (unshared_var);
+  TREE_CONSTANT (addr) = 1;
+  TREE_READONLY (addr) = 1;
+  return addr;
+}
+
+/* Convert shared variable reference VAR into a UPC pointer-to-shared
+   value of the form {0, 0, &VAR} */
+
+tree
+upc_build_shared_var_addr (location_t loc, tree type, tree var)
+{
+  tree var_addr, val;
+  gcc_assert (TREE_CODE (var) == VAR_DECL && TREE_SHARED (var));
+  gcc_assert (TREE_CODE (type) == POINTER_TYPE
+	      && upc_shared_type_p (TREE_TYPE (type)));
+  /* Refer to a shadow variable that has the same type as VAR, but
+     with the shared qualifier removed.  */
+  var_addr = unshared_var_addr (loc, var);
+#ifdef HAVE_UPC_PTS_PACKED_REP
+  {
+    const tree char_ptr_type = build_pointer_type (char_type_node);
+    tree shared_vaddr_base;
+    /* Subtract off the shared section base address so that the
+       resulting quantity will fit into the vaddr field.  */
+    shared_vaddr_base =
+      identifier_global_value (get_identifier ("__upc_shared_start"));
+    if (!shared_vaddr_base)
+      shared_vaddr_base =
+	identifier_global_value (get_identifier ("UPCRL_shared_begin"));
+    if (!shared_vaddr_base)
+      fatal_error ("UPC shared section start address not found; "
+		   "cannot find a definition for either "
+		   "__upc_shared_start or UPCRL_shared_begin");
+    assemble_external (shared_vaddr_base);
+    TREE_USED (shared_vaddr_base) = 1;
+    shared_vaddr_base = build1 (ADDR_EXPR, char_ptr_type, shared_vaddr_base);
+    var_addr = build_binary_op (loc, MINUS_EXPR,
+				convert (ptrdiff_type_node, var_addr),
+				convert (ptrdiff_type_node,
+					 shared_vaddr_base), 0);
+  }
+#endif
+  val = (*upc_pts.build) (loc, type,
+			  var_addr, integer_zero_node, integer_zero_node);
+  return val;
+}
+
+/* Expand the pre/post increment/decrement of UPC pointer-to-shared
+   into its equivalent expression tree. */
+
+tree
+upc_pts_increment (location_t location ATTRIBUTE_UNUSED,
+		   enum tree_code code, tree arg)
+{
+  /* The result type is a pointer of the same type as the argument
+     type after dropping the shared qualifier (for PTS's that happen
+     to live in shared memory). */
+  tree stable_arg = stabilize_reference (arg);
+  tree val = (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
+    ? stable_arg : save_expr (stable_arg);
+  enum tree_code incr_op = (code == PREINCREMENT_EXPR
+			    || code == POSTINCREMENT_EXPR)
+    ? PLUS_EXPR : MINUS_EXPR;
+  tree incr_val, result;
+  incr_val = upc_pts_int_sum (location, incr_op, val, integer_one_node);
+  TREE_SIDE_EFFECTS (incr_val) = 1;
+  result = build_modify_expr (location, arg, NULL_TREE, NOP_EXPR,
+			      location, incr_val, NULL_TREE);
+  if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
+    result = build2 (COMPOUND_EXPR, TREE_TYPE (incr_val), result, val);
+  return result;
+}
+
+/* Return an expression that calculates the sum of a UPC
+   pointer-to-shared value and an integer value.  The sum
+   operator may be PLUS_EXPR or MINUS_EXPR.  The result is a
+   POINTER_PLUS_EXPR with a properly scaled integer operand.
+   This POINTER_PLUS_EXPR will be translated by the UPC lowering
+   pass into the sequence of operations dictated both by the
+   properties of the UPC pointer-to-shared type, and the UPC
+   pointer-to-shared representation.  */
+
+tree
+upc_pts_int_sum (location_t loc,
+		 enum tree_code resultcode, tree ptrop, tree intop)
+{
+
+  /* The result type is a pointer of the same type that is being added,
+     after dropping the UPC shared qualifier.  For example, this would
+     apply to UPC pointers-to-shared that happen to live in shared memory;
+     the result of the expression must not be UPC shared qualified.  */
+
+  const tree ttype = TREE_TYPE (ptrop);
+  const int shared_quals =
+    (TYPE_QUAL_SHARED | TYPE_QUAL_STRICT | TYPE_QUAL_RELAXED);
+  const int quals_minus_shared = TYPE_QUALS (ttype) & ~shared_quals;
+  const tree result_type = c_build_qualified_type (ttype, quals_minus_shared);
+  const tree result_targ_type = TREE_TYPE (result_type);
+  const tree base_type = strip_array_types (result_targ_type);
+  tree result;
+
+  if (TREE_CODE (result_targ_type) == VOID_TYPE)
+    error_at (loc, "UPC does not allow a pointer of type %<shared void *%> "
+	      "to be used in arithmetic");
+
+  /* We have a pointer to a UPC shared object.  For pointers to
+     simple objects, just build a "resultcode" tree with the intop and
+     let upc_genericize() handle the arithmetic correctly.  For pointers to
+     arrays, compute the number of elements represented by the intop
+     and build a "resultcode" tree with the ptrop and that number. */
+
+  if (result_targ_type != base_type)
+    {
+      tree elt_cnt;
+      gcc_assert (TREE_CODE (result_targ_type) == ARRAY_TYPE);
+      if (TREE_CODE (TYPE_SIZE (result_targ_type)) == INTEGER_CST)
+	{
+	  tree n_threads = convert (sizetype, upc_num_threads ());
+	  int size = TREE_INT_CST_LOW (TYPE_SIZE (result_targ_type));
+	  int elt_size = TREE_INT_CST_LOW (TYPE_SIZE (base_type));
+	  elt_cnt = size_int (size / elt_size);
+	  if (UPC_TYPE_HAS_THREADS_FACTOR (result_targ_type))
+	    elt_cnt = size_binop (MULT_EXPR, n_threads, elt_cnt);
+	}
+      else
+	{
+	  tree size = TYPE_SIZE (result_targ_type);
+	  tree elt_size = TYPE_SIZE (base_type);
+	  elt_cnt = build2 (EXACT_DIV_EXPR, sizetype, size, elt_size);
+	}
+      intop = convert (sizetype, intop);
+      intop = size_binop (MULT_EXPR, intop, elt_cnt);
+    }
+  gcc_assert (resultcode == PLUS_EXPR || resultcode == MINUS_EXPR);
+  if (resultcode == MINUS_EXPR)
+    intop = build1 (NEGATE_EXPR, TREE_TYPE (intop), intop);
+  intop = fold (intop);
+
+  /* POINTER_PLUS expects the operand to be sizetype, which
+     is potentially unsigned.  This will have to be dealt
+     with later, when expanding the UPC pointer-to-shared arithmetic.  */
+
+  intop = convert (sizetype, intop);
+  result = build2 (POINTER_PLUS_EXPR, result_type, ptrop, intop);
+
+  /* Although there may be some specific cases where the
+     addition of a constant integer to a UPC pointer-to-shared can
+     be calculated at compile-time, in the more general
+     cases the calculation must be made at runtime, so
+     we mark the resulting sum as non-constant.  This will
+     avoid situations where the compiler attempts to convert
+     things like &A[14] where A is a shared array into a
+     compile-time constant. */
+
+  TREE_CONSTANT (result) = 0;
+  return result;
+}
+
+/* Return an expression that calculates the difference between
+   two UPC pointers-to-shared values.  */
+
+tree
+upc_pts_diff (tree op0, tree op1)
+{
+  const tree target_type = TREE_TYPE (TREE_TYPE (op0));
+  tree result;
+
+  /* The two pointers must both point to shared objects.  */
+
+  if ((upc_shared_type_p (target_type)
+       && !upc_shared_type_p (TREE_TYPE (TREE_TYPE (op1))))
+      || (upc_shared_type_p (TREE_TYPE (TREE_TYPE (op1)))
+	  && !upc_shared_type_p (target_type)))
+    {
+      error ("attempt to take the difference of a UPC pointer-to-shared "
+	     "and a local pointer");
+      return size_one_node;
+    }
+  result = build2 (MINUS_EXPR, ptrdiff_type_node, op0, op1);
+  return result;
+}
+
+/* Return TRUE if EXP is a null UPC pointer-to-shared value.
+   (Call the representation-specific hook routine to
+   perform the check.)  */
+
+int
+upc_is_null_pts_p (tree exp)
+{
+  return (*upc_pts.is_null_p) (exp);
+}
+
+/* Return TRUE if the type of EXP is a UPC pointer-to-shared type.  */
+
+int
+upc_pts_is_valid_p (tree exp)
+{
+  tree type = TREE_TYPE (exp);
+  return (TREE_CODE (type) == POINTER_TYPE)
+    && upc_shared_type_p (TREE_TYPE (type));
+}
+
+static void
+upc_build_init_func (const tree stmt_list)
+{
+  tree init_func_id = get_identifier (UPC_INIT_DECLS_FUNC);
+  struct c_declspecs *specs;
+  struct c_typespec void_spec;
+  struct c_declarator *init_func_decl;
+  struct c_arg_info args;
+  tree init_func, fn_body;
+  location_t loc = input_location;
+  rtx init_func_symbol;
+  int decl_ok;
+  memset (&void_spec, '\0', sizeof (struct c_typespec));
+  void_spec.kind = ctsk_typedef;
+  void_spec.spec = lookup_name (get_identifier ("void"));
+  specs = declspecs_add_type (loc, build_null_declspecs (), void_spec);
+  init_func_decl = build_id_declarator (init_func_id);
+  init_func_decl->id_loc = loc;
+  memset (&args, '\0', sizeof (struct c_arg_info));
+  args.types = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
+  init_func_decl = build_function_declarator (&args, init_func_decl);
+  decl_ok = start_function (specs, init_func_decl, NULL_TREE);
+  gcc_assert (decl_ok);
+  store_parm_decls ();
+  init_func = current_function_decl;
+  DECL_SOURCE_LOCATION (current_function_decl) = loc;
+  TREE_PUBLIC (current_function_decl) = 0;
+  TREE_USED (current_function_decl) = 1;
+  DECL_SECTION_NAME (current_function_decl) =
+    build_string (strlen (UPC_INIT_SECTION_NAME), UPC_INIT_SECTION_NAME);
+  fn_body = c_begin_compound_stmt (true);
+  append_to_statement_list_force (stmt_list, &fn_body);
+  fn_body = c_end_compound_stmt (loc, fn_body, true);
+  add_stmt (fn_body);
+  finish_function ();
+  gcc_assert (DECL_RTL (init_func));
+  mark_decl_referenced (init_func);
+  DECL_PRESERVE_P (init_func) = 1;
+  upc_init_array_section =
+    get_section (UPC_INIT_ARRAY_SECTION_NAME, 0, NULL);
+  init_func_symbol = XEXP (DECL_RTL (init_func), 0);
+  assemble_addr_to_section (init_func_symbol, upc_init_array_section);
+}
+
+/* If the accumulated UPC initialization statement list is
+   not empty, then build (and define) the per-file UPC
+   global initialization function.  */
+
+static void
+upc_write_init_func (void)
+{
+  if (upc_init_stmt_list)
+    {
+      upc_build_init_func (upc_init_stmt_list);
+      upc_init_stmt_list = NULL;
+    }
+}
+
+/* Free the hash table used to map UPC VAR_DECL's
+   into the "unshared" shadow variables that were created
+   in order to establish the offset of a UPC shared
+   variable with the special linker section that is
+   created to collect the UPC shared variables.  */
+
+static void
+upc_free_unshared_var_table (void)
+{
+  if (unshared_vars)
+    {
+      htab_delete (unshared_vars);
+      unshared_vars = NULL;
+    }
+}
+
+/* Write out the UPC global initialization function, if required
+   and free the hash table used to track the "shadow" variables
+   that are created to generate addresses of UPC shared variables.
+
+   This function is called from c_common_parse_file(), just after
+   parsing the main source file.  */
+
+void
+upc_write_global_declarations (void)
+{
+  upc_write_init_func ();
+  upc_free_unshared_var_table ();
+}
+
+#include "gt-upc-upc-act.h"
Index: gcc/defaults.h
===================================================================
--- gcc/defaults.h	(.../trunk)	(revision 175584)
+++ gcc/defaults.h	(.../branches/gupc)	(revision 175735)
@@ -1339,4 +1339,67 @@ see the files COPYING3 and COPYING.RUNTI
 
 #endif /* GCC_INSN_FLAGS_H  */
 
+/* UPC section names and begin/end labels */
+
+/* Name of section used to assign addresses to shared data items */
+#ifndef UPC_SHARED_SECTION_NAME
+#define UPC_SHARED_SECTION_NAME "upc_shared"
+#endif
+
+/* Used by upc-crtbegin to define the beginning of the shared section */
+#ifndef UPC_SHARED_BEGIN_NAME
+#define UPC_SHARED_BEGIN_NAME __upc_shared_start
+#endif
+
+/* Used by upc-crtend to define the end of the shared section */
+#ifndef UPC_SHARED_END_NAME
+#define UPC_SHARED_END_NAME __upc_shared_end
+#endif
+
+/* Name of section used to hold info. describing how a UPC source file was compiled. */
+#ifndef UPC_PGM_INFO_SECTION_NAME
+#define UPC_PGM_INFO_SECTION_NAME "upc_pgm_info"
+#endif
+
+/* Used by upc-crtbegin to define the beginning of the shared section */
+#ifndef UPC_PGM_INFO_BEGIN_NAME
+#define UPC_PGM_INFO_BEGIN_NAME __upc_pgm_info_start
+#endif
+
+/* Used by upc-crtend to define the end of the shared section */
+#ifndef UPC_PGM_INFO_END_NAME
+#define UPC_PGM_INFO_END_NAME __upc_pgm_info_end
+#endif
+
+/* Name of section where UPC iniitialization routines are located.  */
+#ifndef UPC_INIT_SECTION_NAME
+#define UPC_INIT_SECTION_NAME "upc_init"
+#endif
+
+/* Used by upc-crtbegin to define the beginning of init. routines section */
+#ifndef UPC_INIT_BEGIN_NAME
+#define UPC_INIT_BEGIN_NAME __upc_init_start
+#endif
+
+/* Used by upc-crtend to define the beginning of init. routines section */
+#ifndef UPC_INIT_END_NAME
+#define UPC_INIT_END_NAME __upc_init_end
+#endif
+
+/* Name of section that holds an array of addresses that points to 
+   the UPC initialization routiones */
+#ifndef UPC_INIT_ARRAY_SECTION_NAME
+#define UPC_INIT_ARRAY_SECTION_NAME "upc_init_array"
+#endif
+
+/* Used by upc-crtbegin to define the beginning of UPC init. array ection.  */
+#ifndef UPC_INIT_ARRAY_BEGIN_NAME
+#define UPC_INIT_ARRAY_BEGIN_NAME __upc_init_array_start
+#endif
+
+/* Used by upc-crtend to define the beginning of UPC init. array section.  */
+#ifndef UPC_INIT_ARRAY_END_NAME
+#define UPC_INIT_ARRAY_END_NAME __upc_init_array_end
+#endif
+
 #endif  /* ! GCC_DEFAULTS_H */
Index: gcc/genopinit.c
===================================================================
--- gcc/genopinit.c	(.../trunk)	(revision 175584)
+++ gcc/genopinit.c	(.../branches/gupc)	(revision 175735)
@@ -213,6 +213,27 @@ static const char * const optabs[] =
   "set_optab_handler (cstore_optab, $A, CODE_FOR_$(cstore$a4$))",
   "set_optab_handler (ctrap_optab, $A, CODE_FOR_$(ctrap$a4$))",
   "set_optab_handler (push_optab, $A, CODE_FOR_$(push$a1$))",
+
+  /* UPC opcodes */
+  "set_optab_handler (get_optab, $A, CODE_FOR_$(get$a2$)",
+  "set_optab_handler (gets_optab, $A, CODE_FOR_$(gets$a2$)",
+  "set_optab_handler (put_optab, $A, CODE_FOR_$(put$a2$)",
+  "set_optab_handler (puts_optab, $A, CODE_FOR_$(puts$a2$)",
+  "set_optab_handler (xget_optab, $A, CODE_FOR_$(xget$a2$)",
+  "set_optab_handler (xgets_optab, $A, CODE_FOR_$(xgets$a2$)",
+  "set_optab_handler (xput_optab, $A, CODE_FOR_$(xput$a2$)",
+  "set_optab_handler (xputs_optab, $A, CODE_FOR_$(xputs$a2$)",
+
+  /* UPC profiled opcodes */
+  "set_optab_handler (getg_optab, $A, CODE_FOR_$(getg$a2$)",
+  "set_optab_handler (getsg_optab, $A, CODE_FOR_$(getsg$a2$)",
+  "set_optab_handler (putg_optab, $A, CODE_FOR_$(putg$a2$)",
+  "set_optab_handler (putsg_optab, $A, CODE_FOR_$(putsg$a2$)",
+  "set_optab_handler (xgetg_optab, $A, CODE_FOR_$(xgetg$a2$)",
+  "set_optab_handler (xgetsg_optab, $A, CODE_FOR_$(xgetsg$a2$)",
+  "set_optab_handler (xputg_optab, $A, CODE_FOR_$(xputg$a2$)",
+  "set_optab_handler (xputsg_optab, $A, CODE_FOR_$(xputsg$a2$)",
+
   "set_direct_optab_handler (reload_in_optab, $A, CODE_FOR_$(reload_in$a$))",
   "set_direct_optab_handler (reload_out_optab, $A, CODE_FOR_$(reload_out$a$))",
   "set_direct_optab_handler (movmem_optab, $A, CODE_FOR_$(movmem$a$))",
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(.../trunk)	(revision 175584)
+++ gcc/tree.c	(.../branches/gupc)	(revision 175735)
@@ -3502,6 +3502,9 @@ stabilize_reference (tree ref)
   TREE_READONLY (result) = TREE_READONLY (ref);
   TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
   TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
+  TREE_SHARED (result)  = TREE_SHARED (ref);
+  TREE_STRICT (result)  = TREE_STRICT (ref);
+  TREE_RELAXED (result) = TREE_RELAXED (ref);
 
   return result;
 }
@@ -3583,6 +3586,9 @@ stabilize_reference_1 (tree e)
   TREE_READONLY (result) = TREE_READONLY (e);
   TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e);
   TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);
+  TREE_SHARED (result)  = TREE_SHARED (e);
+  TREE_STRICT (result)  = TREE_STRICT (e);
+  TREE_RELAXED (result) = TREE_RELAXED (e);
 
   return result;
 }
@@ -3727,6 +3733,7 @@ build1_stat (enum tree_code code, tree t
       /* Whether a dereference is readonly has nothing to do with whether
 	 its operand is readonly.  */
       TREE_READONLY (t) = 0;
+      TREE_SHARED (t) = upc_shared_type_p (type);
       break;
 
     case ADDR_EXPR:
@@ -3742,6 +3749,12 @@ build1_stat (enum tree_code code, tree t
       if (TREE_CODE_CLASS (code) == tcc_reference
 	  && node && TREE_THIS_VOLATILE (node))
 	TREE_THIS_VOLATILE (t) = 1;
+      /* Drop the UPC "shared" type qualifier for
+         expressions involving UPC shared objects.  */ 
+      if (TREE_CODE_CLASS (code) == tcc_unary
+	  && node && !TYPE_P (node)
+	  && upc_shared_type_p (type))
+	TREE_TYPE (t) = build_upc_unshared_type (type);
       break;
     }
 
@@ -5644,6 +5657,9 @@ set_type_quals (tree type, int type_qual
   TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
   TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
   TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
+  TYPE_SHARED (type) = (type_quals & TYPE_QUAL_SHARED) != 0;
+  TYPE_STRICT (type) = (type_quals & TYPE_QUAL_STRICT) != 0;
+  TYPE_RELAXED (type) = (type_quals & TYPE_QUAL_RELAXED) != 0;
 }
 
 /* Returns true iff CAND is equivalent to BASE with TYPE_QUALS.  */
@@ -5655,6 +5671,9 @@ check_qualified_type (const_tree cand, c
 	  && TYPE_NAME (cand) == TYPE_NAME (base)
 	  /* Apparently this is needed for Objective-C.  */
 	  && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
+	  /* For UPC, the blocking factors have to be equal. */
+	  && tree_int_cst_equal (TYPE_BLOCK_FACTOR (cand),
+	                         TYPE_BLOCK_FACTOR (base))
 	  /* Check alignment.  */
 	  && TYPE_ALIGN (cand) == TYPE_ALIGN (base)
 	  && attribute_list_equal (TYPE_ATTRIBUTES (cand),
@@ -5732,6 +5751,40 @@ build_qualified_type (tree type, int typ
   return t;
 }
 
+/* Return a variant of TYPE, where all UPC qualifiers
+   have been removed.  */
+
+tree
+build_upc_unshared_type (tree type)
+{
+  tree u_type = type;
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      const tree elem_type = TREE_TYPE(type);
+      const tree u_elem_type = build_upc_unshared_type (elem_type);
+      if (u_elem_type != elem_type)
+        {
+          for (u_type = TYPE_MAIN_VARIANT (type);
+               u_type && TREE_TYPE(u_type) != u_elem_type;
+               u_type = TYPE_NEXT_VARIANT (u_type)) /* loop */;
+          if (!u_type)
+            {
+              u_type = build_variant_type_copy (type);
+              TREE_TYPE (u_type) = u_elem_type;
+            }
+        }
+    }
+  else
+    {
+      const int quals = TYPE_QUALS (type);
+      const int u_quals = quals & ~(TYPE_QUAL_SHARED
+                                    | TYPE_QUAL_RELAXED
+                                    | TYPE_QUAL_STRICT);
+      u_type = build_qualified_type (type, u_quals);
+    }
+  return u_type;
+}
+
 /* Create a variant of type T with alignment ALIGN.  */
 
 tree
@@ -7088,6 +7141,8 @@ build_pointer_type (tree to_type)
   addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
 					      : TYPE_ADDR_SPACE (to_type);
   enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
+  if (upc_shared_type_p (to_type))
+    pointer_mode = TYPE_MODE (upc_pts_rep_type_node);
   return build_pointer_type_for_mode (to_type, pointer_mode, false);
 }
 
@@ -11021,6 +11076,7 @@ static inline bool
 tree_nop_conversion (const_tree exp)
 {
   tree outer_type, inner_type;
+  int outer_is_pts_p, inner_is_pts_p;
 
   if (!CONVERT_EXPR_P (exp)
       && TREE_CODE (exp) != NON_LVALUE_EXPR)
@@ -11034,6 +11090,22 @@ tree_nop_conversion (const_tree exp)
   if (!inner_type)
     return false;
 
+  outer_is_pts_p = (POINTER_TYPE_P (outer_type)
+                    && upc_shared_type_p (TREE_TYPE (outer_type)));
+  inner_is_pts_p = (POINTER_TYPE_P (inner_type)
+                    && upc_shared_type_p (TREE_TYPE (inner_type)));
+
+  /* UPC pointer-to-shared types have special
+     equivalence rules that must be checked. */
+  if (outer_is_pts_p && inner_is_pts_p
+      && lang_hooks.types_compatible_p)
+    return lang_hooks.types_compatible_p (outer_type, inner_type);
+
+  /* UPC pointer-to-shared types are not interchangeable
+     with integral types.  */
+  if (outer_is_pts_p || inner_is_pts_p)
+    return false;
+  
   /* Use precision rather then machine mode when we can, which gives
      the correct answer even for submode (bit-field) types.  */
   if ((INTEGRAL_TYPE_P (outer_type)
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(.../trunk)	(revision 175584)
+++ gcc/tree.h	(.../branches/gupc)	(revision 175735)
@@ -462,8 +462,11 @@ struct GTY(()) tree_base {
   unsigned packed_flag : 1;
   unsigned user_align : 1;
   unsigned nameless_flag : 1;
+  unsigned upc_shared_flag : 1;
+  unsigned upc_strict_flag : 1;
+  unsigned upc_relaxed_flag : 1;
 
-  unsigned spare : 12;
+  unsigned spare : 9;
 
   /* This field is only used with type nodes; the only reason it is present
      in tree_base instead of tree_type is to save space.  The size of the
@@ -1169,6 +1172,29 @@ extern void omp_clause_range_check_faile
 #define COMPLETE_OR_UNBOUND_ARRAY_TYPE_P(NODE) \
   (COMPLETE_TYPE_P (TREE_CODE (NODE) == ARRAY_TYPE ? TREE_TYPE (NODE) : (NODE)))
 
+
+/* Record that we are processing a UPC shared array declaration
+   or type definition that refers to THREADS in its array dimension.*/
+#define UPC_TYPE_HAS_THREADS_FACTOR(TYPE) TYPE_LANG_FLAG_3 (TYPE)
+
+/* Return TRUE if TYPE is a UPC shared type.  For arrays,
+   the element type must be queried, because array types
+   are never qualified.  */
+#define upc_shared_type_p(TYPE) \
+  ((TYPE) && TYPE_P (TYPE) \
+   && TYPE_SHARED ((TREE_CODE (TYPE) != ARRAY_TYPE \
+                    ? (TYPE) : strip_array_types (TYPE))))
+
+/* Return TRUE if EXP is a conversion operation involving
+   UPC pointers-to-shared.  If either of the types involved
+   in the conversion is a UPC pointer-to-shared type, return TRUE.  */
+#define upc_pts_cvt_op_p(EXP) \
+  ((EXP) && ((POINTER_TYPE_P (TREE_TYPE (EXP)) \
+              && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (EXP, 0)))) \
+              && (upc_shared_type_p (TREE_TYPE (TREE_TYPE (EXP))) \
+                  || upc_shared_type_p (TREE_TYPE ( \
+	                TREE_TYPE (TREE_OPERAND (EXP, 0)))))))
+
 
 /* Define many boolean fields that all tree nodes have.  */
 
@@ -1347,6 +1373,14 @@ extern void omp_clause_range_check_faile
 #define DECL_UNSIGNED(NODE) \
   (DECL_COMMON_CHECK (NODE)->base.unsigned_flag)
 
+/* Convert tree flags to type qualifiers. */
+#define TREE_QUALS(NODE)			\
+  ((TREE_READONLY(NODE) * TYPE_QUAL_CONST) |	\
+   (TREE_THIS_VOLATILE(NODE) * TYPE_QUAL_VOLATILE) |	\
+   (TREE_SHARED(NODE) * TYPE_QUAL_SHARED) |	\
+   (TREE_STRICT(NODE) * TYPE_QUAL_STRICT) |	\
+   (TREE_RELAXED(NODE) * TYPE_QUAL_RELAXED))
+
 /* In integral and pointer types, means an unsigned type.  */
 #define TYPE_UNSIGNED(NODE) (TYPE_CHECK (NODE)->base.unsigned_flag)
 
@@ -1441,6 +1475,11 @@ extern void omp_clause_range_check_faile
 #define IDENTIFIER_TRANSPARENT_ALIAS(NODE) \
   (IDENTIFIER_NODE_CHECK (NODE)->base.deprecated_flag)
 
+/* UPC common tree flags */
+#define TREE_SHARED(NODE) ((NODE)->base.upc_shared_flag)
+#define TREE_STRICT(NODE) ((NODE)->base.upc_strict_flag)
+#define TREE_RELAXED(NODE) ((NODE)->base.upc_relaxed_flag)
+
 /* In fixed-point types, means a saturating type.  */
 #define TYPE_SATURATING(NODE) ((NODE)->base.saturating_flag)
 
@@ -2134,6 +2173,7 @@ struct GTY(()) tree_block {
 #define TYPE_SIZE_UNIT(NODE) (TYPE_CHECK (NODE)->type_common.size_unit)
 #define TYPE_POINTER_TO(NODE) (TYPE_CHECK (NODE)->type_common.pointer_to)
 #define TYPE_REFERENCE_TO(NODE) (TYPE_CHECK (NODE)->type_common.reference_to)
+#define TYPE_BLOCK_FACTOR(NODE) (TYPE_CHECK (NODE)->type_common.block_factor)
 #define TYPE_PRECISION(NODE) (TYPE_CHECK (NODE)->type_common.precision)
 #define TYPE_NAME(NODE) (TYPE_CHECK (NODE)->type_common.name)
 #define TYPE_NEXT_VARIANT(NODE) (TYPE_CHECK (NODE)->type_common.next_variant)
@@ -2242,6 +2282,15 @@ extern enum machine_mode vector_type_mod
    the term.  */
 #define TYPE_RESTRICT(NODE) (TYPE_CHECK (NODE)->type_common.restrict_flag)
 
+/* If nonzero, this type is `shared'-qualified, in the UPC dialect */
+#define TYPE_SHARED(NODE) (TYPE_CHECK (NODE)->base.upc_shared_flag)
+
+/* If nonzero, this type is `strict'-qualified, in the UPC dialect  */
+#define TYPE_STRICT(NODE) (TYPE_CHECK (NODE)->base.upc_strict_flag)
+
+/* If nonzero, this type is `relaxed'-qualified, in the UPC dialect  */
+#define TYPE_RELAXED(NODE) (TYPE_CHECK (NODE)->base.upc_relaxed_flag)
+
 /* If nonzero, type's name shouldn't be emitted into debug info.  */
 #define TYPE_NAMELESS(NODE) (TYPE_CHECK (NODE)->base.nameless_flag)
 
@@ -2253,10 +2302,14 @@ extern enum machine_mode vector_type_mod
    type.  */
 enum cv_qualifier
   {
-    TYPE_UNQUALIFIED   = 0x0,
-    TYPE_QUAL_CONST    = 0x1,
-    TYPE_QUAL_VOLATILE = 0x2,
-    TYPE_QUAL_RESTRICT = 0x4
+    TYPE_UNQUALIFIED   = 0x00,
+    TYPE_QUAL_CONST    = 0x01,
+    TYPE_QUAL_VOLATILE = 0x02,
+    TYPE_QUAL_RESTRICT = 0x04,
+    /* UPC qualifiers */
+    TYPE_QUAL_SHARED   = 0x10,
+    TYPE_QUAL_RELAXED  = 0x20,
+    TYPE_QUAL_STRICT   = 0x40
   };
 
 /* Encode/decode the named memory support as part of the qualifier.  If more
@@ -2276,13 +2329,24 @@ enum cv_qualifier
   ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST)			\
    | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE)		\
    | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)		\
+   | (TYPE_SHARED  (NODE) * TYPE_QUAL_SHARED)			\
+   | (TYPE_STRICT  (NODE) * TYPE_QUAL_STRICT)			\
+   | (TYPE_RELAXED (NODE) * TYPE_QUAL_RELAXED)			\
    | (ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (NODE))))
 
+/* The set of qualifiers pertinent to a FUNCTION_DECL node.  */
+#define TREE_FUNC_QUALS(NODE)				\
+  ((TREE_READONLY (NODE) * TYPE_QUAL_CONST)		\
+   | (TREE_THIS_VOLATILE (NODE) * TYPE_QUAL_VOLATILE))
+
 /* The same as TYPE_QUALS without the address space qualifications.  */
 #define TYPE_QUALS_NO_ADDR_SPACE(NODE)				\
   ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST)			\
    | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE)		\
-   | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT))
+   | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)		\
+   | (TYPE_SHARED  (NODE) * TYPE_QUAL_SHARED)			\
+   | (TYPE_STRICT  (NODE) * TYPE_QUAL_STRICT)			\
+   | (TYPE_RELAXED (NODE) * TYPE_QUAL_RELAXED))
 
 /* These flags are available for each language front end to use internally.  */
 #define TYPE_LANG_FLAG_0(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_0)
@@ -2405,6 +2469,9 @@ struct GTY(()) tree_type_common {
   alias_set_type alias_set;
   tree pointer_to;
   tree reference_to;
+  /* UPC: for block-distributed arrays */
+  tree block_factor;
+
   union tree_type_symtab {
     int GTY ((tag ("TYPE_SYMTAB_IS_ADDRESS"))) address;
     const char * GTY ((tag ("TYPE_SYMTAB_IS_POINTER"))) pointer;
@@ -2600,7 +2667,7 @@ struct GTY (()) tree_binfo {
 
 /* Nonzero if DECL represents a variable for the SSA passes.  */
 #define SSA_VAR_P(DECL)							\
-	(TREE_CODE (DECL) == VAR_DECL					\
+	((TREE_CODE (DECL) == VAR_DECL && !TREE_SHARED (DECL))          \
 	 || TREE_CODE (DECL) == PARM_DECL				\
 	 || TREE_CODE (DECL) == RESULT_DECL				\
 	 || (TREE_CODE (DECL) == SSA_NAME				\
@@ -3724,6 +3791,19 @@ enum tree_index
   TI_BOOLEAN_TYPE,
   TI_FILEPTR_TYPE,
 
+  TI_UPC_PTS_TYPE,
+  TI_UPC_PTS_REP_TYPE,
+  TI_UPC_PHASE_FIELD,
+  TI_UPC_THREAD_FIELD,
+  TI_UPC_VADDR_FIELD,
+  TI_UPC_PHASE_MASK,
+  TI_UPC_THREAD_MASK,
+  TI_UPC_VADDR_MASK,
+  TI_UPC_PHASE_SHIFT,
+  TI_UPC_THREAD_SHIFT,
+  TI_UPC_VADDR_SHIFT,
+  TI_UPC_NULL_PTS,
+
   TI_DFLOAT32_TYPE,
   TI_DFLOAT64_TYPE,
   TI_DFLOAT128_TYPE,
@@ -3883,6 +3963,21 @@ extern GTY(()) tree global_trees[TI_MAX]
 #define boolean_false_node		global_trees[TI_BOOLEAN_FALSE]
 #define boolean_true_node		global_trees[TI_BOOLEAN_TRUE]
 
+/* UPC pointer to shared object representation */
+/* The UPC type `void *'.  */
+#define upc_pts_type_node	global_trees[TI_UPC_PTS_TYPE]
+#define upc_pts_rep_type_node	global_trees[TI_UPC_PTS_REP_TYPE]
+#define upc_phase_field_node	global_trees[TI_UPC_PHASE_FIELD]
+#define upc_thread_field_node	global_trees[TI_UPC_THREAD_FIELD]
+#define upc_vaddr_field_node	global_trees[TI_UPC_VADDR_FIELD]
+#define upc_phase_mask_node	global_trees[TI_UPC_PHASE_MASK]
+#define upc_thread_mask_node	global_trees[TI_UPC_THREAD_MASK]
+#define upc_vaddr_mask_node	global_trees[TI_UPC_VADDR_MASK]
+#define upc_phase_shift_node	global_trees[TI_UPC_PHASE_SHIFT]
+#define upc_thread_shift_node	global_trees[TI_UPC_THREAD_SHIFT]
+#define upc_vaddr_shift_node	global_trees[TI_UPC_VADDR_SHIFT]
+#define upc_null_pts_node	global_trees[TI_UPC_NULL_PTS]
+
 /* The decimal floating point types. */
 #define dfloat32_type_node              global_trees[TI_DFLOAT32_TYPE]
 #define dfloat64_type_node              global_trees[TI_DFLOAT64_TYPE]
@@ -4651,6 +4746,7 @@ typedef struct record_layout_info_s
   int packed_maybe_necessary;
 } *record_layout_info;
 
+extern void set_lang_adjust_rli (void (*) (record_layout_info));
 extern record_layout_info start_record_layout (tree);
 extern tree bit_from_pos (tree, tree);
 extern tree byte_from_pos (tree, tree);
@@ -4710,6 +4806,11 @@ extern HOST_WIDE_INT int_bit_position (c
 extern tree byte_position (const_tree);
 extern HOST_WIDE_INT int_byte_position (const_tree);
 
+/* UPC related functions */
+extern void set_lang_layout_decl_p (int (*) (tree, tree));
+extern void set_lang_layout_decl (void (*) (tree, tree));
+extern tree build_upc_unshared_type (tree);
+
 /* Define data structures, macros, and functions for handling sizes
    and the various types used to represent sizes.  */
 
Index: gcc/tree-pass.h
===================================================================
--- gcc/tree-pass.h	(.../trunk)	(revision 175584)
+++ gcc/tree-pass.h	(.../branches/gupc)	(revision 175735)
@@ -238,9 +238,11 @@ struct dump_file_info
 #define PROP_gimple_lomp	(1 << 8)	/* lowered OpenMP directives */
 #define PROP_cfglayout	 	(1 << 9)	/* cfglayout mode on RTL */
 #define PROP_gimple_lcx		(1 << 10)       /* lowered complex */
+#define PROP_gimple_lupc	(1 << 11)	/* lowered UPC operations */
 
 #define PROP_trees \
-  (PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_lomp)
+  (PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh \
+   | PROP_gimple_lomp | PROP_gimple_lupc)
 
 /* To-do flags.  */
 #define TODO_dump_func			(1 << 0)
Index: gcc/c-config-lang.in
===================================================================
--- gcc/c-config-lang.in	(.../trunk)	(revision 175584)
+++ gcc/c-config-lang.in	(.../branches/gupc)	(revision 175735)
@@ -23,4 +23,4 @@
 # files used by C that have garbage collection GTY macros in them
 # which therefore need to be scanned by gengtype.c.
 
-gtfiles="\$(srcdir)/c-lang.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-parser.c \$(srcdir)/c-lang.h"
+gtfiles="\$(srcdir)/c-lang.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-upc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-parser.c \$(srcdir)/c-lang.h"
Index: gcc/gcc.c
===================================================================
--- gcc/gcc.c	(.../trunk)	(revision 175584)
+++ gcc/gcc.c	(.../branches/gupc)	(revision 175735)
@@ -673,11 +673,14 @@ proper position among the other output f
     %{flto} %{flto=*} %l " LINK_PIE_SPEC \
    "%X %{o*} %{e*} %{N} %{n} %{r}\
     %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}}\
+    %{!nostdlib:%{!nostartfiles:%{fupc-link:%:include(upc-crtbegin.spec)%(upc_crtbegin)}}}\
     %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
     %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}\
+    %{fupc-link:%:include(libupc.spec)%(link_upc)}\
     %(mflib) " STACK_SPLIT_SPEC "\
     %{fprofile-arcs|fprofile-generate*|coverage:-lgcov}\
     %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
+    %{!nostdlib:%{!nostartfiles:%{fupc-link:%:include(upc-crtend.spec)%(upc_crtend)}}}\
     %{!nostdlib:%{!nostartfiles:%E}} %{T*} }}}}}}"
 #endif
 
@@ -715,6 +718,9 @@ static const char *lib_spec = LIB_SPEC;
 static const char *mfwrap_spec = MFWRAP_SPEC;
 static const char *mflib_spec = MFLIB_SPEC;
 static const char *link_gomp_spec = "";
+static const char *upc_crtbegin_spec = "";
+static const char *link_upc_spec = "";
+static const char *upc_crtend_spec = "";
 static const char *libgcc_spec = LIBGCC_SPEC;
 static const char *endfile_spec = ENDFILE_SPEC;
 static const char *startfile_spec = STARTFILE_SPEC;
@@ -789,6 +795,9 @@ static const char *cc1_options =
  %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\
  %{coverage:-fprofile-arcs -ftest-coverage}";
 
+static const char *upc_options = "-lang-upc \
+ %{!fno-upc-pre-include:-include gcc-upc.h}";
+
 static const char *asm_options =
 "%{-target-help:%:print-asm-header()} "
 #if HAVE_GNU_AS
@@ -925,6 +934,7 @@ static const struct compiler default_com
   {".r", "#Ratfor", 0, 0, 0},
   {".p", "#Pascal", 0, 0, 0}, {".pas", "#Pascal", 0, 0, 0},
   {".java", "#Java", 0, 0, 0}, {".class", "#Java", 0, 0, 0},
+  {".upc", "#UPC", 0, 0, 0},
   {".zip", "#Java", 0, 0, 0}, {".jar", "#Java", 0, 0, 0},
   {".go", "#Go", 0, 1, 0},
   /* Next come the entries for C.  */
@@ -1184,6 +1194,7 @@ static struct spec_list static_specs[] =
   INIT_STATIC_SPEC ("trad_capable_cpp",		&trad_capable_cpp),
   INIT_STATIC_SPEC ("cc1",			&cc1_spec),
   INIT_STATIC_SPEC ("cc1_options",		&cc1_options),
+  INIT_STATIC_SPEC ("upc_options",		&upc_options),
   INIT_STATIC_SPEC ("cc1plus",			&cc1plus_spec),
   INIT_STATIC_SPEC ("link_gcc_c_sequence",	&link_gcc_c_sequence_spec),
   INIT_STATIC_SPEC ("link_ssp",			&link_ssp_spec),
@@ -1193,6 +1204,9 @@ static struct spec_list static_specs[] =
   INIT_STATIC_SPEC ("mfwrap",			&mfwrap_spec),
   INIT_STATIC_SPEC ("mflib",			&mflib_spec),
   INIT_STATIC_SPEC ("link_gomp",		&link_gomp_spec),
+  INIT_STATIC_SPEC ("upc_crtbegin",		&upc_crtbegin_spec),
+  INIT_STATIC_SPEC ("link_upc",			&link_upc_spec),
+  INIT_STATIC_SPEC ("upc_crtend",		&upc_crtend_spec),
   INIT_STATIC_SPEC ("libgcc",			&libgcc_spec),
   INIT_STATIC_SPEC ("startfile",		&startfile_spec),
   INIT_STATIC_SPEC ("cross_compile",		&cross_compile),
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(.../trunk)	(revision 175584)
+++ gcc/fold-const.c	(.../branches/gupc)	(revision 175735)
@@ -7699,6 +7699,23 @@ fold_unary_loc (location_t loc, enum tre
 	  unsigned int final_prec = TYPE_PRECISION (type);
 	  int final_unsignedp = TYPE_UNSIGNED (type);
 
+	  /* check for cases specific to UPC, involving pointer types */
+	  if (final_ptr || inter_ptr || inside_ptr)
+	    {
+	      int final_pts = final_ptr
+	                      && upc_shared_type_p (TREE_TYPE (type));
+	      int inter_pts = inter_ptr
+	                      && upc_shared_type_p (TREE_TYPE (inter_type));
+	      int inside_pts = inside_ptr
+	                      && upc_shared_type_p (TREE_TYPE (inside_type));
+	      if (!((final_pts && inter_pts)
+	             && TREE_TYPE (type) == TREE_TYPE (inter_type))
+                    || ((inter_pts && inside_pts)
+		         && (TREE_TYPE (inter_type)
+			     == TREE_TYPE (inside_type))))
+	        return NULL;
+	    }
+
 	  /* In addition to the cases of two conversions in a row
 	     handled below, if we are converting something to its own
 	     type via an object of identical or wider precision, neither
@@ -7856,7 +7873,10 @@ fold_unary_loc (location_t loc, enum tre
          when one of the new casts will fold away. Conservatively we assume
 	 that this happens when X or Y is NOP_EXPR or Y is INTEGER_CST. */
       if (POINTER_TYPE_P (type)
+          && !upc_shared_type_p (TREE_TYPE (type))
 	  && TREE_CODE (arg0) == POINTER_PLUS_EXPR
+	  && !upc_shared_type_p (TREE_TYPE (
+	                           TREE_TYPE (TREE_OPERAND (arg0, 0))))
 	  && (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
 	      || TREE_CODE (TREE_OPERAND (arg0, 0)) == NOP_EXPR
 	      || TREE_CODE (TREE_OPERAND (arg0, 1)) == NOP_EXPR))
@@ -7936,18 +7956,24 @@ fold_unary_loc (location_t loc, enum tre
       /* For integral conversions with the same precision or pointer
 	 conversions use a NOP_EXPR instead.  */
       if ((INTEGRAL_TYPE_P (type)
-	   || POINTER_TYPE_P (type))
+	   || (POINTER_TYPE_P (type)
+	       && !upc_shared_type_p (TREE_TYPE (type))))
 	  && (INTEGRAL_TYPE_P (TREE_TYPE (op0))
-	      || POINTER_TYPE_P (TREE_TYPE (op0)))
+	      || (POINTER_TYPE_P (TREE_TYPE (op0))
+	          && !upc_shared_type_p (TREE_TYPE (TREE_TYPE (op0)))))
 	  && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (op0)))
 	return fold_convert_loc (loc, type, op0);
 
       /* Strip inner integral conversions that do not change the precision.  */
       if (CONVERT_EXPR_P (op0)
 	  && (INTEGRAL_TYPE_P (TREE_TYPE (op0))
-	      || POINTER_TYPE_P (TREE_TYPE (op0)))
+	      || (POINTER_TYPE_P (TREE_TYPE (op0))
+	          && !upc_shared_type_p (TREE_TYPE (TREE_TYPE (op0)))))
 	  && (INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0)))
-	      || POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0))))
+	      || (POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0)))
+	          && !upc_shared_type_p (TREE_TYPE (
+		                          TREE_TYPE (
+					    TREE_OPERAND (op0, 0))))))
 	  && (TYPE_PRECISION (TREE_TYPE (op0))
 	      == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))))
 	return fold_build1_loc (loc, VIEW_CONVERT_EXPR,
@@ -9493,7 +9519,8 @@ fold_binary_loc (location_t loc,
 			    fold_convert_loc (loc, sizetype, arg0));
 
       /* (PTR +p B) +p A -> PTR +p (B + A) */
-      if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
+      if (TREE_CODE (arg0) == POINTER_PLUS_EXPR
+          && !upc_shared_type_p (TREE_TYPE (type)))
 	{
 	  tree inner;
 	  tree arg01 = fold_convert_loc (loc, sizetype, TREE_OPERAND (arg0, 1));
@@ -9539,6 +9566,14 @@ fold_binary_loc (location_t loc,
 			    fold_convert_loc (loc, type,
 					      TREE_OPERAND (arg0, 0)));
 
+      /* Disable further optimizations involving UPC shared pointers,
+         because integers are not interoperable with shared pointers.  */
+      if ((TREE_TYPE (arg0) && POINTER_TYPE_P (TREE_TYPE (arg0))
+          && upc_shared_type_p (TREE_TYPE (TREE_TYPE (arg0))))
+         || (TREE_TYPE (arg1) && POINTER_TYPE_P (TREE_TYPE (arg1))
+             && upc_shared_type_p (TREE_TYPE (TREE_TYPE (arg1)))))
+        return NULL_TREE;
+
       if (INTEGRAL_TYPE_P (type))
 	{
 	  /* Convert ~A + 1 to -A.  */
@@ -10016,6 +10051,16 @@ fold_binary_loc (location_t loc,
 	return fold_build2_loc (loc, PLUS_EXPR, type, op0,
 			    fold_convert_loc (loc, type,
 					      TREE_OPERAND (arg1, 0)));
+
+      /* Disable further optimizations involving UPC shared pointers,
+         because integers are not interoperable with shared pointers.
+	 (The test below also detects pointer difference between
+	 shared pointers, which cannot be folded.  */
+
+      if (TREE_TYPE (arg0) && POINTER_TYPE_P (TREE_TYPE (arg0))
+          && upc_shared_type_p (TREE_TYPE (TREE_TYPE (arg0))))
+        return NULL_TREE;
+
       /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
       if (TREE_CODE (arg0) == NEGATE_EXPR
 	  && (FLOAT_TYPE_P (type)
Index: gcc/dojump.c
===================================================================
--- gcc/dojump.c	(.../trunk)	(revision 175584)
+++ gcc/dojump.c	(.../branches/gupc)	(revision 175735)
@@ -404,6 +404,10 @@ do_jump (tree exp, rtx if_false_label, r
            < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0)))))
         goto normal;
     case NON_LVALUE_EXPR:
+      /* if a shared pointer conversion that will change representation,
+	 then we have to compare in the result type.  */
+      if (upc_pts_cvt_op_p (exp))
+	goto normal;
     case ABS_EXPR:
     case NEGATE_EXPR:
     case LROTATE_EXPR:
Index: gcc/c-objc-common.h
===================================================================
--- gcc/c-objc-common.h	(.../trunk)	(revision 175584)
+++ gcc/c-objc-common.h	(.../branches/gupc)	(revision 175735)
@@ -96,6 +96,10 @@ along with GCC; see the file COPYING3.  
 #undef LANG_HOOKS_WRITE_GLOBALS
 #define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
 
+/* Hook for lowering function body to GENERIC before finalization.  */
+#undef LANG_HOOKS_GENERICIZE
+#define LANG_HOOKS_GENERICIZE c_genericize
+
 /* Hooks for tree gimplification.  */
 #undef LANG_HOOKS_GIMPLIFY_EXPR
 #define LANG_HOOKS_GIMPLIFY_EXPR c_gimplify_expr
Index: gcc/c-tree.h
===================================================================
--- gcc/c-tree.h	(.../trunk)	(revision 175584)
+++ gcc/c-tree.h	(.../branches/gupc)	(revision 175735)
@@ -222,6 +222,9 @@ struct c_declspecs {
      NULL; attributes (possibly from multiple lists) will be passed
      separately.  */
   tree attrs;
+  /* For UPC, this is the blocking factor (layout qualifier).
+     For example, shared [10] int x;  */
+  tree upc_layout_qualifier;
   /* The storage class specifier, or csc_none if none.  */
   enum c_storage_class storage_class;
   /* Any type specifier keyword used such as "int", not reflecting
@@ -276,6 +279,12 @@ struct c_declspecs {
   BOOL_BITFIELD restrict_p : 1;
   /* Whether "_Sat" was specified.  */
   BOOL_BITFIELD saturating_p : 1;
+  /* Whether "shared" was specified.  */
+  BOOL_BITFIELD shared_p : 1;
+  /* Whether "strict" was specified.  */
+  BOOL_BITFIELD strict_p : 1;
+  /* Whether "relaxed" was specified.  */
+  BOOL_BITFIELD relaxed_p : 1;
   /* The address space that the declaration belongs to.  */
   addr_space_t address_space;
 };
@@ -352,7 +361,10 @@ struct c_declarator {
       BOOL_BITFIELD vla_unspec_p : 1;
     } array;
     /* For pointers, the qualifiers on the pointer type.  */
-    int pointer_quals;
+    struct {
+      int quals;
+      tree upc_layout_qual;
+    } pointer;
     /* For attributes.  */
     tree attrs;
   } u;
Index: gcc/config.in
===================================================================
--- gcc/config.in	(.../trunk)	(revision 175584)
+++ gcc/config.in	(.../branches/gupc)	(revision 175735)
@@ -1501,6 +1501,32 @@
 #endif
 
 
+/* Define to 1 if UPC link script is supported. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_UPC_LINK_SCRIPT
+#endif
+
+
+/* Define to 1 if UPC pointer-to-shared representation is a packed 64 bit
+   word. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_UPC_PTS_PACKED_REP
+#endif
+
+
+/* Define to 1 if UPC pointer-to-shared representation is a structure. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_UPC_PTS_STRUCT_REP
+#endif
+
+
+/* Define to 1 if the 'vaddr' field is the first field in the UPC
+   pointer-to-shared representation. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_UPC_PTS_VADDR_FIRST
+#endif
+
+
 /* Define if valgrind's valgrind/memcheck.h header is installed. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_VALGRIND_MEMCHECK_H
@@ -1754,6 +1780,27 @@
 #endif
 
 
+/* For packed UPC pointers-to-shared, the size of the phase field (in bits).
+   */
+#ifndef USED_FOR_TARGET
+#undef UPC_PTS_PHASE_SIZE
+#endif
+
+
+/* For packed UPC pointers-to-shared, the size of the thread field (in bits).
+   */
+#ifndef USED_FOR_TARGET
+#undef UPC_PTS_THREAD_SIZE
+#endif
+
+
+/* For packed UPC pointers-to-shared, the size of the address field (in bits).
+   */
+#ifndef USED_FOR_TARGET
+#undef UPC_PTS_VADDR_SIZE
+#endif
+
+
 /* Define if your assembler mis-optimizes .eh_frame data. */
 #ifndef USED_FOR_TARGET
 #undef USE_AS_TRADITIONAL_FORMAT
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(.../trunk)	(revision 175584)
+++ gcc/c-decl.c	(.../branches/gupc)	(revision 175735)
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3.  
 #include "timevar.h"
 #include "c-family/c-common.h"
 #include "c-family/c-objc.h"
+#include "c-family/c-upc.h"
 #include "c-family/c-pragma.h"
 #include "c-lang.h"
 #include "langhooks.h"
@@ -2218,6 +2219,13 @@ merge_decls (tree newdecl, tree olddecl,
   if (TREE_THIS_VOLATILE (newdecl))
     TREE_THIS_VOLATILE (olddecl) = 1;
 
+  if (TREE_SHARED (newdecl))
+    {
+      TREE_SHARED (olddecl) = 1;
+      if (TREE_CODE (newdecl) == VAR_DECL)
+	TREE_THIS_VOLATILE (newdecl) = 1;
+    }
+
   /* Merge deprecatedness.  */
   if (TREE_DEPRECATED (newdecl))
     TREE_DEPRECATED (olddecl) = 1;
@@ -2972,6 +2980,8 @@ undeclared_variable (location_t loc, tre
     }
   else
     {
+      if (upc_diagnose_deprecated_stmt (loc, id))
+        return;
       if (!objc_diagnose_private_ivar (id))
         error_at (loc, "%qE undeclared (first use in this function)", id);
       if (!already)
@@ -3767,6 +3777,9 @@ quals_from_declspecs (const struct c_dec
   int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
 	       | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
 	       | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
+	       | (specs->shared_p   ? TYPE_QUAL_SHARED : 0)
+	       | (specs->strict_p   ? TYPE_QUAL_STRICT : 0)
+	       | (specs->relaxed_p  ? TYPE_QUAL_RELAXED : 0)
 	       | (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
   gcc_assert (!specs->type
 	      && !specs->decl_attr
@@ -4295,7 +4308,22 @@ finish_decl (tree decl, location_t init_
 	    constant_expression_warning (DECL_SIZE (decl));
 	  else
 	    {
-	      error ("storage size of %q+D isn%'t constant", decl);
+	      if (upc_shared_type_p (TREE_TYPE (decl)))
+	        {
+		  gcc_assert (!flag_upc_threads);
+		  if (UPC_TYPE_HAS_THREADS_FACTOR (TREE_TYPE (decl)))
+		    error ("in the UPC dynamic translation environment, THREADS may "
+		            "not appear in declarations of shared arrays "
+			    "with indefinite block size; "
+		            "the storage size of %q+D cannot be calculated", decl);
+		  else
+		    error ("in the UPC dynamic translation environment, "
+		           "THREADS must appear exactly once in "
+		           "declarations of shared arrays; "
+		           "the storage size of %q+D cannot be calculated", decl);
+	        }
+	      else
+	        error ("storage size of %q+D isn%'t constant", decl);
 	      TREE_TYPE (decl) = error_mark_node;
 	    }
 	}
@@ -4334,6 +4362,10 @@ finish_decl (tree decl, location_t init_
       if (c_dialect_objc ())
 	objc_check_decl (decl);
 
+      /* Give UPC a chance to check the declaration.  */
+      if (c_dialect_upc ())
+	upc_check_decl (decl);
+
       if (asmspec)
 	{
 	  /* If this is not a static variable, issue a warning.
@@ -4836,6 +4868,9 @@ grokdeclarator (const struct c_declarato
   int constp;
   int restrictp;
   int volatilep;
+  int sharedp;
+  int strictp;
+  int relaxedp;
   int type_quals = TYPE_UNQUALIFIED;
   tree name = NULL_TREE;
   bool funcdef_flag = false;
@@ -4847,6 +4882,8 @@ grokdeclarator (const struct c_declarato
   int array_parm_static = 0;
   bool array_parm_vla_unspec_p = false;
   tree returned_attrs = NULL_TREE;
+  int upc_threads_ref = 0;	/* for static declarations of shared arrays */
+  tree layout_qualifier;
   bool bitfield = width != NULL;
   tree element_type;
   struct c_arg_info *arg_info = 0;
@@ -4945,6 +4982,8 @@ grokdeclarator (const struct c_declarato
 
   size_varies = C_TYPE_VARIABLE_SIZE (type) != 0;
 
+  upc_threads_ref = UPC_TYPE_HAS_THREADS_FACTOR (type);
+
   /* Diagnose defaulting to "int".  */
 
   if (declspecs->default_int_p && !in_system_header)
@@ -4989,6 +5028,34 @@ grokdeclarator (const struct c_declarato
   constp = declspecs->const_p + TYPE_READONLY (element_type);
   restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
   volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
+  sharedp = declspecs->shared_p + upc_shared_type_p (element_type);
+  strictp = declspecs->strict_p + TYPE_STRICT (element_type);
+  relaxedp = declspecs->relaxed_p + TYPE_RELAXED (element_type);
+  layout_qualifier = declspecs->upc_layout_qualifier;
+  if (TYPE_SHARED (element_type) && TYPE_BLOCK_FACTOR (element_type))
+    {
+      if (!layout_qualifier)
+	layout_qualifier = build4 (ARRAY_REF, NULL_TREE, NULL_TREE, 
+				   TYPE_BLOCK_FACTOR (element_type),
+				   NULL_TREE, NULL_TREE);
+      else
+        {
+          tree t = build_variant_type_copy (element_type);
+	  TYPE_BLOCK_FACTOR (t) = NULL_TREE;
+	  t = upc_set_block_factor (TREE_CODE (t), t, layout_qualifier);
+	  if (t != NULL_TREE && t != error_mark_node)
+	    {
+              const tree b1 = upc_get_block_factor (element_type);
+              const tree b2 = upc_get_block_factor (t);
+	      if (!tree_int_cst_equal (b1, b2))
+	        {
+                  error_at (loc, "UPC layout qualifier is incompatible with "
+	                         "the type specified by a typedef");
+		  layout_qualifier = NULL_TREE;
+	        }
+	    }
+	}
+    }
   as1 = declspecs->address_space;
   as2 = TYPE_ADDR_SPACE (element_type);
   address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
@@ -5001,7 +5068,20 @@ grokdeclarator (const struct c_declarato
 	pedwarn (loc, OPT_pedantic, "duplicate %<restrict%>");
       if (volatilep > 1)
 	pedwarn (loc, OPT_pedantic, "duplicate %<volatile%>");
-    }
+      if (sharedp > 1)
+	pedwarn (loc, OPT_pedantic, "duplicate %<shared%>");
+      if (strictp > 1)
+	pedwarn (loc, OPT_pedantic, "duplicate %<strict%>");
+      if (relaxedp > 1)
+	pedwarn (loc, OPT_pedantic, "duplicate %<relaxed%>");
+    }
+  if (strictp && relaxedp)
+    error_at (loc, "UPC shared variable %qE is declared "
+                   "both strict and relaxed", name);
+  if (strictp && !sharedp)
+    error_at (loc, "%qE is declared with UPC strict qualifier but not shared", name);
+  if (relaxedp && !sharedp)
+    error_at (loc, "%qE is declared with UPC relaxed qualifier but not shared", name);
 
   if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
     error_at (loc, "conflicting named address spaces (%s vs %s)",
@@ -5014,8 +5094,11 @@ grokdeclarator (const struct c_declarato
   type_quals = ((constp ? TYPE_QUAL_CONST : 0)
 		| (restrictp ? TYPE_QUAL_RESTRICT : 0)
 		| (volatilep ? TYPE_QUAL_VOLATILE : 0)
+		| (sharedp ? TYPE_QUAL_SHARED : 0)
+		| (strictp ? TYPE_QUAL_STRICT : 0)
+		| (relaxedp ? TYPE_QUAL_RELAXED : 0)
 		| ENCODE_QUAL_ADDR_SPACE (address_space));
-
+  
   /* Warn about storage classes that are invalid for certain
      kinds of declarations (parameters, typenames, etc.).  */
 
@@ -5108,7 +5191,7 @@ grokdeclarator (const struct c_declarato
 	  threadp = false;
 	}
     }
-
+    
   /* Now figure out the structure of the declarator proper.
      Descend through it, creating more complex types, until we reach
      the declared identifier (or NULL_TREE, in an absolute declarator).
@@ -5292,6 +5375,40 @@ grokdeclarator (const struct c_declarato
 			warn_variable_length_array (name, size);
 		      }
 		  }
+		else if (sharedp && count_upc_threads_refs (size))
+		  {
+		    /* We have a shared array with a non-constant
+		       dimension.  If the expression is a factor of
+		       THREADS, then we'll need to set the flag
+		       in the result type.  Otherwise, it is an error. */
+		    int n_thread_refs = count_upc_threads_refs (size);
+		    if (upc_threads_ref || n_thread_refs > 1)
+		      {
+			error_at (loc, "UPC shared array declaration references THREADS "
+			               "more than once; the size of %qE "
+				       "cannot be calculated", name);
+			size = integer_one_node;
+		      }
+		    else if (!is_multiple_of_upc_threads (size))
+		      {
+			error_at (loc, "UPC shared array dimension is not a simple multiple "
+			               "of THREADS; the size of %qE "
+				       "cannot be calculated.", name);
+			size = integer_one_node;
+		      }
+		    else
+		      {
+			upc_threads_ref = 1;
+			set_upc_threads_refs_to_one (&size);
+			size = fold (size);
+			if (TREE_CODE (size) != INTEGER_CST)
+			  {
+			    error_at (loc, "UPC forbids variable-size shared array %qE",
+				           name);
+			    size = integer_one_node;
+			  }
+		      }
+		  }
 		else if ((decl_context == NORMAL || decl_context == FIELD)
 			 && current_scope == file_scope)
 		  {
@@ -5452,6 +5569,18 @@ grokdeclarator (const struct c_declarato
 		    C_TYPE_VARIABLE_SIZE (type) = 1;
 		  }
 
+                if (upc_threads_ref)
+		  {
+		    /* We need a unique type copy here for UPC shared
+		       array types compiled in a dynamic threads enviroment
+		       that reference THREADS as a multiplier; to avoid
+		       setting the "has threads factor" bit in
+		       a re-used non- UPC shared array type node.  */
+		    if (size && TREE_CODE (size) == INTEGER_CST)
+		      type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+	            UPC_TYPE_HAS_THREADS_FACTOR (type) = 1; 
+                  }
+
 		/* The GCC extension for zero-length arrays differs from
 		   ISO flexible array members in that sizeof yields
 		   zero.  */
@@ -5507,6 +5636,8 @@ grokdeclarator (const struct c_declarato
 	      continue;
 
 	    size_varies = false;
+	    upc_threads_ref = 0;
+	    layout_qualifier = 0;
 
 	    /* Warn about some types functions can't return.  */
 	    if (TREE_CODE (type) == FUNCTION_TYPE)
@@ -5554,6 +5685,12 @@ grokdeclarator (const struct c_declarato
 		if (VOID_TYPE_P (type) && really_funcdef)
 		  pedwarn (loc, 0,
 			   "function definition has qualified void return type");
+                else if (type_quals & TYPE_QUAL_SHARED)
+                  {
+                    error_at (loc, "function definition has UPC shared qualified return type");
+                    type_quals &= ~(TYPE_QUAL_SHARED | TYPE_QUAL_STRICT
+                                    | TYPE_QUAL_RELAXED);
+                  }
 		else
 		  warning_at (loc, OPT_Wignored_qualifiers,
 			   "type qualifiers ignored on function return type");
@@ -5588,7 +5725,14 @@ grokdeclarator (const struct c_declarato
 		       "ISO C forbids qualified function types");
 	    if (type_quals)
 	      type = c_build_qualified_type (type, type_quals);
+
+	    /* Add UPC-defined block size, if supplied */
+	    if (layout_qualifier)
+	      type = upc_set_block_factor (POINTER_TYPE, type, layout_qualifier);
+
 	    size_varies = false;
+	    upc_threads_ref = 0;
+	    layout_qualifier = 0;
 
 	    /* When the pointed-to type involves components of variable size,
 	       care must be taken to ensure that the size evaluation code is
@@ -5628,7 +5772,9 @@ grokdeclarator (const struct c_declarato
 
 	    /* Process type qualifiers (such as const or volatile)
 	       that were given inside the `*'.  */
-	    type_quals = declarator->u.pointer_quals;
+	    type_quals = declarator->u.pointer.quals;
+	    layout_qualifier = declarator->u.pointer.upc_layout_qual;
+	    sharedp = ((type_quals & TYPE_QUAL_SHARED) != 0);
 
 	    declarator = declarator->declarator;
 	    break;
@@ -5699,6 +5845,13 @@ grokdeclarator (const struct c_declarato
   if (bitfield)
     check_bitfield_type_and_width (&type, width, name);
 
+  /* Check for UPC's layout qualifier.  */
+  if (layout_qualifier)
+    {
+      type = upc_set_block_factor (TREE_CODE (type), type, layout_qualifier);
+      layout_qualifier = 0;
+    }
+
   /* Did array size calculations overflow?  */
 
   if (TREE_CODE (type) == ARRAY_TYPE
@@ -5726,6 +5879,11 @@ grokdeclarator (const struct c_declarato
 		 "ISO C forbids qualified function types");
       if (type_quals)
 	type = c_build_qualified_type (type, type_quals);
+
+      /* Add UPC-defined block size, if supplied */
+      if (layout_qualifier)
+        type = upc_set_block_factor (TYPE_DECL, type, layout_qualifier);
+
       decl = build_decl (declarator->id_loc,
 			 TYPE_DECL, declarator->u.id, type);
       if (declspecs->explicit_signed_p)
@@ -5828,6 +5986,8 @@ grokdeclarator (const struct c_declarato
 			  "attributes in parameter array declarator ignored");
 
 	    size_varies = false;
+	    upc_threads_ref = 0;
+	    layout_qualifier = 0;
 	  }
 	else if (TREE_CODE (type) == FUNCTION_TYPE)
 	  {
@@ -5839,6 +5999,12 @@ grokdeclarator (const struct c_declarato
 	    type = build_pointer_type (type);
 	    type_quals = TYPE_UNQUALIFIED;
 	  }
+        else if (type_quals & TYPE_QUAL_SHARED)
+	  {
+	    error ("parameter declared with UPC shared qualifier");
+	    type_quals &= ~(TYPE_QUAL_SHARED | TYPE_QUAL_STRICT
+			    | TYPE_QUAL_RELAXED);
+	  }
 	else if (type_quals)
 	  type = c_build_qualified_type (type, type_quals);
 
@@ -5884,6 +6050,13 @@ grokdeclarator (const struct c_declarato
 	      error_at (loc, "unnamed field has incomplete type");
 	    type = error_mark_node;
 	  }
+        else if (type_quals & TYPE_QUAL_SHARED)
+	  {
+	    error_at (loc, "field %qE declared with UPC shared qualifier",
+		   name);
+	    type_quals &= ~(TYPE_QUAL_SHARED | TYPE_QUAL_STRICT
+			    | TYPE_QUAL_RELAXED);
+	  }
 	type = c_build_qualified_type (type, type_quals);
 	decl = build_decl (declarator->id_loc,
 			   FIELD_DECL, declarator->u.id, type);
@@ -5974,8 +6147,21 @@ grokdeclarator (const struct c_declarato
 	/* An uninitialized decl with `extern' is a reference.  */
 	int extern_ref = !initialized && storage_class == csc_extern;
 
+	if ((type_quals & TYPE_QUAL_SHARED)
+	     && !extern_ref
+	     && !((current_scope == file_scope)
+	           || (storage_class == csc_static)))
+          {
+	    error_at (loc, "UPC does not support shared auto variables");
+	  }
+
 	type = c_build_qualified_type (type, type_quals);
 
+	/* Block sizes don't make much sense for scalar variables,
+           but UPC permits them. */
+	if (layout_qualifier)
+	  type = upc_set_block_factor (VAR_DECL, type, layout_qualifier);
+
 	/* C99 6.2.2p7: It is invalid (compile-time undefined
 	   behavior) to create an 'extern' declaration for a
 	   variable if there is a global declaration that is
@@ -6021,6 +6207,11 @@ grokdeclarator (const struct c_declarato
 	else
 	  {
 	    TREE_STATIC (decl) = (storage_class == csc_static);
+	    /* UPC's 'shared' attribute implies that the storage
+	       is 'static' to the extent it is stored in
+	       memory.  */
+	    if (type_quals & TYPE_QUAL_SHARED)
+	      TREE_STATIC (decl) = 1;
 	    TREE_PUBLIC (decl) = extern_ref;
 	  }
 
@@ -6089,6 +6280,13 @@ grokdeclarator (const struct c_declarato
 		   "questionable in C++"),
 		  decl);
 
+    /* Shared variables are given their own link section on
+       most target platforms, and if compiling in pthreads mode
+       regular local file scope variables are made thread local. */
+    if ((TREE_CODE(decl) == VAR_DECL)
+        && !threadp && (TREE_SHARED (decl) || flag_upc_pthreads))
+      upc_set_decl_section (decl);
+
     return decl;
   }
 }
@@ -8287,7 +8485,8 @@ finish_function (void)
       if (!decl_function_context (fndecl))
 	{
 	  invoke_plugin_callbacks (PLUGIN_PRE_GENERICIZE, fndecl);
-	  c_genericize (fndecl);
+	  /* Lower to GENERIC form before finalization. */
+	  lang_hooks.genericize (fndecl);
 
 	  /* ??? Objc emits functions after finalizing the compilation unit.
 	     This should be cleaned up later and this conditional removed.  */
@@ -8593,18 +8792,21 @@ make_pointer_declarator (struct c_declsp
 {
   tree attrs;
   int quals = 0;
+  tree upc_layout_qual = 0;
   struct c_declarator *itarget = target;
   struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
   if (type_quals_attrs)
     {
       attrs = type_quals_attrs->attrs;
       quals = quals_from_declspecs (type_quals_attrs);
+      upc_layout_qual = type_quals_attrs->upc_layout_qualifier;
       if (attrs != NULL_TREE)
 	itarget = build_attrs_declarator (attrs, target);
     }
   ret->kind = cdk_pointer;
   ret->declarator = itarget;
-  ret->u.pointer_quals = quals;
+  ret->u.pointer.quals = quals;
+  ret->u.pointer.upc_layout_qual = upc_layout_qual;
   return ret;
 }
 
@@ -8619,6 +8821,7 @@ build_null_declspecs (void)
   ret->expr = 0;
   ret->decl_attr = 0;
   ret->attrs = 0;
+  ret->upc_layout_qualifier = 0;
   ret->typespec_word = cts_none;
   ret->storage_class = csc_none;
   ret->expr_const_operands = true;
@@ -8640,6 +8843,9 @@ build_null_declspecs (void)
   ret->const_p = false;
   ret->volatile_p = false;
   ret->restrict_p = false;
+  ret->shared_p = false;
+  ret->strict_p = false;
+  ret->relaxed_p = false;
   ret->saturating_p = false;
   ret->address_space = ADDR_SPACE_GENERIC;
   return ret;
@@ -8674,6 +8880,23 @@ declspecs_add_qual (struct c_declspecs *
   bool dupe = false;
   specs->non_sc_seen_p = true;
   specs->declspecs_seen_p = true;
+
+  /* A UPC layout qualifier is encoded as an ARRAY_REF,
+     further, it implies the presence of the 'shared' keyword. */
+  if (TREE_CODE (qual) == ARRAY_REF)
+    {
+      if (specs->upc_layout_qualifier)
+        {
+          error ("two or more layout qualifiers specified");
+	  return specs;
+        }
+      else
+        {
+          specs->upc_layout_qualifier = qual;
+          qual = ridpointers[RID_SHARED];
+        }
+    }
+
   gcc_assert (TREE_CODE (qual) == IDENTIFIER_NODE
 	      && C_IS_RESERVED_WORD (qual));
   i = C_RID_CODE (qual);
@@ -8691,6 +8914,18 @@ declspecs_add_qual (struct c_declspecs *
       dupe = specs->restrict_p;
       specs->restrict_p = true;
       break;
+    case RID_SHARED:
+      dupe = specs->shared_p;
+      specs->shared_p = true;
+      break;
+    case RID_STRICT:
+      dupe = specs->strict_p;
+      specs->strict_p = true;
+      break;
+    case RID_RELAXED:
+      dupe = specs->relaxed_p;
+      specs->relaxed_p = true;
+      break;
     default:
       gcc_unreachable ();
     }
Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac	(.../trunk)	(revision 175584)
+++ gcc/configure.ac	(.../branches/gupc)	(revision 175735)
@@ -693,6 +693,167 @@ else
 fi,
 objc_boehm_gc='')
 
+case ,${enable_languages}, in
+   *,upc,) lang_upc_enabled="yes" ;;
+   *) ;;
+esac
+
+AC_ARG_WITH([upc-pts],
+AS_HELP_STRING(
+  [--with-upc-pts={struct,packed}],
+  [choose the representation of a UPC pointer-to-shared]),
+[
+if test x"$lang_upc_enabled" = x"yes" ; then
+  case "$withval" in
+    packed|struct) upc_pts_rep="$withval" ;;
+    *) AC_MSG_ERROR([$withval is an invalid option to --with-upc-pts])
+      ;;
+  esac
+else
+  AC_MSG_WARN([--with-upc-pts is allowed only when UPC
+support has been enabled])
+fi
+],
+[
+if test x"$lang_upc_enabled" = x"yes" ; then
+  upc_pts_rep="packed"
+fi
+])
+
+
+# Perl is required for checking pts representation
+AC_CHECK_PROG(PERL, perl, perl)
+
+AC_ARG_WITH([upc-pts-vaddr-order],
+AS_HELP_STRING(
+[--with-upc-pts-vaddr-order={last,first}],
+[choose position of the address field in UPC pointer-to-shared representation]),
+[
+if test x"$lang_upc_enabled" = x"yes" ; then
+  upc_vaddr_order="$withval"
+  case "$upc_vaddr_order" in
+    first|last) ;;
+    *) AC_MSG_ERROR(
+	 [$withval is an invalid option to --with-upc-pts-vaddr-order]) ;;
+  esac
+else
+  AC_MSG_WARN([--upc-pts-vaddr-order is allowed only when UPC
+support has been enabled])
+fi
+],
+[
+if test x"$lang_upc_enabled" = x"yes" ; then
+  # Default UPC PTS vaddr order to "first"
+  upc_vaddr_order="first"
+fi
+])
+
+AC_ARG_WITH([packed-upc-pts-bits],
+AS_HELP_STRING(
+[--with-packed-upc-pts-bits=phase,thread,vaddr],
+[choose bit distribution in packed UPC pointer-to-shared representation]),
+[
+if test x"$lang_upc_enabled" = x"yes" ; then
+  if test x"$upc_pts_rep" = x"packed"; then
+    upc_packed_bits="$withval";
+    UPC_PTS_PHASE_SIZE=`echo "$withval" | $PERL -ne 'm/^(\d+),(\d+),(\d+)$/;
+						  print $1 if ($1+$2+$3 == 64) && $1>=1;'`
+    UPC_PTS_THREAD_SIZE=`echo "$withval" | $PERL -ne 'm/^(\d+),(\d+),(\d+)$/;
+						  print $2 if ($1+$2+$3 == 64) && $2>=1;'`
+    UPC_PTS_VADDR_SIZE=`echo "$withval" | $PERL -ne 'm/^(\d+),(\d+),(\d+)$/;
+						  print $3 if ($1+$2+$3 == 64) && $3>=20;'`
+    if test -z $UPC_PTS_PHASE_SIZE -o \
+	    -z $UPC_PTS_THREAD_SIZE -o \
+	    -z $UPC_PTS_VADDR_SIZE ; then
+      AC_MSG_ERROR([--with-packed-upc-pts-bits=phase,thread,vaddr requires
+  phase+thread+vaddr=64 and phase >= 1 and thread >= 1 and vaddr >= 20])
+    fi
+  else
+    AC_MSG_ERROR([--with-packed-upc-pts-bits is only supported for
+the packed UPC pointer-to-shared representation])
+  fi
+else
+  AC_MSG_WARN([--with-packed-upc-pts-bits is allowed only when UPC
+support has been enabled])
+fi
+],
+[
+if test x"$lang_upc_enabled" = x"yes" ; then
+  # GCC UPC packed pointer representation defaults.
+  UPC_PTS_PHASE_SIZE=20
+  UPC_PTS_THREAD_SIZE=10
+  UPC_PTS_VADDR_SIZE=34
+fi
+])
+
+AC_ARG_ENABLE(upc-link-script,
+AS_HELP_STRING(
+  [--enable-upc-link-script],
+  [enable UPC's use of a custom linker script;
+  this will define the UPC shared section as a no load section on
+  targets where this feature is supported (requires GNU LD)]),
+[
+if test x"$lang_upc_enabled" = x"yes" ; then
+  case $enableval in
+  yes | no) ;;
+  *)
+    AC_MSG_ERROR([--enable-upc-link-script accepts only yes or no.])
+  esac
+else
+  AC_MSG_WARN([--enable-upc-link-script is allowed only when UPC
+support has been enabled])
+fi
+],
+[
+if test x"$lang_upc_enabled" = x"yes" ; then
+  enable_upc_link_script=no
+fi
+])
+
+if test x"$lang_upc_enabled" = x"yes" ; then
+  AC_MSG_CHECKING([for UPC pointer-to-shared representation])
+  AC_MSG_RESULT([$upc_pts_rep])
+  case "$upc_pts_rep" in
+    packed)
+      AC_DEFINE(HAVE_UPC_PTS_PACKED_REP,[1],
+	[Define to 1 if UPC pointer-to-shared representation
+	 is a packed 64 bit word.])
+      ;;
+    struct)
+      AC_DEFINE(HAVE_UPC_PTS_STRUCT_REP,[1],
+	[Define to 1 if UPC pointer-to-shared representation
+	 is a structure.])
+      ;;
+  esac
+  AC_MSG_CHECKING([for UPC pointer-to-shared address field position])
+  AC_MSG_RESULT([$upc_vaddr_order])
+  if test x"$upc_vaddr_order" = x"first"; then
+    AC_DEFINE(HAVE_UPC_PTS_VADDR_FIRST,[1],
+      [Define to 1 if the 'vaddr' field is the first field
+in the UPC pointer-to-shared representation.])
+  fi
+  if test x"$upc_pts_rep" = x"packed"; then
+    AC_DEFINE_UNQUOTED(UPC_PTS_PHASE_SIZE,$UPC_PTS_PHASE_SIZE,
+      [For packed UPC pointers-to-shared,
+       the size of the phase field (in bits).])
+    AC_DEFINE_UNQUOTED(UPC_PTS_THREAD_SIZE,$UPC_PTS_THREAD_SIZE,
+      [For packed UPC pointers-to-shared,
+       the size of the thread field (in bits).])
+    AC_DEFINE_UNQUOTED(UPC_PTS_VADDR_SIZE,$UPC_PTS_VADDR_SIZE,
+      [For packed UPC pointers-to-shared,
+       the size of the address field (in bits).])
+    AC_MSG_CHECKING([for packed UPC pointer-to-shared layout])
+    AC_MSG_RESULT(
+      ["phase=${UPC_PTS_PHASE_SIZE},thread=${UPC_PTS_THREAD_SIZE},
+vaddr=${UPC_PTS_VADDR_SIZE}"])
+  fi
+  AC_MSG_CHECKING([for UPC link script support])
+  AC_MSG_RESULT($enable_upc_link_script)
+  if test "$enable_upc_link_script" = yes; then
+    AC_DEFINE(HAVE_UPC_LINK_SCRIPT, 1, [Define to 1 if UPC link script is supported.])
+  fi
+fi
+
 AC_ARG_WITH(dwarf2,
 [AS_HELP_STRING([--with-dwarf2], [force the default debug format to be DWARF 2])],
 dwarf2="$with_dwarf2",
@@ -770,7 +931,7 @@ AC_ARG_WITH(specs,
 AC_SUBST(CONFIGURE_SPECS)
 
 ACX_PKGVERSION([GCC])
-ACX_BUGURL([http://gcc.gnu.org/bugs.html])
+ACX_BUGURL([http://gccupc.org/bugs])
 
 # Sanity check enable_languages in case someone does not run the toplevel
 # configure # script.
Index: gcc/function.c
===================================================================
--- gcc/function.c	(.../trunk)	(revision 175584)
+++ gcc/function.c	(.../branches/gupc)	(revision 175735)
@@ -2024,6 +2024,17 @@ aggregate_value_p (const_tree exp, const
   if (flag_pcc_struct_return && AGGREGATE_TYPE_P (type))
     return 1;
 
+  /* Pointers-to-shared must be considered as aggregates for
+     the purpose of passing them as return values, but only
+     when the underlying mode of the representation would
+     require that its value be passed on the stack.
+     This occurs when using the 'struct' representation
+     of a shared pointer.  */
+  if (flag_pcc_struct_return && POINTER_TYPE_P (type)
+      && upc_shared_type_p (TREE_TYPE (type))
+      && AGGREGATE_TYPE_P (upc_pts_rep_type_node))
+    return 1;
+
   if (targetm.calls.return_in_memory (type, fntype))
     return 1;
 
Index: gcc/langhooks.c
===================================================================
--- gcc/langhooks.c	(.../trunk)	(revision 175584)
+++ gcc/langhooks.c	(.../branches/gupc)	(revision 175735)
@@ -267,7 +267,9 @@ lhd_tree_dump_type_quals (const_tree t)
 int
 lhd_gimplify_expr (tree *expr_p ATTRIBUTE_UNUSED,
 		   gimple_seq *pre_p ATTRIBUTE_UNUSED,
-		   gimple_seq *post_p ATTRIBUTE_UNUSED)
+		   gimple_seq *post_p ATTRIBUTE_UNUSED,
+	           bool (* gimple_test_f) (tree) ATTRIBUTE_UNUSED,
+		   int fallback ATTRIBUTE_UNUSED)
 {
   return GS_UNHANDLED;
 }
Index: gcc/langhooks.h
===================================================================
--- gcc/langhooks.h	(.../trunk)	(revision 175584)
+++ gcc/langhooks.h	(.../branches/gupc)	(revision 175735)
@@ -428,9 +428,19 @@ struct lang_hooks
   /* Determine if a tree is a function parameter pack.  */
   bool (*function_parameter_pack_p) (const_tree);
 
+  /* Genericize before finalization (called from finish_function()).
+     Perform lowering of function bodies from language dependent form
+     to language independent (GENERIC) form.  */
+  void (*genericize) (tree);
+
   /* Perform language-specific gimplification on the argument.  Returns an
      enum gimplify_status, though we can't see that type here.  */
-  int (*gimplify_expr) (tree *, gimple_seq *, gimple_seq *);
+  int (*gimplify_expr) (tree *, gimple_seq *, gimple_seq *,
+                        bool (*) (tree), int);
+
+  /* Perform language-specific instrumentation of a function.
+     (called from gimplify_function_tree()).  */
+  void (*instrument_func) (tree);
 
   /* Do language specific processing in the builtin function DECL  */
   tree (*builtin_function) (tree decl);
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	(.../trunk)	(revision 175584)
+++ gcc/stor-layout.c	(.../branches/gupc)	(revision 175735)
@@ -509,6 +509,29 @@ mode_for_array (tree elem_type, tree siz
   return mode_for_size_tree (size, MODE_INT, limit_p);
 }
 
+/* Hook for a front-end function that tests to see if a declared
+   object's size needs to be calculated in a language defined way */
+
+int (*lang_layout_decl_p)(tree, tree) = 0;
+
+void
+set_lang_layout_decl_p (int (*f)(tree, tree))
+{
+  lang_layout_decl_p = f;
+}
+
+/* Hook for a front-end function that can size a declared
+   object, when the size is unknown at the time that
+   `layout_type' is called. */
+
+void (*lang_layout_decl) (tree, tree) = 0;
+
+void
+set_lang_layout_decl (void (*f) (tree, tree))
+{
+  lang_layout_decl = f;
+}
+
 /* Subroutine of layout_decl: Force alignment required for the data type.
    But if the decl itself wants greater alignment, don't override that.  */
 
@@ -569,7 +592,11 @@ layout_decl (tree decl, unsigned int kno
   if (DECL_MODE (decl) == VOIDmode)
     DECL_MODE (decl) = TYPE_MODE (type);
 
-  if (DECL_SIZE (decl) == 0)
+  if (lang_layout_decl_p && (*lang_layout_decl_p) (decl, type))
+    {
+      (*lang_layout_decl) (decl, type);
+    }
+  else if (DECL_SIZE (decl) == 0)
     {
       DECL_SIZE (decl) = TYPE_SIZE (type);
       DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(.../trunk)	(revision 175584)
+++ gcc/c-typeck.c	(.../branches/gupc)	(revision 175735)
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  
 #include "bitmap.h"
 #include "gimple.h"
 #include "c-family/c-objc.h"
+#include "c-family/c-upc.h"
 
 /* Possible cases of implicit bad conversions.  Used to select
    diagnostic messages in convert_for_assignment.  */
@@ -78,6 +79,7 @@ static int type_lists_compatible_p (cons
 static tree lookup_field (tree, tree);
 static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
 			      tree);
+static tree c_pointer_int_sum (location_t, enum tree_code, tree, tree);
 static tree pointer_diff (location_t, tree, tree);
 static tree convert_for_assignment (location_t, tree, tree, tree,
 				    enum impl_conv, bool, tree, tree, int);
@@ -307,6 +309,7 @@ addr_space_superset (addr_space_t as1, a
 static tree
 qualify_type (tree type, tree like)
 {
+  tree result_type;
   addr_space_t as_type = TYPE_ADDR_SPACE (type);
   addr_space_t as_like = TYPE_ADDR_SPACE (like);
   addr_space_t as_common;
@@ -320,10 +323,24 @@ qualify_type (tree type, tree like)
 	     type, like);
     }
 
-  return c_build_qualified_type (type,
-				 TYPE_QUALS_NO_ADDR_SPACE (type)
-				 | TYPE_QUALS_NO_ADDR_SPACE (like)
-				 | ENCODE_QUAL_ADDR_SPACE (as_common));
+  result_type = c_build_qualified_type (type,
+			   TYPE_QUALS_NO_ADDR_SPACE (type)
+			   | TYPE_QUALS_NO_ADDR_SPACE (like)
+			   | ENCODE_QUAL_ADDR_SPACE (as_common));
+
+  if (upc_shared_type_p (result_type))
+    {
+      tree b1 = TYPE_BLOCK_FACTOR (type);
+      tree b2 = TYPE_BLOCK_FACTOR (like);
+      if (!b1 || (b2 && tree_int_cst_equal (b1, b2)))
+        TYPE_BLOCK_FACTOR (result_type) = b2;
+      else if (b1 && !b2)
+        TYPE_BLOCK_FACTOR (result_type) = b1;
+      else
+        gcc_unreachable ();
+    }
+
+  return result_type;
 }
 
 /* Return true iff the given tree T is a variable length array.  */
@@ -664,8 +681,34 @@ common_pointer_type (tree t1, tree t2)
     gcc_unreachable ();
 
   target_quals |= ENCODE_QUAL_ADDR_SPACE (as_common);
+  t2 = c_build_qualified_type (target, target_quals);
 
-  t1 = build_pointer_type (c_build_qualified_type (target, target_quals));
+  if (upc_shared_type_p (t2))
+    {
+      const tree elem_type = strip_array_types (pointed_to_1);
+      if (TYPE_BLOCK_FACTOR (elem_type))
+        {
+	  t2 = build_variant_type_copy (t2);
+	  if (TREE_CODE (t2) == ARRAY_TYPE)
+	    {
+	      tree last = t2;
+	      tree inner;
+	      while (TREE_CODE (TREE_TYPE (last)) == ARRAY_TYPE)
+		last = TREE_TYPE (last);
+	      inner = build_variant_type_copy (TREE_TYPE (last));
+	      /* Push the blocking factor down to the array
+		 element type.  */
+	      TYPE_BLOCK_FACTOR (inner) = TYPE_BLOCK_FACTOR (elem_type);
+	      TREE_TYPE (last) = inner;
+	    }
+	  else
+	    {
+	      TYPE_BLOCK_FACTOR (t2) = TYPE_BLOCK_FACTOR (elem_type);
+	    }
+	}
+    }
+
+  t1 = build_pointer_type (t2);
   return build_type_attribute_variant (t1, attributes);
 }
 
@@ -1066,6 +1109,13 @@ comptypes_internal (const_tree type1, co
   if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
     return 0;
 
+  /* If the type is UPC qualified, the block sizes have
+     to be equal.  The block sizes are either NULL
+     or are the same integer constant.  */
+  if ((TYPE_QUALS (t1) & TYPE_QUAL_SHARED)
+      && (TYPE_BLOCK_FACTOR (t1) != TYPE_BLOCK_FACTOR (t2)))
+    return 0;
+
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
@@ -1953,6 +2003,10 @@ default_conversion (tree exp)
 
   /* Functions and arrays have been converted during parsing.  */
   gcc_assert (code != FUNCTION_TYPE);
+
+  if (code == ARRAY_TYPE && upc_shared_type_p (type))
+    return array_to_pointer_conversion (input_location, exp);
+
   if (code == ARRAY_TYPE)
     return exp;
 
@@ -2178,6 +2232,36 @@ build_component_ref (location_t loc, tre
 	      || (use_datum_quals && TREE_THIS_VOLATILE (datum)))
 	    TREE_THIS_VOLATILE (ref) = 1;
 
+          if (TREE_SHARED (datum))
+           {
+	     tree ref_type;
+             /* For shared record types, mark the reference
+	        Push the shared attribute down to the field type,
+		and set the field's blocking factor to 0,
+		so that references to arrays declared within a structure
+		come up with the required zero blocksize.  */
+             TREE_SHARED (ref) = 1;
+	     gcc_assert (!TREE_SHARED (field));
+	     ref_type = build_variant_type_copy (TREE_TYPE (ref));
+	     if (TREE_CODE (ref_type) == ARRAY_TYPE)
+	       {
+		 tree last = ref_type;
+		 tree inner;
+		 while (TREE_CODE (TREE_TYPE (last)) == ARRAY_TYPE)
+		   last = TREE_TYPE (last);
+		 inner = build_variant_type_copy (TREE_TYPE (last));
+		 TYPE_BLOCK_FACTOR (inner) = size_zero_node;
+		 TYPE_SHARED (inner) = 1;
+		 TREE_TYPE (last) = inner;
+	       }
+	     else
+	       {
+	         TYPE_BLOCK_FACTOR (ref_type) = size_zero_node;
+		 TYPE_SHARED (ref_type) = 1;
+	       }
+	     TREE_TYPE (ref) = ref_type;
+           }
+
 	  if (TREE_DEPRECATED (subdatum))
 	    warn_deprecated_use (subdatum, NULL_TREE);
 
@@ -2257,6 +2341,7 @@ build_indirect_ref (location_t loc, tree
 	  TREE_SIDE_EFFECTS (ref)
 	    = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
 	  TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
+	  TREE_SHARED (ref) = upc_shared_type_p (t);
 	  protected_set_expr_location (ref, loc);
 	  return ref;
 	}
@@ -2338,7 +2423,6 @@ build_array_ref (location_t loc, tree ar
     {
       tree type = TREE_TYPE (array);
       tree type1;
-
       if (TREE_CODE (index) == INTEGER_CST)
         if (!host_integerp (index, 1) 
             || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1) 
@@ -2353,7 +2437,8 @@ build_array_ref (location_t loc, tree ar
       array = convert (type, array);
     }
 
-  if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
+  if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE
+      && !upc_shared_type_p (TREE_TYPE (array)))
     {
       tree rval, type;
 
@@ -2363,7 +2448,8 @@ build_array_ref (location_t loc, tree ar
 	 Likewise an array of elements of variable size.  */
       if (TREE_CODE (index) != INTEGER_CST
 	  || (COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (array)))
-	      && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))
+	      && TREE_CODE (TYPE_SIZE (TREE_TYPE (
+	                                 TREE_TYPE (array)))) != INTEGER_CST))
 	{
 	  if (!c_mark_addressable (array))
 	    return error_mark_node;
@@ -3267,6 +3353,23 @@ parser_build_binary_op (location_t locat
   return result;
 }
 
+/* Return a tree for the sum or difference (RESULTCODE says which)
+   of pointer PTROP and integer INTOP.  */
+
+static
+tree
+c_pointer_int_sum (location_t location, enum tree_code resultcode,
+                   tree ptrop, tree intop)
+{
+  /* The result is a pointer of the same type that is being added.  */
+  tree result_type = TREE_TYPE (ptrop);
+
+  if (upc_shared_type_p (TREE_TYPE (result_type)))
+    return upc_pts_int_sum (location, resultcode, ptrop, intop);
+
+  return pointer_int_sum (location, resultcode, ptrop, intop);
+}
+
 /* Return a tree for the difference of pointers OP0 and OP1.
    The resulting tree has type int.  */
 
@@ -3279,6 +3382,7 @@ pointer_diff (location_t loc, tree op0, 
   addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0)));
   addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1)));
   tree target_type = TREE_TYPE (TREE_TYPE (op0));
+  tree subtrahend_type = TREE_TYPE (TREE_TYPE (op1));
   tree con0, con1, lit0, lit1;
   tree orig_op1 = op1;
 
@@ -3318,6 +3422,9 @@ pointer_diff (location_t loc, tree op0, 
     pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
 	     "pointer to a function used in subtraction");
 
+  if (upc_shared_type_p (target_type) || upc_shared_type_p (subtrahend_type))
+    return upc_pts_diff (op0, op1);
+
   /* If the conversion to ptrdiff_type does anything like widening or
      converting a partial to an integral mode, we get a convert_expression
      that is in the way to do any simplifications.
@@ -3355,7 +3462,9 @@ pointer_diff (location_t loc, tree op0, 
   else
     lit1 = integer_zero_node;
 
-  if (operand_equal_p (con0, con1, 0))
+  if (operand_equal_p (con0, con1, 0)
+      && !upc_shared_type_p (TREE_TYPE (TREE_TYPE (con0)))
+      && !upc_shared_type_p (TREE_TYPE (TREE_TYPE (con1))))
     {
       op0 = lit0;
       op1 = lit1;
@@ -3643,6 +3752,11 @@ build_unary_op (location_t location,
 			   "wrong type argument to decrement");
 	      }
 
+	    /* UPC pointer-to-shared types cannot be
+	       incremented/decrmented directly.  */
+            if (upc_shared_type_p (TREE_TYPE (argtype)))
+	      return upc_pts_increment (location, code, arg);
+
 	    inc = c_size_in_bytes (TREE_TYPE (argtype));
 	    inc = fold_convert_loc (location, sizetype, inc);
 	  }
@@ -3732,6 +3846,12 @@ build_unary_op (location_t location,
 	  tree op0 = TREE_OPERAND (arg, 0);
 	  if (!c_mark_addressable (op0))
 	    return error_mark_node;
+	  /* Taking the address of a UPC shared array element
+	     cannot be performed as a simple addition. 
+	     Return an ADDR_EXPR node, and let upc_gimplify_expr()
+	     implement the proper semantics.  */
+	  if (TREE_SHARED (arg))
+	    return build1 (ADDR_EXPR, TREE_TYPE (arg), arg);
 	}
 
       /* Anything not already handled and not a true memory reference
@@ -3797,7 +3917,10 @@ build_unary_op (location_t location,
 	  goto return_build_unary_op;
 	}
 
-      val = build1 (ADDR_EXPR, argtype, arg);
+      if (TREE_CODE (arg) == VAR_DECL && TREE_SHARED (arg))
+	val = upc_build_shared_var_addr (location, argtype, arg);
+      else
+        val = build1 (ADDR_EXPR, argtype, arg);
 
       ret = val;
       goto return_build_unary_op;
@@ -3816,6 +3939,10 @@ build_unary_op (location_t location,
     ret = build1 (code, argtype, arg);
  return_build_unary_op:
   gcc_assert (ret != error_mark_node);
+  /* The result of an operation on objects that
+     are UPC shared qualified, must not be shared qualified.  */
+  if (upc_shared_type_p (TREE_TYPE (ret)))
+    TREE_TYPE (ret) = build_upc_unshared_type (TREE_TYPE (ret));
   if (TREE_CODE (ret) == INTEGER_CST && !TREE_OVERFLOW (ret)
       && !(TREE_CODE (xarg) == INTEGER_CST && !TREE_OVERFLOW (xarg)))
     ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
@@ -4244,7 +4371,8 @@ build_conditional_expr (location_t colon
 		 "pointer/integer type mismatch in conditional expression");
       else
 	{
-	  op2 = null_pointer_node;
+	  op2 = !upc_shared_type_p (TREE_TYPE (type1))
+	        ? null_pointer_node : upc_null_pts_node;
 	}
       result_type = type1;
     }
@@ -4255,7 +4383,8 @@ build_conditional_expr (location_t colon
 		 "pointer/integer type mismatch in conditional expression");
       else
 	{
-	  op1 = null_pointer_node;
+	  op1 = !upc_shared_type_p (TREE_TYPE (type2))
+	        ? null_pointer_node : upc_null_pts_node;
 	}
       result_type = type2;
     }
@@ -4504,6 +4633,12 @@ build_c_cast (location_t loc, tree type,
   if (objc_is_object_ptr (type) && objc_is_object_ptr (TREE_TYPE (expr)))
     return build1 (NOP_EXPR, type, expr);
 
+  if (upc_shared_type_p (type))
+    {
+      error ("UPC does not allow casts to a shared type");
+      return error_mark_node;
+    }
+
   type = TYPE_MAIN_VARIANT (type);
 
   if (TREE_CODE (type) == ARRAY_TYPE)
@@ -4525,6 +4660,22 @@ build_c_cast (location_t loc, tree type,
 	return error_mark_node;
     }
 
+  if (integer_zerop (value)
+      && POINTER_TYPE_P (type)
+      && upc_shared_type_p (TREE_TYPE (type))
+      && POINTER_TYPE_P (TREE_TYPE (expr))
+      && ! upc_shared_type_p (TREE_TYPE (TREE_TYPE (expr))))
+    {
+      value = upc_null_pts_node;
+    }
+
+  if (!upc_shared_type_p (type) && upc_shared_type_p (TREE_TYPE (expr)))
+    {
+      /* UPC disallows things like:
+           (int)p = <expr>; (where p is a shared int) */
+      value = non_lvalue (value);
+    }
+
   if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value)))
     {
       if (TREE_CODE (type) == RECORD_TYPE
@@ -4573,6 +4724,17 @@ build_c_cast (location_t loc, tree type,
 
       otype = TREE_TYPE (value);
 
+      if (TREE_CODE (type) == POINTER_TYPE
+	  && TREE_CODE (otype) == POINTER_TYPE)
+        {
+	  int t_shared = upc_shared_type_p (TREE_TYPE (type));
+	  int o_shared = upc_shared_type_p (TREE_TYPE (otype));
+	  if ((!t_shared && o_shared)
+	      || (t_shared && o_shared
+	          && !lang_hooks.types_compatible_p (type, otype)))
+	    return build1 (CONVERT_EXPR, type, value);
+	}
+
       /* Optionally warn about potentially worrisome casts.  */
       if (warn_cast_qual
 	  && TREE_CODE (type) == POINTER_TYPE
@@ -4624,6 +4786,33 @@ build_c_cast (location_t loc, tree type,
 	warning_at (loc, OPT_Wcast_align,
 		    "cast increases required alignment of target type");
 
+      if (POINTER_TYPE_P (type)
+	  && upc_shared_type_p (TREE_TYPE (type))
+	  && POINTER_TYPE_P (otype)
+	  && !upc_shared_type_p (TREE_TYPE (otype)))
+	{
+          error ("UPC does not allow casts from a local pointer to a pointer-to-shared");
+          return error_mark_node;
+	}
+
+      if (TREE_CODE (type) == POINTER_TYPE
+	  && TREE_CODE (otype) == INTEGER_TYPE
+	  && upc_shared_type_p (TREE_TYPE (type))
+	  && !integer_zerop (value))
+        {
+	  error ("UPC does not allow casts from an integer to a pointer-to-shared");
+          return error_mark_node;
+	}
+
+      if (TREE_CODE (type) == INTEGER_TYPE
+	  && TREE_CODE (otype) == POINTER_TYPE
+	  && upc_shared_type_p (TREE_TYPE (otype)))
+        {
+	  error ("UPC does not allow casts from a pointer-to-shared to an integer");
+	  return error_mark_node;
+	}
+
+
       if (TREE_CODE (type) == INTEGER_TYPE
 	  && TREE_CODE (otype) == POINTER_TYPE
 	  && TYPE_PRECISION (type) != TYPE_PRECISION (otype))
@@ -4903,6 +5092,14 @@ build_modify_expr (location_t location, 
   newrhs = c_fully_fold (newrhs, false, NULL);
   if (rhs_semantic_type)
     newrhs = build1 (EXCESS_PRECISION_EXPR, rhs_semantic_type, newrhs);
+
+  /* If the lhs is UPC 'shared' qualified, we drop the qualifier
+     for the purposes of conversions from rhstype to lhstype.
+     This will prevent the inadvertent creation of temporaries
+     with "shared asserted.  */
+  if (upc_shared_type_p (lhstype))
+    lhstype = build_upc_unshared_type (lhstype);
+
   newrhs = convert_for_assignment (location, lhstype, newrhs, rhs_origtype,
 				   ic_assign, npc, NULL_TREE, NULL_TREE, 0);
   if (TREE_CODE (newrhs) == ERROR_MARK)
@@ -5114,6 +5311,34 @@ convert_for_assignment (location_t locat
       }                                                                  \
   } while (0)
 
+  /* Similar to WARN_FOR_ASSIGNMENT, but used to diagnose certain
+     error conditions defined by the UPC language specification
+     when converting between pointer-to-shared types and other types.  */
+#define ERROR_FOR_ASSIGNMENT(LOCATION, OPT, AR, AS, IN, RE)            	 \
+  do {                                                                   \
+    switch (errtype)                                                     \
+      {                                                                  \
+      case ic_argpass:                                                   \
+        error_at (LOCATION, AR, parmnum, rname);                         \
+        inform ((fundecl && !DECL_IS_BUILTIN (fundecl))			 \
+	    	? DECL_SOURCE_LOCATION (fundecl) : LOCATION,		 \
+                "expected %qT but argument is of type %qT",              \
+                type, rhstype);                                          \
+        break;                                                           \
+      case ic_assign:                                                    \
+        error_at (LOCATION, AS);                                         \
+        break;                                                           \
+      case ic_init:                                                      \
+        error_at (LOCATION, IN);                                         \
+        break;                                                           \
+      case ic_return:                                                    \
+        error_at (LOCATION, RE);                                 	 \
+        break;                                                           \
+      default:                                                           \
+        gcc_unreachable ();                                              \
+      }                                                                  \
+  } while (0)
+
   /* This macro is used to emit diagnostics to ensure that all format
      strings are complete sentences, visible to gettext and checked at
      compile time.  It is the same as WARN_FOR_ASSIGNMENT but with an
@@ -5325,7 +5550,9 @@ convert_for_assignment (location_t locat
 	  /* Can convert integer zero to any pointer type.  */
 	  if (null_pointer_constant)
 	    {
-	      rhs = null_pointer_node;
+	      tree ttl = TREE_TYPE (memb_type);
+	      rhs = !upc_shared_type_p (ttl)
+		    ? null_pointer_node : upc_null_pts_node;
 	      break;
 	    }
 	}
@@ -5407,6 +5634,43 @@ convert_for_assignment (location_t locat
 	mvl = TYPE_MAIN_VARIANT (mvl);
       if (TREE_CODE (mvr) != ARRAY_TYPE)
 	mvr = TYPE_MAIN_VARIANT (mvr);
+      if ((upc_shared_type_p (ttl) && !upc_shared_type_p (ttr))
+           && !integer_zerop (rhs))
+        {
+	  error_at (location, "UPC does not allow assignments from a local pointer "
+	                      "to a pointer-to-shared");
+	  return error_mark_node;
+	}
+      if (!upc_shared_type_p (ttl) && upc_shared_type_p (ttr))
+        {
+	  if (upc_is_null_pts_p (rhs))
+	    {
+	      return null_pointer_node; 
+	    }
+	  else
+	    {
+	      error_at (location, "UPC does not allow assignments "
+	                          "from a pointer-to-shared to a local pointer");
+	      return error_mark_node;
+	    }
+        }
+      if (upc_shared_type_p (ttl) && upc_shared_type_p (ttr) && (ttl != ttr)
+          && !(VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)))
+        {
+	  const tree bs_l = upc_get_block_factor (ttl);
+	  const tree bs_r = upc_get_block_factor (ttr);
+	  /* Both source and destination are non-void pointers to shared,
+	     whose target types are not equal.
+	     UPC dictates that their blocking factors must be equal. */
+	  if (!tree_int_cst_equal (bs_l, bs_r))
+	    {
+	      error_at (location, "UPC does not allow assignment "
+	                          "between pointers to shared with "
+				  "differing block sizes without a cast");
+	      return error_mark_node;
+	    }
+	}
+
       /* Opaque pointers are treated like void pointers.  */
       is_opaque_pointer = vector_targets_convertible_p (ttl, ttr);
 
@@ -5613,15 +5877,28 @@ convert_for_assignment (location_t locat
 	 or one that results from arithmetic, even including
 	 a cast to integer type.  */
       if (!null_pointer_constant)
-	WARN_FOR_ASSIGNMENT (location, 0,
-			     G_("passing argument %d of %qE makes "
-				"pointer from integer without a cast"),
-			     G_("assignment makes pointer from integer "
-				"without a cast"),
-			     G_("initialization makes pointer from "
-				"integer without a cast"),
-			     G_("return makes pointer from integer "
-				"without a cast"));
+        {
+	  if (upc_shared_type_p (TREE_TYPE (type)))
+	    ERROR_FOR_ASSIGNMENT (location, 0,
+				  G_("passing argument %d of %qE attempts to make "
+				     "a UPC pointer-to-shared value from an integer"),
+				  G_("assignment attempts to make a UPC pointer-to-shared "
+				     "value from an integer"),
+				  G_("initialization attempts to make a UPC pointer-to-shared "
+				     "value from an integer without a cast"),
+				  G_("return makes a UPC pointer-to-shared value from an "
+				     "integer"));
+	  else
+	    WARN_FOR_ASSIGNMENT (location, 0,
+				 G_("passing argument %d of %qE makes "
+				    "pointer from integer without a cast"),
+				 G_("assignment makes pointer from integer "
+				    "without a cast"),
+				 G_("initialization makes pointer from "
+				    "integer without a cast"),
+				 G_("return makes pointer from integer "
+				     "without a cast"));
+        }
 
       return convert (type, rhs);
     }
@@ -5711,21 +5988,31 @@ valid_compound_expr_initializer (tree va
 void
 store_init_value (location_t init_loc, tree decl, tree init, tree origtype)
 {
-  tree value, type;
-  bool npc = false;
+  const bool npc = init && null_pointer_constant_p (init);
+  const bool is_upc_decl_init = upc_check_decl_init (decl, init);
+  const bool require_constant = TREE_STATIC (decl) && !is_upc_decl_init;
+  tree type = TREE_TYPE (decl);
+  tree value;
 
   /* If variable's type was invalidly declared, just ignore it.  */
 
-  type = TREE_TYPE (decl);
   if (TREE_CODE (type) == ERROR_MARK)
     return;
 
   /* Digest the specified initializer into an expression.  */
 
-  if (init)
-    npc = null_pointer_constant_p (init);
   value = digest_init (init_loc, type, init, origtype, npc,
-      		       true, TREE_STATIC (decl));
+      		       true, require_constant);
+
+  /* UPC cannot initialize certain values at compile time.
+     For example, the address of a UPC 'shared' variable must
+     be evaluated at runtime.  */
+
+  if (is_upc_decl_init)
+    {
+      upc_decl_init (decl, value);
+      return;
+    }
 
   /* Store the expression if valid; else report error.  */
 
@@ -6584,6 +6871,9 @@ really_start_incremental_init (tree type
   designator_depth = 0;
   designator_erroneous = 0;
 
+  /* The result of the constructor must not be UPC shared qualified */
+  if (upc_shared_type_p (constructor_type))
+    constructor_type = build_upc_unshared_type (constructor_type);
   if (TREE_CODE (constructor_type) == RECORD_TYPE
       || TREE_CODE (constructor_type) == UNION_TYPE)
     {
@@ -9513,12 +9803,12 @@ build_binary_op (location_t location, en
       /* Handle the pointer + int case.  */
       if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
 	{
-	  ret = pointer_int_sum (location, PLUS_EXPR, op0, op1);
+	  ret = c_pointer_int_sum (location, PLUS_EXPR, op0, op1);
 	  goto return_build_binary_op;
 	}
       else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
 	{
-	  ret = pointer_int_sum (location, PLUS_EXPR, op1, op0);
+	  ret = c_pointer_int_sum (location, PLUS_EXPR, op1, op0);
 	  goto return_build_binary_op;
 	}
       else
@@ -9537,7 +9827,7 @@ build_binary_op (location_t location, en
       /* Handle pointer minus int.  Just like pointer plus int.  */
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
 	{
-	  ret = pointer_int_sum (location, MINUS_EXPR, op0, op1);
+	  ret = c_pointer_int_sum (location, MINUS_EXPR, op0, op1);
 	  goto return_build_binary_op;
 	}
       else
@@ -9829,6 +10119,16 @@ build_binary_op (location_t location, en
 	  addr_space_t as1 = TYPE_ADDR_SPACE (tt1);
 	  addr_space_t as_common = ADDR_SPACE_GENERIC;
 
+	  if ((upc_shared_type_p (tt0)
+	           && !(upc_shared_type_p (tt1) || integer_zerop(op1)))
+              || (upc_shared_type_p (tt1)
+	           && !(upc_shared_type_p (tt0) || integer_zerop(op0))))
+	    {
+	      error_at (location, "UPC does not allow comparisons "
+	                          "between pointers to shared and "
+				  "local pointers");
+	      return error_mark_node;
+	    }
 	  /* Anything compares with void *.  void * compares with anything.
 	     Otherwise, the targets must be compatible
 	     and both must be object or both incomplete.  */
@@ -9860,9 +10160,17 @@ build_binary_op (location_t location, en
 
 	  if (result_type == NULL_TREE)
 	    {
-	      int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
-	      result_type = build_pointer_type
-			      (build_qualified_type (void_type_node, qual));
+	      if (upc_shared_type_p(tt0) || upc_shared_type_p(tt1))
+	        {
+	          result_type = upc_pts_type_node;
+		}
+              else
+	        {
+		  int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
+		  result_type = build_pointer_type
+				  (build_qualified_type (void_type_node,
+				                         qual));
+		}
 	    }
 	}
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
@@ -9889,10 +10197,18 @@ build_binary_op (location_t location, en
 	short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
 	{
-	  addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (type0));
-	  addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1));
+	  const tree tt0 = TREE_TYPE (type0);
+	  const tree tt1 = TREE_TYPE (type1);
+	  addr_space_t as0 = TYPE_ADDR_SPACE (tt0);
+	  addr_space_t as1 = TYPE_ADDR_SPACE (tt1);
 	  addr_space_t as_common;
 
+	  if (upc_shared_type_p (tt0) != upc_shared_type_p (tt1))
+	    {
+	      error_at (location, "UPC does not allow comparisons between "
+	                          "pointers to shared and local pointers");
+	      return error_mark_node;
+	    }
 	  if (comp_target_types (location, type0, type1))
 	    {
 	      result_type = common_pointer_type (type0, type1);
@@ -9915,6 +10231,11 @@ build_binary_op (location_t location, en
 			"disjoint address spaces");
 	      return error_mark_node;
 	    }
+	  else if (upc_shared_type_p (TREE_TYPE (type0))
+	           || upc_shared_type_p (TREE_TYPE (type1)))
+	    {
+	      result_type = upc_pts_type_node;
+	    }
 	  else
 	    {
 	      int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
@@ -10256,7 +10577,6 @@ build_binary_op (location_t location, en
   return ret;
 }
 
-
 /* Convert EXPR to be a truth-value, validating its type for this
    purpose.  LOCATION is the source location for the expression.  */
 
@@ -10634,16 +10954,26 @@ c_build_qualified_type (tree type, int t
 
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
-      tree t;
-      tree element_type = c_build_qualified_type (TREE_TYPE (type),
+      const tree element_type = c_build_qualified_type (TREE_TYPE (type),
 						  type_quals);
+      const tree elem_block_factor = upc_get_block_factor (element_type);
+      tree t;
 
       /* See if we already have an identically qualified type.  */
       for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
 	{
-	  if (TYPE_QUALS (strip_array_types (t)) == type_quals
+	  const tree t_elem_type = strip_array_types (t);
+	  const tree t_elem_block_factor = TYPE_BLOCK_FACTOR (t_elem_type);
+	  /* UPC requires that the blocking factors are either both
+	     empty or equal in value.  The check for pointer equality
+	     generally works because blocking factors are stored
+	     as integer constants, and integer constants are commonized
+	     so that identical integer constant values are represented
+	     by a single tree node.  */
+	  if (TYPE_QUALS (t_elem_type) == type_quals
 	      && TYPE_NAME (t) == TYPE_NAME (type)
 	      && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
+	      && t_elem_block_factor == elem_block_factor
 	      && attribute_list_equal (TYPE_ATTRIBUTES (t),
 				       TYPE_ATTRIBUTES (type)))
 	    break;
Index: gcc/explow.c
===================================================================
--- gcc/explow.c	(.../trunk)	(revision 175584)
+++ gcc/explow.c	(.../branches/gupc)	(revision 175735)
@@ -833,6 +833,8 @@ promote_mode (const_tree type ATTRIBUTE_
 #ifdef POINTERS_EXTEND_UNSIGNED
     case REFERENCE_TYPE:
     case POINTER_TYPE:
+      if (upc_shared_type_p (TREE_TYPE (type)))
+        return Pmode;
       *punsignedp = POINTERS_EXTEND_UNSIGNED;
       return targetm.addr_space.address_mode
 	       (TYPE_ADDR_SPACE (TREE_TYPE (type)));
Index: gcc/print-tree.c
===================================================================
--- gcc/print-tree.c	(.../trunk)	(revision 175584)
+++ gcc/print-tree.c	(.../branches/gupc)	(revision 175735)
@@ -333,6 +333,8 @@ print_node (FILE *file, const char *pref
 
   if (TYPE_P (node) ? TYPE_READONLY (node) : TREE_READONLY (node))
     fputs (" readonly", file);
+  if (TREE_SHARED (node))
+    fputs (" shared", file);
   if (!TYPE_P (node) && TREE_CONSTANT (node))
     fputs (" constant", file);
   else if (TYPE_P (node) && TYPE_SIZES_GIMPLIFIED (node))
@@ -359,6 +361,10 @@ print_node (FILE *file, const char *pref
     fputs (" protected", file);
   if (TREE_STATIC (node))
     fputs (" static", file);
+  if (TREE_CODE (node) == FUNCTION_DECL && DECL_STATIC_CONSTRUCTOR (node))
+    fputs (" constructor", file);
+  if (TREE_CODE (node) == FUNCTION_DECL && DECL_STATIC_DESTRUCTOR (node))
+    fputs (" destructor", file);
   if (TREE_DEPRECATED (node))
     fputs (" deprecated", file);
   if (TREE_VISITED (node))
@@ -653,6 +659,8 @@ print_node (FILE *file, const char *pref
 
       print_node (file, "size", TYPE_SIZE (node), indent + 4);
       print_node (file, "unit size", TYPE_SIZE_UNIT (node), indent + 4);
+      if (TYPE_BLOCK_FACTOR (node))
+	print_node (file, "block_factor", TYPE_BLOCK_FACTOR (node), indent + 4);
       indent_to (file, indent + 3);
 
       if (TYPE_USER_ALIGN (node))
Index: gcc/c-convert.c
===================================================================
--- gcc/c-convert.c	(.../trunk)	(revision 175584)
+++ gcc/c-convert.c	(.../branches/gupc)	(revision 175735)
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  
 #include "flags.h"
 #include "convert.h"
 #include "c-family/c-common.h"
+#include "c-family/c-upc.h"
 #include "c-tree.h"
 #include "langhooks.h"
 #include "target.h"
@@ -92,6 +93,12 @@ convert (tree type, tree expr)
 
   STRIP_TYPE_NOPS (e);
 
+  /* Drop 'shared' qualifier when considering conversions
+     of expression values.  */
+  if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))
+      && upc_shared_type_p (type))
+    return fold_convert_loc (loc, build_upc_unshared_type(type), expr);
+
   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
     return fold_convert_loc (loc, type, expr);
   if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	(.../trunk)	(revision 175584)
+++ gcc/varasm.c	(.../branches/gupc)	(revision 175735)
@@ -6102,6 +6102,19 @@ default_section_type_flags (tree decl, c
 	  || strcmp (name, ".preinit_array") == 0))
     flags |= SECTION_NOTYPE;
 
+#ifdef UPC_SHARED_SECTION_NAME
+  /* The UPC shared section is not loaded into memory.
+     It is used only to layout shared veriables.  */
+  if (!(flags & (SECTION_CODE | SECTION_BSS | SECTION_TLS))
+      && (strcmp (name, UPC_SHARED_SECTION_NAME) == 0))
+    {
+      flags |= SECTION_BSS;
+# ifdef HAVE_UPC_LINK_SCRIPT
+      flags = SECTION_DEBUG | (flags & ~SECTION_WRITE);
+# endif
+    }
+#endif
+
   return flags;
 }
 
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(.../trunk)	(revision 175584)
+++ gcc/Makefile.in	(.../branches/gupc)	(revision 175735)
@@ -1195,8 +1195,9 @@ C_AND_OBJC_OBJS = attribs.o c-errors.o c
   c-convert.o c-aux-info.o c-objc-common.o c-parser.o tree-mudflap.o \
   $(C_COMMON_OBJS) $(C_TARGET_OBJS)
 
+C_STUB_OBJS = c-family/stub-objc.o c-family/stub-upc.o
 # Language-specific object files for C.
-C_OBJS = c-lang.o c-family/stub-objc.o $(C_AND_OBJC_OBJS)
+C_OBJS = c-lang.o $(C_STUB_OBJS) $(C_AND_OBJC_OBJS)
 
 # Language-independent object files.
 # We put the insn-*.o files first so that a parallel make will build
@@ -2073,7 +2074,7 @@ c-decl.o : c-decl.c c-lang.h $(CONFIG_H)
 	$(HASHTAB_H) $(LIBFUNCS_H) $(EXCEPT_H) $(LANGHOOKS_DEF_H) \
 	$(TREE_DUMP_H) $(C_COMMON_H) $(CPPLIB_H) $(DIAGNOSTIC_CORE_H) \
 	$(INPUT_H) langhooks.h tree-mudflap.h pointer-set.h tree-iterator.h \
-	$(PLUGIN_H) c-family/c-ada-spec.h c-family/c-objc.h
+	$(PLUGIN_H) c-family/c-ada-spec.h c-family/c-objc.h c-family/c-upc.h
 
 c-errors.o: c-errors.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
 	$(C_TREE_H) $(FLAGS_H) $(DIAGNOSTIC_H) $(TM_P_H)
@@ -2093,14 +2094,15 @@ c-objc-common.o : c-objc-common.c c-objc
 c-parser.o : c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
 	$(TM_H) $(TREE_H) $(C_TREE_H) $(C_COMMON_H) $(C_PRAGMA_H) $(CPPLIB_H) \
 	$(GGC_H) $(TIMEVAR_H) $(INPUT_H) $(FLAGS_H) output.h \
+	upc/upc-gasp.h upc/upc-tree.h \
 	gt-c-parser.h langhooks.h \
 	$(VEC_H) $(TARGET_H) $(CGRAPH_H) $(PLUGIN_H) \
-	 c-family/c-objc.h
+	 c-family/c-objc.h c-family/c-upc.h
 
 c-typeck.o : c-typeck.c c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
 	$(TREE_H) $(C_TREE_H) $(TARGET_H) $(FLAGS_H) intl.h output.h $(EXPR_H) \
 	langhooks.h tree-iterator.h $(BITMAP_H) $(GIMPLE_H) \
-	 c-family/c-objc.h
+	 c-family/c-objc.h c-family/c-upc.h
 
 
 
@@ -2145,7 +2147,7 @@ c-family/c-common.o : c-family/c-common.
 	$(TM_H) $(TREE_H) \
 	$(OBSTACK_H) $(C_COMMON_H) $(FLAGS_H) toplev.h output.h $(C_PRAGMA_H) \
 	$(GGC_H) builtin-types.def builtin-attrs.def \
-	$(DIAGNOSTIC_H) langhooks.h c-family/c-objc.h \
+	$(DIAGNOSTIC_H) langhooks.h c-family/c-objc.h c-family/c-upc.h \
 	$(TARGET_H) tree-iterator.h langhooks.h tree-mudflap.h \
 	intl.h $(OPTS_H) $(CPPLIB_H) $(TREE_INLINE_H) $(HASHTAB_H) \
 	$(BUILTINS_DEF) $(CGRAPH_H) $(BASIC_BLOCK_H) $(TARGET_DEF_H) \
@@ -2165,7 +2167,7 @@ c-family/c-dump.o : c-family/c-dump.c $(
 c-family/c-format.o : c-family/c-format.c c-family/c-format.h \
 	$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) langhooks.h \
 	$(C_COMMON_H) $(FLAGS_H) intl.h $(C_TARGET_H) \
-	$(DIAGNOSTIC_CORE_H) alloc-pool.h c-family/c-objc.h
+	$(DIAGNOSTIC_CORE_H) alloc-pool.h c-family/c-objc.h c-family/c-upc.h
 
 c-family/c-gimplify.o : c-family/c-gimplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
 	$(C_COMMON_H) $(DIAGNOSTIC_CORE_H) $(GIMPLE_H) \
@@ -2222,6 +2224,9 @@ c-family/c-ada-spec.o : c-family/c-ada-s
 c-family/stub-objc.o : c-family/stub-objc.c $(CONFIG_H) $(SYSTEM_H) \
 	coretypes.h $(TREE_H) $(C_COMMON_H) c-family/c-objc.h
 
+c-family/stub-upc.o : c-family/stub-upc.c $(CONFIG_H) $(SYSTEM_H) \
+	coretypes.h $(TREE_H) $(C_COMMON_H) c-family/c-upc.h
+
 default-c.o: config/default-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
   $(C_TARGET_H) $(C_TARGET_DEF_H)
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
@@ -4627,7 +4632,7 @@ PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $
   $(tm_file_list) $(tm_include_list) $(tm_p_file_list) $(tm_p_include_list) \
   $(host_xm_file_list) $(host_xm_include_list) $(xm_include_list) \
   intl.h $(PLUGIN_VERSION_H) $(DIAGNOSTIC_H) \
-  $(C_COMMON_H) c-family/c-objc.h $(C_PRETTY_PRINT_H) \
+  $(C_COMMON_H) c-family/c-objc.h c-family/c-upc.h $(C_PRETTY_PRINT_H) \
   tree-iterator.h $(PLUGIN_H) $(TREE_FLOW_H) langhooks.h incpath.h debug.h \
   $(EXCEPT_H) tree-ssa-sccvn.h real.h output.h $(IPA_UTILS_H) \
   $(C_PRAGMA_H)  $(CPPLIB_H)  $(FUNCTION_H) \
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c	(.../trunk)	(revision 175584)
+++ gcc/c-parser.c	(.../branches/gupc)	(revision 175735)
@@ -53,11 +53,14 @@ along with GCC; see the file COPYING3.  
 #include "ggc.h"
 #include "c-family/c-common.h"
 #include "c-family/c-objc.h"
+#include "c-family/c-upc.h"
 #include "vec.h"
 #include "target.h"
 #include "cgraph.h"
 #include "plugin.h"
 
+#include "upc/upc-tree.h"
+
 
 /* Initialization routine for this file.  */
 
@@ -86,6 +89,9 @@ c_parse_init (void)
   if (!c_dialect_objc ())
     mask |= D_OBJC | D_CXX_OBJC;
 
+  if (!c_dialect_upc ())
+    mask |= D_UPC;
+
   ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
   for (i = 0; i < num_c_common_reswords; i++)
     {
@@ -496,6 +502,11 @@ c_token_starts_typename (c_token *token)
 	case RID_ACCUM:
 	case RID_SAT:
 	  return true;
+        /* UPC qualifiers */
+	case RID_SHARED:
+	case RID_STRICT:
+	case RID_RELAXED:
+	  return true;
 	default:
 	  return false;
 	}
@@ -572,6 +583,11 @@ c_token_is_qualifier (c_token *token)
 	case RID_RESTRICT:
 	case RID_ATTRIBUTE:
 	  return true;
+        case RID_SHARED:
+        case RID_STRICT:
+        case RID_RELAXED:
+	  /* UPC qualifiers */
+	  return true;
 	default:
 	  return false;
 	}
@@ -650,6 +666,11 @@ c_token_starts_declspecs (c_token *token
 	case RID_ACCUM:
 	case RID_SAT:
 	  return true;
+        /* UPC qualifiers */
+	case RID_SHARED:
+	case RID_STRICT:
+	case RID_RELAXED:
+	  return true;
 	default:
 	  return false;
 	}
@@ -1190,6 +1211,12 @@ static void c_parser_objc_at_dynamic_dec
 static bool c_parser_objc_diagnose_bad_element_prefix
   (c_parser *, struct c_declspecs *);
 
+/* These UPC parser functions are only ever called when
+   compiling UPC.  */
+static void c_parser_upc_forall_statement (c_parser *);
+static void c_parser_upc_sync_statement (c_parser *, int);
+static void c_parser_upc_shared_qual (c_parser *, struct c_declspecs *);
+
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
    translation-unit:
@@ -2139,6 +2166,17 @@ c_parser_declspecs (c_parser *parser, st
 	  declspecs_add_qual (specs, c_parser_peek_token (parser)->value);
 	  c_parser_consume_token (parser);
 	  break;
+        /* UPC qualifiers */
+	case RID_SHARED:
+	  attrs_ok = true;
+          c_parser_upc_shared_qual (parser, specs);
+	  break;
+	case RID_STRICT:
+	case RID_RELAXED:
+	  attrs_ok = true;
+	  declspecs_add_qual (specs, c_parser_peek_token (parser)->value);
+	  c_parser_consume_token (parser);
+	  break;
 	case RID_ATTRIBUTE:
 	  if (!attrs_ok)
 	    goto out;
@@ -3429,6 +3467,12 @@ c_parser_attributes (c_parser *parser)
 		case RID_SAT:
 		  ok = true;
 		  break;
+		/* UPC qualifiers */
+		case RID_SHARED:
+		case RID_STRICT:
+		case RID_RELAXED:
+		  ok = true;
+		  break;
 		default:
 		  ok = false;
 		  break;
@@ -4024,6 +4068,19 @@ c_parser_compound_statement_nostart (c_p
       c_parser_consume_token (parser);
       return;
     }
+  /* Process all #pragma's just after the opening brace.  This
+     handles #pragma upc, which can only appear just after
+     the opening brace, when it appears within a function body.  */
+  push_upc_consistency_mode ();
+  permit_pragma_upc ();
+  while (c_parser_next_token_is (parser, CPP_PRAGMA))
+    {
+      location_t loc ATTRIBUTE_UNUSED = c_parser_peek_token (parser)->location;
+      if (c_parser_pragma (parser, pragma_compound))
+        last_label = false, last_stmt = true;
+      parser->error = false;
+    }
+  deny_pragma_upc ();
   while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
     {
       location_t loc = c_parser_peek_token (parser)->location;
@@ -4133,6 +4190,7 @@ c_parser_compound_statement_nostart (c_p
   if (last_label)
     error_at (label_loc, "label at end of compound statement");
   c_parser_consume_token (parser);
+  pop_upc_consistency_mode ();
   /* Restore the value we started with.  */
   mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
 }
@@ -4427,6 +4485,22 @@ c_parser_statement_after_labels (c_parse
 	  gcc_assert (c_dialect_objc ());
 	  c_parser_objc_synchronized_statement (parser);
 	  break;
+	case RID_UPC_FORALL:
+          gcc_assert (c_dialect_upc ());
+	  c_parser_upc_forall_statement (parser);
+	  break;
+        case RID_UPC_NOTIFY:
+          gcc_assert (c_dialect_upc ());
+	  c_parser_upc_sync_statement (parser, UPC_SYNC_NOTIFY_OP);
+	  goto expect_semicolon;
+        case RID_UPC_WAIT:
+          gcc_assert (c_dialect_upc ());
+	  c_parser_upc_sync_statement (parser, UPC_SYNC_WAIT_OP);
+	  goto expect_semicolon;
+        case RID_UPC_BARRIER:
+          gcc_assert (c_dialect_upc ());
+	  c_parser_upc_sync_statement (parser, UPC_SYNC_BARRIER_OP);
+	  goto expect_semicolon;
 	default:
 	  goto expr_stmt;
 	}
@@ -4475,7 +4549,7 @@ c_parser_statement_after_labels (c_parse
 static tree
 c_parser_condition (c_parser *parser)
 {
-  location_t loc = c_parser_peek_token (parser)->location;
+  location_t loc ATTRIBUTE_UNUSED = c_parser_peek_token (parser)->location;
   tree cond;
   cond = c_parser_expression_conv (parser).value;
   cond = c_objc_common_truthvalue_conversion (loc, cond);
@@ -5825,6 +5899,11 @@ c_parser_unary_expression (c_parser *par
 	{
 	case RID_SIZEOF:
 	  return c_parser_sizeof_expression (parser);
+	case RID_UPC_BLOCKSIZEOF:
+	case RID_UPC_ELEMSIZEOF:
+	case RID_UPC_LOCALSIZEOF:
+          gcc_assert (c_dialect_upc ());
+	  return c_parser_sizeof_expression (parser);
 	case RID_ALIGNOF:
 	  return c_parser_alignof_expression (parser);
 	case RID_EXTENSION:
@@ -5853,6 +5932,147 @@ c_parser_unary_expression (c_parser *par
     }
 }
 
+/* Return the result of upc_blocksizeof applied to EXPR.  */
+
+static
+struct c_expr
+upc_blocksizeof_expr (location_t loc, struct c_expr expr)
+{
+  struct c_expr ret;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  if (expr.value == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_blocksizeof (loc, TREE_TYPE (expr.value));
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
+    }
+  return ret;
+}
+
+/* Return the result of upc_blocksizeof applied to T, a structure
+   for the type name passed to sizeof (rather than the type itself).  */
+
+static
+struct c_expr
+upc_blocksizeof_type (location_t loc, struct c_type_name *t)
+{
+  tree type;
+  struct c_expr ret;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  type = groktypename (t, NULL, NULL);
+  if (type == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_blocksizeof (loc, type);
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (type));
+    }
+  return ret;
+}
+
+/* Return the result of upc_elemsizeof applied to EXPR.  */
+
+static
+struct c_expr
+upc_elemsizeof_expr (location_t loc, struct c_expr expr)
+{
+  struct c_expr ret;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  if (expr.value == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_elemsizeof (loc, TREE_TYPE (expr.value));
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
+    }
+  return ret;
+}
+
+/* Return the result of upc_elemsizeof applied to T, a structure
+   for the type name passed to sizeof (rather than the type itself).  */
+
+static
+struct c_expr
+upc_elemsizeof_type (location_t loc, struct c_type_name *t)
+{
+  tree type;
+  struct c_expr ret;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  type = groktypename (t, NULL, NULL);
+  if (type == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_elemsizeof (loc, type);
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (type));
+    }
+  return ret;
+}
+
+/* Return the result of upc_localsizeof applied to EXPR.  */
+
+static
+struct c_expr
+upc_localsizeof_expr (location_t loc, struct c_expr expr)
+{
+  struct c_expr ret;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  if (expr.value == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_localsizeof (loc, TREE_TYPE (expr.value));
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
+    }
+  return ret;
+}
+
+/* Return the result of upc_localsizeof applied to T, a structure
+   for the type name passed to sizeof (rather than the type itself).  */
+
+static
+struct c_expr
+upc_localsizeof_type (location_t loc, struct c_type_name *t)
+{
+  tree type;
+  struct c_expr ret;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  type = groktypename (t, NULL, NULL);
+  if (type == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_localsizeof (loc, type);
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (type));
+    }
+  return ret;
+}
+
 /* Parse a sizeof expression.  */
 
 static struct c_expr
@@ -5860,7 +6080,7 @@ c_parser_sizeof_expression (c_parser *pa
 {
   struct c_expr expr;
   location_t expr_loc;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
+  enum rid keyword = c_parser_peek_token (parser)->keyword;
   c_parser_consume_token (parser);
   c_inhibit_evaluation_warnings++;
   in_sizeof++;
@@ -5894,6 +6114,17 @@ c_parser_sizeof_expression (c_parser *pa
       /* sizeof ( type-name ).  */
       c_inhibit_evaluation_warnings--;
       in_sizeof--;
+      /* Handle upc_*_sizeof (type) operations.  */
+      switch (keyword)
+        {
+        case RID_UPC_BLOCKSIZEOF:
+          return upc_blocksizeof_type (expr_loc, type_name);
+        case RID_UPC_ELEMSIZEOF:
+          return upc_elemsizeof_type (expr_loc, type_name);
+        case RID_UPC_LOCALSIZEOF:
+          return upc_localsizeof_type (expr_loc, type_name);
+        default: break;
+        }
       return c_expr_sizeof_type (expr_loc, type_name);
     }
   else
@@ -5907,6 +6138,19 @@ c_parser_sizeof_expression (c_parser *pa
       if (TREE_CODE (expr.value) == COMPONENT_REF
 	  && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
 	error_at (expr_loc, "%<sizeof%> applied to a bit-field");
+      /* Handle upc_*_sizeof (expr) operations.  */
+      switch (keyword)
+        {
+        case RID_UPC_BLOCKSIZEOF:
+          return upc_blocksizeof_expr (expr_loc, expr);
+        case RID_UPC_ELEMSIZEOF:
+          return upc_elemsizeof_expr (expr_loc, expr);
+        case RID_UPC_LOCALSIZEOF:
+          return upc_localsizeof_expr (expr_loc, expr);
+        case RID_SIZEOF:
+          return c_expr_sizeof_expr (expr_loc, expr);
+        default: break;
+        }
       return c_expr_sizeof_expr (expr_loc, expr);
     }
 }
@@ -8194,6 +8438,225 @@ c_parser_objc_at_dynamic_declaration (c_
   objc_add_dynamic_declaration (loc, list);
 }
 
+/* Parse UPC shared qualifier
+
+   shared-type-qualifier: shared layout-qualifier-opt
+   layout-qualifier: [ constant-expression-opt ] | [ * ]
+
+*/
+static void
+c_parser_upc_shared_qual (c_parser *parser, struct c_declspecs *specs)
+{
+  tree array_qual, arg1;
+
+  /* consume "shared" part */
+  c_parser_consume_token (parser);
+
+  /* check for shared array layout specifier */
+  if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+    {
+      declspecs_add_qual (specs, ridpointers[RID_SHARED]);
+      return;
+    }
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+    {
+      /*  [] layout specifier */ 
+      arg1 = size_zero_node;
+    }
+  else if (c_parser_next_token_is (parser, CPP_MULT))
+    {
+      /*  [*] layout specifier */ 
+      arg1 = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE);
+      c_parser_consume_token (parser);
+    }
+  else
+    {
+      /*  [ expression ] layout specifier */ 
+      arg1 = c_parser_expression (parser).value;
+    }
+  array_qual = build4 (ARRAY_REF, NULL_TREE, NULL_TREE, 
+                 arg1, NULL_TREE, NULL_TREE);
+  declspecs_add_qual (specs, array_qual);
+
+  if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+    {
+      c_parser_error (parser, "expected ]");
+    }
+  c_parser_consume_token (parser);
+}
+
+/* Parse a UPC upc_forall statement
+
+   upc_forall-statement:
+     upc_forall ( expression[opt] ; expression[opt] ;
+                  expression[opt] ; affinity[opt] ) statement
+   affinity: experssion | continue  */
+
+static void
+c_parser_upc_forall_statement (c_parser *parser)
+{
+  tree block, cond, incr, save_break, save_cont, body;
+  tree affinity;
+  location_t loc = c_parser_peek_token (parser)->location;
+  location_t affinity_loc = UNKNOWN_LOCATION;
+  const int profile_upc_forall = flag_upc_instrument && get_upc_pupc_mode();
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_UPC_FORALL));
+  c_parser_consume_token (parser);
+  block = c_begin_compound_stmt (flag_isoc99);
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      /* Parse the initialization declaration or expression.  */
+      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+	{
+	  c_parser_consume_token (parser);
+	  c_finish_expr_stmt (loc, NULL_TREE);
+	}
+      else if (c_parser_next_token_starts_declspecs (parser))
+	{
+	  c_parser_declaration_or_fndef (parser, true, true, true,
+	                                 true, true, NULL);
+	  check_for_loop_decls (loc, true);
+	}
+      else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
+	{
+	  /* __extension__ can start a declaration, but is also an
+	     unary operator that can start an expression.  Consume all
+	     but the last of a possible series of __extension__ to
+	     determine which.  */
+	  while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
+		 && (c_parser_peek_2nd_token (parser)->keyword
+		     == RID_EXTENSION))
+	    c_parser_consume_token (parser);
+	  if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser)))
+	    {
+	      int ext;
+	      ext = disable_extension_diagnostics ();
+	      c_parser_consume_token (parser);
+	      c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
+	      restore_extension_diagnostics (ext);
+	      check_for_loop_decls (loc, true);
+	    }
+	  else
+	    goto init_expr;
+	}
+      else
+	{
+	init_expr:
+	  c_finish_expr_stmt (loc, c_parser_expression (parser).value);
+	  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+	}
+      /* Parse the loop condition.  */
+      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+	{
+	  c_parser_consume_token (parser);
+	  cond = NULL_TREE;
+	}
+      else
+	{
+	  cond = c_parser_condition (parser);
+	  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+	}
+      /* Parse the increment expression.  */
+      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+	incr = c_process_expr_stmt (loc, NULL_TREE);
+      else
+	incr = c_process_expr_stmt (loc, c_parser_expression (parser).value);
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+      /* Parse the UPC affinity expression. */
+      affinity_loc = c_parser_peek_token (parser)->location;
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+        {
+	  affinity = NULL_TREE;
+        }
+      else if (c_parser_peek_token (parser)->type == CPP_KEYWORD
+               && c_parser_peek_token (parser)->keyword == RID_CONTINUE)
+	{
+	  affinity = NULL_TREE;
+	  c_parser_consume_token (parser);
+	}
+      else
+	{
+	  affinity = c_parser_expression_conv (parser).value;
+          affinity = c_fully_fold (affinity, false, NULL);
+	}
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+      if (affinity)
+        affinity = upc_affinity_test (affinity_loc, affinity);
+    }
+  else
+    {
+      cond = error_mark_node;
+      incr = error_mark_node;
+      affinity = error_mark_node;
+    }
+  save_break = c_break_label;
+  c_break_label = NULL_TREE;
+  save_cont = c_cont_label;
+  c_cont_label = NULL_TREE;
+  body = c_parser_c99_block_statement (parser);
+  if (profile_upc_forall)
+    {
+      const tree gasp_start = upc_instrument_forall (loc, 1 /* start */);
+      add_stmt (gasp_start);
+    }
+  loc = c_parser_peek_token (parser)->location;
+  if (affinity != NULL_TREE && affinity != error_mark_node)
+    {
+      tree upc_forall_depth = upc_rts_forall_depth_var ();
+      tree inc_depth, depth_gt_one;
+      inc_depth = build_unary_op (loc, PREINCREMENT_EXPR, upc_forall_depth, 0);
+      c_finish_expr_stmt (loc, inc_depth);
+      depth_gt_one = build_binary_op (affinity_loc,
+				      GT_EXPR, upc_forall_depth, integer_one_node, 0);
+      depth_gt_one = c_objc_common_truthvalue_conversion (affinity_loc, depth_gt_one);
+      depth_gt_one = c_fully_fold (depth_gt_one, false, NULL);
+      affinity = build_binary_op (affinity_loc, TRUTH_OR_EXPR,
+                                  depth_gt_one, affinity, 0);
+      body = build3 (COND_EXPR, void_type_node, affinity,
+		     body, NULL_TREE);
+      c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
+      c_finish_expr_stmt (loc,
+        build_unary_op (loc, PREDECREMENT_EXPR, upc_forall_depth, 0));
+    }
+  else
+    c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
+  if (profile_upc_forall)
+    {
+      const tree gasp_end = upc_instrument_forall (loc, 0 /* start */);
+      add_stmt (gasp_end);
+    }
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
+  c_break_label = save_break;
+  c_cont_label = save_cont;
+}
+
+/* Parse an upc-sync-statement.
+
+   upc_barrier, upc_wait, upc_notify
+*/
+
+static void
+c_parser_upc_sync_statement (c_parser *parser, int sync_kind)
+{
+  location_t loc;
+  tree expr = NULL_TREE;
+  tree stmt;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_UPC_BARRIER) ||
+              c_parser_next_token_is_keyword (parser, RID_UPC_NOTIFY) ||
+              c_parser_next_token_is_keyword (parser, RID_UPC_WAIT));
+  loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_token (parser);
+  if (c_parser_peek_token (parser)->type != CPP_SEMICOLON)
+    {
+      expr = c_parser_expression (parser).value;
+      if (expr == error_mark_node)
+        expr = NULL;
+    }
+  stmt = size_int (sync_kind);
+  (void) upc_build_sync_stmt (loc, stmt, expr);
+}
+
 
 /* Handle pragmas.  Some OpenMP pragmas are associated with, and therefore
    should be considered, statements.  ALLOW_STMT is true if we're within
Index: gcc/convert.c
===================================================================
--- gcc/convert.c	(.../trunk)	(revision 175584)
+++ gcc/convert.c	(.../branches/gupc)	(revision 175735)
@@ -44,6 +44,14 @@ convert_to_pointer (tree type, tree expr
   if (TREE_TYPE (expr) == type)
     return expr;
 
+  if (integer_zerop (expr) && POINTER_TYPE_P (type)
+      && upc_shared_type_p (TREE_TYPE (type)))
+    {
+      expr = copy_node (upc_null_pts_node);
+      TREE_TYPE (expr) = build_upc_unshared_type (type);
+      return expr;
+    }
+
   /* Propagate overflow to the NULL pointer.  */
   if (integer_zerop (expr))
     return force_fit_type_double (type, double_int_zero, 0,
@@ -419,6 +427,16 @@ convert_to_integer (tree type, tree expr
       return error_mark_node;
     }
 
+  /* Can't optimize the conversion of UPC shared pointer difference.  */
+  if (ex_form == MINUS_EXPR
+      && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
+      && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1)))
+      && upc_shared_type_p (TREE_TYPE (TREE_TYPE (TREE_OPERAND (expr, 0))))
+      && upc_shared_type_p (TREE_TYPE (TREE_TYPE (TREE_OPERAND (expr, 0)))))
+  {
+      return build1 (CONVERT_EXPR, type, expr);
+  }
+
   /* Convert e.g. (long)round(d) -> lround(d).  */
   /* If we're converting to char, we may encounter differing behavior
      between converting from double->char vs double->long->char.
@@ -536,6 +554,11 @@ convert_to_integer (tree type, tree expr
     {
     case POINTER_TYPE:
     case REFERENCE_TYPE:
+      if (upc_shared_type_p (TREE_TYPE (intype)))
+        {
+          error ("invalid conversion from a UPC pointer-to-shared to an integer");
+	  expr = integer_zero_node;
+        }
       if (integer_zerop (expr))
 	return build_int_cst (type, 0);
 
Index: gcc/langhooks-def.h
===================================================================
--- gcc/langhooks-def.h	(.../trunk)	(revision 175584)
+++ gcc/langhooks-def.h	(.../branches/gupc)	(revision 175735)
@@ -73,7 +73,8 @@ extern tree lhd_callgraph_analyze_expr (
 
 
 /* Declarations for tree gimplification hooks.  */
-extern int lhd_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
+extern int lhd_gimplify_expr (tree *, gimple_seq *, gimple_seq *,
+                              bool (*) (tree), int);
 extern enum omp_clause_default_kind lhd_omp_predetermined_sharing (tree);
 extern tree lhd_omp_assignment (tree, tree, tree);
 struct gimplify_omp_ctx;
@@ -138,9 +139,15 @@ extern void lhd_omp_firstprivatize_type_
   LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR \
 }
 
+/* Hook for lowering function body to GENERIC before finalization.  */
+#define LANG_HOOKS_GENERICIZE lhd_do_nothing_t
+
 /* Hooks for tree gimplification.  */
 #define LANG_HOOKS_GIMPLIFY_EXPR lhd_gimplify_expr
 
+/* Hook for function instrumentation */
+#define LANG_HOOKS_INSTRUMENT_FUNC lhd_do_nothing_t
+
 /* Tree dump hooks.  */
 extern bool lhd_tree_dump_dump_tree (void *, tree);
 extern int lhd_tree_dump_type_quals (const_tree);
@@ -300,7 +307,9 @@ extern void lhd_end_section (void);
   LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS, \
   LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS, \
   LANG_HOOKS_FUNCTION_PARAMETER_PACK_P, \
+  LANG_HOOKS_GENERICIZE, \
   LANG_HOOKS_GIMPLIFY_EXPR, \
+  LANG_HOOKS_INSTRUMENT_FUNC, \
   LANG_HOOKS_BUILTIN_FUNCTION, \
   LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE, \
   LANG_HOOKS_INIT_TS,          \

Comments

Joseph Myers July 1, 2011, 7:28 p.m. UTC | #1
On Fri, 1 Jul 2011, Gary Funck wrote:

> * Most of the #ifdef conditionals have been removed.  Some target macros
> have been defined and documented in tm.texi.  We still have some questions

For each target macro, what is the justification requiring it to be a 
macro rather than a hook documented in target.def with just an @hook line 
in tm.texi.in?  The justification should be one of:

* Macro is used in a case label, defining the values of an enum or some 
other such context that requires a constant value and the code would be 
substantially obfuscated by changing it to avoid this.  (Normally "if" 
statements are preferred to #if conditionals.  Simple use in #if is not 
sufficient justification for a target macro, you need to explain why it is 
necessary to use a preprocessor conditional - for example, if the #if is 
there to control values in an enum.)

* Macro is very closely related to an existing set of macros, such that it 
does not make sense for some members of the set to be hooks while others 
are macros.

* Benchmarking with provided figures has shown significant performance 
regressions from use of a hook.

I looked at the first of the documented macros, and it doesn't seem to be 
a target macro at all, being defined by configure rather than in tm.h.  
Configure-defined macros don't go in tm.texi.  But any that are really 
target macros need such a justification, and it's still preferable to 
define configure-defined macros to 1 or 0 (rather than defined or 
undefined) and test them in "if" statements not #if.
Gary Funck July 1, 2011, 8:34 p.m. UTC | #2
On 07/01/11 19:28:34, Joseph S. Myers wrote:
> On Fri, 1 Jul 2011, Gary Funck wrote:
> GF: * Most of the #ifdef conditionals have been removed.  Some target macros
> GF: have been defined and documented in tm.texi.  We still have some questions
> 
> For each target macro, what is the justification requiring it to be a 
> macro rather than a hook documented in target.def with just an @hook line 
> in tm.texi.in?  The justification should be one of:
[...]

Joseph, thanks for the follow up.

I have several questions on the best method of documenting and
packaging UPC's configuration (and target) specific definition.
I will describe those questions and some potential solutions in
an email, to follow.

- Gary
Jakub Jelinek July 1, 2011, 8:42 p.m. UTC | #3
On Fri, Jul 01, 2011 at 11:31:45AM -0700, Gary Funck wrote:
> @@ -2405,6 +2469,9 @@ struct GTY(()) tree_type_common {
>    alias_set_type alias_set;
>    tree pointer_to;
>    tree reference_to;
> +  /* UPC: for block-distributed arrays */
> +  tree block_factor;
> 

I think this is undesirable.  Using a single bit and looking
it up in a hash table might be a better solution, the vast majority
of the types aren't going to be UPC block distributed arrays.

	Jakub
Gary Funck July 1, 2011, 9:34 p.m. UTC | #4
On 07/01/11 22:42:55, Jakub Jelinek wrote:
> On Fri, Jul 01, 2011 at 11:31:45AM -0700, Gary Funck wrote:
> > @@ -2405,6 +2469,9 @@ struct GTY(()) tree_type_common {
> >    alias_set_type alias_set;
> >    tree pointer_to;
> >    tree reference_to;
> > +  /* UPC: for block-distributed arrays */
> > +  tree block_factor;
> > 
> 
> I think this is undesirable.  Using a single bit and looking
> it up in a hash table might be a better solution, the vast majority
> of the types aren't going to be UPC block distributed arrays.

Jakub, it is true that the vast majority of types will
not have a UPC blocking factor.  However, building a hash table
will be complicated by questions of the scope and lifetime
of the type that references the blocking factor in
a hash table.  Implementing the hash table sounds like
it might be quite a bit of work.

Is there precedent for this technique being used in other GCC front-ends?

Some other fields in a tree_type_common node
are also likely not used by very many types
(or in the case of the symtab info. are only used,
for example, if debug info. is being generated?):

  * attributes
  * reference_to
  * tree_type_symtab
  * name

Is there some way to use the language specific information hook?

    struct GTY(()) tree_type_with_lang_specific {
      struct tree_type_common common;
      /* Points to a structure whose details depend on the language in use.  */
      struct lang_type *lang_specific;
    };

- Gary
Jakub Jelinek July 1, 2011, 10:06 p.m. UTC | #5
On Fri, Jul 01, 2011 at 02:34:41PM -0700, Gary Funck wrote:
> Is there precedent for this technique being used in other GCC front-ends?

Yes, look at DECL_VALUE_EXPR/SET_DECL_VALUE_EXPR/DECL_HAS_VALUE_EXPR_P
or DECL_DEBUG_EXPR/SET_DECL_DEBUG_EXPR/DEBUG_EXPR_IS_FROM.

	Jakub
Mike Stump July 1, 2011, 11:39 p.m. UTC | #6
On Jul 1, 2011, at 2:34 PM, Gary Funck wrote:
> Is there some way to use the language specific information hook?
> 
>    struct GTY(()) tree_type_with_lang_specific {
>      struct tree_type_common common;
>      /* Points to a structure whose details depend on the language in use.  */
>      struct lang_type *lang_specific;
>    };

You can use that to allocate additional data for the frontend's exclusive use.  See the C++ frontend, it uses language specific data.  :-)
Gary Funck July 2, 2011, 5:47 a.m. UTC | #7
On 07/01/11 19:28:34, Joseph S. Myers wrote:
> On Fri, 1 Jul 2011, Gary Funck wrote:
> GF: * Most of the #ifdef conditionals have been removed.  Some target macros
> GF: have been defined and documented in tm.texi.  We still have some questions
>
> [...]
> I looked at the first of the documented macros, and it doesn't seem to be 
> a target macro at all, being defined by configure rather than in tm.h.  
> Configure-defined macros don't go in tm.texi.  But any that are really 
> target macros need such a justification, and it's still preferable to 
> define configure-defined macros to 1 or 0 (rather than defined or 
> undefined) and test them in "if" statements not #if.

I was uncertain where/how to document the macros used to configure UPC.
(Your explanation in the [...] above was helpful in answering
the technical questions that I had in that regard, thanks.)

The patch submitted for review did document (as target macros)
switches that are set by the 'configure' script.  Whether they should
be #defines/not, I'm not sure, and whether they are target specific
I wasn't sure.  Hopefully, the following description will provide
enough background to figure out the best way to handle these
configuration items.

The recent changes were motivated by your original suggestion:

    * It appears you have a large number of #ifdef conditionals
    with no obvious reason for the macros being conditionally
    defined or not defined.  The use of conditional compilation
    like this is deprecated for new code.  If something may
    vary from target to target, use target hooks, not macros,
    and document them in tm.texi (if they are in fact documented
    there in something outside this patch, perhaps you need to
    post that other patch).  Conditions using "if" are strongly
    preferred to those using "#if" whenever possible.

In the version of GUPC that your comments above relate to,
the #define's were primarily in config/upc_conf.h:
http://gcc.gnu.org/viewcvs/branches/gupc/gcc/config/upc-conf.h?revision=173527&view=markup&pathrev=173545

Some of those definitions, which list the names of UPC runtime functions
now in upc/rts-names.h:
http://gcc.gnu.org/viewcvs/branches/gupc/gcc/upc/upc-rts-names.h?revision=173837&view=markup

The definitions that are specific to the representation of the UPC
pointer-to-shared (PTS) type that has been configured by the user were
swept under this corner of the rug in upc/upc-pts.h:
http://gcc.gnu.org/viewcvs/branches/gupc/gcc/upc/upc-pts.h?revision=173837&view=markup

The reason that so many #ifdef's and #defines remain is that
I wasn't sure about the best method of parameterizing those values to
avoid the use of conditional compilation.  For example, should
a small struct be defined that has fields for the configuration-specific
values?

The switching between the files that implement the packed representation
of a pointer-to-shared and those that implemented the struct representation
used to be done in the UPC Makefile fragment Make-lang.in (lines 61 and 62):
http://gcc.gnu.org/viewcvs/branches/gupc/gcc/upc/Make-lang.in?revision=169939&view=markup&pathrev=173545
In that version of GUPC only one of two files upc-pts-packed.c or
upc-pts-struct.c was compiled, depending upon the configuration switch
that selected between the two representations.  Both files defined the
same exported functions.

In an effort to make sure that both implementations are compiled,
a table of PTS operations is defined in the current version of GUPC
in  upc-pts.h:
http://gcc.gnu.org/viewcvs/branches/gupc/gcc/upc/upc-pts.h?revision=173837&view=markup
The table of representation-specific functions is filled in with either
the packed PTS routines or the struct representation routines when
the UPC compiler is initialized.

Where the need for this PTS representation specific logic begins
is controlled by the following UPC configure options:

  --with-upc-pts={struct,packed}
                          choose the representation of a UPC pointer-to-shared
  --with-upc-pts-vaddr-order={last,first}
                          choose position of the address field in UPC
                          pointer-to-shared representation
  --with-packed-upc-pts-bits=phase,thread,vaddr
                          choose bit distribution in packed UPC
                          pointer-to-shared representation

The set of configuration choices looks like this:
PTS Representation
   Packed
      Vaddr: {first, last}
      field sizes: {phase,thread,vaddr}
   Struct
      Vaddr: {first, last}

Although the PTS representation is not target-specific, it has some
aspects of being target-specific in that the representation and
layout of the PTS changes the binary representation of the PTS
in the compiled program (and runtime), and some representations
will perform better/worse on a specific target (for example,
on some targets some UPC programs may run faster if vaddr is first.
Generally, the 'struct PTS' is chosen because it provides the
maximum range of the various fields (at the expense of using
more space to represent the PTS).

Based upon your suggestions/comments, it sounds like:

1. The PTS-related #define's set by 'configure' are not
target macros, and should not be documented as such.

2. The PTS-related operations that are specific either to
the packed or the struct PTS representation are not target
hooks and should not be documented as such.

3. UPC_PTS_VADDR_FIRST currently defined in upc-pts.h:

83 	#ifdef HAVE_UPC_PTS_VADDR_FIRST
84 	#define UPC_PTS_VADDR_FIRST 1
85 	#else
86 	#define UPC_PTS_VADDR_FIRST 0
87 	#endif /* HAVE_UPC_PTS_VADDR_FIRST */

should be set directly to 1 or 0 by 'configure', avoiding the
need to test HAVE_UPC_PTS_VADDR_FIRST with an #ifdef.

4. The #define's in upc-pts.h that are derived based upon PTS-specific
configuration settings:

#ifdef HAVE_UPC_PTS_PACKED_REP
51 	/* 'packed' UPC pointer-to-shared representation */
52 	#define UPC_PTS_SIZE 64
53 	#else
54 	/* 'struct' UPC pointer-to-shared representation */
55 	#define UPC_PTS_SIZE (LONG_TYPE_SIZE + POINTER_SIZE)
56 	#define UPC_PTS_PHASE_SIZE (LONG_TYPE_SIZE/2)
57 	#define UPC_PTS_THREAD_SIZE (LONG_TYPE_SIZE/2)
58 	#define UPC_PTS_VADDR_SIZE POINTER_SIZE
59 	#define UPC_PTS_PHASE_TYPE ((LONG_TYPE_SIZE == 64) ? "uint32_t" : "uint16_t")
60 	#define UPC_PTS_THREAD_TYPE ((LONG_TYPE_SIZE == 64) ? "uint32_t" : "uint16_t")
61 	#define UPC_PTS_VADDR_TYPE "char *"
62 	#endif /* HAVE_UPC_PTS_PACKED_REP */
63 	
64 	#ifdef HAVE_UPC_PTS_VADDR_FIRST
65 	#define UPC_PTS_PHASE_SHIFT 0
66 	#define UPC_PTS_THREAD_SHIFT UPC_PTS_PHASE_SIZE
67 	#define UPC_PTS_VADDR_SHIFT (UPC_PTS_PHASE_SIZE+UPC_PTS_THREAD_SIZE)
68 	#else
69 	#define UPC_PTS_PHASE_SHIFT (UPC_PTS_VADDR_SIZE+UPC_PTS_THREAD_SIZE)
70 	#define UPC_PTS_THREAD_SHIFT UPC_PTS_VADDR_SIZE
71 	#define UPC_PTS_VADDR_SHIFT 0
72 	#endif
73 	#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
74 	#define UPC_PTS_VADDR_MASK ((1L << UPC_PTS_VADDR_SIZE) - 1L)
75 	#elif HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONGLONG
76 	#define UPC_PTS_VADDR_MASK ((1LL << UPC_PTS_VADDR_SIZE) - 1LL)
77 	#else
78 	#error Unexpected "HOST_BITS_PER_WIDE_INT" value.
79 	#endif /* HOST_BITS_PER_WIDE_INT */
80 	#define UPC_PTS_THREAD_MASK ((1 << UPC_PTS_THREAD_SIZE) - 1)
81 	#define UPC_PTS_PHASE_MASK ((1 << UPC_PTS_PHASE_SIZE) - 1)

Should be moved into a 'struct' that is filled in with the UPC
compiler is initialized.  This can be done by the representation
specific 'init' routine.

Does that make sense?

- Gary
Gary Funck July 2, 2011, 6:13 a.m. UTC | #8
On 07/02/11 00:06:07, Jakub Jelinek wrote:
> Yes, look at DECL_VALUE_EXPR/SET_DECL_VALUE_EXPR/DECL_HAS_VALUE_EXPR_P
> or DECL_DEBUG_EXPR/SET_DECL_DEBUG_EXPR/DEBUG_EXPR_IS_FROM.

OK, thanks.  The UPC front end will be changed use a similar method to
encode UPC's block size.
Gary Funck July 2, 2011, 6:16 a.m. UTC | #9
On 07/01/11 16:39:55, Mike Stump wrote:
> You can use that to allocate additional data for the frontend's exclusive use. 
> See the C++ frontend, it uses language specific data.  :-)

Heh.  It sounds like this language-specific hook works well for language
front-ends that aren't sharing the logic of the "C" front end.
Therefore, a no-go for UPC.
Joseph Myers July 2, 2011, 3:21 p.m. UTC | #10
On Fri, 1 Jul 2011, Gary Funck wrote:

> The reason that so many #ifdef's and #defines remain is that
> I wasn't sure about the best method of parameterizing those values to
> avoid the use of conditional compilation.  For example, should
> a small struct be defined that has fields for the configuration-specific
> values?

You need to make a technical judgement among possible approaches - which 
may include such a structure, or a structure of function pointers, or 
conditionals at various places in the code.

> Although the PTS representation is not target-specific, it has some
> aspects of being target-specific in that the representation and
> layout of the PTS changes the binary representation of the PTS
> in the compiled program (and runtime), and some representations
> will perform better/worse on a specific target (for example,
> on some targets some UPC programs may run faster if vaddr is first.
> Generally, the 'struct PTS' is chosen because it provides the
> maximum range of the various fields (at the expense of using
> more space to represent the PTS).

In general configure options aren't really a good idea in many cases:

* If something is always best on a particular architecture, maybe you want 
a target hook (not macro) rather than a configure option, with the target 
hook being set appropriately for each target and no option for the person 
configuring GCC to override.

* If what's best depends on the particular application, a normal 
command-line option for the person using GCC to use is better (and then 
any configure option can just control specs in the driver and not directly 
affect the rest of the compiler).  That might run into problems if there's 
a runtime library included with GCC that can only be built compatibly with 
one of the possible ABIs at a time, though it may be possible to avoid 
this issue in some cases (for example, using different function names for 
the different ABIs; cf. how libstdc++ works with both 64-bit and 128-bit 
long double on various targets).  (Actually multilibbing the library for 
each ABI variant - in addition to the existing multilibbing for all GCC's 
runtime libraries - would be better in some cases but harder to 
implement.)

Even if you need a configure option for the default, the command-line 
options may still be useful in some cases for testing and debugging 
purposes.
Gary Funck July 2, 2011, 6:59 p.m. UTC | #11
On 07/02/11 15:21:32, Joseph S. Myers wrote:
[...]
> In general configure options aren't really a good idea in many cases:
> 
> * If something is always best on a particular architecture, maybe you want 
> a target hook (not macro) rather than a configure option, with the target 
> hook being set appropriately for each target and no option for the person 
> configuring GCC to override.

With UPC, the packed pointer-to-shared (PTS) representation takes
less space and is generally useful for most applications.  However,
it is sometimes necessary to allocate more bits for the number of
threads, and less for the block offset for example, which makes
it possible to continue to use the packed PTS representation in
certain applications.  This motivates the 'configure' setting.

The 'struct' PTS has essentially no limitations but the
pointers-to-shared are bigger and accessing the sub-fields of this
"fat pointer" is somewhat slower.  Also, passing 'struct' based
PTS's as arguments (to the runtime for example) can be slower on
some architectures.

The difficulty with making this representation choice a
compile-time selection is that the runtime needs to be aware of
the pointer-to-shared layout.  Perhaps we could build two separate
runtimes (packed PTS and struct PTS) and parameterize the packed
PTS based runtime to calculate the shifts and masks it needs rather
than compiling them as constants, but that will probably impact
performance on various commonly called paths through the runtime.

> Even if you need a configure option for the default, the command-line 
> options may still be useful in some cases for testing and debugging 
> purposes.

Yes, that would be useful.
Gary Funck July 2, 2011, 8:07 p.m. UTC | #12
Off list, Mike S. pointed out that the Objective C
front-end uses the lang-specific extensions to
GCC's tree node, and it shares logic with the C
and C++ front ends.  Therefore, the lang-specific
extensions might offer an alternative approach
for storing UPC's layout qualifier.  The current plan,
however, is to use a hash table.
Gary Funck Aug. 17, 2011, 3:38 p.m. UTC | #13
I have been looking at changing UPC's method of 
recording the blocking factor so that it uses less space
in the tree type node.  The suggested method for
achieving this space reduction is to use a hash table to
map pointers to type nodes into UPC blocking factors
(for less commonly used blocking factor values). 

In UPC, the default blocking factor for arrays is one,
and for UPC shared scalar/struct variables it is zero.
Therefore, the current approach is to only record
blocking factors greater than one in a hash table.

The basics are in place (in tree.h):

--------------------------------------------------------------------
/* Non-zero if the UPC shared type refers to THREADS
   in its array dimension.  */
#define UPC_TYPE_HAS_THREADS_FACTOR(TYPE) TYPE_LANG_FLAG_3 (TYPE)

/* Non-zero if the UPC blocking factor is 0.  */
#define UPC_TYPE_HAS_BLOCK_FACTOR_0(TYPE) TYPE_LANG_FLAG_4 (TYPE)

/* Non-zero if the UPC blocking factor is greater than 1.
   In this case, the blocking factor value is stored in a hash table.  */
#define UPC_TYPE_HAS_BLOCK_FACTOR_X(TYPE) TYPE_LANG_FLAG_5 (TYPE)

extern void upc_block_factor_insert (tree, tree);
extern tree upc_block_factor_lookup (tree);

/* Return the UPC blocking factor of the type given by NODE.
   The default block factor is one.  The additional flag bits
   over-ride the default.  */
#define UPC_TYPE_BLOCK_FACTOR(NODE) \
  (UPC_TYPE_HAS_BLOCK_FACTOR_0 (NODE) ? size_zero_node \
   : UPC_TYPE_HAS_BLOCK_FACTOR_X (NODE) ? upc_block_factor_lookup (NODE) \
   : size_one_node)
--------------------------------------------------------------------

Note above, that the bits used are the TYPE_LANG_FLAG bits.
This should be acceptable for UPC, because it is built as
a language variant.

Interestingly, if additional bits were allocated just for UPC,
they would likely increase the size of the tree node, because
there are no spare bits here:

struct GTY(()) tree_type_common {
  [....]
  unsigned int precision : 10;
  [...]
  unsigned lang_flag_6 : 1;

The bit field sizes in the interval shown above total to 32 bits.
Therefore, it seems that any attempt to add new flag bits will
likely increase the size of a tree_type_common node.
--------------------------------------------------------------------

The issue that I'm running into, however, is that the
re-implementation of UPC_TYPE_BLOCK_FACTOR() is not
plug-and-play with its previous version that used
a tree pointer in the node to record the blocking factor.

Here's why:

gcc/tree.c|5681 col 27| warning: passing argument 1 of
 ‘upc_block_factor_lookup’ discards qualifiers from pointer target type
gcc/tree.h|1196 col 13| note: expected ‘tree’ but argument is of type ‘const_tree’

The code referenced above is:

--------------------------------------------------------------------
bool
check_qualified_type (const_tree cand, const_tree base, int type_quals)
{
  return (TYPE_QUALS (cand) == type_quals
[...]
          /* For UPC, the blocking factors have to be equal. */
          && tree_int_cst_equal (UPC_TYPE_BLOCK_FACTOR (cand),
                                 UPC_TYPE_BLOCK_FACTOR (base))
[...]
}         
--------------------------------------------------------------------

The prototype for upc_block_factor_lookup() accepts a 'tree', not
a 'const_tree'.  If the parameter is changed to 'const_tree',
then the body of the procedure will encounter another 'const' clash
because a tree_map is defined as having nodes of type 'tree',
not 'const_tree'.  For example,

struct GTY(()) tree_map_base {
  tree from;
};
--------------------------------------------------------------------

NOTE: I looked at calls to DECL_VALUE_EXPR() to see if it ran
into this issue, however, only 'tree' nodes appear to be passed
to this function macro.

Any suggestions on how to work around this 'const' clash warning?

Thanks,
- Gary
Gary Funck Aug. 31, 2011, 12:16 a.m. UTC | #14
On 08/17/11 08:38:44, Gary Funck wrote:
> 
> I have been looking at changing UPC's method of 
> recording the blocking factor so that it uses less space
> in the tree type node.  The suggested method for
> achieving this space reduction is to use a hash table to
> map pointers to type nodes into UPC blocking factors
> (for less commonly used blocking factor values). 
[...]
> The issue that I'm running into, however, is that the
> re-implementation of UPC_TYPE_BLOCK_FACTOR() is not
> plug-and-play with its previous version that used
> a tree pointer in the node to record the blocking factor.
[...]

As a follow up, I wasn't able to find an alternative method
that preserved the const'ness of the API's involved in
the change, so ended up reverting them back to regular tree pointers.
The following change was committed to the GUPC branch.

2011-08-30  Gary Funck  <gary@intrepid.com>

        * tree.h (check_qualified_type): Change 'const_tree'
        argument types back to 'tree' to avoid complaints
        of assignment drops qualifiers for invocations of the
        newly implemented TYPE_BLOCK_FACTOR() macro, which
        invokes hash functions with 'tree' pointer values that
        are not const qualified.
        * tree.c (check_qualified_type, check_aligned_type): Ditto.
        * c-typeck.c (comptypes_internal): Ditto.
Gary Funck Oct. 10, 2011, 5:02 p.m. UTC | #15
Recently, a few UPC test programs failed to compile
due to mis-matches of parameters in a prototype and its
corresponding function definition.  The mis-match was
based upon the apparent inequality of UPC layout qualifiers
(blocking factors).

UPC blocking factors are integer constants.  They are
recorded in a hash table indexed by the type tree node
that they correspond to.

Currently, the test for equality of blocking factors
tests only the pointer to the tree node defining the constant.
All blocking factors are recorded as "sizetype" type'd nodes.
Given that integer constants are hashed by type/value, it seemed
safe to assume that a given blocking factor would map to
a single tree node due to the underlying hash method that is used
when integral constants are created.

Is it valid to assume that pointer equality is sufficient
to ensure that two integer constants are equal as long
as their type and values are equal?

The bug that we ran into occurred because a garbage collection
pass was run between the point that the function prototype
tree node was created and the point at which the function declaration
was processed.  The garbage collector decided that the integer
constant representing the blocking factor was no longer in use,
because it had not been marked.

In fact, the integer constant was needed because it appeared
in the blocking factor hash table, but not via a direct pointer.
Rather it was referenced by nature of the fact that
the blocking factor hash table referenced the integer constant
that is mapped in the integer constant hash table.

Here's a rough diagram:

   tree (type) -> [ blocking factor hash ] -> tree (integer constant)
   tree (integer constant) -> [ integer constant hash ] {unique map}
                              -> tree (integer constant)

When the garbage collector deleted the entry from the
"integer constant hash", it forced a new integer constant tree
node to be created for the same (type, value) integral constant
blocking factor.

One easy way to address the current issue is to call
tree_int_cst_equal() if the integer constant tree pointers
do not match:

    if ((c1 != c2) && !tree_int_cst_equal (c1, c2))
      /* integer constants aren't equal.  */

This may be necessary if 'int_cst_hash_table' is viewed as
a cache rather than a persistent, unique mapping.

Another approach, would be to somehow mark the node
in int_cst_hash_table as in use when the blocking factor
hash table is traversed by the garbage collector, or
to add logic the hash table delete function associated
with int_cst_hash_table; to dis-allow the delete if the
integer constant is present in the UPC blocking factor
hash table.

To effect this change in a modular way probably the hash table
delete function associated with 'int_cst_hash_table' would have
to be daisy-chained, where the UPC blocking factor check is made
first.  The difficulty with implementing the daisy chaining is that
int_cst_hash_table needs to exist before the UPC-related initialization
code is run.  One way to handle this might be yet another language
hook, called from the code that creates 'int_cst_hash_table'.
That seems overly complex.

For reference, the current blocking factor mapping table
is created as follows:

  upc_block_factor_for_type = htab_create_ggc (512, tree_map_hash,
                                               tree_map_eq, 0);

Summary:

1. Is it valid to assume that pointer equality is sufficient
to compare two integer constants for equality as long as they
have identical type and value?

2. Should 'int_cst_hash_table' be viewed as a cache, where
the mapping of a given (type, value) integer constant may
vary over time?

3. If the answer to 1. is "yes" and the answer to 2. is "no"
then what is the recommended way to ensure that nodes in
'int_cst_hash_table' are not removed if the integer constant
is being referenced via the 'upc_block_factor_for_type'
hash table?

thanks,
- Gary
Richard Biener Oct. 11, 2011, 8:24 a.m. UTC | #16
On Mon, Oct 10, 2011 at 7:02 PM, Gary Funck <gary@intrepid.com> wrote:
> Recently, a few UPC test programs failed to compile
> due to mis-matches of parameters in a prototype and its
> corresponding function definition.  The mis-match was
> based upon the apparent inequality of UPC layout qualifiers
> (blocking factors).
>
> UPC blocking factors are integer constants.  They are
> recorded in a hash table indexed by the type tree node
> that they correspond to.
>
> Currently, the test for equality of blocking factors
> tests only the pointer to the tree node defining the constant.
> All blocking factors are recorded as "sizetype" type'd nodes.
> Given that integer constants are hashed by type/value, it seemed
> safe to assume that a given blocking factor would map to
> a single tree node due to the underlying hash method that is used
> when integral constants are created.
>
> Is it valid to assume that pointer equality is sufficient
> to ensure that two integer constants are equal as long
> as their type and values are equal?
>
> The bug that we ran into occurred because a garbage collection
> pass was run between the point that the function prototype
> tree node was created and the point at which the function declaration
> was processed.  The garbage collector decided that the integer
> constant representing the blocking factor was no longer in use,
> because it had not been marked.
>
> In fact, the integer constant was needed because it appeared
> in the blocking factor hash table, but not via a direct pointer.
> Rather it was referenced by nature of the fact that
> the blocking factor hash table referenced the integer constant
> that is mapped in the integer constant hash table.
>
> Here's a rough diagram:
>
>   tree (type) -> [ blocking factor hash ] -> tree (integer constant)
>   tree (integer constant) -> [ integer constant hash ] {unique map}
>                              -> tree (integer constant)
>
> When the garbage collector deleted the entry from the
> "integer constant hash", it forced a new integer constant tree
> node to be created for the same (type, value) integral constant
> blocking factor.
>
> One easy way to address the current issue is to call
> tree_int_cst_equal() if the integer constant tree pointers
> do not match:
>
>    if ((c1 != c2) && !tree_int_cst_equal (c1, c2))
>      /* integer constants aren't equal.  */
>
> This may be necessary if 'int_cst_hash_table' is viewed as
> a cache rather than a persistent, unique mapping.
>
> Another approach, would be to somehow mark the node
> in int_cst_hash_table as in use when the blocking factor
> hash table is traversed by the garbage collector, or
> to add logic the hash table delete function associated
> with int_cst_hash_table; to dis-allow the delete if the
> integer constant is present in the UPC blocking factor
> hash table.
>
> To effect this change in a modular way probably the hash table
> delete function associated with 'int_cst_hash_table' would have
> to be daisy-chained, where the UPC blocking factor check is made
> first.  The difficulty with implementing the daisy chaining is that
> int_cst_hash_table needs to exist before the UPC-related initialization
> code is run.  One way to handle this might be yet another language
> hook, called from the code that creates 'int_cst_hash_table'.
> That seems overly complex.
>
> For reference, the current blocking factor mapping table
> is created as follows:
>
>  upc_block_factor_for_type = htab_create_ggc (512, tree_map_hash,
>                                               tree_map_eq, 0);
>
> Summary:
>
> 1. Is it valid to assume that pointer equality is sufficient
> to compare two integer constants for equality as long as they
> have identical type and value?

Yes, if both constants are "live"

> 2. Should 'int_cst_hash_table' be viewed as a cache, where
> the mapping of a given (type, value) integer constant may
> vary over time?

Yes, if a constant is unused it may get collected and re-allocated
later.  Cannot be observed from any valid use of 1.

> 3. If the answer to 1. is "yes" and the answer to 2. is "no"
> then what is the recommended way to ensure that nodes in
> 'int_cst_hash_table' are not removed if the integer constant
> is being referenced via the 'upc_block_factor_for_type'
> hash table?

You need to ensure the constants are marked properly.

Richard.

> thanks,
> - Gary
>
Eric Botcazou Oct. 11, 2011, 9:05 a.m. UTC | #17
> In fact, the integer constant was needed because it appeared
> in the blocking factor hash table, but not via a direct pointer.
> Rather it was referenced by nature of the fact that
> the blocking factor hash table referenced the integer constant
> that is mapped in the integer constant hash table.

You'd need to elaborate here: what does "by nature of the fact that" mean?

> When the garbage collector deleted the entry from the
> "integer constant hash", it forced a new integer constant tree
> node to be created for the same (type, value) integral constant
> blocking factor.
>
> One easy way to address the current issue is to call
> tree_int_cst_equal() if the integer constant tree pointers
> do not match:
>
>     if ((c1 != c2) && !tree_int_cst_equal (c1, c2))
>       /* integer constants aren't equal.  */

You have two objects C1 and C2 for the same constant and you're comparing them.
One was created first, say C1.  If C1 was still live when C2 was created, why 
was C2 created in the first class?  If C1 wasn't live anymore when C2 was 
created, why are you still using C1 here?
Gary Funck Oct. 11, 2011, 5:06 p.m. UTC | #18
On 10/11/11 10:24:52, Richard Guenther wrote:
> GF: 1. Is it valid to assume that pointer equality is sufficient
> GF: to compare two integer constants for equality as long as they
> GF: have identical type and value?
> 
> Yes, if both constants are "live"

The upc blocking factor hash table is declared as follows:

static GTY ((if_marked ("tree_map_marked_p"),
           param_is (struct tree_map)))
     htab_t upc_block_factor_for_type;
[...]
  upc_block_factor_for_type = htab_create_ggc (512, tree_map_hash,
                                               tree_map_eq, 0);

I had hoped that this would be sufficient to ensure that all
integer constant references recorded in this hash table would
be considered "live" by the GC.  Reading the code in tree_map_marked_p(),
however, I see the following:

#define tree_map_marked_p tree_map_base_marked_p
[...]
/* Return true if this tree map structure is marked for garbage collection
   purposes.  We simply return true if the from tree is marked, so that this
   structure goes away when the from tree goes away.  */

int
tree_map_base_marked_p (const void *p)
{ 
  return ggc_marked_p (((const struct tree_map_base *) p)->from);
}

This takes care of recycling an entry when the '->from' reference
goes away, but it doesn't make sure that the '->to' reference is
considered "live".  I don't understand the GC well enough to
know when/where the '->to' entry should be marked as "live".

(note: in the cited test case, the ->from pointers in question
are known to be "live" and did survive garbage collection.)

Given that the declaration above tells the GC that the nodes
in the blocking factor hash table are of type 'struct tree_map',

struct GTY(()) tree_map_base {
  tree from;
};


/* Map from a tree to another tree.  */

struct GTY(()) tree_map {
  struct tree_map_base base;
  unsigned int hash;
  tree to;
};

I thought that the GC would mark the ->to nodes as
live automatically?  (note: probably the only direct
reference to the integer constant that is the focus of
this discussion is in the upc_block_factor_for_type hash table.
Therefore, if it isn't seen as "live" there, it won't be seen
as live anywhere else.)

I suppose that I could declare a linear "tree list" of mapped integer
constants and let the GC walk that, but that is more of a hack than a solution.

- Gary
Gary Funck Oct. 12, 2011, 6:37 a.m. UTC | #19
On 10/11/11 11:05:18, Eric Botcazou wrote:
> > One easy way to address the current issue is to call
> > tree_int_cst_equal() if the integer constant tree pointers
> > do not match:
> >
> >     if ((c1 != c2) && !tree_int_cst_equal (c1, c2))
> >       /* integer constants aren't equal.  */
> 
> You have two objects C1 and C2 for the same constant and you're comparing
> them. One was created first, say C1.  If C1 was still live when C2 was
> created, why was C2 created in the first class?  If C1 wasn't live
> anymore when C2 was created, why are you still using C1 here?

Eric, this note provides some more detail in addition to my
earlier reply to Richard.

The problem is that the references to object C1 and C2 live in
a hash table, and that although the referenced nodes will be retained
by the garbage collector, their mapping in int_cst_hash_table is
deleted by the GC.

Thus, if we follow the diagram:

 tree (type) -> [ upc_block_factor_for_type ]
                 -> tree (integer constant)
 tree (integer constant) -> [ int_cst_hash_table ] {unique map}
                         -> tree (integer constant)

Given two tree nodes, P (prototype) and F (function) they declare
a parameter that is pointer to a UPC shared object and this pointer
is declared with a UPC blocking factor of 1000.  Without garbage
collection, the mappings look like this:

 P.param -> C1, F.param -> C1 where C1 is an integer constant of
                           the form (sizetype, 1000).

but when GC kicks in, it decides that the hash table entry
in int_cst_hash_table can be deleted because it doesn't think
that C1 is live.  Therefore the next attempt to map (sizetype, 1000)
will yield a new integral constant tree node, C2.  Then the mapping
changes to: P.param -> C1, F.param -> C2, and we can no longer use

  TYPE_UPC_BLOCKING_FACTOR (P.param) == TYPE_UPC_BLOCKING_FACTOR (F.param)

to check that the blocking factors of P.param and F.param are equal.

For the GC to know that int_cst_hash_table
entry is needed, perhaps the upc_block_factor_for_type needs
to be traversed, and then each integer constant needs to be
"marked", or the constant has to be hashed into int_cst_hash_table
and the actual hash table entry has to be marked.

I am not familiar with the details of garbage collection and
pretty much just try use existing code as a model.  Apparently,
this sequence of statements is insufficient to tell the GC that it should
mark the integer constants referenced in this hash table as "in use".

  static GTY ((if_marked ("tree_map_marked_p"),
	     param_is (struct tree_map)))
       htab_t upc_block_factor_for_type;
[...]
 upc_block_factor_for_type = htab_create_ggc (512, tree_map_hash
                                              tree_map_eq, 0);

Reading the GC code:

static int
ggc_htab_delete (void **slot, void *info)
{
  const struct ggc_cache_tab *r = (const struct ggc_cache_tab *) info;

  if (! (*r->marked_p) (*slot))
    htab_clear_slot (*r->base, slot);
  else
    (*r->cb) (*slot);

  return 1;
}

It appears that the int_cst_hash_table entry for C1 needs to be
marked or it will be cleared.  I don't know how to set things
up so that so that the garbage collecting mechanisms are in
place to do that, and was hoping that tree_map_hash table
would provide the required mechanisms.  Apparently, this is
not the case.

I had hoped that this declaration would be sufficient to convince
the GC to consider all mapped integer constant nodes to be "live".
If not, then perhaps I need a GC hook associated with
upc_block_factor_for_type that does something like the following:

  for t (each used upc_block_factor_for_type entry):
    c = t.to  # the mapped integer constant
    if is_integer_constant (c):
      h = int_cst_hash_table.hash(c)
      gc_mark_htab (int_cst_hash_table, h)

or perhaps this is sufficient?

  for t (each used upc_block_factor_for_type entry):
    c = t.to
    gc_mark_tree_node (c)

However, I thought that this would already have been done
automatically by the GC hash tree implementation.

If either of those methods are required, I would appreciate
suggestions/pointers/code that would help me make sure that
this approach is implemented correctly.

thanks,
- Gary
Eric Botcazou Oct. 12, 2011, 7:27 a.m. UTC | #20
> The problem is that the references to object C1 and C2 live in
> a hash table, and that although the referenced nodes will be retained
> by the garbage collector, their mapping in int_cst_hash_table is
> deleted by the GC.

This isn't a simple hash table, is it?

> I am not familiar with the details of garbage collection and
> pretty much just try use existing code as a model.  Apparently,
> this sequence of statements is insufficient to tell the GC that it should
> mark the integer constants referenced in this hash table as "in use".
>
>   static GTY ((if_marked ("tree_map_marked_p"),
> 	     param_is (struct tree_map)))
>        htab_t upc_block_factor_for_type;
> [...]
>  upc_block_factor_for_type = htab_create_ggc (512, tree_map_hash
>                                               tree_map_eq, 0);

This is a map so it is garbage-collected as a map: if the key isn't marked, 
then the value isn't either.  Hence 2 questions:
 - why using a map and not a simple hash table?
 - what is the key and why isn't it marked?
Gary Funck Oct. 12, 2011, 7:55 a.m. UTC | #21
On 10/12/11 09:27:43, Eric Botcazou wrote:
> > The problem is that the references to object C1 and C2 live in
> > a hash table, and that although the referenced nodes will be retained
> > by the garbage collector, their mapping in int_cst_hash_table is
> > deleted by the GC.
> 
> This isn't a simple hash table, is it?

At the moment, it is a simple garbage collected hash table, yes.

It maps a type node into a corresponding integer node that is
the "blocking factor" associated with the type node.  Before
the advent of this hash table the blocking factor was stored
in a dedicated field in the tree type node.  The suggestion was
made to move this into a hash table to save space.  I chose
the "tree map" hash table because I thought it could do the job.
And does work well, except when the GC steps in and decides
to remove a node from int_cst_hash_table, because it thinks
that the integer constant is no longer needed.

> This is a map so it is garbage-collected as a map: if the key isn't marked, 
> then the value isn't either. 

The keys are valid.  In the example discussed in this thread,
there is a pointer to type node that used in a parameter declaration
of a function prototype and also in the similarly named parameter
of the function definition.  Both tree pointers are used as keys,
and they are "live" at the point that the GC runs.

> Hence 2 questions:
>  - why using a map and not a simple hash table?

I had thought that the garbage collected nature of the
map would perhaps save some space and better track the
lifetimes of the type nodes that have a UPC blocking factor.

It would be easy enough to switch to a hash table that is
not garbage collected and where entries once allocated
remain that way until the end of the compilation.

>  - what is the key and why isn't it marked?

The key is a type.  The value is an "sizetype" integer constant.

/* Return the UPC blocking factor of the type given by NODE.
   The default block factor is one.  The additional flag bits
   over-ride the default.  */
#define TYPE_BLOCK_FACTOR(NODE) \
  (TYPE_SHARED (NODE) \
    ? (TYPE_HAS_BLOCK_FACTOR_0 (NODE) ? size_zero_node \
      : TYPE_HAS_BLOCK_FACTOR_X (NODE) ? upc_block_factor_lookup (NODE) \
      : NULL_TREE) \
    : NULL_TREE)

A blocking factor of 0 is a special case, it is encoded
as a flag.  Otherwise, if the blocking factor has been set,
then TYPE_HAS_BLOCK_FACTOR_X() is true, and the blocking
factor for NODE is looked up in a hash table.
Eric Botcazou Oct. 12, 2011, 8:29 a.m. UTC | #22
> It maps a type node into a corresponding integer node that is
> the "blocking factor" associated with the type node.  Before
> the advent of this hash table the blocking factor was stored
> in a dedicated field in the tree type node.  The suggestion was
> made to move this into a hash table to save space.  I chose
> the "tree map" hash table because I thought it could do the job.

So this isn't a simple hash table since this is a map.  A simple hash table 
doesn't store the key in the slot, only the value; a map does.

> The keys are valid.  In the example discussed in this thread,
> there is a pointer to type node that used in a parameter declaration
> of a function prototype and also in the similarly named parameter
> of the function definition.  Both tree pointers are used as keys,
> and they are "live" at the point that the GC runs.

But somehow they aren't marked by the GC.  You need to find out why, since the 
value will be kept only if the key is already marked by the GC.

By the time a GC pass is run, all trees to be kept must be linked to a GC root.
You said that the pass was run "between the point that the function prototype
tree node was created and the point at which the function declaration was 
processed".  To which GC root are the keys linked between these points?
Richard Biener Oct. 12, 2011, noon UTC | #23
On Wed, Oct 12, 2011 at 10:29 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> It maps a type node into a corresponding integer node that is
>> the "blocking factor" associated with the type node.  Before
>> the advent of this hash table the blocking factor was stored
>> in a dedicated field in the tree type node.  The suggestion was
>> made to move this into a hash table to save space.  I chose
>> the "tree map" hash table because I thought it could do the job.
>
> So this isn't a simple hash table since this is a map.  A simple hash table
> doesn't store the key in the slot, only the value; a map does.
>
>> The keys are valid.  In the example discussed in this thread,
>> there is a pointer to type node that used in a parameter declaration
>> of a function prototype and also in the similarly named parameter
>> of the function definition.  Both tree pointers are used as keys,
>> and they are "live" at the point that the GC runs.
>
> But somehow they aren't marked by the GC.  You need to find out why, since the
> value will be kept only if the key is already marked by the GC.
>
> By the time a GC pass is run, all trees to be kept must be linked to a GC root.
> You said that the pass was run "between the point that the function prototype
> tree node was created and the point at which the function declaration was
> processed".  To which GC root are the keys linked between these points?

I think there is an issue when two cache htabs refer to each other
with respect to GC, you might search the list to find out more.

Richard.

> --
> Eric Botcazou
>
Gary Funck Oct. 12, 2011, 4:27 p.m. UTC | #24
On 10/12/11 14:00:54, Richard Guenther wrote:
> I think there is an issue when two cache htabs refer to each other
> with respect to GC, you might search the list to find out more.

Richard, thanks.  I thought that might be the case, but
I don't understand the GC well enough to make this determination.

- Gary
Eric Botcazou Oct. 12, 2011, 9:01 p.m. UTC | #25
> I think there is an issue when two cache htabs refer to each other
> with respect to GC, you might search the list to find out more.

I'm not sure this is the case here, there seems to be a clear hierarchy.
Laurynas Biveinis Oct. 13, 2011, 3:15 a.m. UTC | #26
2011/10/11 Gary Funck <gary@intrepid.com>:
> static GTY ((if_marked ("tree_map_marked_p"),
>           param_is (struct tree_map)))
>     htab_t upc_block_factor_for_type;
> [...]
>  upc_block_factor_for_type = htab_create_ggc (512, tree_map_hash,
>                                               tree_map_eq, 0);
>
> I had hoped that this would be sufficient to ensure that all
> integer constant references recorded in this hash table would
> be considered "live" by the GC.  Reading the code in tree_map_marked_p(),
> however, I see the following:
>
> #define tree_map_marked_p tree_map_base_marked_p
> [...]
> /* Return true if this tree map structure is marked for garbage collection
>   purposes.  We simply return true if the from tree is marked, so that this
>   structure goes away when the from tree goes away.  */
>
> int
> tree_map_base_marked_p (const void *p)
> {
>  return ggc_marked_p (((const struct tree_map_base *) p)->from);
> }
>
> This takes care of recycling an entry when the '->from' reference
> goes away, but it doesn't make sure that the '->to' reference is
> considered "live".  I don't understand the GC well enough to
> know when/where the '->to' entry should be marked as "live".

If "->from" is marked, then GC will mark the whole hash table entry,
including the tree_map::to field.

Currently I believe that your issue is one hash table pointing to
another one.  Basically all the objects that need to be live must be
known before the hash table marking starts, either by being already
marked in that GC run, either by having mark bits set somewhere where
if_marked option will check them correctly. In your case (correct me
if I misunderstood something) you have one hash table, marking of
which will mark more objects which are required for the correct
marking of the second hash table. GC might be simply walking the
second one first.
Gary Funck Oct. 13, 2011, 7:08 a.m. UTC | #27
On 10/13/11 06:15:31, Laurynas Biveinis wrote:
> [...] In your case (correct me if I misunderstood something)
> you have one hash table, marking of which will mark more objects
> which are required for the correct marking of the second hash table.
> GC might be simply walking the second one first.

Yes, I think that this accurately summarizes the situation, and the result.

Any suggestions on how to fix this?  It seems that one fix might
be to use a non garbage-collected hash table for the hash map.

- Gary
Laurynas Biveinis Oct. 13, 2011, 12:41 p.m. UTC | #28
2011/10/13 Gary Funck <gary@intrepid.com>:
> On 10/13/11 06:15:31, Laurynas Biveinis wrote:
>> [...] In your case (correct me if I misunderstood something)
>> you have one hash table, marking of which will mark more objects
>> which are required for the correct marking of the second hash table.
>> GC might be simply walking the second one first.
>
> Yes, I think that this accurately summarizes the situation, and the result.
>
> Any suggestions on how to fix this?  It seems that one fix might
> be to use a non garbage-collected hash table for the hash map.

Is it feasible to write an if_marked function for the second hash
table that would duplicate the work of the first hash table function
and then some? I.e. it would determine if an entry needs to be marked
based on information outside of both hash tables and independently of
the first one (even if duplicating its logic).
diff mbox

Patch

--- gcc/tree.h	(.../trunk)	(revision 175584)
+++ gcc/tree.h	(.../branches/gupc)	(revision 175683)
@@ -462,8 +462,11 @@  struct GTY(()) tree_base {
   unsigned packed_flag : 1;
   unsigned user_align : 1;
   unsigned nameless_flag : 1;
+  unsigned upc_shared_flag : 1;
+  unsigned upc_strict_flag : 1;
+  unsigned upc_relaxed_flag : 1;
 
-  unsigned spare : 12;
+  unsigned spare : 9;

@@ -2405,6 +2469,9 @@  struct GTY(()) tree_type_common {
   alias_set_type alias_set;