Skip to content

Conversation

@aykevl
Copy link
Member

@aykevl aykevl commented Oct 7, 2020

For a full explanation, see interp/README.md. In short, this rewrite is a redesign of the partial evaluator which improves it over the previous partial evaluator. The main functional difference is that when interpreting a function, the interpretation can be rolled back when an unsupported instruction is encountered (for example, an actual unknown instruction or a branch on a value that's only known at runtime). This also means that it is no longer necessary to scan functions to see whether they can be interpreted: instead, this package now just tries to interpret it and reverts when it can't go further.

This new design has several benefits:

  • Most errors coming from the interp package are avoided, as it can simply skip the code it can't handle. This has long been an issue.
  • The memory model has been improved, which means some packages now pass all tests that previously didn't pass them.
  • Because of a better design, it is in fact a bit faster than the previous version.

This means the following packages now pass tests with tinygo test:

  • hash/adler32: previously it would hang in an infinite loop
  • math/cmplx: previously it resulted in errors

This PR depends on #1412, which should be merged first. Also, it requires a change to the go-llvm package.

@deadprogram
Copy link
Member

#1412 has been merged. Not sure what change is needed to go-llvm or if that has already been made.

@aykevl
Copy link
Member Author

aykevl commented Oct 17, 2020

No, a different change is needed. I'll get back to this, it really helps to make TinyGo a more correct Go compiler.

@aykevl
Copy link
Member Author

aykevl commented Oct 27, 2020

Looks like this almost works, but needs some work to support some Go versions.

@sago35 sago35 mentioned this pull request Oct 28, 2020
@aykevl aykevl force-pushed the interp-rewrite branch 2 times, most recently from 0749d15 to 87258f6 Compare October 29, 2020 12:02
@aykevl
Copy link
Member Author

aykevl commented Oct 29, 2020

Note that this should probably be merged after the next release, to give it some time to find possible bugs.

@deadprogram
Copy link
Member

Indeed 😺

@aykevl
Copy link
Member Author

aykevl commented Nov 4, 2020

Updated the PR, I think it is ready now. This newer version fixes an issue with the append builtin and (in a separate commit) fixes a bug with an assertion in the coroutine lowering pass (#1409 and #733).

@ofauchon
Copy link
Contributor

With tinygo (dev branch), I could not compile my application:

traceback:
/usr/lib/go/src/bytes/bytes.go:
  br i1 %14, label %for.body, label %for.done, !dbg !2460
/home/olivier/go/src/github.com/jacobsa/crypto/cmac/subkey.go:29:27:
  %9 = call { i8*, i32, i32 } @bytes.Repeat(i8* %6, i32 %7, i32 %8, i32 16, i8* undef, i8* undef), !dbg !2457
github.com/jacobsa/crypto/cmac/<init>:
  call void @"github.com/jacobsa/crypto/cmac.init#1"(i8* undef, i8* undef), !dbg !2452

Then I applied the 3 commits

git cherry-pick b3794a9ea8af6b7c71112a15ad54470db060c66c
git cherry-pick 54ce74a784e05ac6c7d009aa840c802cf66fa1b6
git cherry-pick 0b3b692d533630e306bc815ac3387073bd954f8c
go install

This fixed the previous error !

Thanks

Olivier

Previously, EmitPointerPack would generate an out-of-bounds read from an
alloca. This commit fixes that by creating an alloca of the appropriate
size instead of using the size of the to-be-packed data (which might be
smaller than a pointer).

I discovered this error while working on a rewrite of the interp
package, which checks for out-of-bounds reads and writes. There I
discovered this issue when the image package was compiled.
Because the parentHandle parameter wasn't always set to the right value,
the coroutine lowering pass would sometimes panic with "trying to make
exported function async" even though there was no exported function
involved. Therefore, it should unconditionally be set to avoid this.

The parent function doesn't always have the parentHandle function
parameter set because it can only be set after defining a function, not
when it is only declared.
Copy link
Member

@niaow niaow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, one minor comment

interp/memory.go Outdated
}
mv.objects[objectIndex] = obj
}
// TODO: also mark objects referenced by this object.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this going to break anything now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my testing, no. However it is technically unsound and should probably be fixed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, does this require additional work now, or should we merge and deal with in future effort?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think I shouldn't be lazy and fix this (even if it doesn't seem to affect the behavior right now).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed now.

For a full explanation, see interp/README.md. In short, this rewrite is
a redesign of the partial evaluator which improves it over the previous
partial evaluator. The main functional difference is that when
interpreting a function, the interpretation can be rolled back when an
unsupported instruction is encountered (for example, an actual unknown
instruction or a branch on a value that's only known at runtime). This
also means that it is no longer necessary to scan functions to see
whether they can be interpreted: instead, this package now just tries to
interpret it and reverts when it can't go further.

This new design has several benefits:

  * Most errors coming from the interp package are avoided, as it can
    simply skip the code it can't handle. This has long been an issue.
  * The memory model has been improved, which means some packages now
    pass all tests that previously didn't pass them.
  * Because of a better design, it is in fact a bit faster than the
    previous version.

This means the following packages now pass tests with `tinygo test`:

  * hash/adler32: previously it would hang in an infinite loop
  * math/cmplx: previously it resulted in errors

This also means that the math/big package can be imported. It would
previously fail with a "interp: branch on a non-constant" error.
@aykevl
Copy link
Member Author

aykevl commented Dec 12, 2020

Okay, I've written the missing bits (see the force push for a diff). Ready for review again.

@niaow niaow self-requested a review December 13, 2020 00:11
@deadprogram
Copy link
Member

What is the status of this PR? It would appear that all feedback has now been addressed.

@aykevl
Copy link
Member Author

aykevl commented Dec 22, 2020

Ready from my POV but maybe @niaow wants to comment.

@deadprogram
Copy link
Member

Here we go!! 🚀 🦝

@deadprogram deadprogram merged commit 30df912 into dev Dec 22, 2020
@deadprogram deadprogram deleted the interp-rewrite branch December 22, 2020 14:54
@aykevl
Copy link
Member Author

aykevl commented Dec 24, 2020

Unfortunately this appears to have broken at least support for the Circuit Playground Express. Even examples/blinky1 doesn't work anymore. It appears to be related to machine.RingBuffer (the Put and Used methods). I haven't investigated further yet.

@deadprogram
Copy link
Member

OK that seems odd, because the TinyHCI tests passed on CPE board after the merge.

However I am able right now to verify the problem on CPE myself. Also confirm it is commit 30df912 that causes the problem.

@aykevl
Copy link
Member Author

aykevl commented Dec 24, 2020

I'll take a look, but probably not before Saturday.

@deadprogram
Copy link
Member

I wonder if it is specifically related to USB-CDC code somehow?

I notice that now that this merged into dev in subsequent PRs that most of the ARM boards are failing, except for Microbit which along with RISC-V and AVR boards are still passing TinyHCI:
https://github.com/tinygo-org/tinygo/pull/1543/checks?check_run_id=1601942130

@aykevl
Copy link
Member Author

aykevl commented Dec 26, 2020

Yes, probably. I will investigate soon.

@aykevl
Copy link
Member Author

aykevl commented Dec 26, 2020

What I've discovered so far is that -opt=1 seems to mask the issue. Not sure why or how yet, don't rely on it.

@aykevl
Copy link
Member Author

aykevl commented Dec 26, 2020

I have figured out the issue, the fix is in #1547.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants