BrainFDriver.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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. //
  25. //===--------------------------------------------------------------------===//
  26. #include "BrainF.h"
  27. #include "llvm/Analysis/Verifier.h"
  28. #include "llvm/Bitcode/ReaderWriter.h"
  29. #include "llvm/ExecutionEngine/GenericValue.h"
  30. #include "llvm/ExecutionEngine/JIT.h"
  31. #include "llvm/IR/Constants.h"
  32. #include "llvm/Support/CommandLine.h"
  33. #include "llvm/Support/ManagedStatic.h"
  34. #include "llvm/Support/TargetSelect.h"
  35. #include "llvm/Support/raw_ostream.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::getInt32Ty(mod->getContext()),
  53. IntegerType::getInt32Ty(mod->getContext()),
  54. PointerType::getUnqual(PointerType::getUnqual(
  55. IntegerType::getInt8Ty(mod->getContext()))), NULL));
  56. {
  57. Function::arg_iterator args = main_func->arg_begin();
  58. Value *arg_0 = args++;
  59. arg_0->setName("argc");
  60. Value *arg_1 = args++;
  61. arg_1->setName("argv");
  62. }
  63. //main.0:
  64. BasicBlock *bb = BasicBlock::Create(mod->getContext(), "main.0", main_func);
  65. //call void @brainf()
  66. {
  67. CallInst *brainf_call = CallInst::Create(mod->getFunction("brainf"),
  68. "", bb);
  69. brainf_call->setTailCall(false);
  70. }
  71. //ret i32 0
  72. ReturnInst::Create(mod->getContext(),
  73. ConstantInt::get(mod->getContext(), APInt(32, 0)), bb);
  74. }
  75. int main(int argc, char **argv) {
  76. cl::ParseCommandLineOptions(argc, argv, " BrainF compiler\n");
  77. LLVMContext &Context = getGlobalContext();
  78. if (InputFilename == "") {
  79. errs() << "Error: You must specify the filename of the program to "
  80. "be compiled. Use --help to see the options.\n";
  81. abort();
  82. }
  83. //Get the output stream
  84. raw_ostream *out = &outs();
  85. if (!JIT) {
  86. if (OutputFilename == "") {
  87. std::string base = InputFilename;
  88. if (InputFilename == "-") { base = "a"; }
  89. // Use default filename.
  90. OutputFilename = base+".bc";
  91. }
  92. if (OutputFilename != "-") {
  93. std::string ErrInfo;
  94. out = new raw_fd_ostream(OutputFilename.c_str(), ErrInfo,
  95. sys::fs::F_Binary);
  96. }
  97. }
  98. //Get the input stream
  99. std::istream *in = &std::cin;
  100. if (InputFilename != "-")
  101. in = new std::ifstream(InputFilename.c_str());
  102. //Gather the compile flags
  103. BrainF::CompileFlags cf = BrainF::flag_off;
  104. if (ArrayBoundsChecking)
  105. cf = BrainF::CompileFlags(cf | BrainF::flag_arraybounds);
  106. //Read the BrainF program
  107. BrainF bf;
  108. Module *mod = bf.parse(in, 65536, cf, Context); //64 KiB
  109. if (in != &std::cin)
  110. delete in;
  111. addMainFunction(mod);
  112. //Verify generated code
  113. if (verifyModule(*mod)) {
  114. errs() << "Error: module failed verification. This shouldn't happen.\n";
  115. abort();
  116. }
  117. //Write it out
  118. if (JIT) {
  119. InitializeNativeTarget();
  120. outs() << "------- Running JIT -------\n";
  121. ExecutionEngine *ee = EngineBuilder(mod).create();
  122. std::vector<GenericValue> args;
  123. Function *brainf_func = mod->getFunction("brainf");
  124. GenericValue gv = ee->runFunction(brainf_func, args);
  125. } else {
  126. WriteBitcodeToFile(mod, *out);
  127. }
  128. //Clean up
  129. if (out != &outs())
  130. delete out;
  131. delete mod;
  132. llvm_shutdown();
  133. return 0;
  134. }