BrainFDriver.cpp 5.4 KB

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