Selaa lähdekoodia

store/load и операции с памятью

kpmy 9 vuotta sitten
vanhempi
commit
4ebfec8511
7 muutettua tiedostoa jossa 229 lisäystä ja 5 poistoa
  1. BIN
      TODO.odc
  2. 5 5
      gen/impl/sexpr/sexpr.go
  3. 49 0
      ir/ast.go
  4. 7 0
      ir/code.go
  5. 134 0
      ir/mem.go
  6. 4 0
      ir/types/types.go
  7. 30 0
      tiss_test.go

BIN
TODO.odc


+ 5 - 5
gen/impl/sexpr/sexpr.go

@@ -72,6 +72,8 @@ func (w *wr) Atom(_v interface{}) {
 		w.Atom(v.ValueOf())
 	case int:
 		w.Raw(strconv.Itoa(v))
+	case uint:
+		w.Raw(strconv.FormatUint(uint64(v), 10))
 	default:
 		Halt(100, "wrong atom ", reflect.TypeOf(v))
 	}
@@ -100,9 +102,8 @@ func (w *wr) WriteValue(v interface{}) (err error) {
 			w.Atom(x0)
 		}
 		return
-	}, v).Catch(nil, func(e error) {
-		err = e
-	}).Do()
+	}, v).Do()
+	//.Catch(nil, func(e error) {err = e})
 	return
 }
 
@@ -127,9 +128,8 @@ func (w *wr) WriteExpr(e ir.Expression) (err error) {
 				}
 			}
 			w.Raw(")")
-		}).Catch(nil, func(e error) {
-			err = e
 		}).Do()
+		//.Catch(nil, func(e error) {err = e})
 	}
 	return err
 }

+ 49 - 0
ir/ast.go

