1 //===-- BrainFDriver.cpp - BrainF compiler driver -----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===--------------------------------------------------------------------===//
10 // This program converts the BrainF language into LLVM assembly,
11 // which it can then run using the JIT or output as BitCode.
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.
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
23 // lli prog.bf.bc #Run generated BitCode
24 // llvm-ld -native -o=prog prog.bf.bc #Compile BitCode into native executable
26 //===--------------------------------------------------------------------===//
29 #include "llvm/Constants.h"
30 #include "llvm/ModuleProvider.h"
31 #include "llvm/Analysis/Verifier.h"
32 #include "llvm/Bitcode/ReaderWriter.h"
33 #include "llvm/ExecutionEngine/GenericValue.h"
34 #include "llvm/ExecutionEngine/JIT.h"
35 #include "llvm/Support/CommandLine.h"
36 #include "llvm/Support/ManagedStatic.h"
41 //Command line options
43 static cl::opt
<std::string
>
44 InputFilename(cl::Positional
, cl::desc("<input brainf>"));
46 static cl::opt
<std::string
>
47 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"));
50 ArrayBoundsChecking("abc", cl::desc("Enable array bounds checking"));
53 JIT("jit", cl::desc("Run program Just-In-Time"));
56 //Add main function so can be fully compiled
57 void addMainFunction(Module
*mod
) {
58 //define i32 @main(i32 %argc, i8 **%argv)
59 Function
*main_func
= cast
<Function
>(mod
->
60 getOrInsertFunction("main", IntegerType::Int32Ty
, IntegerType::Int32Ty
,
61 PointerType::getUnqual(PointerType::getUnqual(
62 IntegerType::Int8Ty
)), NULL
));
64 Function::arg_iterator args
= main_func
->arg_begin();
65 Value
*arg_0
= args
++;
66 arg_0
->setName("argc");
67 Value
*arg_1
= args
++;
68 arg_1
->setName("argv");
72 BasicBlock
*bb
= BasicBlock::Create("main.0", main_func
);
76 CallInst
*brainf_call
= CallInst::Create(mod
->getFunction("brainf"),
78 brainf_call
->setTailCall(false);
82 ReturnInst::Create(ConstantInt::get(APInt(32, 0)), bb
);
85 int main(int argc
, char **argv
) {
86 cl::ParseCommandLineOptions(argc
, argv
, " BrainF compiler\n");
88 if (InputFilename
== "") {
89 std::cerr
<<"Error: You must specify the filename of the program to "
90 "be compiled. Use --help to see the options.\n";
94 //Get the output stream
95 std::ostream
*out
= &std::cout
;
97 if (OutputFilename
== "") {
98 std::string base
= InputFilename
;
99 if (InputFilename
== "-") {base
= "a";}
101 //Use default filename
102 const char *suffix
= ".bc";
103 OutputFilename
= base
+suffix
;
105 if (OutputFilename
!= "-") {
107 ofstream(OutputFilename
.c_str(),
108 std::ios::out
| std::ios::trunc
| std::ios::binary
);
112 //Get the input stream
113 std::istream
*in
= &std::cin
;
114 if (InputFilename
!= "-") {
115 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
);
124 //Read the BrainF program
126 Module
*mod
= bf
.parse(in
, 65536, cf
); //64 KiB
127 if (in
!= &std::cin
) {delete in
;}
128 addMainFunction(mod
);
130 //Verify generated code
131 if (verifyModule(*mod
)) {
132 std::cerr
<<"Error: module failed verification. This shouldn't happen.\n";
138 std::cout
<< "------- Running JIT -------\n";
139 ExistingModuleProvider
*mp
= new ExistingModuleProvider(mod
);
140 ExecutionEngine
*ee
= ExecutionEngine::create(mp
, false);
141 std::vector
<GenericValue
> args
;
142 Function
*brainf_func
= mod
->getFunction("brainf");
143 GenericValue gv
= ee
->runFunction(brainf_func
, args
);
145 WriteBitcodeToFile(mod
, *out
);
149 if (out
!= &std::cout
) {delete out
;}