PageRenderTime 47ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/internal/bcgen.d

http://github.com/plol/d-interp
D | 255 lines | 223 code | 29 blank | 3 comment | 45 complexity | 2fb65df3979af82d00e324d65f8dde6d MD5 | raw file
  1. module internal.bcgen;
  2. import std.array;
  3. import std.stdio;
  4. import std.conv;
  5. import internal.bytecode;
  6. import internal.ctenv;
  7. import internal.ir;
  8. import internal.typeinfo;
  9. import internal.val;
  10. ByteCode[] generate_bytecode(IR ir, CTEnv env) {
  11. ByteCode[] ret;
  12. generate_bytecode(ir, env, ret);
  13. return ret;
  14. }
  15. size_t generate_bytecode(IR ir, CTEnv env, ref ByteCode[] bc) {
  16. switch (ir.type) {
  17. default: assert (0, text(ir.type));
  18. case IR.Type.if_: return generate_if(ir, env, bc);
  19. case IR.Type.while_: return generate_while(ir, env, bc);
  20. //case IR.Type.switch_: return generate_switch(ir, env, bc);
  21. case IR.Type.variable: return generate_variable(ir, env, bc);
  22. case IR.Type.sequence: return generate_sequence(ir, env, bc);
  23. case IR.Type.constant: return generate_constant(ir, env, bc);
  24. case IR.Type.application: return generate_application(ir, env, bc);
  25. case IR.Type.assignment: return generate_assignment(ir, env, bc);
  26. //case IR.Type.typeid_: return generate_typeid(ir, env, bc);
  27. //case IR.Type.typeof_: return generate_typeof(ir, env, bc);
  28. case IR.Type.addressof: return generate_addressof(ir, env, bc);
  29. case IR.Type.deref: return generate_deref(ir, env, bc);
  30. case IR.Type.return_: return generate_return(ir, env, bc);
  31. case IR.Type.var_decl: return generate_var_decl(ir, env, bc);
  32. case IR.Type.var_init: return generate_var_init(ir, env, bc);
  33. case IR.Type.function_: return generate_function(ir, env, bc);
  34. case IR.Type.up_ref: return generate_up_ref(ir, env, bc);
  35. case IR.Type.nothing: return generate_nothing(ir, env, bc);
  36. }
  37. }
  38. size_t end(ref ByteCode[] bc) {
  39. return bc.length - 1;
  40. }
  41. void jump_to(size_t a, size_t b, ref ByteCode[] bc) {
  42. bc[a].jump.target = b;
  43. }
  44. size_t generate_branch(ref ByteCode[] bc) {
  45. bc ~= ByteCode(ByteCode.Type.branch);
  46. return bc.end;
  47. }
  48. size_t generate_jump(ref ByteCode[] bc) {
  49. bc ~= ByteCode(ByteCode.Type.jump);
  50. return bc.end;
  51. }
  52. size_t generate_if(IR ir, CTEnv env, ref ByteCode[] bc) {
  53. auto ret = ir.if_.if_part.generate_bytecode(env, bc);
  54. auto skip = bc.generate_branch();
  55. ir.if_.then_part.generate_bytecode(env, bc);
  56. auto jump_out = bc.generate_jump();
  57. auto else_start = ir.if_.else_part.generate_bytecode(env, bc);
  58. skip.jump_to(else_start, bc);
  59. jump_out.jump_to(bc.end + 1, bc);
  60. return ret;
  61. }
  62. size_t generate_while(IR ir, CTEnv env, ref ByteCode[] bc) {
  63. auto ret = bc.generate_jump();
  64. auto body_start = ir.while_.body_.generate_bytecode(env, bc);
  65. auto test_start = ir.while_.condition.generate_bytecode(env, bc);
  66. auto exit_loop = bc.generate_branch();
  67. auto jump_back = bc.generate_jump();
  68. ret.jump_to(test_start, bc);
  69. exit_loop.jump_to(bc.end + 1, bc);
  70. jump_back.jump_to(body_start, bc);
  71. return ret;
  72. }
  73. IR unwind_up_ref(IR ir, ref ByteCode[] bc) {
  74. while (ir.type == IR.Type.up_ref) {
  75. bc ~= ByteCode(ByteCode.Type.get_parent_env);
  76. ir = ir.next;
  77. }
  78. return ir;
  79. }
  80. size_t generate_up_ref(IR ir, CTEnv env, ref ByteCode[] bc) {
  81. auto ret = bc.end + 1;
  82. bc ~= ByteCode(ByteCode.Type.push_env);
  83. auto inner = unwind_up_ref(ir, bc);
  84. inner.generate_bytecode(env, bc);
  85. bc ~= ByteCode(ByteCode.Type.pop_env);
  86. return ret;
  87. }
  88. size_t generate_variable(IR ir, CTEnv env, ref ByteCode[] bc) {
  89. auto var = ir.variable;
  90. if (var.local) {
  91. bc ~= ByteCode(ByteCode.Type.local_variable_lookup, var.index);
  92. return bc.end;
  93. } else if (var.global) {
  94. bc ~= ByteCode(ByteCode.Type.global_variable_lookup, var.index);
  95. return bc.end;
  96. } else {
  97. assert (0);
  98. }
  99. }
  100. size_t generate_sequence(IR ir, CTEnv env, ref ByteCode[] bc) {
  101. auto ret = bc.end + 1;
  102. if (ir.sequence.empty) {
  103. bc ~= ByteCode(ByteCode.Type.nop);
  104. } else {
  105. foreach (r; ir.sequence) {
  106. r.generate_bytecode(env, bc);
  107. }
  108. }
  109. return ret;
  110. }
  111. size_t generate_constant(IR ir, CTEnv env, ref ByteCode[] bc) {
  112. bc ~= ByteCode(ByteCode.Type.constant, ir.constant.val);
  113. auto ret = bc.end;
  114. if (ir.ti.type == TI.Type.delegate_) {
  115. bc ~= ByteCode(ByteCode.Type.make_delegate);
  116. }
  117. return ret;
  118. }
  119. size_t generate_application(IR ir, CTEnv env, ref ByteCode[] bc) {
  120. auto ret = bc.end + 1;
  121. foreach (operand; ir.application.operands) {
  122. operand.generate_bytecode(env, bc);
  123. bc ~= ByteCode(ByteCode.Type.push_arg);
  124. }
  125. auto operator = ir.application.operator;
  126. operator.generate_bytecode(env, bc);
  127. auto ti = operator.ti;
  128. auto argc = ti.operands.length;
  129. void append_call_bytecode(TI ti) {
  130. if (ti.type == TI.Type.builtin_function) {
  131. bc ~= ByteCode(ByteCode.Type.call_builtin_function, argc);
  132. } else if (ti.type == TI.Type.builtin_delegate) {
  133. bc ~= ByteCode(ByteCode.Type.call_builtin_delegate, argc);
  134. } else if (ti.type == TI.Type.delegate_) {
  135. bc ~= ByteCode(ByteCode.Type.call_delegate, argc);
  136. } else if (ti.type == TI.Type.function_) {
  137. bc ~= ByteCode(ByteCode.Type.call_function, argc);
  138. } else if (ti.type == TI.Type.local_function) {
  139. bc ~= ByteCode(ByteCode.Type.call_local_function, argc);
  140. } else if (ti.type == TI.Type.pointer) {
  141. append_call_bytecode(ti.next);
  142. } else {
  143. assert (0);
  144. }
  145. }
  146. append_call_bytecode(ti);
  147. return ret;
  148. }
  149. size_t generate_pointer_for(IR ir, CTEnv env, ref ByteCode[] bc) {
  150. if (ir.type == IR.Type.variable) {
  151. auto bctype = ir.variable.local
  152. ? ByteCode.Type.local_variable_reference_lookup
  153. : ByteCode.Type.global_variable_reference_lookup;
  154. bc ~= ByteCode(bctype, ir.variable.index);
  155. return bc.end;
  156. } else if (ir.type == IR.Type.deref) {
  157. return ir.next.generate_bytecode(env, bc);
  158. } else if (ir.type == IR.Type.up_ref) {
  159. auto ret = bc.end + 1;
  160. bc ~= ByteCode(ByteCode.Type.push_env);
  161. auto inner = unwind_up_ref(ir, bc);
  162. generate_pointer_for(inner, env, bc);
  163. bc ~= ByteCode(ByteCode.Type.pop_env);
  164. return ret;
  165. } else {
  166. assert (0);
  167. }
  168. }
  169. size_t generate_assignment(IR ir, CTEnv env, ref ByteCode[] bc) {
  170. auto ret = ir.bin.rhs.generate_bytecode(env, bc);
  171. bc ~= ByteCode(ByteCode.Type.push_arg);
  172. generate_pointer_for(ir.bin.lhs, env, bc);
  173. bc ~= ByteCode(ByteCode.Type.assignment, ir.ti.tsize());
  174. return ret;
  175. }
  176. size_t generate_addressof(IR ir, CTEnv env, ref ByteCode[] bc) {
  177. if (ir.next.type == IR.Type.constant) {
  178. assert (0);
  179. }
  180. return generate_pointer_for(ir.next, env, bc);
  181. }
  182. size_t generate_deref(IR ir, CTEnv env, ref ByteCode[] bc) {
  183. assert (0);
  184. }
  185. size_t generate_return(IR ir, CTEnv env, ref ByteCode[] bc) {
  186. auto ret = ir.next.generate_bytecode(env, bc);
  187. bc ~= ByteCode(ByteCode.Type.leave);
  188. return ret;
  189. }
  190. size_t generate_var_decl(IR ir, CTEnv env, ref ByteCode[] bc) {
  191. auto ret = bc.end+1;
  192. foreach (vi; ir.var_decl.inits) {
  193. vi.generate_bytecode(env, bc);
  194. }
  195. return ret;
  196. }
  197. size_t generate_var_init(IR ir, CTEnv env, ref ByteCode[] bc) {
  198. auto var_init = ir.var_init;
  199. assert (env.lookup(var_init.name).type == IR.Type.variable);
  200. auto var_ir = env.lookup(var_init.name);
  201. auto var = var_ir.variable;
  202. if (var.global) {
  203. return var_ir.generate_bytecode(env, bc);
  204. }
  205. size_t ret;
  206. if (var_init.initializer.type == IR.Type.nothing) {
  207. bc ~= ByteCode(ByteCode.Type.constant, init_val(ir.ti));
  208. ret = bc.end;
  209. } else {
  210. ret = var_init.initializer.generate_bytecode(env, bc);
  211. }
  212. bc ~= ByteCode(ByteCode.Type.push_arg);
  213. generate_pointer_for(var_ir, env, bc);
  214. bc ~= ByteCode(ByteCode.Type.assignment, ir.ti.tsize());
  215. return ret;
  216. }
  217. size_t generate_nothing(IR ir, CTEnv env, ref ByteCode[] bc) {
  218. bc ~= ByteCode(ByteCode.Type.nop);
  219. return bc.end;
  220. }
  221. size_t generate_function(IR ir, CTEnv env, ref ByteCode[] bc) {
  222. bc ~= ByteCode(ByteCode.Type.nop);
  223. auto ret = bc.end;
  224. ir.function_.body_.generate_bytecode(ir.function_.env, ir.function_.bc);
  225. return ret;
  226. }