-
Notifications
You must be signed in to change notification settings - Fork 263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize compilation of functional-looking assignment RHSs #5589
Optimize compilation of functional-looking assignment RHSs #5589
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me. I'm happy to see that it's a relatively simple change!
The first couple of test failures look like they're just because some files need to be regenerated, but there are a few integration test failures that look real. |
# Conflicts: # Source/DafnyCore/Backends/SinglePassCodeGenerator/SinglePassCodeGenerator.cs
# Conflicts: # Source/DafnyCore/Backends/SinglePassCodeGenerator/SinglePassCodeGenerator.Statement.cs # Source/DafnyCore/GeneratedFromDafny/DCOMP.cs # Source/DafnyCore/GeneratedFromDafny/RAST.cs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks good. There's an #if
block that I wasn't sure you intended to leave in or not, but I'll let you decide whether or not to remove it.
Contract.Assert(n == inTmps.Count); | ||
// finally, the jump back to the head of the function | ||
EmitJumpToTailCallStart(wr); | ||
Contract.Assert(!inLetExprBody); // a tail call had better not sit inside a target-code lambda |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice consolidation!
@@ -2749,7 +2750,10 @@ protected class NullClassWriter : IClassWriter { | |||
Coverage.Instrument(f.Body.tok, $"entry to function {f.FullName}", w); | |||
Contract.Assert(enclosingFunction == null); | |||
enclosingFunction = f; | |||
CompileReturnBody(f.Body, f.OriginalResultTypeWithRenamings(), w, accVar); | |||
#if NEW_ATTEMPT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this relevant beyond debugging?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops. That was leftover from straightening out a merge. Thanks for catching that.
@@ -3606,6 +3606,10 @@ protected class ClassWriter : IClassWriter { | |||
message = "unexpected control point"; | |||
} | |||
|
|||
// Wrapping an "if (true) { ... }" around the "break" statement is a way to tell the Java compiler not to give | |||
// errors for any (unreachable) code that may follow. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:-P
Description
Previously, the single-pass compiler would use
TrExprOpt
to turn nested expressions into target-language statements, ending in areturn
. This PR generalizes that mechanism so that the ending action is parameterized. In particular, the PR now appliesTrExprOpt
to single-LHS assignment statements. This allows the RHS of such assignment statements to be deeply nested expressions, without running into, for example, the limits ofjavac
to deal with nested lambda expressions.Fixes #3868
Implementation
This PR required a change to the target-code strategy of
match
constructs. Previously,case
s turned into a sequence ofif
statements (note, not a cascadingif
). If one of thoseif
statements determined that thecase
applied, then a boolean variable,unmatched
, was set tofalse
. Each of theseif
statements was thus also guarded by the conditionunmatched
.This previous strategy caused a problem when the body of the cases is an assignment. Since every assignment was guarded by an
if
, target languages with definite-assignment rules weren't able to determine that the variable was always assigned.A more straightforward strategy is to jump (using a
break
orgoto
) to the end of the target code for thematch
, rather than setting theunmatched
variable. This lets the target language easily see that the variable has been assigned on all paths. It also means that theunmatched
variable and its tests are not needed at all. Furthermore, the lastcase
does not need an enclosingif
structure at all, since if the priorcase
s don't apply, then the last one must apply.This PR improves the strategy to the one with jumps.
Work along the way
fix: Use Downcast for let RHS and for function body
Fixes #5597
By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.