From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18505 invoked by alias); 31 Oct 2014 17:29:33 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 18488 invoked by uid 89); 31 Oct 2014 17:29:32 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL,BAYES_00 autolearn=unavailable version=3.3.2 X-HELO: eggs.gnu.org Received: from eggs.gnu.org (HELO eggs.gnu.org) (208.118.235.92) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Fri, 31 Oct 2014 17:29:27 +0000 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XkFfd-0005rL-Kr for gcc-patches@gcc.gnu.org; Fri, 31 Oct 2014 13:07:34 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45756) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XkFfd-0005qP-AP; Fri, 31 Oct 2014 13:07:29 -0400 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s9VH7RwV028085 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 31 Oct 2014 13:07:28 -0400 Received: from surprise.redhat.com (vpn-236-100.phx2.redhat.com [10.3.236.100]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s9VH7ESK008517; Fri, 31 Oct 2014 13:07:26 -0400 From: David Malcolm To: gcc-patches@gcc.gnu.org, jit@gcc.gnu.org Cc: David Malcolm Subject: [PATCH 17/27] New file: gcc/jit/libgccjit++.h Date: Fri, 31 Oct 2014 17:30:00 -0000 Message-Id: <1414774977-25605-18-git-send-email-dmalcolm@redhat.com> In-Reply-To: <1414774977-25605-1-git-send-email-dmalcolm@redhat.com> References: <1414774977-25605-1-git-send-email-dmalcolm@redhat.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 X-IsSubscribed: yes X-SW-Source: 2014-10/txt/msg03349.txt.bz2 This adds a C++ wrapper API, with syntactic sugar for reducing the verbosity compared to the C API. gcc/jit/ * libgccjit++.h: New. --- gcc/jit/libgccjit++.h | 1574 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1574 insertions(+) create mode 100644 gcc/jit/libgccjit++.h diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h new file mode 100644 index 0000000..67ed5d5 --- /dev/null +++ b/gcc/jit/libgccjit++.h @@ -0,0 +1,1574 @@ +/* A C++ API for libgccjit, purely as inline wrapper functions. + Copyright (C) 2014 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#ifndef LIBGCCJIT_PLUS_PLUS_H +#define LIBGCCJIT_PLUS_PLUS_H + +#include "libgccjit.h" + +#include +#include +#include + +/**************************************************************************** + C++ API + ****************************************************************************/ + +namespace gccjit +{ + class context; + class location; + class field; + class type; + class struct_; + class param; + class function; + class block; + class rvalue; + class lvalue; + + /* Errors within the API become C++ exceptions of this class. */ + class error + { + }; + + class object + { + public: + context get_context () const; + + std::string get_debug_string () const; + + protected: + object (); + object (gcc_jit_object *obj); + + gcc_jit_object *get_inner_object () const; + + private: + gcc_jit_object *m_inner_obj; + }; + + inline std::ostream& operator << (std::ostream& stream, const object &obj); + + /* Some client code will want to supply source code locations, others + won't. To avoid doubling the number of entrypoints, everything + accepting a location also has a default argument. To do this, the + other classes need to see that "location" has a default constructor, + hence we need to declare it first. */ + class location : public object + { + public: + location (); + location (gcc_jit_location *loc); + + gcc_jit_location *get_inner_location () const; + }; + + class context + { + public: + static context acquire (); + context (); + context (gcc_jit_context *ctxt); + + gccjit::context new_child_context (); + + gcc_jit_context *get_inner_context () { return m_inner_ctxt; } + + void release (); + + gcc_jit_result *compile (); + + void dump_to_file (const std::string &path, + bool update_locations); + + void set_int_option (enum gcc_jit_int_option opt, + int value); + + void set_bool_option (enum gcc_jit_bool_option opt, + int value); + + location + new_location (const std::string &filename, + int line, + int column); + + type get_type (enum gcc_jit_types kind); + type get_int_type (size_t num_bytes, int is_signed); + + /* A way to map a specific int type, using the compiler to + get the details automatically e.g.: + gccjit::type type = get_int_type (); */ + template + type get_int_type (); + + type new_array_type (type element_type, int num_elements, + location loc = location ()); + + field new_field (type type_, const std::string &name, + location loc = location ()); + + struct_ new_struct_type (const std::string &name, + std::vector &fields, + location loc = location ()); + + struct_ new_opaque_struct_type (const std::string &name, + location loc = location ()); + + param new_param (type type_, + const std::string &name, + location loc = location ()); + + function new_function (enum gcc_jit_function_kind kind, + type return_type, + const std::string &name, + std::vector ¶ms, + int is_variadic, + location loc = location ()); + + function get_builtin_function (const std::string &name); + + lvalue new_global (type type_, + const std::string &name, + location loc = location ()); + + rvalue new_rvalue (type numeric_type, + int value) const; + rvalue zero (type numeric_type) const; + rvalue one (type numeric_type) const; + rvalue new_rvalue (type numeric_type, + double value) const; + rvalue new_rvalue (type pointer_type, + void *value) const; + rvalue new_rvalue (const std::string &value) const; + + /* Generic unary operations... */ + rvalue new_unary_op (enum gcc_jit_unary_op op, + type result_type, + rvalue a, + location loc = location ()); + + /* ...and shorter ways to spell the various specific kinds of + unary op. */ + rvalue new_minus (type result_type, + rvalue a, + location loc = location ()); + rvalue new_bitwise_negate (type result_type, + rvalue a, + location loc = location ()); + rvalue new_logical_negate (type result_type, + rvalue a, + location loc = location ()); + + /* Generic binary operations... */ + rvalue new_binary_op (enum gcc_jit_binary_op op, + type result_type, + rvalue a, rvalue b, + location loc = location ()); + + /* ...and shorter ways to spell the various specific kinds of + binary op. */ + rvalue new_plus (type result_type, + rvalue a, rvalue b, + location loc = location ()); + rvalue new_minus (type result_type, + rvalue a, rvalue b, + location loc = location ()); + rvalue new_mult (type result_type, + rvalue a, rvalue b, + location loc = location ()); + rvalue new_divide (type result_type, + rvalue a, rvalue b, + location loc = location ()); + rvalue new_modulo (type result_type, + rvalue a, rvalue b, + location loc = location ()); + rvalue new_bitwise_and (type result_type, + rvalue a, rvalue b, + location loc = location ()); + rvalue new_bitwise_xor (type result_type, + rvalue a, rvalue b, + location loc = location ()); + rvalue new_bitwise_or (type result_type, + rvalue a, rvalue b, + location loc = location ()); + rvalue new_logical_and (type result_type, + rvalue a, rvalue b, + location loc = location ()); + rvalue new_logical_or (type result_type, + rvalue a, rvalue b, + location loc = location ()); + + /* Generic comparisons... */ + rvalue new_comparison (enum gcc_jit_comparison op, + rvalue a, rvalue b, + location loc = location ()); + /* ...and shorter ways to spell the various specific kinds of + comparison. */ + rvalue new_eq (rvalue a, rvalue b, + location loc = location ()); + rvalue new_ne (rvalue a, rvalue b, + location loc = location ()); + rvalue new_lt (rvalue a, rvalue b, + location loc = location ()); + rvalue new_le (rvalue a, rvalue b, + location loc = location ()); + rvalue new_gt (rvalue a, rvalue b, + location loc = location ()); + rvalue new_ge (rvalue a, rvalue b, + location loc = location ()); + + /* The most general way of creating a function call. */ + rvalue new_call (function func, + std::vector &args, + location loc = location ()); + + /* In addition, we provide a series of overloaded "new_call" methods + for specific numbers of args (from 0 - 6), to avoid the need for + client code to manually build a vector. */ + rvalue new_call (function func, + location loc = location ()); + rvalue new_call (function func, + rvalue arg0, + location loc = location ()); + rvalue new_call (function func, + rvalue arg0, rvalue arg1, + location loc = location ()); + rvalue new_call (function func, + rvalue arg0, rvalue arg1, rvalue arg2, + location loc = location ()); + rvalue new_call (function func, + rvalue arg0, rvalue arg1, rvalue arg2, + rvalue arg3, + location loc = location ()); + rvalue new_call (function func, + rvalue arg0, rvalue arg1, rvalue arg2, + rvalue arg3, rvalue arg4, + location loc = location ()); + rvalue new_call (function func, + rvalue arg0, rvalue arg1, rvalue arg2, + rvalue arg3, rvalue arg4, rvalue arg5, + location loc = location ()); + + rvalue new_cast (rvalue expr, + type type_, + location loc = location ()); + + lvalue new_array_access (rvalue ptr, + rvalue index, + location loc = location ()); + + private: + gcc_jit_context *m_inner_ctxt; + }; + + class field : public object + { + public: + field (); + field (gcc_jit_field *inner); + + gcc_jit_field *get_inner_field () const; + }; + + class type : public object + { + public: + type (); + type (gcc_jit_type *inner); + + gcc_jit_type *get_inner_type () const; + + type get_pointer (); + type get_volatile (); + + // Shortcuts for getting values of numeric types: + rvalue zero (); + rvalue one (); + }; + + class struct_ : public type + { + public: + struct_ (); + struct_ (gcc_jit_struct *inner); + + gcc_jit_struct *get_inner_struct () const; + }; + + class function : public object + { + public: + function (); + function (gcc_jit_function *func); + + gcc_jit_function *get_inner_function () const; + + void dump_to_dot (const std::string &path); + + param get_param (int index) const; + + block new_block (); + block new_block (const std::string &name); + + lvalue new_local (type type_, + const std::string &name, + location loc = location ()); + + /* A series of overloaded operator () with various numbers of arguments + for a very terse way of creating a call to this function. The call + is created within the same context as the function itself, which may + not be what you want. */ + rvalue operator() (location loc = location ()); + rvalue operator() (rvalue arg0, + location loc = location ()); + rvalue operator() (rvalue arg0, rvalue arg1, + location loc = location ()); + rvalue operator() (rvalue arg0, rvalue arg1, rvalue arg2, + location loc = location ()); + }; + + class block : public object + { + public: + block (); + block (gcc_jit_block *inner); + + gcc_jit_block *get_inner_block () const; + + function get_function () const; + + void add_eval (rvalue rvalue, + location loc = location ()); + + void add_assignment (lvalue lvalue, + rvalue rvalue, + location loc = location ()); + + void add_assignment_op (lvalue lvalue, + enum gcc_jit_binary_op op, + rvalue rvalue, + location loc = location ()); + + /* A way to add a function call to the body of a function being + defined, with various numbers of args. */ + rvalue add_call (function other, + location loc = location ()); + rvalue add_call (function other, + rvalue arg0, + location loc = location ()); + rvalue add_call (function other, + rvalue arg0, rvalue arg1, + location loc = location ()); + rvalue add_call (function other, + rvalue arg0, rvalue arg1, rvalue arg2, + location loc = location ()); + rvalue add_call (function other, + rvalue arg0, rvalue arg1, rvalue arg2, rvalue arg3, + location loc = location ()); + + void add_comment (const std::string &text, + location loc = location ()); + + void end_with_conditional (rvalue boolval, + block on_true, + block on_false, + location loc = location ()); + + void end_with_jump (block target, + location loc = location ()); + + void end_with_return (rvalue rvalue, + location loc = location ()); + void end_with_return (location loc = location ()); + + }; + + class rvalue : public object + { + public: + rvalue (); + rvalue (gcc_jit_rvalue *inner); + gcc_jit_rvalue *get_inner_rvalue () const; + + type get_type (); + + rvalue access_field (field field, + location loc = location ()); + + lvalue dereference_field (field field, + location loc = location ()); + + lvalue dereference (location loc = location ()); + + rvalue cast_to (type type_, + location loc = location ()); + + /* Array access. */ + lvalue operator[] (rvalue index); + lvalue operator[] (int index); + }; + + class lvalue : public rvalue + { + public: + lvalue (); + lvalue (gcc_jit_lvalue *inner); + + gcc_jit_lvalue *get_inner_lvalue () const; + + lvalue access_field (field field, + location loc = location ()); + + rvalue get_address (location loc = location ()); + }; + + class param : public lvalue + { + public: + param (); + param (gcc_jit_param *inner); + + gcc_jit_param *get_inner_param () const; + }; + + + /* Overloaded operators, for those who want the most terse API + (at the possible risk of being a little too magical). + + In each case, the first parameter is used to determine which context + owns the resulting expression, and, where appropriate, what the + latter's type is. */ + + /* Unary operators. */ + rvalue operator- (rvalue a); // unary minus + rvalue operator~ (rvalue a); // unary bitwise negate + rvalue operator! (rvalue a); // unary logical negate + + /* Binary operators. */ + rvalue operator+ (rvalue a, rvalue b); + rvalue operator- (rvalue a, rvalue b); + rvalue operator* (rvalue a, rvalue b); + rvalue operator/ (rvalue a, rvalue b); + rvalue operator% (rvalue a, rvalue b); + rvalue operator& (rvalue a, rvalue b); // bitwise and + rvalue operator^ (rvalue a, rvalue b); // bitwise_xor + rvalue operator| (rvalue a, rvalue b); // bitwise_or + rvalue operator&& (rvalue a, rvalue b); // logical_and + rvalue operator|| (rvalue a, rvalue b); // logical_or + + /* Comparisons. */ + rvalue operator== (rvalue a, rvalue b); + rvalue operator!= (rvalue a, rvalue b); + rvalue operator< (rvalue a, rvalue b); + rvalue operator<= (rvalue a, rvalue b); + rvalue operator> (rvalue a, rvalue b); + rvalue operator>= (rvalue a, rvalue b); + + /* Dereferencing. */ + lvalue operator* (rvalue ptr); +} + +/**************************************************************************** + Implementation of the API + ****************************************************************************/ +namespace gccjit { + +// class context +inline context context::acquire () +{ + return context (gcc_jit_context_acquire ()); +} +inline context::context () : m_inner_ctxt (NULL) {} +inline context::context (gcc_jit_context *inner) : m_inner_ctxt (inner) +{ + if (!inner) + throw error (); +} + +inline gccjit::context +context::new_child_context () +{ + return context (gcc_jit_context_new_child_context (m_inner_ctxt)); +} + +inline void +context::release () +{ + gcc_jit_context_release (m_inner_ctxt); + m_inner_ctxt = NULL; +} + +inline gcc_jit_result * +context::compile () +{ + gcc_jit_result *result = gcc_jit_context_compile (m_inner_ctxt); + if (!result) + throw error (); + return result; +} + +inline void +context::dump_to_file (const std::string &path, + bool update_locations) +{ + gcc_jit_context_dump_to_file (m_inner_ctxt, + path.c_str (), + update_locations); +} + +inline void +context::set_int_option (enum gcc_jit_int_option opt, + int value) +{ + gcc_jit_context_set_int_option (m_inner_ctxt, opt, value); + +} + +inline void +context::set_bool_option (enum gcc_jit_bool_option opt, + int value) +{ + gcc_jit_context_set_bool_option (m_inner_ctxt, opt, value); + +} + +inline location +context::new_location (const std::string &filename, + int line, + int column) +{ + return location (gcc_jit_context_new_location (m_inner_ctxt, + filename.c_str (), + line, + column)); +} + +inline type +context::get_type (enum gcc_jit_types kind) +{ + return type (gcc_jit_context_get_type (m_inner_ctxt, kind)); +} + +inline type +context::get_int_type (size_t num_bytes, int is_signed) +{ + return type (gcc_jit_context_get_int_type (m_inner_ctxt, + num_bytes, + is_signed)); +} + +template +inline type +context::get_int_type () +{ + return get_int_type (sizeof (T), std::numeric_limits::is_signed); +} + +inline type +context::new_array_type (type element_type, int num_elements, location loc) +{ + return type (gcc_jit_context_new_array_type ( + m_inner_ctxt, + loc.get_inner_location (), + element_type.get_inner_type (), + num_elements)); +} + +inline field +context::new_field (type type_, const std::string &name, location loc) +{ + return field (gcc_jit_context_new_field (m_inner_ctxt, + loc.get_inner_location (), + type_.get_inner_type (), + name.c_str ())); +} + +inline struct_ +context::new_struct_type (const std::string &name, + std::vector &fields, + location loc) +{ + /* Treat std::vector as an array, relying on it not being resized: */ + field *as_array_of_wrappers = &fields[0]; + + /* Treat the array as being of the underlying pointers, relying on + the wrapper type being such a pointer internally. */ + gcc_jit_field **as_array_of_ptrs = + reinterpret_cast (as_array_of_wrappers); + + return struct_ (gcc_jit_context_new_struct_type (m_inner_ctxt, + loc.get_inner_location (), + name.c_str (), + fields.size (), + as_array_of_ptrs)); +} + +inline struct_ +context::new_opaque_struct_type (const std::string &name, + location loc) +{ + return struct_ (gcc_jit_context_new_opaque_struct ( + m_inner_ctxt, + loc.get_inner_location (), + name.c_str ())); +} + +inline param +context::new_param (type type_, + const std::string &name, + location loc) +{ + return param (gcc_jit_context_new_param (m_inner_ctxt, + loc.get_inner_location (), + type_.get_inner_type (), + name.c_str ())); +} + +inline function +context::new_function (enum gcc_jit_function_kind kind, + type return_type, + const std::string &name, + std::vector ¶ms, + int is_variadic, + location loc) +{ + /* Treat std::vector as an array, relying on it not being resized: */ + param *as_array_of_wrappers = ¶ms[0]; + + /* Treat the array as being of the underlying pointers, relying on + the wrapper type being such a pointer internally. */ + gcc_jit_param **as_array_of_ptrs = + reinterpret_cast (as_array_of_wrappers); + + return function (gcc_jit_context_new_function (m_inner_ctxt, + loc.get_inner_location (), + kind, + return_type.get_inner_type (), + name.c_str (), + params.size (), + as_array_of_ptrs, + is_variadic)); +} + +inline function +context::get_builtin_function (const std::string &name) +{ + return function (gcc_jit_context_get_builtin_function (m_inner_ctxt, + name.c_str ())); +} + +inline lvalue +context::new_global (type type_, + const std::string &name, + location loc) +{ + return lvalue (gcc_jit_context_new_global (m_inner_ctxt, + loc.get_inner_location (), + type_.get_inner_type (), + name.c_str ())); +} + +inline rvalue +context::new_rvalue (type numeric_type, + int value) const +{ + return rvalue ( + gcc_jit_context_new_rvalue_from_int (m_inner_ctxt, + numeric_type.get_inner_type (), + value)); +} + +inline rvalue +context::zero (type numeric_type) const +{ + return rvalue (gcc_jit_context_zero (m_inner_ctxt, + numeric_type.get_inner_type ())); +} + +inline rvalue +context::one (type numeric_type) const +{ + return rvalue (gcc_jit_context_one (m_inner_ctxt, + numeric_type.get_inner_type ())); +} + +inline rvalue +context::new_rvalue (type numeric_type, + double value) const +{ + return rvalue ( + gcc_jit_context_new_rvalue_from_double (m_inner_ctxt, + numeric_type.get_inner_type (), + value)); +} + +inline rvalue +context::new_rvalue (type pointer_type, + void *value) const +{ + return rvalue ( + gcc_jit_context_new_rvalue_from_ptr (m_inner_ctxt, + pointer_type.get_inner_type (), + value)); +} + +inline rvalue +context::new_rvalue (const std::string &value) const +{ + return rvalue ( + gcc_jit_context_new_string_literal (m_inner_ctxt, value.c_str ())); +} + +inline rvalue +context::new_unary_op (enum gcc_jit_unary_op op, + type result_type, + rvalue a, + location loc) +{ + return rvalue (gcc_jit_context_new_unary_op (m_inner_ctxt, + loc.get_inner_location (), + op, + result_type.get_inner_type (), + a.get_inner_rvalue ())); +} +inline rvalue +context::new_minus (type result_type, + rvalue a, + location loc) +{ + return rvalue (new_unary_op (GCC_JIT_UNARY_OP_MINUS, + result_type, a, loc)); +} +inline rvalue +context::new_bitwise_negate (type result_type, + rvalue a, + location loc) +{ + return rvalue (new_unary_op (GCC_JIT_UNARY_OP_BITWISE_NEGATE, + result_type, a, loc)); +} +inline rvalue +context::new_logical_negate (type result_type, + rvalue a, + location loc) +{ + return rvalue (new_unary_op (GCC_JIT_UNARY_OP_LOGICAL_NEGATE, + result_type, a, loc)); +} + +inline rvalue +context::new_binary_op (enum gcc_jit_binary_op op, + type result_type, + rvalue a, rvalue b, + location loc) +{ + return rvalue (gcc_jit_context_new_binary_op (m_inner_ctxt, + loc.get_inner_location (), + op, + result_type.get_inner_type (), + a.get_inner_rvalue (), + b.get_inner_rvalue ())); +} +inline rvalue +context::new_plus (type result_type, + rvalue a, rvalue b, + location loc) +{ + return new_binary_op (GCC_JIT_BINARY_OP_PLUS, + result_type, a, b, loc); +} +inline rvalue +context::new_minus (type result_type, + rvalue a, rvalue b, + location loc) +{ + return new_binary_op (GCC_JIT_BINARY_OP_MINUS, + result_type, a, b, loc); +} +inline rvalue +context::new_mult (type result_type, + rvalue a, rvalue b, + location loc) +{ + return new_binary_op (GCC_JIT_BINARY_OP_MULT, + result_type, a, b, loc); +} +inline rvalue +context::new_divide (type result_type, + rvalue a, rvalue b, + location loc) +{ + return new_binary_op (GCC_JIT_BINARY_OP_DIVIDE, + result_type, a, b, loc); +} +inline rvalue +context::new_modulo (type result_type, + rvalue a, rvalue b, + location loc) +{ + return new_binary_op (GCC_JIT_BINARY_OP_MODULO, + result_type, a, b, loc); +} +inline rvalue +context::new_bitwise_and (type result_type, + rvalue a, rvalue b, + location loc) +{ + return new_binary_op (GCC_JIT_BINARY_OP_BITWISE_AND, + result_type, a, b, loc); +} +inline rvalue +context::new_bitwise_xor (type result_type, + rvalue a, rvalue b, + location loc) +{ + return new_binary_op (GCC_JIT_BINARY_OP_BITWISE_XOR, + result_type, a, b, loc); +} +inline rvalue +context::new_bitwise_or (type result_type, + rvalue a, rvalue b, + location loc) +{ + return new_binary_op (GCC_JIT_BINARY_OP_BITWISE_OR, + result_type, a, b, loc); +} +inline rvalue +context::new_logical_and (type result_type, + rvalue a, rvalue b, + location loc) +{ + return new_binary_op (GCC_JIT_BINARY_OP_LOGICAL_AND, + result_type, a, b, loc); +} +inline rvalue +context::new_logical_or (type result_type, + rvalue a, rvalue b, + location loc) +{ + return new_binary_op (GCC_JIT_BINARY_OP_LOGICAL_OR, + result_type, a, b, loc); +} + +inline rvalue +context::new_comparison (enum gcc_jit_comparison op, + rvalue a, rvalue b, + location loc) +{ + return rvalue (gcc_jit_context_new_comparison (m_inner_ctxt, + loc.get_inner_location (), + op, + a.get_inner_rvalue (), + b.get_inner_rvalue ())); +} +inline rvalue +context::new_eq (rvalue a, rvalue b, + location loc) +{ + return new_comparison (GCC_JIT_COMPARISON_EQ, + a, b, loc); +} +inline rvalue +context::new_ne (rvalue a, rvalue b, + location loc) +{ + return new_comparison (GCC_JIT_COMPARISON_NE, + a, b, loc); +} +inline rvalue +context::new_lt (rvalue a, rvalue b, + location loc) +{ + return new_comparison (GCC_JIT_COMPARISON_LT, + a, b, loc); +} +inline rvalue +context::new_le (rvalue a, rvalue b, + location loc) +{ + return new_comparison (GCC_JIT_COMPARISON_LE, + a, b, loc); +} +inline rvalue +context::new_gt (rvalue a, rvalue b, + location loc) +{ + return new_comparison (GCC_JIT_COMPARISON_GT, + a, b, loc); +} +inline rvalue +context::new_ge (rvalue a, rvalue b, + location loc) +{ + return new_comparison (GCC_JIT_COMPARISON_GE, + a, b, loc); +} + +inline rvalue +context::new_call (function func, + std::vector &args, + location loc) +{ + /* Treat std::vector as an array, relying on it not being resized: */ + rvalue *as_array_of_wrappers = &args[0]; + + /* Treat the array as being of the underlying pointers, relying on + the wrapper type being such a pointer internally. */ + gcc_jit_rvalue **as_array_of_ptrs = + reinterpret_cast (as_array_of_wrappers); + return gcc_jit_context_new_call (m_inner_ctxt, + loc.get_inner_location (), + func.get_inner_function (), + args.size (), + as_array_of_ptrs); +} +inline rvalue +context::new_call (function func, + location loc) +{ + std::vector args; + return new_call (func, args, loc); +} + +inline rvalue +context::new_call (function func, + rvalue arg0, + location loc) +{ + std::vector args(1); + args[0] = arg0; + return new_call (func, args, loc); +} +inline rvalue +context::new_call (function func, + rvalue arg0, rvalue arg1, + location loc) +{ + std::vector args(2); + args[0] = arg0; + args[1] = arg1; + return new_call (func, args, loc); +} +inline rvalue +context::new_call (function func, + rvalue arg0, rvalue arg1, rvalue arg2, + location loc) +{ + std::vector args(3); + args[0] = arg0; + args[1] = arg1; + args[2] = arg2; + return new_call (func, args, loc); +} +inline rvalue +context::new_call (function func, + rvalue arg0, rvalue arg1, rvalue arg2, + rvalue arg3, + location loc) +{ + std::vector args(4); + args[0] = arg0; + args[1] = arg1; + args[2] = arg2; + args[3] = arg3; + return new_call (func, args, loc); +} +inline rvalue +context::new_call (function func, + rvalue arg0, rvalue arg1, rvalue arg2, + rvalue arg3, rvalue arg4, + location loc) +{ + std::vector args(5); + args[0] = arg0; + args[1] = arg1; + args[2] = arg2; + args[3] = arg3; + args[4] = arg4; + return new_call (func, args, loc); +} +inline rvalue +context::new_call (function func, + rvalue arg0, rvalue arg1, rvalue arg2, + rvalue arg3, rvalue arg4, rvalue arg5, + location loc) +{ + std::vector args(6); + args[0] = arg0; + args[1] = arg1; + args[2] = arg2; + args[3] = arg3; + args[4] = arg4; + args[5] = arg5; + return new_call (func, args, loc); +} + +inline rvalue +context::new_cast (rvalue expr, + type type_, + location loc) +{ + return rvalue (gcc_jit_context_new_cast (m_inner_ctxt, + loc.get_inner_location (), + expr.get_inner_rvalue (), + type_.get_inner_type ())); +} + +inline lvalue +context::new_array_access (rvalue ptr, + rvalue index, + location loc) +{ + return lvalue (gcc_jit_context_new_array_access (m_inner_ctxt, + loc.get_inner_location (), + ptr.get_inner_rvalue (), + index.get_inner_rvalue ())); +} + +// class object +inline context +object::get_context () const +{ + return context (gcc_jit_object_get_context (m_inner_obj)); +} + +inline std::string +object::get_debug_string () const +{ + return gcc_jit_object_get_debug_string (m_inner_obj); +} + +inline object::object () : m_inner_obj (NULL) {} +inline object::object (gcc_jit_object *obj) : m_inner_obj (obj) +{ + if (!obj) + throw error (); +} + +inline gcc_jit_object * +object::get_inner_object () const +{ + return m_inner_obj; +} + +inline std::ostream& +operator << (std::ostream& stream, const object &obj) +{ + return stream << obj.get_debug_string (); +} + +// class location +inline location::location () : object () {} +inline location::location (gcc_jit_location *loc) + : object (gcc_jit_location_as_object (loc)) +{} + +inline gcc_jit_location * +location::get_inner_location () const +{ + /* Manual downcast: */ + return reinterpret_cast (get_inner_object ()); +} + +// class field +inline field::field () : object () {} +inline field::field (gcc_jit_field *inner) + : object (gcc_jit_field_as_object (inner)) +{} + +inline gcc_jit_field * +field::get_inner_field () const +{ + /* Manual downcast: */ + return reinterpret_cast (get_inner_object ()); +} + +// class type +inline type::type () : object () {} +inline type::type (gcc_jit_type *inner) + : object (gcc_jit_type_as_object (inner)) +{} + +inline gcc_jit_type * +type::get_inner_type () const +{ + /* Manual downcast: */ + return reinterpret_cast (get_inner_object ()); +} + +inline type +type::get_pointer () +{ + return type (gcc_jit_type_get_pointer (get_inner_type ())); +} + +inline type +type::get_volatile () +{ + return type (gcc_jit_type_get_volatile (get_inner_type ())); +} + +inline rvalue +type::zero () +{ + return get_context ().new_rvalue (*this, 0); +} + +inline rvalue +type::one () +{ + return get_context ().new_rvalue (*this, 1); +} + +// class struct_ +inline struct_::struct_ () : type (NULL) {} +inline struct_::struct_ (gcc_jit_struct *inner) : + type (gcc_jit_struct_as_type (inner)) +{ +} + +inline gcc_jit_struct * +struct_::get_inner_struct () const +{ + /* Manual downcast: */ + return reinterpret_cast (get_inner_object ()); +} + +// class function +inline function::function () : object () {} +inline function::function (gcc_jit_function *inner) + : object (gcc_jit_function_as_object (inner)) +{} + +inline gcc_jit_function * +function::get_inner_function () const +{ + /* Manual downcast: */ + return reinterpret_cast (get_inner_object ()); +} + +inline void +function::dump_to_dot (const std::string &path) +{ + gcc_jit_function_dump_to_dot (get_inner_function (), + path.c_str ()); +} + +inline param +function::get_param (int index) const +{ + return param (gcc_jit_function_get_param (get_inner_function (), + index)); +} + +inline block +function::new_block () +{ + return block (gcc_jit_function_new_block (get_inner_function (), + NULL)); +} + +inline block +function::new_block (const std::string &name) +{ + return block (gcc_jit_function_new_block (get_inner_function (), + name.c_str ())); +} + +inline lvalue +function::new_local (type type_, + const std::string &name, + location loc) +{ + return lvalue (gcc_jit_function_new_local (get_inner_function (), + loc.get_inner_location (), + type_.get_inner_type (), + name.c_str ())); +} + +inline function +block::get_function () const +{ + return function (gcc_jit_block_get_function ( get_inner_block ())); +} + +inline void +block::add_eval (rvalue rvalue, + location loc) +{ + gcc_jit_block_add_eval (get_inner_block (), + loc.get_inner_location (), + rvalue.get_inner_rvalue ()); +} + +inline void +block::add_assignment (lvalue lvalue, + rvalue rvalue, + location loc) +{ + gcc_jit_block_add_assignment (get_inner_block (), + loc.get_inner_location (), + lvalue.get_inner_lvalue (), + rvalue.get_inner_rvalue ()); +} + +inline void +block::add_assignment_op (lvalue lvalue, + enum gcc_jit_binary_op op, + rvalue rvalue, + location loc) +{ + gcc_jit_block_add_assignment_op (get_inner_block (), + loc.get_inner_location (), + lvalue.get_inner_lvalue (), + op, + rvalue.get_inner_rvalue ()); +} + +inline void +block::add_comment (const std::string &text, + location loc) +{ + gcc_jit_block_add_comment (get_inner_block (), + loc.get_inner_location (), + text.c_str ()); +} + +inline void +block::end_with_conditional (rvalue boolval, + block on_true, + block on_false, + location loc) +{ + gcc_jit_block_end_with_conditional (get_inner_block (), + loc.get_inner_location (), + boolval.get_inner_rvalue (), + on_true.get_inner_block (), + on_false.get_inner_block ()); +} + +inline void +block::end_with_jump (block target, + location loc) +{ + gcc_jit_block_end_with_jump (get_inner_block (), + loc.get_inner_location (), + target.get_inner_block ()); +} + +inline void +block::end_with_return (rvalue rvalue, + location loc) +{ + gcc_jit_block_end_with_return (get_inner_block (), + loc.get_inner_location (), + rvalue.get_inner_rvalue ()); +} + +inline void +block::end_with_return (location loc) +{ + gcc_jit_block_end_with_void_return (get_inner_block (), + loc.get_inner_location ()); +} + +inline rvalue +block::add_call (function other, + location loc) +{ + rvalue c = get_context ().new_call (other, loc); + add_eval (c); + return c; +} +inline rvalue +block::add_call (function other, + rvalue arg0, + location loc) +{ + rvalue c = get_context ().new_call (other, arg0, loc); + add_eval (c); + return c; +} +inline rvalue +block::add_call (function other, + rvalue arg0, rvalue arg1, + location loc) +{ + rvalue c = get_context ().new_call (other, arg0, arg1, loc); + add_eval (c); + return c; +} +inline rvalue +block::add_call (function other, + rvalue arg0, rvalue arg1, rvalue arg2, + location loc) +{ + rvalue c = get_context ().new_call (other, arg0, arg1, arg2, loc); + add_eval (c); + return c; +} + +inline rvalue +block::add_call (function other, + rvalue arg0, rvalue arg1, rvalue arg2, rvalue arg3, + location loc) +{ + rvalue c = get_context ().new_call (other, arg0, arg1, arg2, arg3, loc); + add_eval (c); + return c; +} + +inline rvalue +function::operator() (location loc) +{ + return get_context ().new_call (*this, loc); +} +inline rvalue +function::operator() (rvalue arg0, + location loc) +{ + return get_context ().new_call (*this, + arg0, + loc); +} +inline rvalue +function::operator() (rvalue arg0, rvalue arg1, + location loc) +{ + return get_context ().new_call (*this, + arg0, arg1, + loc); +} +inline rvalue +function::operator() (rvalue arg0, rvalue arg1, rvalue arg2, + location loc) +{ + return get_context ().new_call (*this, + arg0, arg1, arg2, + loc); +} + +// class block +inline block::block () : object () {} +inline block::block (gcc_jit_block *inner) + : object (gcc_jit_block_as_object (inner)) +{} + +inline gcc_jit_block * +block::get_inner_block () const +{ + /* Manual downcast: */ + return reinterpret_cast (get_inner_object ()); +} + +// class rvalue +inline rvalue::rvalue () : object () {} +inline rvalue::rvalue (gcc_jit_rvalue *inner) + : object (gcc_jit_rvalue_as_object (inner)) +{} + +inline gcc_jit_rvalue * +rvalue::get_inner_rvalue () const +{ + /* Manual downcast: */ + return reinterpret_cast (get_inner_object ()); +} + +inline type +rvalue::get_type () +{ + return type (gcc_jit_rvalue_get_type (get_inner_rvalue ())); +} + +inline rvalue +rvalue::access_field (field field, + location loc) +{ + return rvalue (gcc_jit_rvalue_access_field (get_inner_rvalue (), + loc.get_inner_location (), + field.get_inner_field ())); +} + +inline lvalue +rvalue::dereference_field (field field, + location loc) +{ + return lvalue (gcc_jit_rvalue_dereference_field (get_inner_rvalue (), + loc.get_inner_location (), + field.get_inner_field ())); +} + +inline lvalue +rvalue::dereference (location loc) +{ + return lvalue (gcc_jit_rvalue_dereference (get_inner_rvalue (), + loc.get_inner_location ())); +} + +inline rvalue +rvalue::cast_to (type type_, + location loc) +{ + return get_context ().new_cast (*this, type_, loc); +} + +inline lvalue +rvalue::operator[] (rvalue index) +{ + return get_context ().new_array_access (*this, index); +} + +inline lvalue +rvalue::operator[] (int index) +{ + context ctxt = get_context (); + type int_t = ctxt.get_int_type (); + return ctxt.new_array_access (*this, + ctxt.new_rvalue (int_t, + index)); +} + +// class lvalue : public rvalue +inline lvalue::lvalue () : rvalue () {} +inline lvalue::lvalue (gcc_jit_lvalue *inner) + : rvalue (gcc_jit_lvalue_as_rvalue (inner)) +{} + +inline gcc_jit_lvalue * +lvalue::get_inner_lvalue () const +{ + /* Manual downcast: */ + return reinterpret_cast (get_inner_object ()); +} + +inline lvalue +lvalue::access_field (field field, location loc) +{ + return lvalue (gcc_jit_lvalue_access_field (get_inner_lvalue (), + loc.get_inner_location (), + field.get_inner_field ())); +} + +inline rvalue +lvalue::get_address (location loc) +{ + return rvalue (gcc_jit_lvalue_get_address (get_inner_lvalue (), + loc.get_inner_location ())); +} + +// class param : public lvalue +inline param::param () : lvalue () {} +inline param::param (gcc_jit_param *inner) + : lvalue (gcc_jit_param_as_lvalue (inner)) +{} + +/* Overloaded operators. */ +// Unary operators +inline rvalue operator- (rvalue a) +{ + return a.get_context ().new_minus (a.get_type (), a); +} +inline rvalue operator~ (rvalue a) +{ + return a.get_context ().new_bitwise_negate (a.get_type (), a); +} +inline rvalue operator! (rvalue a) +{ + return a.get_context ().new_logical_negate (a.get_type (), a); +} + +// Binary operators +inline rvalue operator+ (rvalue a, rvalue b) +{ + return a.get_context ().new_plus (a.get_type (), a, b); +} +inline rvalue operator- (rvalue a, rvalue b) +{ + return a.get_context ().new_minus (a.get_type (), a, b); +} +inline rvalue operator* (rvalue a, rvalue b) +{ + return a.get_context ().new_mult (a.get_type (), a, b); +} +inline rvalue operator/ (rvalue a, rvalue b) +{ + return a.get_context ().new_divide (a.get_type (), a, b); +} +inline rvalue operator% (rvalue a, rvalue b) +{ + return a.get_context ().new_modulo (a.get_type (), a, b); +} +inline rvalue operator& (rvalue a, rvalue b) +{ + return a.get_context ().new_bitwise_and (a.get_type (), a, b); +} +inline rvalue operator^ (rvalue a, rvalue b) +{ + return a.get_context ().new_bitwise_xor (a.get_type (), a, b); +} +inline rvalue operator| (rvalue a, rvalue b) +{ + return a.get_context ().new_bitwise_or (a.get_type (), a, b); +} +inline rvalue operator&& (rvalue a, rvalue b) +{ + return a.get_context ().new_logical_and (a.get_type (), a, b); +} +inline rvalue operator|| (rvalue a, rvalue b) +{ + return a.get_context ().new_logical_or (a.get_type (), a, b); +} + +/* Comparisons. */ +inline rvalue operator== (rvalue a, rvalue b) +{ + return a.get_context ().new_eq (a, b); +} +inline rvalue operator!= (rvalue a, rvalue b) +{ + return a.get_context ().new_ne (a, b); +} +inline rvalue operator< (rvalue a, rvalue b) +{ + return a.get_context ().new_lt (a, b); +} +inline rvalue operator<= (rvalue a, rvalue b) +{ + return a.get_context ().new_le (a, b); +} +inline rvalue operator> (rvalue a, rvalue b) +{ + return a.get_context ().new_gt (a, b); +} +inline rvalue operator>= (rvalue a, rvalue b) +{ + return a.get_context ().new_ge (a, b); +} + +/* Dereferencing. */ +inline lvalue operator* (rvalue ptr) +{ + return ptr.dereference (); +} + +} // namespace gccjit + +#endif /* #ifndef LIBGCCJIT_PLUS_PLUS_H */ -- 1.8.5.3