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/Analysis/Verifier.h"
31 #include "llvm/Bitcode/ReaderWriter.h"
32 #include "llvm/ExecutionEngine/GenericValue.h"
33 #include "llvm/ExecutionEngine/JIT.h"
34 #include "llvm/Target/TargetSelect.h"
35 #include "llvm/Support/CommandLine.h"
36 #include "llvm/Support/ManagedStatic.h"
37 #include "llvm/Support/raw_ostream.h"
42 //Command line options
44 static cl::opt
<std::string
>
45 InputFilename(cl::Positional
, cl::desc("<input brainf>"));
47 static cl::opt
<std::string
>
48 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"));
51 ArrayBoundsChecking("abc", cl::desc("Enable array bounds checking"));
54 JIT("jit", cl::desc("Run program Just-In-Time"));
57 //Add main function so can be fully compiled
58 void addMainFunction(Module
*mod
) {
59 //define i32 @main(i32 %argc, i8 **%argv)
60 Function
*main_func
= cast
<Function
>(mod
->
61 getOrInsertFunction("main", IntegerType::getInt32Ty(mod
->getContext()),
62 IntegerType::getInt32Ty(mod
->getContext()),
63 PointerType::getUnqual(PointerType::getUnqual(
64 IntegerType::getInt8Ty(mod
->getContext()))), NULL
));
66 Function::arg_iterator args
= main_func
->arg_begin();
67 Value
*arg_0
= args
++;
68 arg_0
->setName("argc");
69 Value
*arg_1
= args
++;
70 arg_1
->setName("argv");
74 BasicBlock
*bb
= BasicBlock::Create(mod
->getContext(), "main.0", main_func
);
78 CallInst
*brainf_call
= CallInst::Create(mod
->getFunction("brainf"),
80 brainf_call
->setTailCall(false);
84 ReturnInst::Create(mod
->getContext(),
85 ConstantInt::get(mod
->getContext(), APInt(32, 0)), bb
);
88 int main(int argc
, char **argv
) {
89 cl::ParseCommandLineOptions(argc
, argv
, " BrainF compiler\n");
91 LLVMContext
&Context
= getGlobalContext();
93 if (InputFilename
== "") {
94 errs() << "Error: You must specify the filename of the program to "
95 "be compiled. Use --help to see the options.\n";
99 //Get the output stream
100 raw_ostream
*out
= &outs();
102 if (OutputFilename
== "") {
103 std::string base
= InputFilename
;
104 if (InputFilename
== "-") { base
= "a"; }
106 // Use default filename.
107 OutputFilename
= base
+".bc";
109 if (OutputFilename
!= "-") {
111 out
= new raw_fd_ostream(OutputFilename
.c_str(), ErrInfo
,
112 raw_fd_ostream::F_Binary
);
116 //Get the input stream
117 std::istream
*in
= &std::cin
;
118 if (InputFilename
!= "-")
119 in
= new std::ifstream(InputFilename
.c_str());
121 //Gather the compile flags
122 BrainF::CompileFlags cf
= BrainF::flag_off
;
123 if (ArrayBoundsChecking
)
124 cf
= BrainF::CompileFlags(cf
| BrainF::flag_arraybounds
);
126 //Read the BrainF program
128 Module
*mod
= bf
.parse(in
, 65536, cf
, Context
); //64 KiB
131 addMainFunction(mod
);
133 //Verify generated code
134 if (verifyModule(*mod
)) {
135 errs() << "Error: module failed verification. This shouldn't happen.\n";
141 InitializeNativeTarget();
143 outs() << "------- Running JIT -------\n";
144 ExecutionEngine
*ee
= EngineBuilder(mod
).create();
145 std::vector
<GenericValue
> args
;
146 Function
*brainf_func
= mod
->getFunction("brainf");
147 GenericValue gv
= ee
->runFunction(brainf_func
, args
);
149 WriteBitcodeToFile(mod
, *out
);