guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] 36/437: update manual for jit_allocai


From: Andy Wingo
Subject: [Guile-commits] 36/437: update manual for jit_allocai
Date: Mon, 2 Jul 2018 05:13:40 -0400 (EDT)

wingo pushed a commit to branch lightning
in repository guile.

commit f748b3c5e76a2fe87cf4cf906335c55499fded3b
Author: Paolo Bonzini <address@hidden>
Date:   Mon Nov 20 12:59:13 2006 +0000

    update manual for jit_allocai
    
    git-archimport-id: address@hidden/lightning--stable--1.2--patch-38
---
 NEWS             |   4 ++
 doc/porting.texi |  12 ++----
 doc/using.texi   | 123 ++++++++++++++++++++++++++++++++++++++-----------------
 3 files changed, 92 insertions(+), 47 deletions(-)

diff --git a/NEWS b/NEWS
index 9292f12..e6e7d9f 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,10 @@ o   Initial support for x86-64 back-end.
 
 o   Many bug fixes.
 
+o   jit_pushr/jit_popr are deprecated, you need to #define
+    JIT_NEED_PUSH_POP prior to including lightning.h if you
+    want to use them.
+
 o   Support for stack-allocated variables.  Because of this,
     backends defining JIT_FP should now rename it to JIT_AP.
     JIT_FP is now a user-visible register used in ldxi/ldxr
diff --git a/doc/porting.texi b/doc/porting.texi
index 4608587..1cc2a11 100644
--- a/doc/porting.texi
+++ b/doc/porting.texi
@@ -858,7 +858,7 @@ operations:
 @section Macros composing the platform-independent layer
 
 @table @b
address@hidden Register names (all mandatory but the last two)
address@hidden Register names (all mandatory but the last three)
 @example
 #define JIT_R
 #define JIT_R_NUM
@@ -866,6 +866,7 @@ operations:
 #define JIT_V_NUM
 #define JIT_FPR
 #define JIT_FPR_NUM
+#define JIT_FP
 #define JIT_SP
 #define JIT_AP
 #define JIT_RZERO
@@ -878,6 +879,7 @@ operations:
 
 @item Mandatory:
 @example
+#define jit_allocai()
 #define jit_arg_c()
 #define jit_arg_i()
 #define jit_arg_l()
@@ -1022,11 +1024,9 @@ operations:
 #define jit_orr_i(d, s1, s2)
 #define jit_patch_at(jump_pc, value)
 #define jit_patch_movi(jump_pc, value)
-#define jit_pop_i(rs)
 #define jit_prepare_d(numargs)
 #define jit_prepare_f(numargs)
 #define jit_prepare_i(numargs)
-#define jit_push_i(rs)
 #define jit_pusharg_i(rs)
 #define jit_ret()
 #define jit_retval_i(rd)
@@ -1242,10 +1242,6 @@ operations:
 #define jit_ori_ul(d, rs, is)
 #define jit_orr_ui(d, s1, s2)
 #define jit_orr_ul(d, s1, s2)
-#define jit_pop_ui(rs)
-#define jit_pop_ul(rs)
-#define jit_push_ui(rs)
-#define jit_push_ul(rs)
 #define jit_pusharg_c(rs)
 #define jit_pusharg_p(rs)
 #define jit_pusharg_s(rs)
@@ -1478,8 +1474,6 @@ operations:
 #define jit_ner_l(d, s1, s2)
 #define jit_ori_l(d, rs, is)
 #define jit_orr_l(d, s1, s2)
-#define jit_pop_l(rs)
-#define jit_push_l(rs)
 #define jit_pusharg_l(rs)
 #define jit_retval_l(rd)
 #define jit_rshi_l(d, rs, is)
diff --git a/doc/using.texi b/doc/using.texi
index 3a8578a..af13901 100644
--- a/doc/using.texi
+++ b/doc/using.texi
@@ -90,10 +90,9 @@ is equivalent to @code{i} on 32-bit machines, and @code{p} is
 substantially equivalent to @code{ul}).
 
 There are at least seven integer registers, of which six are
