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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
"llvm.org/llvm/bindings/go/llvm"
|
"llvm.org/llvm/bindings/go/llvm"
|
||||||
)
|
)
|
||||||
@ -14,10 +15,11 @@ type BuildCtx struct {
|
|||||||
func (bctx BuildCtx) Build(ctx Ctx, stmts ...Statement) llvm.Value {
|
func (bctx BuildCtx) Build(ctx Ctx, stmts ...Statement) llvm.Value {
|
||||||
var lastVal llvm.Value
|
var lastVal llvm.Value
|
||||||
for _, stmt := range stmts {
|
for _, stmt := range stmts {
|
||||||
fmt.Println(stmt)
|
|
||||||
if e := bctx.BuildStmt(ctx, stmt); e != nil {
|
if e := bctx.BuildStmt(ctx, stmt); e != nil {
|
||||||
if lv, ok := e.(llvmVal); ok {
|
if lv, ok := e.(llvmVal); ok {
|
||||||
lastVal = llvm.Value(lv)
|
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 {
|
func (bctx BuildCtx) BuildStmt(ctx Ctx, s Statement) Expr {
|
||||||
m := s.Op.(Macro)
|
log.Printf("building: %v", s)
|
||||||
return ctx.Macro(m)(bctx, ctx, s.Arg)
|
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
|
// 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 {
|
"bind": func(bctx BuildCtx, ctx Ctx, e Expr) Expr {
|
||||||
tup := bctx.buildExprTill(ctx, e, isIdentifier).(Tuple)
|
tup := bctx.buildExprTill(ctx, e, isIdentifier).(Tuple)
|
||||||
id := bctx.buildExprTill(ctx, tup[0], isIdentifier).(Identifier)
|
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()
|
return NewTuple()
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -129,6 +142,30 @@ var _ = func() bool {
|
|||||||
}
|
}
|
||||||
return NewTuple()
|
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
|
return false
|
||||||
|
@ -71,6 +71,10 @@ func (i Int) equal(e equaler) bool {
|
|||||||
return ok && ii == i
|
return ok && ii == i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i Int) String() string {
|
||||||
|
return fmt.Sprint(int64(i))
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/*
|
/*
|
||||||
// String represents a string value
|
// String represents a string value
|
||||||
@ -157,6 +161,11 @@ func (l List) equal(e equaler) bool {
|
|||||||
return ok && exprsEqual(l, ll)
|
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
|
// Statement represents an actual action which will be taken. The input value is
|
||||||
|
88
main.go
88
main.go
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/mediocregopher/ginger/expr"
|
"github.com/mediocregopher/ginger/expr"
|
||||||
|
|
||||||
@ -17,93 +18,68 @@ func main() {
|
|||||||
// fmt.Println(e)
|
// fmt.Println(e)
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
log.Printf("initializing llvm")
|
||||||
llvm.LinkInMCJIT()
|
llvm.LinkInMCJIT()
|
||||||
llvm.InitializeNativeTarget()
|
llvm.InitializeNativeTarget()
|
||||||
llvm.InitializeNativeAsmPrinter()
|
llvm.InitializeNativeAsmPrinter()
|
||||||
|
|
||||||
// setup our context, builder, and module
|
log.Printf("initializing build context")
|
||||||
ctx := expr.NewCtx()
|
ctx := expr.NewCtx()
|
||||||
bctx := expr.BuildCtx{
|
bctx := expr.BuildCtx{
|
||||||
B: llvm.NewBuilder(),
|
B: llvm.NewBuilder(),
|
||||||
M: llvm.NewModule("my_module"),
|
M: llvm.NewModule("my_module"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// do the work in the function
|
log.Printf("making program")
|
||||||
add := expr.Macro("add")
|
add := expr.Macro("add")
|
||||||
bind := expr.Macro("bind")
|
bind := expr.Macro("bind")
|
||||||
do := expr.Macro("do")
|
op := expr.Macro("op")
|
||||||
ctxnew := expr.Macro("ctxnew")
|
in := expr.Macro("in")
|
||||||
ctxbind := expr.Macro("ctxbind")
|
incr := expr.Identifier("incr")
|
||||||
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)),
|
|
||||||
//)
|
|
||||||
|
|
||||||
stmts := []expr.Statement{
|
stmts := []expr.Statement{
|
||||||
// TODO revisit how bind and related macros (maybe all macros?) deal
|
expr.NewStatement(bind, incr,
|
||||||
// with arguments and their evaluation (keeping an identifier vs
|
expr.NewStatement(op,
|
||||||
// eval-ing it)
|
expr.NewList(
|
||||||
//expr.NewStatement(bind, myAdd, myAddStmts),
|
expr.NewStatement(add, expr.NewTuple(
|
||||||
|
expr.Int(1),
|
||||||
expr.NewStatement(bind, ctx1, expr.NewStatement(ctxnew)),
|
expr.NewStatement(in, expr.NewTuple()),
|
||||||
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(
|
expr.NewStatement(
|
||||||
add,
|
incr,
|
||||||
expr.NewStatement(ctxget, ctx1, out),
|
expr.Int(5),
|
||||||
expr.NewStatement(ctxget, ctx2, out),
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
// create main and call our function
|
log.Printf("creating main function")
|
||||||
mainFn := llvm.AddFunction(bctx.M, "main", llvm.FunctionType(llvm.Int64Type(), []llvm.Type{}, false))
|
mainFn := llvm.AddFunction(bctx.M, "main", llvm.FunctionType(llvm.Int64Type(), []llvm.Type{}, false))
|
||||||
mainBlock := llvm.AddBasicBlock(mainFn, "entry")
|
mainBlock := llvm.AddBasicBlock(mainFn, "entry")
|
||||||
bctx.B.SetInsertPoint(mainBlock, mainBlock.FirstInstruction())
|
bctx.B.SetInsertPoint(mainBlock, mainBlock.FirstInstruction())
|
||||||
v := bctx.Build(ctx, stmts...)
|
log.Printf("actually processing program")
|
||||||
bctx.B.CreateRet(v)
|
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 {
|
if err := llvm.VerifyModule(bctx.M, llvm.ReturnStatusAction); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
fmt.Println("# verified")
|
|
||||||
|
|
||||||
// Dump the IR
|
log.Printf("creating execution enging")
|
||||||
fmt.Println("# dumping IR")
|
|
||||||
bctx.M.Dump()
|
|
||||||
fmt.Println("# done dumping IR")
|
|
||||||
|
|
||||||
// create our exe engine
|
|
||||||
fmt.Println("# creating new execution engine")
|
|
||||||
engine, err := llvm.NewExecutionEngine(bctx.M)
|
engine, err := llvm.NewExecutionEngine(bctx.M)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the function!
|
log.Printf("running main function")
|
||||||
fmt.Println("# running the function main")
|
|
||||||
funcResult := engine.RunFunction(bctx.M.NamedFunction("main"), []llvm.GenericValue{})
|
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