Skip to content

reflect, compiler: add signature based methods, fix String#5339

Draft
jakebailey wants to merge 2 commits intotinygo-org:devfrom
jakebailey:reflect-signatures
Draft

reflect, compiler: add signature based methods, fix String#5339
jakebailey wants to merge 2 commits intotinygo-org:devfrom
jakebailey:reflect-signatures

Conversation

@jakebailey
Copy link
Copy Markdown
Member

Fixes #2650
Fixes #3943
Fixes #4458

This is all pretty much boilerplate; writing this info out, reading it back in again 😅

I have not done any of the fancy DCE I did in #5304. I am hoping it's not required, but I'm probably not that lucky.

Copy link
Copy Markdown
Member

@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.

Looks reasonable to me, but see the comment below for an optimization.

That said, does this actually move things forward? Or are real-world programs just going to call .Call next and fail at that point, in which case we haven't made much progress?

Also, for context, here is the binary size difference (lifted from the CI run that couldn't make a comment here):

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=pico ./examples/tmc5160/main.go
    go: downloading golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d
 flash                          ram
 before   after   diff          before   after   diff
  17112   17112      0   0.00%    6576    6576      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-rp2040 ./examples/adafruit4650
   8764    8764      0   0.00%    5088    5088      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adxl345/main.go
  13636   13636      0   0.00%    7136    7136      0   0.00% tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/amg88xx
   8924    8924      0   0.00%    5088    5088      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/main.go
  11372   11372      0   0.00%    6928    6928      0   0.00% tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/apds9960/proximity/main.go
   7356    7356      0   0.00%    2296    2296      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/at24cx/main.go
   8008    8008      0   0.00%    5080    5080      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bh1750/main.go
   7368    7368      0   0.00%    5080    5080      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/blinkm/main.go
  27664   27664      0   0.00%    5120    5120      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmp180/main.go
  11816   11816      0   0.00%    5152    5152      0   0.00% tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/bmp388/main.go
  23336   23336      0   0.00%    5744    5744      0   0.00% tinygo build -size short -o ./build/test.hex -target=metro-rp2350 ./examples/bno08x/i2c/main.go
   7712    7712      0   0.00%    3336    3336      0   0.00% tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/sram/main.go
   4400    4400      0   0.00%    2256    2256      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/easystepper/main.go
   7068    7068      0   0.00%    2260    2260      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/gc9a01/main.go
   8420    8420      0   0.00%    5080    5080      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/hcsr04/main.go
  10376   10376      0   0.00%    5088    5088      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/hd44780i2c/main.go
  14248   14248      0   0.00%    6928    6928      0   0.00% tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/hts221/main.go
  15980   15980      0   0.00%    2340    2340      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hub75/main.go
  10156   10156      0   0.00%    7264    7264      0   0.00% tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/basic
  11144   11144      0   0.00%    5224    5224      0   0.00% tinygo build -size short -o ./build/test.hex -target=xiao ./examples/ili9341/basic
  29436   29436      0   0.00%   38424   38424      0   0.00% tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/pyportal_boing
  10188   10188      0   0.00%    7256    7256      0   0.00% tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/scroll
  11224   11224      0   0.00%    5216    5216      0   0.00% tinygo build -size short -o ./build/test.hex -target=xiao ./examples/ili9341/scroll
  10472   10472      0   0.00%    5120    5120      0   0.00% tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/lis3dh/main.go
  13632   13632      0   0.00%    6928    6928      0   0.00% tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/lps22hb/main.go
  26188   26188      0   0.00%    2304    2304      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/lsm303agr/main.go
  27860   27860      0   0.00%    7168    7168      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/lsm303dlhc/main.go
  12312   12312      0   0.00%    5128    5128      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/lsm6ds3/main.go
  10020   10020      0   0.00%    5080    5080      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mag3110/main.go
   8984    8984      0   0.00%    5120    5120      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp23017/main.go
   9416    9416      0   0.00%    5128    5128      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp23017-multiple/main.go
   9440    9440      0   0.00%    5088    5088      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp3008/main.go
   7464    7464      0   0.00%    5088    5088      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mma8653/main.go
   7368    7368      0   0.00%    5080    5080      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mpu6050/main.go
  12312   12312      0   0.00%    5756    5756      0   0.00% tinygo build -size short -o ./build/test.hex -target=pico ./examples/pca9685/main.go
  12296   12296      0   0.00%    6200    6200      0   0.00% tinygo build -size short -o ./build/test.hex -target=badger2040 ./examples/waveshare-epd/epd2in9v2/main.go
  10516   10516      0   0.00%    5752    5752      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/scd4x/main.go
   7984    7984      0   0.00%    5088    5088      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=circuitplay-express ./examples/makeybutton/main.go
   9448    9448      0   0.00%    5104    5104      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/ds18b20/main.go
  16104   16104      0   0.00%    7348    7348      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/as560x/main.go
   9912    9912      0   0.00%    5700    5700      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/mpu6886/main.go
   7764    7764      0   0.00%    5080    5080      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/ttp229/main.go
   9364    9364      0   0.00%    5692    5692      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/mpu9150/main.go
  11612   11612      0   0.00%    5728    5728      0   0.00% tinygo build -size short -o ./build/test.hex -target=macropad-rp2040 ./examples/sh1106/macropad_spi
   8508    8508      0   0.00%    6156    6156      0   0.00% tinygo build -size short -o ./build/test.hex -target=macropad-rp2040 ./examples/encoders/quadrature-interrupt
  13220   13220      0   0.00%    5688    5688      0   0.00% tinygo build -size short -o ./build/test.hex -target=pico ./examples/tmc5160/main.go
  12004   12004      0   0.00%    4900    4900      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=nicenano ./examples/sharpmem/main.go
  12856   12856      0   0.00%    5748    5748      0   0.00% tinygo build -size short -o ./build/test.hex -target=pico ./examples/ens160/main.go
  16108   16108      0   0.00%    5764    5764      0   0.00% tinygo build -size short -o ./build/test.hex -target=pico ./examples/si5351/main.go
  13128   13132      4   0.03%    4924    4924      0   0.00% tinygo build -size short -o ./build/test.hex -target=nucleo-wl55jc ./examples/sx126x/lora_rxtx/
   5528    5544     16   0.29%    2256    2256      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hd44780/customchar/main.go
   5568    5584     16   0.29%    2256    2256      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hd44780/text/main.go
  11728   11752     24   0.20%    5684    5684      0   0.00% tinygo build -size short -o ./build/test.hex -target=xiao-rp2040 ./examples/ssd1306/
  11816   11840     24   0.20%    5684    5684      0   0.00% tinygo build -size short -o ./build/test.hex -target=thumby ./examples/ssd1306/
   9828    9896     68   0.69%    5108    5108      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/itsybitsy-m0/main.go
  27444   27780    336   1.22%    3808    3808      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/microbitmatrix/main.go
  29108   29448    340   1.17%    5316    5316      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/ds3231/alarms/main.go
  36252   36592    340   0.94%    6388    6388      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-rp2040 ./examples/pcf8523/
  42440   42780    340   0.80%    7536    7536      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/tmc2209/main.go
  71676   72020    344   0.48%    3640    3640      0   0.00% tinygo build -size short -o ./build/test.hex -target=pinetime     ./examples/bma42x/main.go
  42980   43324    344   0.80%    5316    5316      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/ds3231/basic/main.go
  57612   57956    344   0.60%    3672    3672      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/sht3x/main.go
  57612   57956    344   0.60%    3672    3672      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/shtc3/main.go
  74056   74400    344   0.46%   11092   11092      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/sdcard/console/
  31848   32192    344   1.08%    7200    7200      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/ssd1289/main.go
  67464   67808    344   0.51%    7212    7212      0   0.00% tinygo build -size short -o ./build/test.hex -target=pico ./examples/ndir/main_ndir.go
  65572   65916    344   0.52%    6600    6600      0   0.00% tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/ndir/main_ndir.go
  62024   62376    352   0.57%    6528    6528      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adt7410/main.go
  65908   66260    352   0.53%    6544    6544      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmi160/main.go
  64580   64932    352   0.55%    6568    6568      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmp280/main.go
  72036   72388    352   0.49%    6584    6584      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp2515/main.go
  76548   76900    352   0.46%    7788    7788      0   0.00% tinygo build -size short -o ./build/test.hex -target=p1am-100 ./examples/p1am/main.go
  57604   57956    352   0.61%    3680    3680      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/sht4x/main.go
  77244   77596    352   0.46%    6680    6680      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/dht/main.go
  71608   71960    352   0.49%    6688    6688      0   0.00% tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/alarm/
  71044   71396    352   0.50%    6688    6688      0   0.00% tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/time/
  71440   71792    352   0.49%    6688    6688      0   0.00% tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/timer/
 122768  123120    352   0.29%    8112    8112      0   0.00% tinygo build -size short -o ./build/test.hex -target=nucleo-wl55jc ./examples/lora/lorawan/atcmd/
  62228   62580    352   0.57%    3768    3768      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ndir/main_ndir.go
  67136   67488    352   0.52%    7180    7180      0   0.00% tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/mcp9808/main.go
 264552  264912    360   0.14%   47108   47108      0   0.00% tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/slideshow
  62948   63308    360   0.57%    6296    6296      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-nrf52840 ./examples/is31fl3731/main.go
  62264   62624    360   0.58%    8576    8576      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/i2csoft/adt7410/
  62696   63056    360   0.57%    6332    6332      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-nrf52840 ./examples/max6675/main.go
  21616   21984    368   1.70%    3532    3532      0   0.00% tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/time/main.go
  67660   68028    368   0.54%    6704    6704      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/gps/i2c/main.go
  68360   68728    368   0.54%    6852    6852      0   0.00% tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/gps/uart/main.go
  27324   27692    368   1.35%    5852    5852      0   0.00% tinygo build -size short -o ./build/test.hex -target=microbit-v2 ./examples/microbitmatrix/main.go
  42192   42564    372   0.88%    8964    8964      0   0.00% tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/sx127x/lora_rxtx/
  67004   68052   1048   1.56%    9356    9356      0   0.00% tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/flash/console/qspi
  70612   71684   1072   1.52%    7316    7316      0   0.00% tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/flash/console/spi
3540292 3554532  14240   0.00%  850252  850252      0   0.00%

Comment thread src/internal/reflectlite/type.go Outdated
@aykevl
Copy link
Copy Markdown
Member

aykevl commented Apr 22, 2026

Adding .Call() for common parameter/return types on normal architectures (ARM etc) is possible, but requires some familiarity with the calling convention. Doing it on WebAssembly is going to be much more difficult, since function signatures need to match.

@jakebailey
Copy link
Copy Markdown
Member Author

That said, does this actually move things forward? Or are real-world programs just going to call .Call next and fail at that point, in which case we haven't made much progress?

Call is where I'm going with this, ultimately. Whether or not that's going to turn out well, I'm unsure. Largely this all is me going "I need AssignableTo to work", then noticing missing stuff after that and so on, so could probably stop at any point.

@aykevl
Copy link
Copy Markdown
Member

aykevl commented Apr 24, 2026

Call is where I'm going with this, ultimately. Whether or not that's going to turn out well, I'm unsure.

Is your goal doing a Call on something returned from Method (or MethodByName etc), or doing it from things that were originally func value (stuff like reflect.ValueOf(strings.Compare) as a silly example)? This matters a lot!
The latter case is doable though needs some annoying low level calling convention stuff, the former would mean that every object that is ever made into an interface needs to have all methods (and their implementations) preserved in case its method is extracted and called with Call. Which would disable all the dead code elimination we've been doing.

@jakebailey
Copy link
Copy Markdown
Member Author

jakebailey commented Apr 24, 2026

I would assume both? I was hoping new DCE could detect whether or not Call was even used, or, some sort of flag to start disabling this information.

@aykevl
Copy link
Copy Markdown
Member

aykevl commented Apr 24, 2026

Yeah, you can detect the usage of Call and disable all the DCE. It would be annoying compiler-wise since it is yet another difference in behavior (and requires whole program optimizations which I hope to eventually get rid of - they're a huge burden on compile time). Also, with larger programs it becomes increasingly likely that somewhere something calls Call which means the optimization is still disabled even if that call is never reached.

Anyway, maybe it would be good to have some measurements before continuing this? Since the tradeoff might not be worth it.

@jakebailey jakebailey marked this pull request as draft April 24, 2026 14:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants