Ejemplo n.º 1
0
    // 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);
    }
Ejemplo n.º 2
0
 /// <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)
 {
 }
Ejemplo n.º 3
0
 /// <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));
 }