From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12830 invoked by alias); 10 Oct 2014 20:43:37 -0000 Mailing-List: contact libffi-discuss-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libffi-discuss-owner@sourceware.org Received: (qmail 12552 invoked by uid 89); 10 Oct 2014 20:43:36 -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,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-qc0-f170.google.com Received: from mail-qc0-f170.google.com (HELO mail-qc0-f170.google.com) (209.85.216.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Fri, 10 Oct 2014 20:43:33 +0000 Received: by mail-qc0-f170.google.com with SMTP id m20so2623787qcx.1 for ; Fri, 10 Oct 2014 13:43:30 -0700 (PDT) X-Received: by 10.224.79.67 with SMTP id o3mr12610338qak.103.1412973810866; Fri, 10 Oct 2014 13:43:30 -0700 (PDT) Received: from anchor.com (50-194-63-110-static.hfc.comcastbusiness.net. [50.194.63.110]) by mx.google.com with ESMTPSA id s49sm5909008qge.15.2014.10.10.13.43.29 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 10 Oct 2014 13:43:30 -0700 (PDT) From: Richard Henderson To: gcc-patches@gcc.gnu.org Cc: libffi-discuss@sourceware.org, gofrontend-dev@googlegroups.com Subject: [PATCH 03/13] HACK! Allow the static chain to be set from C Date: Fri, 10 Oct 2014 20:43:00 -0000 Message-Id: <1412973773-3942-4-git-send-email-rth@redhat.com> In-Reply-To: <1412973773-3942-1-git-send-email-rth@redhat.com> References: <1412973773-3942-1-git-send-email-rth@redhat.com> X-IsSubscribed: yes X-SW-Source: 2014/txt/msg00098.txt.bz2 This is awful syntax, and therefore contains no documentation. But we'll need to be able to set the static chain on a few calls within the Go runtime, so we need to expose this by some means. It currently looks like function(args...) __builtin_call_chain(pointer) because that was easy to parse. I've considered alternatives such as __builtin_call_static_chain(function, pointer)(args...) wherein the builtin returns function, and magically remembers that a static chain should be applied. Or __builtin_call_go(function, pointer, args...) which is a bit more specific. Or __builtin_call_go(descriptor, args...) where descriptor must be a pointer to a structure type with a function pointer field at offset zero. The builtin would automatically perform the dereference, and apply the arguments to the function type of that field. That seems way too overkill for exactly two uses within libgo. We'd have to imagine the gccgo community writing all sorts of C-to-Go style plugins and whatnot before that becomes worthwhile. Other reasonable approaches solicited... --- gcc/c-family/c-common.c | 1 + gcc/c-family/c-common.h | 2 +- gcc/c/c-parser.c | 29 +++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/static-chain.c | 31 +++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/static-chain.c diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index e69d128..5d1bff7 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -442,6 +442,7 @@ 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_chain", RID_BUILTIN_CALL_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..6fe4748 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_CHAIN, /* C11 */ RID_ALIGNAS, RID_GENERIC, diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 0d159fd..8ec6f48 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -7776,6 +7776,35 @@ c_parser_postfix_expression_after_primary (c_parser *parser, release_tree_vector (origtypes); } arg_loc.release (); + + if (c_parser_next_token_is_keyword (parser, RID_BUILTIN_CALL_CHAIN)) + { + vec *cexpr_list; + tree chain_value; + + c_parser_consume_token (parser); + if (!c_parser_get_builtin_args (parser, "__builtin_call_chain", + &cexpr_list, true)) + break; + + if (vec_safe_length (cexpr_list) != 1) + { + error_at (expr_loc, "wrong number of arguments to " + "%<__builtin_call_chain%>"); + break; + } + chain_value = (*cexpr_list)[0].value; + mark_exp_read (chain_value); + + if (TREE_CODE (TREE_TYPE (chain_value)) != POINTER_TYPE) + { + error_at (expr_loc, "argument to %<__builtin_call_chain%> " + "must be pointer type"); + break; + } + + CALL_EXPR_STATIC_CHAIN (expr.value) = chain_value; + } break; case CPP_DOT: /* Structure element reference. */ diff --git a/gcc/testsuite/gcc.dg/static-chain.c b/gcc/testsuite/gcc.dg/static-chain.c new file mode 100644 index 0000000..ff99fdc --- /dev/null +++ b/gcc/testsuite/gcc.dg/static-chain.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 = ptr() __builtin_call_chain(&c); + if (x != &c) + abort(); + return 0; +} +#else +int main() { return 0; } +#endif -- 1.9.3