Previously, the compiler used LLVM's shift instructions directly, which have UB whenever the shifts are large or negative.
This commit adds runtime checks for negative shifts, and handles oversized shifts.
This commit teaches the interp scanner that supported interface
operations (type assertions, interface assertions) are supported.
This fixes a problem with math/rand in Go 1.14.
Non-constant type asserts are not yet implemented, but should be
relatively easy to add at a later time. They should result in a clear
error message for now.
This commit removes a panic and replaces it with a proper source
location. The message still isn't very helpful, but at least it points
to a location in the source code.
I'm not very happy with all the `err.Error()` calls, but that's the way
to fit this in a `scanner.Error`. Eventually we should make a
replacement for `scanner.Error` that does proper wrapping of the
original error message.
Some mapassign operations cannot (yet) be done by the interp package.
Implement a fallback mechanism so that these operations can still be
performed at runtime.
This commit replaces most panics in interp/frame.go and interp/scan.go
with real error messages. The remaining ones are panics that should not
happen when working with valid IR.
This kind of code might be generated by the switch implementation of
func values. The func value is represented as a ptrtoint, and before
calling it, it is compared against 0.
This commit improves error reporting in several ways:
* Location information is read from the intruction that causes the
error, as far as that's available.
* The package that is being interpreted is included in the error
message. This may be the most useful part of the improvements.
* The hashmap update intrinsics now doesn't panic, instead it logs a
clear error (with location information, as in the above two bullet
points).
This is possible thanks to improvements in LLVM 9. This means that after
this change, TinyGo will depend on LLVM 9.
This is really just a simple workaround. When such an instruction is
encountered, it will just fall back to marking the entire function as
having side effects. Ideally it should trace all affected instructions
and check if they would have any side effects, but this at least fixes a
number of compile errors.
This commit gets the following packages to compile:
* context
* database/sql/driver
* image/jpeg
* image/png
Declarations would enter an infinite loop when trying to loop over basic
blocks. That was probably an undefined operation, but still somehow
didn't crash the compiler.
Make sure that scanning declarations works as expected.
This implements the copy() built-in function. It may not work in all
cases, but should work in most cases.
This commit gets the following 3 packages to compile, according to
tinygo-site/imports/main.go:
* encoding/base32
* encoding/base64
* encoding/pem (was blocked by encoding/base64)
The IR builder does not appear to fold comparisons of constant inttoptr
instructions to const null pointer. So do it manually during
interpretatin, as a somewhat ugly hack.
This fixes https://github.com/tinygo-org/tinygo/issues/363
Previously, there was a suble error in that .IsConstant() is not always
allowed to be called, resulting in a i1 that was not 0 or 1. Fix this by
checking for the constants directly and adding some more diagnostics to
catch more cases.
During a scan, consider loads from dirty globals to be dirty and check
whether they have any local side effects.
This fixes a problem with the new volatile operations that are now in
methods on registers instead of being emitted inline as volatile
instructions.
This commit adds debug info to function arguments, so that in many cases
you can see them when compiling with less optimizations enabled.
Unfortunately, due to the way Go SSA works, it is hard to preserve them
in many cases.
Local variables are not yet saved.
Also, change the language type to C, to make sure lldb shows function
arguments. The previous language was Modula 3, apparently due to a
off-by-one error somewhere.
A call to .IsConstant() also returns true for constant globals, not just
constant expressions. Do an extra check that we're really operating on a
constant expression.
This function returns the current timestamp, or 0 at compile time.
runtime.nanotime is used at package initialization by the time package
starting with Go 1.12.
Whenever interp hits an unreachable instruction, it bails out at that
point. However, it used to insert new instructions at the bottom with
the old init calls still at the top. So when a panic() happened in a
non-main package, the last packages to init would actually be called
first.
This commit fixes this by setting the insert point at the top of
runtime.initAll before starting interpretation, so the initialization
order is still correct when a panic() happens during init.
There were a few issues that made interp not perform as it should:
* The scan was non-recursive due to a bug.
* Recursive scanning would always return the severity level, which is
not always the best strategy.
The interp package interprets calls in runtime.initAll and replaces
these calls with non-interpretable instructions if needed.
When hitting an unreachable instruction, this call should be removed,
but it wasn't. This commit makes sure the call is removed even before
trying to interpret the package init function.
Before this commit, goroutine support was spread through the compiler.
This commit changes this support, so that the compiler itself only
generates simple intrinsics and leaves the real support to a compiler
pass that runs as one of the TinyGo-specific optimization passes.
The biggest change, that was done together with the rewrite, was support
for goroutines in WebAssembly for JavaScript. The challenge in
JavaScript is that in general no blocking operations are allowed, which
means that programs that call time.Sleep() but do not start goroutines
also have to be scheduled by the scheduler.
This reduces complexity in the compiler without affecting binary sizes
too much.
Cortex-M0: no changes
Linux x64: no changes
WebAssembly: some testcases (calls, coroutines, map) are slightly bigger
This commit changes many things:
* Most interface-related operations are moved into an optimization
pass for more modularity. IR construction creates pseudo-calls which
are lowered in this pass.
* Type codes are assigned in this interface lowering pass, after DCE.
* Type codes are sorted by usage: types more often used in type
asserts are assigned lower numbers to ease jump table construction
during machine code generation.
* Interface assertions are optimized: they are replaced by constant
false, comparison against a constant, or a typeswitch with only
concrete types in the general case.
* Interface calls are replaced with unreachable, direct calls, or a
concrete type switch with direct calls depending on the number of
implementing types. This hopefully makes some interface patterns
zero-cost.
These changes lead to a ~0.5K reduction in code size on Cortex-M for
testdata/interface.go. It appears that a major cause for this is the
replacement of function pointers with direct calls, which are far more
susceptible to optimization. Also, not having a fixed global array of
function pointers greatly helps dead code elimination.
This change also makes future optimizations easier, like optimizations
on interface value comparisons.
* Loading from a dirty global must be done at runtime (!). For some
reason this wasn't already the case.
* Global variables somehow had IsConstant() the wrong way round,
returning the inverse from what they should.
* Do binary and logical operations at runtime if necessary, relying on
const propagation in the IR builder.
* Don't try to interpret functions that take a dirty parameter. Call
them at runtime.
Cast operations will still be evaluated at compile time in all cases
they did before because of the built-in constant propagation of the
IRBuilder, but when one of the parameters is not a constant it will
transparently be evaluated at runtime.
This avoids some errors in the partial evaluator. It is not yet complete
as all binops will need a similar treatment.