BrainFDriver.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. //===-- BrainFDriver.cpp - BrainF compiler driver -----------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===--------------------------------------------------------------------===//
  9. //
  10. // This program converts the BrainF language into LLVM assembly,
  11. // which it can then run using the JIT or output as BitCode.
  12. //
  13. // This implementation has a tape of 65536 bytes,
  14. // with the head starting in the middle.
  15. // Range checking is off by default, so be careful.
  16. // It can be enabled with -abc.
  17. //
  18. // Use:
  19. // ./BrainF -jit prog.bf #Run program now
  20. // ./BrainF -jit -abc prog.bf #Run program now safely
  21. // ./BrainF prog.bf #Write as BitCode
  22. //
  23. // lli prog.bf.bc #Run generated BitCode
  24. // llvm-ld -native -o=prog prog.bf.bc #Compile BitCode into native executable
  25. //
  26. //===--------------------------------------------------------------------===//
  27. #include "BrainF.h"
  28. #include "llvm/Constants.h"
  29. #include "llvm/ModuleProvider.h"
  30. #include "llvm/Analysis/Verifier.h"
  31. #include "llvm/Bitcode/ReaderWriter.h"
  32. #include "llvm/ExecutionEngine/GenericValue.h"
  33. #include "llvm/ExecutionEngine/JIT.h"
  34. #include "llvm/Support/CommandLine.h"
  35. #include "llvm/Support/ManagedStatic.h"
  36. #include <fstream>
  37. #include <iostream>
  38. using namespace llvm;
  39. //Command line options
  40. static cl::opt<std::string>
  41. InputFilename(cl::Positional, cl::desc("<input brainf>"));
  42. static cl::opt<std::string>
  43. OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"));
  44. static cl::opt<bool>
  45. ArrayBoundsChecking("abc", cl::desc("Enable array bounds checking"));
  46. static cl::opt<bool>
  47. JIT("jit", cl::desc("Run program Just-In-Time"));
  48. //Add main function so can be fully compiled
  49. void addMainFunction(Module *mod) {
  50. //define i32 @main(i32 %argc, i8 **%argv)
  51. Function *main_func = cast<Function>(mod->
  52. getOrInsertFunction("main", IntegerType::Int32Ty, IntegerType::Int32Ty,
  53. PointerType::getUnqual(PointerType::getUnqual(
  54. IntegerType::Int8Ty)), NULL));
  55. {
  56. Function::arg_iterator args = main_func->arg_begin();
  57. Value *arg_0 = args++;
  58. arg_0->setName("argc");
  59. Value *arg_1 = args++;
  60. arg_1->setName("argv");
  61. }
  62. //main.0:
  63. BasicBlock *bb = BasicBlock::Create("main.0", main_func);
  64. //call void @brainf()
  65. {
  66. CallInst *brainf_call = CallInst::Create(mod->getFunction("brainf"),
  67. "", bb);
  68. brainf_call->setTailCall(false);
  69. }
  70. //ret i32 0
  71. ReturnInst::Create(ConstantInt::get(APInt(32, 0)), bb);
  72. }
  73. int main(int argc, char **argv) {
  74. cl::ParseCommandLineOptions(argc, argv, " BrainF compiler\n");
  75. if (InputFilename == "") {
  76. std::cerr<<"Error: You must specify the filename of the program to "
  77. "be compiled. Use --help to see the options.\n";
  78. abort();
  79. }
  80. //Get the output stream
  81. std::ostream *out = &std::cout;
  82. if (!JIT) {
  83. if (OutputFilename == "") {
  84. std::string base = InputFilename;
  85. if (InputFilename == "-") {base = "a";}
  86. //Use default filename
  87. const char *suffix = ".bc";
  88. OutputFilename = base+suffix;
  89. }
  90. if (OutputFilename != "-") {
  91. out = new std::
  92. ofstream(OutputFilename.c_str(),
  93. std::ios::out | std::ios::trunc | std::ios::binary);
  94. }
  95. }
  96. //Get the input stream
  97. std::istream *in = &std::cin;
  98. if (InputFilename != "-") {
  99. in = new std::ifstream(InputFilename.c_str());
  100. }
  101. //Gather the compile flags
  102. BrainF::CompileFlags cf = BrainF::flag_off;
  103. if (ArrayBoundsChecking) {
  104. cf = BrainF::CompileFlags(cf | BrainF::flag_arraybounds);
  105. }
  106. //Read the BrainF program
  107. BrainF bf;
  108. Module *mod = bf.parse(in, 65536, cf); //64 KiB
  109. if (in != &std::cin) {delete in;}
  110. addMainFunction(mod);
  111. //Verify generated code
  112. if (verifyModule(*mod)) {
  113. std::cerr<<"Error: module failed verification. This shouldn't happen.\n";
  114. abort();
  115. }
  116. //Write it out
  117. if (JIT) {
  118. std::cout << "------- Running JIT -------\n";
  119. ExistingModuleProvider *mp = new ExistingModuleProvider(mod);
  120. ExecutionEngine *ee = ExecutionEngine::create(mp, false);
  121. std::vector<GenericValue> args;
  122. Function *brainf_func = mod->getFunction("brainf");
  123. GenericValue gv = ee->runFunction(brainf_func, args);
  124. } else {
  125. WriteBitcodeToFile(mod, *out);
  126. }
  127. //Clean up
  128. if (out != &std::cout) {delete out;}
  129. delete mod;
  130. llvm_shutdown();
  131. return 0;
  132. }