Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasip1: add //go:wasmexport support #4451

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open

wasip1: add //go:wasmexport support #4451

wants to merge 1 commit into from

Conversation

aykevl
Copy link
Member

@aykevl aykevl commented Sep 1, 2024

This adds support for the //go:wasmexport pragma as proposed here: golang/go#65199

It is currently implemented only for wasip1, but it is certainly possible to extend it to other targets like GOOS=js, -target=wasm-unknown, or -target=wasip2. It is also currently limited to -buildmode=c-shared, this is a limitation that could easily be lifted in the future.

WIP: this needs tests, but I'm not entirely sure how to test this (I've tested it by using the --invoke flag to wasmtime).

This will likely replace #4082.

If you want fast calls into the binary, I'd recommend to disable the scheduler (-scheduler=none). That should give a significant speedup since lots of complexity is avoided. Though there are also some possible optimizations that I haven't implemented yet (like caching stacks).

Copy link

github-actions bot commented Sep 1, 2024

Size difference with the dev branch:

Binary size difference
not the same command!
    tinygo build -size short -o ./build/test.hex -target=feather-rp2040 ./examples/adafruit4650
    go: downloading tinygo.org/x/tinyfont v0.3.0
not the same command!
    tinygo build -size short -o ./build/test.hex -target=nano-rp2040 -stack-size 8kb ./examples/net/websocket/dial/
    go: downloading golang.org/x/net v0.7.0
not the same command!
    tinygo build -size short -o ./build/test.hex -target=nano-rp2040 -stack-size 8kb ./examples/net/mqttclient/natiu/
    go: downloading github.com/soypat/natiu-mqtt v0.5.1
