Only try to convert the C symbols to their Go equivalents that are
actually referenced by the Go code with C.<somesymbol>. This avoids
having to support all possible C types, which is difficult because of
oddities like `typedef void` or `__builtin_va_list`. Especially
__builtin_va_list, which varies between targets.
These types (called elaborated types in C) are used as part of linked
lists, among others.
This is part an extra feature (to be compatible with CGo C.struct_
types) and part a bugfix: linked lists would result in endless recursion
leading to a stack overflow.
Sometimes when a GC happens while processing a C fragment with libclang,
a pointer-typed integer with value 0x1 ends up on the Go stack and the
GC will trip over it. This commit changes the offending struct type to
be uintptr_t instead of void*.
See https://go-review.googlesource.com/c/go/+/66332 for a similar
change.
Unions are somewhat hard to implement in Go because they are not a
native type. But it is actually possible with some compiler magic.
This commit inserts a special "C union" field at the start of a struct
to indicate that it is a union. As such a field cannot be written
directly in Go, this is a useful to distinguish structs and unions.
This makes CGo-emitted diagnostics very similar to regular errors
emitted while parsing/typechecking a package.
It's not complete, but after introducing some errors in testdata/cgo,
this is the resulting output:
# ./testdata/cgo/
testdata/cgo/main.h:18:11: error: a parameter list without types is only allowed in a function definition
testdata/cgo/main.go:5:10: note: in file included from testdata/cgo/main.go!cgo.c:2:
testdata/cgo/main.go:6:19: error: expected identifier or '('
Previously, this was the output:
/home/ayke/src/github.com/tinygo-org/tinygo/testdata/cgo/main.h:18:11: error: a parameter list without types is only allowed in a function definition
cgo-fake.c:3:19: error: expected identifier or '('
# ./testdata/cgo/
cgo: libclang cannot parse fragment
The magic CGo construct to turn a C array into a slice turned out to be
not portable.
Note: this is not the only problem, there is also a bug in the Go
bindings for LLVM. With that one fixed, it is possible to build TinyGo
on a Raspberry Pi (32-bit).