-general-purpose, while the last is used to contain the stack pointer
-(@code{SP}).  The stack pointer can be used to allocate and access local
-variables on the stack (which is supposed to grow downwards in memory
-on all architectures).
+general-purpose, while the last is used to contain the frame pointer
+(@code{FP}).  The frame pointer can be used to allocate and access local
+variables on the stack, using the @code{allocai} instruction.
 
 Of the general-purpose registers, at least three are guaranteed to be
 preserved across function calls (@code{V0}, @code{V1} and
@@ -271,15 +270,6 @@ stxr    c  uc  s  us  i  ui  l  ul  p  f  d  *(O1+O2) = O3
 stxi    c  uc  s  us  i  ui  l  ul  p  f  d  *(O1+O2) = O3
 @end example
 
address@hidden Stack management
-These accept a single register parameter.  These operations are not
-guaranteed to be efficient on all architectures.
-
address@hidden
-pushr                     i  ui  l  ul  p   @r{push address@hidden on the 
stack}
-popr                      i  ui  l  ul  p   @r{pop address@hidden off the 
stack}
address@hidden example
-
 @item Argument management
 These are:
 @example
@@ -388,16 +378,13 @@ These accept one argument except @code{ret} which has 
none; the
 difference between @code{finish} and @code{calli} is that the
 latter does not clean the stack from pushed parameters (if any)
 and the former must @strong{always} follow a @code{prepare}
-instruction.  Results are undefined when using function calls
-in a leaf function.
+instruction.
 @example
 calli     (not specified)                  @r{function call to O1}
 callr     (not specified)                  @r{function call to a register}
 finish    (not specified)                  @r{function call to O1}
 finishr   (not specified)                  @r{function call to a register}
 jmpi/jmpr (not specified)                  @r{unconditional jump to O1}
-prolog    (not specified)                  @r{function prolog for O1 args}
-leaf      (not specified)                  @r{the same for leaf functions}
 ret       (not specified)                  @r{return from subroutine}
 retval    c  uc s  us i  ui l  ul p  f  d  @r{move return value}
                                            @r{to register}
@@ -407,6 +394,26 @@ Like branch instruction, @code{jmpi} also returns a value 
which is to
 be used to compile forward branches. @xref{Fibonacci, , Fibonacci
 numbers}.
 
address@hidden Function prolog
+
+These macros are used to set up the function prolog, in particular to
+declare the number of arguments accepted by a function, and to reserve
+space on the stack to be used for variables.  They accept a single
+numeric argument.
+
address@hidden
+prolog    (not specified)                  @r{function prolog for O1 args}
+leaf      (not specified)                  @r{the same for leaf functions}
+allocai   (not specified)                  @r{reserve space on the stack}
address@hidden example
+
+Results are undefined when using function calls in a leaf function.
+
address@hidden receives the number of bytes to allocate and returns
+the offset from the frame pointer register @code{FP} to the base of
+the area.  The area is aligned to an @code{int}; future versions of
address@hidden may provide more fine-grained control on the alignment of
+stack-allocated variables.
 @end table
 
 As a small appetizer, here is a small function that adds 1 to the input
@@ -740,39 +747,72 @@ and is able to compile different formulas to different 
functions.
 Here is the code for the expression compiler; a sample usage will
 follow.
 
+Since @lightning{} does not provide push/pop instruction, this
+example uses a stack-allocated area to store the data.  Such an
+area can be allocated using the macro @code{jit_allocai}, which
+receives the number of bytes to allocate and returns the offset
+from the frame pointer register @code{JIT_FP} to the base of the
+area.  The area is aligned to an @code{int}; future versions
+of @lightning{} may provide more fine-grained control on the
+alignment of stack-allocated variables.
+
+Usually, you will use the @code{ldxi} and @code{stxi} instruction
+to access stack-allocated variables.  However, it is possible to
+use operations such as @code{add} to compute the address of the
+variables, and pass the address around.
+
 @example
 #include <stdio.h>
 #include "lightning.h"
 
 typedef int (*pifi)(int);       @rem{/* Pointer to Int Function of Int */}
 
+void stack_push(int reg, int *sp)
+{
+  jit_stxi_i (*sp, JIT_FP, reg);
+  *sp += sizeof (int);
+}
+
+void stack_pop(int reg, int *sp)
+{
+  *sp -= sizeof (int);
+  jit_ldxi_i (reg, JIT_FP, *sp);
+}
+
 pifi compile_rpn(char *expr)
 @{
   pifi fn;
+  int stack_base, stack_ptr;
   int in;
+
   fn = (pifi) (jit_get_ip().iptr);
   jit_leaf(1);
   in = jit_arg_i();
-  jit_getarg_i(JIT_R0, in);
+  stack_ptr = stack_base = jit_allocai (32 * sizeof (int));
+
+  jit_getarg_i(JIT_R2, in);
 
   while (*expr) @{
     char buf[32];
     int n;
     if (sscanf(expr, "%[0-9]%n", buf, &n)) @{
       expr += n - 1;
-      jit_push_i(JIT_R0);
+      stack_push(JIT_R0, &stack_ptr);
       jit_movi_i(JIT_R0, atoi(buf));
+    @} else if (*expr == 'x') @{
+      stack_push(JIT_R0, &stack_ptr);
+      jit_movi_i(JIT_R0, JIT_R2);
     @} else if (*expr == '+') @{
-      jit_pop_i(JIT_R1);
+      stack_pop(JIT_R1, &stack_ptr);
       jit_addr_i(JIT_R0, JIT_R1, JIT_R0);
     @} else if (*expr == '-') @{
-      jit_pop_i(JIT_R1);
+      stack_pop(JIT_R1, &stack_ptr);
       jit_subr_i(JIT_R0, JIT_R1, JIT_R0);
     @} else if (*expr == '*') @{
-      jit_pop_i(JIT_R1);
+      stack_pop(JIT_R1, &stack_ptr);
       jit_mulr_i(JIT_R0, JIT_R1, JIT_R0);
     @} else if (*expr == '/') @{
-      jit_pop_i(JIT_R1);
+      stack_pop(JIT_R1, &stack_ptr);
       jit_divr_i(JIT_R0, JIT_R1, JIT_R0);
     @} else @{
       fprintf(stderr, "cannot compile: %s\n", expr);
@@ -786,13 +826,20 @@ pifi compile_rpn(char *expr)
 @}
 @end example
 
-The principle on which the calculator is based is easy: the stack
-top is held in R0, while the remaining items of the stack are held
-on the hardware stack.  Compiling an operand pushes the old stack
-top onto the stack and moves the operand into R0; compiling an
-operator pops the second operand off the stack into R1, and
-compiles the operation so that the result goes into R0, thus
-becoming the new stack top.
+The principle on which the calculator is based is easy: the stack top
+is held in R0, while the remaining items of the stack are held in the
+memory area that we allocate with @code{allocai}.  Compiling a numeric
+operand or the argument @code{x} pushes the old stack top onto the
+stack and moves the operand into R0; compiling an operator pops the
+second operand off the stack into R1, and compiles the operation so
+that the result goes into R0, thus becoming the new stack top.
+
+This example allocates a fixed area for 32 @code{int}s.  This is not
+a problem when the function is a leaf like in this case; in a full-blown
+compiler you will want to analyze the input and determine the number
+of needed stack slots---a very simple example of register allocation.
+The area is then managed like a stack using @code{stack_push} and
address@hidden
 
 Try to locate a call to @code{jit_set_ip} in the source code.  You
 will not find one; this means that the client has to manually set
@@ -814,8 +861,8 @@ int main()
   int i;
 
   jit_set_ip(codeBuffer);
-  c2f = compile_rpn("9*5/32+");
-  f2c = compile_rpn("32-5*9/");
+  c2f = compile_rpn("32x9*5/+");
+  f2c = compile_rpn("x32-5*9/");
   jit_flush_code(codeBuffer, jit_get_ip().ptr);
 
   printf("\nC:");
@@ -845,9 +892,9 @@ generation so powerful.
 
 The @file{rpn.c} file in the @lightning{} distribution includes a more
 complete (and more complex) implementation of @code{compile_rpn},
-which does constant folding, allows the argument to the functions
-to be used more than once, and is able to assemble instructions with
-an immediate parameter.
+which does constant folding and is able to assemble instructions with
+an immediate parameter.  Still, it is based on the same principle and
+also uses @code{allocai} to allocate space for the stack.
 
 @node Fibonacci
 @section Fibonacci numbers
@@ -1160,9 +1207,9 @@ extern void _opt_muli_i(struct jit_state *, int, int, 
int);
 @section Registers
 @chapter Accessing the whole register file
 
-As mentioned earlier in this chapter, all @lightning{} back-ends
-are guaranteed to have at least six integer registers and six
-floating-point registers, but many back-ends will have more.
+As mentioned earlier in this chapter, all @lightning{} back-ends are
+guaranteed to have at least six general-purpose integer registers and
+six floating-point registers, but many back-ends will have more.
 
 To access the entire register files, you can use the
 @code{JIT_R}, @code{JIT_V} and @code{JIT_FPR} macros.  They



reply via email to

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