2016-07-23 17:06:26 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/mediocregopher/ginger/expr"
|
2016-07-24 21:57:43 +00:00
|
|
|
|
|
|
|
"llvm.org/llvm/bindings/go/llvm"
|
2016-07-23 17:06:26 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
2016-07-24 21:57:43 +00:00
|
|
|
//ee, err := expr.Parse(os.Stdin)
|
|
|
|
//if err != nil {
|
|
|
|
// panic(err)
|
|
|
|
//}
|
|
|
|
//for _, e := range ee {
|
|
|
|
// fmt.Println(e)
|
|
|
|
//}
|
|
|
|
|
|
|
|
llvm.LinkInMCJIT()
|
|
|
|
llvm.InitializeNativeTarget()
|
|
|
|
llvm.InitializeNativeAsmPrinter()
|
|
|
|
|
2016-08-06 18:20:53 +00:00
|
|
|
// setup our context, builder, and module
|
2016-08-07 15:06:46 +00:00
|
|
|
ctx := expr.NewCtx()
|
2016-08-06 18:20:53 +00:00
|
|
|
bctx := expr.BuildCtx{
|
2016-08-02 00:08:51 +00:00
|
|
|
B: llvm.NewBuilder(),
|
|
|
|
M: llvm.NewModule("my_module"),
|
|
|
|
}
|
2016-07-24 21:57:43 +00:00
|
|
|
|
2016-08-02 00:08:51 +00:00
|
|
|
// do the work in the function
|
2016-08-06 18:36:46 +00:00
|
|
|
add := expr.Macro("add")
|
|
|
|
bind := expr.Macro("bind")
|
2016-08-09 01:43:05 +00:00
|
|
|
do := expr.Macro("do")
|
|
|
|
ctxnew := expr.Macro("ctxnew")
|
|
|
|
ctxbind := expr.Macro("ctxbind")
|
|
|
|
ctxget := expr.Macro("ctxget")
|
|
|
|
|
|
|
|
ctx1 := expr.Identifier("ctx1")
|
|
|
|
ctx2 := expr.Identifier("ctx2")
|
2016-08-06 18:36:46 +00:00
|
|
|
idA := expr.Identifier("A")
|
|
|
|
idB := expr.Identifier("B")
|
2016-08-09 01:43:05 +00:00
|
|
|
|
|
|
|
//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)),
|
|
|
|
//)
|
|
|
|
|
2016-08-06 18:36:46 +00:00
|
|
|
stmts := []expr.Statement{
|
2016-08-09 01:43:05 +00:00
|
|
|
// 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),
|
2016-08-05 18:34:17 +00:00
|
|
|
|
2016-08-09 01:43:05 +00:00
|
|
|
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(
|
|
|
|
add,
|
|
|
|
expr.NewStatement(ctxget, ctx1, out),
|
|
|
|
expr.NewStatement(ctxget, ctx2, out),
|
|
|
|
),
|
|
|
|
}
|
2016-08-02 00:08:51 +00:00
|
|
|
|
|
|
|
// create main and call our function
|
2016-08-06 18:20:53 +00:00
|
|
|
mainFn := llvm.AddFunction(bctx.M, "main", llvm.FunctionType(llvm.Int64Type(), []llvm.Type{}, false))
|
2016-08-02 00:08:51 +00:00
|
|
|
mainBlock := llvm.AddBasicBlock(mainFn, "entry")
|
2016-08-06 18:20:53 +00:00
|
|
|
bctx.B.SetInsertPoint(mainBlock, mainBlock.FirstInstruction())
|
2016-08-09 01:43:05 +00:00
|
|
|
v := bctx.Build(ctx, stmts...)
|
2016-08-06 18:20:53 +00:00
|
|
|
bctx.B.CreateRet(v)
|
2016-07-28 19:57:17 +00:00
|
|
|
|
2016-07-24 21:57:43 +00:00
|
|
|
// verify it's all good
|
2016-08-06 18:20:53 +00:00
|
|
|
if err := llvm.VerifyModule(bctx.M, llvm.ReturnStatusAction); err != nil {
|
2016-07-23 17:06:26 +00:00
|
|
|
panic(err)
|
|
|
|
}
|
2016-07-24 21:57:43 +00:00
|
|
|
fmt.Println("# verified")
|
|
|
|
|
|
|
|
// Dump the IR
|
|
|
|
fmt.Println("# dumping IR")
|
2016-08-06 18:20:53 +00:00
|
|
|
bctx.M.Dump()
|
2016-07-24 21:57:43 +00:00
|
|
|
fmt.Println("# done dumping IR")
|
|
|
|
|
|
|
|
// create our exe engine
|
|
|
|
fmt.Println("# creating new execution engine")
|
2016-08-06 18:20:53 +00:00
|
|
|
engine, err := llvm.NewExecutionEngine(bctx.M)
|
2016-07-24 21:57:43 +00:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
2016-07-23 17:06:26 +00:00
|
|
|
}
|
2016-07-24 21:57:43 +00:00
|
|
|
|
|
|
|
// run the function!
|
|
|
|
fmt.Println("# running the function main")
|
2016-08-06 18:20:53 +00:00
|
|
|
funcResult := engine.RunFunction(bctx.M.NamedFunction("main"), []llvm.GenericValue{})
|
2016-07-24 21:57:43 +00:00
|
|
|
fmt.Printf("%d\n", funcResult.Int(false))
|
2016-07-23 17:06:26 +00:00
|
|
|
}
|