// Init is the rule that defines our entire program. public VisitResult VisitInit([Antlr4.Runtime.Misc.NotNull] BFParser.InitContext context) { // Create our builder. builder = LLVM.CreateBuilder(); // Define all the functions we need to make a BF program. This includes input, output, and memory management programs to get our initial block of memory. outputFunc = LLVM.AddFunction(mod, "putchar", LLVM.FunctionType(LLVM.Int32Type(), new LLVMTypeRef[] { LLVM.Int8Type() }, false)); inputFunc = LLVM.AddFunction(mod, "getchar", LLVM.FunctionType(LLVM.Int8Type(), new LLVMTypeRef[] {}, false)); var malloc = LLVM.AddFunction(mod, "malloc", LLVM.FunctionType(LLVM.PointerType(LLVM.Int32Type(), 0), new LLVMTypeRef[] { LLVM.Int32Type() }, false)); var memset = LLVM.AddFunction(mod, "memset", LLVM.FunctionType(LLVM.PointerType(LLVM.Int32Type(), 0), new LLVMTypeRef[] { LLVM.PointerType(LLVM.Int32Type(), 0), LLVM.Int32Type(), LLVM.Int32Type() }, false)); var free = LLVM.AddFunction(mod, "free", LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] { LLVM.PointerType(LLVM.Int32Type(), 0) }, false)); main = LLVM.AddFunction(mod, "main", LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] {}, false)); // Start the entry point. var entry = LLVM.AppendBasicBlock(main, "entry"); LLVM.PositionBuilderAtEnd(builder, entry); // Call malloc to get a void* (which is actually a int32*) that points to our program memory. We will just allocate a chunk to play with. basePtr = LLVM.BuildCall(builder, malloc, new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), memSize, false) }, "basePtr"); // Set memory to 0 (otherwise BF would almost never work). LLVM.BuildCall(builder, memset, new LLVMValueRef[] { basePtr, LLVM.ConstInt(LLVM.Int32Type(), 0, true), LLVM.ConstInt(LLVM.Int32Type(), memSize, false) }, "callMemset"); // Due to how LLVM works, once creating pointer we wouldn't be able to use it again. To counter this, we create a pointer to our pointer. ptr = LLVM.BuildAlloca(builder, LLVM.PointerType(LLVM.Int8Type(), 0), "ptr"); // Cast our void* as a int8* and set our pointer value to it. SetValue(ptr, LLVM.BuildPointerCast(builder, basePtr, LLVM.PointerType(LLVM.Int8Type(), 0), "tempPtr")); // This is where we actually start adding our program instructions. for (int i = 0; i < context.ChildCount; i++) { context.GetChild(i).Accept(visitor); } // Free our malloc'd memory and return nothing. LLVM.BuildFree(builder, basePtr); LLVM.BuildRetVoid(builder); return(null); }
/// <summary> /// Exit a parse tree produced by <see cref="BFParser.init"/>. /// <para>The default implementation does nothing.</para> /// </summary> /// <param name="context">The parse tree.</param> public virtual void ExitInit([NotNull] BFParser.InitContext context) { }
/// <summary> /// Visit a parse tree produced by <see cref="BFParser.init"/>. /// <para> /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/> /// on <paramref name="context"/>. /// </para> /// </summary> /// <param name="context">The parse tree.</param> /// <return>The visitor result.</return> public virtual Result VisitInit([NotNull] BFParser.InitContext context) { return(VisitChildren(context)); }