golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
122.25k stars 17.47k forks source link

wasm: duplicate import in wasip1 compiled binary #60525

Open johanbrandhorst opened 1 year ago

johanbrandhorst commented 1 year ago

What version of Go are you using (go version)?

$ go version
go version devel go1.21-993707a9d6 Tue May 30 20:19:54 2023 +0000 linux/arm64

What did you do?

package main

import (
    "crypto/rand"
    "encoding/hex"
    "fmt"
)

func main() {
    b := [16]byte{}
    rand.Read(b[:])
    fmt.Println(hex.EncodeToString(b[:]))
}
GOARCH=wasm GOOS=wasip1 go build -o main.wasm main.go
wasm2wat main.wasm

The imports in the generated .wat file are:

  (import "wasi_snapshot_preview1" "sched_yield" (func (;0;) (type 1)))
  (import "wasi_snapshot_preview1" "proc_exit" (func (;1;) (type 2)))
  (import "wasi_snapshot_preview1" "args_get" (func (;2;) (type 3)))
  (import "wasi_snapshot_preview1" "args_sizes_get" (func (;3;) (type 3)))
  (import "wasi_snapshot_preview1" "clock_time_get" (func (;4;) (type 4)))
  (import "wasi_snapshot_preview1" "environ_get" (func (;5;) (type 3)))
  (import "wasi_snapshot_preview1" "environ_sizes_get" (func (;6;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_write" (func (;7;) (type 5)))
  (import "wasi_snapshot_preview1" "random_get" (func (;8;) (type 3)))
  (import "wasi_snapshot_preview1" "poll_oneoff" (func (;9;) (type 5)))
  (import "wasi_snapshot_preview1" "fd_close" (func (;10;) (type 0)))
  (import "wasi_snapshot_preview1" "fd_read" (func (;11;) (type 5)))
  (import "wasi_snapshot_preview1" "fd_write" (func (;12;) (type 5)))
  (import "wasi_snapshot_preview1" "random_get" (func (;13;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_fdstat_get" (func (;14;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_fdstat_set_flags" (func (;15;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_prestat_get" (func (;16;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_prestat_dir_name" (func (;17;) (type 6)))

Both fd_write and random_get appear twice.

What did you expect to see?

Each import appears only once

This isn't an invalid wasm file and doesn't affect the end result much, but there is clearly some part of the compiler that isn't weeding out duplicate imports for wasm.

HarikrishnanBalagopal commented 1 year ago

Also happening for me with this code

The duplicate imports for fd_write in the compiled wasm (disassembled with wasm2wat)

(module
  (type (;0;) (func (param i32) (result i32)))
  (type (;1;) (func (result i32)))
  (type (;2;) (func (param i32)))
  (type (;3;) (func (param i32 i32) (result i32)))
  (type (;4;) (func (param i32 i64 i32) (result i32)))
  (type (;5;) (func (param i32 i32 i32 i32) (result i32)))
  (type (;6;) (func (param i32 i32 i32 i64 i32) (result i32)))
  (type (;7;) (func (param i32 i32 i32 i32 i32) (result i32)))
  (type (;8;) (func (param i32 i32 i32 i32 i32 i64 i64 i32 i32) (result i32)))
  (type (;9;) (func (param i32 i32 i32) (result i32)))
  (type (;10;) (func (param i64 i64 i64 i64) (result i64)))
  (type (;11;) (func (param i64 i64 i64) (result i64)))
  (type (;12;) (func (param i64) (result i64)))
  (type (;13;) (func (result i64)))
  (type (;14;) (func))
  (type (;15;) (func (param i64 i64) (result i64)))
  (type (;16;) (func (param f64) (result i64)))
  (import "wasi_snapshot_preview1" "sched_yield" (func (;0;) (type 1)))
  (import "wasi_snapshot_preview1" "proc_exit" (func (;1;) (type 2)))
  (import "wasi_snapshot_preview1" "args_get" (func (;2;) (type 3)))
  (import "wasi_snapshot_preview1" "args_sizes_get" (func (;3;) (type 3)))
  (import "wasi_snapshot_preview1" "clock_time_get" (func (;4;) (type 4)))
  (import "wasi_snapshot_preview1" "environ_get" (func (;5;) (type 3)))
  (import "wasi_snapshot_preview1" "environ_sizes_get" (func (;6;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_write" (func (;7;) (type 5)))
  (import "wasi_snapshot_preview1" "random_get" (func (;8;) (type 3)))
  (import "wasi_snapshot_preview1" "poll_oneoff" (func (;9;) (type 5)))
  (import "wasi_snapshot_preview1" "fd_close" (func (;10;) (type 0)))
  (import "wasi_snapshot_preview1" "fd_read" (func (;11;) (type 5)))
  (import "wasi_snapshot_preview1" "fd_readdir" (func (;12;) (type 6)))
  (import "wasi_snapshot_preview1" "fd_filestat_get" (func (;13;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_write" (func (;14;) (type 5)))
  (import "wasi_snapshot_preview1" "path_filestat_get" (func (;15;) (type 7)))
  (import "wasi_snapshot_preview1" "path_open" (func (;16;) (type 8)))
  (import "wasi_snapshot_preview1" "fd_fdstat_get" (func (;17;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_fdstat_set_flags" (func (;18;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_prestat_get" (func (;19;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_prestat_dir_name" (func (;20;) (type 9)))
  (func $go_buildid (type 0) (param i32) (result i32)

Compiled with

$ go version
go version go1.21.0 darwin/amd64
$ CGO_ENABLED=0 GOOS=wasip1 GOARCH=wasm go build -o bin/test.wasm .
$ echo $?
0

The Golang code

package main

import (
    "os"

    "github.com/sirupsen/logrus"
)

func must(err error) {
    if err != nil {
        panic(err)
    }
}

func main() {
    logrus.Infof("start")
    pwd, err := os.Getwd()
    logrus.Infof("pwd: '%s'", pwd)
    must(err)
    fs, err := os.ReadDir(".")
    must(err)
    for _, f := range fs {
        logrus.Infof("f: %+v", f)
    }
    b, err := os.ReadFile("./dep.json")
    must(err)
    logrus.Infof("The contents are:\n%s", string(b))
    logrus.Infof("done")
}

The go.mod file

module foo.com/b

go 1.21

require github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af

require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect

The go.sum file

github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af h1:Sp5TG9f7K39yfB+If0vjp97vuT74F72r8hfRpP8jLU0=
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=