xref: /aosp_15_r20/external/llvm/examples/BrainF/BrainF.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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