not the same command!
    tinygo build -size short -o ./build/test.hex -target=wioterminal -stack-size 8kb ./examples/net/mqttclient/paho/
    go: downloading github.com/eclipse/paho.mqtt.golang v1.2.0
 flash                          ram
 before   after   diff          before   after   diff
  16736   16736      0   0.00%    4308    4308      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-rp2040 ./examples/adafruit4650
  61152   61152      0   0.00%    6180    6180      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adt7410/main.go
   9468    9468      0   0.00%    4740    4740      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adxl345/main.go
  13472   13472      0   0.00%    6780    6780      0   0.00% tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/amg88xx
   8580    8580      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/main.go
  11660   11660      0   0.00%    6564    6564      0   0.00% tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/apds9960/proximity/main.go
   9668    9668      0   0.00%    4752    4752      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/itsybitsy-m0/main.go
   8272    8272      0   0.00%    2304    2304      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/at24cx/main.go
   8024    8024      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bh1750/main.go
   7332    7332      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/blinkm/main.go
  70360   70360      0   0.00%    3644    3644      0   0.00% tinygo build -size short -o ./build/test.hex -target=pinetime     ./examples/bma42x/main.go
  63692   63692      0   0.00%    6180    6180      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmi160/main.go
  27324   27324      0   0.00%    4772    4772      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmp180/main.go
  63736   63736      0   0.00%    6212    6212      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmp280/main.go
  12084   12084      0   0.00%    4804    4804      0   0.00% tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/bmp388/main.go
   8152    8152      0   0.00%    3332    3332      0   0.00% tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/sram/main.go
  22072   22072      0   0.00%    3528    3528      0   0.00% tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/time/main.go
  69448   69448      0   0.00%    6356    6356      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/ds3231/main.go
   4520    4520      0   0.00%    2264    2264      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/easystepper/main.go
  69024   69024      0   0.00%    6960    6960      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/flash/console/spi
  65404   65404      0   0.00%    8996    8996      0   0.00% tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/flash/console/qspi
   7112    7112      0   0.00%    2264    2264      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/gc9a01/main.go
  67428   67428      0   0.00%    6352    6352      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/gps/i2c/main.go
  67956   67956      0   0.00%    6488    6488      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/gps/uart/main.go
   7772    7772      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/hcsr04/main.go
   5732    5732      0   0.00%    2264    2264      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hd44780/customchar/main.go
   5684    5684      0   0.00%    2264    2264      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hd44780/text/main.go
  10412   10412      0   0.00%    4740    4740      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/hd44780i2c/main.go
  14588   14588      0   0.00%    6564    6564      0   0.00% tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/hts221/main.go
  16048   16048      0   0.00%    2344    2344      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hub75/main.go
  10072   10072      0   0.00%    6900    6900      0   0.00% tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/basic
  10544   10544      0   0.00%    4852    4852      0   0.00% tinygo build -size short -o ./build/test.hex -target=xiao ./examples/ili9341/basic
  29448   29448      0   0.00%   38060   38060      0   0.00% tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/pyportal_boing
  10092   10092      0   0.00%    6908    6908      0   0.00% tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/scroll
  10632   10632      0   0.00%    4860    4860      0   0.00% tinygo build -size short -o ./build/test.hex -target=xiao ./examples/ili9341/scroll
 263388  263388      0   0.00%   46744   46744      0   0.00% tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/slideshow
  11632   11632      0   0.00%    4772    4772      0   0.00% tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/lis3dh/main.go
  13932   13932      0   0.00%    6564    6564      0   0.00% tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/lps22hb/main.go
  26028   26028      0   0.00%    2312    2312      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/lsm303agr/main.go
  12348   12348      0   0.00%    4780    4780      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/lsm6ds3/main.go
  10644   10644      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mag3110/main.go
   9820    9820      0   0.00%    4764    4764      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp23017/main.go
  10256   10256      0   0.00%    4772    4772      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp23017-multiple/main.go
   9680    9680      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp3008/main.go
  68352   68352      0   0.00%    6180    6180      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp2515/main.go
  27140   27140      0   0.00%    3568    3568      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/microbitmatrix/main.go
  26932   26932      0   0.00%    5612    5612      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit-v2 ./examples/microbitmatrix/main.go
   8140    8140      0   0.00%    4740    4740      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mma8653/main.go
   8048    8048      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mpu6050/main.go
  75632   75632      0   0.00%    7460    7460      0   0.00% tinygo build -size short -o ./build/test.hex -target=p1am-100 ./examples/p1am/main.go
  12132   12132      0   0.00%    3336    3336      0   0.00% tinygo build -size short -o ./build/test.hex -target=pico ./examples/pca9685/main.go
   6128    6128      0   0.00%    3272    3272      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setbuffer/main.go
   5160    5160      0   0.00%    2264    2264      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setpixel/main.go
  10404   10404      0   0.00%    3312    3312      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-rp2040 ./examples/seesaw
   2825    2825      0   0.00%     558     558      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino ./examples/servo
  13644   13644      0   0.00%    3384    3384      0   0.00% tinygo build -size short -o ./build/test.hex -target=pico     ./examples/sgp30
   8000    8000      0   0.00%    6780    6780      0   0.00% tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/shifter/main.go
  57156   57156      0   0.00%    3676    3676      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/sht3x/main.go
  57212   57212      0   0.00%    3684    3684      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/sht4x/main.go
  57128   57128      0   0.00%    3676    3676      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/shtc3/main.go
   6552    6552      0   0.00%    2272    2272      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/i2c_128x32/main.go
   6000    6000      0   0.00%    2264    2264      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/spi_128x64/main.go
   5748    5748      0   0.00%    2264    2264      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1331/main.go
   6676    6676      0   0.00%    2264    2264      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/st7735/main.go
   6588    6588      0   0.00%    2264    2264      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/st7789/main.go
  16868   16868      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/thermistor/main.go
  10372   10372      0   0.00%    4524    4524      0   0.00% tinygo build -size short -o ./build/test.hex -target=circuitplay-bluefruit ./examples/tone
   9968    9968      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/tm1637/main.go
   9448    9448      0   0.00%    6772    6772      0   0.00% tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/touch/resistive/fourwire/main.go
  12516   12516      0   0.00%    6968    6968      0   0.00% tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/touch/resistive/pyportal_touchpaint/main.go
  14896   14896      0   0.00%    4740    4740      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/vl53l1x/main.go
  13372   13372      0   0.00%    4740    4740      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/vl6180x/main.go
   6452    6452      0   0.00%    2304    2304      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd2in13/main.go
   6080    6080      0   0.00%    2296    2296      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd2in13x/main.go
   6332    6332      0   0.00%    2304    2304      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd4in2/main.go
  26320   26320      0   0.00%   16716   16716      0   0.00% tinygo build -size short -o ./build/test.hex -target=pico ./examples/waveshare-epd/epd2in66b/main.go
   6748    6748      0   0.00%    4772    4772      0   0.00% tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/ws2812
   5662    5662      0   0.00%    9506    9506      0   0.00% tinygo build -size short -o ./build/test.bin -target=m5stamp-c3          ./examples/ws2812
  62180   62180      0   0.00%    5936    5936      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-nrf52840 ./examples/is31fl3731/main.go
   1581    1581      0   0.00%     598     598      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino   ./examples/ws2812
   1056    1056      0   0.00%     180     180      0   0.00% tinygo build -size short -o ./build/test.hex -target=digispark ./examples/ws2812
  31752   31752      0   0.00%    4772    4772      0   0.00% tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/bme280/main.go
  16356   16356      0   0.00%    4716    4716      0   0.00% tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/microphone/main.go
  10992   10992      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/buzzer/main.go
  12700   12700      0   0.00%    4772    4772      0   0.00% tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/veml6070/main.go
   6664    6664      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l293x/simple/main.go
   8576    8576      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l293x/speed/main.go
   6632    6632      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l9110x/simple/main.go
   9184    9184      0   0.00%    4740    4740      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l9110x/speed/main.go
   7284    7284      0   0.00%    3304    3304      0   0.00% tinygo build -size short -o ./build/test.hex -target=nucleo-f103rb ./examples/shiftregister/main.go
   6900    6900      0   0.00%    2252    2252      0   0.00% tinygo build -size short -o ./build/test.hex -target=hifive1b ./examples/ssd1351/main.go
  12904   12904      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/lis2mdl/main.go
   8780    8780      0   0.00%    4748    4748      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/max72xx/main.go
  77012   77012      0   0.00%    6324    6324      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/dht/main.go
  36388   36388      0   0.00%    3972    3972      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-rp2040 ./examples/pcf8523/
  71048   71048      0   0.00%    6324    6324      0   0.00% tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/alarm/
   7176    7176      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/clkout/
  70584   70584      0   0.00%    6320    6320      0   0.00% tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/time/
  71008   71008      0   0.00%    6332    6332      0   0.00% tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/timer/
  12064   12064      0   0.00%    3288    3288      0   0.00% tinygo build -size short -o ./build/test.hex -target=pico ./examples/qmi8658c/main.go
   8656    8656      0   0.00%    4740    4740      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/ina260/main.go
   9284    9284      0   0.00%    5244    5244      0   0.00% tinygo build -size short -o ./build/test.hex -target=nucleo-l432kc ./examples/aht20/main.go
  72492   72492      0   0.00%   10732   10732      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/sdcard/console/
  61248   61248      0   0.00%    8216    8216      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/i2csoft/adt7410/
  10216   10216      0   0.00%    6780    6780      0   0.00% tinygo build -size short -o ./build/test.elf -target=wioterminal ./examples/axp192/m5stack-core2-blinky/
   8916    8916      0   0.00%    3260    3260      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/xpt2046/main.go
  13696   13696      0   0.00%    4924    4924      0   0.00% tinygo build -size short -o ./build/test.hex -target=nucleo-wl55jc ./examples/sx126x/lora_rxtx/
  31208   31208      0   0.00%    4532    4532      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/ssd1289/main.go
  11140   11140      0   0.00%    4236    4236      0   0.00% tinygo build -size short -o ./build/test.hex -target=pico ./examples/irremote/main.go
  11784   11784      0   0.00%    3308    3308      0   0.00% tinygo build -size short -o ./build/test.hex -target=badger2040 ./examples/uc8151/main.go
  10296   10296      0   0.00%    3340    3340      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/scd4x/main.go
   8452    8452      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=circuitplay-express ./examples/makeybutton/main.go
   9448    9448      0   0.00%    4748    4748      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/ds18b20/main.go
  82928   82928      0   0.00%    6572    6572      0   0.00% tinygo build -size short -o ./build/test.hex -target=nucleo-wl55jc ./examples/lora/lorawan/atcmd/
  15816   15816      0   0.00%    4864    4864      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/as560x/main.go
   9776    9776      0   0.00%    3280    3280      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/mpu6886/main.go
   7708    7708      0   0.00%    4732    4732      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/ttp229/main.go
  66584   66584      0   0.00%    4800    4800      0   0.00% tinygo build -size short -o ./build/test.hex -target=pico ./examples/ndir/main_ndir.go
  62020   62020      0   0.00%    3772    3772      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ndir/main_ndir.go
  65004   65004      0   0.00%    6244    6244      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/ndir/main_ndir.go
   9204    9204      0   0.00%    3272    3272      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/mpu9150/main.go
  11284   11284      0   0.00%    3308    3308      0   0.00% tinygo build -size short -o ./build/test.hex -target=macropad-rp2040 ./examples/sh1106/macropad_spi
   8384    8384      0   0.00%    3744    3744      0   0.00% tinygo build -size short -o ./build/test.hex -target=macropad-rp2040 ./examples/encoders/quadrature-interrupt
  65560   65560      0   0.00%    4768    4768      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/mcp9808/main.go
  85748   85748      0   0.00%    5124    5124      0   0.00% tinygo build -size short -o ./build/test.hex -target=challenger-rp2040 ./examples/net/ntpclient/
 295004  295004      0   0.00%   12744   12744      0   0.00% tinygo build -size short -o ./build/test.hex -target=pyportal -stack-size 8kb ./examples/net/http-get/
 119160  119160      0   0.00%    7832    7832      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 -stack-size 8kb ./examples/net/tcpclient/
 244088  244088      0   0.00%    9496    9496      0   0.00% tinygo build -size short -o ./build/test.hex -target=nano-rp2040 -stack-size 8kb ./examples/net/websocket/dial/
 103296  103296      0   0.00%    9816    9816      0   0.00% tinygo build -size short -o ./build/test.hex -target=metro-m4-airlift -stack-size 8kb ./examples/net/socket/
 336880  336880      0   0.00%   15732   15732      0   0.00% tinygo build -size short -o ./build/test.hex -target=matrixportal-m4 -stack-size 8kb ./examples/net/webstatic/
 111372  111372      0   0.00%    7756    7756      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-mkrwifi1010 -stack-size 8kb ./examples/net/tlsclient/
 154024  154024      0   0.00%    6524    6524      0   0.00% tinygo build -size short -o ./build/test.hex -target=nano-rp2040 -stack-size 8kb ./examples/net/mqttclient/natiu/
 116892  116892      0   0.00%   13116   13116      0   0.00% tinygo build -size short -o ./build/test.hex -target=wioterminal -stack-size 8kb ./examples/net/webclient/
 284592  284592      0   0.00%   18156   18156      0   0.00% tinygo build -size short -o ./build/test.hex -target=wioterminal -stack-size 8kb ./examples/net/webserver/
 285624  285624      0   0.00%   17228   17228      0   0.00% tinygo build -size short -o ./build/test.hex -target=wioterminal -stack-size 8kb ./examples/net/mqttclient/paho/
