Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions fncompiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -597,9 +597,6 @@ func (fn *funcCompiler) newLabel() *ast.Ident {
}

func (fn *funcCompiler) cleanup() {
// Resolve imports.
ast.Inspect(fn.decl, fn.resolveImports)

// Sanity checks.
passes.CheckMaterialized(fn.decl)

Expand Down
12 changes: 7 additions & 5 deletions libc-gen/test_alloc/bump/bump.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions libc-gen/test_alloc/sbrk/sbrk.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions libc-gen/test_alloc/tlsf/tlsf.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 9 additions & 7 deletions libc-gen/test_sjlj/sjlj.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

77 changes: 41 additions & 36 deletions module.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,21 @@ func (t *translator) createModuleStruct() ast.Decl {
Names: []*ast.Ident{newID("elements")},
Type: &ast.ArrayType{Elt: &ast.ArrayType{Elt: newID("any")}}})
}
// Memory: owned a []byte; imported a *[]byte and a Memory field.
// Memory: owned an embedded wasmMemory; imported a *[]byte and a Memory field.
if t.memory != nil {
if t.memory.imported {
fields = append(fields, &ast.Field{
Names: []*ast.Ident{t.memory.id},
Type: &ast.StarExpr{X: &ast.ArrayType{Elt: newID("byte")}},
}, &ast.Field{Names: []*ast.Ident{newID("memImp")}, Type: newID("Memory")})
if t.memory.shared || t.helpers.has("atomic_waiters") {
fields = append(fields, &ast.Field{
Names: []*ast.Ident{newID("waiters")},
Type: &ast.StarExpr{X: &ast.SelectorExpr{X: newID("sync"), Sel: newID("Map")}}})
}
} else {
fields = append(fields, &ast.Field{
Names: []*ast.Ident{t.memory.id},
Type: &ast.ArrayType{Elt: newID("byte")}})
}
if t.memory.shared || t.helpers.has("atomic_waiters") {
fields = append(fields, &ast.Field{
Names: []*ast.Ident{newID("waiters")},
Type: &ast.StarExpr{X: &ast.SelectorExpr{X: newID("sync"), Sel: newID("Map")}}})
t.packages.add("sync")
// The []byte (and waiters) are promoted from wasmMemory.
fields = append(fields, &ast.Field{Type: newID("wasmMemory")})
}
}
// Globals: owned/immutable are type; imported *type.
Expand Down Expand Up @@ -359,10 +357,10 @@ func (t *translator) createHostInterfaces() []ast.Decl {
return decls
}

func (t *translator) createMemoryTypes() []ast.Decl {
func (t *translator) createMemoryTypes(exported bool) []ast.Decl {
var decls []ast.Decl
// Memory interface as a type alias.
if !*nohost {
if !*nohost && (exported || t.memory.imported) {
iface := &ast.InterfaceType{Methods: &ast.FieldList{
List: []*ast.Field{{
Names: []*ast.Ident{newID("Slice")},
Expand Down Expand Up @@ -395,45 +393,53 @@ func (t *translator) createMemoryTypes() []ast.Decl {
Specs: []ast.Spec{&ast.TypeSpec{
Assign: 1, Name: newID("Memory"), Type: iface}}})
}
// Memory structure implementing the interface for owned memory.
// Memory structure for owned memory.
// It is embedded in Module, so its fields are promoted.
if !t.memory.imported {
fields := []*ast.Field{{
Names: []*ast.Ident{t.memory.id},
Type: &ast.ArrayType{Elt: newID("byte")}}}
if t.memory.shared || t.helpers.has("atomic_waiters") {
fields = append(fields, &ast.Field{
Names: []*ast.Ident{newID("waiters")},
Type: &ast.StarExpr{X: &ast.SelectorExpr{X: newID("sync"), Sel: newID("Map")}}})
}
decls = append(decls, &ast.GenDecl{
Tok: token.TYPE,
Specs: []ast.Spec{&ast.TypeSpec{
Name: newID("wasmMemory"),
Type: &ast.StructType{Fields: &ast.FieldList{List: fields}}}}})
}
// Methods implementing the Memory interface for exported owned memory.
if !t.memory.imported && exported {
name := "memory_grow"
if t.memory.shared {
name = "atomic_memory_grow"
needsUnsafe("shared memory")
}
t.helpers.add(name)

decls = append(decls, &ast.GenDecl{
Tok: token.TYPE,
Specs: []ast.Spec{&ast.TypeSpec{
Name: newID("wasmMemory"),
Type: &ast.ArrayType{Elt: newID("byte")}}},
}, &ast.FuncDecl{
Recv: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{newID("m")}, Type: &ast.StarExpr{X: newID("wasmMemory")}}}},
recv := &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{newID("m")}, Type: &ast.StarExpr{X: newID("wasmMemory")}}}}
mem := &ast.UnaryExpr{Op: token.AND, X: modSel(t.memory.id)}

decls = append(decls, &ast.FuncDecl{
Recv: recv,
Name: newID("Slice"),
Type: &ast.FuncType{Results: &ast.FieldList{List: []*ast.Field{{Type: &ast.StarExpr{X: &ast.ArrayType{Elt: newID("byte")}}}}}},
Body: &ast.BlockStmt{List: []ast.Stmt{&ast.ReturnStmt{Results: []ast.Expr{&ast.CallExpr{
Fun: &ast.StarExpr{X: &ast.ArrayType{Elt: newID("byte")}},
Args: []ast.Expr{newID("m")}}}}}},
Body: &ast.BlockStmt{List: []ast.Stmt{&ast.ReturnStmt{Results: []ast.Expr{mem}}}},
}, &ast.FuncDecl{
Recv: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{newID("m")}, Type: &ast.StarExpr{X: newID("wasmMemory")}}}},
Recv: recv,
Name: newID("Grow"),
Type: &ast.FuncType{
Params: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{newID("delta"), newID("max")}, Type: newID("int64")}}},
Results: &ast.FieldList{List: []*ast.Field{{Type: newID("int64")}}}},
Body: &ast.BlockStmt{List: []ast.Stmt{&ast.ReturnStmt{Results: []ast.Expr{&ast.CallExpr{
Fun: newID(name),
Args: []ast.Expr{
&ast.CallExpr{
Fun: &ast.StarExpr{X: &ast.ArrayType{Elt: newID("byte")}},
Args: []ast.Expr{newID("m")}},
newID("delta"),
newID("max")}}}}}}})
t.helpers.add(name)
Fun: newID(name),
Args: []ast.Expr{mem, newID("delta"), newID("max")}}}}}}})

