Tinygo: TinyGo fails to compile a Vecty program

Created on 7 Aug 2020  路  3Comments  路  Source: tinygo-org/tinygo

Hi there,
I have a simple Vecty program that compiles with Go but fails to compile with TinyGo:

package main

import (
    "github.com/gopherjs/vecty"
    "github.com/gopherjs/vecty/elem"
)

type comp struct {
    vecty.Core
}

func (c *comp) Render() vecty.ComponentOrHTML {
    return elem.Div(vecty.Text("hello"))
}

func main() {
    vecty.RenderBody(&comp{})
}

I was using Go modules and TinyGo v0.14.0 when running the following and got the error:

root@05844ebaa1e7:/app# tinygo build -o wasm.wasm -target=wasm .
# github.com/gopherjs/vecty
/go/pkg/mod/github.com/gopherjs/[email protected]/dom_wasmjs_gopherjs.go: interp: unknown GEP

traceback:
github.com/gopherjs/vecty/<init>:41:24:
  %15 = call %runtime._interface @"github.com/gopherjs/vecty.wrapObject"([0 x %runtime.funcValue] %12, i64 %13, i64* %14, i8* undef, i8* undef), !dbg !216

This is issue is a follow up on https://github.com/tinygo-org/tinygo/issues/93 - see this comment for more context.

It would be great to either solve this on the TinyGo side or the Vecty side.

CC: @slimsag @deadprogram

Thanks!

bug question wasm

Most helpful comment

Hey folks - author of Vecty here - I had some time over the weekend and have just landed experimental support for TinyGo into the main branch of Vecty so you can try it out!

I won't pretend it's all roses, though - there are some pretty rough edges due to some limitations of TinyGo (primarily reflect.New) - but my hope is this will give people enough of a taste that:

  1. We can close this issue in favor of more specific / targeted issues for improving TinyGo.
  2. We can get more people excited about the prospect of TinyGo + Vecty and (hopefully) end up with more contributors to TinyGo :) In particular I think it would be really cool if someone took a pass at some of the limitations I describe encountering in the PR.

Check it out: https://github.com/gopherjs/vecty/pull/243

All 3 comments

FWIW the "unknown GEP" error from the interp package usually means that there is some code in a global initializer that cannot be executed by the interpreter in the TinyGo compiler that is responsible for computing global variables (and marking the resulting values as constants when appropriate). This is a documented difference from the standard Go implementation, which always defers the computation of globals and the execution of initializers to when the program executes (see last bullet on this page - https://tinygo.org/compiler-internals/differences-from-go/). The compile-time interpretation of initializers is an important aspect of how the TinyGo compiler is able to emit smaller binaries that can run in resource-constrained environments.

In my experience, a lot of the time the "unknown GEP" error happens when functions called from global initializers return an interface, and similar scenarios usually involving interfaces (if I'm not mistaken, global sentinel error values created with errors.New(...) are a common cause of this).
Without digging too much into what vecty is doing, it seems like the culprit in this case has something to do with this line: https://github.com/gopherjs/vecty/blob/eafd720f09ee91f8bea692e524cf89efb09b485a/dom_wasmjs_gopherjs.go#L41

I'm not smart enough to know whether or not this can/should be improved on the TinyGo side, but it is a common issue that as far as I know must be fixed in the package you're trying to compile, which is unfortunate. In this particular case, vecty already has this code path guarded with build tags, so perhaps refactoring that library to make it work with TinyGo is an option (in case you don't already know this, the TinyGo compiler implicitly adds a tinygo build tag when compiling which could be useful for that purpose). I suspect that modifying TinyGo so that this GEP instruction can be resolved at compile time is either impossible or at least difficult, but like I said I'm not that smart so maybe @Ayke or @jaddr2line could weigh in and correct anything I might be wrong about :)

@bgould thank you for the hint!

I changed Vecty itself so that global is not a package-level variable but a function that returns an interface and changed all the code that access global to call it as a function global()

I ended up getting a different error now:

root@78e86f409bc3:/app# tinygo build -o wasm.wasm -target=wasm main.go
panic: trying to make exported function async: (github.com/gopherjs/vecty.jsFuncImpl).Release$invoke

goroutine 1 [running]:
github.com/tinygo-org/tinygo/transform.(*coroutineLoweringPass).findAsyncFuncs(0xc000c4f1c8)
    /home/circleci/project/transform/coroutines.go:186 +0xa64
github.com/tinygo-org/tinygo/transform.(*coroutineLoweringPass).load(0xc000c4f1c8, 0x20, 0x7f1cc40169a0)
    /home/circleci/project/transform/coroutines.go:305 +0x36c
github.com/tinygo-org/tinygo/transform.LowerCoroutines(0x895f880, 0x895f801, 0x0, 0x0)
    /home/circleci/project/transform/coroutines.go:70 +0x15f
github.com/tinygo-org/tinygo/transform.Optimize(0x895f880, 0xc0002083c0, 0x2, 0x2, 0x5, 0x0, 0x0, 0x0)
    /home/circleci/project/transform/optimizer.go:120 +0xef0
github.com/tinygo-org/tinygo/builder.Build(0x7ffd51d9dee7, 0x7, 0x7ffd51d9ded0, 0x9, 0xc0002083c0, 0xc000c4fc88, 0x0, 0x0)
    /home/circleci/project/builder/build.go:95 +0x2ba9
main.Build(0x7ffd51d9dee7, 0x7, 0x7ffd51d9ded0, 0x9, 0xc0001920e0, 0x0, 0x12)
    /home/circleci/project/main.go:97 +0xc5
main.main()
    /home/circleci/project/main.go:888 +0x1b7f

I'm not sure what this error is since it's referring to a path in circleci?

Hey folks - author of Vecty here - I had some time over the weekend and have just landed experimental support for TinyGo into the main branch of Vecty so you can try it out!

I won't pretend it's all roses, though - there are some pretty rough edges due to some limitations of TinyGo (primarily reflect.New) - but my hope is this will give people enough of a taste that:

  1. We can close this issue in favor of more specific / targeted issues for improving TinyGo.
  2. We can get more people excited about the prospect of TinyGo + Vecty and (hopefully) end up with more contributors to TinyGo :) In particular I think it would be really cool if someone took a pass at some of the limitations I describe encountering in the PR.

Check it out: https://github.com/gopherjs/vecty/pull/243

Was this page helpful?
0 / 5 - 0 ratings

Related issues

johanbrandhorst picture johanbrandhorst  路  8Comments

tranxuanthang picture tranxuanthang  路  8Comments

johanbrandhorst picture johanbrandhorst  路  7Comments

prologic picture prologic  路  8Comments

wdevore picture wdevore  路  5Comments