diff options
Diffstat (limited to 'contrib/llvm/examples/BrainF')
-rw-r--r-- | contrib/llvm/examples/BrainF/BrainF.cpp | 467 | ||||
-rw-r--r-- | contrib/llvm/examples/BrainF/BrainF.h | 94 | ||||
-rw-r--r-- | contrib/llvm/examples/BrainF/BrainFDriver.cpp | 160 | ||||
-rw-r--r-- | contrib/llvm/examples/BrainF/CMakeLists.txt | 6 | ||||
-rw-r--r-- | contrib/llvm/examples/BrainF/Makefile | 15 |
5 files changed, 0 insertions, 742 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(); - } -} diff --git a/contrib/llvm/examples/BrainF/BrainF.h b/contrib/llvm/examples/BrainF/BrainF.h deleted file mode 100644 index add0687..0000000 --- a/contrib/llvm/examples/BrainF/BrainF.h +++ /dev/null @@ -1,94 +0,0 @@ -//===-- BrainF.h - BrainF compiler class ----------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===--------------------------------------------------------------------===// -// -// This class stores the data for the BrainF compiler so it doesn't have -// to pass all of it around. The main method is parse. -// -//===--------------------------------------------------------------------===// - -#ifndef BRAINF_H -#define BRAINF_H - -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/Support/IRBuilder.h" - -using namespace llvm; - -/// This class provides a parser for the BrainF language. -/// The class itself is made to store values during -/// parsing so they don't have to be passed around -/// as much. -class BrainF { - public: - /// Options for how BrainF should compile - enum CompileFlags { - flag_off = 0, - flag_arraybounds = 1 - }; - - /// This is the main method. It parses BrainF from in1 - /// and returns the module with a function - /// void brainf() - /// containing the resulting code. - /// On error, it calls abort. - /// The caller must delete the returned module. - Module *parse(std::istream *in1, int mem, CompileFlags cf, - LLVMContext& C); - - protected: - /// The different symbols in the BrainF language - enum Symbol { - SYM_NONE, - SYM_READ, - SYM_WRITE, - SYM_MOVE, - SYM_CHANGE, - SYM_LOOP, - SYM_ENDLOOP, - SYM_EOF - }; - - /// Names of the different parts of the language. - /// Tape is used for reading and writing the tape. - /// headreg is used for the position of the head. - /// label is used for the labels for the BasicBlocks. - /// testreg is used for testing the loop exit condition. - static const char *tapereg; - static const char *headreg; - static const char *label; - static const char *testreg; - - /// Put the brainf function preamble and other fixed pieces of code - void header(LLVMContext& C); - - /// The main loop for parsing. It calls itself recursively - /// to handle the depth of nesting of "[]". - void readloop(PHINode *phi, BasicBlock *oldbb, - BasicBlock *testbb, LLVMContext &Context); - - /// Constants during parsing - int memtotal; - CompileFlags comflag; - std::istream *in; - Module *module; - Function *brainf_func; - Function *getchar_func; - Function *putchar_func; - Value *ptr_arr; - Value *ptr_arrmax; - BasicBlock *endbb; - BasicBlock *aberrorbb; - - /// Variables - IRBuilder<> *builder; - Value *curhead; -}; - -#endif diff --git a/contrib/llvm/examples/BrainF/BrainFDriver.cpp b/contrib/llvm/examples/BrainF/BrainFDriver.cpp deleted file mode 100644 index c11a580..0000000 --- a/contrib/llvm/examples/BrainF/BrainFDriver.cpp +++ /dev/null @@ -1,160 +0,0 @@ -//===-- BrainFDriver.cpp - BrainF compiler driver -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===--------------------------------------------------------------------===// -// -// This program converts the BrainF language into LLVM assembly, -// which it can then run using the JIT or output as BitCode. -// -// This implementation has a tape of 65536 bytes, -// with the head starting in the middle. -// Range checking is off by default, so be careful. -// It can be enabled with -abc. -// -// Use: -// ./BrainF -jit prog.bf #Run program now -// ./BrainF -jit -abc prog.bf #Run program now safely -// ./BrainF prog.bf #Write as BitCode -// -// lli prog.bf.bc #Run generated BitCode -// llvm-ld -native -o=prog prog.bf.bc #Compile BitCode into native executable -// -//===--------------------------------------------------------------------===// - -#include "BrainF.h" -#include "llvm/Constants.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/Target/TargetSelect.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/raw_ostream.h" -#include <iostream> -#include <fstream> -using namespace llvm; - -//Command line options - -static cl::opt<std::string> -InputFilename(cl::Positional, cl::desc("<input brainf>")); - -static cl::opt<std::string> -OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); - -static cl::opt<bool> -ArrayBoundsChecking("abc", cl::desc("Enable array bounds checking")); - -static cl::opt<bool> -JIT("jit", cl::desc("Run program Just-In-Time")); - - -//Add main function so can be fully compiled -void addMainFunction(Module *mod) { - //define i32 @main(i32 %argc, i8 **%argv) - Function *main_func = cast<Function>(mod-> - getOrInsertFunction("main", IntegerType::getInt32Ty(mod->getContext()), - IntegerType::getInt32Ty(mod->getContext()), - PointerType::getUnqual(PointerType::getUnqual( - IntegerType::getInt8Ty(mod->getContext()))), NULL)); - { - Function::arg_iterator args = main_func->arg_begin(); - Value *arg_0 = args++; - arg_0->setName("argc"); - Value *arg_1 = args++; - arg_1->setName("argv"); - } - - //main.0: - BasicBlock *bb = BasicBlock::Create(mod->getContext(), "main.0", main_func); - - //call void @brainf() - { - CallInst *brainf_call = CallInst::Create(mod->getFunction("brainf"), - "", bb); - brainf_call->setTailCall(false); - } - - //ret i32 0 - ReturnInst::Create(mod->getContext(), - ConstantInt::get(mod->getContext(), APInt(32, 0)), bb); -} - -int main(int argc, char **argv) { - cl::ParseCommandLineOptions(argc, argv, " BrainF compiler\n"); - - LLVMContext &Context = getGlobalContext(); - - if (InputFilename == "") { - errs() << "Error: You must specify the filename of the program to " - "be compiled. Use --help to see the options.\n"; - abort(); - } - - //Get the output stream - raw_ostream *out = &outs(); - if (!JIT) { - if (OutputFilename == "") { - std::string base = InputFilename; - if (InputFilename == "-") { base = "a"; } - - // Use default filename. - OutputFilename = base+".bc"; - } - if (OutputFilename != "-") { - std::string ErrInfo; - out = new raw_fd_ostream(OutputFilename.c_str(), ErrInfo, - raw_fd_ostream::F_Binary); - } - } - - //Get the input stream - std::istream *in = &std::cin; - if (InputFilename != "-") - in = new std::ifstream(InputFilename.c_str()); - - //Gather the compile flags - BrainF::CompileFlags cf = BrainF::flag_off; - if (ArrayBoundsChecking) - cf = BrainF::CompileFlags(cf | BrainF::flag_arraybounds); - - //Read the BrainF program - BrainF bf; - Module *mod = bf.parse(in, 65536, cf, Context); //64 KiB - if (in != &std::cin) - delete in; - addMainFunction(mod); - - //Verify generated code - if (verifyModule(*mod)) { - errs() << "Error: module failed verification. This shouldn't happen.\n"; - abort(); - } - - //Write it out - if (JIT) { - InitializeNativeTarget(); - - outs() << "------- Running JIT -------\n"; - ExecutionEngine *ee = EngineBuilder(mod).create(); - std::vector<GenericValue> args; - Function *brainf_func = mod->getFunction("brainf"); - GenericValue gv = ee->runFunction(brainf_func, args); - } else { - WriteBitcodeToFile(mod, *out); - } - - //Clean up - if (out != &outs()) - delete out; - delete mod; - - llvm_shutdown(); - - return 0; -} diff --git a/contrib/llvm/examples/BrainF/CMakeLists.txt b/contrib/llvm/examples/BrainF/CMakeLists.txt deleted file mode 100644 index 7bec105..0000000 --- a/contrib/llvm/examples/BrainF/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -set(LLVM_LINK_COMPONENTS jit bitwriter nativecodegen interpreter) - -add_llvm_example(BrainF - BrainF.cpp - BrainFDriver.cpp - ) diff --git a/contrib/llvm/examples/BrainF/Makefile b/contrib/llvm/examples/BrainF/Makefile deleted file mode 100644 index 2c3e066..0000000 --- a/contrib/llvm/examples/BrainF/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- examples/BrainF/Makefile ----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = BrainF -EXAMPLE_TOOL = 1 - -LINK_COMPONENTS := jit bitwriter nativecodegen interpreter - -include $(LEVEL)/Makefile.common |