Previously, libclang was run on each fragment (import "C") separately.
However, in regular Go it's possible for later fragments to refer to
types in earlier fragments so they must have been parsed as one.
This commit changes the behavior to run only one C parser invocation for
each Go file.
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 commit changes a target triple like "armv6m-none-eabi" to
"armv6m-unknown-unknow-eabi". The reason is that while the former is
correctly parsed in Clang (due to normalization), it wasn't parsed
correctly in LLVM meaning that the environment wasn't set to EABI.
This change normalizes all target triples and uses the EABI environment
(-eabi in the triple) for Cortex-M targets.
This change also drops the `--target=` flag in the target JSON files,
the flag is now added implicitly in `(*compileopts.Config).CFlags()`.
This removes some duplication in target JSON files.
Unfortunately, this change also increases code size for Cortex-M
targets. It looks like LLVM now emits calls like __aeabi_memmove instead
of memmove, which pull in slightly more code (they basically just call
the regular C functions) and the calls themself don't seem to be as
efficient as they could be. Perhaps this is a LLVM bug that will be
fixed in the future, as this is a very common occurrence.
This is a loose collection of small fixes flagged by staticcheck:
- dead code
- regexp expressions not using backticks (`foobar` / "foobar")
- redundant types of slice and map initializers
- misc other fixes
Not all of these seem very useful to me, but in particular dead code is
nice to fix. I've fixed them all just so that if there are problems,
they aren't hidden in the noise of less useful issues.
Normalization was required because previously we supported Go 1.13 and
Go 1.14 at the same time. Now we've dropped support for both so this
normalization is not necessary anymore.
CGo support remains the same. It's just the test outputs that aren't
normalized anymore.
This converts the existing const parser to the basics of a Pratt parser,
following the book "Writing An Interpreter In Go" by Thorsten Ball. It
doesn't really do anything interesting yet, it simply converts the
existing code (with existing tests) to the new structure.
This patch adds support for passing CFLAGS added in #cgo lines of the
CGo preprocessing phase to the compiler when compiling C files inside
packages. This is expected and convenient but didn't work before.
This commit switches from the previous behavior of compiling the whole
program at once, to compiling every package in parallel and linking the
LLVM bitcode files together for further whole-program optimization.
This is a small performance win, but it has several advantages in the
future:
- There are many more things that can be done per package in parallel,
avoiding the bottleneck at the end of the compiler phase. This
should speed up the compiler futher.
- This change is a necessary step towards a non-LTO build mode for
fast incremental builds that only rebuild the changed package, when
compiler speed is more important than binary size.
- This change refactors the compiler in such a way that it will be
easier to inspect the IR for one package only. Inspecting this IR
will be very helpful for compiler developers.
This LLVM version breaks CI and is now relatively rather old anyway, so
remove support for it.
This also reverts a workaround for LLVM 9, see a9568932b ("maixbit:
workaround to avoid medium code model").
This doesn't yet add support for actually making use of variadic
functions, but at least allows (unintended) variadic functions like the
following to work:
void foo();
This can be useful to test improvements in LLVM master and to make it
possible to support LLVM 11 for the most part already before the next
release. That also allows catching LLVM bugs early to fix them upstream.
Note that tests do not yet pass for this LLVM version, but the TinyGo
compiler can be built with the binaries from apt.llvm.org (at the time
of making this commit).
Previously it would return a `*scanner.Error`, which is not supported in
the error printer of the main package. This can easily be fixed by
making it a regular object (instead of a pointer).
This makes the result consistent across Go versions, by running a regex
on the CGo output that wraps all single-line functions in a consistent
way.
Originally written by Elliott Sales de Andrade and modified by Ayke van
Laethem.
This commit also adds a bit of version independence, in particular for
external commands. It also adds the LLVM version to the `tinygo version`
command, which might help while debugging.
This is necessary for better CGo support on bare metal. Existing
libraries expect to be able to include parts of libc and expect to be
able to link to those symbols.
Because with this all targets have a working libc, it is now possible to
add tests to check that a libc in fact works basically.
Not all parts of picolibc are included, such as the math or stdio parts.
These should be added later, when needed.
This commit also avoids the need for the custom memcpy/memset/memcmp
symbols that are sometimes emitted by LLVM. The C library will take care
of that.
Since LLVM 9, CGo sometimes randomly breaks with weird error messages on
Windows. I'm not sure why this is the case, but it might be related to
concurrency.
Disable concurrency for now, and hope that will make the errors go away.
This implementation is still very limited but provides a base to build
upon. Limitations:
* CGO_CFLAGS etc is not taken into account.
* These CFLAGS are not used in C files compiled with the package.
* Other flags (CPPFLAGS, LDFAGS, ...) are not yet implemented.
This commit adds tests for CGo preprocessing. There are various errors
that can be reported while preprocessing, and they should integrate well
with the compiler (including accurate source location tracking).
Also allow CGo preprocessing to continue after Clang encountered an
error, for a better view of what happened.
When this flag is set, the testdata/*.out.go files will be updated when
they have changed. This is very convenient for updating these files
after the expected output changes.
Of course, the updated output must still be checked for validity.
Instead of putting the magic in the AST, generate regular accessor
methods. This avoids a number of special cases in the compiler, and
avoids missing any of them.
The resulting union accesses are somewhat clunkier to use, but the
compiler implementation has far less coupling between the CGo
implementation and the IR generator.
Not all enums may be used as a type anywhere, which was previously the
only way to include an enum in the AST. This commit makes sure all enums
are included.
This commit renames reserved field names like `type` to `_type`, and in
turn renames those fields as well (recursively). This avoids name
clashes when a C struct contains a field named `type`, which is a
reserved keyword in Go.
For some details, see:
https://golang.org/cmd/cgo/#hdr-Go_references_to_C
Previously it was just a combination of heuristics to try to fit a
constant in an *ast.BasicLit. For more complex expressions, this is not
enough.
This change also introduces proper syntax error with locations, if
parsing a constant failed. For example, this will print a real error
message with source location:
#define FOO 5)
Previously, a GenDecl was shared between many different
consts/vars/types. However, it actually makes much more sense not to
bundle them as that is also the case in C.
This makes the printed output of the CGo AST much nicer, and works
around a bug in Go 1.11.
This commit improves diagnostics in a few ways:
* All panics apart from panics with no (easy) recovery are converted to
regular errors with source location.
* Some errors were improved slightly to give more information. For
example, show the libclang type kind as a string instead of a
number.
* Improve source location by respecting line directives in the C
preprocessor.
* Refactor to unify error handling between libclang diagnostics and
failures to parse the libclang AST.
Types used in a program may not be implemented. Print a nice error
message explaining the situation, instead of just prepending C. to the
type spelling (and hoping the user knows what that undefined reference
means).
Enum types are implemented as named types (with possible accompanying
typedefs as type aliases). The constants inside the enums are treated as
Go constants like in the Go toolchain.