PageRenderTime 25ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/src/example/BrainFuck/BrainFuck.java

https://github.com/qznc/jFirm
Java | 225 lines | 175 code | 43 blank | 7 comment | 8 complexity | 1cc1678a21c4d30191b09efd308d7a73 MD5 | raw file
  1. package example.BrainFuck;
  2. import java.io.FileInputStream;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import com.sun.jna.Platform;
  6. import firm.ArrayType;
  7. import firm.Construction;
  8. import firm.Entity;
  9. import firm.Graph;
  10. import firm.MethodType;
  11. import firm.Mode;
  12. import firm.PrimitiveType;
  13. import firm.Program;
  14. import firm.Type;
  15. import firm.bindings.binding_typerep.ir_type_state;
  16. import firm.bindings.binding_typerep.ir_visibility;
  17. import firm.nodes.Block;
  18. import firm.nodes.Call;
  19. import firm.nodes.Cmp;
  20. import firm.nodes.Cond;
  21. import firm.nodes.Load;
  22. import firm.nodes.Node;
  23. import firm.nodes.Store;
  24. public class BrainFuck {
  25. private static int DATA_SIZE = 1000;
  26. private Construction construction;
  27. private InputStream input;
  28. private Entity putcharEntity;
  29. private Entity getcharEntity;
  30. private Node putcharSymConst;
  31. private Node getcharSymConst;
  32. private static String makeLdIdent(String str) {
  33. if (Platform.isMac() || Platform.isWindows()) {
  34. str = "_" + str;
  35. }
  36. return str;
  37. }
  38. public Graph compile(String name) throws IOException {
  39. FileInputStream input = new FileInputStream(name);
  40. this.input = input;
  41. /* create a new entity for the main function */
  42. MethodType type = new MethodType(0, 0);
  43. Type global = Program.getGlobalType();
  44. Entity mainEnt = new Entity(global, "main", type);
  45. mainEnt.setLdIdent(makeLdIdent("main"));
  46. mainEnt.setVisibility(ir_visibility.ir_visibility_default);
  47. /* create a new global array for the brainfuck data */
  48. PrimitiveType btype = new PrimitiveType(Mode.getBu());
  49. ArrayType atype = new ArrayType(1, btype);
  50. atype.setBounds(0, 0, DATA_SIZE);
  51. atype.setSizeBytes(DATA_SIZE);
  52. atype.setTypeState(ir_type_state.layout_fixed);
  53. Type globalType = Program.getGlobalType();
  54. Entity data = new Entity(globalType, "data", atype);
  55. data.setLdIdent(makeLdIdent("data"));
  56. data.setVisibility(ir_visibility.ir_visibility_local);
  57. /* create a graph */
  58. int n_vars = 1;
  59. Graph graph = new Graph(mainEnt, n_vars);
  60. construction = new Construction(graph);
  61. Node symconst = construction.newSymConst(data);
  62. construction.setVariable(0, symconst);
  63. /* create putchar entity */
  64. PrimitiveType intType = new PrimitiveType(Mode.getIs());
  65. MethodType putcharType
  66. = new MethodType(new Type[] {intType}, new Type[] {intType});
  67. putcharEntity = new Entity(globalType, "putchar", putcharType);
  68. putcharEntity.setVisibility(ir_visibility.ir_visibility_external);
  69. putcharEntity.setLdIdent(makeLdIdent("putchar"));
  70. putcharSymConst = construction.newSymConst(putcharEntity);
  71. /* create getchar entity */
  72. MethodType getcharType = new MethodType(new Type[] {}, new Type[] {intType});
  73. getcharEntity = new Entity(globalType, "getchar", getcharType);
  74. getcharEntity.setVisibility(ir_visibility.ir_visibility_external);
  75. getcharEntity.setLdIdent(makeLdIdent("getchar"));
  76. getcharSymConst = construction.newSymConst(getcharEntity);
  77. while (input.available() > 0) {
  78. parse();
  79. if (input.available() > 0) {
  80. System.err.println("warning: unexpected ']' - ignoring");
  81. }
  82. }
  83. input.close();
  84. /* create return statement */
  85. Node nreturn = construction.newReturn(construction.getCurrentMem(), new Node[] {});
  86. graph.getEndBlock().addPred(nreturn);
  87. construction.finish();
  88. /* you could call optimisations here... */
  89. return graph;
  90. }
  91. private void parse() throws IOException {
  92. while(input.available() > 0) {
  93. int c = input.read();
  94. switch(c) {
  95. case '>': changePointer(1); break;
  96. case '<': changePointer(-1); break;
  97. case '+': changeMemory(1); break;
  98. case '-': changeMemory(-1); break;
  99. case '.': outputByte(); break;
  100. case ',': inputByte(); break;
  101. case '[': parseLoop(); break;
  102. case ']': return;
  103. default: break;
  104. }
  105. }
  106. }
  107. private void inputByte() {
  108. Node mem = construction.getCurrentMem();
  109. Node call = construction.newCall(mem, getcharSymConst, new Node[] {}, getcharEntity.getType());
  110. Node callMem = construction.newProj(call, Mode.getM(), Call.pnM);
  111. Node callResults = construction.newProj(call, Mode.getT(), Call.pnTResult);
  112. Node result = construction.newProj(callResults, Mode.getIs(), 0);
  113. Node conv = construction.newConv(result, Mode.getBu());
  114. Node pointer = construction.getVariable(0, Mode.getP());
  115. Node store = construction.newStore(callMem, pointer, conv);
  116. Node storeMem = construction.newProj(store, Mode.getM(), Store.pnM);
  117. construction.setCurrentMem(storeMem);
  118. }
  119. private void parseLoop() throws IOException {
  120. Node jump = construction.newJmp();
  121. Block loopHeader = construction.newBlock();
  122. loopHeader.addPred(jump);
  123. construction.setCurrentBlock(loopHeader);
  124. Node pointer = construction.getVariable(0, Mode.getP());
  125. Node mem = construction.getCurrentMem();
  126. Node load = construction.newLoad(mem, pointer, Mode.getBu());
  127. Node loadRes = construction.newProj(load, Mode.getBu(), Load.pnRes);
  128. Node loadMem = construction.newProj(load, Mode.getM(), Load.pnM);
  129. construction.setCurrentMem(loadMem);
  130. Node zero = construction.newConst(0, Mode.getBu());
  131. Node cmp = construction.newCmp(loadRes, zero);
  132. Node pEqual = construction.newProj(cmp, Mode.getb(), Cmp.pnEq);
  133. Node cond = construction.newCond(pEqual);
  134. Node projTrue = construction.newProj(cond, Mode.getX(), Cond.pnTrue);
  135. Node projFalse = construction.newProj(cond, Mode.getX(), Cond.pnFalse);
  136. Block loopBody = construction.newBlock();
  137. loopBody.addPred(projFalse);
  138. construction.setCurrentBlock(loopBody);
  139. parse();
  140. if (input.available() == 0) {
  141. System.err.println("Parse Error: unmatched '['");
  142. }
  143. Node jmp2 = construction.newJmp();
  144. loopHeader.addPred(jmp2);
  145. Block afterLoop = construction.newBlock();
  146. afterLoop.addPred(projTrue);
  147. construction.setCurrentBlock(afterLoop);
  148. }
  149. private void outputByte() {
  150. Node pointer = construction.getVariable(0, Mode.getP());
  151. Node mem = construction.getCurrentMem();
  152. Node load = construction.newLoad(mem, pointer, Mode.getBu());
  153. Node result = construction.newProj(load, Mode.getBu(), Load.pnRes);
  154. Node conv = construction.newConv(result, Mode.getIs());
  155. Node call = construction.newCall(mem, putcharSymConst, new Node[] {conv}, putcharEntity.getType());
  156. Node callMem = construction.newProj(call, Mode.getM(), Call.pnM);
  157. construction.setCurrentMem(callMem);
  158. }
  159. private void changeMemory(int delta_int) {
  160. Node pointer = construction.getVariable(0, Mode.getP());
  161. Node mem = construction.getCurrentMem();
  162. Node load = construction.newLoad(mem, pointer, Mode.getBu());
  163. Node result = construction.newProj(load, Mode.getBu(), Load.pnRes);
  164. Node loadMem = construction.newProj(load, Mode.getM(), Load.pnM);
  165. Node delta = construction.newConst(Math.abs(delta_int), Mode.getBu());
  166. Node op;
  167. if (delta_int < 0) {
  168. op = construction.newSub(result, delta, Mode.getBu());
  169. } else {
  170. op = construction.newAdd(result, delta, Mode.getBu());
  171. }
  172. Node store = construction.newStore(loadMem, pointer, op);
  173. Node storeMem = construction.newProj(store, Mode.getM(), Store.pnM);
  174. construction.setCurrentMem(storeMem);
  175. }
  176. private void changePointer(int delta_int) {
  177. Node pointer = construction.getVariable(0, Mode.getP());
  178. Node delta = construction.newConst(delta_int, Mode.getIs());
  179. Node add = construction.newAdd(pointer, delta, Mode.getP());
  180. construction.setVariable(0, add);
  181. }
  182. }