123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- /*
- * Copyright (C) 2020 Weber Yann
- *
- * This file is part of pyrpn.
- *
- * pyrpn 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 of the License, or
- * any later version.
- *
- * pyrpn 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 pyrpn. If not, see <http://www.gnu.org/licenses/>.
- */
- #ifndef __rpn_jit__h__
- #define __rpn_jit__h__
-
- #include "config.h"
-
- #include <stdlib.h>
- #include <errno.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/mman.h>
- #include <sys/random.h>
-
-
- #include "rpn_lib.h"
- #include "rpn_parse.h"
-
- /**@defgroup rpn RPN evaluation lib
- * @brief High speed RPN expression evaluation librarie
- */
- /**@defgroup rpn_compile RPN expression compilation
- * @brief How is an RPN expression transformed into a callable function
- *
- * Compilation is done in two steps :
- * - @ref rpn_tokenize
- * - @ref rpn_exec
- * @ingroup rpn
- */
- /**@defgroup rpn_cmap Executable code map creation
- * @brief A code map containing compiled code to evaluate the expression
- *
- * In order to provide a callable memory adress, the compilation process starts
- * by creating a new memory map. Then @ref rpn_lib precompiled symbols are
- * copyied in it, suffixed by @ref rpn_exec_ret symbol. Finally, the map is set executable using mprotect.
- * @ingroup rpn_compile
- */
-
- /**@file rpn_jit.h
- * @brief Contains structure & functions for rpn_expr_t manipulation & evaluation
- * @ingroup rpn
- */
-
- /**@brief Mremap chunk size */
- #define RPN_MAP_CHUNK 512
-
- /**@brief @ref rpn_expr_t error state */
- #define RPN_ERROR -1
- /**@brief @ref rpn_expr_t initialization state */
- #define RPN_SOURCE 0
- /**@brief @ref rpn_expr_t ready to eval state */
- #define RPN_READY 1
-
- /**@brief Code part copy macro
- * @param expr rpn_expr_t* A pointer on @ref rpn_expr_t
- * @param NAME code part name
- * @see _rpn_code_part_cpy
- * @ingroup rpn_cmap
- */
- #define CODE_PART_CPY(expr, NAME) _rpn_code_part_cpy(expr, &NAME, CODE_SZ(NAME), NULL)
-
- /**@brief Copy a value push in rpn code ptr
- * @param expr rpn_expr_t* A pointer on @ref rpn_expr_t
- * @param value unsigned long that will be push
- * @see _rpn_code_part_cpy
- * @ingroup rpn_cmap
- */
- #define CODE_VALUE_CPY(expr, value) _rpn_code_part_cpy(expr, &rpn_value, CODE_SZ(rpn_value), &(value));
-
- /**@brief Add an instruction to push an argument on RPN stack
- * @param expr rpn_expr_t* A pointer on @ref rpn_expr_t
- * @param value unsigned long The argument number
- * @see _rpn_code_part_cpy
- * @ingroup rpn_cmap
- */
- #define CODE_ARG_CPY(expr, value) _rpn_code_part_cpy(expr, &rpn_arg, CODE_SZ(rpn_arg), &(value));
-
- /**@brief RPN evaluation function type
- * @ingroup rpn_cmap
- */
- typedef unsigned long (*rpn_run_f)(unsigned long, unsigned long*, void*);
-
- /**@brief RPN expression type
- * @ingroup rpn */
- typedef struct rpn_expr_s rpn_expr_t;
-
- /** @brief Serialized expression form */
- typedef struct rpn_expr_serial_s rpn_expr_serial_t;
-
- /**@brief Stores RPN expression informations
- * @ingroup rpn
- */
- struct rpn_expr_s
- {
- /**@brief pointer on RPN expression */
- char *expr;
- /**@brief Tokenized version of expression (set by @ref rpn_expr_compile)*/
- rpn_tokenized_t toks;
-
- /**@brief pointer on jit code memory map */
- void *code_map;
-
- /**@brief Pointer on next copy addr in code map */
- void *code_map_ptr;
- /**@brief Code map size */
- size_t code_map_sz;
-
- /**@brief rpn expression arguments count */
- size_t args_count;
-
- /**@brief Stack values memory */
- rpn_value_t *stack;
- /**@brief rpn jit function stack size
- * @note item size (size in bytes is sizeof(long) * stack_sz */
- unsigned char stack_sz;
-
- /**@brief Expression status. Takes value in @ref RPN_ERROR,
- * @ref RPN_SOURCE, @ref RPN_READY */
- short state;
- /**@brief Error reason */
- char err_reason[128];
- };
-
- /**@brief Serialized form of an RPN expression
- * @ingroup rpn
- */
- struct rpn_expr_serial_s
- {
- size_t token_sz;
- unsigned char stack_sz;
- size_t argc;
- short state;
- char err_reason[128];
- };
-
- /**@brief Initialize a new @ref rpn_expr_s
- * @param expr Pointer on the expression
- * @param stack_sz Expression stack size
- * @param args_count Expression argument counter
- * @return 0 if no error else -1
- * @note Once rpn_expr_init has been called, you have to call
- * @ref rpn_expr_close in order to free handled ressources
- * @ingroup rpn
- */
- int rpn_expr_init(rpn_expr_t* expr, const unsigned char stack_sz,
- const size_t args_count);
-
- /**@brief Reinit an existing @ref rpn_expr_s avoiding mmap and malloc
- * for executable memory map and for stack
- * @param expr Pointer on the expression
- * @return 0 or -1 on error
- */
- int rpn_expr_reinit(rpn_expr_t* expr);
-
- /**@brief Recompile an existing, allready initialized, expression
- * @param expr The expression
- * @param code The code to compile
- * @return 0 if no error else -1
- */
- int rpn_expr_recompile(rpn_expr_t *expr, const char *code);
-
- /**@brief Takes into account modifications in token representation
- * @param expr The expression with updated tokens
- * @return 0 if no error else -1
- */
- int rpn_expr_tokens_updated(rpn_expr_t* expr);
-
- /**@brief Starts a new initialized expression from an expression string
- * @param expr Pointer on an intialized expression ( see @ref rpn_expr_init )
- * @param code '\0' terminated string representing the RPN expr
- * @return 0 if no error else -1 and @ref rpn_expr_s::err_reason is set
- * @note The expression is copied, given buffer can be deallocated after call
- * @ingroup rpn
- */
- int rpn_expr_compile(rpn_expr_t *expr, const char *code);
-
- /**@brief Starts a new initialized expression from a tokenized form
- * @param expr Pointer on an intialized expression ( see @ref rpn_expr_init )
- * @param tokens Tokenized form
- * @param long_op If true long operation are used, else 1 chr op are used
- * @return 0 if no error else -1 and @ref rpn_expr_s::err_reason is set
- *
- * @note The @ref rpn_tokenized_s.tokens attribute is "captured" by the
- * @ref rpn_expr_s structure and will be deallocated when @ref rpn_expr_close
- * is called. It is not encouraged to keep a reference on this attribute after
- * @ref rpn_expr_untokenize call (but pointed @ref rpn_tokenized_t
- * can be reused)
- * @ingroup rpn
- */
- int rpn_expr_untokenize(rpn_expr_t *expr, const rpn_tokenized_t *tokens, char long_op);
-
- /**@brief Generate a new random rpn_expression
- * @param op_sz Number of token in generated expression
- * @param args_count Number of arguments for generated expression
- * @return A pointer on allocated memory storing a valid random RPN expression.
- * NULL if error with errno set (produce a message on stderr)
- * @ingroup rpn
- */
- char* rpn_random(size_t op_sz, size_t args_count);
-
- /**@brief Compile an new RPN expression from string expression
- * @param expr Pointer on @ref rpn_expr_s
- * @return 0 if no error else -1 and set @ref rpn_expr_s err_reason
- * @ingroup rpn_compile
- */
- int _rpn_expr_compile_expr(rpn_expr_t* expr);
- /**@brief Compile an new RPN expression from tokens
- * @param expr Pointer on @ref rpn_expr_s
- * @return 0 if no error else -1 and set @ref rpn_expr_s err_reason
- * @ingroup rpn_compile
- */
- int _rpn_expr_compile_tokens(rpn_expr_t* expr);
-
- /**@brief Evaluate an RPN expression
- * @param expr Pointer on @ref rpn_expr_s
- * @param args List of arguments
- * @return Head of stack after evaluation
- * @note If expression not compiled yet compile it before eval
- * @ingroup rpn
- */
- unsigned long rpn_expr_eval(rpn_expr_t *expr, unsigned long *args);
-
- /**@brief Free ressources handled by given @ref rpn_expr_s
- * @param expr Pointer on rpn_expr_t
- * @ingroup rpn
- */
- void rpn_expr_close(rpn_expr_t* expr);
-
- /**@brief bzero memory allocated for stack
- * @param expr Pointer on rpn_expr_t
- * @ingroup rpn
- */
- void rpn_expr_reset_stack(rpn_expr_t *expr);
-
- /**@todo document*/
- size_t rpn_expr_serialize(rpn_expr_t* expr, void *buf, size_t buf_sz);
- /**@todo document*/
- int rpn_expr_deserialize(rpn_expr_t* expr, const void *buf, size_t buf_sz);
-
- /**@brief Copy precompiled code from @ref rpn_lib.h in expression code map
- * @param expr The expression being compiled
- * @param token Pointer on token informations
- * @return 0 if no error else -1, set error and errno
- * @ingroup rpn_cmap
- */
- int _rpn_expr_token_copy(rpn_expr_t *expr, rpn_token_t *token);
-
- /**@brief Copy a part of code to the code map
- * @warning designed to be use with @ref CODE_PART_CPY and CODE_VALUE_CPY macros
- * @param expr Pointer on rpn_expr_t
- * @param code_part copy src address
- * @param code_part_sz the code part size
- * @param value if not NULL set the first code part
- * instruction argument to this value
- * @return 0 if no error else -1 and set errno
- * @ingroup rpn_cmap
- */
- int _rpn_code_part_cpy(rpn_expr_t* expr, const void* code_part,
- unsigned long code_part_sz, const unsigned long *value);
-
- /**@brief Allocate a memory map for given rpn_expt_t and copy the function
- * header
- * @param expr Pointer on rpn_expr_t
- * @return 0 if no error, else -1 and set errno
- * @ingroup rpn_cmap
- */
- int _rpn_expr_init_map(rpn_expr_t* expr);
-
- /**@brief Copy the function suffix and change memory map protection
- * @param expr Pointer on rpn_expr_t
- * @return 0 if no error, else -1 and set errno
- * @ingroup rpn_cmap
- */
- int _rpn_expr_end_map(rpn_expr_t *expr);
-
- /**@brief Reset the memory map, filling it with zeroes and reseting permissions
- * @param expr Pointer on rpn_expr_t
- * @return 0 if no error else -1
- */
- int _rpn_expr_reset_map(rpn_expr_t *expr);
-
- #endif
|