BrainFDriver.cpp 4.6 KB

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