From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR01-VE1-obe.outbound.protection.outlook.com (mail-eopbgr140059.outbound.protection.outlook.com [40.107.14.59]) by sourceware.org (Postfix) with ESMTPS id 5FF663865C10; Wed, 19 Aug 2020 07:17:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 5FF663865C10 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=Andrea.Corallo@arm.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=9Fv59261Q+hn0yjnb9Fzh5WioML/cXHzs8ddIX9IgM0=; b=Ub5uJRxPtexnnkVlQKPcx5C7ID+VWT7DwF7UYdzaxNliNfDEzpMDcwwcPwEs57WGPQjJuCQvoFqZVcDUjRGes2oQuciimQ00EYqNlsFfuis3FCZcy40hhhPEJzBfZjHIf1bo+mSvn3mDKT9bQaGywq8c9gqYou5bgKmhM+bMr7k= Received: from AM5PR0701CA0069.eurprd07.prod.outlook.com (2603:10a6:203:2::31) by VE1PR08MB5725.eurprd08.prod.outlook.com (2603:10a6:800:1b0::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.20; Wed, 19 Aug 2020 07:17:18 +0000 Received: from AM5EUR03FT008.eop-EUR03.prod.protection.outlook.com (2603:10a6:203:2:cafe::b5) by AM5PR0701CA0069.outlook.office365.com (2603:10a6:203:2::31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3305.17 via Frontend Transport; Wed, 19 Aug 2020 07:17:18 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; gcc.gnu.org; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com;gcc.gnu.org; dmarc=bestguesspass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 63.35.35.123 as permitted sender) receiver=protection.outlook.com; client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com; Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT008.mail.protection.outlook.com (10.152.16.123) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3305.24 via Frontend Transport; Wed, 19 Aug 2020 07:17:18 +0000 Received: ("Tessian outbound bac899b43a54:v64"); Wed, 19 Aug 2020 07:17:18 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 2df07948cbd701b9 X-CR-MTA-TID: 64aa7808 Received: from 95a13d7d8163.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 586CE8AC-633A-41B3-96A2-9DC30583796C.1; Wed, 19 Aug 2020 07:17:11 +0000 Received: from EUR05-VI1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 95a13d7d8163.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 19 Aug 2020 07:17:11 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=foPUbL3phxWN431lP5XuwRgMiP1Bv2fIaJaTe8Dn2UJfSHIYxNW4AIbEII9DHFnTwFsxsT8AXj//ZLP1NJh49LcVARqPt3mwfcODUtGb3ATSWAzLpgJZ8AkHIblPNGo1cAuX8QCX8QUlPSD7afJGkoJv7yRSAbIZbn8dze/8fPqAG4JU8FdDM32bzCeEvNOvh3Sj8dlulpaLkkmwp001Aee6nLDgpSc4PkGgrMKyDSThDY/Jo7ynkGn48aKBI3nF84SRSQpyXIdeeUEJi7eQcV4NZ8X9CjO4J+gmVodb31LnIpv8kTvobMYKTFkKHDWYpM1vZcUtT48hC6nRjOMh8w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=9Fv59261Q+hn0yjnb9Fzh5WioML/cXHzs8ddIX9IgM0=; b=ND9QptHzcES8TlFnWdXpVCzwo9VewGTwGrTVler8Kdy8Hu/UTxH8QBz0gLjuV5EbNw9nWxrJNzvhVuXX6DREOZfIxUDVulZ7SjhXb7sG5cVQX1ZbNmP3iJGBietJR0QVvrgQWXNGsv19Pdwu73yWdOyIGSnu8978HjVjWp7m55U9Le7o2dcVMNfmx72Tenl0B7bupVmD1FUT7yYh/cCNORY0jjIVjwIIPdpDXW5SZXbbmDxEiT+qFcbgJkQtNGguobBTtikJlaB/ikZD0Gdf4TPM22WH5SMj49wvCPo4M60a+9C4Shf7nb89jKmxnHjVthVFXMCY+s+tf0Wi0YUhaQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=9Fv59261Q+hn0yjnb9Fzh5WioML/cXHzs8ddIX9IgM0=; b=Ub5uJRxPtexnnkVlQKPcx5C7ID+VWT7DwF7UYdzaxNliNfDEzpMDcwwcPwEs57WGPQjJuCQvoFqZVcDUjRGes2oQuciimQ00EYqNlsFfuis3FCZcy40hhhPEJzBfZjHIf1bo+mSvn3mDKT9bQaGywq8c9gqYou5bgKmhM+bMr7k= Authentication-Results-Original: gcc.gnu.org; dkim=none (message not signed) header.d=none;gcc.gnu.org; dmarc=none action=none header.from=arm.com; Received: from AM6PR08MB4900.eurprd08.prod.outlook.com (2603:10a6:20b:cc::10) by AM6PR08MB3351.eurprd08.prod.outlook.com (2603:10a6:209:48::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.18; Wed, 19 Aug 2020 07:17:09 +0000 Received: from AM6PR08MB4900.eurprd08.prod.outlook.com ([fe80::d070:f136:4090:9ed3]) by AM6PR08MB4900.eurprd08.prod.outlook.com ([fe80::d070:f136:4090:9ed3%5]) with mapi id 15.20.3305.025; Wed, 19 Aug 2020 07:17:09 +0000 From: Andrea Corallo To: David Malcolm Cc: jit@gcc.gnu.org, nd@arm.com, gcc-patches@gcc.gnu.org Subject: Re: [PATCH V2] libgccjit: Add new gcc_jit_context_new_blob entry point References: <59a8d345c642d49281a601278946e087a4bbe3e2.camel@redhat.com> <87zh9kumwi.fsf@arm.com> <93e3d65a0b04b13a5d5c9970a2058d167357ed6c.camel@redhat.com> <22479e6a6a1e27df07a3d2c2cfb8c6c8420a7d3d.camel@redhat.com> Date: Wed, 19 Aug 2020 09:17:05 +0200 In-Reply-To: (David Malcolm's message of "Thu, 06 Aug 2020 15:53:56 -0400") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) Content-Type: multipart/mixed; boundary="=-=-=" X-ClientProxiedBy: LO2P265CA0052.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::16) To AM6PR08MB4900.eurprd08.prod.outlook.com (2603:10a6:20b:cc::10) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from e124257 (217.140.106.37) by LO2P265CA0052.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3305.24 via Frontend Transport; Wed, 19 Aug 2020 07:17:08 +0000 X-Originating-IP: [217.140.106.37] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: b3c6c70e-5cfb-4483-cd0b-08d8440fe829 X-MS-TrafficTypeDiagnostic: AM6PR08MB3351:|VE1PR08MB5725: X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Oob-TLC-OOBClassifiers: OLM:1850;OLM:1850; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: LkoVKIeU87eYO0JZ+nuhKP5zl091DFtWhAZFqgFceAjMfoAAdTODbJKVHT5/VRJVe5573pyuajf36Tm8t/JFFERzOmxomkpZBkaFTAeMJjS9O0dsddtioeWUg1YHIyVzpQdZ8Ngq+llAliy5sr9/jp6xz3M9pnBaPNjmQcY13D1I55Oc4k73uyZkOSIMHGqk+ooPs4LsL/U3tkk3wuh737OLsLCjnw9/x5C3HAp8bnf4fI2iVsqDHfyM6FpRyVJUX+7daAcAI4KYC6JBoOE9BnAn9dzAfknTMc5ld/xdsCdN6rd31pJfIKoW3Du11c7qscNLunYPFp7IiJeqMw6J3Q== X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:AM6PR08MB4900.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(4636009)(376002)(39860400002)(136003)(366004)(346002)(396003)(235185007)(66946007)(26005)(5660300002)(44832011)(316002)(36756003)(8676002)(16526019)(186003)(4326008)(2906002)(83380400001)(6486002)(6496006)(6666004)(8936002)(33964004)(2616005)(66616009)(66556008)(66476007)(86362001)(478600001)(956004)(6916009)(52116002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData: Z9O291tsOHadYNNyl9mN15tK2NxuvZEE16Jln2HMEsFMA/9J4yPVROxIZbEyZtEiht61Fj+wxD2Vu2msTkLYk+dUdRT679N3g1cHn1aByNp3CzbkYUs2R3+i/2uTAbc6fSIWw8QHYZd/zE9AaDCRmY0ACPau6O55lho3QGr6/t/MFb8fbPgIWkXC7tKeyx9WgDzyW/rrL1iFN2WYRlpK23VSZemSM++87I7TfWrQHqrI7ZQGv8izDWltZAHGGoo0F6J5o7WD06+Ezygx+X13X9CT7NbDLOI3i+RB0dV7pXolyX9RY3+1bBQeOvsB2MYXxNLkh8lHUy/9UXKLVctxiYE81rHzsu92w+wuNxl/7uKUb1VNIYu7l8iBJOnxEwxhCEqM9ANCP7T81lO31OjiPqJaKfH1QWdAKv/M0KEC38s1vQ9shHQcOcPvnIEi4FzavGIoESLAFDq8Tc3WDKQYqlhBZwF1+BslnYDQRPJwFBhS+wJyZZSvomFgacBHbnzQKWAfXrbYX6MJsm7FDL71e82G2clHZeprYfX8ftfE28Z3Ck/JpXnZdEmrs9d3lTHtegfScT3Ba2+nmwks8XNl8ZRSCta3zPqeSHxhOC2M3jzawUy8dl8rglpa3b4wSWfBFAl1SECZ/lFaQwLNLW/O5w== X-MS-Exchange-Transport-Forked: True X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR08MB3351 Original-Authentication-Results: gcc.gnu.org; dkim=none (message not signed) header.d=none;gcc.gnu.org; dmarc=none action=none header.from=arm.com; X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT008.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 895f3dc1-b04d-44c0-caf6-08d8440fe23d X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: UUKeMU4SrbTtlWkhjAbo2mOki6oXnakSzsoMnnKt6ec6nkrx03O0p0ov6EeRKbUa83WBbL2RHr7ajYAqKL0F2Qavvgza7ahCjRDOwPlA0T5NfNO5C7S0/ejUIGMHbJEMcvNgDLxtVkmTflZLGfwQUUejq1NzIKD8bsv01C+RS24NFwDxywBuXGlEqOxFKNhliqqe+K1jrGJ17er5B4NQ1VFDnmM2n0BqAaQ8SpEksndavreWFRA6qbJ3bqo8fAZVUTYdMHx7Ljgp6IJeOYyXRmPzkYwZVFwjyxdx6fWZiTkHP9f6ulfqOVEnE7dw2Q3EnFLlMhkY6pbITCSiwJh8oRj66BNYRh83IswLjbB4AmciBmkPu5B2X/BqAJ4bepy7JRdFDp70ZrTwfCWrRSAIuw== X-Forefront-Antispam-Report: CIP:63.35.35.123; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:64aa7808-outbound-1.mta.getcheckrecipient.com; PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com; CAT:NONE; SFS:(4636009)(396003)(376002)(136003)(39860400002)(346002)(46966005)(8676002)(5660300002)(82310400002)(356005)(4326008)(36756003)(6496006)(235185007)(478600001)(36906005)(66616009)(70586007)(316002)(81166007)(8936002)(450100002)(6862004)(82740400003)(86362001)(70206006)(47076004)(6486002)(33964004)(956004)(186003)(44832011)(2616005)(83380400001)(26005)(336012)(6666004)(16526019)(2906002); DIR:OUT; SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2020 07:17:18.2408 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: b3c6c70e-5cfb-4483-cd0b-08d8440fe829 X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d; Ip=[63.35.35.123]; Helo=[64aa7808-outbound-1.mta.getcheckrecipient.com] X-MS-Exchange-CrossTenant-AuthSource: AM5EUR03FT008.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: VE1PR08MB5725 X-Spam-Status: No, score=-14.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, MSGID_FROM_MTA_HEADER, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP, T_FILL_THIS_FORM_SHORT, UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: jit@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Jit mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 19 Aug 2020 07:17:25 -0000 --=-=-= Content-Type: text/plain David Malcolm writes: > Thanks for the updated patch. Comments inline below. Hi Dave, sorry for the late reply. > [...] > >> diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst >> index d783ceea51a8..7699dcfd27be 100644 >> --- a/gcc/jit/docs/topics/expressions.rst >> +++ b/gcc/jit/docs/topics/expressions.rst >> @@ -582,6 +582,27 @@ Global variables >> referring to it. Analogous to using an "extern" global from a >> header file. >> >> +.. function:: gcc_jit_lvalue *\ >> + gcc_jit_global_set_initializer (gcc_jit_lvalue *global,\ >> + const void *blob,\ >> + size_t num_bytes) >> + >> + Set an initializer for an object using the memory content pointed >> + by ``blob`` for ``num_bytes``. ``global`` must be an arrays of an > > Typo: "arrays" -> "array" Fixed >> + integral type. > > Why the non-void return type? Looking at libgccjit.c I see it returns > "global" if it succeeds, or NULL if it fails. Wouldn't it be better to > simply have void return type, and rely on the normaly error-handling > mechanisms? > Or is this inspired by the inline asm patch? (for PR 87291) The idea is that this way the user could also create the global, initialize it and directly use it like: foo (gcc_jit_global_set_initializer (gcc_jit_context_new_global (...), ...)) I left it that way, let me know if you prefer otherwise. [...] > >> --- a/gcc/jit/jit-playback.h >> +++ b/gcc/jit/jit-playback.h >> @@ -111,6 +111,15 @@ public: >> type *type, >> const char *name); >> >> + lvalue * >> + new_global_initialized (location *loc, >> + enum gcc_jit_global_kind kind, >> + type *type, >> + size_t element_size, >> + size_t initializer_num_elem, >> + const void *initializer, >> + const char *name); >> + >> template >> rvalue * >> new_rvalue_from_const (type *type, >> @@ -266,6 +275,14 @@ private: >> const char * get_path_s_file () const; >> const char * get_path_so_file () const; >> >> + tree >> + global_new_decl (location *loc, >> + enum gcc_jit_global_kind kind, >> + type *type, >> + const char *name); >> + lvalue * >> + global_finalize_lvalue (tree inner); >> + >> private: >> >> /* Functions for implementing "compile". */ >> diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c >> index 0fddf04da873..52fc92f5928c 100644 >> --- a/gcc/jit/jit-playback.c >> +++ b/gcc/jit/jit-playback.c >> @@ -510,14 +510,14 @@ new_function (location *loc, >> return func; >> } >> >> -/* Construct a playback::lvalue instance (wrapping a tree). */ >> +/* In use by new_global and new_global_initialized. */ >> >> -playback::lvalue * >> +tree >> playback::context:: >> -new_global (location *loc, >> - enum gcc_jit_global_kind kind, >> - type *type, >> - const char *name) >> +global_new_decl (location *loc, >> + enum gcc_jit_global_kind kind, >> + type *type, >> + const char *name) >> { >> gcc_assert (type); >> gcc_assert (name); >> @@ -547,6 +547,15 @@ new_global (location *loc, >> if (loc) >> set_tree_location (inner, loc); >> >> + return inner; >> +} >> + >> +/* In use by new_global and new_global_initialized. */ >> + >> +playback::lvalue * >> +playback::context:: >> +global_finalize_lvalue (tree inner) >> +{ >> varpool_node::get_create (inner); >> >> varpool_node::finalize_decl (inner); >> @@ -556,6 +565,90 @@ new_global (location *loc, >> return new lvalue (this, inner); >> } >> >> +/* Construct a playback::lvalue instance (wrapping a tree). */ >> + >> +playback::lvalue * >> +playback::context:: >> +new_global (location *loc, >> + enum gcc_jit_global_kind kind, >> + type *type, >> + const char *name) >> +{ >> + tree inner = global_new_decl (loc, kind, type, name); >> + >> + return global_finalize_lvalue (inner); >> +} >> + >> +/* Fill 'constructor_elements' with the memory content of >> + 'initializer'. Each element of the initializer is of the size of >> + type T. In use by new_global_initialized.*/ >> + >> +template >> +static void >> +load_blob_in_ctor (vec *&constructor_elements, >> + size_t num_elem, >> + const void *initializer) >> +{ >> + /* Loosely based on 'output_init_element' c-typeck.c:9691. */ >> + const T *p = (const T *)initializer; >> + tree node = make_unsigned_type (BITS_PER_UNIT * sizeof (T)); >> + for (size_t i = 0; i < num_elem; i++) >> + { >> + constructor_elt celt = >> + { build_int_cst (long_unsigned_type_node, i), >> + build_int_cst (node, p[i]) }; >> + vec_safe_push (constructor_elements, celt); >> + } >> +} >> + >> +/* Construct an initialized playback::lvalue instance (wrapping a >> + tree). */ >> + >> +playback::lvalue * >> +playback::context:: >> +new_global_initialized (location *loc, >> + enum gcc_jit_global_kind kind, >> + type *type, >> + size_t element_size, >> + size_t initializer_num_elem, >> + const void *initializer, >> + const char *name) >> +{ >> + tree inner = global_new_decl (loc, kind, type, name); >> + >> + static vec *constructor_elements; > > Why the use of a function-level static variable here, and why va_gc? > Wouldn't an auto_vec be cleaner? > Ah: is it because of the call to build_constructor? > If so, can the "static" be removed and replaced with an "= NULL;" > initializer? > > (I'm very wary of function-level static variables, as they're a place > when state can "hide" between multiple in-process invocations of the > compiler) Sorry that's due to my ignorance on how GCC GC works, I thought GC roots had to be static, fixed. [...] >> private: >> string * make_debug_string () FINAL OVERRIDE { return m_name; } >> + template >> + void write_initializer_reproducer (const char *id, reproducer &r); >> void write_reproducer (reproducer &r) FINAL OVERRIDE; >> enum precedence get_precedence () const FINAL OVERRIDE >> { >> @@ -1346,6 +1370,8 @@ private: >> private: >> enum gcc_jit_global_kind m_kind; >> string *m_name; >> + void *m_initializer = NULL; >> + size_t m_initializer_num_bytes = 0; >> }; > > Are we still targetting C++98, and are these initializers compatible > with it? Apparently C++03 but AFAIU this should be compatible only with C++11 on, moved the zeroing into the ctor. >> template >> diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c >> index b73cd76a0a02..f97de00f63c3 100644 >> --- a/gcc/jit/jit-recording.c >> +++ b/gcc/jit/jit-recording.c > > [...] > >> @@ -4440,9 +4510,26 @@ recording::global::write_to_dump (dump &d) >> d.write ("extern "); >> break; >> } >> - d.write ("%s %s;\n", >> + >> + d.write ("%s %s", >> m_type->get_debug_string (), >> get_debug_string ()); >> + >> + if (!m_initializer) >> + { >> + d.write (";\n"); >> + return; >> + } >> + >> + d.write ("=\n { "); >> + const char *p = (const char *)m_initializer; > > Should be "const unsigned char"? Probably better, fixed. >> + for (size_t i = 0; i < m_initializer_num_bytes; i++) >> + { >> + d.write ("0x%x, ", p[i]); >> + if (i && !(i % 64)) >> + d.write ("\n "); >> + } >> + d.write ("};\n"); >> } >> >> /* A table of enum gcc_jit_global_kind values expressed in string >> @@ -4454,6 +4541,27 @@ static const char * const global_kind_reproducer_strings[] = { >> "GCC_JIT_GLOBAL_IMPORTED" >> }; [...] > > Thanks again for the patch; hope this is constructive > Dave Sure it is, thanks for reviewing. Attached the updated version of the patch. make check-jit is clean plus I tested the new entry point with the modified Emacs. Thanks Andrea --=-=-= Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename=0001-Add-new-gcc_jit_global_set_initializer-entry-point.patch >From 74970a5ac988e8a641967dee39ec8fa711228a91 Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Sat, 30 May 2020 10:33:08 +0100 Subject: [PATCH] Add new gcc_jit_global_set_initializer entry point gcc/jit/ChangeLog 2020-08-01 Andrea Corallo * docs/topics/compatibility.rst (LIBGCCJIT_ABI_14): New ABI tag. * docs/topics/expressions.rst (gcc_jit_global_set_initializer): Document new entry point in section 'Global variables'. * jit-playback.c (global_new_decl, global_finalize_lvalue): New method. (playback::context::new_global): Make use of global_new_decl, global_finalize_lvalue. (load_blob_in_ctor): New template function in use by the following. (playback::context::new_global_initialized): New method. * jit-playback.h (class context): Decl 'new_global_initialized', 'global_new_decl', 'global_finalize_lvalue'. (lvalue::set_initializer): Add implementation. * jit-recording.c (recording::memento_of_get_pointer::get_size) (recording::memento_of_get_type::get_size): Add implementation. (recording::global::write_initializer_reproducer): New function in use by 'recording::global::write_reproducer'. (recording::global::replay_into) (recording::global::write_to_dump) (recording::global::write_reproducer): Handle initialized case. * jit-recording.h (class type): Decl 'get_size' and 'num_elements'. * libgccjit++.h (class lvalue): Declare new 'set_initializer' method. (class lvalue): Decl 'is_global' and 'set_initializer'. (class global) Decl 'write_initializer_reproducer'. Add 'm_initializer', 'm_initializer_num_bytes' fields. Implement 'set_initializer'. Add a destructor to free 'm_initializer'. * libgccjit.c (gcc_jit_global_set_initializer): New function. * libgccjit.h (gcc_jit_global_set_initializer): New function declaration. * libgccjit.map (LIBGCCJIT_ABI_14): New ABI tag. gcc/testsuite/ChangeLog 2020-08-01 Andrea Corallo * jit.dg/all-non-failing-tests.h: Add test-blob.c. * jit.dg/test-global-set-initializer.c: New testcase. --- gcc/jit/docs/topics/compatibility.rst | 7 + gcc/jit/docs/topics/expressions.rst | 21 +++ gcc/jit/jit-playback.c | 105 +++++++++++++- gcc/jit/jit-playback.h | 17 +++ gcc/jit/jit-recording.c | 137 +++++++++++++++++- gcc/jit/jit-recording.h | 38 ++++- gcc/jit/libgccjit++.h | 10 ++ gcc/jit/libgccjit.c | 38 +++++ gcc/jit/libgccjit.h | 14 ++ gcc/jit/libgccjit.map | 7 +- gcc/testsuite/jit.dg/all-non-failing-tests.h | 7 + .../jit.dg/test-global-set-initializer.c | 78 ++++++++++ 12 files changed, 466 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-global-set-initializer.c diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index bb3387fa583..6bfa101ed71 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -219,3 +219,10 @@ entrypoints: * :func:`gcc_jit_version_minor` * :func:`gcc_jit_version_patchlevel` + +.. _LIBGCCJIT_ABI_14: + +``LIBGCCJIT_ABI_14`` +-------------------- +``LIBGCCJIT_ABI_14`` covers the addition of +:func:`gcc_jit_global_set_initializer` diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst index d783ceea51a..28f81be0060 100644 --- a/gcc/jit/docs/topics/expressions.rst +++ b/gcc/jit/docs/topics/expressions.rst @@ -582,6 +582,27 @@ Global variables referring to it. Analogous to using an "extern" global from a header file. +.. function:: gcc_jit_lvalue *\ + gcc_jit_global_set_initializer (gcc_jit_lvalue *global,\ + const void *blob,\ + size_t num_bytes) + + Set an initializer for an object using the memory content pointed + by ``blob`` for ``num_bytes``. ``global`` must be an array of an + integral type. + + The parameter ``blob`` must be non-NULL. The call copies the memory + pointed by ``blob`` for ``num_bytes`` bytes, so it is valid to pass + in a pointer to an on-stack buffer. The content will be stored in + the compilation unit and used as initialization value of the array. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_14`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer + Working with pointers, structs and unions ----------------------------------------- diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c index 0fddf04da87..b68e18278e3 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -510,14 +510,14 @@ new_function (location *loc, return func; } -/* Construct a playback::lvalue instance (wrapping a tree). */ +/* In use by new_global and new_global_initialized. */ -playback::lvalue * +tree playback::context:: -new_global (location *loc, - enum gcc_jit_global_kind kind, - type *type, - const char *name) +global_new_decl (location *loc, + enum gcc_jit_global_kind kind, + type *type, + const char *name) { gcc_assert (type); gcc_assert (name); @@ -547,6 +547,15 @@ new_global (location *loc, if (loc) set_tree_location (inner, loc); + return inner; +} + +/* In use by new_global and new_global_initialized. */ + +playback::lvalue * +playback::context:: +global_finalize_lvalue (tree inner) +{ varpool_node::get_create (inner); varpool_node::finalize_decl (inner); @@ -556,6 +565,90 @@ new_global (location *loc, return new lvalue (this, inner); } +/* Construct a playback::lvalue instance (wrapping a tree). */ + +playback::lvalue * +playback::context:: +new_global (location *loc, + enum gcc_jit_global_kind kind, + type *type, + const char *name) +{ + tree inner = global_new_decl (loc, kind, type, name); + + return global_finalize_lvalue (inner); +} + +/* Fill 'constructor_elements' with the memory content of + 'initializer'. Each element of the initializer is of the size of + type T. In use by new_global_initialized.*/ + +template +static void +load_blob_in_ctor (vec *&constructor_elements, + size_t num_elem, + const void *initializer) +{ + /* Loosely based on 'output_init_element' c-typeck.c:9691. */ + const T *p = (const T *)initializer; + tree node = make_unsigned_type (BITS_PER_UNIT * sizeof (T)); + for (size_t i = 0; i < num_elem; i++) + { + constructor_elt celt = + { build_int_cst (long_unsigned_type_node, i), + build_int_cst (node, p[i]) }; + vec_safe_push (constructor_elements, celt); + } +} + +/* Construct an initialized playback::lvalue instance (wrapping a + tree). */ + +playback::lvalue * +playback::context:: +new_global_initialized (location *loc, + enum gcc_jit_global_kind kind, + type *type, + size_t element_size, + size_t initializer_num_elem, + const void *initializer, + const char *name) +{ + tree inner = global_new_decl (loc, kind, type, name); + + vec *constructor_elements = NULL; + + switch (element_size) + { + case 1: + load_blob_in_ctor (constructor_elements, initializer_num_elem, + initializer); + break; + case 2: + load_blob_in_ctor (constructor_elements, initializer_num_elem, + initializer); + break; + case 4: + load_blob_in_ctor (constructor_elements, initializer_num_elem, + initializer); + break; + case 8: + load_blob_in_ctor (constructor_elements, initializer_num_elem, + initializer); + break; + default: + gcc_unreachable (); + } + /* Compare with 'pop_init_level' c-typeck.c:8780. */ + tree ctor = build_constructor (type->as_tree (), constructor_elements); + constructor_elements = NULL; + + /* Compare with 'store_init_value' c-typeck.c:7555. */ + DECL_INITIAL (inner) = ctor; + + return global_finalize_lvalue (inner); +} + /* Implementation of the various gcc::jit::playback::context::new_rvalue_from_const methods. diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index f9b3e675368..50b69753bb4 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -111,6 +111,15 @@ public: type *type, const char *name); + lvalue * + new_global_initialized (location *loc, + enum gcc_jit_global_kind kind, + type *type, + size_t element_size, + size_t initializer_num_elem, + const void *initializer, + const char *name); + template rvalue * new_rvalue_from_const (type *type, @@ -266,6 +275,14 @@ private: const char * get_path_s_file () const; const char * get_path_so_file () const; + tree + global_new_decl (location *loc, + enum gcc_jit_global_kind kind, + type *type, + const char *name); + lvalue * + global_finalize_lvalue (tree inner); + private: /* Functions for implementing "compile". */ diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index b73cd76a0a0..39510097c6f 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -2175,6 +2175,57 @@ recording::type::access_as_type (reproducer &r) return r.get_identifier (this); } +/* Override of default implementation of + recording::type::get_size. + + Return the size in bytes. This is in use for global + initialization. */ + +size_t +recording::memento_of_get_type::get_size () +{ + int size; + switch (m_kind) + { + case GCC_JIT_TYPE_VOID: + return 0; + case GCC_JIT_TYPE_BOOL: + case GCC_JIT_TYPE_CHAR: + case GCC_JIT_TYPE_SIGNED_CHAR: + case GCC_JIT_TYPE_UNSIGNED_CHAR: + return 1; + case GCC_JIT_TYPE_SHORT: + case GCC_JIT_TYPE_UNSIGNED_SHORT: + size = SHORT_TYPE_SIZE; + break; + case GCC_JIT_TYPE_INT: + case GCC_JIT_TYPE_UNSIGNED_INT: + size = INT_TYPE_SIZE; + break; + case GCC_JIT_TYPE_LONG: + case GCC_JIT_TYPE_UNSIGNED_LONG: + size = LONG_TYPE_SIZE; + break; + case GCC_JIT_TYPE_LONG_LONG: + case GCC_JIT_TYPE_UNSIGNED_LONG_LONG: + size = LONG_LONG_TYPE_SIZE; + break; + case GCC_JIT_TYPE_FLOAT: + size = FLOAT_TYPE_SIZE; + break; + case GCC_JIT_TYPE_DOUBLE: + size = DOUBLE_TYPE_SIZE; + break; + case GCC_JIT_TYPE_LONG_DOUBLE: + size = LONG_DOUBLE_TYPE_SIZE; + break; + default: + gcc_unreachable (); + } + + return size / BITS_PER_UNIT; +} + /* Implementation of pure virtual hook recording::type::dereference for recording::memento_of_get_type. */ @@ -2482,6 +2533,15 @@ recording::memento_of_get_type::write_reproducer (reproducer &r) /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */ +/* Override of default implementation of + recording::type::get_size for get_pointer. */ + +size_t +recording::memento_of_get_pointer::get_size () +{ + return POINTER_SIZE / BITS_PER_UNIT; +} + /* Override of default implementation of recording::type::accepts_writes_from for get_pointer. @@ -4393,10 +4453,20 @@ recording::block::dump_edges_to_dot (pretty_printer *pp) void recording::global::replay_into (replayer *r) { - set_playback_obj (r->new_global (playback_location (r, m_loc), - m_kind, - m_type->playback_type (), - playback_string (m_name))); + set_playback_obj ( + m_initializer + ? r->new_global_initialized (playback_location (r, m_loc), + m_kind, + m_type->playback_type (), + m_type->dereference ()->get_size (), + m_initializer_num_bytes + / m_type->dereference ()->get_size (), + m_initializer, + playback_string (m_name)) + : r->new_global (playback_location (r, m_loc), + m_kind, + m_type->playback_type (), + playback_string (m_name))); } /* Override the default implementation of @@ -4440,9 +4510,26 @@ recording::global::write_to_dump (dump &d) d.write ("extern "); break; } - d.write ("%s %s;\n", + + d.write ("%s %s", m_type->get_debug_string (), get_debug_string ()); + + if (!m_initializer) + { + d.write (";\n"); + return; + } + + d.write ("=\n { "); + const unsigned char *p = (const unsigned char *)m_initializer; + for (size_t i = 0; i < m_initializer_num_bytes; i++) + { + d.write ("0x%x, ", p[i]); + if (i && !(i % 64)) + d.write ("\n "); + } + d.write ("};\n"); } /* A table of enum gcc_jit_global_kind values expressed in string @@ -4454,6 +4541,27 @@ static const char * const global_kind_reproducer_strings[] = { "GCC_JIT_GLOBAL_IMPORTED" }; +template +void +recording::global::write_initializer_reproducer (const char *id, reproducer &r) +{ + const char *init_id = r.make_tmp_identifier ("init_for", this); + r.write (" %s %s[] =\n {", + m_type->dereference ()->get_debug_string (), + init_id); + + const T *p = (const T *)m_initializer; + for (size_t i = 0; i < m_initializer_num_bytes / sizeof (T); i++) + { + r.write ("%" PRIu64 ", ", (uint64_t)p[i]); + if (i && !(i % 64)) + r.write ("\n "); + } + r.write ("};\n"); + r.write (" gcc_jit_global_set_initializer (%s, %s, sizeof (%s));\n", + id, init_id, init_id); +} + /* Implementation of recording::memento::write_reproducer for globals. */ void @@ -4472,6 +4580,25 @@ recording::global::write_reproducer (reproducer &r) global_kind_reproducer_strings[m_kind], r.get_identifier_as_type (get_type ()), m_name->get_debug_string ()); + + if (m_initializer) + switch (m_type->dereference ()->get_size ()) + { + case 1: + write_initializer_reproducer (id, r); + break; + case 2: + write_initializer_reproducer (id, r); + break; + case 4: + write_initializer_reproducer (id, r); + break; + case 8: + write_initializer_reproducer (id, r); + break; + default: + gcc_unreachable (); + } } /* The implementation of the various const-handling classes: diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 726b9c4b837..aa38e606a8d 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -502,6 +502,12 @@ public: This will return NULL if it's not valid to dereference this type. The caller is responsible for setting an error. */ virtual type *dereference () = 0; + /* Get the type size in bytes. + + This is implemented only for memento_of_get_type and + memento_of_get_pointer as is use for initializing globals of + these types. */ + virtual size_t get_size () { gcc_unreachable (); } /* Dynamic casts. */ virtual function_type *dyn_cast_function_type () { return NULL; } @@ -569,6 +575,8 @@ public: type *dereference () FINAL OVERRIDE; + size_t get_size () FINAL OVERRIDE; + bool accepts_writes_from (type *rtype) FINAL OVERRIDE { if (m_kind == GCC_JIT_TYPE_VOID_PTR) @@ -610,6 +618,8 @@ public: type *dereference () FINAL OVERRIDE { return m_other_type; } + size_t get_size () FINAL OVERRIDE; + bool accepts_writes_from (type *rtype) FINAL OVERRIDE; void replay_into (replayer *r) FINAL OVERRIDE; @@ -755,6 +765,7 @@ class array_type : public type bool is_bool () const FINAL OVERRIDE { return false; } type *is_pointer () FINAL OVERRIDE { return NULL; } type *is_array () FINAL OVERRIDE { return m_element_type; } + int num_elements () { return m_num_elements; } void replay_into (replayer *) FINAL OVERRIDE; @@ -1107,6 +1118,7 @@ public: const char *access_as_rvalue (reproducer &r) OVERRIDE; virtual const char *access_as_lvalue (reproducer &r); + virtual bool is_global () const { return false; } }; class param : public lvalue @@ -1327,7 +1339,14 @@ public: : lvalue (ctxt, loc, type), m_kind (kind), m_name (name) - {} + { + m_initializer = NULL; + m_initializer_num_bytes = 0; + } + ~global () + { + free (m_initializer); + } void replay_into (replayer *) FINAL OVERRIDE; @@ -1335,8 +1354,23 @@ public: void write_to_dump (dump &d) FINAL OVERRIDE; + bool is_global () const FINAL OVERRIDE { return true; } + + void + set_initializer (const void *initializer, + size_t num_bytes) + { + if (m_initializer) + free (m_initializer); + m_initializer = xmalloc (num_bytes); + memcpy (m_initializer, initializer, num_bytes); + m_initializer_num_bytes = num_bytes; + } + private: string * make_debug_string () FINAL OVERRIDE { return m_name; } + template + void write_initializer_reproducer (const char *id, reproducer &r); void write_reproducer (reproducer &r) FINAL OVERRIDE; enum precedence get_precedence () const FINAL OVERRIDE { @@ -1346,6 +1380,8 @@ private: private: enum gcc_jit_global_kind m_kind; string *m_name; + void *m_initializer; + size_t m_initializer_num_bytes; }; template diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h index 69e67766640..1b9ef1a5db9 100644 --- a/gcc/jit/libgccjit++.h +++ b/gcc/jit/libgccjit++.h @@ -488,6 +488,7 @@ namespace gccjit location loc = location ()); rvalue get_address (location loc = location ()); + lvalue set_initializer (const void *blob, size_t num_bytes); }; class param : public lvalue @@ -1737,6 +1738,15 @@ lvalue::get_address (location loc) loc.get_inner_location ())); } +inline lvalue +lvalue::set_initializer (const void *blob, size_t num_bytes) +{ + gcc_jit_global_set_initializer (get_inner_lvalue (), + blob, + num_bytes); + return *this; +} + // class param : public lvalue inline param::param () : lvalue () {} inline param::param (gcc_jit_param *inner) diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 3d04f6db3af..bc45bd80b2c 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -1117,6 +1117,44 @@ gcc_jit_context_new_global (gcc_jit_context *ctxt, return (gcc_jit_lvalue *)ctxt->new_global (loc, kind, type, name); } +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::global::set_initializer method, in + jit-recording.c. */ + +extern gcc_jit_lvalue * +gcc_jit_global_set_initializer (gcc_jit_lvalue *global, + const void *blob, + size_t num_bytes) +{ + RETURN_NULL_IF_FAIL (global, NULL, NULL, "NULL global"); + RETURN_NULL_IF_FAIL (blob, NULL, NULL, "NULL blob"); + RETURN_NULL_IF_FAIL_PRINTF1 (global->is_global (), NULL, NULL, + "lvalue \"%s\" not a global", + global->get_debug_string ()); + + gcc::jit::recording::type *lval_type = global->get_type (); + RETURN_NULL_IF_FAIL_PRINTF1 (lval_type->is_array (), NULL, NULL, + "global \"%s\" is not an array", + global->get_debug_string ()); + RETURN_NULL_IF_FAIL_PRINTF1 (lval_type->dereference ()->is_int (), NULL, NULL, + "global \"%s\" is not an array of integral type", + global->get_debug_string ()); + size_t lvalue_size = + lval_type->dereference ()->get_size () + * static_cast (lval_type)->num_elements (); + RETURN_NULL_IF_FAIL_PRINTF3 ( + lvalue_size == num_bytes, NULL, NULL, + "global \"%s\" of size %zu don't match initializer of size %zu", + global->get_debug_string (), lvalue_size, num_bytes); + + reinterpret_cast (global) + ->set_initializer (blob, num_bytes); + + return global; +} + /* Public entrypoint. See description in libgccjit.h. After error-checking, this calls the trivial diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 1c5a12e9c01..3cbcbef2693 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -788,6 +788,20 @@ gcc_jit_context_new_global (gcc_jit_context *ctxt, gcc_jit_type *type, const char *name); +#define LIBGCCJIT_HAVE_gcc_jit_global_set_initializer + +/* Set a static initializer for a global return the global itself. + + This API entrypoint was added in LIBGCCJIT_ABI_14; you can test for its + presence using + #ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer +*/ + +extern gcc_jit_lvalue * +gcc_jit_global_set_initializer (gcc_jit_lvalue *global, + const void *blob, + size_t num_bytes); + /* Upcasting. */ extern gcc_jit_object * gcc_jit_lvalue_as_object (gcc_jit_lvalue *lvalue); diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 6137dd4b4b0..a6e67e781a4 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -186,4 +186,9 @@ LIBGCCJIT_ABI_13 { gcc_jit_version_major; gcc_jit_version_minor; gcc_jit_version_patchlevel; -} LIBGCCJIT_ABI_12; \ No newline at end of file +} LIBGCCJIT_ABI_12; + +LIBGCCJIT_ABI_14 { + global: + gcc_jit_global_set_initializer; +} LIBGCCJIT_ABI_13; diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index 632ab8cfb2e..4202eb7798b 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -174,6 +174,13 @@ #undef create_code #undef verify_code +/* test-global-set-initializer.c */ +#define create_code create_code_global_set_initializer +#define verify_code verify_code_global_set_initializer +#include "test-global-set-initializer.c" +#undef create_code +#undef verify_code + /* test-hello-world.c */ #define create_code create_code_hello_world #define verify_code verify_code_hello_world diff --git a/gcc/testsuite/jit.dg/test-global-set-initializer.c b/gcc/testsuite/jit.dg/test-global-set-initializer.c new file mode 100644 index 00000000000..d38aba7d73f --- /dev/null +++ b/gcc/testsuite/jit.dg/test-global-set-initializer.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +#include "libgccjit.h" + +#include "harness.h" + +#define BIG_BLOB_SIZE (1 << 12) /* 4KB. */ + +static signed char test_blob1[] = { 0xc, 0xa, 0xf, 0xf, 0xe }; +static unsigned test_blob2[] = { 0x3, 0x2, 0x1, 0x0, 0x1, 0x2, 0x3 }; +static unsigned char test_blob3[BIG_BLOB_SIZE]; + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + + signed char bin_blob1[] = { 0xc, 0xa, 0xf, 0xf, 0xe }; + unsigned bin_blob2[] = { 0x3, 0x2, 0x1, 0x0, 0x1, 0x2, 0x3 }; + unsigned char bin_blob3[4096]... + */ + gcc_jit_type *unsigned_char_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_CHAR); + gcc_jit_type *signed_char_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_SIGNED_CHAR); + gcc_jit_type *unsigned_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_INT); + + gcc_jit_lvalue *glob = + gcc_jit_context_new_global ( + ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED, + gcc_jit_context_new_array_type (ctxt, NULL, signed_char_type, + sizeof (test_blob1)), + "bin_blob1"); + gcc_jit_global_set_initializer (glob, test_blob1, sizeof (test_blob1)); + + glob = + gcc_jit_context_new_global ( + ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED, + gcc_jit_context_new_array_type ( + ctxt, NULL, unsigned_type, + sizeof (test_blob2) / sizeof (*test_blob2)), + "bin_blob2"); + gcc_jit_global_set_initializer (glob, test_blob2, + sizeof (test_blob2)); + + for (size_t i = 0; i < BIG_BLOB_SIZE; i++) + test_blob3[i] = i * i + i; + glob = + gcc_jit_context_new_global ( + ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED, + gcc_jit_context_new_array_type (ctxt, NULL, unsigned_char_type, + sizeof (test_blob3)), + "bin_blob3"); + gcc_jit_global_set_initializer (glob, test_blob3, sizeof (test_blob3)); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + CHECK_NON_NULL (result); + void *glob = gcc_jit_result_get_global (result, "bin_blob1"); + CHECK_NON_NULL (glob); + CHECK_VALUE (memcmp (test_blob1, glob, sizeof (test_blob1)), 0); + + glob = gcc_jit_result_get_global (result, "bin_blob2"); + CHECK_NON_NULL (glob); + CHECK_VALUE (memcmp (test_blob2, glob, + sizeof (test_blob2)), 0); + + glob = gcc_jit_result_get_global (result, "bin_blob3"); + CHECK_NON_NULL (glob); + CHECK_VALUE (memcmp (test_blob3, glob, sizeof (test_blob3)), 0); + +} -- 2.20.1 --=-=-=--