1*9880d681SAndroid Build Coastguard Worker //===-- BrainF.cpp - BrainF compiler example ------------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This class compiles the BrainF language into LLVM assembly.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker // The BrainF language has 8 commands:
13*9880d681SAndroid Build Coastguard Worker // Command Equivalent C Action
14*9880d681SAndroid Build Coastguard Worker // ------- ------------ ------
15*9880d681SAndroid Build Coastguard Worker // , *h=getchar(); Read a character from stdin, 255 on EOF
16*9880d681SAndroid Build Coastguard Worker // . putchar(*h); Write a character to stdout
17*9880d681SAndroid Build Coastguard Worker // - --*h; Decrement tape
18*9880d681SAndroid Build Coastguard Worker // + ++*h; Increment tape
19*9880d681SAndroid Build Coastguard Worker // < --h; Move head left
20*9880d681SAndroid Build Coastguard Worker // > ++h; Move head right
21*9880d681SAndroid Build Coastguard Worker // [ while(*h) { Start loop
22*9880d681SAndroid Build Coastguard Worker // ] } End loop
23*9880d681SAndroid Build Coastguard Worker //
24*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Worker #include "BrainF.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/APInt.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/BasicBlock.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constant.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DerivedTypes.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/GlobalValue.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/GlobalVariable.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/InstrTypes.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instruction.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Intrinsics.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Type.h"
41*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Casting.h"
42*9880d681SAndroid Build Coastguard Worker #include <cstdlib>
43*9880d681SAndroid Build Coastguard Worker #include <iostream>
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Worker using namespace llvm;
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Worker //Set the constants for naming
48*9880d681SAndroid Build Coastguard Worker const char *BrainF::tapereg = "tape";
49*9880d681SAndroid Build Coastguard Worker const char *BrainF::headreg = "head";
50*9880d681SAndroid Build Coastguard Worker const char *BrainF::label = "brainf";
51*9880d681SAndroid Build Coastguard Worker const char *BrainF::testreg = "test";
52*9880d681SAndroid Build Coastguard Worker
parse(std::istream * in1,int mem,CompileFlags cf,LLVMContext & Context)53*9880d681SAndroid Build Coastguard Worker Module *BrainF::parse(std::istream *in1, int mem, CompileFlags cf,
54*9880d681SAndroid Build Coastguard Worker LLVMContext& Context) {
55*9880d681SAndroid Build Coastguard Worker in = in1;
56*9880d681SAndroid Build Coastguard Worker memtotal = mem;
57*9880d681SAndroid Build Coastguard Worker comflag = cf;
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Worker header(Context);
60*9880d681SAndroid Build Coastguard Worker readloop(nullptr, nullptr, nullptr, Context);
61*9880d681SAndroid Build Coastguard Worker delete builder;
62*9880d681SAndroid Build Coastguard Worker return module;
63*9880d681SAndroid Build Coastguard Worker }
64*9880d681SAndroid Build Coastguard Worker
header(LLVMContext & C)65*9880d681SAndroid Build Coastguard Worker void BrainF::header(LLVMContext& C) {
66*9880d681SAndroid Build Coastguard Worker module = new Module("BrainF", C);
67*9880d681SAndroid Build Coastguard Worker
68*9880d681SAndroid Build Coastguard Worker //Function prototypes
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker //declare void @llvm.memset.p0i8.i32(i8 *, i8, i32, i32, i1)
71*9880d681SAndroid Build Coastguard Worker Type *Tys[] = { Type::getInt8PtrTy(C), Type::getInt32Ty(C) };
72*9880d681SAndroid Build Coastguard Worker Function *memset_func = Intrinsic::getDeclaration(module, Intrinsic::memset,
73*9880d681SAndroid Build Coastguard Worker Tys);
74*9880d681SAndroid Build Coastguard Worker
75*9880d681SAndroid Build Coastguard Worker //declare i32 @getchar()
76*9880d681SAndroid Build Coastguard Worker getchar_func = cast<Function>(module->
77*9880d681SAndroid Build Coastguard Worker getOrInsertFunction("getchar", IntegerType::getInt32Ty(C), NULL));
78*9880d681SAndroid Build Coastguard Worker
79*9880d681SAndroid Build Coastguard Worker //declare i32 @putchar(i32)
80*9880d681SAndroid Build Coastguard Worker putchar_func = cast<Function>(module->
81*9880d681SAndroid Build Coastguard Worker getOrInsertFunction("putchar", IntegerType::getInt32Ty(C),
82*9880d681SAndroid Build Coastguard Worker IntegerType::getInt32Ty(C), NULL));
83*9880d681SAndroid Build Coastguard Worker
84*9880d681SAndroid Build Coastguard Worker //Function header
85*9880d681SAndroid Build Coastguard Worker
86*9880d681SAndroid Build Coastguard Worker //define void @brainf()
87*9880d681SAndroid Build Coastguard Worker brainf_func = cast<Function>(module->
88*9880d681SAndroid Build Coastguard Worker getOrInsertFunction("brainf", Type::getVoidTy(C), NULL));
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Worker builder = new IRBuilder<>(BasicBlock::Create(C, label, brainf_func));
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard Worker //%arr = malloc i8, i32 %d
93*9880d681SAndroid Build Coastguard Worker ConstantInt *val_mem = ConstantInt::get(C, APInt(32, memtotal));
94*9880d681SAndroid Build Coastguard Worker BasicBlock* BB = builder->GetInsertBlock();
95*9880d681SAndroid Build Coastguard Worker Type* IntPtrTy = IntegerType::getInt32Ty(C);
96*9880d681SAndroid Build Coastguard Worker Type* Int8Ty = IntegerType::getInt8Ty(C);
97*9880d681SAndroid Build Coastguard Worker Constant* allocsize = ConstantExpr::getSizeOf(Int8Ty);
98*9880d681SAndroid Build Coastguard Worker allocsize = ConstantExpr::getTruncOrBitCast(allocsize, IntPtrTy);
99*9880d681SAndroid Build Coastguard Worker ptr_arr = CallInst::CreateMalloc(BB, IntPtrTy, Int8Ty, allocsize, val_mem,
100*9880d681SAndroid Build Coastguard Worker nullptr, "arr");
101*9880d681SAndroid Build Coastguard Worker BB->getInstList().push_back(cast<Instruction>(ptr_arr));
102*9880d681SAndroid Build Coastguard Worker
103*9880d681SAndroid Build Coastguard Worker //call void @llvm.memset.p0i8.i32(i8 *%arr, i8 0, i32 %d, i32 1, i1 0)
104*9880d681SAndroid Build Coastguard Worker {
105*9880d681SAndroid Build Coastguard Worker Value *memset_params[] = {
106*9880d681SAndroid Build Coastguard Worker ptr_arr,
107*9880d681SAndroid Build Coastguard Worker ConstantInt::get(C, APInt(8, 0)),
108*9880d681SAndroid Build Coastguard Worker val_mem,
109*9880d681SAndroid Build Coastguard Worker ConstantInt::get(C, APInt(32, 1)),
110*9880d681SAndroid Build Coastguard Worker ConstantInt::get(C, APInt(1, 0))
111*9880d681SAndroid Build Coastguard Worker };
112*9880d681SAndroid Build Coastguard Worker
113*9880d681SAndroid Build Coastguard Worker CallInst *memset_call = builder->
114*9880d681SAndroid Build Coastguard Worker CreateCall(memset_func, memset_params);
115*9880d681SAndroid Build Coastguard Worker memset_call->setTailCall(false);
116*9880d681SAndroid Build Coastguard Worker }
117*9880d681SAndroid Build Coastguard Worker
118*9880d681SAndroid Build Coastguard Worker //%arrmax = getelementptr i8 *%arr, i32 %d
119*9880d681SAndroid Build Coastguard Worker if (comflag & flag_arraybounds) {
120*9880d681SAndroid Build Coastguard Worker ptr_arrmax = builder->
121*9880d681SAndroid Build Coastguard Worker CreateGEP(ptr_arr, ConstantInt::get(C, APInt(32, memtotal)), "arrmax");
122*9880d681SAndroid Build Coastguard Worker }
123*9880d681SAndroid Build Coastguard Worker
124*9880d681SAndroid Build Coastguard Worker //%head.%d = getelementptr i8 *%arr, i32 %d
125*9880d681SAndroid Build Coastguard Worker curhead = builder->CreateGEP(ptr_arr,
126*9880d681SAndroid Build Coastguard Worker ConstantInt::get(C, APInt(32, memtotal/2)),
127*9880d681SAndroid Build Coastguard Worker headreg);
128*9880d681SAndroid Build Coastguard Worker
129*9880d681SAndroid Build Coastguard Worker //Function footer
130*9880d681SAndroid Build Coastguard Worker
131*9880d681SAndroid Build Coastguard Worker //brainf.end:
132*9880d681SAndroid Build Coastguard Worker endbb = BasicBlock::Create(C, label, brainf_func);
133*9880d681SAndroid Build Coastguard Worker
134*9880d681SAndroid Build Coastguard Worker //call free(i8 *%arr)
135*9880d681SAndroid Build Coastguard Worker endbb->getInstList().push_back(CallInst::CreateFree(ptr_arr, endbb));
136*9880d681SAndroid Build Coastguard Worker
137*9880d681SAndroid Build Coastguard Worker //ret void
138*9880d681SAndroid Build Coastguard Worker ReturnInst::Create(C, endbb);
139*9880d681SAndroid Build Coastguard Worker
140*9880d681SAndroid Build Coastguard Worker //Error block for array out of bounds
141*9880d681SAndroid Build Coastguard Worker if (comflag & flag_arraybounds)
142*9880d681SAndroid Build Coastguard Worker {
143*9880d681SAndroid Build Coastguard Worker //@aberrormsg = internal constant [%d x i8] c"\00"
144*9880d681SAndroid Build Coastguard Worker Constant *msg_0 =
145*9880d681SAndroid Build Coastguard Worker ConstantDataArray::getString(C, "Error: The head has left the tape.",
146*9880d681SAndroid Build Coastguard Worker true);
147*9880d681SAndroid Build Coastguard Worker
148*9880d681SAndroid Build Coastguard Worker GlobalVariable *aberrormsg = new GlobalVariable(
149*9880d681SAndroid Build Coastguard Worker *module,
150*9880d681SAndroid Build Coastguard Worker msg_0->getType(),
151*9880d681SAndroid Build Coastguard Worker true,
152*9880d681SAndroid Build Coastguard Worker GlobalValue::InternalLinkage,
153*9880d681SAndroid Build Coastguard Worker msg_0,
154*9880d681SAndroid Build Coastguard Worker "aberrormsg");
155*9880d681SAndroid Build Coastguard Worker
156*9880d681SAndroid Build Coastguard Worker //declare i32 @puts(i8 *)
157*9880d681SAndroid Build Coastguard Worker Function *puts_func = cast<Function>(module->
158*9880d681SAndroid Build Coastguard Worker getOrInsertFunction("puts", IntegerType::getInt32Ty(C),
159*9880d681SAndroid Build Coastguard Worker PointerType::getUnqual(IntegerType::getInt8Ty(C)), NULL));
160*9880d681SAndroid Build Coastguard Worker
161*9880d681SAndroid Build Coastguard Worker //brainf.aberror:
162*9880d681SAndroid Build Coastguard Worker aberrorbb = BasicBlock::Create(C, label, brainf_func);
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Worker //call i32 @puts(i8 *getelementptr([%d x i8] *@aberrormsg, i32 0, i32 0))
165*9880d681SAndroid Build Coastguard Worker {
166*9880d681SAndroid Build Coastguard Worker Constant *zero_32 = Constant::getNullValue(IntegerType::getInt32Ty(C));
167*9880d681SAndroid Build Coastguard Worker
168*9880d681SAndroid Build Coastguard Worker Constant *gep_params[] = {
169*9880d681SAndroid Build Coastguard Worker zero_32,
170*9880d681SAndroid Build Coastguard Worker zero_32
171*9880d681SAndroid Build Coastguard Worker };
172*9880d681SAndroid Build Coastguard Worker
173*9880d681SAndroid Build Coastguard Worker Constant *msgptr = ConstantExpr::
174*9880d681SAndroid Build Coastguard Worker getGetElementPtr(aberrormsg->getValueType(), aberrormsg, gep_params);
175*9880d681SAndroid Build Coastguard Worker
176*9880d681SAndroid Build Coastguard Worker Value *puts_params[] = {
177*9880d681SAndroid Build Coastguard Worker msgptr
178*9880d681SAndroid Build Coastguard Worker };
179*9880d681SAndroid Build Coastguard Worker
180*9880d681SAndroid Build Coastguard Worker CallInst *puts_call =
181*9880d681SAndroid Build Coastguard Worker CallInst::Create(puts_func,
182*9880d681SAndroid Build Coastguard Worker puts_params,
183*9880d681SAndroid Build Coastguard Worker "", aberrorbb);
184*9880d681SAndroid Build Coastguard Worker puts_call->setTailCall(false);
185*9880d681SAndroid Build Coastguard Worker }
186*9880d681SAndroid Build Coastguard Worker
187*9880d681SAndroid Build Coastguard Worker //br label %brainf.end
188*9880d681SAndroid Build Coastguard Worker BranchInst::Create(endbb, aberrorbb);
189*9880d681SAndroid Build Coastguard Worker }
190*9880d681SAndroid Build Coastguard Worker }
191*9880d681SAndroid Build Coastguard Worker
readloop(PHINode * phi,BasicBlock * oldbb,BasicBlock * testbb,LLVMContext & C)192*9880d681SAndroid Build Coastguard Worker void BrainF::readloop(PHINode *phi, BasicBlock *oldbb, BasicBlock *testbb,
193*9880d681SAndroid Build Coastguard Worker LLVMContext &C) {
194*9880d681SAndroid Build Coastguard Worker Symbol cursym = SYM_NONE;
195*9880d681SAndroid Build Coastguard Worker int curvalue = 0;
196*9880d681SAndroid Build Coastguard Worker Symbol nextsym = SYM_NONE;
197*9880d681SAndroid Build Coastguard Worker int nextvalue = 0;
198*9880d681SAndroid Build Coastguard Worker char c;
199*9880d681SAndroid Build Coastguard Worker int loop;
200*9880d681SAndroid Build Coastguard Worker int direction;
201*9880d681SAndroid Build Coastguard Worker
202*9880d681SAndroid Build Coastguard Worker while(cursym != SYM_EOF && cursym != SYM_ENDLOOP) {
203*9880d681SAndroid Build Coastguard Worker // Write out commands
204*9880d681SAndroid Build Coastguard Worker switch(cursym) {
205*9880d681SAndroid Build Coastguard Worker case SYM_NONE:
206*9880d681SAndroid Build Coastguard Worker // Do nothing
207*9880d681SAndroid Build Coastguard Worker break;
208*9880d681SAndroid Build Coastguard Worker
209*9880d681SAndroid Build Coastguard Worker case SYM_READ:
210*9880d681SAndroid Build Coastguard Worker {
211*9880d681SAndroid Build Coastguard Worker //%tape.%d = call i32 @getchar()
212*9880d681SAndroid Build Coastguard Worker CallInst *getchar_call =
213*9880d681SAndroid Build Coastguard Worker builder->CreateCall(getchar_func, {}, tapereg);
214*9880d681SAndroid Build Coastguard Worker getchar_call->setTailCall(false);
215*9880d681SAndroid Build Coastguard Worker Value *tape_0 = getchar_call;
216*9880d681SAndroid Build Coastguard Worker
217*9880d681SAndroid Build Coastguard Worker //%tape.%d = trunc i32 %tape.%d to i8
218*9880d681SAndroid Build Coastguard Worker Value *tape_1 = builder->
219*9880d681SAndroid Build Coastguard Worker CreateTrunc(tape_0, IntegerType::getInt8Ty(C), tapereg);
220*9880d681SAndroid Build Coastguard Worker
221*9880d681SAndroid Build Coastguard Worker //store i8 %tape.%d, i8 *%head.%d
222*9880d681SAndroid Build Coastguard Worker builder->CreateStore(tape_1, curhead);
223*9880d681SAndroid Build Coastguard Worker }
224*9880d681SAndroid Build Coastguard Worker break;
225*9880d681SAndroid Build Coastguard Worker
226*9880d681SAndroid Build Coastguard Worker case SYM_WRITE:
227*9880d681SAndroid Build Coastguard Worker {
228*9880d681SAndroid Build Coastguard Worker //%tape.%d = load i8 *%head.%d
229*9880d681SAndroid Build Coastguard Worker LoadInst *tape_0 = builder->CreateLoad(curhead, tapereg);
230*9880d681SAndroid Build Coastguard Worker
231*9880d681SAndroid Build Coastguard Worker //%tape.%d = sext i8 %tape.%d to i32
232*9880d681SAndroid Build Coastguard Worker Value *tape_1 = builder->
233*9880d681SAndroid Build Coastguard Worker CreateSExt(tape_0, IntegerType::getInt32Ty(C), tapereg);
234*9880d681SAndroid Build Coastguard Worker
235*9880d681SAndroid Build Coastguard Worker //call i32 @putchar(i32 %tape.%d)
236*9880d681SAndroid Build Coastguard Worker Value *putchar_params[] = {
237*9880d681SAndroid Build Coastguard Worker tape_1
238*9880d681SAndroid Build Coastguard Worker };
239*9880d681SAndroid Build Coastguard Worker CallInst *putchar_call = builder->
240*9880d681SAndroid Build Coastguard Worker CreateCall(putchar_func,
241*9880d681SAndroid Build Coastguard Worker putchar_params);
242*9880d681SAndroid Build Coastguard Worker putchar_call->setTailCall(false);
243*9880d681SAndroid Build Coastguard Worker }
244*9880d681SAndroid Build Coastguard Worker break;
245*9880d681SAndroid Build Coastguard Worker
246*9880d681SAndroid Build Coastguard Worker case SYM_MOVE:
247*9880d681SAndroid Build Coastguard Worker {
248*9880d681SAndroid Build Coastguard Worker //%head.%d = getelementptr i8 *%head.%d, i32 %d
249*9880d681SAndroid Build Coastguard Worker curhead = builder->
250*9880d681SAndroid Build Coastguard Worker CreateGEP(curhead, ConstantInt::get(C, APInt(32, curvalue)),
251*9880d681SAndroid Build Coastguard Worker headreg);
252*9880d681SAndroid Build Coastguard Worker
253*9880d681SAndroid Build Coastguard Worker //Error block for array out of bounds
254*9880d681SAndroid Build Coastguard Worker if (comflag & flag_arraybounds)
255*9880d681SAndroid Build Coastguard Worker {
256*9880d681SAndroid Build Coastguard Worker //%test.%d = icmp uge i8 *%head.%d, %arrmax
257*9880d681SAndroid Build Coastguard Worker Value *test_0 = builder->
258*9880d681SAndroid Build Coastguard Worker CreateICmpUGE(curhead, ptr_arrmax, testreg);
259*9880d681SAndroid Build Coastguard Worker
260*9880d681SAndroid Build Coastguard Worker //%test.%d = icmp ult i8 *%head.%d, %arr
261*9880d681SAndroid Build Coastguard Worker Value *test_1 = builder->
262*9880d681SAndroid Build Coastguard Worker CreateICmpULT(curhead, ptr_arr, testreg);
263*9880d681SAndroid Build Coastguard Worker
264*9880d681SAndroid Build Coastguard Worker //%test.%d = or i1 %test.%d, %test.%d
265*9880d681SAndroid Build Coastguard Worker Value *test_2 = builder->
266*9880d681SAndroid Build Coastguard Worker CreateOr(test_0, test_1, testreg);
267*9880d681SAndroid Build Coastguard Worker
268*9880d681SAndroid Build Coastguard Worker //br i1 %test.%d, label %main.%d, label %main.%d
269*9880d681SAndroid Build Coastguard Worker BasicBlock *nextbb = BasicBlock::Create(C, label, brainf_func);
270*9880d681SAndroid Build Coastguard Worker builder->CreateCondBr(test_2, aberrorbb, nextbb);
271*9880d681SAndroid Build Coastguard Worker
272*9880d681SAndroid Build Coastguard Worker //main.%d:
273*9880d681SAndroid Build Coastguard Worker builder->SetInsertPoint(nextbb);
274*9880d681SAndroid Build Coastguard Worker }
275*9880d681SAndroid Build Coastguard Worker }
276*9880d681SAndroid Build Coastguard Worker break;
277*9880d681SAndroid Build Coastguard Worker
278*9880d681SAndroid Build Coastguard Worker case SYM_CHANGE:
279*9880d681SAndroid Build Coastguard Worker {
280*9880d681SAndroid Build Coastguard Worker //%tape.%d = load i8 *%head.%d
281*9880d681SAndroid Build Coastguard Worker LoadInst *tape_0 = builder->CreateLoad(curhead, tapereg);
282*9880d681SAndroid Build Coastguard Worker
283*9880d681SAndroid Build Coastguard Worker //%tape.%d = add i8 %tape.%d, %d
284*9880d681SAndroid Build Coastguard Worker Value *tape_1 = builder->
285*9880d681SAndroid Build Coastguard Worker CreateAdd(tape_0, ConstantInt::get(C, APInt(8, curvalue)), tapereg);
286*9880d681SAndroid Build Coastguard Worker
287*9880d681SAndroid Build Coastguard Worker //store i8 %tape.%d, i8 *%head.%d\n"
288*9880d681SAndroid Build Coastguard Worker builder->CreateStore(tape_1, curhead);
289*9880d681SAndroid Build Coastguard Worker }
290*9880d681SAndroid Build Coastguard Worker break;
291*9880d681SAndroid Build Coastguard Worker
292*9880d681SAndroid Build Coastguard Worker case SYM_LOOP:
293*9880d681SAndroid Build Coastguard Worker {
294*9880d681SAndroid Build Coastguard Worker //br label %main.%d
295*9880d681SAndroid Build Coastguard Worker BasicBlock *testbb = BasicBlock::Create(C, label, brainf_func);
296*9880d681SAndroid Build Coastguard Worker builder->CreateBr(testbb);
297*9880d681SAndroid Build Coastguard Worker
298*9880d681SAndroid Build Coastguard Worker //main.%d:
299*9880d681SAndroid Build Coastguard Worker BasicBlock *bb_0 = builder->GetInsertBlock();
300*9880d681SAndroid Build Coastguard Worker BasicBlock *bb_1 = BasicBlock::Create(C, label, brainf_func);
301*9880d681SAndroid Build Coastguard Worker builder->SetInsertPoint(bb_1);
302*9880d681SAndroid Build Coastguard Worker
303*9880d681SAndroid Build Coastguard Worker // Make part of PHI instruction now, wait until end of loop to finish
304*9880d681SAndroid Build Coastguard Worker PHINode *phi_0 =
305*9880d681SAndroid Build Coastguard Worker PHINode::Create(PointerType::getUnqual(IntegerType::getInt8Ty(C)),
306*9880d681SAndroid Build Coastguard Worker 2, headreg, testbb);
307*9880d681SAndroid Build Coastguard Worker phi_0->addIncoming(curhead, bb_0);
308*9880d681SAndroid Build Coastguard Worker curhead = phi_0;
309*9880d681SAndroid Build Coastguard Worker
310*9880d681SAndroid Build Coastguard Worker readloop(phi_0, bb_1, testbb, C);
311*9880d681SAndroid Build Coastguard Worker }
312*9880d681SAndroid Build Coastguard Worker break;
313*9880d681SAndroid Build Coastguard Worker
314*9880d681SAndroid Build Coastguard Worker default:
315*9880d681SAndroid Build Coastguard Worker std::cerr << "Error: Unknown symbol.\n";
316*9880d681SAndroid Build Coastguard Worker abort();
317*9880d681SAndroid Build Coastguard Worker break;
318*9880d681SAndroid Build Coastguard Worker }
319*9880d681SAndroid Build Coastguard Worker
320*9880d681SAndroid Build Coastguard Worker cursym = nextsym;
321*9880d681SAndroid Build Coastguard Worker curvalue = nextvalue;
322*9880d681SAndroid Build Coastguard Worker nextsym = SYM_NONE;
323*9880d681SAndroid Build Coastguard Worker
324*9880d681SAndroid Build Coastguard Worker // Reading stdin loop
325*9880d681SAndroid Build Coastguard Worker loop = (cursym == SYM_NONE)
326*9880d681SAndroid Build Coastguard Worker || (cursym == SYM_MOVE)
327*9880d681SAndroid Build Coastguard Worker || (cursym == SYM_CHANGE);
328*9880d681SAndroid Build Coastguard Worker while(loop) {
329*9880d681SAndroid Build Coastguard Worker *in>>c;
330*9880d681SAndroid Build Coastguard Worker if (in->eof()) {
331*9880d681SAndroid Build Coastguard Worker if (cursym == SYM_NONE) {
332*9880d681SAndroid Build Coastguard Worker cursym = SYM_EOF;
333*9880d681SAndroid Build Coastguard Worker } else {
334*9880d681SAndroid Build Coastguard Worker nextsym = SYM_EOF;
335*9880d681SAndroid Build Coastguard Worker }
336*9880d681SAndroid Build Coastguard Worker loop = 0;
337*9880d681SAndroid Build Coastguard Worker } else {
338*9880d681SAndroid Build Coastguard Worker direction = 1;
339*9880d681SAndroid Build Coastguard Worker switch(c) {
340*9880d681SAndroid Build Coastguard Worker case '-':
341*9880d681SAndroid Build Coastguard Worker direction = -1;
342*9880d681SAndroid Build Coastguard Worker // Fall through
343*9880d681SAndroid Build Coastguard Worker
344*9880d681SAndroid Build Coastguard Worker case '+':
345*9880d681SAndroid Build Coastguard Worker if (cursym == SYM_CHANGE) {
346*9880d681SAndroid Build Coastguard Worker curvalue += direction;
347*9880d681SAndroid Build Coastguard Worker // loop = 1
348*9880d681SAndroid Build Coastguard Worker } else {
349*9880d681SAndroid Build Coastguard Worker if (cursym == SYM_NONE) {
350*9880d681SAndroid Build Coastguard Worker cursym = SYM_CHANGE;
351*9880d681SAndroid Build Coastguard Worker curvalue = direction;
352*9880d681SAndroid Build Coastguard Worker // loop = 1
353*9880d681SAndroid Build Coastguard Worker } else {
354*9880d681SAndroid Build Coastguard Worker nextsym = SYM_CHANGE;
355*9880d681SAndroid Build Coastguard Worker nextvalue = direction;
356*9880d681SAndroid Build Coastguard Worker loop = 0;
357*9880d681SAndroid Build Coastguard Worker }
358*9880d681SAndroid Build Coastguard Worker }
359*9880d681SAndroid Build Coastguard Worker break;
360*9880d681SAndroid Build Coastguard Worker
361*9880d681SAndroid Build Coastguard Worker case '<':
362*9880d681SAndroid Build Coastguard Worker direction = -1;
363*9880d681SAndroid Build Coastguard Worker // Fall through
364*9880d681SAndroid Build Coastguard Worker
365*9880d681SAndroid Build Coastguard Worker case '>':
366*9880d681SAndroid Build Coastguard Worker if (cursym == SYM_MOVE) {
367*9880d681SAndroid Build Coastguard Worker curvalue += direction;
368*9880d681SAndroid Build Coastguard Worker // loop = 1
369*9880d681SAndroid Build Coastguard Worker } else {
370*9880d681SAndroid Build Coastguard Worker if (cursym == SYM_NONE) {
371*9880d681SAndroid Build Coastguard Worker cursym = SYM_MOVE;
372*9880d681SAndroid Build Coastguard Worker curvalue = direction;
373*9880d681SAndroid Build Coastguard Worker // loop = 1
374*9880d681SAndroid Build Coastguard Worker } else {
375*9880d681SAndroid Build Coastguard Worker nextsym = SYM_MOVE;
376*9880d681SAndroid Build Coastguard Worker nextvalue = direction;
377*9880d681SAndroid Build Coastguard Worker loop = 0;
378*9880d681SAndroid Build Coastguard Worker }
379*9880d681SAndroid Build Coastguard Worker }
380*9880d681SAndroid Build Coastguard Worker break;
381*9880d681SAndroid Build Coastguard Worker
382*9880d681SAndroid Build Coastguard Worker case ',':
383*9880d681SAndroid Build Coastguard Worker if (cursym == SYM_NONE) {
384*9880d681SAndroid Build Coastguard Worker cursym = SYM_READ;
385*9880d681SAndroid Build Coastguard Worker } else {
386*9880d681SAndroid Build Coastguard Worker nextsym = SYM_READ;
387*9880d681SAndroid Build Coastguard Worker }
388*9880d681SAndroid Build Coastguard Worker loop = 0;
389*9880d681SAndroid Build Coastguard Worker break;
390*9880d681SAndroid Build Coastguard Worker
391*9880d681SAndroid Build Coastguard Worker case '.':
392*9880d681SAndroid Build Coastguard Worker if (cursym == SYM_NONE) {
393*9880d681SAndroid Build Coastguard Worker cursym = SYM_WRITE;
394*9880d681SAndroid Build Coastguard Worker } else {
395*9880d681SAndroid Build Coastguard Worker nextsym = SYM_WRITE;
396*9880d681SAndroid Build Coastguard Worker }
397*9880d681SAndroid Build Coastguard Worker loop = 0;
398*9880d681SAndroid Build Coastguard Worker break;
399*9880d681SAndroid Build Coastguard Worker
400*9880d681SAndroid Build Coastguard Worker case '[':
401*9880d681SAndroid Build Coastguard Worker if (cursym == SYM_NONE) {
402*9880d681SAndroid Build Coastguard Worker cursym = SYM_LOOP;
403*9880d681SAndroid Build Coastguard Worker } else {
404*9880d681SAndroid Build Coastguard Worker nextsym = SYM_LOOP;
405*9880d681SAndroid Build Coastguard Worker }
406*9880d681SAndroid Build Coastguard Worker loop = 0;
407*9880d681SAndroid Build Coastguard Worker break;
408*9880d681SAndroid Build Coastguard Worker
409*9880d681SAndroid Build Coastguard Worker case ']':
410*9880d681SAndroid Build Coastguard Worker if (cursym == SYM_NONE) {
411*9880d681SAndroid Build Coastguard Worker cursym = SYM_ENDLOOP;
412*9880d681SAndroid Build Coastguard Worker } else {
413*9880d681SAndroid Build Coastguard Worker nextsym = SYM_ENDLOOP;
414*9880d681SAndroid Build Coastguard Worker }
415*9880d681SAndroid Build Coastguard Worker loop = 0;
416*9880d681SAndroid Build Coastguard Worker break;
417*9880d681SAndroid Build Coastguard Worker
418*9880d681SAndroid Build Coastguard Worker // Ignore other characters
419*9880d681SAndroid Build Coastguard Worker default:
420*9880d681SAndroid Build Coastguard Worker break;
421*9880d681SAndroid Build Coastguard Worker }
422*9880d681SAndroid Build Coastguard Worker }
423*9880d681SAndroid Build Coastguard Worker }
424*9880d681SAndroid Build Coastguard Worker }
425*9880d681SAndroid Build Coastguard Worker
426*9880d681SAndroid Build Coastguard Worker if (cursym == SYM_ENDLOOP) {
427*9880d681SAndroid Build Coastguard Worker if (!phi) {
428*9880d681SAndroid Build Coastguard Worker std::cerr << "Error: Extra ']'\n";
429*9880d681SAndroid Build Coastguard Worker abort();
430*9880d681SAndroid Build Coastguard Worker }
431*9880d681SAndroid Build Coastguard Worker
432*9880d681SAndroid Build Coastguard Worker // Write loop test
433*9880d681SAndroid Build Coastguard Worker {
434*9880d681SAndroid Build Coastguard Worker //br label %main.%d
435*9880d681SAndroid Build Coastguard Worker builder->CreateBr(testbb);
436*9880d681SAndroid Build Coastguard Worker
437*9880d681SAndroid Build Coastguard Worker //main.%d:
438*9880d681SAndroid Build Coastguard Worker
439*9880d681SAndroid Build Coastguard Worker //%head.%d = phi i8 *[%head.%d, %main.%d], [%head.%d, %main.%d]
440*9880d681SAndroid Build Coastguard Worker //Finish phi made at beginning of loop
441*9880d681SAndroid Build Coastguard Worker phi->addIncoming(curhead, builder->GetInsertBlock());
442*9880d681SAndroid Build Coastguard Worker Value *head_0 = phi;
443*9880d681SAndroid Build Coastguard Worker
444*9880d681SAndroid Build Coastguard Worker //%tape.%d = load i8 *%head.%d
445*9880d681SAndroid Build Coastguard Worker LoadInst *tape_0 = new LoadInst(head_0, tapereg, testbb);
446*9880d681SAndroid Build Coastguard Worker
447*9880d681SAndroid Build Coastguard Worker //%test.%d = icmp eq i8 %tape.%d, 0
448*9880d681SAndroid Build Coastguard Worker ICmpInst *test_0 = new ICmpInst(*testbb, ICmpInst::ICMP_EQ, tape_0,
449*9880d681SAndroid Build Coastguard Worker ConstantInt::get(C, APInt(8, 0)), testreg);
450*9880d681SAndroid Build Coastguard Worker
451*9880d681SAndroid Build Coastguard Worker //br i1 %test.%d, label %main.%d, label %main.%d
452*9880d681SAndroid Build Coastguard Worker BasicBlock *bb_0 = BasicBlock::Create(C, label, brainf_func);
453*9880d681SAndroid Build Coastguard Worker BranchInst::Create(bb_0, oldbb, test_0, testbb);
454*9880d681SAndroid Build Coastguard Worker
455*9880d681SAndroid Build Coastguard Worker //main.%d:
456*9880d681SAndroid Build Coastguard Worker builder->SetInsertPoint(bb_0);
457*9880d681SAndroid Build Coastguard Worker
458*9880d681SAndroid Build Coastguard Worker //%head.%d = phi i8 *[%head.%d, %main.%d]
459*9880d681SAndroid Build Coastguard Worker PHINode *phi_1 = builder->
460*9880d681SAndroid Build Coastguard Worker CreatePHI(PointerType::getUnqual(IntegerType::getInt8Ty(C)), 1,
461*9880d681SAndroid Build Coastguard Worker headreg);
462*9880d681SAndroid Build Coastguard Worker phi_1->addIncoming(head_0, testbb);
463*9880d681SAndroid Build Coastguard Worker curhead = phi_1;
464*9880d681SAndroid Build Coastguard Worker }
465*9880d681SAndroid Build Coastguard Worker
466*9880d681SAndroid Build Coastguard Worker return;
467*9880d681SAndroid Build Coastguard Worker }
468*9880d681SAndroid Build Coastguard Worker
469*9880d681SAndroid Build Coastguard Worker //End of the program, so go to return block
470*9880d681SAndroid Build Coastguard Worker builder->CreateBr(endbb);
471*9880d681SAndroid Build Coastguard Worker
472*9880d681SAndroid Build Coastguard Worker if (phi) {
473*9880d681SAndroid Build Coastguard Worker std::cerr << "Error: Missing ']'\n";
474*9880d681SAndroid Build Coastguard Worker abort();
475*9880d681SAndroid Build Coastguard Worker }
476*9880d681SAndroid Build Coastguard Worker }
477