diff options
Diffstat (limited to 'contrib/llvm/examples/BrainF/BrainF.cpp')
-rw-r--r-- | contrib/llvm/examples/BrainF/BrainF.cpp | 467 |
1 files changed, 0 insertions, 467 deletions
diff --git a/contrib/llvm/examples/BrainF/BrainF.cpp b/contrib/llvm/examples/BrainF/BrainF.cpp deleted file mode 100644 index a443ad4..0000000 --- a/contrib/llvm/examples/BrainF/BrainF.cpp +++ /dev/null @@ -1,467 +0,0 @@ -//===-- BrainF.cpp - BrainF compiler example ----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===--------------------------------------------------------------------===// -// -// This class compiles the BrainF language into LLVM assembly. -// -// The BrainF language has 8 commands: -// Command Equivalent C Action -// ------- ------------ ------ -// , *h=getchar(); Read a character from stdin, 255 on EOF -// . putchar(*h); Write a character to stdout -// - --*h; Decrement tape -// + ++*h; Increment tape -// < --h; Move head left -// > ++h; Move head right -// [ while(*h) { Start loop -// ] } End loop -// -//===--------------------------------------------------------------------===// - -#include "BrainF.h" -#include "llvm/Constants.h" -#include "llvm/Instructions.h" -#include "llvm/Intrinsics.h" -#include "llvm/ADT/STLExtras.h" -#include <iostream> -using namespace llvm; - -//Set the constants for naming -const char *BrainF::tapereg = "tape"; -const char *BrainF::headreg = "head"; -const char *BrainF::label = "brainf"; -const char *BrainF::testreg = "test"; - -Module *BrainF::parse(std::istream *in1, int mem, CompileFlags cf, - LLVMContext& Context) { - in = in1; - memtotal = mem; - comflag = cf; - - header(Context); - readloop(0, 0, 0, Context); - delete builder; - return module; -} - -void BrainF::header(LLVMContext& C) { - module = new Module("BrainF", C); - - //Function prototypes - - //declare void @llvm.memset.i32(i8 *, i8, i32, i32) - const Type *Tys[] = { Type::getInt32Ty(C) }; - Function *memset_func = Intrinsic::getDeclaration(module, Intrinsic::memset, - Tys, 1); - - //declare i32 @getchar() - getchar_func = cast<Function>(module-> - getOrInsertFunction("getchar", IntegerType::getInt32Ty(C), NULL)); - - //declare i32 @putchar(i32) - putchar_func = cast<Function>(module-> - getOrInsertFunction("putchar", IntegerType::getInt32Ty(C), - IntegerType::getInt32Ty(C), NULL)); - - - //Function header - - //define void @brainf() - brainf_func = cast<Function>(module-> - getOrInsertFunction("brainf", Type::getVoidTy(C), NULL)); - - builder = new IRBuilder<>(BasicBlock::Create(C, label, brainf_func)); - - //%arr = malloc i8, i32 %d - ConstantInt *val_mem = ConstantInt::get(C, APInt(32, memtotal)); - BasicBlock* BB = builder->GetInsertBlock(); - const Type* IntPtrTy = IntegerType::getInt32Ty(C); - const Type* Int8Ty = IntegerType::getInt8Ty(C); - Constant* allocsize = ConstantExpr::getSizeOf(Int8Ty); - allocsize = ConstantExpr::getTruncOrBitCast(allocsize, IntPtrTy); - ptr_arr = CallInst::CreateMalloc(BB, IntPtrTy, Int8Ty, allocsize, val_mem, - NULL, "arr"); - BB->getInstList().push_back(cast<Instruction>(ptr_arr)); - - //call void @llvm.memset.i32(i8 *%arr, i8 0, i32 %d, i32 1) - { - Value *memset_params[] = { - ptr_arr, - ConstantInt::get(C, APInt(8, 0)), - val_mem, - ConstantInt::get(C, APInt(32, 1)) - }; - - CallInst *memset_call = builder-> - CreateCall(memset_func, memset_params, array_endof(memset_params)); - memset_call->setTailCall(false); - } - - //%arrmax = getelementptr i8 *%arr, i32 %d - if (comflag & flag_arraybounds) { - ptr_arrmax = builder-> - CreateGEP(ptr_arr, ConstantInt::get(C, APInt(32, memtotal)), "arrmax"); - } - - //%head.%d = getelementptr i8 *%arr, i32 %d - curhead = builder->CreateGEP(ptr_arr, - ConstantInt::get(C, APInt(32, memtotal/2)), - headreg); - - - - //Function footer - - //brainf.end: - endbb = BasicBlock::Create(C, label, brainf_func); - - //call free(i8 *%arr) - endbb->getInstList().push_back(CallInst::CreateFree(ptr_arr, endbb)); - - //ret void - ReturnInst::Create(C, endbb); - - - - //Error block for array out of bounds - if (comflag & flag_arraybounds) - { - //@aberrormsg = internal constant [%d x i8] c"\00" - Constant *msg_0 = - ConstantArray::get(C, "Error: The head has left the tape.", true); - - GlobalVariable *aberrormsg = new GlobalVariable( - *module, - msg_0->getType(), - true, - GlobalValue::InternalLinkage, - msg_0, - "aberrormsg"); - - //declare i32 @puts(i8 *) - Function *puts_func = cast<Function>(module-> - getOrInsertFunction("puts", IntegerType::getInt32Ty(C), - PointerType::getUnqual(IntegerType::getInt8Ty(C)), NULL)); - - //brainf.aberror: - aberrorbb = BasicBlock::Create(C, label, brainf_func); - - //call i32 @puts(i8 *getelementptr([%d x i8] *@aberrormsg, i32 0, i32 0)) - { - Constant *zero_32 = Constant::getNullValue(IntegerType::getInt32Ty(C)); - - Constant *gep_params[] = { - zero_32, - zero_32 - }; - - Constant *msgptr = ConstantExpr:: - getGetElementPtr(aberrormsg, gep_params, - array_lengthof(gep_params)); - - Value *puts_params[] = { - msgptr - }; - - CallInst *puts_call = - CallInst::Create(puts_func, - puts_params, array_endof(puts_params), - "", aberrorbb); - puts_call->setTailCall(false); - } - - //br label %brainf.end - BranchInst::Create(endbb, aberrorbb); - } -} - -void BrainF::readloop(PHINode *phi, BasicBlock *oldbb, BasicBlock *testbb, - LLVMContext &C) { - Symbol cursym = SYM_NONE; - int curvalue = 0; - Symbol nextsym = SYM_NONE; - int nextvalue = 0; - char c; - int loop; - int direction; - - while(cursym != SYM_EOF && cursym != SYM_ENDLOOP) { - // Write out commands - switch(cursym) { - case SYM_NONE: - // Do nothing - break; - - case SYM_READ: - { - //%tape.%d = call i32 @getchar() - CallInst *getchar_call = builder->CreateCall(getchar_func, tapereg); - getchar_call->setTailCall(false); - Value *tape_0 = getchar_call; - - //%tape.%d = trunc i32 %tape.%d to i8 - Value *tape_1 = builder-> - CreateTrunc(tape_0, IntegerType::getInt8Ty(C), tapereg); - - //store i8 %tape.%d, i8 *%head.%d - builder->CreateStore(tape_1, curhead); - } - break; - - case SYM_WRITE: - { - //%tape.%d = load i8 *%head.%d - LoadInst *tape_0 = builder->CreateLoad(curhead, tapereg); - - //%tape.%d = sext i8 %tape.%d to i32 - Value *tape_1 = builder-> - CreateSExt(tape_0, IntegerType::getInt32Ty(C), tapereg); - - //call i32 @putchar(i32 %tape.%d) - Value *putchar_params[] = { - tape_1 - }; - CallInst *putchar_call = builder-> - CreateCall(putchar_func, - putchar_params, array_endof(putchar_params)); - putchar_call->setTailCall(false); - } - break; - - case SYM_MOVE: - { - //%head.%d = getelementptr i8 *%head.%d, i32 %d - curhead = builder-> - CreateGEP(curhead, ConstantInt::get(C, APInt(32, curvalue)), - headreg); - - //Error block for array out of bounds - if (comflag & flag_arraybounds) - { - //%test.%d = icmp uge i8 *%head.%d, %arrmax - Value *test_0 = builder-> - CreateICmpUGE(curhead, ptr_arrmax, testreg); - - //%test.%d = icmp ult i8 *%head.%d, %arr - Value *test_1 = builder-> - CreateICmpULT(curhead, ptr_arr, testreg); - - //%test.%d = or i1 %test.%d, %test.%d - Value *test_2 = builder-> - CreateOr(test_0, test_1, testreg); - - //br i1 %test.%d, label %main.%d, label %main.%d - BasicBlock *nextbb = BasicBlock::Create(C, label, brainf_func); - builder->CreateCondBr(test_2, aberrorbb, nextbb); - - //main.%d: - builder->SetInsertPoint(nextbb); - } - } - break; - - case SYM_CHANGE: - { - //%tape.%d = load i8 *%head.%d - LoadInst *tape_0 = builder->CreateLoad(curhead, tapereg); - - //%tape.%d = add i8 %tape.%d, %d - Value *tape_1 = builder-> - CreateAdd(tape_0, ConstantInt::get(C, APInt(8, curvalue)), tapereg); - - //store i8 %tape.%d, i8 *%head.%d\n" - builder->CreateStore(tape_1, curhead); - } - break; - - case SYM_LOOP: - { - //br label %main.%d - BasicBlock *testbb = BasicBlock::Create(C, label, brainf_func); - builder->CreateBr(testbb); - - //main.%d: - BasicBlock *bb_0 = builder->GetInsertBlock(); - BasicBlock *bb_1 = BasicBlock::Create(C, label, brainf_func); - builder->SetInsertPoint(bb_1); - - // Make part of PHI instruction now, wait until end of loop to finish - PHINode *phi_0 = - PHINode::Create(PointerType::getUnqual(IntegerType::getInt8Ty(C)), - headreg, testbb); - phi_0->reserveOperandSpace(2); - phi_0->addIncoming(curhead, bb_0); - curhead = phi_0; - - readloop(phi_0, bb_1, testbb, C); - } - break; - - default: - std::cerr << "Error: Unknown symbol.\n"; - abort(); - break; - } - - cursym = nextsym; - curvalue = nextvalue; - nextsym = SYM_NONE; - - // Reading stdin loop - loop = (cursym == SYM_NONE) - || (cursym == SYM_MOVE) - || (cursym == SYM_CHANGE); - while(loop) { - *in>>c; - if (in->eof()) { - if (cursym == SYM_NONE) { - cursym = SYM_EOF; - } else { - nextsym = SYM_EOF; - } - loop = 0; - } else { - direction = 1; - switch(c) { - case '-': - direction = -1; - // Fall through - - case '+': - if (cursym == SYM_CHANGE) { - curvalue += direction; - // loop = 1 - } else { - if (cursym == SYM_NONE) { - cursym = SYM_CHANGE; - curvalue = direction; - // loop = 1 - } else { - nextsym = SYM_CHANGE; - nextvalue = direction; - loop = 0; - } - } - break; - - case '<': - direction = -1; - // Fall through - - case '>': - if (cursym == SYM_MOVE) { - curvalue += direction; - // loop = 1 - } else { - if (cursym == SYM_NONE) { - cursym = SYM_MOVE; - curvalue = direction; - // loop = 1 - } else { - nextsym = SYM_MOVE; - nextvalue = direction; - loop = 0; - } - } - break; - - case ',': - if (cursym == SYM_NONE) { - cursym = SYM_READ; - } else { - nextsym = SYM_READ; - } - loop = 0; - break; - - case '.': - if (cursym == SYM_NONE) { - cursym = SYM_WRITE; - } else { - nextsym = SYM_WRITE; - } - loop = 0; - break; - - case '[': - if (cursym == SYM_NONE) { - cursym = SYM_LOOP; - } else { - nextsym = SYM_LOOP; - } - loop = 0; - break; - - case ']': - if (cursym == SYM_NONE) { - cursym = SYM_ENDLOOP; - } else { - nextsym = SYM_ENDLOOP; - } - loop = 0; - break; - - // Ignore other characters - default: - break; - } - } - } - } - - if (cursym == SYM_ENDLOOP) { - if (!phi) { - std::cerr << "Error: Extra ']'\n"; - abort(); - } - - // Write loop test - { - //br label %main.%d - builder->CreateBr(testbb); - - //main.%d: - - //%head.%d = phi i8 *[%head.%d, %main.%d], [%head.%d, %main.%d] - //Finish phi made at beginning of loop - phi->addIncoming(curhead, builder->GetInsertBlock()); - Value *head_0 = phi; - - //%tape.%d = load i8 *%head.%d - LoadInst *tape_0 = new LoadInst(head_0, tapereg, testbb); - - //%test.%d = icmp eq i8 %tape.%d, 0 - ICmpInst *test_0 = new ICmpInst(*testbb, ICmpInst::ICMP_EQ, tape_0, - ConstantInt::get(C, APInt(8, 0)), testreg); - - //br i1 %test.%d, label %main.%d, label %main.%d - BasicBlock *bb_0 = BasicBlock::Create(C, label, brainf_func); - BranchInst::Create(bb_0, oldbb, test_0, testbb); - - //main.%d: - builder->SetInsertPoint(bb_0); - - //%head.%d = phi i8 *[%head.%d, %main.%d] - PHINode *phi_1 = builder-> - CreatePHI(PointerType::getUnqual(IntegerType::getInt8Ty(C)), headreg); - phi_1->reserveOperandSpace(1); - phi_1->addIncoming(head_0, testbb); - curhead = phi_1; - } - - return; - } - - //End of the program, so go to return block - builder->CreateBr(endbb); - - if (phi) { - std::cerr << "Error: Missing ']'\n"; - abort(); - } -} |