In the go protobuf code, a pattern is used to statically prevent
comparable structs by embedding:
```
type DoNotCompare [0]func()
type message struct {
DoNotCompare
data *uint32
}
```
Previously, sizezof(message{}) is 2 words large, but it only needs to be
1 byte. Making it be 1 byte allows protobufs to compile slightly more
(though not all the way).
There used to be a difference between `byte` and `uint8` in interface
methods. These are aliases, so they should be treated the same.
This patch introduces a custom serialization format for types,
circumventing the `Type.String()` method that is slightly wrong for our
purposes.
This also fixes an issue with the `any` keyword in Go 1.18, which
suffers from the same problem (but this time actually leads to a crash).
Also fix typo in error message in sub_test.go from upstream,
and move a few members from B to common where they belonged.
Note that testdata/testing.go seems to be pushing the edge of what
the emulated cortex-m3 target can handle; using regexp in that test
causes it to fail on that target with an out of memory error.
TODO: once tinygo supports runtime.Goexit, consider just using upstream's testing directory...
This change prevents interp from trying to execute goroutine starts or checks.
This fixes a bug where a goroutine started by an init function would run before the init function.
This change fixes the edge case where a negative sleep time is provided.
When this happens, the call now returns immediately (as specified by the docs for time.Sleep).
Operations on nil maps are accepted and shouldn't
panic. The base hashmapGet/hashmapDelete handled
nil-maps correctly, but the hashmapBinary versions
could segfault accessing the nil map while trying
to hash the key.
Fixes#2341
Some map keys are hard to compare, such as floats. They are stored as if
the map keys are of interface type instead of the key type itself. This
makes working with them in the runtime package easier: they are compared
as regular interfaces.
Iterating over maps didn't care about this special case though. It just
returns the key, value pair as it is stored in the map. This is buggy,
and this commit fixes this bug.
This allows positive and negative zero to hash to the same value,
as required by Go.
This is not perfect, but the best I could do without
revamping all the hash funtions to take a seed.
Fixes#2356
This is necessary for the following:
- to make sure os/exec can be imported
- to make sure internal/testenv can be imported
The internal/testenv package (which imports os/exec) is used by a lot of
tests. By adding support for it, more tests can be run.
This commit adds a bunch of new packages that now pass all tests.
The implementation has been mostly copied from the Go reference
implementation with some small changes to fit TinyGo.
Source: 77a11c05d6/src/reflect/deepequal.go
In addition, this commit also contains the following:
- A set of tests copied from the Go reflect package.
- An increased stack size for the riscv-qemu and hifive1-qemu targets
(because they otherwise fail to run the tests). Because these
targets are only used for testing, this seems fine to me.
v.Interaface() could construct an interface in interface value if v was
of type interface. This is not correct, and doesn't follow upstream Go
behavior. Instead, it should return the interface value itself.
This commit will use the memory layout information for heap allocations
added in the previous commit to determine LLVM types, instead of
guessing their types based on the content. This fixes a bug in which
recursive data structures (such as doubly linked lists) would result in
a compiler stack overflow due to infinite recursion.
Not all heap allocations have a memory layout yet, but this can be
incrementally fixed in the future. So far, this commit should fix
(almost?) all cases of this stack overflow issue.
This adds support for a construct like this:
type foo func(fn foo)
Unfortunately, LLVM cannot create function pointers that look like this.
LLVM only supports named types for structs (not for pointers) and thus
can't add a pointer to a function type of the same type to a parameter
of that function type.
The fix is simple: cast all function pointers to a void function, in
LLVM IR:
void ()*
Raw function pointers are cast to this type before storing, and cast
back to the regular function type before calling. This means that
function parameters will never refer to its own type because raw
function types are fixed at that one type.
Somehow, this does have an effect on binary size in some cases. The
effect is small and goes both ways. On top of that, there is work
underway in LLVM which would make all pointer types opaque (without a
pointee type). This would make this whole commit useless and therefore
should fix any size increases that might happen.
https://llvm.org/docs/OpaquePointers.html
The division and remainder operations were lowered directly to LLVM IR.
This is wrong however because the Go specification defines exactly what
happens on a divide by zero or signed integer overflow and LLVM IR
itself treats those cases as undefined behavior. Therefore, this commit
implements divide by zero and signed integer overflow according to the
Go specification.
This does have an impact on the generated code, but it is surprisingly
small. I've used the drivers repo to test the code before and after, and
to my surprise most driver smoke tests are not changed at all. Those
that are, have only a small increase in code size. At the same time,
this change makes TinyGo more compliant to the Go specification.
This adds support for stdio in picolibc and fixes wasm_exec.js so that
it can also support C puts. With this, C stdout works on all supported
platforms.
This is just a first step. It's not complete, but it gets some real
world C code to parse.
This signature, from the ESP-IDF:
esp_err_t esp_wifi_get_mac(wifi_interface_t ifx, uint8_t mac[6]);
Was previously converted to something like this (pseudocode):
C.esp_err_t esp_wifi_get_mac(ifx C.wifi_interface_t, mac [6]uint8)
But this is not correct. C array parameters will decay. The array is
passed by reference instead of by value. Instead, this would be the
correct signature:
C.esp_err_t esp_wifi_get_mac(ifx C.wifi_interface_t, mac *uint8)
So that it can be called like this (using CGo):
var mac [6]byte
errCode := C.esp_wifi_get_mac(C.ESP_IF_WIFI_AP, &mac[0])
This stores the result in the 6-element array mac.
For example, the following did not work before but does work with this
change:
// int add(int a, int b) {
// return a + b;
// }
import "C"
func main() {
println("add:", C.add(3, 5))
}
Even better, the functions in the header are compiled together with the
rest of the Go code and so they can be optimized together! Currently,
inlining is not yet allowed but const-propagation across functions
works. This should be improved in the future.
This flag is passed automatically with the (new) -v flag for TinyGo. For
example, this prints all the test outputs:
$ tinygo test -v crypto/md5
=== RUN TestGolden
--- PASS: TestGolden
=== RUN TestGoldenMarshal
--- PASS: TestGoldenMarshal
=== RUN TestLarge
--- PASS: TestLarge
=== RUN TestBlockGeneric
--- PASS: TestBlockGeneric
=== RUN TestLargeHashes
--- PASS: TestLargeHashes
PASS
ok crypto/md5 0.002s
This prints just a summary:
$ tinygo test crypto/md5
PASS
ok crypto/md5 0.002s
(The superfluous 'PASS' message may be removed in the future).
This is especially useful when testing a large number of packages:
$ tinygo test crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512
PASS
ok crypto/md5 0.002s
PASS
ok crypto/sha1 0.043s
PASS
ok crypto/sha256 0.002s
PASS
ok crypto/sha512 0.003s
At the moment, the -test.v flag is not supplied to binaries running in
emulation. I intend to fix this after
https://github.com/tinygo-org/tinygo/pull/2038 lands by refactoring
runPackageTest, Run, and runTestWithConfig in the main package which all
do something similar.
Bug 1790 ("musttail call must precede a ret with an optional bitcast")
is caused by the GC stack slot pass inserting a store instruction
between a musttail call and a return instruction. This is not allowed in
LLVM IR.
One solution would be to remove the musttail. That would probably work,
but 1) the go-llvm API doesn't support this and 2) this might have
unforeseen consequences. What I've done in this commit is to move the
store instruction to a position earlier in the basic block, just after
the last access to the GC stack slot alloca.
Thanks to @fgsch for a very small repro, which I've used as a regression
test.
This fixes https://github.com/tinygo-org/tinygo/issues/1884.
My original plan to fix this was much more complicated, but then I
realized that the output type doesn't matter anyway and I can simply
cast the type to an *i8 and perform a GEP on that pointer.