5248664 5248664      0   0.00%  781946  781946      0   0.00%

if c.pkg.Path() == "runtime" || c.pkg.Path() == "syscall/js" || c.pkg.Path() == "syscall" {
// The runtime is a special case. Allow all kinds of parameters
// (importantly, including pointers).
return
}
if f.Blocks != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be retained for go:wasmimport

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, the check has been moved into case "//go:wasmimport": above.

@@ -649,6 +650,13 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
result.Binary = result.Executable // final file
ldflags := append(config.LDFlags(), "-o", result.Executable)

if config.Options.BuildMode == "c-shared" {
if config.GOOS() != "wasip1" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we’ll quickly relax this, perhaps better to check the triple or GOARCH for a wasm prefix?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m fairly certain that @deadprogram will want to use this for unknown.

Copy link
Member Author

@aykevl aykevl Oct 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. But to avoid too much complexity in this PR I've left it out. I tried to do it all at once but it became a bit more complex than I liked. Better to get it working for wasip1 first and then expand support to other targets (which should be relatively easy).

// Use reactor mode, which means the application is initialized in
// _initialize and main.main is not called by default. See for example:
// https://github.com/WebAssembly/WASI/blob/main/legacy/application-abi.md
tags = append(tags, "tinygo_wasm_reactor")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proposal: rename tinygo_wasm_reactor to tinygo.buildmode.c_shared

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we can do that, but tinygo_wasm_reactor seemed a bit more explicit. We can always change it later (I hope, if no external packages suddenly start depending on the build tag).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Context: I think mapping the tag to the flag eases the developer experience, both for TinyGo developers and end users.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have fixed this by removing the tag altogether and selecting between entry points inside the compiler. (This is similar to how big Go does it).

@@ -26,6 +27,7 @@ type Options struct {
GOMIPS string // environment variable (only used with GOARCH=mips and GOARCH=mipsle)
Directory string // working dir, leave it unset to use the current working dir
Target string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth adding BuildMode to TargetSpec as well, so wasm-unknown and wasip2 can set build mode to c-shared by default?

Copy link
Member Author

@aykevl aykevl Oct 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can do that in the PR that adds //go:wasmexport to wasm-unknown :)
This kind of complexity is why I kept //go:wasmexport to wasip1 for the initial version.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I'll make a follow up PR for wasip2 and unknown.

continue
}
name := parts[1]
if name == "_start" || name == "_initialize" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So //export remains for exports like _start and _initialize that don’t get the goroutine / scheduler dance?

Copy link
Member Author

@aykevl aykevl Oct 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but it's an implementation detail. Eventually I'd like to make //export work as it does on every other architecture (that is, it makes the function available to the linker but doesn't export it on a wasm level) - but that will probably require a deprecation period so people have time to switch to //go:wasmexport.

continue
}
if c.BuildMode != "c-shared" && f.RelString(nil) == "main.main" {
c.addError(f.Pos(), fmt.Sprintf("//go:wasmexport does not allow main.main to be exported with -buildmode=%s", c.BuildMode))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does big Go blow up if main.main is declared with -buildmode=c-shared?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This is what the proposal says:

When the -buildmode flag is unset, the _start function and any exported functions will be exported to the host. Using //go:wasmexport on the main function in this mode will result in a compilation error. In this mode, only _start will initialize the runtime, and so must be the first export called from the host. Any other exported functions may only be called through calling into host functions that call other exports during the execution of the _start function. Once the _start function has returned, no other exports may be called on the same instance.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the proposal allows main.main, and wasmexport on it, when -buildmode=c-shared:

When using -buildmode=c-shared, the resulting Wasm binary will not contain a _start function, and will only contain the _initialize function and any exported functions. The Go main function will not be exported to the host. The user can choose to export it like any other function using the //go:wasmexport directive. The _initialize function will not automatically call main. The main function will not initialize the runtime.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I missed the ! in the line. My mistake!

@ydnar
Copy link
Contributor

ydnar commented Sep 1, 2024

Looks like big Go supports go:wasmexport under js and with main.main: golang/go#65199 (comment)

@ydnar
Copy link
Contributor

ydnar commented Sep 29, 2024

For backwards compatibility, if both //export and //go:wasmexport are found, only implement go:wasmexport?

@ydnar
Copy link
Contributor

ydnar commented Sep 29, 2024

For tests, we could implement wasip1, wasip2, and unknown tests.

For wasip2, we can implement both worlds: wasi:cli/command and wasi:http/proxy, verifying:

  1. Goroutines started during init run during the reactor call (wasi:cli/command#run and wasi:http/incoming-handler#handle).
  2. The expected reactor function is called, by verifying output to either stdout/stderr or the HTTP response.

For wasip1 and unknown, using wasmtime with --invoke should be sufficient.

Copy link
Member Author

@aykevl aykevl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR still needs tests, that's what's needed to make this mergeable.

Looks like big Go supports go:wasmexport under js and with main.main: golang/go#65199 (comment)

Yes, I've intentionally left that out of the first PR. Focusing on wasip1 first made the PR a lot simpler.
(And to be clear, the comment does not say that main.main can be exported, just that if you call an imported function that imported function can then call back into an exported function. Which is exactly what I've implemented for wasip1 here).

For backwards compatibility, if both //export and //go:wasmexport are found, only implement go:wasmexport?

I guess we can do this. I don't see any obvious problems with that, as far as I can think the external ABI is the same (though of course //go:wasmexport has clearly defined semantics and //export does not). I would like to remove the ability for //export to produce wasm exported functions at some point though, because it's a non-standard TinyGo extension.

continue
}
name := parts[1]
if name == "_start" || name == "_initialize" {
Copy link
Member Author

@aykevl aykevl Oct 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but it's an implementation detail. Eventually I'd like to make //export work as it does on every other architecture (that is, it makes the function available to the linker but doesn't export it on a wasm level) - but that will probably require a deprecation period so people have time to switch to //go:wasmexport.

@@ -649,6 +650,13 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
result.Binary = result.Executable // final file
ldflags := append(config.LDFlags(), "-o", result.Executable)

if config.Options.BuildMode == "c-shared" {
if config.GOOS() != "wasip1" {
Copy link
Member Author

@aykevl aykevl Oct 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. But to avoid too much complexity in this PR I've left it out. I tried to do it all at once but it became a bit more complex than I liked. Better to get it working for wasip1 first and then expand support to other targets (which should be relatively easy).

// Use reactor mode, which means the application is initialized in
// _initialize and main.main is not called by default. See for example:
// https://github.com/WebAssembly/WASI/blob/main/legacy/application-abi.md
tags = append(tags, "tinygo_wasm_reactor")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we can do that, but tinygo_wasm_reactor seemed a bit more explicit. We can always change it later (I hope, if no external packages suddenly start depending on the build tag).

@@ -26,6 +27,7 @@ type Options struct {
GOMIPS string // environment variable (only used with GOARCH=mips and GOARCH=mipsle)
Directory string // working dir, leave it unset to use the current working dir
Target string
Copy link
Member Author

@aykevl aykevl Oct 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can do that in the PR that adds //go:wasmexport to wasm-unknown :)
This kind of complexity is why I kept //go:wasmexport to wasip1 for the initial version.

continue
}
if c.BuildMode != "c-shared" && f.RelString(nil) == "main.main" {
c.addError(f.Pos(), fmt.Sprintf("//go:wasmexport does not allow main.main to be exported with -buildmode=%s", c.BuildMode))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This is what the proposal says:

When the -buildmode flag is unset, the _start function and any exported functions will be exported to the host. Using //go:wasmexport on the main function in this mode will result in a compilation error. In this mode, only _start will initialize the runtime, and so must be the first export called from the host. Any other exported functions may only be called through calling into host functions that call other exports during the execution of the _start function. Once the _start function has returned, no other exports may be called on the same instance.

This adds support for the `//go:wasmexport` pragma as proposed here:
golang/go#65199

It is currently implemented only for wasip1, but it is certainly
possible to extend it to other targets like GOOS=js, wasm-unknown, or
wasip2. It is also currently limited to -buildmode=c-shared, this is a
limitation that could easily be lifted in the future.
@aykevl aykevl marked this pull request as ready for review October 2, 2024 16:02
@aykevl
Copy link
Member Author

aykevl commented Oct 2, 2024

  • Added some light testing
  • Removed the tinygo_wasm_reactor build tag.
  • Added runtime asserts to check that //go:wasmexport functions aren't being called at a time that it is not allowed.
  • Added support for //go:wasmexport with -buildmode=default (though I couldn't really test this: it's impossible to test through wasmtime --invoke).

This is now ready for review.

}

func runTestWithConfig(name string, t *testing.T, options compileopts.Options, cmdArgs, environmentVars []string) {
func runTestWithConfig(name string, t *testing.T, options compileopts.Options, cmdArgs, environmentVars []string, emulator string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than override emulator, what if struct TargetSpec had an EmulatorArgs field that is injected into the argument string for the default emulator for a target?

It could be injected in (*Config).Emulator(), appending " " + c.Target.EmulatorArgs.

@@ -100,6 +134,51 @@ func ticks() timeUnit {
return timeUnit(nano)
}

// Track which state we're in: before (or during) init, running inside
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can these lines be moved out to a runtime_wasm.go file, so they can be shared with wasip1, wasip2, and unknown?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants