lightning
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A first attempt to implement jit_embed


From: Paulo César Pereira de Andrade
Subject: Re: A first attempt to implement jit_embed
Date: Wed, 31 Aug 2022 15:10:43 -0300

Em ter., 30 de ago. de 2022 às 18:29, Marc Nieper-Wißkirchen
<marc.nieper+gnu@gmail.com> escreveu:
>
> I am currently trying to wrap my head around GNU lightning's size 
> calculations.  I have never paid them any attention.
>
> Where does the magic number 144 in jit_get_max_instr in lib/jit_size.c come 
> from?

  I do not remember all the details. I believe it was some special value for
x86 prolog or arm embedded constants. The commit does not say much:

""
...
    Avoid problems if JIT_INSTR_MAX is miscalculated

            * lib/jit_size.c: Preventively use at least 144 bytes
            if JIT_INSTR_MAX is less than it. The logic is not
            guaranteed to be 100% precise, it is mostly heuristics
            to allocate a buffer with as close as possible size,
            but a wrong value may cause code generation to write
            past the end of the buffer.
...
diff --git a/lib/jit_size.c b/lib/jit_size.c
index ae4c633..612417e 100644
--- a/lib/jit_size.c
+++ b/lib/jit_size.c
@@ -110,7 +110,7 @@ _jit_get_size(jit_state_t *_jit)
 jit_word_t
 jit_get_max_instr(void)
 {
-    return (JIT_INSTR_MAX);
+    return (JIT_INSTR_MAX >= 144 ? JIT_INSTR_MAX : 144);
 }
