@@ -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,
NUM_INNER_BOOL_OPTIONS
};
@@ -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"
#include <pthread.h>
@@ -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));
default:
gcc_assert (gcc::jit::active_playback_ctxt);
@@ -679,6 +682,24 @@ new_global_initialized (location *loc,
namespace playback
{
+/* 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) ==
+ TYPE_CANONICAL (complex_float_type_node))
+ return float_type_node;
+ else if (TYPE_CANONICAL (complex_type) ==
+ TYPE_CANONICAL (complex_double_type_node))
+ return double_type_node;
+ else if (TYPE_CANONICAL (complex_type) ==
+ 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 <int>. */
template <>
@@ -694,6 +715,25 @@ new_rvalue_from_const <int> (type *type,
tree inner = 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 = complex_real_to_real (inner_type);
+
+ real_from_integer (&real_value, VOIDmode, value, SIGNED);
+ real_from_integer (&imag_value, VOIDmode, 0, SIGNED);
+
+ tree_real = build_real (real_type, real_value);
+ tree_imag = build_real (real_type, imag_value);
+
+ tree inner = 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 <long> (type *type,
tree inner = 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 = complex_real_to_real (inner_type);
+
+ real_from_integer (&real_value, VOIDmode, value, SIGNED);
+ real_from_integer (&imag_value, VOIDmode, 0, SIGNED);
+
+ tree_real = build_real (real_type, real_value);
+ tree_imag = build_real (real_type, imag_value);
+
+ tree inner = 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 <double> (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 = value;
+ long int as_long_ints[2];
+ as_long_ints[0] = u_real.as_uint32s[0];
+ as_long_ints[1] = 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 = 0.;
+ zero_as_long_ints[0] = u_imag.as_uint32s[0];
+ zero_as_long_ints[1] = u_imag.as_uint32s[1];
+
+ real_from_target (&imag_value, zero_as_long_ints, DFmode);
+
+ real_type = complex_real_to_real (inner_type);
+
+ tree_real = build_real (real_type, real_value);
+ tree_imag = build_real (real_type, imag_value);
+
+ tree inner = build_complex (inner_type, tree_real, tree_imag);
+ return new rvalue (this, inner);
+ }
+ else
+ {
+ tree inner = build_real (inner_type, real_value);
+ return new rvalue (this, inner);
+ }
+}
+
+/* Specialization of making an rvalue from a const,
+ for host <double _Complex>. */
+
+template <>
+rvalue *
+context::
+new_rvalue_from_const <_Complex double> (type *type,
+ _Complex double value)
+{
+ tree inner_type = type->as_tree ();
+
union
{
double as_double;
uint32_t as_uint32s[2];
- } u;
- u.as_double = value;
+ } u_real, u_imag;
+
+ u_real.as_double = creal(value);
long int as_long_ints[2];
- as_long_ints[0] = u.as_uint32s[0];
- as_long_ints[1] = u.as_uint32s[1];
+ as_long_ints[0] = u_real.as_uint32s[0];
+ as_long_ints[1] = u_real.as_uint32s[1];
+
+ REAL_VALUE_TYPE real_value;
real_from_target (&real_value, as_long_ints, DFmode);
- tree inner = 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 = cimag(value);
+ value_as_long_ints[0] = u_imag.as_uint32s[0];
+ value_as_long_ints[1] = u_imag.as_uint32s[1];
+
+ real_from_target (&imag_value, value_as_long_ints, DFmode);
+
+ real_type = complex_real_to_real (inner_type);
+
+ tree_real = build_real (real_type, real_value);
+ tree_imag = build_real (real_type, imag_value);
+
+ tree inner = build_complex (inner_type, tree_real, tree_imag);
+ return new rvalue (this, inner);
+ }
+ else
+ {
+ tree inner = build_real (inner_type, real_value);
+ return new rvalue (this, inner);
+ }
}
/* Specialization of making an rvalue from a const, for host <void *>. */
@@ -985,6 +1129,11 @@ new_binary_op (location *loc,
case GCC_JIT_BINARY_OP_RSHIFT:
inner_op = RSHIFT_EXPR;
break;
+
+ /* Create complex value from two real values */
+ case GCC_JIT_BINARY_OP_COMPLEX:
+ inner_op = COMPLEX_EXPR;
+ break;
}
tree inner_expr = build2 (inner_op,
@@ -1163,6 +1312,10 @@ playback::context::build_cast (playback::location *loc,
build_int_cst (TREE_TYPE (t_expr), 0));
goto maybe_fold;
+ case COMPLEX_TYPE:
+ t_ret = convert_to_complex (t_dst_type, t_expr);
+ goto maybe_fold;
+
case REAL_TYPE:
t_ret = convert_to_real (t_dst_type, t_expr);
goto maybe_fold;
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "toplev.h"
#include <pthread.h>
+#include <complex.h>
#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] = {
"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"
};
/* 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
}
}
+/* 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. */
@@ -4704,6 +4759,7 @@ recording::global::write_reproducer (reproducer &r)
template class recording::memento_of_new_rvalue_from_const <int>;
template class recording::memento_of_new_rvalue_from_const <long>;
template class recording::memento_of_new_rvalue_from_const <double>;
+template class recording::memento_of_new_rvalue_from_const <_Complex double>;
template class recording::memento_of_new_rvalue_from_const <void *>;
/* Implementation of the pure virtual hook recording::memento::replay_into
@@ -4881,6 +4937,51 @@ recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproduc
m_value);
}
+/* The make_debug_string specialization for <double complex>, 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 = creal(m_value);
+ double imag = 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 <double complex>. */
+
+template <>
+bool
+memento_of_new_rvalue_from_const <_Complex double>::get_wide_int (wide_int *) const
+{
+ return false;
+}
+
+/* The write_reproducer specialization for <double>. */
+
+template <>
+void
+recording::memento_of_new_rvalue_from_const <_Complex double>::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "rvalue");
+ double real = creal(m_value);
+ double imag = cimag(m_value);
+ r.write (" gcc_jit_rvalue *%s =\n"
+ " gcc_jit_context_new_rvalue_from_complex_double (%s, /* gcc_jit_context *ctxt */\n"
+ " %s, /* gcc_jit_type *numeric_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 <void *>, rendering it as
(TARGET_TYPE)HEX
e.g.
@@ -5178,13 +5279,20 @@ static const char * const binary_op_strings[] = {
"||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
"<<", /* GCC_JIT_BINARY_OP_LSHIFT */
">>", /* GCC_JIT_BINARY_OP_RSHIFT */
+ "", /* GCC_JIT_BINARY_OP_COMPLEX - dummy not used */
};
recording::string *
recording::binary_op::make_debug_string ()
{
enum precedence prec = get_precedence ();
- return string::from_printf (m_ctxt,
+ if (m_op == 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[] = {
"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",
};
/* Implementation of recording::memento::write_reproducer for binary ops. */
@@ -5244,6 +5353,7 @@ static const enum precedence binary_op_precedence[] = {
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 */
@@ -544,10 +544,14 @@ public:
virtual bool is_int () const = 0;
virtual bool is_float () const = 0;
virtual bool is_bool () const = 0;
+ virtual bool is_complex () const = 0;
virtual type *is_pointer () = 0;
virtual type *is_array () = 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; }
bool is_numeric () const
{
@@ -598,9 +602,28 @@ public:
return type::accepts_writes_from (rtype);
}
+ 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 == 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; }
@@ -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_complex (); }
type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
@@ -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; }
@@ -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; }
@@ -128,7 +128,8 @@ namespace gccjit
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);
+
void add_command_line_option (const char *optname);
void add_driver_option (const char *optname);
@@ -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);
}
+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));
}
+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
@@ -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 >= GCC_JIT_TYPE_VOID
- && type <= GCC_JIT_TYPE_FILE_PTR),
+ && type <= GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE),
ctxt, NULL,
"unrecognized value for enum gcc_jit_types: %i", type);
+ if (type >= GCC_JIT_TYPE_COMPLEX_FLOAT
+ && type <= 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()");
return (gcc_jit_type *)ctxt->get_type (type);
}
@@ -1320,6 +1328,26 @@ gcc_jit_context_new_rvalue_from_double (gcc_jit_context *ctxt,
->new_rvalue_from_const <double> (numeric_type, value));
}
+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 <double _Complex> (numeric_type, value));
+}
+
+
/* Public entrypoint. See description in libgccjit.h.
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");
+ if (rvalue->get_type ()->is_complex ())
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ op == 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, rvalue);
}
@@ -1426,7 +1462,7 @@ static bool
valid_binary_op_p (enum gcc_jit_binary_op op)
{
return (op >= GCC_JIT_BINARY_OP_PLUS
- && op <= GCC_JIT_BINARY_OP_RSHIFT);
+ && op <= GCC_JIT_BINARY_OP_COMPLEX);
}
/* 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 ());
+ if (op == 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 () ==
+ 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);
}
@@ -1506,6 +1574,14 @@ gcc_jit_context_new_comparison (gcc_jit_context *ctxt,
b->get_debug_string (),
b->get_type ()->get_debug_string ());
+ if (a->get_type ()->is_complex())
+ RETURN_NULL_IF_FAIL_PRINTF1 (
+ (op == GCC_JIT_COMPARISON_EQ
+ || op == 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);
}
@@ -2735,6 +2811,23 @@ gcc_jit_context_set_bool_allow_unreachable_blocks (gcc_jit_context *ctxt,
bool_value);
}
+/* 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.
After error-checking, the real work is done by the
@@ -848,6 +848,17 @@ gcc_jit_context_new_rvalue_from_double (gcc_jit_context *ctxt,
gcc_jit_type *numeric_type,
double value);
+/* 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
};
extern gcc_jit_rvalue *
@@ -1434,6 +1464,19 @@ gcc_jit_timer_print (gcc_jit_timer *timer,
FILE *f_out);
+#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
/* Mark/clear a call as needing tail-call optimization.
@@ -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