Exemplo n.º 1
0
jit_node_t *compile_rpn(char *expr)
{
  jit_node_t *in, *fn;
  int stack_base, stack_ptr;

  fn = jit_note(NULL, 0);
  jit_prolog();
  in = jit_arg();
  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;
      stack_push(JIT_R0, &stack_ptr);
      jit_movi(JIT_R0, atoi(buf));
    } else if (*expr == 'x') {
      stack_push(JIT_R0, &stack_ptr);
      jit_movr(JIT_R0, JIT_R2);
    } else if (*expr == '+') {
      stack_pop(JIT_R1, &stack_ptr);
      jit_addr(JIT_R0, JIT_R1, JIT_R0);
    } else if (*expr == '-') {
      stack_pop(JIT_R1, &stack_ptr);
      jit_subr(JIT_R0, JIT_R1, JIT_R0);
    } else if (*expr == '*') {
      stack_pop(JIT_R1, &stack_ptr);
      jit_mulr(JIT_R0, JIT_R1, JIT_R0);
    } else if (*expr == '/') {
      stack_pop(JIT_R1, &stack_ptr);
      jit_divr(JIT_R0, JIT_R1, JIT_R0);
    } else {
      fprintf(stderr, "cannot compile: %s\n", expr);
      abort();
    }
    ++expr;
  }
  jit_retr(JIT_R0);
  jit_epilog();
  return fn;
}
Exemplo n.º 2
0
    bool compile(const Program &program, Translator &trans, Environment &env) {
        jit_node_t *ref;        
        jit_node_t *fn = jit_note(NULL, 0);
        jit_prolog();
        const int stack_base_offset = jit_allocai(32 * sizeof(double));
        int stack_top_idx = 0;

        auto &&stackPush = [&](int reg) {
            jit_stxi_d(stack_base_offset + stack_top_idx * sizeof(double), JIT_FP, reg);
            ++stack_top_idx;
        };
        
        auto &&stackPop = [&](int reg) {
            --stack_top_idx;
            jit_ldxi_d(reg, JIT_FP, stack_base_offset + stack_top_idx * sizeof(double));
            return reg;
        };

        size_t pc = 0;
        const size_t progsz = program.size();
        while (pc < progsz) {
            const Instruction &instr = program[pc];
            switch (instr.op) {
            case OP_NOP:
                break;
            case OP_PUSH:
                stackPush(JIT_F0);
                jit_movi_d(JIT_F0, instr.dval);
                break;
            case OP_ADD: {
                const int reg = stackPop(JIT_F1);
                jit_addr_d(JIT_F0, reg, JIT_F0);
            }
                break;
            case OP_SUB: {
                const int reg = stackPop(JIT_F1);
                jit_subr_d(JIT_F0, reg, JIT_F0);
            }
                break;
            case OP_MUL: {
                const int reg = stackPop(JIT_F1);
                jit_mulr_d(JIT_F0, reg, JIT_F0);
            }
                break;
            case OP_DIV: {
                const int reg = stackPop(JIT_F1);
                jit_divr_d(JIT_F0, reg, JIT_F0);                
            }
                break;
            case OP_CALL: {
                stackPush(JIT_F0);
                const int sp = stack_top_idx - (instr.callop.nargs);
                jit_addi(JIT_R0, JIT_FP, stack_base_offset + sp * sizeof(double));
                
                jit_prepare();
                jit_pushargi((jit_word_t)&env);    // 1st arg: userdata
                jit_pushargi(instr.callop.nargs);  // 2nd arg: # of arguments
                jit_pushargr(JIT_R0);              // 3rd arg: pointer to args on stack
                jit_pushargi((jit_word_t)&error_); // 4th arg: pointer to error message

                auto &&cb = trans.lookup(instr.callop.fidx);
                jit_finishi(reinterpret_cast<jit_pointer_t>(cb));

                stack_top_idx -= instr.callop.nargs; // consume arguments on stack
                jit_retval_d(JIT_F0);
                jit_retval(JIT_R0);

                ref = jit_bnei(JIT_R0, 0);
                jit_reti_d(*reinterpret_cast<const double*>(&JIT_ERROR));
                jit_patch(ref);
            }
                break;
            }

            ++pc;
        }

        jit_retr_d(JIT_F0);
        jit_epilog();

        (void)jit_emit();
        func_ = reinterpret_cast<JitFunction>(jit_address(fn));
        
        return true;
    }
Exemplo n.º 3
0
// reserve space on the stack
jit::imm32 jit::allocai (imm32 n) { return jit_allocai (n); }
Exemplo n.º 4
0
Arquivo: rpn.c Projeto: pcpa/lightning
/* This function does all of lexing, parsing, and picking a good
   order of evaluation...  Needless to say, this is not the best
   possible design, but it avoids cluttering everything with globals. */
pifi
compile_rpn (char *expr)
{
  struct stack_element stack[32];
  int sp = 0;
  int curr_tos = -1;		/* stack element currently in R0 */
  int spill_base, spill_sp;

  pifi fn;
  int ofs;
  fn = (pifi) (jit_get_ip ().iptr);
  jit_leaf (1);
  ofs = jit_arg_i ();

  spill_sp = spill_base = jit_allocai (32 * sizeof (int));

  while (*expr)
    {
      int with_imm;
      int imm;
      int tok;
      int src1, src2;

      /* This is the lexer.  */
      switch (*expr)
	{
	case ' ': case '\t':
	  expr++;
	  continue;

	case '0': case '1': case '2': case '3': case '4':
	case '5': case '6': case '7': case '8': case '9':
	  stack[sp].kind = IMM;
	  stack[sp++].imm = strtol (expr, &expr, 0);
	  continue;

	case 'x':
	  expr++;
	  stack[sp++].kind = ARG;
	  continue;

	case '~':
	  /* NOT.  Implemented as a XOR with -1.  */
	  stack[sp].kind = IMM;
	  stack[sp++].imm = ~0;
	  tok = '^';
	  break;

	case '_':
	  /* Unary minus.  Transform to 0 - X and go on.
	     Also used to enter negative constants (32_ = -32).  */
	  expr++;
	  stack[sp] = stack[sp - 1];

	  /* Ensure CURR_TOS is correct.  */
	  if (curr_tos == sp - 1)
	    curr_tos = sp;

	  stack[sp - 1].kind = IMM;
	  stack[sp - 1].imm = 0;
	  sp++;
	  tok = '-';
	  break;

	case '+':
	case '-':
	case '*':
	case '/':
	case '%':
	case '&':
	case '|':
	case '^':
	case '=':
	  tok = *expr++;
	  break;

	case '!':
	  /* Get != */
	  expr++;
	  assert (*expr == '=');
	  tok = NE;
	  break;

	case '<':
	  /* Get <, <<, <= */
	  if (expr[1] == '=')
	    expr += 2, tok = LE;
	  else if (expr[1] == '<')
	    expr += 2, tok = LSH;
	  else
	    expr++, tok = '<';
	  break;

	case '>':
	  /* Get >, >>, >>>, >= */
	  if (expr[1] == '=')
	    expr += 2, tok = GE;
	  else if (expr[1] == '>' && expr[2] == '>')
	    expr += 3, tok = RSHU;
	  else if (expr[1] == '>')
	    expr += 2, tok = RSH;
	  else
	    expr++, tok = '>';
	  break;

	default:
	  abort ();
	}

      assert (sp >= 2);

      /* Constant folding.  */
      if (stack[sp - 1].kind == IMM && stack[sp - 2].kind == IMM)
	{
	  stack[sp - 2].imm =
	    fold (stack[sp - 2].imm, stack[sp - 1].imm, tok);
	  sp--;
	  continue;
	}

      /* If possible, ensure that the constant is the RHS, possibly
	 by changing TOK (if it is a comparison).  */
      if (stack[sp - 2].kind == IMM)
	{
	  int swapped_operation = swap_op (tok);
          if (swapped_operation)
	    {
	      tok = swapped_operation;
	      stack[sp - 2].kind = stack[sp - 1].kind;
	      stack[sp - 1].kind = IMM;
	      stack[sp - 1].imm = stack[sp - 2].imm;

	      /* Ensure CURR_TOS is correct.  */
	      if (curr_tos == sp - 1)
	        curr_tos = sp - 2;
	    }
        }

      /* Get the second argument into a register, if not an immediate.
         Also decide which argument will be prepared into JIT_R0 and
         which will be prepared into JIT_V0.  */
      with_imm = 0;
      src1 = JIT_R0;
      src2 = JIT_V0;
      switch (stack[sp - 1].kind)
	{
	case IMM:
	  /* RHS is an immediate, use an immediate instruction.  */
	  with_imm = 1;
	  imm = stack[sp - 1].imm;
	  break;

	case EXPR:
	  /* RHS is an expression, check if it is already in JIT_R0.  */
	  if (curr_tos == sp - 1)
	    {
	      /* Invert the two sources.  */
	      src1 = JIT_V0;
	      src2 = JIT_R0;
	    }
	  else
	    popr (JIT_V0, &spill_sp);

	  curr_tos = -1;
	  break;

	case ARG:
	  jit_getarg_i (JIT_V0, ofs);
	  break;
	}

      /* Get the first argument into a register indicated by SRC1.  */
      switch (stack[sp - 2].kind)
	{
	case IMM:
	  /* LHS is an immediate, check if we must spill the top of stack.  */
	  if (curr_tos != -1)
	    {
	      pushr (JIT_R0, &spill_sp);
	      curr_tos = -1;
	    }

	  jit_movi_i (src1, stack[sp - 2].imm);
	  break;

	case EXPR:
	  /* LHS is an expression, check if it is already in JIT_R0.  */
	  if (curr_tos != sp - 2)
	    {
	      popr (src1, &spill_sp);
	      curr_tos = -1;
	    }
	  else
	    assert (src1 == JIT_R0);
	  break;

	case ARG:
	  if (curr_tos != -1)
	    {
	      pushr (JIT_R0, &spill_sp);
	      curr_tos = -1;
	    }

	  jit_getarg_i (src1, ofs);
	  break;
	}

      /* Set up the new stack entry, which is cached in R0.  */
      sp -= 2;
      curr_tos = sp;
      stack[sp++].kind = EXPR;

      /* Perform the computation.  */
      if (with_imm)
	gen_reg_imm (src1, imm, tok);
      else
	gen_reg_reg (src1, src2, tok);
    }

  assert (sp == 1);
  switch (stack[0].kind)
    {
    case IMM:
      jit_movi_i (JIT_RET, stack[0].imm);
      break;

    case EXPR:
      assert (curr_tos == 0);
      jit_movr_i (JIT_RET, JIT_R0);
      break;

    case ARG:
      jit_getarg_i (JIT_V0, ofs);
      break;
    }

  jit_ret ();
  jit_flush_code ((char *) fn, jit_get_ip ().ptr);

#ifdef LIGHTNING_DISASSEMBLE
  disassemble (stderr, (char *) fn, jit_get_ip ().ptr);
#endif
  return fn;
}