...
"""

> In lib/jit_x86-sz.c, the size of the align statement is 6 for x86_64.  This 
> seems to be off by one given the current limitation of jit_align (at most a 
> word size).

  It just collects the size generated by instructions during a "make check"
when built with "--enable-devel-get-jit-size" and run "make get_jit_size"
and chooses the largest number of bytes used for the specific lightning
instruction.

> Marc
>
> Am Di., 16. Aug. 2022 um 20:35 Uhr schrieb Paulo César Pereira de Andrade 
> <paulo.cesar.pereira.de.andrade@gmail.com>:
>>
>> Em dom., 14 de ago. de 2022 às 17:35, Marc Nieper-Wißkirchen
>> <marc.nieper+gnu@gmail.com> escreveu:
>>
>>   Hi,
>>
>> > With the patch below, I implemented
>> >
>> > jit_embed(jit_pointer_t data, jit_uint32_t length)
>> >
>> > At the moment, the implementation is for x86, but porting to other CPUs is 
>> > simple.
>> >
>> > Criticism is welcome.
>>
>>   It appears you forgot to add the embed.tst file to the patch.
>>   It could be useful to add multiple data types, so one could even add
>> assembly code in some different way, like encoded bytes.
>>
>>   It should also be possible to add embed data larger than jit_instr_max.
>>   Could change lib/jit_size.c:_jit_get_size() to check for jit_embed and
>> update the guessed size as appropriate. BTW, jit_get_size() likely
>> overestimates the size. It just plays safe, to not risk writing out of 
>> bounds.
>>   jit_code_embed should be handled in a special way, so that the jit_*sz.c
>> files would not add the largest found value when computing the size.
>>   The patch also did not update the jit_x86-sz.c file, nor any other files,
>> so, it will compute the guessed buffer size incorrectly.
>>   Probably  no need to have jit_cc_a1_len, otherwise, could have a
>> generic way to print integers. Currently it only prints hexadecimal values
>> for any immediate value. Having it print signed integers for offsets would
>> be useful.
>>   Could also use the word (w) field, no need for an extra uint32 field.
>>   I suggested a prototype with a int32 field because I do not expect one
>> to embed more than 2G of data in a code buffer :)
>>
>> > Thanks,
>> >
>> > Marc
>> >
>> > diff --git a/bootstrap.conf b/bootstrap.conf
>> > index 423491b..c257814 100644
>> > --- a/bootstrap.conf
>> > +++ b/bootstrap.conf
>> > @@ -18,6 +18,7 @@
>> >
>> >  # gnulib modules used by this package.
>> >  gnulib_modules="
>> > +  obstack
>> >  "
>> >
>> >  # gnulib library name.
>> > diff --git a/check/Makefile.am b/check/Makefile.am
>> > index fc9f232..48b6f41 100644
>> > --- a/check/Makefile.am
>> > +++ b/check/Makefile.am
>> > @@ -49,6 +49,7 @@ EXTRA_DIST = \
>> >   3to2.tst 3to2.ok \
>> >   add.tst add.ok \
>> >   align.tst align.ok \
>> > + embed.tst embed.ok \
>> >   allocai.tst allocai.ok \
>> >   allocar.tst allocar.ok \
>> >   bp.tst bp.ok \
>> > @@ -113,7 +114,7 @@ EXTRA_DIST = \
>> >   run-test all.tst
>> >
>> >  base_TESTS = \
>> > - 3to2 add align allocai \
>> > + 3to2 add align embed allocai \
>> >   allocar bp divi fib rpn \
>> >   ldstr ldsti \
>> >   ldstxr ldstxi \
>> > @@ -192,7 +193,8 @@ endif
>> >  if test_arm_arm
>> >  #arm_TESTS = $(addsuffix .arm, $(base_TESTS))
>> >  arm_TESTS = \
>> > - 3to2.arm add.arm align.arm allocai.arm \
>> > + 3to2.arm add.arm align.arm embed.arm \
>> > + allocai.arm \
>> >   allocar.arm bp.arm divi.arm fib.arm \
>> >   rpn.arm ldstr.arm ldsti.arm \
>> >   ldstxr.arm ldstxi.arm \
>> > diff --git a/check/lightning.c b/check/lightning.c
>> > index 3cf3e70..0a4b5ca 100644
>> > --- a/check/lightning.c
>> > +++ b/check/lightning.c
>> > @@ -26,6 +26,7 @@
>> >  #else
>> >  #  include <unistd.h>
>> >  #endif
>> > +#include <obstack.h>
>> >  #include <stdio.h>
>> >  #include <stdarg.h>
>> >  #include <lightning.h>
>> > @@ -529,6 +530,7 @@ static label_t *get_label(skip_t skip);
>> >  static token_t regname(void);
>> >  static token_t identifier(int ch);
>> >  static void get_data(type_t type);
>> > +static void get_embedded_data(type_t type);
>> >  static void dot(void);
>> >  static token_t number(int ch);
>> >  static int escape(int ch);
>> > @@ -585,6 +587,7 @@ static int  symbol_offset;
>> >  static hash_t *instrs;
>> >  static char *data;
>> >  static size_t  data_offset, data_length;
>> > +static struct obstack     obstack[1];
>> >  static instr_t  instr_vector[] = {
>> >  #define entry(value) { NULL, #value, value }
>> >  #define entry2(name, function) { NULL, name, function }
>> > @@ -833,6 +836,12 @@ static instr_t  instr_vector[] = {
>> >  #undef entry
>> >  };
>> >
>> > +/*
>> > + * Obstack allocation
>> > + */
>> > +#define obstack_chunk_alloc xmalloc
>> > +#define obstack_chunk_free free
>> > +
>> >  /*
>> >   * Implementation
>> >   */
>> > @@ -2176,6 +2185,9 @@ get_data(type_t type)
>> >      token_t token;
>> >      char *test = data;
>> >
>> > +    if (parser.parsing == PARSING_CODE)
>> > +      return get_embedded_data(type);
>> > +
>> >      for (;;) {
>> >   switch (type) {
>> >      case type_c:
>> > @@ -2239,6 +2251,32 @@ get_data(type_t type)
>> >      }
>> >  }
>> >
>> > +static void
>> > +get_embedded_data(type_t type)
>> > +{
>> > +    void *data;
>> > +    int ch;
>> > +    jit_uint32_t len;
>> > +
>> > +    for (;;) {
>> > + switch (type) {
>> > + case type_i:
>> > +    len = sizeof(signed int);
>> > +    data = obstack_alloc(obstack, len);
>> > +    *(signed int *)data = get_int(skip_ws);
>> > +    jit_embed(data, len);
>> > +    break;
>> > + /* FIXME **more types** */
>> > + default:
>> > +    abort();
>> > + }
>> > + ch = skipws();
>> > + if (ch == '\n' || ch == ';' || ch == EOF)
>> > +    break;
>> > + ungetch(ch);
>> > +    }
>> > +}
>> > +
>> >  static void
>> >  dot(void)
>> >  {
>> > @@ -4086,6 +4124,8 @@ main(int argc, char *argv[])
>> >      optind = 1;
>> >  #endif
>> >
>> > +    obstack_init (obstack);
>> > +
>> >      progname = argv[0];
>> >
>> >      init_jit(progname);
>> > @@ -4344,5 +4384,7 @@ main(int argc, char *argv[])
>> >
>> >      finish_jit();
>> >
>> > +    obstack_free (obstack, NULL);
>> > +
>> >      return (0);
>> >  }
>> > diff --git a/gnulib-lib/.gitignore b/gnulib-lib/.gitignore
>> > index d9f5394..9d61cde 100644
>> > --- a/gnulib-lib/.gitignore
>> > +++ b/gnulib-lib/.gitignore
>> > @@ -1,2 +1,18 @@
>> >  /Makefile.am
>> > -/dummy.c
>> > +/_Noreturn.h
>> > +/alignof.h
>> > +/arg-nonnull.h
>> > +/c++defs.h
>> > +/exitfail.c
>> > +/exitfail.h
>> > +/gettext.h
>> > +/limits.in.h
>> > +/obstack.c
>> > +/obstack.h
>> > +/stddef.in.h
>> > +/stdint.in.h
>> > +/stdlib.in.h
>> > +/sys_types.in.h
>> > +/unistd.c
>> > +/unistd.in.h
>> > +/warn-on-use.h
>> > diff --git a/include/lightning.h.in b/include/lightning.h.in
>> > index 887a951..a7186a7 100644
>> > --- a/include/lightning.h.in
>> > +++ b/include/lightning.h.in
>> > @@ -187,6 +187,8 @@ typedef enum {
>> >  #define jit_align(u) jit_new_node_w(jit_code_align, u)
>> >      jit_code_live, jit_code_align,
>> >      jit_code_save, jit_code_load,
>> > +#define jit_embed(u,v)          jit_new_node_pl(jit_code_embed,u,v)
>> > +    jit_code_embed,
>> >  #define jit_name(u) _jit_name(_jit,u)
>> >      jit_code_name,
>> >  #define jit_note(u, v) _jit_note(_jit, u, v)
>> > @@ -1096,6 +1098,9 @@ extern jit_node_t *_jit_new_node_pwf(jit_state_t*, 
>> > jit_code_t,
>> >  #define jit_new_node_pwd(c,u,v,w) _jit_new_node_pwd(_jit,c,u,v,w)
>> >  extern jit_node_t *_jit_new_node_pwd(jit_state_t*, jit_code_t,
>> >       jit_pointer_t, jit_word_t, jit_float64_t);
>> > +#define jit_new_node_pl(c,u,v)    _jit_new_node_pl(_jit,c,u,v)
>> > +extern jit_node_t *_jit_new_node_pl(jit_state_t*, jit_code_t,
>> > +    jit_pointer_t, jit_uint32_t);
>> >
>> >  #define jit_arg_register_p(u) _jit_arg_register_p(_jit,u)
>> >  extern jit_bool_t _jit_arg_register_p(jit_state_t*, jit_node_t*);
>> > diff --git a/include/lightning/jit_private.h 
>> > b/include/lightning/jit_private.h
>> > index 0af24cb..97822e2 100644
>> > --- a/include/lightning/jit_private.h
>> > +++ b/include/lightning/jit_private.h
>> > @@ -276,6 +276,7 @@ extern jit_node_t *_jit_data(jit_state_t*, const void*,
>> >  #define jit_cc_a2_int 0x00100000 /* arg2 is immediate word */
>> >  #define jit_cc_a2_flt 0x00200000 /* arg2 is immediate float */
>> >  #define jit_cc_a2_dbl 0x00400000 /* arg2 is immediate double */
>> > +#define jit_cc_a1_len           0x00800000 /* arg1 is an immediate uint 
>> > length */
>> >
>> >  #if __ia64__ || (__sparc__ && __WORDSIZE == 64)
>> >  extern void
>> > @@ -381,6 +382,7 @@ union jit_data {
>> >      jit_float64_t d;
>> >      jit_pointer_t p;
>> >      jit_node_t *n;
>> > +    jit_uint32_t         l;
>> >  };
>> >
>> >  struct jit_note {
>> > diff --git a/lib/jit_names.c b/lib/jit_names.c
>> > index ebd3d56..69ae274 100644
>> > --- a/lib/jit_names.c
>> > +++ b/lib/jit_names.c
>> > @@ -21,6 +21,7 @@ static char *code_name[] = {
>> >      "data",
>> >      "live", "align",
>> >      "save", "load",
>> > +    "embed",
>> >      "#name", "#note",
>> >      "label",
>> >      "prolog",
>> > diff --git a/lib/jit_print.c b/lib/jit_print.c
>> > index 61d9650..b9b3ece 100644
>> > --- a/lib/jit_print.c
>> > +++ b/lib/jit_print.c
>> > @@ -107,7 +107,7 @@ _jit_print_node(jit_state_t *_jit, jit_node_t *node)
>> >   (jit_cc_a0_int|jit_cc_a0_flt|jit_cc_a0_dbl|jit_cc_a0_jmp|
>> >   jit_cc_a0_reg|jit_cc_a0_rlh|jit_cc_a0_arg|
>> >   jit_cc_a1_reg|jit_cc_a1_int|jit_cc_a1_flt|jit_cc_a1_dbl|jit_cc_a1_arg|
>> > - jit_cc_a2_reg|jit_cc_a2_int|jit_cc_a2_flt|jit_cc_a2_dbl);
>> > + jit_cc_a2_reg|jit_cc_a2_int|jit_cc_a2_flt|jit_cc_a2_dbl|jit_cc_a1_len);
>> >      if (!(node->flag & jit_flag_synth) && ((value & jit_cc_a0_jmp) ||
>> >     node->code == jit_code_finishr ||
>> >     node->code == jit_code_finishi))
>> > @@ -289,6 +289,10 @@ _jit_print_node(jit_state_t *_jit, jit_node_t *node)
>> >      else
>> >   print_flt(node->w.d);
>> >      return;
>> > +        l:
>> > +    print_chr(' '); print_ptr(node->u.p);
>> > +    print_chr(' '); print_dec(node->v.l);
>> > +    return;
>> >   case jit_code_name:
>> >      print_chr(' ');
>> >      if (node->v.p && _jitc->emit)
>> > @@ -371,7 +375,9 @@ _jit_print_node(jit_state_t *_jit, jit_node_t *node)
>> >      goto n_r_f;
>> >   case jit_cc_a0_jmp|jit_cc_a1_reg|jit_cc_a2_dbl:
>> >      goto n_r_d;
>> > - default:
>> > +        case jit_cc_a1_len:
>> > +    goto l;
>> > +        default:
>> >      abort();
>> >      }
>> >      break;
>> > diff --git a/lib/jit_x86.c b/lib/jit_x86.c
>> > index e3e1383..b650f7f 100644
>> > --- a/lib/jit_x86.c
>> > +++ b/lib/jit_x86.c
>> > @@ -1598,6 +1598,11 @@ _emit_code(jit_state_t *_jit)
>> >   if ((word = _jit->pc.w & (node->u.w - 1)))
>> >      nop(node->u.w - word);
>> >   break;
>> > +    case jit_code_embed:
>> > + assert(node->v.l <= jit_get_max_instr());
>> > + jit_memcpy(_jit->pc.uc, node->u.p, node->v.l);
>> > + _jit->pc.uc += node->v.l;
>> > + break;
>> >      case jit_code_note: case jit_code_name:
>> >   node->u.w = _jit->pc.w;
>> >   break;
>> > diff --git a/lib/lightning.c b/lib/lightning.c
>> > index b78bd07..374aa32 100644
>> > --- a/lib/lightning.c
>> > +++ b/lib/lightning.c
>> > @@ -1198,6 +1198,17 @@ _jit_new_node_pwd(jit_state_t *_jit, jit_code_t 
>> > code,
>> >      return (link_node(node));
>> >  }
>> >
>> > +jit_node_t *
>> > +_jit_new_node_pl(jit_state_t *_jit, jit_code_t code,
>> > + jit_pointer_t u, jit_uint32_t v)
>> > +{
>> > +    jit_node_t *node = new_node(code);
>> > +    assert(!_jitc->realize);
>> > +    node->u.p = u;
>> > +    node->v.l = v;
>> > +    return (link_node(node));
>> > +}
>> > +
>> >  jit_node_t *
>> >  _jit_label(jit_state_t *_jit)
>> >  {
>> > @@ -1316,6 +1327,9 @@ _jit_classify(jit_state_t *_jit, jit_code_t code)
>> >   case jit_code_finishi: /* synthesized will set jit_cc_a0_jmp */
>> >      mask = jit_cc_a0_int;
>> >      break;
>> > +        case jit_code_embed:
>> > +    mask = jit_cc_a1_len;
>> > +    break;
>> >   case jit_code_reti_f: case jit_code_pushargi_f:
>> >      mask = jit_cc_a0_flt;
>> >      break;
>> > diff --git a/m4/.gitignore b/m4/.gitignore
>> > index 24e2f3f..870b024 100644
>> > --- a/m4/.gitignore
>> > +++ b/m4/.gitignore
>> > @@ -8,3 +8,21 @@
>> >  /gnulib-comp.m4
>> >  /gnulib-tool.m4
>> >  /zzgnulib.m4
>> > +/absolute-header.m4
>> > +/extensions.m4
>> > +/extern-inline.m4
>> > +/include_next.m4
>> > +/limits-h.m4
>> > +/multiarch.m4
>> > +/obstack.m4
>> > +/off_t.m4
>> > +/pid_t.m4
>> > +/ssize_t.m4
>> > +/stddef_h.m4
>> > +/stdint.m4
>> > +/stdlib_h.m4
>> > +/sys_types_h.m4
>> > +/unistd_h.m4
>> > +/warn-on-use.m4
>> > +/wchar_t.m4
>> > +/wint_t.m4
>> > diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4
>> > index 45be7ba..2a2d48b 100644
>> > --- a/m4/gnulib-cache.m4
>> > +++ b/m4/gnulib-cache.m4
>> > @@ -36,12 +36,13 @@
>> >  #  --aux-dir=build-aux \
>> >  #  --no-conditional-dependencies \
>> >  #  --libtool \
>> > -#  --macro-prefix=gl
>> > +#  --macro-prefix=gl \
>> > +#  obstack
>> >
>> >  # Specification in the form of a few gnulib-tool.m4 macro invocations:
>> >  gl_LOCAL_DIR([gl])
>> >  gl_MODULES([
>> > -
>> > +  obstack
>> >  ])
>> >  gl_AVOID([])
>> >  gl_SOURCE_BASE([gnulib-lib])



reply via email to

[Prev in Thread] Current Thread [Next in Thread]