@@ -222,6 +222,8 @@ type Module struct {
 	Start *StartExpr
 	Func  []*FuncExpr
 	Type  []*TypeDef
+	Table *TableDef
+	Imp   []*Import
 }
 
 func (m *Module) Children() (ret []interface{}) {
@@ -229,6 +231,10 @@ func (m *Module) Children() (ret []interface{}) {
 		ret = append(ret, t)
 	}
 
+	if m.Table != nil {
+		ret = append(ret, m.Table)
+	}
+
 	for _, f := range m.Func {
 		ret = append(ret, f)
 	}
@@ -240,3 +246,46 @@ func (m *Module) Children() (ret []interface{}) {
 func (m *Module) Validate() (err error) {
 	return
 }
+
+type TableDef struct {
+	ns    `sexpr:"module"`
+	Index []Variable
+}
+
+func (t *TableDef) Validate() error { return nil }
+
+func (t *TableDef) Children() (ret []interface{}) {
+	for _, v := range t.Index {
+		ret = append(ret, v)
+	}
+	return
+}
+
+type Import struct {
+	named
+	Mod    string
+	Func   string
+	Params []*Param
+	Result *ResultExpr
+}
+
+func (i *Import) Validate() error { return nil }
+
+func (i *Import) Children() (ret []interface{}) {
+	if i.name != "" {
+		ret = append(ret, i.name)
+	}
+
+	ret = append(ret, `"`+i.Mod+`"`)
+	ret = append(ret, `"`+i.Func+`"`)
+
+	for _, p := range i.Params {
+		ret = append(ret, p)
+	}
+
+	if !fn.IsNil(i.Result) {
+		ret = append(ret, i.Result)
+	}
+
+	return
+}

+ 7 - 0
ir/code.go

@@ -236,3 +236,10 @@ func (c *ConvertOp) Children() (ret []interface{}) {
 }
 
 func (*ConvertOp) Eval() {}
+
+type UnreachableExpr struct {
+	ns `sexpr:"unreachable"`
+}
+
+func (*UnreachableExpr) Validate() error { return nil }
+func (*UnreachableExpr) Eval()           {}

+ 134 - 0
ir/mem.go

@@ -0,0 +1,134 @@
+package ir
+
+import (
+	"fmt"
+
+	"github.com/kpmy/tiss/ir/types"
+	"github.com/kpmy/ypk/fn"
+	. "github.com/kpmy/ypk/tc"
+)
+
+type CurrentMemoryExpr struct {
+	ns `sexpr:"current_memory"`
+}
+
+func (*CurrentMemoryExpr) Validate() error { return nil }
+func (*CurrentMemoryExpr) Eval()           {}
+
+type GrowMemoryExpr struct {
+	ns   `sexpr:"grow_memory"`
+	Expr CodeExpr
+}
+
+func (m *GrowMemoryExpr) Validate() (err error) {
+	if fn.IsNil(m.Expr) {
+		err = Error("no expression for grow memory")
+	}
+	return
+}
+
+func (m *GrowMemoryExpr) Children() (ret []interface{}) {
+	return append(ret, m.Expr)
+}
+
+func (*GrowMemoryExpr) Eval() {}
+
+type LoadSize int
+
+const (
+	Load8  LoadSize = 8
+	Load16 LoadSize = 16
+	Load32 LoadSize = 32
+)
+
+func (s LoadSize) Valid() bool {
+	return s == Load8 || s == Load16 || s == Load32
+}
+
+type LoadExpr struct {
+	Type   types.Type
+	Size   LoadSize
+	Signed bool
+	Offset uint
+	Align  uint
+	Expr   CodeExpr
+}
+
+func (l *LoadExpr) Name() (ret string) {
+	ret = fmt.Sprint(l.Type, ".", "load", l.Size)
+	if l.Type == types.I64 || l.Type == types.I32 {
+		if l.Signed {
+			ret = fmt.Sprint(ret, "_s")
+		} else {
+			ret = fmt.Sprint(ret, "_u")
+		}
+	}
+	return
+}
+
+func (l *LoadExpr) Validate() error {
+	if !l.Type.Valid() {
+		return Error("invalid load type")
+	}
+
+	if !l.Size.Valid() {
+		return Error("invalid load size")
+	}
+
+	if l.Align != 1 && l.Align%2 == 1 {
+		return Error("load align must be power of 2")
+	}
+
+	if fn.IsNil(l.Expr) {
+		return Error("load expression is nil")
+	}
+	return nil
+}
+
+func (l *LoadExpr) Children() (ret []interface{}) {
+	return append(ret, l.Offset, l.Align, l.Expr)
+}
+
+func (l *LoadExpr) Eval() {}
+
+type StoreExpr struct {
+	Type        types.Type
+	Size        LoadSize
+	Offset      uint
+	Align       uint
+	Expr, Value CodeExpr
+}
+
+func (s *StoreExpr) Name() (ret string) {
+	ret = fmt.Sprint(s.Type, ".", "store", s.Size)
+	return
+}
+
+func (s *StoreExpr) Validate() error {
+	if !s.Type.Valid() {
+		return Error("invalid store type")
+	}
+
+	if !s.Size.Valid() {
+		return Error("invalid store size")
+	}
+
+	if s.Align != 1 && s.Align%2 == 1 {
+		return Error("store align must be power of 2")
+	}
+
+	if fn.IsNil(s.Expr) {
+		return Error("store expression is nil")
+	}
+
+	if fn.IsNil(s.Value) {
+		return Error("store value expression is nil")
+	}
+	return nil
+}
+
+func (s *StoreExpr) Children() (ret []interface{}) {
+	return append(ret, s.Offset, s.Align, s.Expr, s.Value)
+}
+
+func (l *StoreExpr) Eval() {}

+ 4 - 0
ir/types/types.go

@@ -8,3 +8,7 @@ const (
 	F32 Type = "f32"
 	F64 Type = "f64"
 )
+
+func (t Type) Valid() bool {
+	return t == I32 || t == I64 || t == F32 || t == F64
+}

+ 30 - 0
tiss_test.go

@@ -71,3 +71,33 @@ func TestOp(t *testing.T) {
 	t.Log(ops.Conv(types.I64, types.F32, ops.Convert, true))
 	t.Log(ops.Conv(types.I64, types.F64, ops.Reinterpret))
 }
+
+func TestExpr(t *testing.T) {
+	{
+		buf := bytes.NewBufferString("")
+		expr := &ir.LoadExpr{}
+		expr.Size = ir.Load32
+		expr.Offset = 14
+		expr.Align = 32
+		expr.Type = types.I64
+		expr.Expr = &ir.ConstExpr{Type: types.I64, Value: 34}
+		if err := gen.NewWriter(buf).WriteExpr(expr); err != nil {
+			t.Error(err)
+		}
+		t.Log(buf.String())
+	}
+	{
+		buf := bytes.NewBufferString("")
+		expr := &ir.StoreExpr{}
+		expr.Size = ir.Load32
+		expr.Offset = 14
+		expr.Align = 32
+		expr.Type = types.I64
+		expr.Expr = &ir.ConstExpr{Type: types.I64, Value: 34}
+		expr.Value = &ir.ConstExpr{Type: types.I64, Value: 124}
+		if err := gen.NewWriter(buf).WriteExpr(expr); err != nil {
+			t.Error(err)
+		}
+		t.Log(buf.String())
+	}
+}