public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* RFC: [GUPC] UPC-related front-end changes
@ 2010-07-08  6:17 Gary Funck
  2010-07-08 15:07 ` Tom Tromey
                   ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: Gary Funck @ 2010-07-08  6:17 UTC (permalink / raw)
  To: Gcc Patches; +Cc: Joseph Myers, Richard Henderson

[-- Attachment #1: Type: text/plain, Size: 14143 bytes --]


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 (161517), and has been
bootstrapped on both x86_64 Linux and i686 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 differnces
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.

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 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, when the designated shared
object has affinity to the referencing thread.

A "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.

--- gcc/tree.h	(.../trunk)	(revision 161517)
+++ gcc/tree.h	(.../branches/gupc)	(revision 161914)
@@ -367,6 +367,12 @@ struct GTY(()) tree_base {
   unsigned asm_written_flag: 1;
   unsigned nowarning_flag : 1;
 
+  /* UPC flags */
+  unsigned shared_flag : 1;		/* UPC: shared  qualified */
+  unsigned strict_flag : 1;		/* UPC: strict  qualified */
+  unsigned relaxed_flag : 1;		/* UPC: relaxed qualified */
+  unsigned upc_unused : 5;		/* UPC: unused bits  */

--- gcc/c-tree.h	(.../trunk)	(revision 161517)
+++ gcc/c-tree.h	(.../branches/gupc)	(revision 161914)
@@ -221,6 +261,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;

UPC defines a few additional tree node types:

+++ gcc/upc/upc-tree.def	(.../branches/gupc)	(revision 161914)
+/* 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)

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

--- gcc/c-family/c-common.c	(.../trunk)	(revision 161517)
+++ gcc/c-family/c-common.c	(.../branches/gupc)	(revision 161914)
[...]
+
+  /* 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 161517)
+++ gcc/c-family/c-pragma.c	(.../branches/gupc)	(revision 161914)
[...]
+/*
+ *  #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:

+  /* 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");
+      else
+        {
+          specs->upc_layout_qualifier = qual;
+          qual = ridpointers[RID_SHARED];
+        }
+    }
[...]
+
+	    /* 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;

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:

+/* In upc-act.c and stub-upc.c */
+extern int count_upc_threads_refs (tree);
+extern int is_multiple_of_upc_threads (tree);
+extern int upc_check_decl_init (tree, tree);
+extern int upc_is_null_pts_p (tree);
+extern int upc_pts_cvt_op_p (tree);
+extern int upc_shared_type_p (tree);
+extern struct c_expr upc_blocksizeof_expr (location_t, struct c_expr);
+extern struct c_expr upc_elemsizeof_expr (location_t, struct c_expr);
+extern struct c_expr upc_localsizeof_expr (location_t, struct c_expr);
+extern tree upc_affinity_test (location_t, tree, tree);
+extern tree upc_build_shared_var_addr (location_t, tree, tree);
+extern tree upc_build_sync_stmt (location_t, tree, tree);
+extern tree upc_get_block_factor (const tree);
+extern tree upc_get_unshared_type (tree);
+extern tree upc_instrument_forall (location_t, int);
+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_set_block_factor (enum tree_code, tree, tree);
+extern void set_upc_threads_refs_to_one (tree *);
+extern void upc_check_decl (tree);
+extern void upc_decl_init (tree, tree);
+extern void upc_set_decl_section (tree);

+/* used by c-parser */
+extern tree upc_build_sync_stmt (location_t, tree, tree);
+extern tree upc_affinity_test (location_t, tree, tree);
+extern struct c_expr upc_blocksizeof_expr (location_t, struct c_expr);
+extern struct c_expr upc_blocksizeof_type (location_t, struct c_type_name *);
+extern struct c_expr upc_elemsizeof_expr (location_t, struct c_expr);
+extern struct c_expr upc_elemsizeof_type (location_t, struct c_type_name *);
+extern struct c_expr upc_localsizeof_expr (location_t, struct c_expr);
+extern struct c_expr upc_localsizeof_type (location_t, struct c_type_name *);

+/* UPC related functions */
+extern void set_lang_layout_decl_p (int (*) (tree, tree));
+extern void set_lang_layout_decl (void (*) (tree, tree));

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 161914)
[...]
+int compiling_upc;
+int flag_upc;
+int flag_upc_instrument;
+int flag_upc_instrument_functions;
+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.

thanks,
- Gary

[-- Attachment #2: gupc-rfc-front-end-diffs.txt --]
[-- Type: text/plain, Size: 181544 bytes --]

This file has shows the differences between GCC trunk version 161517
and the GUPC branch, for the following files:

gcc/c-convert.c                gcc/c-parser.c         gcc/tree.c
gcc/c-decl.c                   gcc/cp/lex.c           gcc/tree.h
gcc/c-family/c-common.c        gcc/c-tree.h           gcc/upc/ChangeLog
gcc/c-family/c-common.h        gcc/c-typeck.c         gcc/upc/upc-act.c
gcc/c-family/c-cppbuiltin.c    gcc/explow.c           gcc/upc/upc-act.h
gcc/c-family/c-lex.c           gcc/function.c         gcc/upc/upc-lang.c
gcc/c-family/c-pragma.c        gcc/gcc.c              gcc/upc/upc-tree.def
gcc/ChangeLog.upc              gcc/langhooks-def.h    gcc/upc/upc-tree.h
gcc/c-objc-common.h            gcc/langhooks.h        gcc/varasm.c
gcc/config/upc-conf.h          gcc/libfuncs.h
gcc/convert.c                  gcc/stor-layout.c


Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(.../trunk)	(revision 161517)
+++ gcc/c-family/c-common.c	(.../branches/gupc)	(revision 161914)
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.  
 #include "tm.h"
 #include "intl.h"
 #include "tree.h"
+#include "c-tree.h"
 #include "flags.h"
 #include "output.h"
 #include "c-pragma.h"
@@ -199,6 +200,31 @@ const char *pch_file;
    user's namespace.  */
 int flag_iso;
 
+/* FIXME: Convert the UPC switch values below to use
+   the Var() definitions in c.opts, where applicable.  */
+
+/* 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 -fupc-inline-lib switch tells the UPC compiler to
+   inline shared access routines. */
+int flag_upc_inline_lib;
+ 
+/* 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.  */
@@ -376,8 +402,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
@@ -546,6 +573,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 },
+
 };
 
 const unsigned int num_c_common_reswords =
@@ -3593,6 +3633,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 = upc_get_unshared_type (result_type);
+
   if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
     {
       pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
@@ -3989,6 +4034,20 @@ 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;
+      /* UPC TODO: assert TREE_THIS_VOLATILE() and TREE_SIDE_EFFECTS()
+	 for "strict" qualified types?  At the moment, this
+	 leads to ICE in gimple_has_volatile_ops(). */
+      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
@@ -4246,6 +4305,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

Property changes on: gcc/c-family/c-common.c
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /branches/gupc/gcc/c-common.c:r157128-161646

Index: gcc/c-family/c-lex.c
===================================================================
--- gcc/c-family/c-lex.c	(.../trunk)	(revision 161517)
+++ gcc/c-family/c-lex.c	(.../branches/gupc)	(revision 161914)
@@ -43,7 +43,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);

Property changes on: gcc/c-family/c-lex.c
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /branches/gupc/gcc/c-lex.c:r157128-161646

Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(.../trunk)	(revision 161517)
+++ gcc/c-family/c-common.h	(.../branches/gupc)	(revision 161914)
@@ -50,9 +50,9 @@ along with GCC; see the file COPYING3.  
 */
 
 /* 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
@@ -64,6 +64,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,
 
@@ -137,6 +140,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
@@ -297,6 +305,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[];
@@ -387,7 +396,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;
 
@@ -397,6 +408,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 {
@@ -512,6 +524,50 @@ extern const char *pch_file;
 
 extern int flag_iso;
 
+/* FIXME: Convert the UPC switch values below to use
+   the Var() definitions in c.opts, where applicable.  */
+
+/* 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;
+
+/* The -fupc-inline-lib switch tells the UPC compiler to
+   inline shared access routines. */
+extern int flag_upc_inline_lib;
+
 /* Warn about #pragma directives that are not recognized.  */
 
 extern int warn_unknown_pragmas; /* Tri state variable.  */
@@ -832,6 +888,8 @@ extern bool c_cpp_error (cpp_reader *, i
 			 const char *, va_list *)
      ATTRIBUTE_GCC_DIAG(6,0);
 
+extern void upc_cpp_builtins (cpp_reader *);
+
 /* Positive if an implicit `extern "C"' scope has just been entered;
    negative if such a scope has just been exited.  */
 extern GTY(()) int pending_lang_change;
@@ -897,7 +955,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  */

Property changes on: gcc/c-family/c-common.h
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /branches/gupc/gcc/c-common.h:r157128-161647

Index: gcc/c-family/c-pragma.c
===================================================================
--- gcc/c-family/c-pragma.c	(.../trunk)	(revision 161517)
+++ gcc/c-family/c-pragma.c	(.../branches/gupc)	(revision 161914)
@@ -18,11 +18,15 @@ You should have received a copy of the G
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
+#undef HANDLE_PRAGMA_UPC
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#ifdef HANDLE_PRAGMA_UPC
+#include "c-tree.h"
+#endif
 #include "function.h"		/* For cfun.  FIXME: Does the parser know
 				   when it is inside a function, so that
 				   we don't have to look at cfun?  */
@@ -511,6 +515,233 @@ handle_pragma_extern_prefix (cpp_reader 
 	     "#pragma extern_prefix not supported on this target");
 }
 
+#ifdef HANDLE_PRAGMA_UPC
+
+/* 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];
+}
+
+#endif /* HANDLE_PRAGMA_UPC */
+
+#ifdef HANDLE_PRAGMA_PUPC
+
+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");
+}
+
+#endif /* HANDLE_PRAGMA_PUPC */
+
 /* Hook from the front ends to apply the results of one of the preceding
    pragmas that rename variables.  */
 
@@ -1329,6 +1560,16 @@ init_pragma (void)
 
   c_register_pragma_with_expansion (0, "message", handle_pragma_message);
 
+#ifdef HANDLE_PRAGMA_UPC
+  c_register_pragma (0, "upc", handle_pragma_upc);
+  init_pragma_upc ();
+#endif
+
+#ifdef HANDLE_PRAGMA_PUPC
+  c_register_pragma (0, "pupc", handle_pragma_pupc);
+  init_pragma_pupc ();
+#endif
+
 #ifdef REGISTER_TARGET_PRAGMAS
   REGISTER_TARGET_PRAGMAS ();
 #endif

Property changes on: gcc/c-family/c-pragma.c
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /branches/gupc/gcc/c-pragma.c:r157128-161646

Index: gcc/c-family/c-cppbuiltin.c
===================================================================
--- gcc/c-family/c-cppbuiltin.c	(.../trunk)	(revision 161517)
+++ gcc/c-family/c-cppbuiltin.c	(.../branches/gupc)	(revision 161914)
@@ -810,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);
+
   builtin_define_type_sizeof ("__SIZEOF_INT__", integer_type_node);
   builtin_define_type_sizeof ("__SIZEOF_LONG__", long_integer_type_node);
   builtin_define_type_sizeof ("__SIZEOF_LONG_LONG__",

Property changes on: gcc/c-family/c-cppbuiltin.c
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /branches/gupc/gcc/c-cppbuiltin.c:r157128-161646

Index: gcc/libfuncs.h
===================================================================
--- gcc/libfuncs.h	(.../trunk)	(revision 161517)
+++ gcc/libfuncs.h	(.../branches/gupc)	(revision 161914)
@@ -42,6 +42,12 @@ enum libfunc_index
 
   LTI_gcov_flush,
 
+  /* UPC support functions */
+  LTI_upc_barrier,
+  LTI_upc_notify,
+  LTI_upc_wait,
+  LTI_upc_getaddr,
+
   LTI_MAX
 };
 
@@ -66,6 +72,11 @@ extern GTY(()) rtx libfunc_table[LTI_MAX
 
 #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 161914)
@@ -0,0 +1,41 @@
+/* This file contains the definitions and documentation for the
+   additional tree codes used in the UPC front end (see tree.def
+   for the standard codes).
+   Copyright (C) 2001 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC 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.
+
+GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* 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/upc-act.h
===================================================================
--- gcc/upc/upc-act.h	(.../trunk)	(revision 0)
+++ gcc/upc/upc-act.h	(.../branches/gupc)	(revision 161914)
@@ -0,0 +1,53 @@
+/* Declarations for upc-act.c.
+   Copyright (C) 2001 Free Software Foundation, Inc.
+   Original Implementation by Jesse M. Draper <jdraper@super.org>
+   and William W. Carlson <wwc@super.org>.
+   Ported to SGI Irix 6.5 and the gcc 2.95.2 baseline by
+   Gary Funck <gary@intrepid.com> and Nenad Vukicevic <nenad@intrepid.com>.
+
+This file is part of GNU CC.
+
+GNU CC 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.
+
+GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#ifndef _UPC_ACT_H_
+#define _UPC_ACT_H_
+
+
+extern int upc_handle_option (size_t, const char *, int, int);
+extern bool upc_lang_init (void);
+extern void upc_finish (void);
+extern void upc_finish_file (void);
+extern void upc_write_init_func (void);
+extern void upc_free_unshared_var_table (void);
+extern void upc_check_decl (tree);
+extern int upc_types_compatible_p (tree, tree);
+extern int upc_inner_shared_ref_p (tree);
+
+/* used by c-parser */
+extern tree upc_build_sync_stmt (location_t, tree, tree);
+extern tree upc_affinity_test (location_t, tree, tree);
+extern struct c_expr upc_blocksizeof_expr (location_t, struct c_expr);
+extern struct c_expr upc_blocksizeof_type (location_t, struct c_type_name *);
+extern struct c_expr upc_elemsizeof_expr (location_t, struct c_expr);
+extern struct c_expr upc_elemsizeof_type (location_t, struct c_type_name *);
+extern struct c_expr upc_localsizeof_expr (location_t, struct c_expr);
+extern struct c_expr upc_localsizeof_type (location_t, struct c_type_name *);
+
+/* UPC-specific routines */
+extern tree upc_num_threads (void);
+extern int is_valid_pts_p (tree);
+
+#endif /* !_UPC_ACT_H_ */
Index: gcc/upc/ChangeLog
===================================================================
--- gcc/upc/ChangeLog	(.../trunk)	(revision 0)
+++ gcc/upc/ChangeLog	(.../branches/gupc)	(revision 161914)
@@ -0,0 +1,25 @@
+2010-07-03  Gary Funck  <gary@intrepid.com>
+
+	Merge trunk version 161517 into gupc branch.
+	* config-lang.in: Update references to files
+	  moved into c-family/.
+	* Make-lang.in: Likewise.
+	* upc-act.c: Likewise.
+	* upc-gasp.c: Likewise.
+	* upc-gimplify.c: Likewise.
+	* upc-lang.c: Likewise.
+	* upc-pts-packed.c: Likewise.
+	* upc-pts-struct.c: Likewise.
+	* upc-act.c: (upc_handle_option) add parameters to
+	  effect pass through call to c_common_handle_option.
+	* upc-act.h: (upc_handle_option) Likewise.
+	* upc-act.c: (map_unshared_var) used typed ggc allocation.
+	* upc-act.c: (upc_build_init_func) add call to
+	  to mark_decl_referenced(), to ensure that UPC shared
+	  variable initializer function is not removed from
+	  the call tree graph.
+
+2010-02-28  Gary Funck  <gary@intrepid.com>
+
+	Initial implementation and checkin.
+
Index: gcc/upc/upc-lang.c
===================================================================
--- gcc/upc/upc-lang.c	(.../trunk)	(revision 0)
+++ gcc/upc/upc-lang.c	(.../branches/gupc)	(revision 161914)
@@ -0,0 +1,215 @@
+/* Language-dependent hooks for UPC
+   Copyright 2001 Free Software Foundation, Inc.
+   Contributed by Ziemowit Laski  <zlaski@apple.com>
+
+This file is part of GNU CC.
+
+GNU CC 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.
+
+GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#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 "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 "flags.h"
+
+/* FIXME: Convert the UPC switch values below to use
+   the Var() definitions in c.opt, where applicable.  */
+
+/* Non-zero if the current compilation context is UPC */
+int compiling_upc;
+
+/* Non-zero if dwarf2 debugging info. should
+   encode UPC specific information. */
+int use_upc_dwarf2_extensions;
+
+/* Nonzero whenever UPC functionality is being used.  */
+int flag_upc;
+
+/* The -fupc-instrument switch tells the UPC compiler to
+   instrument UPC shared accesses and library calls, using GASP tool support.  */
+int flag_upc_instrument;
+
+/* The -fupc-instrument-functions switch tells the UPC compiler to
+   instrument function entry/exit, using GASP tool support.  */
+int flag_upc_instrument_functions;
+
+enum c_language_kind c_language = clk_upc;
+
+static void upc_initialize_diagnostics (diagnostic_context *);
+static unsigned int upc_init_options (unsigned int, const char **);
+static bool upc_post_options (const char **);
+static void upc_write_global_declarations (void);
+static alias_set_type upc_get_alias_set (tree);
+
+/* 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_WRITE_GLOBALS
+#define LANG_HOOKS_WRITE_GLOBALS upc_write_global_declarations
+#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
+
+
+/* Each front end provides its own hooks, for toplev.c.  */
+struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+
+void
+finish_file (void)
+{
+  upc_finish_file ();
+}
+
+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 unsigned int
+upc_init_options (unsigned int argc, const char **argv)
+{
+  unsigned int result;
+  result = c_common_init_options (argc, argv);
+
+  /* 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 */ );
+
+#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;
+  return result;
+}
+
+static bool upc_post_options (const char **pfilename)
+{
+  return c_common_post_options (pfilename);
+}
+
+static void
+upc_write_global_declarations (void)
+{
+  c_write_global_declarations ();
+}
+
+static alias_set_type
+upc_get_alias_set (tree t)
+{
+
+  /* For the time being, make shared pointers conflict
+     with everything else. Ideally, shared pointers should
+     only conflict with the internal type used to represent
+     the shared pointer (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);
+}
+
+#include "gtype-upc.h"
Index: gcc/upc/upc-tree.h
===================================================================
--- gcc/upc/upc-tree.h	(.../trunk)	(revision 0)
+++ gcc/upc/upc-tree.h	(.../branches/gupc)	(revision 161914)
@@ -0,0 +1,45 @@
+/* Definitions for UPC parsing and type checking.
+   Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001, 2002 Free Software Foundation, Inc.
+   Contributed by Michael Tiemann (tiemann@cygnus.com)
+
+This file is part of GNU CC.
+
+GNU CC 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.
+
+GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#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 161914)
@@ -0,0 +1,1577 @@
+/* Implement UPC semantics
+   Copyright (C) 2001 Free Software Foundation, Inc.
+   Original Implementation by Jesse M. Draper <jdraper@super.org>
+   and William W. Carlson <wwc@super.org>.
+   Ported to SGI Irix 6.5 and the gcc 2.95.2 baseline by
+   Gary Funck <gary@intrepid.com> and Nenad Vukicevic <nenad@intrepid.com>.
+
+This file is part of GNU CC.
+
+GNU CC 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.
+
+GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#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 "upc-act.h"
+#include "upc-pts.h"
+#include "cgraph.h"
+#include "c-family/c-common.h"
+#include "c-family/c-pragma.h"
+/* define decl_default_tls_model() prototype */
+#include "rtl.h"
+
+static int contains_pts_refs_p (tree);
+static int recursive_count_upc_threads_refs (tree);
+static tree upc_blocksizeof (location_t, tree);
+static void upc_lang_layout_decl (tree, tree);
+static int upc_lang_layout_decl_p (tree, tree);
+static void upc_parse_init (void);
+static int upc_sizeof_type_check (const char *, tree);
+static void upc_build_init_func (const tree);
+
+/* Given a shared variable's VAR_DECL node, map to another
+   VAR_DECL that has same 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 lookup_unshared_var (const tree);
+static tree unshared_var_name (const tree);
+static tree create_unshared_var (location_t, const tree);
+static void map_unshared_var (const tree, const tree);
+static tree unshared_var_addr (location_t, const tree);
+
+\f
+   
+/* Process UPC specific command line switches */
+
+int
+upc_handle_option (size_t scode, const char *arg, int value, int kind)
+{
+  enum opt_code code = (enum opt_code) scode;
+  int result = 1;
+  switch (code)
+    {
+    default:
+      result = c_common_handle_option (scode, arg, value, kind);
+      break;
+    case OPT_dwarf_2_upc:
+      use_upc_dwarf2_extensions = value;
+      break;
+    case OPT_fupc_inline_lib:
+      if ((value == 1) && (flag_upc_instrument == 1))
+        error ("-fupc-instrument is incompatible with -fupc-inline-lib");
+      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)
+	{
+	  char msg[100];
+	  sprintf (msg, "THREADS value exceeds implementation limit of %d",
+		   UPC_MAX_THREADS);
+	  error (msg);
+	  value = 1;
+	}
+      flag_upc_pthreads_per_process = value;
+      break;
+    case OPT_fupc_threads_:
+      if (value > UPC_MAX_THREADS)
+	{
+	  char msg[100];
+	  sprintf (msg, "THREADS value exceeds implementation limit of %d",
+		   UPC_MAX_THREADS);
+	  error (msg);
+	  value = 1;
+	}
+      flag_upc_threads = value;
+      break;
+    case OPT_lang_upc:
+      flag_upc = value;
+      break;
+    }
+  return result;
+}
+
+bool
+upc_lang_init (void)
+{
+  if (!targetm.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;
+}
+
+void
+upc_finish (void)
+{
+}
+
+/* UPC specific initialization */
+
+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=%s", UPC_MAX_BLOCK_SIZE_STRING);
+  cpp_define (pfile, def_buf);
+#if defined(UPC_PTS_PACKED_REP)
+  cpp_define (pfile, "__UPC_PTS_PACKED_REP__=1");
+#elif defined(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);
+#ifdef UPC_PTS_VADDR_FIELD
+  (void) sprintf (def_buf, "__UPC_VADDR_FIELD__=%s", UPC_PTS_VADDR_FIELD);
+  cpp_define (pfile, def_buf);
+#endif
+#ifdef UPC_PTS_THREAD_FIELD
+  (void) sprintf (def_buf, "__UPC_THREAD_FIELD__=%s", UPC_PTS_THREAD_FIELD);
+  cpp_define (pfile, def_buf);
+#endif
+#ifdef UPC_PTS_PHASE_FIELD
+  (void) sprintf (def_buf, "__UPC_PHASE_FIELD__=%s", UPC_PTS_PHASE_FIELD);
+  cpp_define (pfile, def_buf);
+#endif
+#elif defined(UPC_PTS_WORD_PAIR_REP)
+  cpp_define (pfile, "__UPC_PTS_WORD_PAIR_REP__=1");
+#endif
+#ifdef UPC_PTS_VADDR_FIRST
+  (void) sprintf (def_buf, "__UPC_VADDR_FIRST__=%d", UPC_PTS_VADDR_FIRST);
+  cpp_define (pfile, def_buf);
+#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");
+    }
+}
+
+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_type ();
+  unshared_vars = htab_create_ggc (101, uid_tree_map_hash, uid_tree_map_eq, NULL);
+  upc_init_stmt_list = NULL;
+}
+
+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)); 
+}
+
+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 ("%s applied to a function type", op_name);
+      return 0;
+    }
+  else if (code == VOID_TYPE)
+    {
+      error ("%s applied to a void type", op_name);
+      return 0;
+    }
+  else if (!upc_shared_type_p (type))
+    {
+      error ("%s applied to a non-shared type", op_name);
+      return 0;
+    }
+  return 1;
+}
+
+/* Compute the value of the `upc_blocksizeof' operator.  */
+
+static
+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;
+}
+
+/* Return the result of upc_blocksizeof applied to EXPR.  */
+
+struct c_expr
+upc_blocksizeof_expr (location_t loc, struct c_expr expr)
+{
+  struct c_expr ret;
+  if (expr.value == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL_TREE;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_blocksizeof (loc, TREE_TYPE (expr.value));
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL_TREE;
+      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).  */
+
+struct c_expr
+upc_blocksizeof_type (location_t loc, struct c_type_name *t)
+{
+  tree type;
+  struct c_expr ret;
+  type = groktypename (t, NULL, NULL);
+  ret.value = upc_blocksizeof (loc, type);
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  pop_maybe_used (C_TYPE_VARIABLE_SIZE (type));
+  return ret;
+}
+
+/* Compute the value of the `upc_elemsizeof' operator.  */
+
+static
+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;
+}
+
+/* Return the result of upc_elemsizeof applied to EXPR.  */
+
+struct c_expr
+upc_elemsizeof_expr (location_t loc, struct c_expr expr)
+{
+  struct c_expr ret;
+  if (expr.value == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL_TREE;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_elemsizeof (loc, TREE_TYPE (expr.value));
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL_TREE;
+      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).  */
+
+struct c_expr
+upc_elemsizeof_type (location_t loc, struct c_type_name *t)
+{
+  tree type;
+  struct c_expr ret;
+  type = groktypename (t, NULL, NULL);
+  ret.value = upc_elemsizeof (loc, type);
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  pop_maybe_used (C_TYPE_VARIABLE_SIZE (type));
+  return ret;
+}
+
+/* Compute the value of the `upc_localsizeof' operator.  This value
+   can vary from thread to thread if the array size is not a multiple of
+   (THREADS * block_factor * upc_elementsizeof (type)). */
+
+static
+tree
+upc_localsizeof (location_t loc, tree type)
+{
+  tree block_factor, local_size, total_size, elt_type, elt_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);
+  total_size = TYPE_SIZE (type);
+  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);
+
+  if (UPC_TYPE_HAS_THREADS_FACTOR (type))
+    {
+      /* Neither an indefinite block size, nor static threads
+         environment should be asserted if "threads factor"
+	 is present. */
+      if (integer_zerop (block_factor) || flag_upc_threads)
+        abort ();
+      /* The type size has already been scaled to give
+         the per thread contribution (in bits). */
+      local_size = total_size;
+    }
+  if (integer_zerop (block_factor))
+    {
+      /* local size is total size, because the entire
+         object lives on a single thread. */
+      local_size = total_size;
+    }
+  else
+    {
+      tree n_threads, n_elts, n_full_blocks;
+      tree n_full_blocks_per_thread, n_elts_in_full_blocks;
+      tree n_rem_elts, n_local_elts;
+      block_factor = convert (bitsizetype, block_factor);
+      n_elts = size_binop (EXACT_DIV_EXPR, total_size, elt_size);
+      if (UPC_TYPE_HAS_THREADS_FACTOR (type))
+        {
+	   /* In the worst case, round up the local contribution
+	      to the next multiple of the block factor */
+	   n_local_elts = size_binop (MULT_EXPR,
+	              size_binop (CEIL_DIV_EXPR, n_elts, block_factor),
+		      block_factor);
+	}
+      else
+        {
+	  n_threads = convert (bitsizetype, upc_num_threads ());
+	  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, n_threads);
+	  n_elts_in_full_blocks    = size_binop (MULT_EXPR,
+	    size_binop (MULT_EXPR, n_full_blocks_per_thread, n_threads),
+	    block_factor);
+	  n_rem_elts = size_binop (MINUS_EXPR, n_elts,
+	                           n_elts_in_full_blocks);
+	  n_local_elts = size_binop (PLUS_EXPR,
+			    size_binop (MULT_EXPR,
+			       n_full_blocks_per_thread, block_factor),
+			    size_binop (MIN_EXPR, n_rem_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;
+}
+
+/* Return the result of upc_localsizeof applied to EXPR.  */
+
+struct c_expr
+upc_localsizeof_expr (location_t loc, struct c_expr expr)
+{
+  struct c_expr ret;
+  if (expr.value == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL_TREE;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      ret.value = upc_localsizeof (loc, TREE_TYPE (expr.value));
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL_TREE;
+      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).  */
+
+struct c_expr
+upc_localsizeof_type (location_t loc, struct c_type_name *t)
+{
+  tree type;
+  struct c_expr ret;
+  type = groktypename (t, NULL, NULL);
+  ret.value = upc_localsizeof (loc, type);
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL_TREE;
+  pop_maybe_used (C_TYPE_VARIABLE_SIZE (type));
+  return ret;
+}
+
+/****** UPC tree-related checks, and operations **************/
+
+/* Traverse the expression and return the number of times
+   THREADS is referenced.  */
+
+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' an expression tree where THREADS appears on
+   the left or the right hand side of a multply, in a series
+   of zero or more mulitplies.  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
+   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 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 specifier, calculate the blocking factor
+   add this into the type field of `type'.  Caller is responsible
+   for checking that the block factor is being applied to a
+   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 ("layout qualifier cannot be applied to a void type");
+      return type;
+    }
+
+  /* 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)
+    {
+      /* layout qualifier 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;
+      /* layout qualifier is [*] */
+      if (!COMPLETE_TYPE_P (type))
+        {
+          error ("layout qualifier of the form [*] cannot be applied to an incomplete type");
+          return type;
+        }
+      if (decl_kind == POINTER_TYPE)
+        {
+          error ("[*] 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 ());
+          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 ("layout qualifier is not an integral constant");
+      else
+        block_factor = fold (layout_qualifier);
+    }
+
+  if (!block_factor)
+    return type;
+
+  /* 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, UPC_MAX_BLOCK_SIZE_CSTU) > 0)
+    {
+      error ("Maximum block size in this implementation is %s",
+	        UPC_MAX_BLOCK_SIZE_STRING);
+      return type;
+    }
+
+  gcc_assert (TREE_CODE (block_factor) == INTEGER_CST);
+
+  /* UPC TODO: Eliminate duplicate variant type copies.  */
+  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;
+}
+
+/* Return TRUE if TYPE is a shared type.  For arrays, we need
+   to query its element type, because array types are never
+   qualified.  */
+
+int
+upc_shared_type_p (tree type)
+{
+  tree elt_type;
+  if (!type || TREE_CODE (type) == ERROR_MARK)
+    return 0;
+  elt_type = strip_array_types (type);
+  return TYPE_SHARED (elt_type);
+}
+
+void
+upc_check_decl (tree decl)
+{
+  /* If this is a shared variable, make sure that it ends up
+     in the executable file.  */
+  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 1 if type TYPE contains any 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;
+    }
+}
+
+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;
+}
+
+tree
+upc_get_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 = upc_get_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;
+}
+
+void
+upc_decl_init (tree decl, tree init)
+{
+  tree cur_stmt_list_save, init_stmt;
+  if (!upc_init_stmt_list)
+    upc_init_stmt_list = alloc_stmt_list ();
+  cur_stmt_list_save = cur_stmt_list;
+  cur_stmt_list = upc_init_stmt_list;
+  init_stmt = build2 (INIT_EXPR, void_type_node, decl, init);
+  add_stmt (init_stmt);
+  cur_stmt_list = cur_stmt_list_save;
+}
+
+/* Return TRUE if DECL's size is zero, and DECL is a 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;
+}
+
+
+/* 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
+      /* 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 asserted
+	 and this is a 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. */
+	    abort ();
+	}
+    }
+}
+
+/* Given that TYPE describes a shared array, and that DECL's size hasn't
+   been calculated, size the type and adust 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 && upc_shared_type_p (TREE_TYPE (t)))
+    {
+      tree elt_type = TREE_TYPE (t);
+      tree elt_size = TYPE_SIZE (elt_type);
+      tree block_factor = TYPE_BLOCK_FACTOR (elt_type)
+               ? convert (bitsizetype, TYPE_BLOCK_FACTOR (elt_type)) : NULL;
+      tree t_size = TYPE_SIZE (type);
+      tree n_elem = size_binop (FLOOR_DIV_EXPR, t_size, elt_size);
+      tree n_threads = convert (bitsizetype, upc_num_threads ());
+      if (UPC_TYPE_HAS_THREADS_FACTOR (type))
+	{
+	  if (block_factor)
+	    if (!integer_zerop (block_factor))
+	      {
+		tree t1, t2;
+		block_factor = convert (bitsizetype, block_factor);
+		t1 = size_binop (CEIL_DIV_EXPR, n_elem, block_factor);
+		t2 = size_binop (MULT_EXPR, t1, block_factor);
+		DECL_SIZE (decl) = size_binop (MULT_EXPR, t2, elt_size);
+	      }
+	    else
+	      DECL_SIZE (decl) = size_binop (MULT_EXPR, elt_size,
+					     n_threads);
+	  else
+	    DECL_SIZE (decl) = t_size;
+	}
+      else if (!(block_factor && integer_zerop (block_factor)))
+	{
+	  /* We want to allocate ceiling of 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 of (ceiling of n_elem/block_factor)/n_threads) *
+	     block_factor) elements 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 shared int x[1]
+	     will work for runtime specification of threads. */
+	  if (integer_onep (n_elem))
+	    DECL_SIZE (decl) = elt_size;
+	  else
+	    DECL_SIZE (decl) = size_binop (MULT_EXPR, n_elem_per_thread,
+					   elt_size);
+	}
+      else
+	/* We want to allocate the entire array on one thread. */
+	DECL_SIZE (decl) = TYPE_SIZE (type);
+    }
+  else
+    DECL_SIZE (decl) = TYPE_SIZE (type);
+
+  DECL_SIZE_UNIT (decl)
+      = convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
+				       bitsize_unit_node));
+}
+
+/* Implement UPC's upc_forall `affinity' test, by augmenting the for statement's
+   for_body by rewriting it into:
+     if (affinity == MYTHREAD) for_body; */
+
+tree
+upc_affinity_test (location_t loc, tree for_body, tree affinity)
+{
+  tree mythread;
+  tree affinity_test;
+  tree if_stmt;
+  
+  if (affinity == NULL_TREE || for_body == NULL_TREE)
+    return for_body;
+
+  /* Make sure that the identifier "MYTHREAD" will be listed in the
+     assembly file as .extern */
+
+  mythread = lookup_name (get_identifier ("MYTHREAD"));
+  assemble_external (mythread);
+  TREE_USED (mythread) = 1;
+  
+  if (TREE_CODE (TREE_TYPE (affinity)) == POINTER_TYPE
+      && upc_shared_type_p (TREE_TYPE (TREE_TYPE (affinity))))
+    {
+	/* then we have a pointer to a 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_build_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 ("Affinity expression is neither an integer nor the address of a shared object");
+      return for_body;
+    }
+  
+  /* Affinity now contains an integer value that can be compared to MY_THREAD.
+     Create an expression that tests if affinity is equal to MY_THREAD. */
+
+  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 the MAYBE_CONST_EXPR's.  */
+  affinity_test = c_fully_fold (affinity_test, false, NULL);
+
+  /* generate the statement: if (<affinity>) <for_body>; */
+
+  SET_EXPR_LOCATION (affinity_test, loc);
+  if_stmt = build3 (COND_EXPR, void_type_node, affinity_test,
+                    for_body, NULL_TREE);
+  return if_stmt;
+}
+
+/*
+ * upc_pts_cvt_op_p checks for conversion operations involving
+ * shared pointers.  If either of the types involved
+ * are shared pointers, return TRUE, else FALSE.
+ */
+int
+upc_pts_cvt_op_p (tree exp)
+{
+  tree t1 = TREE_TYPE (exp);
+  tree t2 = TREE_TYPE (TREE_OPERAND (exp, 0));
+  int result = 0;
+  if ((TREE_CODE (t1) == POINTER_TYPE)
+       && (TREE_CODE (t2) == POINTER_TYPE))
+    {
+      tree tt1 = TREE_TYPE (t1);
+      tree tt2 = TREE_TYPE (t2);
+      if (upc_shared_type_p (tt1) || upc_shared_type_p (tt2))
+        result = 1;
+    }
+  return result;
+}
+
+/* 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 pointer-to-shared,
+	     then they're compatible.  */
+	  if (VOID_TYPE_P (ttx) && VOID_TYPE_P (tty))
+	    return 1;
+          /* Intermediate conversions to (shared void *) 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
+	     with generic pointer-to-shared 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 blocksize
+	     (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 is shared, and the other is local,
+         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 *************/
+
+tree
+upc_num_threads (void)
+{
+  tree n;
+  n = flag_upc_threads ? size_int (flag_upc_threads)
+		  : lookup_name (get_identifier ("THREADS"));
+  if (!n)
+    {
+      error ("THREADS is undefined."
+             " When compiling preprocessd 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;
+}
+
+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;
+}
+
+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;
+}
+
+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_"
+
+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);
+}
+
+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 = TYPE_MAIN_VARIANT (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;
+}
+
+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 shared pointer
+   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 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_value (loc, type,
+                             var_addr, integer_zero_node, integer_zero_node);
+  return val;
+}
+
+/* Expand the pre/post increment/decrement of shared pointer
+   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;
+}
+
+tree
+upc_pts_int_sum (location_t location ATTRIBUTE_UNUSED,
+                 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 shared qualifier (for PTS's that happen
+     to live in shared memory). */
+  tree ttype = TREE_TYPE (ptrop);
+  int quals_minus_shared = TYPE_QUALS (ttype) & !TYPE_QUAL_SHARED;
+  tree result_type = c_build_qualified_type (ttype, quals_minus_shared);
+  tree result_targ_type = TREE_TYPE (result_type);
+  tree base_type = strip_array_types (result_targ_type);
+  tree result;
+
+  /* We have a pointer to a shared object.  For pointers to
+     simple objects, just build a "resultcode" tree with the intop and
+     let upc_genricize() 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)
+    {
+      gcc_assert (TREE_CODE (result_targ_type) == ARRAY_TYPE);
+      if (TREE_CODE (TYPE_SIZE (result_targ_type)) == INTEGER_CST)
+	{
+	  tree elt_cnt;
+	  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);
+	  intop = convert (sizetype, intop);
+	  intop = size_binop (MULT_EXPR, intop, elt_cnt);
+	}
+      else
+	{
+	  tree elt_cnt;
+	  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 = build2 (MULT_EXPR, sizetype, 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);
+  intop = convert (sizetype, intop);
+  result = build2 (POINTER_PLUS_EXPR, result_type, ptrop, intop);
+  /* Althoough there may be some specific cases where the
+     addition of a constant integer to a shared pointer 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;
+}
+
+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 shared and nonshared pointers");
+      return error_mark_node;
+    }
+  result = build2 (MINUS_EXPR, ptrdiff_type_node, op0, op1);
+  return result;
+}
+
+int
+is_valid_pts_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, t_list;
+  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);
+  /* Swap the statement list that we've built up,
+     for the current statement list.  */
+  t_list = c_begin_compound_stmt (true);
+  TREE_CHAIN (stmt_list) = TREE_CHAIN (t_list);
+  cur_stmt_list = stmt_list;
+  free_stmt_list (t_list);
+  t_list = c_end_compound_stmt (loc, stmt_list, true);
+  add_stmt (t_list);
+  finish_function ();
+  gcc_assert (DECL_RTL (init_func));
+  upc_init_array_section = get_section (UPC_INIT_ARRAY_SECTION_NAME,
+				        0, NULL);
+  mark_decl_referenced (init_func);
+  init_func_symbol = XEXP (DECL_RTL (init_func), 0);
+  assemble_addr_to_section (init_func_symbol, upc_init_array_section);
+}
+
+void
+upc_finish_file (void)
+{
+  upc_write_init_func ();
+  upc_free_unshared_var_table ();
+}
+
+void
+upc_write_init_func (void)
+{
+  if (upc_init_stmt_list)
+    {
+      upc_build_init_func (upc_init_stmt_list);
+      upc_init_stmt_list = NULL;
+    }
+}
+
+void
+upc_free_unshared_var_table (void)
+{
+  if (unshared_vars)
+    {
+      htab_delete (unshared_vars);
+      unshared_vars = NULL;
+    }
+}
+
+#include "gt-upc-upc-act.h"
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(.../trunk)	(revision 161517)
+++ gcc/tree.c	(.../branches/gupc)	(revision 161914)
@@ -3419,6 +3419,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;
 }
@@ -3500,6 +3503,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;
 }
@@ -3664,6 +3670,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:
@@ -3679,6 +3686,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) = upc_get_unshared_type (type);
       break;
     }
 
@@ -5476,6 +5489,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.  */
@@ -5487,6 +5503,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))
 	  && attribute_list_equal (TYPE_ATTRIBUTES (cand),
 				   TYPE_ATTRIBUTES (base)));
 }
@@ -6828,6 +6847,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);
 }
 
@@ -10753,6 +10774,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)
@@ -10766,6 +10788,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 161517)
+++ gcc/tree.h	(.../branches/gupc)	(revision 161914)
@@ -367,6 +367,12 @@ struct GTY(()) tree_base {
   unsigned asm_written_flag: 1;
   unsigned nowarning_flag : 1;
 
+  /* UPC flags */
+  unsigned shared_flag : 1;		/* UPC: shared  qualified */
+  unsigned strict_flag : 1;		/* UPC: strict  qualified */
+  unsigned relaxed_flag : 1;		/* UPC: relaxed qualified */
+  unsigned upc_unused : 5;		/* UPC: unused bits  */
+
   unsigned used_flag : 1;
   unsigned nothrow_flag : 1;
   unsigned static_flag : 1;
@@ -1277,6 +1283,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)
 
@@ -1360,6 +1374,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.shared_flag)
+#define TREE_STRICT(NODE) ((NODE)->base.strict_flag)
+#define TREE_RELAXED(NODE) ((NODE)->base.relaxed_flag)
+
 /* In fixed-point types, means a saturating type.  */
 #define TYPE_SATURATING(NODE) ((NODE)->base.saturating_flag)
 
@@ -2053,6 +2072,7 @@ struct GTY(()) tree_block {
 #define TYPE_UID(NODE) (TYPE_CHECK (NODE)->type.uid)
 #define TYPE_SIZE(NODE) (TYPE_CHECK (NODE)->type.size)
 #define TYPE_SIZE_UNIT(NODE) (TYPE_CHECK (NODE)->type.size_unit)
+#define TYPE_BLOCK_FACTOR(NODE) (TYPE_CHECK (NODE)->type.block_factor)
 #define TYPE_VALUES(NODE) (ENUMERAL_TYPE_CHECK (NODE)->type.values)
 #define TYPE_DOMAIN(NODE) (ARRAY_TYPE_CHECK (NODE)->type.values)
 #define TYPE_FIELDS(NODE) (RECORD_OR_UNION_CHECK (NODE)->type.values)
@@ -2196,6 +2216,15 @@ extern enum machine_mode vector_type_mod
    the term.  */
 #define TYPE_RESTRICT(NODE) (TYPE_CHECK (NODE)->type.restrict_flag)
 
+/* If nonzero, this type is `shared'-qualified, in the UPC dialect */
+#define TYPE_SHARED(NODE) (TYPE_CHECK (NODE)->base.shared_flag)
+
+/* If nonzero, this type is `strict'-qualified, in the UPC dialect  */
+#define TYPE_STRICT(NODE) (TYPE_CHECK (NODE)->base.strict_flag)
+
+/* If nonzero, this type is `relaxed'-qualified, in the UPC dialect  */
+#define TYPE_RELAXED(NODE) (TYPE_CHECK (NODE)->base.relaxed_flag)
+
 /* The address space the type is in.  */
 #define TYPE_ADDR_SPACE(NODE) (TYPE_CHECK (NODE)->base.address_space)
 
@@ -2203,10 +2232,15 @@ extern enum machine_mode vector_type_mod
    combined by bitwise-or to form the complete set of qualifiers for a
    type.  */
 
-#define TYPE_UNQUALIFIED   0x0
-#define TYPE_QUAL_CONST    0x1
-#define TYPE_QUAL_VOLATILE 0x2
-#define TYPE_QUAL_RESTRICT 0x4
+#define TYPE_UNQUALIFIED   0x00
+#define TYPE_QUAL_CONST    0x01
+#define TYPE_QUAL_VOLATILE 0x02
+#define TYPE_QUAL_RESTRICT 0x04
+
+/* UPC qualifiers */
+#define TYPE_QUAL_SHARED   0x10
+#define TYPE_QUAL_RELAXED  0x20
+#define TYPE_QUAL_STRICT   0x40
 
 /* Encode/decode the named memory support as part of the qualifier.  If more
    than 8 qualifiers are added, these macros need to be adjusted.  */
@@ -2225,13 +2259,24 @@ extern enum machine_mode vector_type_mod
   ((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.lang_flag_0)
@@ -2331,6 +2376,9 @@ struct GTY(()) tree_type {
   alias_set_type alias_set;
   tree pointer_to;
   tree reference_to;
+  /* UPC: for block-distributed arrays */
+  union tree_node *block_factor;
+
   union tree_type_symtab {
     int GTY ((tag ("0"))) address;
     const char * GTY ((tag ("1"))) pointer;
@@ -2473,7 +2521,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				\
@@ -3568,6 +3616,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,
@@ -3726,6 +3787,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]
@@ -4343,6 +4419,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);
@@ -4402,6 +4479,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 void expand_affinity_test (tree);
+
 /* Define data structures, macros, and functions for handling sizes
    and the various types used to represent sizes.  */
 
@@ -5571,4 +5653,8 @@ is_lang_specific (tree t)
   return TREE_CODE (t) == LANG_TYPE || TREE_CODE (t) >= NUM_TREE_CODES;
 }
 
+/* In upc-act.c and stub-upc.c */
+extern int upc_shared_type_p (tree);
+extern tree upc_get_unshared_type (tree);
+
 #endif  /* GCC_TREE_H  */
Index: gcc/gcc.c
===================================================================
--- gcc/gcc.c	(.../trunk)	(revision 161517)
+++ gcc/gcc.c	(.../branches/gupc)	(revision 161914)
@@ -870,6 +870,8 @@ static const char *cc1_options =
  %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\
  %{coverage:-fprofile-arcs -ftest-coverage}";
 
+static const char *upc_options = "-lang-upc -include gcc-upc.h";
+
 static const char *asm_options =
 "%{--target-help:%:print-asm-header()} "
 #if HAVE_GNU_AS
@@ -1024,6 +1026,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},
   /* Next come the entries for C.  */
   {".c", "@c", 0, 1, 1},
@@ -1627,6 +1630,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),
Index: gcc/cp/lex.c
===================================================================
--- gcc/cp/lex.c	(.../trunk)	(revision 161517)
+++ gcc/cp/lex.c	(.../branches/gupc)	(revision 161914)
@@ -184,6 +184,9 @@ init_reswords (void)
   /* The Objective-C keywords are all context-dependent.  */
   mask |= D_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++)
     {
Index: gcc/c-objc-common.h
===================================================================
--- gcc/c-objc-common.h	(.../trunk)	(revision 161517)
+++ gcc/c-objc-common.h	(.../branches/gupc)	(revision 161914)
@@ -91,6 +91,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 161517)
+++ gcc/c-tree.h	(.../branches/gupc)	(revision 161914)
@@ -59,6 +59,10 @@ along with GCC; see the file COPYING3.  
    This is used for -Wc++-compat. */
 #define C_TYPE_DEFINED_IN_STRUCT(TYPE) TYPE_LANG_FLAG_2 (TYPE)
 
+/* 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)
+
 /* Record whether a typedef for type `int' was actually `signed int'.  */
 #define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP)
 
@@ -131,6 +135,42 @@ struct c_expr
   tree original_type;
 };
 
+\f
+/* In upc-act.c and stub-upc.c */
+extern int count_upc_threads_refs (tree);
+extern int is_multiple_of_upc_threads (tree);
+extern void set_upc_threads_refs_to_one (tree *);
+extern struct c_expr upc_blocksizeof_expr (location_t, struct c_expr);
+extern tree upc_affinity_test (location_t, tree, 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_decl_init (tree, tree);
+extern struct c_expr upc_elemsizeof_expr (location_t, struct c_expr);
+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 struct c_expr upc_localsizeof_expr (location_t, struct c_expr);
+extern tree upc_num_threads (void);
+extern int upc_pts_cvt_op_p (tree);
+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_set_block_factor (enum tree_code, tree, tree);
+extern void upc_set_decl_section (tree);
+
+/* #pragma upc handling in c-pragma.c */
+extern void permit_pragma_upc (void);
+extern void deny_pragma_upc (void);
+extern int pragma_upc_permitted_p (void);
+extern void set_upc_consistency_mode (int);
+extern int get_upc_consistency_mode (void);
+extern void push_upc_consistency_mode (void);
+extern void pop_upc_consistency_mode (void);
+/* determine whether UPC profiling is on or off */
+extern int get_upc_pupc_mode(void);
+
 /* A kind of type specifier.  Note that this information is currently
    only used to distinguish tag definitions, tag references and typeof
    uses.  */
@@ -221,6 +261,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
@@ -278,6 +321,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;
 };
@@ -343,7 +392,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;
@@ -448,6 +500,12 @@ extern void c_pop_function_context (void
 extern void push_parm_decl (const struct c_parm *);
 extern struct c_declarator *set_array_declarator_inner (struct c_declarator *,
 							struct c_declarator *);
+
+/* UPC-related functions defined in upc-act.c and stub-upc.c */
+extern struct c_expr upc_blocksizeof_type (location_t, struct c_type_name *);
+extern struct c_expr upc_localsizeof_type (location_t, struct c_type_name *);
+extern struct c_expr upc_elemsizeof_type (location_t, struct c_type_name *);
+
 extern tree c_builtin_function (tree);
 extern tree c_builtin_function_ext_scope (tree);
 extern void shadow_tag (const struct c_declspecs *);

Property changes on: gcc/c-tree.h
___________________________________________________________________
Added: svn:mergeinfo
   Merged /trunk/gcc/c-tree.h:r157151-161654

Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(.../trunk)	(revision 161517)
+++ gcc/c-decl.c	(.../branches/gupc)	(revision 161914)
@@ -2223,6 +2223,16 @@ merge_decls (tree newdecl, tree olddecl,
   if (TREE_THIS_VOLATILE (newdecl))
     TREE_THIS_VOLATILE (olddecl) = 1;
 
+  if (TREE_SHARED (newdecl))
+    {
+      TREE_SHARED (olddecl) = 1;
+      /* UPC TODO: if "shared" implies "strict", should we
+       * TREE_STRICT(), and TREE_SIDE_EFFECTS() (which is
+       * implied by "volatile"?  */
+      if (TREE_CODE (newdecl) == VAR_DECL)
+	TREE_THIS_VOLATILE (newdecl) = 1;
+    }
+
   /* Merge deprecatedness.  */
   if (TREE_DEPRECATED (newdecl))
     TREE_DEPRECATED (olddecl) = 1;
@@ -3761,6 +3771,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
@@ -4294,6 +4307,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.
@@ -4816,6 +4833,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;
@@ -4827,6 +4847,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;
@@ -4917,6 +4939,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)
@@ -4961,6 +4985,19 @@ 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
+	error ("merge of UPC layout qualifiers is currently unimplemented"); 
+    }
   as1 = declspecs->address_space;
   as2 = TYPE_ADDR_SPACE (element_type);
   address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
