actually connect Expr to llvm somewhat, wrote addExpr
This commit is contained in:
parent
b53da9531c
commit
fd125b3dcd
58
expr/expr.go
58
expr/expr.go
@ -6,12 +6,18 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"llvm.org/llvm/bindings/go/llvm"
|
||||||
|
|
||||||
"github.com/mediocregopher/ginger/lexer"
|
"github.com/mediocregopher/ginger/lexer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO empty blocks
|
// TODO empty blocks
|
||||||
// TODO empty parenthesis
|
// TODO empty parenthesis
|
||||||
|
|
||||||
|
// TODO having Equal as part of the Actual interface is going to be annoying.
|
||||||
|
// The built in macros which return their own expressions don't really care
|
||||||
|
// about it, and it's really only needed for tests I think.
|
||||||
|
|
||||||
// Actual represents the actual expression in question, and has certain
|
// Actual represents the actual expression in question, and has certain
|
||||||
// properties. It is wrapped by Expr which also holds onto contextual
|
// properties. It is wrapped by Expr which also holds onto contextual
|
||||||
// information, like the token to which Actual was originally parsed from
|
// information, like the token to which Actual was originally parsed from
|
||||||
@ -19,6 +25,9 @@ type Actual interface {
|
|||||||
// Equal should return true if the type and value of the other expression
|
// Equal should return true if the type and value of the other expression
|
||||||
// are equal.
|
// are equal.
|
||||||
Equal(Actual) bool
|
Equal(Actual) bool
|
||||||
|
|
||||||
|
// Initializes an llvm.Value and returns it
|
||||||
|
LLVMVal(llvm.Builder) llvm.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expr contains the actual expression as well as some contextual information
|
// Expr contains the actual expression as well as some contextual information
|
||||||
@ -29,6 +38,16 @@ type Expr struct {
|
|||||||
|
|
||||||
// Token is a nice-to-have, nothing will break if it's not there
|
// Token is a nice-to-have, nothing will break if it's not there
|
||||||
Token lexer.Token
|
Token lexer.Token
|
||||||
|
|
||||||
|
val *llvm.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Expr) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
if e.val == nil {
|
||||||
|
v := e.Actual.LLVMVal(builder)
|
||||||
|
e.val = &v
|
||||||
|
}
|
||||||
|
return *e.val
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -45,6 +64,10 @@ func (b Bool) Equal(e Actual) bool {
|
|||||||
return bb == b
|
return bb == b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b Bool) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
return llvm.Value{}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Int represents an integer value
|
// Int represents an integer value
|
||||||
@ -59,6 +82,13 @@ func (i Int) Equal(e Actual) bool {
|
|||||||
return ii == i
|
return ii == i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LLVMVal creates a new llvm value using the builder and returns it
|
||||||
|
func (i Int) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
v := builder.CreateAlloca(llvm.Int64Type(), "")
|
||||||
|
builder.CreateStore(llvm.ConstInt(llvm.Int64Type(), uint64(i), false), v)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// String represents a string value
|
// String represents a string value
|
||||||
@ -73,6 +103,10 @@ func (s String) Equal(e Actual) bool {
|
|||||||
return ss == s
|
return ss == s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s String) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
return llvm.Value{}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Identifier represents a binding to some other value which has been given a
|
// Identifier represents a binding to some other value which has been given a
|
||||||
@ -88,6 +122,10 @@ func (id Identifier) Equal(e Actual) bool {
|
|||||||
return idid == id
|
return idid == id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (id Identifier) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
return llvm.Value{}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Macro is an identifier for a macro which can be used to transform
|
// Macro is an identifier for a macro which can be used to transform
|
||||||
@ -109,6 +147,10 @@ func (m Macro) Equal(e Actual) bool {
|
|||||||
return m == mm
|
return m == mm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m Macro) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
return llvm.Value{}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Tuple represents a fixed set of expressions which are interacted with as if
|
// Tuple represents a fixed set of expressions which are interacted with as if
|
||||||
@ -137,6 +179,10 @@ func (tup Tuple) Equal(e Actual) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tup Tuple) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
return llvm.Value{}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Pipe represents a set of expressions which operate on values and return new
|
// Pipe represents a set of expressions which operate on values and return new
|
||||||
@ -166,6 +212,10 @@ func (p Pipe) Equal(e Actual) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Pipe) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
return llvm.Value{}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// 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
|
||||||
@ -186,6 +236,10 @@ func (s Statement) Equal(e Actual) bool {
|
|||||||
return ok && s.in.Actual.Equal(ss.in.Actual) && s.pipe.Equal(ss.pipe)
|
return ok && s.in.Actual.Equal(ss.in.Actual) && s.pipe.Equal(ss.pipe)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s Statement) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
return llvm.Value{}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Block represents a set of statements which share a scope, i.e. If one
|
// Block represents a set of statements which share a scope, i.e. If one
|
||||||
@ -215,6 +269,10 @@ func (b Block) Equal(e Actual) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b Block) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
return llvm.Value{}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
type exprErr struct {
|
type exprErr struct {
|
||||||
|
68
main.go
68
main.go
@ -2,17 +2,75 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/mediocregopher/ginger/expr"
|
"github.com/mediocregopher/ginger/expr"
|
||||||
|
|
||||||
|
"llvm.org/llvm/bindings/go/llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type addActual []expr.Expr
|
||||||
|
|
||||||
|
func (aa addActual) Equal(expr.Actual) bool { return false }
|
||||||
|
|
||||||
|
func (aa addActual) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
a := builder.CreateLoad(aa[0].LLVMVal(builder), "")
|
||||||
|
for i := range aa[1:] {
|
||||||
|
b := builder.CreateLoad(aa[i+1].LLVMVal(builder), "")
|
||||||
|
a = builder.CreateAdd(a, b, "")
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
ee, err := expr.Parse(os.Stdin)
|
//ee, err := expr.Parse(os.Stdin)
|
||||||
|
//if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
//}
|
||||||
|
//for _, e := range ee {
|
||||||
|
// fmt.Println(e)
|
||||||
|
//}
|
||||||
|
|
||||||
|
llvm.LinkInMCJIT()
|
||||||
|
llvm.InitializeNativeTarget()
|
||||||
|
llvm.InitializeNativeAsmPrinter()
|
||||||
|
|
||||||
|
// setup our builder and module
|
||||||
|
builder := llvm.NewBuilder()
|
||||||
|
mod := llvm.NewModule("my_module")
|
||||||
|
|
||||||
|
// create our function prologue
|
||||||
|
main := llvm.FunctionType(llvm.Int64Type(), []llvm.Type{}, false)
|
||||||
|
llvm.AddFunction(mod, "main", main)
|
||||||
|
block := llvm.AddBasicBlock(mod.NamedFunction("main"), "entry")
|
||||||
|
builder.SetInsertPoint(block, block.FirstInstruction())
|
||||||
|
|
||||||
|
a := expr.Expr{Actual: expr.Int(1)}
|
||||||
|
b := expr.Expr{Actual: expr.Int(2)}
|
||||||
|
c := expr.Expr{Actual: expr.Int(3)}
|
||||||
|
add := addActual{a, b, c}
|
||||||
|
result := add.LLVMVal(builder)
|
||||||
|
builder.CreateRet(result)
|
||||||
|
|
||||||
|
// verify it's all good
|
||||||
|
if err := llvm.VerifyModule(mod, llvm.ReturnStatusAction); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println("# verified")
|
||||||
|
|
||||||
|
// Dump the IR
|
||||||
|
fmt.Println("# dumping IR")
|
||||||
|
mod.Dump()
|
||||||
|
fmt.Println("# done dumping IR")
|
||||||
|
|
||||||
|
// create our exe engine
|
||||||
|
fmt.Println("# creating new execution engine")
|
||||||
|
engine, err := llvm.NewExecutionEngine(mod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
for _, e := range ee {
|
|
||||||
fmt.Println(e)
|
// run the function!
|
||||||
}
|
fmt.Println("# running the function main")
|
||||||
|
funcResult := engine.RunFunction(mod.NamedFunction("main"), []llvm.GenericValue{})
|
||||||
|
fmt.Printf("%d\n", funcResult.Int(false))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user