if t.memory.shared {
decls = append(decls, &ast.FuncDecl{
Recv: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{newID("m")}, Type: &ast.StarExpr{X: newID("wasmMemory")}}}},
Recv: recv,
Name: newID("Waiters"),
Type: &ast.FuncType{
Results: &ast.FieldList{List: []*ast.Field{{Type: &ast.StarExpr{X: &ast.SelectorExpr{X: newID("sync"), Sel: newID("Map")}}}}}},
Expand Down Expand Up @@ -501,9 +507,8 @@ func (t *translator) createExportMethods() []ast.Decl {
if t.memory.imported {
decl.Body.List = []ast.Stmt{&ast.ReturnStmt{Results: []ast.Expr{modSel(newID("memImp"))}}}
} else {
decl.Body.List = []ast.Stmt{&ast.ReturnStmt{Results: []ast.Expr{&ast.CallExpr{
Fun: &ast.ParenExpr{X: &ast.StarExpr{X: newID("wasmMemory")}},
Args: []ast.Expr{&ast.UnaryExpr{Op: token.AND, X: &ast.SelectorExpr{X: newID("m"), Sel: t.memory.id}}}}}}}
decl.Body.List = []ast.Stmt{&ast.ReturnStmt{Results: []ast.Expr{
&ast.UnaryExpr{Op: token.AND, X: modSel(newID("wasmMemory"))}}}}
}
}

Expand Down
20 changes: 20 additions & 0 deletions regression_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
oob_trap_test "github.com/ncruces/wasm2go/testdata/regression/oob_trap"
provided_helper_test "github.com/ncruces/wasm2go/testdata/regression/provided_helper"
select_test "github.com/ncruces/wasm2go/testdata/regression/select_effect"
shared_export_test "github.com/ncruces/wasm2go/testdata/regression/shared_export"
store_grow_test "github.com/ncruces/wasm2go/testdata/regression/store_grow"
)

Expand Down Expand Up @@ -132,6 +133,25 @@ func Test_regression_bulk_grow(t *testing.T) {
mustTrap("table.fill past grown end", func() { m.Xtfill(3, 1) })
}

func Test_regression_shared_export(t *testing.T) {
m := shared_export_test.New()
mem := m.Xmemory()

// The export must view the module's own memory, not a copy.
if mem.Slice() != m.Xmemory().Slice() {
t.Error("Slice() is not stable")
}
if got := mem.Grow(0, 1); got != 1 {
t.Errorf("Grow(0) = %d, want 1", got)
}
if mem.Waiters() == nil {
t.Fatal("Waiters() is nil")
}
if got := m.Xwait0(); got != 2 {
t.Errorf("wait0() = %d, want 2 (timed out)", got)
}
}

func Test_regression_provided_helper(t *testing.T) {
m := provided_helper_test.New()

Expand Down
12 changes: 7 additions & 5 deletions testdata/memory/memory.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading