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