ByteCode.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #define EMIT_DEBUG_OPS
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading;
  9. using MoonSharp.Interpreter.DataStructs;
  10. namespace MoonSharp.Interpreter.Execution.VM
  11. {
  12. public class ByteCode : ITrackableReference
  13. {
  14. public List<Instruction> Code = new List<Instruction>();
  15. internal LoopTracker LoopTracker = new LoopTracker();
  16. #region ITrackableReference
  17. static int s_RefIDCounter = 0;
  18. private int m_RefID = Interlocked.Increment(ref s_RefIDCounter);
  19. public int ReferenceID { get { return m_RefID; } }
  20. #endregion
  21. public void Dump(string file)
  22. {
  23. StringBuilder sb = new StringBuilder();
  24. for (int i = 0; i < Code.Count; i++)
  25. {
  26. if (Code[i].OpCode == OpCode.Debug)
  27. sb.AppendFormat(" {0}\n", Code[i]);
  28. else
  29. sb.AppendFormat("{0:X8} {1}\n", i, Code[i]);
  30. }
  31. File.WriteAllText(file, sb.ToString());
  32. }
  33. public int GetJumpPointForNextInstruction()
  34. {
  35. return Code.Count;
  36. }
  37. public int GetJumpPointForLastInstruction()
  38. {
  39. return Code.Count - 1;
  40. }
  41. public Instruction GetLastInstruction()
  42. {
  43. return Code[Code.Count - 1];
  44. }
  45. private Instruction AppendInstruction(Instruction c)
  46. {
  47. Code.Add(c);
  48. return c;
  49. }
  50. public Instruction Emit_Nop(string comment)
  51. {
  52. return AppendInstruction(new Instruction() { OpCode = OpCode.Nop, Name = comment });
  53. }
  54. public Instruction Emit_Invalid(string type)
  55. {
  56. return AppendInstruction(new Instruction() { OpCode = OpCode.Invalid, Name = type });
  57. }
  58. public Instruction Emit_Pop(int num = 1)
  59. {
  60. return AppendInstruction(new Instruction() { OpCode = OpCode.Pop, NumVal = num });
  61. }
  62. public void Emit_Call(int argCount)
  63. {
  64. AppendInstruction(new Instruction() { OpCode = OpCode.Call, NumVal = argCount });
  65. }
  66. public Instruction Emit_Literal(DynValue value)
  67. {
  68. return AppendInstruction(new Instruction() { OpCode = OpCode.Literal, Value = value });
  69. }
  70. public Instruction Emit_Jump(OpCode jumpOpCode, int idx, int optPar = 0)
  71. {
  72. return AppendInstruction(new Instruction() { OpCode = jumpOpCode, NumVal = idx, NumVal2 = optPar });
  73. }
  74. public Instruction Emit_MkTuple(int cnt)
  75. {
  76. return AppendInstruction(new Instruction() { OpCode = OpCode.MkTuple, NumVal = cnt });
  77. }
  78. public Instruction Emit_Operator(OpCode opcode)
  79. {
  80. var i = AppendInstruction(new Instruction() { OpCode = opcode });
  81. if (opcode == OpCode.LessEq)
  82. AppendInstruction(new Instruction() { OpCode = OpCode.CNot });
  83. if (opcode == OpCode.Eq || opcode == OpCode.Less)
  84. AppendInstruction(new Instruction() { OpCode = OpCode.ToBool });
  85. return i;
  86. }
  87. //[Conditional("EMIT_DEBUG_OPS")]
  88. public void Emit_Debug(string str)
  89. {
  90. AppendInstruction(new Instruction() { OpCode = OpCode.Debug, Name = str.Substring(0, Math.Min(32, str.Length)) });
  91. }
  92. public Instruction Emit_Enter(RuntimeScopeBlock runtimeScopeBlock)
  93. {
  94. return AppendInstruction(new Instruction() { OpCode = OpCode.Enter, NumVal = runtimeScopeBlock.From, NumVal2 = runtimeScopeBlock.ToInclusive });
  95. }
  96. public Instruction Emit_Leave(RuntimeScopeBlock runtimeScopeBlock)
  97. {
  98. return AppendInstruction(new Instruction() { OpCode = OpCode.Leave, NumVal = runtimeScopeBlock.From, NumVal2 = runtimeScopeBlock.To });
  99. }
  100. public Instruction Emit_Exit(RuntimeScopeBlock runtimeScopeBlock)
  101. {
  102. return AppendInstruction(new Instruction() { OpCode = OpCode.Exit, NumVal = runtimeScopeBlock.From, NumVal2 = runtimeScopeBlock.ToInclusive });
  103. }
  104. public Instruction Emit_Closure(SymbolRef[] symbols, int jmpnum)
  105. {
  106. return AppendInstruction(new Instruction() { OpCode = OpCode.Closure, SymbolList = symbols, NumVal = jmpnum });
  107. }
  108. public Instruction Emit_Args(SymbolRef[] symbols)
  109. {
  110. return AppendInstruction(new Instruction() { OpCode = OpCode.Args, SymbolList = symbols });
  111. }
  112. public Instruction Emit_Ret(int retvals)
  113. {
  114. return AppendInstruction(new Instruction() { OpCode = OpCode.Ret, NumVal = retvals });
  115. }
  116. public Instruction Emit_ToNum(int stage = 0)
  117. {
  118. return AppendInstruction(new Instruction() { OpCode = OpCode.ToNum, NumVal = stage });
  119. }
  120. public Instruction Emit_Incr(int i)
  121. {
  122. return AppendInstruction(new Instruction() { OpCode = OpCode.Incr, NumVal = i });
  123. }
  124. public Instruction Emit_NewTable()
  125. {
  126. return AppendInstruction(new Instruction() { OpCode = OpCode.NewTable });
  127. }
  128. public Instruction Emit_IterPrep()
  129. {
  130. return AppendInstruction(new Instruction() { OpCode = OpCode.IterPrep });
  131. }
  132. public Instruction Emit_ExpTuple(int stackOffset)
  133. {
  134. return AppendInstruction(new Instruction() { OpCode = OpCode.ExpTuple, NumVal = stackOffset });
  135. }
  136. public Instruction Emit_IterUpd()
  137. {
  138. return AppendInstruction(new Instruction() { OpCode = OpCode.IterUpd });
  139. }
  140. public Instruction Emit_BeginFn(RuntimeScopeFrame m_StackFrame, string funcName)
  141. {
  142. return AppendInstruction(new Instruction()
  143. {
  144. OpCode = OpCode.BeginFn,
  145. SymbolList = m_StackFrame.DebugSymbols.ToArray(),
  146. NumVal = m_StackFrame.Count,
  147. NumVal2 = m_StackFrame.ToFirstBlock,
  148. Name = funcName
  149. });
  150. }
  151. public Instruction Emit_Scalar()
  152. {
  153. return AppendInstruction(new Instruction() { OpCode = OpCode.Scalar });
  154. }
  155. public int Emit_Load(SymbolRef sym)
  156. {
  157. switch (sym.Type)
  158. {
  159. case SymbolRefType.Global:
  160. Emit_Load(sym.i_Env);
  161. AppendInstruction(new Instruction() { OpCode = OpCode.Index, Value = DynValue.NewString(sym.i_Name) });
  162. return 2;
  163. case SymbolRefType.Local:
  164. AppendInstruction(new Instruction() { OpCode = OpCode.Local, Symbol = sym });
  165. return 1;
  166. case SymbolRefType.Upvalue:
  167. AppendInstruction(new Instruction() { OpCode = OpCode.Upvalue, Symbol = sym });
  168. return 1;
  169. default:
  170. throw new InternalErrorException("Unexpected symbol type : {0}", sym);
  171. }
  172. }
  173. public int Emit_Store(SymbolRef sym, int stackofs, int tupleidx)
  174. {
  175. switch (sym.Type)
  176. {
  177. case SymbolRefType.Global:
  178. Emit_Load(sym.i_Env);
  179. AppendInstruction(new Instruction() { OpCode = OpCode.IndexSet, Symbol = sym, NumVal = stackofs, NumVal2 = tupleidx, Value = DynValue.NewString(sym.i_Name) });
  180. return 2;
  181. case SymbolRefType.Local:
  182. AppendInstruction(new Instruction() { OpCode = OpCode.StoreLcl, Symbol = sym, NumVal = stackofs, NumVal2 = tupleidx });
  183. return 1;
  184. case SymbolRefType.Upvalue:
  185. AppendInstruction(new Instruction() { OpCode = OpCode.StoreUpv, Symbol = sym, NumVal = stackofs, NumVal2 = tupleidx });
  186. return 1;
  187. default:
  188. throw new InternalErrorException("Unexpected symbol type : {0}", sym);
  189. }
  190. }
  191. public Instruction Emit_TblInitN()
  192. {
  193. return AppendInstruction(new Instruction() { OpCode = OpCode.TblInitN });
  194. }
  195. public Instruction Emit_TblInitI(bool lastpos)
  196. {
  197. return AppendInstruction(new Instruction() { OpCode = OpCode.TblInitI, NumVal = lastpos ? 1 : 0 });
  198. }
  199. public Instruction Emit_Index(DynValue index = null)
  200. {
  201. return AppendInstruction(new Instruction() { OpCode = OpCode.Index, Value = index });
  202. }
  203. public Instruction Emit_IndexSet(int stackofs, int tupleidx, DynValue index = null)
  204. {
  205. return AppendInstruction(new Instruction() { OpCode = OpCode.IndexSet, NumVal = stackofs, NumVal2 = tupleidx, Value = index });
  206. }
  207. public Instruction Emit_Copy(int numval)
  208. {
  209. return AppendInstruction(new Instruction() { OpCode = OpCode.Copy, NumVal = numval });
  210. }
  211. public Instruction Emit_Swap(int p1, int p2)
  212. {
  213. return AppendInstruction(new Instruction() { OpCode = OpCode.Swap, NumVal = p1, NumVal2 = p2 });
  214. }
  215. public Instruction Emit_Clone()
  216. {
  217. return AppendInstruction(new Instruction() { OpCode = OpCode.Clone });
  218. }
  219. }
  220. }