@@ -4973,7 +5010,19 @@ 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, "%qE is declared both strict and relaxed.", name);
+  if (strictp && !sharedp)
+    error_at (loc, "%qE is declared strict but not shared.", name);
+  if (relaxedp && !sharedp)
+    error_at (loc, "%qE is declared relaxed 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)",
@@ -4984,8 +5033,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.).  */
 
@@ -5078,7 +5130,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).
@@ -5262,6 +5314,38 @@ 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 ("THREADS may not be referenced more than once"
+			       " in a shared array declaration.");
+			size = integer_one_node;
+		      }
+		    else if (!is_multiple_of_upc_threads (size))
+		      {
+			error ("array dimension is not a simple multiple"
+			       " of THREADS");
+			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)
 		  {
@@ -5387,7 +5471,7 @@ grokdeclarator (const struct c_declarato
 		  }
 	      }
 
-	     /* Complain about arrays of incomplete types.  */
+	    /* Complain about arrays of incomplete types.  */
 	    if (!COMPLETE_TYPE_P (type))
 	      {
 		error_at (loc, "array type has incomplete element type");
@@ -5424,6 +5508,25 @@ 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; 
+                  }
+
+		/* Add UPC-defined block size, if supplied */
+		if (layout_qualifier)
+		  {
+		    type = upc_set_block_factor (ARRAY_TYPE, type, layout_qualifier);
+		    layout_qualifier = 0;
+		  }
+
 		/* The GCC extension for zero-length arrays differs from
 		   ISO flexible array members in that sizeof yields
 		   zero.  */
@@ -5477,6 +5580,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)
@@ -5526,6 +5631,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 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");
@@ -5561,7 +5672,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
@@ -5601,7 +5719,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;
@@ -5801,6 +5921,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)
 	  {
@@ -5812,6 +5934,13 @@ grokdeclarator (const struct c_declarato
 	    type = build_pointer_type (type);
 	    type_quals = TYPE_UNQUALIFIED;
 	  }
+        else if (type_quals & TYPE_QUAL_SHARED)
+	  {
+	    error_at (loc, "parameter %qE declared with shared qualifier",
+		   name);
+	    type_quals &= ~(TYPE_QUAL_SHARED | TYPE_QUAL_STRICT
+			    | TYPE_QUAL_RELAXED);
+	  }
 	else if (type_quals)
 	  type = c_build_qualified_type (type, type_quals);
 
@@ -5857,6 +5986,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 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);
@@ -5872,7 +6008,7 @@ grokdeclarator (const struct c_declarato
 	if (storage_class == csc_register || threadp)
 	  {
 	    error_at (loc, "invalid storage class for function %qE", name);
-	   }
+	  }
 	else if (current_scope != file_scope)
 	  {
 	    /* Function declaration not at file scope.  Storage
@@ -5947,7 +6083,19 @@ grokdeclarator (const struct c_declarato
 	/* An uninitialized decl with `extern' is a reference.  */
 	int extern_ref = !initialized && storage_class == csc_extern;
 
-	type = c_build_qualified_type (type, type_quals);
+	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
@@ -5994,6 +6142,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;
 	  }
 
@@ -6062,6 +6215,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;
   }
 }
@@ -8165,7 +8325,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.  */
@@ -8462,18 +8623,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;
 }
 
@@ -8488,6 +8652,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;
@@ -8510,6 +8675,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;
@@ -8544,6 +8712,20 @@ 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");
+      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);
@@ -8561,6 +8743,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/function.c
===================================================================
--- gcc/function.c	(.../trunk)	(revision 161517)
+++ gcc/function.c	(.../branches/gupc)	(revision 161914)
@@ -1991,6 +1991,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.h
===================================================================
--- gcc/langhooks.h	(.../trunk)	(revision 161517)
+++ gcc/langhooks.h	(.../branches/gupc)	(revision 161914)
@@ -417,9 +417,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 161517)
+++ gcc/stor-layout.c	(.../branches/gupc)	(revision 161914)
@@ -478,6 +478,29 @@ get_mode_alignment (enum machine_mode mo
 }
 
 \f
+/* 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.  */
 
@@ -538,7 +561,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 161517)
+++ gcc/c-typeck.c	(.../branches/gupc)	(revision 161914)
@@ -84,6 +84,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);
@@ -314,6 +315,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;
@@ -327,10 +329,26 @@ 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));
+
+  /* UPC TODO: pass blocking factor to c_build_qualifed_type() */
+
+  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.  */
@@ -675,8 +693,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);
 }
 
@@ -1975,6 +2019,11 @@ default_conversion (tree exp)
 
   /* Functions and arrays have been converted during parsing.  */
   gcc_assert (code != FUNCTION_TYPE);
+
+  /* UPC TODO: is the call to array_to_pointer_conversion() necessary?  */
+  if (code == ARRAY_TYPE && upc_shared_type_p (type))
+    return array_to_pointer_conversion (input_location, exp);
+
   if (code == ARRAY_TYPE)
     return exp;
 
@@ -2174,6 +2223,40 @@ 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.  */
+             /* UPC TODO: "strict" special handling?  */
+             TREE_SHARED (ref) = 1;
+	     gcc_assert (!TREE_SHARED (field));
+	     /* UPC TODO: call build_qualified_type
+		and add layout (blocking factor) as arg.
+		to build_qualified_type.  */
+	     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);
 
@@ -2253,6 +2336,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;
 	}
@@ -2339,7 +2423,8 @@ build_array_ref (location_t loc, tree ar
 
   gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
 
-  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;
 
@@ -2349,7 +2434,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;
@@ -3242,6 +3328,23 @@ parser_build_binary_op (location_t locat
   return result;
 }
 \f
+/* 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.  */
 
@@ -3254,6 +3357,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;
 
@@ -3293,6 +3397,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.
@@ -3330,7 +3437,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;
@@ -3631,6 +3740,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);
 	  }
@@ -3713,6 +3827,16 @@ 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.  */
+          /* UPC TODO: is TREE_SHARED() safe to use here?
+	     or should it be: upc_shared_type_p (TREE_TYPE (arg))?  */
+	  if (TREE_SHARED (arg))
+	    return build1 (ADDR_EXPR, TREE_TYPE (arg), arg);
+
 	  return build_binary_op (location, PLUS_EXPR,
 				  (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE
 				   ? array_to_pointer_conversion (location,
@@ -3747,8 +3871,12 @@ build_unary_op (location_t location,
       /* If the lvalue is const or volatile, merge that into the type
 	 to which the address will point.  This should only be needed
 	 for function types.  */
+
+      /* By checking for all tree qualifiers, we also handle the UPC
+	 defined qualifiers (`shared', `strict', `relaxed') here. */
+
       if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
-	  && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)))
+	  && TREE_QUALS (arg))
 	{
 	  int orig_quals = TYPE_QUALS (strip_array_types (argtype));
 	  int quals = orig_quals;
@@ -3786,7 +3914,11 @@ 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))
+        /* UPC TODO: can &shared_var be handled in upc-gimplify? */
+	val = upc_build_shared_var_addr (location, argtype, arg);
+      else
+        val = build1 (ADDR_EXPR, argtype, arg);
 
       ret = val;
       goto return_build_unary_op;
@@ -3805,6 +3937,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) = upc_get_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);
@@ -4267,7 +4403,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;
     }
@@ -4278,7 +4415,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;
     }
@@ -4548,6 +4686,29 @@ 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)))
+    {
+      error ("UPC does not allow casts from non-shared values"
+             " to shared types");
+      return error_mark_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
@@ -4596,6 +4757,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
@@ -4647,6 +4819,23 @@ 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 local to shared pointers.");
+          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 shared pointers to integers");
+	  return error_mark_node;
+	}
+
       if (TREE_CODE (type) == INTEGER_TYPE
 	  && TREE_CODE (otype) == POINTER_TYPE
 	  && TYPE_PRECISION (type) != TYPE_PRECISION (otype))
@@ -4911,6 +5100,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 = upc_get_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)
@@ -5233,7 +5430,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;
 	    }
 	}
@@ -5315,6 +5514,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 local"
+	                      " to shared pointers.");
+	  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 shared to local pointers.");
+	      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 shared pointers,
+	     whose target type pointers 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);
 
@@ -5424,7 +5660,7 @@ convert_for_assignment (location_t locat
 		   && TREE_CODE (ttl) != FUNCTION_TYPE)
 	    {
 	      if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
-		  & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
+	          & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
 		{
 		  /* Types differing only by the presence of the 'volatile'
 		     qualifier are acceptable if the 'volatile' has been added
@@ -5604,21 +5840,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;
+  const 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.  */
 
@@ -5653,10 +5899,11 @@ store_init_value (location_t init_loc, t
 	      /* For int foo[] = (int [3]){1}; we need to set array size
 		 now since later on array initializer will be just the
 		 brace enclosed list of the compound literal.  */
-	      type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
-	      TREE_TYPE (decl) = type;
-	      TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (cldecl));
-	      layout_type (type);
+	      const tree ntype = build_distinct_type_copy (
+	                           TYPE_MAIN_VARIANT (type));
+	      TREE_TYPE (decl) = ntype;
+	      TYPE_DOMAIN (ntype) = TYPE_DOMAIN (TREE_TYPE (cldecl));
+	      layout_type (ntype);
 	      layout_decl (cldecl, 0);
 	    }
 	}
@@ -6475,6 +6722,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 = upc_get_unshared_type (constructor_type);
   if (TREE_CODE (constructor_type) == RECORD_TYPE
       || TREE_CODE (constructor_type) == UNION_TYPE)
     {
@@ -9380,12 +9630,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
@@ -9404,7 +9654,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
@@ -9665,6 +9915,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.  */
@@ -9696,9 +9956,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)
@@ -9725,10 +9993,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);
@@ -9751,6 +10027,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);
@@ -10086,7 +10367,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.  */
 
@@ -10460,15 +10740,25 @@ 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),
+      /* UPC TODO: add block_factor as arg to c_build_qualified_type(). */
+      const tree element_type = c_build_qualified_type (TREE_TYPE (type),
 						  type_quals);
