From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-4.sys.kth.se (smtp-4.sys.kth.se [IPv6:2001:6b0:1:1300:250:56ff:fea6:2de3]) by sourceware.org (Postfix) with ESMTPS id 905093857802; Tue, 14 Sep 2021 23:37:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 905093857802 Received: from smtp-4.sys.kth.se (localhost.localdomain [127.0.0.1]) by smtp-4.sys.kth.se (Postfix) with ESMTP id A957B63E; Wed, 15 Sep 2021 01:37:51 +0200 (CEST) X-Virus-Scanned: by amavisd-new at kth.se Received: from smtp-4.sys.kth.se ([127.0.0.1]) by smtp-4.sys.kth.se (smtp-4.sys.kth.se [127.0.0.1]) (amavisd-new, port 10024) with LMTP id L0uCYeCfhMKw; Wed, 15 Sep 2021 01:37:50 +0200 (CEST) Received: from exdb6.ug.kth.se (exdb6.ug.kth.se [192.168.32.61]) by smtp-4.sys.kth.se (Postfix) with ESMTPS id 517EF1F6A; Wed, 15 Sep 2021 01:37:49 +0200 (CEST) Received: from exdb6.ug.kth.se (192.168.32.61) by exdb6.ug.kth.se (192.168.32.61) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.858.15; Wed, 15 Sep 2021 01:37:49 +0200 Received: from exdb6.ug.kth.se ([192.168.32.61]) by exdb6.ug.kth.se ([192.168.32.61]) with mapi id 15.02.0858.015; Wed, 15 Sep 2021 01:37:49 +0200 From: Petter Tomner To: "gcc-patches@gcc.gnu.org" , "jit@gcc.gnu.org" Subject: [PATCH 1/2] jit: Add support for complex types Thread-Topic: [PATCH 1/2] jit: Add support for complex types Thread-Index: AQHXqcGHlGT6XCcQrEe4hOinJbeuvg== Date: Tue, 14 Sep 2021 23:37:49 +0000 Message-ID: References: <38cabc705eaf4fe6b26e312b4c5a2cd9@kth.se> In-Reply-To: <38cabc705eaf4fe6b26e312b4c5a2cd9@kth.se> Accept-Language: sv-SE, en-US Content-Language: sv-SE X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [192.168.32.250] Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: Tue, 14 Sep 2021 23:37:55 -0000 >From ff47bbec5a833b4470cae7cb636a5fbf31c6432e Mon Sep 17 00:00:00 2001 From: Petter Tomner Date: Tue, 14 Sep 2021 23:51:41 +0200 Subject: [PATCH 1/2] jit: Support for complex types The patch adds support of complex floating point types to libgccjit. A new binary operator 'COMPLEX' is added to create complex values from real values. Aswell as a function to create a complex double literal. To notify users if a binary linking to libgccjit depends on complex types, complex type support most be enabled with a new option function. Signed-off-by: 2021-09-15 Petter Tomner gcc/jit/ * jit-common.h (INNER_BOOL_OPTION_ENABLE_COMPLEX_TYPES): new * jit-playback.c Create imaginary literals, conversions * jit-recording.c Reproducer, debug strings, forwarding * jit-recording.h (float_size_qual): Poll size qualifier of float types (is_complex): Poll if type is complex * libgccjit++.h New entrypoints, see below * libgccjit.c Implementation of new entry points (gcc_jit_context_get_type): Extend range check, validation (valid_binary_op_p): Extend range check (gcc_jit_context_new_binary_op): Validation (gcc_jit_context_new_unary_op): Validation (gcc_jit_context_new_comparison): Validation * libgccjit.h (gcc_jit_context_new_rvalue_from_complex_double): New (GCC_JIT_BINARY_OP_COMPLEX): New (LIBGCCJIT_HAVE_COMPLEX): New (gcc_jit_context_set_bool_enable_complex_types): New * libgccjit.map Added new entrypoints (LIBGCCJIT_ABI_16): New --- gcc/jit/jit-common.h | 1 + gcc/jit/jit-playback.c | 165 ++++++++++++++++++++++++++++++++++++++-- gcc/jit/jit-recording.c | 116 +++++++++++++++++++++++++++- gcc/jit/jit-recording.h | 28 +++++++ gcc/jit/libgccjit++.h | 23 +++++- gcc/jit/libgccjit.c | 97 ++++++++++++++++++++++- gcc/jit/libgccjit.h | 45 ++++++++++- gcc/jit/libgccjit.map | 6 ++ 8 files changed, 468 insertions(+), 13 deletions(-) diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h index f88e6755b00..bc0453fba05 100644 --- a/gcc/jit/jit-common.h +++ b/gcc/jit/jit-common.h @@ -198,6 +198,7 @@ enum inner_bool_option { INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS, INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER, + INNER_BOOL_OPTION_ENABLE_COMPLEX_TYPES, =20 NUM_INNER_BOOL_OPTIONS }; diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c index 59399dee251..8e4971958c3 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see #include "gcc.h" #include "diagnostic.h" #include "stmt.h" +#include "complex.h" =20 #include =20 @@ -78,6 +79,8 @@ convert (tree dst_type, tree expr) case INTEGER_TYPE: case ENUMERAL_TYPE: return fold (convert_to_integer (dst_type, expr)); + case REAL_TYPE: + return fold (convert_to_real (dst_type, expr)); =20 default: gcc_assert (gcc::jit::active_playback_ctxt); @@ -679,6 +682,24 @@ new_global_initialized (location *loc, namespace playback { =20 +/* Return the corrensponding not complex float type of a + float type. I.e. complex float -> float */ +static tree +complex_real_to_real (tree complex_type) +{ + if (TYPE_CANONICAL (complex_type) =3D=3D + TYPE_CANONICAL (complex_float_type_node)) + return float_type_node; + else if (TYPE_CANONICAL (complex_type) =3D=3D + TYPE_CANONICAL (complex_double_type_node)) + return double_type_node; + else if (TYPE_CANONICAL (complex_type) =3D=3D + TYPE_CANONICAL (complex_long_double_type_node)) + return long_double_type_node; + else + gcc_unreachable(); +} + /* Specialization of making an rvalue from a const, for host . */ =20 template <> @@ -694,6 +715,25 @@ new_rvalue_from_const (type *type, tree inner =3D build_int_cst (inner_type, value); return new rvalue (this, inner); } + else if (COMPLEX_FLOAT_TYPE_P (inner_type)) + { + tree tree_real; + tree tree_imag; + tree real_type; + REAL_VALUE_TYPE real_value; + REAL_VALUE_TYPE imag_value; + + real_type =3D complex_real_to_real (inner_type); + + real_from_integer (&real_value, VOIDmode, value, SIGNED); + real_from_integer (&imag_value, VOIDmode, 0, SIGNED); + + tree_real =3D build_real (real_type, real_value); + tree_imag =3D build_real (real_type, imag_value); + + tree inner =3D build_complex (inner_type, tree_real, tree_imag); + return new rvalue (this, inner); + } else { REAL_VALUE_TYPE real_value; @@ -718,6 +758,25 @@ new_rvalue_from_const (type *type, tree inner =3D build_int_cst (inner_type, value); return new rvalue (this, inner); } + else if (COMPLEX_FLOAT_TYPE_P (inner_type)) + { + tree tree_real; + tree tree_imag; + tree real_type; + REAL_VALUE_TYPE real_value; + REAL_VALUE_TYPE imag_value; + + real_type =3D complex_real_to_real (inner_type); + + real_from_integer (&real_value, VOIDmode, value, SIGNED); + real_from_integer (&imag_value, VOIDmode, 0, SIGNED); + + tree_real =3D build_real (real_type, real_value); + tree_imag =3D build_real (real_type, imag_value); + + tree inner =3D build_complex (inner_type, tree_real, tree_imag); + return new rvalue (this, inner); + } else { REAL_VALUE_TYPE real_value; @@ -743,19 +802,104 @@ new_rvalue_from_const (type *type, real.c:real_from_target appears to require the representation to be split into 32-bit values, and then sent as an pair of host long ints. */ + + union + { + double as_double; + uint32_t as_uint32s[2]; + } u_real, u_imag; + + u_real.as_double =3D value; + long int as_long_ints[2]; + as_long_ints[0] =3D u_real.as_uint32s[0]; + as_long_ints[1] =3D u_real.as_uint32s[1]; + REAL_VALUE_TYPE real_value; + real_from_target (&real_value, as_long_ints, DFmode); + + if (COMPLEX_FLOAT_TYPE_P (inner_type)) + { + tree tree_real; + tree tree_imag; + tree real_type; + + REAL_VALUE_TYPE imag_value; + + long int zero_as_long_ints[2]; + u_imag.as_double =3D 0.; + zero_as_long_ints[0] =3D u_imag.as_uint32s[0]; + zero_as_long_ints[1] =3D u_imag.as_uint32s[1]; + + real_from_target (&imag_value, zero_as_long_ints, DFmode); + + real_type =3D complex_real_to_real (inner_type); + + tree_real =3D build_real (real_type, real_value); + tree_imag =3D build_real (real_type, imag_value); + + tree inner =3D build_complex (inner_type, tree_real, tree_imag); + return new rvalue (this, inner); + } + else + { + tree inner =3D build_real (inner_type, real_value); + return new rvalue (this, inner); + } +} + +/* Specialization of making an rvalue from a const, + for host . */ + +template <> +rvalue * +context:: +new_rvalue_from_const <_Complex double> (type *type, + _Complex double value) +{ + tree inner_type =3D type->as_tree (); + union { double as_double; uint32_t as_uint32s[2]; - } u; - u.as_double =3D value; + } u_real, u_imag; + + u_real.as_double =3D creal(value); long int as_long_ints[2]; - as_long_ints[0] =3D u.as_uint32s[0]; - as_long_ints[1] =3D u.as_uint32s[1]; + as_long_ints[0] =3D u_real.as_uint32s[0]; + as_long_ints[1] =3D u_real.as_uint32s[1]; + + REAL_VALUE_TYPE real_value; real_from_target (&real_value, as_long_ints, DFmode); - tree inner =3D build_real (inner_type, real_value); - return new rvalue (this, inner); + + if (COMPLEX_FLOAT_TYPE_P (inner_type)) + { + tree tree_real; + tree tree_imag; + tree real_type; + + REAL_VALUE_TYPE imag_value; + + long int value_as_long_ints[2]; + u_imag.as_double =3D cimag(value); + value_as_long_ints[0] =3D u_imag.as_uint32s[0]; + value_as_long_ints[1] =3D u_imag.as_uint32s[1]; + + real_from_target (&imag_value, value_as_long_ints, DFmode); + + real_type =3D complex_real_to_real (inner_type); + + tree_real =3D build_real (real_type, real_value); + tree_imag =3D build_real (real_type, imag_value); + + tree inner =3D build_complex (inner_type, tree_real, tree_imag); + return new rvalue (this, inner); + } + else + { + tree inner =3D build_real (inner_type, real_value); + return new rvalue (this, inner); + } } =20 /* Specialization of making an rvalue from a const, for host . */ @@ -985,6 +1129,11 @@ new_binary_op (location *loc, case GCC_JIT_BINARY_OP_RSHIFT: inner_op =3D RSHIFT_EXPR; break; + + /* Create complex value from two real values */ + case GCC_JIT_BINARY_OP_COMPLEX: + inner_op =3D COMPLEX_EXPR; + break; } =20 tree inner_expr =3D build2 (inner_op, @@ -1163,6 +1312,10 @@ playback::context::build_cast (playback::location *l= oc, build_int_cst (TREE_TYPE (t_expr), 0)); goto maybe_fold; =20 + case COMPLEX_TYPE: + t_ret =3D convert_to_complex (t_dst_type, t_expr); + goto maybe_fold; + case REAL_TYPE: t_ret =3D convert_to_real (t_dst_type, t_expr); goto maybe_fold; diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 117ff70114c..565d078d517 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see #include "toplev.h" =20 #include +#include =20 #include "jit-builtins.h" #include "jit-recording.h" @@ -1609,7 +1610,8 @@ static const char * const static const char * const inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] =3D { "gcc_jit_context_set_bool_allow_unreachable_blocks", - "gcc_jit_context_set_bool_use_external_driver" + "gcc_jit_context_set_bool_use_external_driver", + "gcc_jit_context_set_bool_enable_complex_types" }; =20 /* Write the current value of all options to the log file (if any). */ @@ -2423,6 +2425,59 @@ recording::memento_of_get_type::is_float () const } } =20 +/* Implementation of pure virtual hook recording::type::is_complex for + recording::memento_of_get_type. */ + +bool +recording::memento_of_get_type::is_complex () const +{ + switch (m_kind) + { + default: gcc_unreachable (); + + case GCC_JIT_TYPE_VOID: + return false; + + case GCC_JIT_TYPE_VOID_PTR: + return false; + + case GCC_JIT_TYPE_BOOL: + return false; + + case GCC_JIT_TYPE_CHAR: + case GCC_JIT_TYPE_SIGNED_CHAR: + case GCC_JIT_TYPE_UNSIGNED_CHAR: + case GCC_JIT_TYPE_SHORT: + case GCC_JIT_TYPE_UNSIGNED_SHORT: + case GCC_JIT_TYPE_INT: + case GCC_JIT_TYPE_UNSIGNED_INT: + case GCC_JIT_TYPE_LONG: + case GCC_JIT_TYPE_UNSIGNED_LONG: + case GCC_JIT_TYPE_LONG_LONG: + case GCC_JIT_TYPE_UNSIGNED_LONG_LONG: + return false; + + case GCC_JIT_TYPE_FLOAT: + case GCC_JIT_TYPE_DOUBLE: + case GCC_JIT_TYPE_LONG_DOUBLE: + return false; + + case GCC_JIT_TYPE_CONST_CHAR_PTR: + return false; + + case GCC_JIT_TYPE_SIZE_T: + return false; + + case GCC_JIT_TYPE_FILE_PTR: + return false; + + case GCC_JIT_TYPE_COMPLEX_FLOAT: + case GCC_JIT_TYPE_COMPLEX_DOUBLE: + case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE: + return true; + } +} + /* Implementation of pure virtual hook recording::type::is_bool for recording::memento_of_get_type. */ =20 @@ -4704,6 +4759,7 @@ recording::global::write_reproducer (reproducer &r) template class recording::memento_of_new_rvalue_from_const ; template class recording::memento_of_new_rvalue_from_const ; template class recording::memento_of_new_rvalue_from_const ; +template class recording::memento_of_new_rvalue_from_const <_Complex doubl= e>; template class recording::memento_of_new_rvalue_from_const ; =20 /* Implementation of the pure virtual hook recording::memento::replay_into @@ -4881,6 +4937,51 @@ recording::memento_of_new_rvalue_from_const = ::write_reproducer (reproduc m_value); } =20 +/* The make_debug_string specialization for , rendering it= as + (TARGET_TYPE)LITERAL + e.g. + "(complex float)(42.0+42.0j)". */ + +template <> +string * +memento_of_new_rvalue_from_const <_Complex double>::make_debug_string () +{ + double real =3D creal(m_value); + double imag =3D cimag(m_value); + return string::from_printf (m_ctxt, + "(%s)(%g%+gj)", + m_type->get_debug_string (), + real, imag); +} + +/* The get_wide_int specialization for . */ + +template <> +bool +memento_of_new_rvalue_from_const <_Complex double>::get_wide_int (wide_int= *) const +{ + return false; +} + +/* The write_reproducer specialization for . */ + +template <> +void +recording::memento_of_new_rvalue_from_const <_Complex double>::write_repro= ducer (reproducer &r) +{ + const char *id =3D r.make_identifier (this, "rvalue"); + double real =3D creal(m_value); + double imag =3D cimag(m_value); + r.write (" gcc_jit_rvalue *%s =3D\n" + " gcc_jit_context_new_rvalue_from_complex_double (%s, /* gcc_jit_co= ntext *ctxt */\n" + " %s, /* gcc_jit_type *nume= ric_type */\n" + " %f+%fj); /* double value = */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier_as_type (m_type), + real, imag); +} + /* The make_debug_string specialization for , rendering it as (TARGET_TYPE)HEX e.g. @@ -5178,13 +5279,20 @@ static const char * const binary_op_strings[] =3D { "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */ "<<", /* GCC_JIT_BINARY_OP_LSHIFT */ ">>", /* GCC_JIT_BINARY_OP_RSHIFT */ + "", /* GCC_JIT_BINARY_OP_COMPLEX - dummy not used */ }; =20 recording::string * recording::binary_op::make_debug_string () { enum precedence prec =3D get_precedence (); - return string::from_printf (m_ctxt, + if (m_op =3D=3D GCC_JIT_BINARY_OP_COMPLEX) + return string::from_printf (m_ctxt, + "(%s + %s * _Imaginary_I)", + m_a->get_debug_string_parens (prec), + m_b->get_debug_string_parens (prec)); + else + return string::from_printf (m_ctxt, "%s %s %s", m_a->get_debug_string_parens (prec), binary_op_strings[m_op], @@ -5203,7 +5311,8 @@ const char * const binary_op_reproducer_strings[] =3D= { "GCC_JIT_BINARY_OP_LOGICAL_AND", "GCC_JIT_BINARY_OP_LOGICAL_OR", "GCC_JIT_BINARY_OP_LSHIFT", - "GCC_JIT_BINARY_OP_RSHIFT" + "GCC_JIT_BINARY_OP_RSHIFT", + "GCC_JIT_BINARY_OP_COMPLEX", }; =20 /* Implementation of recording::memento::write_reproducer for binary ops. = */ @@ -5244,6 +5353,7 @@ static const enum precedence binary_op_precedence[] = =3D { PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */ PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */ PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */ + PRECEDENCE_CAST, /* GCC_JIT_BINARY_OP_COMPLEX */ }; } /* namespace recording */ =20 diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 03fa1160cf0..d5e0c359a48 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -544,10 +544,14 @@ public: virtual bool is_int () const =3D 0; virtual bool is_float () const =3D 0; virtual bool is_bool () const =3D 0; + virtual bool is_complex () const =3D 0; virtual type *is_pointer () =3D 0; virtual type *is_array () =3D 0; virtual bool is_void () const { return false; } virtual bool has_known_size () const { return true; } + /* Used to pair complex float types with real float type + of the same "base type". */ + virtual int float_size_qual () const { return 0; } =20 bool is_numeric () const { @@ -598,9 +602,28 @@ public: return type::accepts_writes_from (rtype); } =20 + int float_size_qual () const FINAL OVERRIDE + { + switch (m_kind) + { + default: + return 0; + case GCC_JIT_TYPE_FLOAT: + case GCC_JIT_TYPE_COMPLEX_FLOAT: + return 1; + case GCC_JIT_TYPE_DOUBLE: + case GCC_JIT_TYPE_COMPLEX_DOUBLE: + return 2; + case GCC_JIT_TYPE_LONG_DOUBLE: + case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE: + return 3; + } + } + bool is_int () const FINAL OVERRIDE; bool is_float () const FINAL OVERRIDE; bool is_bool () const FINAL OVERRIDE; + bool is_complex () const FINAL OVERRIDE; type *is_pointer () FINAL OVERRIDE { return dereference (); } type *is_array () FINAL OVERRIDE { return NULL; } bool is_void () const FINAL OVERRIDE { return m_kind =3D=3D GCC_JIT_TYPE= _VOID; } @@ -635,6 +658,7 @@ public: bool is_int () const FINAL OVERRIDE { return false; } bool is_float () const FINAL OVERRIDE { return false; } bool is_bool () const FINAL OVERRIDE { return false; } + bool is_complex () const FINAL OVERRIDE { return false; } type *is_pointer () FINAL OVERRIDE { return m_other_type; } type *is_array () FINAL OVERRIDE { return NULL; } =20 @@ -661,6 +685,7 @@ public: bool is_int () const FINAL OVERRIDE { return m_other_type->is_int (); } bool is_float () const FINAL OVERRIDE { return m_other_type->is_float ()= ; } bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); = } + bool is_complex () const FINAL OVERRIDE { return m_other_type->is_comple= x (); } type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer ();= } type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); } =20 @@ -771,6 +796,7 @@ class array_type : public type bool is_int () const FINAL OVERRIDE { return false; } bool is_float () const FINAL OVERRIDE { return false; } bool is_bool () const FINAL OVERRIDE { return false; } + bool is_complex () 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; } @@ -805,6 +831,7 @@ public: bool is_int () const FINAL OVERRIDE { return false; } bool is_float () const FINAL OVERRIDE { return false; } bool is_bool () const FINAL OVERRIDE { return false; } + bool is_complex () const FINAL OVERRIDE { return false; } type *is_pointer () FINAL OVERRIDE { return NULL; } type *is_array () FINAL OVERRIDE { return NULL; } =20 @@ -918,6 +945,7 @@ public: bool is_int () const FINAL OVERRIDE { return false; } bool is_float () const FINAL OVERRIDE { return false; } bool is_bool () const FINAL OVERRIDE { return false; } + bool is_complex () const FINAL OVERRIDE { return false; } type *is_pointer () FINAL OVERRIDE { return NULL; } type *is_array () FINAL OVERRIDE { return NULL; } =20 diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h index 82831ff5da0..6be5a9b9cc3 100644 --- a/gcc/jit/libgccjit++.h +++ b/gcc/jit/libgccjit++.h @@ -128,7 +128,8 @@ namespace gccjit =20 void set_bool_allow_unreachable_blocks (int bool_value); void set_bool_use_external_driver (int bool_value); - + void set_bool_enable_complex_types (int bool_value); + =20 void add_command_line_option (const char *optname); void add_driver_option (const char *optname); =20 @@ -191,6 +192,8 @@ namespace gccjit rvalue one (type numeric_type) const; rvalue new_rvalue (type numeric_type, double value) const; + rvalue new_rvalue (type numeric_type, + _Complex double value) const; rvalue new_rvalue (type pointer_type, void *value) const; rvalue new_rvalue (const std::string &value) const; @@ -732,6 +735,13 @@ context::set_bool_use_external_driver (int bool_value) bool_value); } =20 +inline void +context::set_bool_enable_complex_types (int bool_value) +{ + gcc_jit_context_set_bool_enable_complex_types (m_inner_ctxt, + bool_value); +} + inline void context::add_command_line_option (const char *optname) { @@ -950,6 +960,17 @@ context::new_rvalue (type numeric_type, value)); } =20 +inline rvalue +context::new_rvalue (type numeric_type, + _Complex double value) const +{ + return rvalue ( + gcc_jit_context_new_rvalue_from_complex_double ( + m_inner_ctxt, + numeric_type.get_inner_type (), + value)); +} + inline rvalue context::new_rvalue (type pointer_type, void *value) const diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 7fa948007ad..0859b38f609 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -448,9 +448,17 @@ gcc_jit_context_get_type (gcc_jit_context *ctxt, JIT_LOG_FUNC (ctxt->get_logger ()); RETURN_NULL_IF_FAIL_PRINTF1 ( (type >=3D GCC_JIT_TYPE_VOID - && type <=3D GCC_JIT_TYPE_FILE_PTR), + && type <=3D GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE), ctxt, NULL, "unrecognized value for enum gcc_jit_types: %i", type); + if (type >=3D GCC_JIT_TYPE_COMPLEX_FLOAT + && type <=3D GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE) + RETURN_NULL_IF_FAIL ( + ctxt->get_inner_bool_option( + gcc::jit::INNER_BOOL_OPTION_ENABLE_COMPLEX_TYPES), + ctxt, NULL, + "complex type are only available after enabling them with" + " gcc_jit_context_set_bool_enable_complex_types()"); =20 return (gcc_jit_type *)ctxt->get_type (type); } @@ -1320,6 +1328,26 @@ gcc_jit_context_new_rvalue_from_double (gcc_jit_cont= ext *ctxt, ->new_rvalue_from_const (numeric_type, value)); } =20 +gcc_jit_rvalue * +gcc_jit_context_new_rvalue_from_complex_double (gcc_jit_context *ctxt, + gcc_jit_type *numeric_type, + double _Complex value) +{ + RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); + JIT_LOG_FUNC (ctxt->get_logger ()); + RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type); + + RETURN_NULL_IF_FAIL_PRINTF1 ( + numeric_type->is_float (), + ctxt, NULL, + "not a floating point type (type: %s)", + numeric_type->get_debug_string ()); + + return ((gcc_jit_rvalue *)ctxt + ->new_rvalue_from_const (numeric_type, value)); +} + + /* Public entrypoint. See description in libgccjit.h. =20 After error-checking, the real work is done by the @@ -1415,6 +1443,14 @@ gcc_jit_context_new_unary_op (gcc_jit_context *ctxt, result_type->get_debug_string ()); RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); =20 + if (rvalue->get_type ()->is_complex ()) + RETURN_NULL_IF_FAIL_PRINTF2 ( + op =3D=3D GCC_JIT_UNARY_OP_MINUS, + ctxt, loc, + "only unary minus defined for complex types: %s (type: %s)", + rvalue->get_debug_string (), + rvalue->get_type ()->get_debug_string ()); + return (gcc_jit_rvalue *)ctxt->new_unary_op (loc, op, result_type, rvalu= e); } =20 @@ -1426,7 +1462,7 @@ static bool valid_binary_op_p (enum gcc_jit_binary_op op) { return (op >=3D GCC_JIT_BINARY_OP_PLUS - && op <=3D GCC_JIT_BINARY_OP_RSHIFT); + && op <=3D GCC_JIT_BINARY_OP_COMPLEX); } =20 /* Public entrypoint. See description in libgccjit.h. @@ -1470,6 +1506,38 @@ gcc_jit_context_new_binary_op (gcc_jit_context *ctxt= , a->get_debug_string (), b->get_debug_string (), result_type->get_debug_string ()); =20 + if (op =3D=3D GCC_JIT_BINARY_OP_COMPLEX) + { + RETURN_NULL_IF_FAIL ( + result_type->is_complex (), + ctxt, loc, + "return type is not complex"); + RETURN_NULL_IF_FAIL_PRINTF3 ( + !a->get_type ()->is_complex () && + a->get_type ()->is_float (), + ctxt, loc, + "first operand of %s is not real: %s (type: %s)", + gcc::jit::binary_op_reproducer_strings[op], + a->get_debug_string (), + a->get_type ()->get_debug_string ()); + RETURN_NULL_IF_FAIL_PRINTF3 ( + !b->get_type ()->is_complex () && + b->get_type ()->is_float (), + ctxt, loc, + "2nd operand of %s is not real: %s (type: %s)", + gcc::jit::binary_op_reproducer_strings[op], + b->get_debug_string (), + b->get_type ()->get_debug_string ()); + RETURN_NULL_IF_FAIL_PRINTF2 ( + a->get_type ()-> float_size_qual () =3D=3D + result_type->float_size_qual (), + ctxt, loc, + "size qualifiers of complex operand's not the same as the result:" + " operands: %s, result: %s", + a->get_type ()->get_debug_string (), + result_type->get_debug_string ()); + } + return (gcc_jit_rvalue *)ctxt->new_binary_op (loc, op, result_type, a, b= ); } =20 @@ -1506,6 +1574,14 @@ gcc_jit_context_new_comparison (gcc_jit_context *ctx= t, b->get_debug_string (), b->get_type ()->get_debug_string ()); =20 + if (a->get_type ()->is_complex()) + RETURN_NULL_IF_FAIL_PRINTF1 ( + (op =3D=3D GCC_JIT_COMPARISON_EQ + || op =3D=3D GCC_JIT_COMPARISON_NE), + ctxt, loc, + "invalid enum gcc_jit_comparison for complex operands: %i", + op); + return (gcc_jit_rvalue *)ctxt->new_comparison (loc, op, a, b); } =20 @@ -2735,6 +2811,23 @@ gcc_jit_context_set_bool_allow_unreachable_blocks (g= cc_jit_context *ctxt, bool_value); } =20 +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::context::set_inner_bool_option method in + jit-recording.c. */ + +void +gcc_jit_context_set_bool_enable_complex_types (gcc_jit_context *ctxt, + int bool_value) +{ + RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); + JIT_LOG_FUNC (ctxt->get_logger ()); + ctxt->set_inner_bool_option ( + gcc::jit::INNER_BOOL_OPTION_ENABLE_COMPLEX_TYPES, + bool_value); +} + /* Public entrypoint. See description in libgccjit.h. =20 After error-checking, the real work is done by the diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 5c722c2c57f..f3d2c40d8be 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -848,6 +848,17 @@ gcc_jit_context_new_rvalue_from_double (gcc_jit_contex= t *ctxt, gcc_jit_type *numeric_type, double value); =20 +/* Complex floating-point constants. + + This API entrypoint was added in LIBGCCJIT_ABI_16; you can test for its + presence using + #ifdef LIBGCCJIT_HAVE_COMPLEX +*/ +extern gcc_jit_rvalue * +gcc_jit_context_new_rvalue_from_complex_double (gcc_jit_context *ctxt, + gcc_jit_type *numeric_type, + double _Complex value); + /* Pointers. */ extern gcc_jit_rvalue * gcc_jit_context_new_rvalue_from_ptr (gcc_jit_context *ctxt, @@ -959,7 +970,26 @@ enum gcc_jit_binary_op /* Right shift; analogous to: (EXPR_A) >> (EXPR_B) in C. */ - GCC_JIT_BINARY_OP_RSHIFT + GCC_JIT_BINARY_OP_RSHIFT, + + /* Create a complex floating point value from + two real floating point values. The operands + and the result need to have the same size + qualifier. + + Analogous to: + CMPLX (real,imag) + in C. + + The first operand is the real part, the other + the imaginary. Negative zeroes are preserved + and Inf:s do not lead to NaNs. + + This operator was added in LIBGCCJIT_ABI_16; + you can test for its presence using + #ifdef LIBGCCJIT_HAVE_COMPLEX + */ + GCC_JIT_BINARY_OP_COMPLEX }; =20 extern gcc_jit_rvalue * @@ -1434,6 +1464,19 @@ gcc_jit_timer_print (gcc_jit_timer *timer, FILE *f_out); =20 =20 +#define LIBGCCJIT_HAVE_COMPLEX + +/* Enables complex type support in libgccjit. + + This API entrypoint was added in LIBGCCJIT_ABI_16; you can test for its + presence using + #ifdef LIBGCCJIT_HAVE_COMPLEX +*/ + +extern void +gcc_jit_context_set_bool_enable_complex_types (gcc_jit_context *ctxt, + int bool_value); + #define LIBGCCJIT_HAVE_gcc_jit_rvalue_set_bool_require_tail_call =20 /* Mark/clear a call as needing tail-call optimization. diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 337ea6c7fe4..c9b044dc8f5 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -205,3 +205,9 @@ LIBGCCJIT_ABI_15 { gcc_jit_extended_asm_add_clobber; gcc_jit_context_add_top_level_asm; } LIBGCCJIT_ABI_14; + +LIBGCCJIT_ABI_16 { + global: + gcc_jit_context_new_rvalue_from_complex_double; + gcc_jit_context_set_bool_enable_complex_types; +} LIBGCCJIT_ABI_15; \ No newline at end of file --=20 2.30.2