implement runtime operations and add a bunch of logging
This commit is contained in:
parent
51367a253a
commit
f9aec75bf1
@ -2,6 +2,7 @@ package expr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"llvm.org/llvm/bindings/go/llvm"
|
||||
)
|
||||
@ -14,10 +15,11 @@ type BuildCtx struct {
|
||||
func (bctx BuildCtx) Build(ctx Ctx, stmts ...Statement) llvm.Value {
|
||||
var lastVal llvm.Value
|
||||
for _, stmt := range stmts {
|
||||
fmt.Println(stmt)
|
||||
if e := bctx.BuildStmt(ctx, stmt); e != nil {
|
||||
if lv, ok := e.(llvmVal); ok {
|
||||
lastVal = llvm.Value(lv)
|
||||
} else {
|
||||
log.Printf("BuildStmt returned non llvmVal from %v: %v (%T)", stmt, e, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -28,8 +30,18 @@ func (bctx BuildCtx) Build(ctx Ctx, stmts ...Statement) llvm.Value {
|
||||
}
|
||||
|
||||
func (bctx BuildCtx) BuildStmt(ctx Ctx, s Statement) Expr {
|
||||
m := s.Op.(Macro)
|
||||
return ctx.Macro(m)(bctx, ctx, s.Arg)
|
||||
log.Printf("building: %v", s)
|
||||
switch o := s.Op.(type) {
|
||||
case Macro:
|
||||
return ctx.Macro(o)(bctx, ctx, s.Arg)
|
||||
case Identifier:
|
||||
fn := ctx.Identifier(o).(llvmVal)
|
||||
arg := bctx.buildExpr(ctx, s.Arg).(llvmVal)
|
||||
out := bctx.B.CreateCall(llvm.Value(fn), []llvm.Value{llvm.Value(arg)}, "")
|
||||
return llvmVal(out)
|
||||
default:
|
||||
panic(fmt.Sprintf("non op type %v (%T)", s.Op, s.Op))
|
||||
}
|
||||
}
|
||||
|
||||
// may return nil if e is a Statement which has no return
|
||||
@ -94,7 +106,8 @@ var _ = func() bool {
|
||||
"bind": func(bctx BuildCtx, ctx Ctx, e Expr) Expr {
|
||||
tup := bctx.buildExprTill(ctx, e, isIdentifier).(Tuple)
|
||||
id := bctx.buildExprTill(ctx, tup[0], isIdentifier).(Identifier)
|
||||
ctx.Bind(id, bctx.buildExpr(ctx, tup[1]))
|
||||
val := bctx.buildExpr(ctx, tup[1])
|
||||
ctx.Bind(id, val)
|
||||
return NewTuple()
|
||||
},
|
||||
|
||||
@ -129,6 +142,30 @@ var _ = func() bool {
|
||||
}
|
||||
return NewTuple()
|
||||
},
|
||||
|
||||
"op": func(bctx BuildCtx, ctx Ctx, e Expr) Expr {
|
||||
l := bctx.buildExprTill(ctx, e, isList).(List)
|
||||
stmts := make([]Statement, len(l))
|
||||
for i := range l {
|
||||
stmts[i] = l[i].(Statement)
|
||||
}
|
||||
|
||||
// TODO obviously this needs to be fixed
|
||||
fn := llvm.AddFunction(bctx.M, "", llvm.FunctionType(llvm.Int64Type(), []llvm.Type{llvm.Int64Type()}, false))
|
||||
fnbl := llvm.AddBasicBlock(fn, "entry")
|
||||
|
||||
prevbl := bctx.B.GetInsertBlock()
|
||||
bctx.B.SetInsertPoint(fnbl, fnbl.FirstInstruction())
|
||||
out := bctx.Build(NewCtx(), stmts...)
|
||||
bctx.B.CreateRet(out)
|
||||
bctx.B.SetInsertPointAtEnd(prevbl)
|
||||
return llvmVal(fn)
|
||||
},
|
||||
|
||||
"in": func(bctx BuildCtx, ctx Ctx, e Expr) Expr {
|
||||
fn := bctx.B.GetInsertBlock().Parent()
|
||||
return llvmVal(fn.Param(0))
|
||||
},
|
||||
},
|
||||
}
|
||||
return false
|
||||
|
@ -71,6 +71,10 @@ func (i Int) equal(e equaler) bool {
|
||||
return ok && ii == i
|
||||
}
|
||||
|
||||
func (i Int) String() string {
|
||||
return fmt.Sprint(int64(i))
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
// String represents a string value
|
||||
@ -157,6 +161,11 @@ func (l List) equal(e equaler) bool {
|
||||
return ok && exprsEqual(l, ll)
|
||||
}
|
||||
|
||||
func isList(e Expr) bool {
|
||||
_, ok := e.(List)
|
||||
return ok
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Statement represents an actual action which will be taken. The input value is
|
||||
|
90
main.go
90
main.go
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/mediocregopher/ginger/expr"
|
||||
|
||||
@ -17,93 +18,68 @@ func main() {
|
||||
// fmt.Println(e)
|
||||
//}
|
||||
|
||||
log.Printf("initializing llvm")
|
||||
llvm.LinkInMCJIT()
|
||||
llvm.InitializeNativeTarget()
|
||||
llvm.InitializeNativeAsmPrinter()
|
||||
|
||||
// setup our context, builder, and module
|
||||
log.Printf("initializing build context")
|
||||
ctx := expr.NewCtx()
|
||||
bctx := expr.BuildCtx{
|
||||
B: llvm.NewBuilder(),
|
||||
M: llvm.NewModule("my_module"),
|
||||
}
|
||||
|
||||
// do the work in the function
|
||||
log.Printf("making program")
|
||||
add := expr.Macro("add")
|
||||
bind := expr.Macro("bind")
|
||||
do := expr.Macro("do")
|
||||
ctxnew := expr.Macro("ctxnew")
|
||||
ctxbind := expr.Macro("ctxbind")
|
||||
ctxget := expr.Macro("ctxget")
|
||||
|
||||
ctx1 := expr.Identifier("ctx1")
|
||||
ctx2 := expr.Identifier("ctx2")
|
||||
idA := expr.Identifier("A")
|
||||
idB := expr.Identifier("B")
|
||||
|
||||
//myAdd := expr.Identifier("myAdd")
|
||||
out := expr.Identifier("out")
|
||||
// TODO we couldn't actually use this either, because the builder was
|
||||
// changing out the internal values of the List the first time it was hit,
|
||||
// and then just using those the second time around
|
||||
//myAddStmts := expr.NewList(
|
||||
// expr.NewStatement(bind, out, expr.NewStatement(add, idA, idB)),
|
||||
//)
|
||||
|
||||
op := expr.Macro("op")
|
||||
in := expr.Macro("in")
|
||||
incr := expr.Identifier("incr")
|
||||
stmts := []expr.Statement{
|
||||
// TODO revisit how bind and related macros (maybe all macros?) deal
|
||||
// with arguments and their evaluation (keeping an identifier vs
|
||||
// eval-ing it)
|
||||
//expr.NewStatement(bind, myAdd, myAddStmts),
|
||||
|
||||
expr.NewStatement(bind, ctx1, expr.NewStatement(ctxnew)),
|
||||
expr.NewStatement(ctxbind, ctx1, idA, expr.Int(1)),
|
||||
expr.NewStatement(ctxbind, ctx1, idB, expr.Int(2)),
|
||||
expr.NewStatement(do, ctx1, expr.NewList(
|
||||
expr.NewStatement(bind, out, expr.NewStatement(add, idA, idB)),
|
||||
)),
|
||||
|
||||
expr.NewStatement(bind, ctx2, expr.NewStatement(ctxnew)),
|
||||
expr.NewStatement(ctxbind, ctx2, idA, expr.Int(3)),
|
||||
expr.NewStatement(ctxbind, ctx2, idB, expr.Int(4)),
|
||||
expr.NewStatement(do, ctx2, expr.NewList(
|
||||
expr.NewStatement(bind, out, expr.NewStatement(add, idA, idB)),
|
||||
)),
|
||||
expr.NewStatement(bind, incr,
|
||||
expr.NewStatement(op,
|
||||
expr.NewList(
|
||||
expr.NewStatement(add, expr.NewTuple(
|
||||
expr.Int(1),
|
||||
expr.NewStatement(in, expr.NewTuple()),
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
expr.NewStatement(
|
||||
add,
|
||||
expr.NewStatement(ctxget, ctx1, out),
|
||||
expr.NewStatement(ctxget, ctx2, out),
|
||||
incr,
|
||||
expr.Int(5),
|
||||
),
|
||||
}
|
||||
|
||||
// create main and call our function
|
||||
log.Printf("creating main function")
|
||||
mainFn := llvm.AddFunction(bctx.M, "main", llvm.FunctionType(llvm.Int64Type(), []llvm.Type{}, false))
|
||||
mainBlock := llvm.AddBasicBlock(mainFn, "entry")
|
||||
bctx.B.SetInsertPoint(mainBlock, mainBlock.FirstInstruction())
|
||||
v := bctx.Build(ctx, stmts...)
|
||||
bctx.B.CreateRet(v)
|
||||
log.Printf("actually processing program")
|
||||
out := bctx.Build(ctx, stmts...)
|
||||
bctx.B.CreateRet(out)
|
||||
//bctx.Build(ctx, stmts...)
|
||||
//bctx.B.CreateRet(llvm.ConstInt(llvm.Int64Type(), uint64(5), false))
|
||||
|
||||
// verify it's all good
|
||||
fmt.Println("######## dumping IR")
|
||||
bctx.M.Dump()
|
||||
fmt.Println("######## done dumping IR")
|
||||
|
||||
log.Printf("verifying")
|
||||
if err := llvm.VerifyModule(bctx.M, llvm.ReturnStatusAction); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("# verified")
|
||||
|
||||
// Dump the IR
|
||||
fmt.Println("# dumping IR")
|
||||
bctx.M.Dump()
|
||||
fmt.Println("# done dumping IR")
|
||||
|
||||
// create our exe engine
|
||||
fmt.Println("# creating new execution engine")
|
||||
log.Printf("creating execution enging")
|
||||
engine, err := llvm.NewExecutionEngine(bctx.M)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// run the function!
|
||||
fmt.Println("# running the function main")
|
||||
log.Printf("running main function")
|
||||
funcResult := engine.RunFunction(bctx.M.NamedFunction("main"), []llvm.GenericValue{})
|
||||
fmt.Printf("%d\n", funcResult.Int(false))
|
||||
fmt.Printf("\nOUTPUT:\n%d\n", funcResult.Int(false))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user