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