+      const tree elem_block_factor = TYPE_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
-	      && TYPE_NAME (t) == TYPE_NAME (type)
+	  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
+	      && t_elem_block_factor == elem_block_factor
 	      && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
 	      && attribute_list_equal (TYPE_ATTRIBUTES (t),
 				       TYPE_ATTRIBUTES (type)))
Index: gcc/explow.c
===================================================================
--- gcc/explow.c	(.../trunk)	(revision 161517)
+++ gcc/explow.c	(.../branches/gupc)	(revision 161914)
@@ -807,6 +807,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/c-convert.c
===================================================================
--- gcc/c-convert.c	(.../trunk)	(revision 161517)
+++ gcc/c-convert.c	(.../branches/gupc)	(revision 161914)
@@ -93,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, upc_get_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 161517)
+++ gcc/varasm.c	(.../branches/gupc)	(revision 161914)
@@ -2035,7 +2035,13 @@ emit_tls_common (tree decl ATTRIBUTE_UNU
   ASM_OUTPUT_TLS_COMMON (asm_out_file, decl, name, size);
   return true;
 #else
-  sorry ("thread-local COMMON data not implemented");
+  {
+    char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
+    char msg[512];
+    sprintf (msg, "thread-local COMMON data not implemented for %s",
+             name);
+    sorry (msg);
+  }
   return true;
 #endif
 }
@@ -6190,6 +6196,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/ChangeLog.upc
===================================================================
--- gcc/ChangeLog.upc	(.../trunk)	(revision 0)
+++ gcc/ChangeLog.upc	(.../branches/gupc)	(revision 161914)
@@ -0,0 +1,64 @@
+2010-07-08  Gary Funck  <gary@intrepid.com>
+
+	Make changes so that other language compilers
+	will build and bootstrap.
+	* c-family/c-common.c (compiling_upc, flag_upc,
+	flag_upc_instrument, flag_upc_instrument_functions,
+	use_upc_dwarf2_extensions): Move to stub-upc.c and
+	upc-lang.c.
+	* c-family/c-common.h (use_upc_dwarf2_extensions,
+	compiling_upc): Add extern definitions - needed
+	to compile/build other language front ends.
+	* c-family/c.opt: Fix the spelling of ObjC.
+	It had been incorrectly spelled as Objc.
+	* c-family/c.opt: Add UPC for the various switches
+	that are valid for both C and ObjC.
+	* c-fmaily/c-opts.c: Add CL_UPC to the list of
+	supported options switches when compiling assembly
+	language.
+	* lto/lto-lang.c (use_upc_dwarf2_extensions,
+	flag_upc_instrument, flag_upc_instrument_functions):
+	Remove these definitions.  They have been moved
+	to c-family/stub-upc.c.
+	* upc/ChangeLog: Move relevant entries
+	to ChangeLog.upc.
+	* c-family/stub-upc.c (compiling_upc, flag_upc,
+	flag_upc_instrument, flag_upc_instrument_functions,
+	use_upc_dwarf2_extensions): Moved from c-common.c
+	* upc/upc-lang.c (compiling_upc, flag_upc,
+	flag_upc_instrument, flag_upc_instrument_functions,
+	use_upc_dwarf2_extensions): Moved from c-common.c
+	* objc/objc-act.c (objc_gimplify_expr): Add additional
+	parameters to c_gimplify_expr() call, that are used
+	by upc's tree rewrites.
+	* cp/cp-gimplify.c (cp_gimplify_expr): Likewise.
+	* gcc/cp/lex.c (init_reswords): If not compiling
+	UPC, then mask off the UPC keywords.
+	* cp/Make-lang.in (C_STUB_OBJS): Use this
+	make macro to link with c-family/stub-objc.o
+	and c-family/stub-upc.o.
+	* fortran/Make-lang.in (C_STUB_OBJS): Likewise.
+	* java/Make-lang.in (C_STUB_OBJS): Likewise.
+	* objc/Make-lang.in: Link with c-family/stub-upc.o
+	to avoid undefined references.
+	c-parser.c: Fix line indentation.
+	* libcpp/include/cpplib.h: Remove CL_UPC from
+	the list of language kinds accepted by the
+	C preprocessor.  This is not necessary because
+	UPC is a derivative of C99, and does not need
+	a different language kind.
+	* c-fmaily/c-opts.c (c_common_handle_option):
+	Call set_std_c99() when processing the
+	"--lang upc" switch, instead of setting the
+	language kind to CL_UPC.
+	* libupc/testsuite/libupc.upc/intrepid/ChangeLog: New.
+
+2010-07-03  Gary Funck  <gary@intrepid.com>
+
+	Merge trunk version 161517 into gupc branch.
+	* gcc/stub-upc.c: Move to gcc/c-family/.
+	* libupc/testsuite/libupc.upc/intrepid/test19.upc:
+	Add 'unused' attributes to avoid "set, but
+	not referenced" warnings.
+	* libupc/testsuite/libupc.upc/intrepid/test18.upc:
+	Likewise.
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c	(.../trunk)	(revision 161517)
+++ gcc/c-parser.c	(.../branches/gupc)	(revision 161914)
@@ -58,6 +58,8 @@ along with GCC; see the file COPYING3.  
 #include "cgraph.h"
 #include "plugin.h"
 
+#include "upc/upc-tree.h"
+
 \f
 /* Initialization routine for this file.  */
 
@@ -86,6 +88,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++)
     {
@@ -403,6 +408,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;
 	}
@@ -483,6 +493,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;
 	}
@@ -998,6 +1013,12 @@ static tree c_parser_objc_receiver (c_pa
 static tree c_parser_objc_message_args (c_parser *);
 static tree c_parser_objc_keywordexpr (c_parser *);
 
+/* 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:
@@ -1759,6 +1780,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;
@@ -3033,6 +3065,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;
@@ -3621,6 +3659,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;
@@ -3730,6 +3781,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);
 }
@@ -4023,6 +4075,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;
 	}
@@ -4071,7 +4139,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);
@@ -5312,6 +5380,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:
@@ -5347,7 +5420,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++;
@@ -5381,6 +5454,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
@@ -5394,6 +5478,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);
     }
 }
@@ -7137,6 +7234,202 @@ c_parser_objc_keywordexpr (c_parser *par
   return ret;
 }
 
+
+/* 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 for_loc = c_parser_peek_token (parser)->location;
+  location_t affinity_loc;
+  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);
+	  check_for_loop_decls (for_loc);
+	}
+      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);
+	      restore_extension_diagnostics (ext);
+	      check_for_loop_decls (for_loc);
+	    }
+	  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_CLOSE_PAREN))
+	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)
+	{
+	  c_parser_consume_token (parser);
+	  affinity = NULL_TREE;
+	}
+      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 %<)%>");
+    }
+  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);
+  body = upc_affinity_test (affinity_loc, body, affinity);
+  if (profile_upc_forall)
+    {
+      const tree gasp_start = upc_instrument_forall (loc, 1 /* start */);
+      add_stmt (gasp_start);
+    }
+  c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
+  if (profile_upc_forall)
+    {
+      const tree gasp_end = upc_instrument_forall (loc, 0 /* start */);
+      add_stmt (gasp_end);
+    }
+  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, stmt, ret;
+  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;
+  else
+    expr = NULL_TREE;
+  stmt = size_int (sync_kind);
+  ret = upc_build_sync_stmt (loc, stmt, expr);
+}
+
 \f
 /* Handle pragmas.  Some OpenMP pragmas are associated with, and therefore
    should be considered, statements.  ALLOW_STMT is true if we're within
Index: gcc/config/upc-conf.h
===================================================================
--- gcc/config/upc-conf.h	(.../trunk)	(revision 0)
+++ gcc/config/upc-conf.h	(.../branches/gupc)	(revision 161914)
@@ -0,0 +1,224 @@
+/* Define configuration-related items for UPC
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Original Implementation by Jesse M. Draper <jdraper@super.org>
+   and William W. Carlson <wwc@super.org>.
+   Extended, and ported to other architectures by
+   Gary Funck <gary@intrepid.com> and Nenad Vukicevic <nenad@intrepid.com>.
+
+This file is part of GNU CC.
+
+GNU CC 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.
+
+GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* helper macros for expanding the value of a macro as a string. */
+#define __UPC_STR__(S) #S
+#define __UPC_XSTR__(S) __UPC_STR__(S)
+
+/* Enable parsing of UPC pragma */
+#define HANDLE_PRAGMA_UPC 1
+/* Enable parsing of PUPC pragma */
+#define HANDLE_PRAGMA_PUPC 1
+
+#ifndef UPC_PTS_VADDR_FIRST
+#define UPC_PTS_VADDR_FIRST 1
+#endif
+
+#if defined(UPC_PTS_PACKED_REP)
+
+/* Defaults for packed pointer representation */
+
+#ifndef UPC_PTS_SIZE
+#define UPC_PTS_SIZE            64
+#define UPC_PTS_THREAD_SIZE     12
+#define UPC_PTS_PHASE_SIZE      16
+#define UPC_PTS_VADDR_SIZE      36
+#if UPC_PTS_VADDR_FIRST
+#define UPC_PTS_PHASE_SHIFT     0
+#define UPC_PTS_THREAD_SHIFT    UPC_PTS_PHASE_SIZE
+#define UPC_PTS_VADDR_SHIFT     UPC_PTS_PHASE_SIZE+UPC_PTS_THREAD_SIZE
+#else
+#define UPC_PTS_VADDR_SHIFT     0
+#define UPC_PTS_THREAD_SHIFT    UPC_PTS_VADDR_SIZE
+#define UPC_PTS_PHASE_SHIFT     UPC_PTS_VADDR_SIZE+UPC_PTS_THREAD_SIZE
+#endif
+#endif
+
+#define UPC_MAX_BLOCK_SIZE_STRING __UPC_XSTR__(UPC_MAX_BLOCK_SIZE)
+#define UPC_MAX_BLOCK_SIZE_CSTU build_int_cstu (long_unsigned_type_node, UPC_MAX_BLOCK_SIZE)
+
+#elif defined(UPC_PTS_STRUCT_REP)
+
+/* Define structure shared pointer representation. */
+#define UPC_PTS_SIZE            (LONG_TYPE_SIZE + POINTER_SIZE)
+#define UPC_PTS_THREAD_SIZE     (LONG_TYPE_SIZE/2)
+#define UPC_PTS_PHASE_SIZE      (LONG_TYPE_SIZE/2)
+#define UPC_PTS_VADDR_SIZE      POINTER_SIZE
+#define UPC_PTS_VADDR_TYPE      "char *"
+#define UPC_PTS_THREAD_TYPE     ((LONG_TYPE_SIZE == 64) ? "uint32_t" : "uint16_t")
+#define UPC_PTS_PHASE_TYPE      ((LONG_TYPE_SIZE == 64) ? "uint32_t" : "uint16_t")
+#define UPC_MAX_BLOCK_SIZE_CSTU build_int_cstu (long_unsigned_type_node, \
+                                (LONG_TYPE_SIZE == 64) ? 0x100000000 : 0x10000)
+#define UPC_MAX_BLOCK_SIZE_STRING ((LONG_TYPE_SIZE == 64) ? "4294967295" : "65535")
+#define UPC_MAX_THREADS           ((LONG_TYPE_SIZE == 64) ? "4294967296" : "65536")
+
+#else
+/* UPC shared pointer representaton not specified. */
+#endif
+
+/* Define UPC linker and runtime names and constructs */
+
+#ifdef TARGET_IRIX
+/* Linker switches passed via the "upc" command. */
+#define UPC_LINKER_SWITCHES "-Wl,-LD_MSG:off=84 -lm"
+#endif
+
+/* 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 in crtbegin.o to define the beginning of the shared section */
+#define UPC_SHARED_BEGIN_NAME __upc_shared_start
+#define UPC_SHARED_BEGIN_NAME_STR "__upc_shared_start"
+/* used in crtend.o to define the end of the shared section */
+#define UPC_SHARED_END_NAME __upc_shared_end
+
+/* 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 in crtbegin.o to define the beginning of the shared section */
+#define UPC_PGM_INFO_BEGIN_NAME __upc_pgm_info_start
+/* used in crtend.o to define the end of the shared section */
+#define UPC_PGM_INFO_END_NAME __upc_pgm_info_end
+
+/* Name of section where UPC iniitialization routines are located.  */
+#ifndef UPC_INIT_SECTION_NAME
+#define UPC_INIT_SECTION_NAME "upc_init"
+#endif
+/* used in crtbegin.o to define the beginning of init. routines section */
+#define UPC_INIT_BEGIN_NAME __upc_init_start
+/* used in crtend.o to define the beginning of init. routines section */
+#define UPC_INIT_END_NAME __upc_init_end
+
+/* 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 in crtbegin.o to define the beginning of UPC init. array ection */
+#define UPC_INIT_ARRAY_BEGIN_NAME __upc_init_array_start
+/* used in crtend.o to define the beginning of UPC init. array section */
+#define UPC_INIT_ARRAY_END_NAME __upc_init_array_end
+
+#ifdef TARGET_ASM_NAMED_SECTION
+
+#ifndef UPC_SHARED_SECTION_BEGIN_INIT
+#define UPC_SHARED_SECTION_BEGIN_INIT \
+/* Establish a symbol at the beginning of the data section \
+   Must take up some space, so that variables don't begin \
+   at offset zero.  */ \
+char UPC_SHARED_BEGIN_NAME [256]  \
+     __attribute__((section(UPC_SHARED_SECTION_NAME)));
+#endif
+
+#ifndef UPC_PGM_INFO_SECTION_BEGIN_INIT
+#define UPC_PGM_INFO_SECTION_BEGIN_INIT \
+/* Establish a symbol at the beginning of the progam info data section */ \
+char UPC_PGM_INFO_BEGIN_NAME []  \
+     __attribute__((section(UPC_PGM_INFO_SECTION_NAME))) = {};
+#endif
+
+#ifndef UPC_INIT_SECTION_BEGIN_INIT
+#define UPC_INIT_SECTION_BEGIN_INIT \
+/* Establish a symbol at the beginning of the section containing \
+   the code for UPC initialization procedures */ \
+char UPC_INIT_BEGIN_NAME []  \
+     __attribute__((section(UPC_INIT_SECTION_NAME))) = {};
+#endif
+
+#ifndef UPC_INIT_ARRAY_SECTION_BEGIN_INIT
+#define UPC_INIT_ARRAY_SECTION_BEGIN_INIT \
+/* Establish a symbol at the beginning of the section that contains \
+   a list of addresses pointing to UPC data initialization procedures. */ \
+void (*UPC_INIT_ARRAY_BEGIN_NAME[]) (void) \
+     __attribute__((section(UPC_INIT_ARRAY_SECTION_NAME))) = {};
+#endif
+
+#ifndef UPC_SHARED_SECTION_END_INIT
+#define UPC_SHARED_SECTION_END_INIT \
+/* Establish a symbol at the end of the shared data section */ \
+char UPC_SHARED_END_NAME []  \
+     __attribute__((section(UPC_SHARED_SECTION_NAME))) = {'\0'};
+#endif
+
+#ifndef UPC_PGM_INFO_SECTION_END_INIT
+#define UPC_PGM_INFO_SECTION_END_INIT \
+/* Establish a symbol at the end of the progam info data section */ \
+char UPC_PGM_INFO_END_NAME []  \
+     __attribute__((section(UPC_PGM_INFO_SECTION_NAME))) = {'\0'};
+#endif
+
+#ifndef UPC_INIT_SECTION_END_INIT
+#define UPC_INIT_SECTION_END_INIT \
+/* Establish a symbol at the end of the section containing \
+   the code for UPC initialization procedures */ \
+char UPC_INIT_END_NAME []  \
+     __attribute__((section(UPC_INIT_SECTION_NAME))) = {'\0'};
+#endif
+
+#ifndef UPC_INIT_ARRAY_SECTION_END_INIT
+#define UPC_INIT_ARRAY_SECTION_END_INIT \
+/* Establish a symbol at the end of the UPC init. procedure table section.  */ \
+void (*UPC_INIT_ARRAY_END_NAME[]) (void) \
+     __attribute__((section(UPC_INIT_ARRAY_SECTION_NAME))) = {0};
+#endif
+
+#endif /* TARGET_ASM_NAMED_SECTION */
+
+/* Name of initialization routine that is called to initialize
+   shared variables and calculate shared address.  Both of these
+   operations must be performed at runtime before UPC's main
+   program is called.  */
+#define UPC_INIT_DECLS_FUNC "__upc_init_decls"
+
+
+/* the name of the runtime variable holding the address of the beginning of
+   the global shared region. */
+#define UPC_GLOBAL_BASE_NAME "__upc_global_base"
+
+/* the name of the runtime variable holding the calculated size of the 
+   (per-thread) contribution to the global shared memory. */
+#define UPC_LOCAL_SIZE_NAME "__upc_local_size"
+
+/* Names of various UPC runtime library routines that implement various
+   UPC statement constructs. */
+#define UPC_BARRIER_LIBCALL "__upc_barrier"
+#define UPC_GETADDR_LIBCALL "__getaddr"
+#define UPC_NOTIFY_LIBCALL "__upc_notify"
+#define UPC_WAIT_LIBCALL "__upc_wait"
+
+/* Profiled runtime library routines  */
+#define UPC_BARRIERG_LIBCALL "__upc_barrierg"
+#define UPC_GETADDRG_LIBCALL "__getaddrg"
+#define UPC_NOTIFYG_LIBCALL "__upc_notifyg"
+#define UPC_WAITG_LIBCALL "__upc_waitg"
+
+/* Runtime library function that records upc_forall begin/end
+   when -fupc-instrument is asserted.  */
+#define UPC_INSTRUMENT_FORALL "__upc_forallg"
+
+/* Runtime library function that records function entry/exit 
+   when -fupc-instrument-functions is asserted.  */
+#define UPC_INSTRUMENT_FUNC "__upc_funcg"
Index: gcc/convert.c
===================================================================
--- gcc/convert.c	(.../trunk)	(revision 161517)
+++ gcc/convert.c	(.../branches/gupc)	(revision 161914)
@@ -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) = upc_get_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 shared pointer to 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 161517)
+++ gcc/langhooks-def.h	(.../branches/gupc)	(revision 161914)
@@ -70,7 +70,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;
@@ -133,9 +134,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);
@@ -293,7 +300,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,          \

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2011-10-13 12:42 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-07-08  6:17 RFC: [GUPC] UPC-related front-end changes Gary Funck
2010-07-08 15:07 ` Tom Tromey
2010-07-27 22:46 ` Joseph S. Myers
2010-07-31 19:26   ` Gary Funck
2011-07-01 18:33 ` Gary Funck
2011-07-01 19:28   ` Joseph S. Myers
2011-07-01 20:34     ` Gary Funck
2011-07-02  5:47     ` Gary Funck
2011-07-02 15:21       ` Joseph S. Myers
2011-07-02 19:00         ` Gary Funck
2011-07-01 20:43   ` Jakub Jelinek
2011-07-01 21:35     ` Gary Funck
2011-07-01 22:06       ` Jakub Jelinek
2011-07-02  6:13         ` Gary Funck
2011-08-17 17:53           ` tree hash maps and 'discards qualifiers' warnings? Gary Funck
2011-08-31  7:58             ` Gary Funck
2011-10-10 17:11               ` int_cst_hash_table mapping persistence and the garbage collector Gary Funck
2011-10-11  9:06                 ` Richard Guenther
2011-10-11 17:52                   ` Gary Funck
2011-10-13  5:02                     ` Laurynas Biveinis
2011-10-13  9:04                       ` Gary Funck
2011-10-13 13:08                         ` Laurynas Biveinis
2011-10-11  9:27                 ` Eric Botcazou
2011-10-12  7:56                   ` Gary Funck
2011-10-12  8:55                     ` Eric Botcazou
2011-10-12  9:25                       ` Gary Funck
2011-10-12 10:03                         ` Eric Botcazou
2011-10-12 12:17                           ` Richard Guenther
2011-10-12 17:17                             ` Gary Funck
2011-10-12 21:29                             ` Eric Botcazou
2011-07-01 23:40       ` RFC: [GUPC] UPC-related front-end changes Mike Stump
2011-07-02  6:16         ` Gary Funck
2011-07-02 20:07           ` Gary Funck

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).