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