From patchwork Tue Oct 14 18:44:29 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 399538 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 359C014010F for ; Wed, 15 Oct 2014 05:44:42 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; q=dns; s=default; b=oTYdfychE6ha2Onur wK1ssFW70/VnxqE6Fa4qgRcNPBwvfTqCChWUMrutJT5VBLi6fNGQtfN9frLvBlZ9 9nmhv4PqaVxZjZxOVlrC5KRucgeT9eT2GCicQTab+n23vf0gqA2HNOEfbBjozDb8 CEmDQFnXFWp0RbK7shlcN67cgE= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; s=default; bh=PbAFS+i/jSqLOcCWuYpoIuq 5Tck=; b=CA2NkdnlvkgMsKZ6ajxhW9OLcXWaai50NmoU9COe8w17n3cSvNR7ysP 3kApp3357SC5abXTDw9pgoOCoSbkSMI1/r4P+Kxli4w1Ts+2nfwmJfuN0OqMcBLN 5rcCu1T/ohHWiuHV6AtH86hwHw2pej7tWc0Ud3c0Gz/fMGLqmRHM= Received: (qmail 10180 invoked by alias); 14 Oct 2014 18:44:35 -0000 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 Received: (qmail 10171 invoked by uid 89); 14 Oct 2014 18:44:35 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Tue, 14 Oct 2014 18:44:33 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s9EIiVla007037 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 14 Oct 2014 14:44:31 -0400 Received: from anchor.twiddle.net (vpn-233-138.phx2.redhat.com [10.3.233.138]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s9EIiU3Z029536; Tue, 14 Oct 2014 14:44:31 -0400 Message-ID: <543D6F0D.5000901@redhat.com> Date: Tue, 14 Oct 2014 11:44:29 -0700 From: Richard Henderson User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.1.1 MIME-Version: 1.0 To: gcc-patches@gcc.gnu.org CC: libffi-discuss@sourceware.org, gofrontend-dev@googlegroups.com Subject: [PATCH v2 03/13] Allow the static chain to be set from C References: <1412973773-3942-1-git-send-email-rth@redhat.com> <1412973773-3942-4-git-send-email-rth@redhat.com> In-Reply-To: <1412973773-3942-4-git-send-email-rth@redhat.com> X-IsSubscribed: yes Replacing the hacky v1 with the proposed syntax relayed by PCC, and changing the name to __builtin_call_with_static_chain. Which is kinda long, but at least it's more properly descriptive. Adds documentation and an errors test case. r~ >From 7e31234f2e112bad576b748b2ff6cc615194c0f7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 7 Oct 2014 12:17:28 -0700 Subject: [PATCH 03/13] Allow the static chain to be set from C We need to be able to set the static chain on a few calls within the Go runtime, so expose this with __builtin_call_with_static_chain. --- gcc/c-family/c-common.c | 2 ++ gcc/c-family/c-common.h | 2 +- gcc/c/c-parser.c | 40 ++++++++++++++++++++++++++++++++++++++++ gcc/doc/extend.texi | 13 +++++++++++++ gcc/testsuite/gcc.dg/cwsc0.c | 18 ++++++++++++++++++ gcc/testsuite/gcc.dg/cwsc1.c | 31 +++++++++++++++++++++++++++++++ 6 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/cwsc0.c create mode 100644 gcc/testsuite/gcc.dg/cwsc1.c diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 23163f5..f1bf47b 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -442,6 +442,8 @@ const struct c_common_resword c_common_reswords[] = { "__attribute__", RID_ATTRIBUTE, 0 }, { "__auto_type", RID_AUTO_TYPE, D_CONLY }, { "__bases", RID_BASES, D_CXXONLY }, + { "__builtin_call_with_static_chain", + RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY }, { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY }, { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY }, { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 }, diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 1e3477f..da1c12e 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -102,7 +102,7 @@ enum rid RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR, RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE, RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128, - RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, + RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN, /* C11 */ RID_ALIGNAS, RID_GENERIC, diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 346448a..708a125 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -7372,6 +7372,46 @@ c_parser_postfix_expression (c_parser *parser) = comptypes (e1, e2) ? integer_one_node : integer_zero_node; } break; + case RID_BUILTIN_CALL_WITH_STATIC_CHAIN: + { + vec *cexpr_list; + c_expr_t *e2_p; + tree chain_value; + + c_parser_consume_token (parser); + if (!c_parser_get_builtin_args (parser, + "__builtin_call_with_static_chain", + &cexpr_list, false)) + { + expr.value = error_mark_node; + break; + } + if (vec_safe_length (cexpr_list) != 2) + { + error_at (loc, "wrong number of arguments to " + "%<__builtin_call_with_static_chain%>"); + expr.value = error_mark_node; + break; + } + + expr = (*cexpr_list)[0]; + e2_p = &(*cexpr_list)[1]; + *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true); + chain_value = e2_p->value; + mark_exp_read (chain_value); + + if (TREE_CODE (expr.value) != CALL_EXPR) + error_at (loc, "first argument to " + "%<__builtin_call_with_static_chain%> " + "must be a call expression"); + else if (TREE_CODE (TREE_TYPE (chain_value)) != POINTER_TYPE) + error_at (loc, "second argument to " + "%<__builtin_call_with_static_chain%> " + "must be a pointer type"); + else + CALL_EXPR_STATIC_CHAIN (expr.value) = chain_value; + break; + } case RID_BUILTIN_COMPLEX: { vec *cexpr_list; diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 6db142e..f092ea1 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -8639,6 +8639,7 @@ in the Cilk Plus language manual which can be found at @node Other Builtins @section Other Built-in Functions Provided by GCC @cindex built-in functions +@findex __builtin_call_with_static_chain @findex __builtin_fpclassify @findex __builtin_isfinite @findex __builtin_isnormal @@ -9227,6 +9228,18 @@ depending on the arguments' types. For example: @end deftypefn +@deftypefn {Built-in Function} @var{type} __builtin_call_with_static_chain (@var{call_exp}, @var{pointer_exp}) + +The @var{call_exp} expression must be a function call, and the +@var{pointer_exp} expression must be a pointer. The @var{pointer_exp} +is passed to the function call in the target's static chain location. +The result of builtin is the result of the function call. + +@emph{Note:} This builtin is only available for C@. +This builtin can be used to call Go closures from C. + +@end deftypefn + @deftypefn {Built-in Function} @var{type} __builtin_choose_expr (@var{const_exp}, @var{exp1}, @var{exp2}) You can use the built-in function @code{__builtin_choose_expr} to diff --git a/gcc/testsuite/gcc.dg/cwsc0.c b/gcc/testsuite/gcc.dg/cwsc0.c new file mode 100644 index 0000000..4918b85 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cwsc0.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ + +#include + +#define cwsc __builtin_call_with_static_chain + +void foo(void); +void test(int (*f)(void), char *p) +{ + cwsc(f(), p); + cwsc(p, f()); /* { dg-error "must be a call" } */ + cwsc(f() + 1, p); /* { dg-error "must be a call" } */ + cwsc(f(), 0); /* { dg-error "must be a pointer" } */ + cwsc(f(), NULL); + cwsc(foo, p); /* { dg-error "must be a call" } */ + cwsc(foo(), p); + cwsc(foo(), foo); +} diff --git a/gcc/testsuite/gcc.dg/cwsc1.c b/gcc/testsuite/gcc.dg/cwsc1.c new file mode 100644 index 0000000..4ab86fb --- /dev/null +++ b/gcc/testsuite/gcc.dg/cwsc1.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +#if defined(__x86_64__) +# define CHAIN "%r10" +#elif defined(__i386__) +# define CHAIN "%ecx" +#elif defined(__aarch64__) +# define CHAIN "x18" +#endif + +#ifdef CHAIN +void *__attribute__((noinline, noclone)) foo(void) +{ + register void *chain __asm__(CHAIN); + return chain; +} + +void * (*ptr)(void) = foo; +extern void abort(void); + +int main() +{ + char c; + void *x = __builtin_call_with_static_chain(ptr(), &c); + if (x != &c) + abort(); + return 0; +} +#else +int main() { return 0; } +#endif -- 1.9.3