Closed leongross closed 1 week ago
apparently this can also be done using device.Asm, no need for these wrappers for each architecture?
The best way to use inline assembly is actually by using CGo. See this file for an example:
https://github.com/tinygo-org/drivers/blob/release/ws2812/ws2812_avr.go
I've wanted to remove inline assembly from TinyGo entirely for a while but never actually got around to doing it. The reason is that it's incredibly complex so needs a complex API. But there's one already: in C. So no need to reinvent it.
If performance is a concern: a static inline CGo function will typically be inlined directly into Go (unlike the main Go implementation which has a big CGo overheid).
I see your point with CGO but there are use cases where CGO cannot/should not be used and these projects would not have any custom assembly support. In u-root for example afaik we do not use CGO so this would make things way more complicated.
Why do you not use CGo? In the case of TinyGo, it's not even possible to disable CGo support - it's always enabled.
Could you please elaborate on that? Why is CGO impossible to disable?
Maybe I can give you a rundown of what I am trying to achieve here. On the u-root project, we want to keep the size of the binaries small, so CGO is disabled to prohibit any use of C libraries, so the entire project disables it. Currently, this is policy and can't/shouldn't be changed. There won't be any C libraries in the binary, which renders CGO inline assembly unusable for us.
Now, some libraries like github.com/intel-go/
need to use inline assembly for instructions like cpuid
. Often, libraries use assembly files for that, which afaik tinygo does not support except for the target definitions. That leaves us with using the tinygo inline assembly approach that you want to deprecate.
Could you think of any other way how to drop-in and replace these assembly files in external packages we depend on? And what speaks against enabling support for assembly files as upstream go has?
Also, I can observe, that the CGO_ENABLED
variable in fact does make a difference in building applications; When I let cgo
enabled I tend to get the following error:
# os/user
../../../../../usr/lib/golang/src/os/user/cgo_lookup_cgo.go:14:6: not implemented: build constraints in #cgo line
When setting CGO_ENABLED=0
this error disappears. Can you tell me what's going on there?
Could you please elaborate on that? Why is CGO impossible to disable?
There are a few systems where CGo is required for TinyGo to work at all, such as MacOS and the rp2040 chip. Previously it was possible to disable CGo but that only led to confused users. See: https://github.com/tinygo-org/tinygo/pull/4136
On the u-root project, we want to keep the size of the binaries small, so CGO is disabled to prohibit any use of C libraries, so the entire project disables it.
TinyGo works differently. It does not include external C libraries. On Linux, there are two that are always included (and statically linked): compiler-rt and musl.
compiler-rt
is needed for lots of basic stuff in the compiler, without it nothing but the most trivial programs would work.musl
is needed for a few things: builtin functions the compiler emits (memory builtins like memcpy and math builtins like sqrt) and to make CGo work at all. It is also used for startup code (what comes before main
) and a few functions like mmap and clock_gettime.I did a quick check and musl currently takes up around 5kB of binary size. You can check this yourself using the -size=full
parameter. But, again, this is for pretty critical stuff that can't just be removed.
If we were to make it possible to disable CGo, you wouldn't actually gain anything from this. The compiler-rt and musl libraries would still be included. The only thing you would disable is the import "C"
construct.
And what speaks against enabling support for assembly files as upstream go has?
This is actually much more difficult than it may appear to be. In fact, I tried this (see https://github.com/tinygo-org/tinygo/pull/3103) and while it worked, it was one giant hack that was pretty brittle. So no, unless the Go project makes it a lot easier to reuse those assembly files we're not going to do that.
Also, I can observe, that the
CGO_ENABLED
variable in fact does make a difference in building applications; When I letcgo
enabled I tend to get the following error:
Odd, I think we're not passing the CGO_ENABLED
environment variable to our internal go list
call. That's a bug in TinyGo.
In any case, this specific build issue (with os/user) has been fixed in our latest release (by replacing the os/user package with a stub).
Currently
tinygo
does not support inline assembly for x86 (neither 32-bit nor 64-bit). This PR adds this functionality.