aboutsummaryrefslogtreecommitdiff
path: root/lcode.c
blob: c6162f6f2fb94b59ff8ca666f911cf9391ac35a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
** $Id: $
** Code generator for Lua
** See Copyright Notice in lua.h
*/


#include "lcode.h"
#include "llex.h"
#include "lmem.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lparser.h"


static Instruction *last_i (FuncState *fs) {
  static Instruction dummy = SET_OPCODE(0, ENDCODE);
  if (fs->last_pc < 0)
    return &dummy;
  else
    return &fs->f->code[fs->last_pc];
}


int luaK_primitivecode (LexState *ls, Instruction i) {
  FuncState *fs = ls->fs;
  luaM_growvector(ls->L, fs->f->code, fs->pc, 1, Instruction, codeEM, MAXARG_S);
  fs->f->code[fs->pc] = i;
  return fs->pc++;
}



int luaK_code (LexState *ls, Instruction i) {
  FuncState *fs = ls->fs;
  Instruction *last = last_i(fs);
  switch (GET_OPCODE(i)) {

    case MINUSOP:
      switch(GET_OPCODE(*last)) {
        case PUSHINT: *last = SETARG_S(*last, -GETARG_S(*last)); break;
        case PUSHNUM: *last = SET_OPCODE(*last, PUSHNEGNUM); break;
        case PUSHNEGNUM: *last = SET_OPCODE(*last, PUSHNUM); break;
        default: fs->last_pc = luaK_primitivecode(ls, i);
      }
      break;

    case GETTABLE:
      switch(GET_OPCODE(*last)) {
        case PUSHSTRING: *last = SET_OPCODE(*last, GETDOTTED); break;
        default: fs->last_pc = luaK_primitivecode(ls, i);
      }
      break;

    case RETCODE:
      switch(GET_OPCODE(*last)) {
        case CALL:
          *last = SET_OPCODE(*last, TAILCALL);
          *last = SETARG_B(*last, GETARG_U(i));
          break;
        default: fs->last_pc = luaK_primitivecode(ls, i);
      }
      break;

    case ADDOP:
      switch(GET_OPCODE(*last)) {
        case PUSHINT: *last = SET_OPCODE(*last, ADDI); break;
        default: fs->last_pc = luaK_primitivecode(ls, i);
      }
      break;

    case SUBOP:
      switch(GET_OPCODE(*last)) {
        case PUSHINT:
          *last = SET_OPCODE(*last, ADDI);
          *last = SETARG_S(*last, -GETARG_S(*last));
          break;
        default: fs->last_pc = luaK_primitivecode(ls, i);
      }
      break;

    default: fs->last_pc = luaK_primitivecode(ls, i);
  }
  return fs->last_pc;
}


void luaK_fixjump (LexState *ls, int pc, int dest) {
  FuncState *fs = ls->fs;
  Instruction *jmp = &fs->f->code[pc];
  /* jump is relative to position following jump instruction */
  *jmp = SETARG_S(*jmp, dest-(pc+1));
  fs->last_pc = pc;
}