Fast IFS using RPN notation
python
c
x86-64
nasm
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

rpn_jit.h 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. * Copyright (C) 2020 Weber Yann
  3. *
  4. * This file is part of pyrpn.
  5. *
  6. * pyrpn is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * any later version.
  10. *
  11. * pyrpn is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with pyrpn. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef __rpn_jit__h__
  20. #define __rpn_jit__h__
  21. #include "config.h"
  22. #include <stdlib.h>
  23. #include <errno.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <sys/mman.h>
  27. #include <sys/random.h>
  28. #include "rpn_lib.h"
  29. #include "rpn_parse.h"
  30. /**@defgroup rpn RPN evaluation lib
  31. * @brief High speed RPN expression evaluation librarie
  32. */
  33. /**@defgroup rpn_compile RPN expression compilation
  34. * @brief How is an RPN expression transformed into a callable function
  35. *
  36. * Compilation is done in two steps :
  37. * - @ref rpn_tokenize
  38. * - @ref rpn_exec
  39. * @ingroup rpn
  40. */
  41. /**@defgroup rpn_cmap Executable code map creation
  42. * @brief A code map containing compiled code to evaluate the expression
  43. *
  44. * In order to provide a callable memory adress, the compilation process starts
  45. * by creating a new memory map. Then @ref rpn_lib precompiled symbols are
  46. * copyied in it, suffixed by @ref rpn_exec_ret symbol. Finally, the map is set executable using mprotect.
  47. * @ingroup rpn_compile
  48. */
  49. /**@file rpn_jit.h
  50. * @brief Contains structure & functions for rpn_expr_t manipulation & evaluation
  51. * @ingroup rpn
  52. */
  53. /**@brief Mremap chunk size */
  54. #define RPN_MAP_CHUNK 512
  55. /**@brief @ref rpn_expr_t error state */
  56. #define RPN_ERROR -1
  57. /**@brief @ref rpn_expr_t initialization state */
  58. #define RPN_SOURCE 0
  59. /**@brief @ref rpn_expr_t ready to eval state */
  60. #define RPN_READY 1
  61. /**@brief Code part copy macro
  62. * @param expr rpn_expr_t* A pointer on @ref rpn_expr_t
  63. * @param NAME code part name
  64. * @see _rpn_code_part_cpy
  65. * @ingroup rpn_cmap
  66. */
  67. #define CODE_PART_CPY(expr, NAME) _rpn_code_part_cpy(expr, &NAME, CODE_SZ(NAME), NULL)
  68. /**@brief Copy a value push in rpn code ptr
  69. * @param expr rpn_expr_t* A pointer on @ref rpn_expr_t
  70. * @param value unsigned long that will be push
  71. * @see _rpn_code_part_cpy
  72. * @ingroup rpn_cmap
  73. */
  74. #define CODE_VALUE_CPY(expr, value) _rpn_code_part_cpy(expr, &rpn_value, CODE_SZ(rpn_value), &(value));
  75. /**@brief Add an instruction to push an argument on RPN stack
  76. * @param expr rpn_expr_t* A pointer on @ref rpn_expr_t
  77. * @param value unsigned long The argument number
  78. * @see _rpn_code_part_cpy
  79. * @ingroup rpn_cmap
  80. */
  81. #define CODE_ARG_CPY(expr, value) _rpn_code_part_cpy(expr, &rpn_arg, CODE_SZ(rpn_arg), &(value));
  82. /**@brief RPN evaluation function type
  83. * @ingroup rpn_cmap
  84. */
  85. typedef unsigned long (*rpn_run_f)(unsigned long, unsigned long*, void*);
  86. /**@brief RPN expression type
  87. * @ingroup rpn */
  88. typedef struct rpn_expr_s rpn_expr_t;
  89. /**@brief Stores RPN expression informations
  90. * @ingroup rpn
  91. */
  92. struct rpn_expr_s
  93. {
  94. /**@brief pointer on RPN expression */
  95. char *expr;
  96. /**@brief Tokenized version of expression (set by @ref rpn_expr_compile)*/
  97. rpn_tokenized_t toks;
  98. /**@brief pointer on jit code memory map */
  99. void *code_map;
  100. /**@brief Pointer on next copy addr in code map */
  101. void *code_map_ptr;
  102. /**@brief Code map size */
  103. size_t code_map_sz;
  104. /**@brief rpn expression arguments count */
  105. size_t args_count;
  106. /**@brief Stack values memory */
  107. rpn_value_t *stack;
  108. /**@brief rpn jit function stack size
  109. * @note item size (size in bytes is sizeof(long) * stack_sz */
  110. unsigned char stack_sz;
  111. /**@brief Expression status. Takes value in @ref RPN_ERROR,
  112. * @ref RPN_SOURCE, @ref RPN_READY */
  113. short state;
  114. /**@brief Error reason */
  115. char err_reason[128];
  116. };
  117. /**@brief Initialize a new @ref rpn_expr_s
  118. * @param expr Pointer on the expression
  119. * @param stack_sz Expression stack size
  120. * @param args_count Expression argument counter
  121. * @return 0 if no error else -1
  122. * @note Once rpn_expr_init has been called, you have to call
  123. * @ref rpn_expr_close in order to free handled ressources
  124. * @ingroup rpn
  125. */
  126. int rpn_expr_init(rpn_expr_t* expr, const unsigned char stack_sz,
  127. const size_t args_count);
  128. /**@brief Reinit an existing @ref rpn_expr_s avoiding mmap and malloc
  129. * for executable memory map and for stack
  130. * @param expr
  131. */
  132. int rpn_expr_reinit(rpn_expr_t* expr);
  133. /**@brief Starts a new initialized expression from an expression string
  134. * @param expr Pointer on an intialized expression ( see @ref rpn_expr_init )
  135. * @param code '\0' terminated string representing the RPN expr
  136. * @return 0 if no error else -1 and @ref rpn_expr_s::err_reason is set
  137. * @note The expression is copied, given buffer can be deallocated after call
  138. * @ingroup rpn
  139. */
  140. int rpn_expr_compile(rpn_expr_t *expr, const char *code);
  141. /**@brief Starts a new initialized expression from a tokenized form
  142. * @param expr Pointer on an intialized expression ( see @ref rpn_expr_init )
  143. * @param tokens Tokenized form
  144. * @param long_op If true long operation are used, else 1 chr op are used
  145. * @return 0 if no error else -1 and @ref rpn_expr_s::err_reason is set
  146. * @note The @ref rpn_tokenized_s::tokens attribute is "captured" by the
  147. * @ref rpn_expr_s structure and will be deallocated when @ref rpn_expr_close
  148. * is called. It is not encouraged to keep a reference on this attribute after
  149. * @ref rpn_expr_start_untokenize call (but pointed @ref rpn_tokenized_t
  150. * can be reused)
  151. * @ingroup rpn
  152. */
  153. int rpn_expr_untokenize(rpn_expr_t *expr, rpn_tokenized_t *tokens, char long_op);
  154. /**@brief Generate a new random rpn_expression
  155. * @param op_sz Number of token in generated expression
  156. * @param args_count Number of arguments for generated expression
  157. * @return A pointer on allocated memory storing a valid random RPN expression.
  158. * NULL if error with errno set (produce a message on stderr)
  159. * @ingroup rpn
  160. */
  161. char* rpn_random(size_t op_sz, size_t args_count);
  162. /**@brief Compile an new RPN expression from string expression
  163. * @param expr Pointer on @ref rpn_expr_s
  164. * @return 0 if no error else -1 and set @ref rpn_expr_s err_reason
  165. * @ingroup rpn_compile
  166. */
  167. int _rpn_expr_compile_expr(rpn_expr_t* expr);
  168. /**@brief Compile an new RPN expression from string expression
  169. * @param expr Pointer on @ref rpn_expr_s
  170. * @return 0 if no error else -1 and set @ref rpn_expr_s err_reason
  171. * @ingroup rpn_compile
  172. */
  173. int _rpn_expr_compile_tokens(rpn_expr_t* expr);
  174. /**@brief Evaluate an RPN expression
  175. * @param expr Pointer on @ref rpn_expr_s
  176. * @param args List of arguments
  177. * @return Head of stack after evaluation
  178. * @note If expression not compiled yet compile it before eval
  179. * @ingroup rpn
  180. */
  181. unsigned long rpn_expr_eval(rpn_expr_t *expr, unsigned long *args);
  182. /**@brief Free ressources handled by given @ref rpn_expr_s
  183. * @param expr Pointer on rpn_expr_t
  184. * @param expr Pointer on @ref rpn_expr_s
  185. * @ingroup rpn
  186. */
  187. void rpn_expr_close(rpn_expr_t* expr);
  188. /**@brief bzero memory allocated for stack
  189. * @param expr Pointer on rpn_expr_t
  190. * @ingroup rpn
  191. */
  192. void rpn_expr_reset_stack(rpn_expr_t *expr);
  193. /**@brief Copy precompiled code from @ref rpn_lib.h in expression code map
  194. * @param expr The expression being compiled
  195. * @param token Pointer on token informations
  196. * @return 0 if no error else -1, set error and errno
  197. * @ingroup rpn_cmap
  198. */
  199. int _rpn_expr_token_copy(rpn_expr_t *expr, rpn_token_t *token);
  200. /**@brief Copy a part of code to the code map
  201. * @warning designed to be use with @ref CODE_PART_CPY and CODE_VALUE_CPY macros
  202. * @param expr Pointer on rpn_expr_t
  203. * @param code_part copy src address
  204. * @param code_part_sz the code part size
  205. * @param value if not NULL set the first code part
  206. * instruction argument to this value
  207. * @return 0 if no error else -1 and set errno
  208. * @ingroup rpn_cmap
  209. */
  210. int _rpn_code_part_cpy(rpn_expr_t* expr, const void* code_part,
  211. unsigned long code_part_sz, const unsigned long *value);
  212. /**@brief Allocate a memory map for given rpn_expt_t and copy the function
  213. * header
  214. * @param expr Pointer on rpn_expr_t
  215. * @return 0 if no error, else -1 and set errno
  216. * @ingroup rpn_cmap
  217. */
  218. int _rpn_expr_init_map(rpn_expr_t* expr);
  219. /**@brief Copy the function suffix and change memory map protection
  220. * @param expr Pointer on rpn_expr_t
  221. * @return 0 if no error, else -1 and set errno
  222. * @ingroup rpn_cmap
  223. */
  224. int _rpn_expr_end_map(rpn_expr_t *expr);
  225. #endif