BrainF.cpp revision 89f6d88db334ba088672ae0753deb7d7b7509bac
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"
28e2c4304654442ca353b307d73c86dce2a4acadbfDuncan Sands#include "llvm/Intrinsics.h"
29bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner#include "llvm/ADT/STLExtras.h"
30bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
31bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattnerusing namespace llvm;
32bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
33bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner//Set the constants for naming
34bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattnerconst char *BrainF::tapereg = "tape";
35bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattnerconst char *BrainF::headreg = "head";
36bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattnerconst char *BrainF::label   = "brainf";
37bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattnerconst char *BrainF::testreg = "test";
38bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
39bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris LattnerModule *BrainF::parse(std::istream *in1, int mem, CompileFlags cf) {
40bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  in       = in1;
41bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  memtotal = mem;
42bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  comflag  = cf;
43bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
44bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  header();
45bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  readloop(0, 0, 0);
46bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  delete builder;
47bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  return module;
48bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner}
49bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
50bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattnervoid BrainF::header() {
51bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  module = new Module("BrainF");
52bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
53bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //Function prototypes
54bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
55bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //declare void @llvm.memset.i32(i8 *, i8, i32, i32)
56e2c4304654442ca353b307d73c86dce2a4acadbfDuncan Sands  Function *memset_func = Intrinsic::getDeclaration(module, Intrinsic::memset_i32);
57bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
58bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //declare i32 @getchar()
59bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  getchar_func = cast<Function>(module->
60bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    getOrInsertFunction("getchar", IntegerType::Int32Ty, NULL));
61bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
62bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //declare i32 @putchar(i32)
63bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  putchar_func = cast<Function>(module->
64bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    getOrInsertFunction("putchar", IntegerType::Int32Ty,
65bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                        IntegerType::Int32Ty, NULL));
66bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
67bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
68bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //Function header
69bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
70bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //define void @brainf()
71bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  brainf_func = cast<Function>(module->
72bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    getOrInsertFunction("brainf", Type::VoidTy, NULL));
73bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
7489f6d88db334ba088672ae0753deb7d7b7509bacDuncan Sands  builder = new IRBuilder(BasicBlock::Create(label, brainf_func));
75bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
76bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //%arr = malloc i8, i32 %d
77bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  ConstantInt *val_mem = ConstantInt::get(APInt(32, memtotal));
78bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  ptr_arr = builder->CreateMalloc(IntegerType::Int8Ty, val_mem, "arr");
79bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
80bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //call void @llvm.memset.i32(i8 *%arr, i8 0, i32 %d, i32 1)
81bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  {
82bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    Value *memset_params[] = {
83bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      ptr_arr,
84bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      ConstantInt::get(APInt(8, 0)),
85bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      val_mem,
86bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      ConstantInt::get(APInt(32, 1))
87bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    };
88bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
89bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    CallInst *memset_call = builder->
90bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      CreateCall(memset_func, memset_params, array_endof(memset_params));
91bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    memset_call->setTailCall(false);
92bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  }
93bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
94bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //%arrmax = getelementptr i8 *%arr, i32 %d
95bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  if (comflag & flag_arraybounds) {
96bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    ptr_arrmax = builder->
97bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      CreateGEP(ptr_arr, ConstantInt::get(APInt(32, memtotal)), "arrmax");
98bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  }
99bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
100bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //%head.%d = getelementptr i8 *%arr, i32 %d
101bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  curhead = builder->CreateGEP(ptr_arr,
102bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                               ConstantInt::get(APInt(32, memtotal/2)),
103bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                               headreg);
104bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
105bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
106bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
107bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //Function footer
108bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
109bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //brainf.end:
110051a950000e21935165db56695e35bade668193bGabor Greif  endbb = BasicBlock::Create(label, brainf_func);
111bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
112bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //free i8 *%arr
113bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  new FreeInst(ptr_arr, endbb);
114bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
115bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //ret void
116051a950000e21935165db56695e35bade668193bGabor Greif  ReturnInst::Create(endbb);
117bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
118bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
119bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
120bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //Error block for array out of bounds
121bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  if (comflag & flag_arraybounds)
122bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  {
123bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    //@aberrormsg = internal constant [%d x i8] c"\00"
124bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    Constant *msg_0 = ConstantArray::
125bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      get("Error: The head has left the tape.", true);
126bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
127bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    GlobalVariable *aberrormsg = new GlobalVariable(
128bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      msg_0->getType(),
129bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      true,
130bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      GlobalValue::InternalLinkage,
131bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      msg_0,
132bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      "aberrormsg",
133bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      module);
134bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
135bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    //declare i32 @puts(i8 *)
136bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    Function *puts_func = cast<Function>(module->
137bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      getOrInsertFunction("puts", IntegerType::Int32Ty,
13843ad6b3e0d6ada51e9b23aab3e061187f1f5710cChristopher Lamb                          PointerType::getUnqual(IntegerType::Int8Ty), NULL));
139bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
140bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    //brainf.aberror:
141051a950000e21935165db56695e35bade668193bGabor Greif    aberrorbb = BasicBlock::Create(label, brainf_func);
142bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
143bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    //call i32 @puts(i8 *getelementptr([%d x i8] *@aberrormsg, i32 0, i32 0))
144bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    {
145bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      Constant *zero_32 = Constant::getNullValue(IntegerType::Int32Ty);
146bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
147bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      Constant *gep_params[] = {
148bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        zero_32,
149bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        zero_32
150bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      };
151bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
152bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      Constant *msgptr = ConstantExpr::
153bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        getGetElementPtr(aberrormsg, gep_params,
154bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                         array_lengthof(gep_params));
155bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
156bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      Value *puts_params[] = {
157bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        msgptr
158bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      };
159bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
160bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      CallInst *puts_call =
161051a950000e21935165db56695e35bade668193bGabor Greif        CallInst::Create(puts_func,
162051a950000e21935165db56695e35bade668193bGabor Greif                         puts_params, array_endof(puts_params),
163051a950000e21935165db56695e35bade668193bGabor Greif                         "", aberrorbb);
164bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      puts_call->setTailCall(false);
165bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    }
166bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
167bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    //br label %brainf.end
168051a950000e21935165db56695e35bade668193bGabor Greif    BranchInst::Create(endbb, aberrorbb);
169bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  }
170bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner}
171bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
172bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattnervoid BrainF::readloop(PHINode *phi, BasicBlock *oldbb, BasicBlock *testbb) {
173bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  Symbol cursym = SYM_NONE;
174bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  int curvalue = 0;
175bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  Symbol nextsym = SYM_NONE;
176bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  int nextvalue = 0;
177bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  char c;
178bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  int loop;
179bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  int direction;
180bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
181bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  while(cursym != SYM_EOF && cursym != SYM_ENDLOOP) {
182bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    // Write out commands
183bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    switch(cursym) {
184bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      case SYM_NONE:
185bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        // Do nothing
186bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        break;
187bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
188bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      case SYM_READ:
189bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        {
190bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          //%tape.%d = call i32 @getchar()
191bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          CallInst *getchar_call = builder->CreateCall(getchar_func, tapereg);
192bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          getchar_call->setTailCall(false);
193bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          Value *tape_0 = getchar_call;
194bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
195bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          //%tape.%d = trunc i32 %tape.%d to i8
19689f6d88db334ba088672ae0753deb7d7b7509bacDuncan Sands          Value *tape_1 = builder->
197bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            CreateTrunc(tape_0, IntegerType::Int8Ty, tapereg);
198bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
199bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          //store i8 %tape.%d, i8 *%head.%d
200bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          builder->CreateStore(tape_1, curhead);
201bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        }
202bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        break;
203bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
204bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      case SYM_WRITE:
205bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        {
206bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          //%tape.%d = load i8 *%head.%d
207bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          LoadInst *tape_0 = builder->CreateLoad(curhead, tapereg);
208bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
209bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          //%tape.%d = sext i8 %tape.%d to i32
21089f6d88db334ba088672ae0753deb7d7b7509bacDuncan Sands          Value *tape_1 = builder->
211bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            CreateSExt(tape_0, IntegerType::Int32Ty, tapereg);
212bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
213bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          //call i32 @putchar(i32 %tape.%d)
214bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          Value *putchar_params[] = {
215bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            tape_1
216bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          };
217bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          CallInst *putchar_call = builder->
218bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            CreateCall(putchar_func,
219bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                       putchar_params, array_endof(putchar_params));
220bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          putchar_call->setTailCall(false);
221bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        }
222bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        break;
223bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
224bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      case SYM_MOVE:
225bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        {
226bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          //%head.%d = getelementptr i8 *%head.%d, i32 %d
227bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          curhead = builder->
228bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            CreateGEP(curhead, ConstantInt::get(APInt(32, curvalue)),
229bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                      headreg);
230bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
231bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          //Error block for array out of bounds
232bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          if (comflag & flag_arraybounds)
233bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          {
234bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            //%test.%d = icmp uge i8 *%head.%d, %arrmax
23589f6d88db334ba088672ae0753deb7d7b7509bacDuncan Sands            Value *test_0 = builder->
236bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              CreateICmpUGE(curhead, ptr_arrmax, testreg);
237bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
238bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            //%test.%d = icmp ult i8 *%head.%d, %arr
23989f6d88db334ba088672ae0753deb7d7b7509bacDuncan Sands            Value *test_1 = builder->
240bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              CreateICmpULT(curhead, ptr_arr, testreg);
241bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
242bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            //%test.%d = or i1 %test.%d, %test.%d
24389f6d88db334ba088672ae0753deb7d7b7509bacDuncan Sands            Value *test_2 = builder->
244bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              CreateOr(test_0, test_1, testreg);
245bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
246bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            //br i1 %test.%d, label %main.%d, label %main.%d
247051a950000e21935165db56695e35bade668193bGabor Greif            BasicBlock *nextbb = BasicBlock::Create(label, brainf_func);
248bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            builder->CreateCondBr(test_2, aberrorbb, nextbb);
249bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
250bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            //main.%d:
251bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            builder->SetInsertPoint(nextbb);
252bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          }
253bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        }
254bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        break;
255bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
256bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      case SYM_CHANGE:
257bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        {
258bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          //%tape.%d = load i8 *%head.%d
259bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          LoadInst *tape_0 = builder->CreateLoad(curhead, tapereg);
260bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
261bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          //%tape.%d = add i8 %tape.%d, %d
26289f6d88db334ba088672ae0753deb7d7b7509bacDuncan Sands          Value *tape_1 = builder->
263bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            CreateAdd(tape_0, ConstantInt::get(APInt(8, curvalue)), tapereg);
264bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
265bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          //store i8 %tape.%d, i8 *%head.%d\n"
266bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          builder->CreateStore(tape_1, curhead);
267bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        }
268bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        break;
269bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
270bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      case SYM_LOOP:
271bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        {
272bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          //br label %main.%d
273051a950000e21935165db56695e35bade668193bGabor Greif          BasicBlock *testbb = BasicBlock::Create(label, brainf_func);
274bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          builder->CreateBr(testbb);
275bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
276bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          //main.%d:
277bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          BasicBlock *bb_0 = builder->GetInsertBlock();
278051a950000e21935165db56695e35bade668193bGabor Greif          BasicBlock *bb_1 = BasicBlock::Create(label, brainf_func);
279bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          builder->SetInsertPoint(bb_1);
280bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
281bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          //Make part of PHI instruction now, wait until end of loop to finish
282051a950000e21935165db56695e35bade668193bGabor Greif          PHINode *phi_0 = PHINode::Create(PointerType::getUnqual(IntegerType::Int8Ty),
283bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                                       headreg, testbb);
284bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          phi_0->reserveOperandSpace(2);
285bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          phi_0->addIncoming(curhead, bb_0);
286bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          curhead = phi_0;
287bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
288bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          readloop(phi_0, bb_1, testbb);
289bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        }
290bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        break;
291bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
292bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      default:
293bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        cerr<<"Error: Unknown symbol.\n";
294bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        abort();
295bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        break;
296bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    }
297bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
298bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    cursym = nextsym;
299bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    curvalue = nextvalue;
300bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    nextsym = SYM_NONE;
301bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
302bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    // Reading stdin loop
303bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    loop = (cursym == SYM_NONE)
304bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        || (cursym == SYM_MOVE)
305bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        || (cursym == SYM_CHANGE);
306bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    while(loop) {
307bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      *in>>c;
308bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      if (in->eof()) {
309bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        if (cursym == SYM_NONE) {
310bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          cursym = SYM_EOF;
311bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        } else {
312bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          nextsym = SYM_EOF;
313bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        }
314bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        loop = 0;
315bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      } else {
316bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        direction = 1;
317bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        switch(c) {
318bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          case '-':
319bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            direction = -1;
320bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            // Fall through
321bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
322bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          case '+':
323bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            if (cursym == SYM_CHANGE) {
324bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              curvalue += direction;
325bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              // loop = 1
326bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            } else {
327bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              if (cursym == SYM_NONE) {
328bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                cursym = SYM_CHANGE;
329bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                curvalue = direction;
330bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                // loop = 1
331bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              } else {
332bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                nextsym = SYM_CHANGE;
333bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                nextvalue = direction;
334bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                loop = 0;
335bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              }
336bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            }
337bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            break;
338bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
339bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          case '<':
340bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            direction = -1;
341bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            // Fall through
342bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
343bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          case '>':
344bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            if (cursym == SYM_MOVE) {
345bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              curvalue += direction;
346bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              // loop = 1
347bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            } else {
348bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              if (cursym == SYM_NONE) {
349bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                cursym = SYM_MOVE;
350bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                curvalue = direction;
351bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                // loop = 1
352bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              } else {
353bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                nextsym = SYM_MOVE;
354bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                nextvalue = direction;
355bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                loop = 0;
356bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              }
357bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            }
358bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            break;
359bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
360bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          case ',':
361bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            if (cursym == SYM_NONE) {
362bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              cursym = SYM_READ;
363bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            } else {
364bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              nextsym = SYM_READ;
365bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            }
366bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            loop = 0;
367bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            break;
368bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
369bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          case '.':
370bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            if (cursym == SYM_NONE) {
371bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              cursym = SYM_WRITE;
372bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            } else {
373bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              nextsym = SYM_WRITE;
374bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            }
375bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            loop = 0;
376bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            break;
377bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
378bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          case '[':
379bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            if (cursym == SYM_NONE) {
380bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              cursym = SYM_LOOP;
381bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            } else {
382bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              nextsym = SYM_LOOP;
383bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            }
384bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            loop = 0;
385bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            break;
386bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
387bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          case ']':
388bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            if (cursym == SYM_NONE) {
389bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              cursym = SYM_ENDLOOP;
390bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            } else {
391bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner              nextsym = SYM_ENDLOOP;
392bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            }
393bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            loop = 0;
394bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            break;
395bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
396bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          // Ignore other characters
397bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner          default:
398bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner            break;
399bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner        }
400bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      }
401bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    }
402bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  }
403bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
404bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  if (cursym == SYM_ENDLOOP) {
405bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    if (!phi) {
406bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      cerr<<"Error: Extra ']'\n";
407bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      abort();
408bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    }
409bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
410bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    // Write loop test
411bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    {
412bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      //br label %main.%d
413bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      builder->CreateBr(testbb);
414bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
415bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      //main.%d:
416bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
417bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      //%head.%d = phi i8 *[%head.%d, %main.%d], [%head.%d, %main.%d]
418bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      //Finish phi made at beginning of loop
419bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      phi->addIncoming(curhead, builder->GetInsertBlock());
420bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      Value *head_0 = phi;
421bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
422bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      //%tape.%d = load i8 *%head.%d
423bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      LoadInst *tape_0 = new LoadInst(head_0, tapereg, testbb);
424bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
425bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      //%test.%d = icmp eq i8 %tape.%d, 0
426bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      ICmpInst *test_0 = new ICmpInst(ICmpInst::ICMP_EQ, tape_0,
427bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                                      ConstantInt::get(APInt(8, 0)), testreg,
428bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner                                      testbb);
429bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
430bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      //br i1 %test.%d, label %main.%d, label %main.%d
431051a950000e21935165db56695e35bade668193bGabor Greif      BasicBlock *bb_0 = BasicBlock::Create(label, brainf_func);
432051a950000e21935165db56695e35bade668193bGabor Greif      BranchInst::Create(bb_0, oldbb, test_0, testbb);
433bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
434bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      //main.%d:
435bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      builder->SetInsertPoint(bb_0);
436bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
437bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      //%head.%d = phi i8 *[%head.%d, %main.%d]
438bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      PHINode *phi_1 = builder->
43943ad6b3e0d6ada51e9b23aab3e061187f1f5710cChristopher Lamb        CreatePHI(PointerType::getUnqual(IntegerType::Int8Ty), headreg);
440bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      phi_1->reserveOperandSpace(1);
441bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      phi_1->addIncoming(head_0, testbb);
442bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner      curhead = phi_1;
443bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    }
444bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
445bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    return;
446bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  }
447bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
448bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  //End of the program, so go to return block
449bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  builder->CreateBr(endbb);
450bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner
451bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  if (phi) {
452bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    cerr<<"Error: Missing ']'\n";
453bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner    abort();
454bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner  }
455bef8e0b0a7afe602ddf09165ff4dbb8fa5f696a9Chris Lattner}
456