PageRenderTime 37ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/src/example/BrainFuck/BrainFuck.java

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