[fpc-devel] Deeper problem with Internal Error 200309201
J. Gareth Moreton
gareth at moreton-family.com
Sat Jul 13 18:39:46 CEST 2019
Points seem fair so far. And true, the Boolean result won't be
necessary because the error flag will be set, and this can be checked
instead.
While the idea behind "pass_1" and "simplify" are different, to me it
isn't always clear what is simplification and what is regular code pass,
and is often just left to the discretion of the programmer.
Also, though not a major point, with the code that handles a transformed
node...
p.free;
p := hp;
firstpass(p);
...there could be a huge performance gain if, instead of calling
firstpass(p), it just jumps to the top of the procedure (although after
the code that preserves the state). The code that follows is too
complicated for the compiler to see a tail recursion, but if you follow
the code logic from such a call, p has already had pass 1 completed by
the time it exits, regardless of how much it gets transformed. That's
that something that would test on the side though, but might be nice if
it helps offset the performance penalty tha comes from adding another
tree traversal.
The other saving is that a lot of the semantic checking (seems I need to
learn the difference between 'syntactic' and 'semantic') will be moved
out of "pass_1" and the routine will just transform and traverse the
nodes based on what it learnt from the "pass_semantic" stage.
Note that it won't just be the tgotonode that requires rewriting to take
advantage of the semantic stage, but virtually every node so that all
semantics are checked, but code is not generated if it's not necessary,
since it was that that caused the internal error that started this mess
in the first place!
What do others think?
Gareth aka. Kit
P.S. If I were to take on the challenge of adapting this node pass
thing, would you like a design specification to go with it so it is
easier to explain and justify what's going on and so future developers
can get to grips with the compiler's internals?
P.P.S. The nice thing about method and field names is that, if I get
them wrong, they are very easy to rename in Lazarus.
On 13/07/2019 14:44, Sven Barth via fpc-devel wrote:
> Am 13.07.2019 um 14:12 schrieb J. Gareth Moreton:
>> I would like some discussion on this with the administrative team
>> because this does require some careful design if we're going to do
>> this properly. Building on Florian's suggestion, I would like to
>> propose splitting "pass_1" into "pass_syntax" and a pass that
>> transforms the nodes (I would name it "pass_transform", but this
>> doesn't sound 'important' enough, given it is effectively compiling
>> the nodes). "pass_syntax" would be a public method declared in tnode
>> as the following "function pass_syntax: Boolean; virtual;" - if it
>> returns True, then everything was fine; if not, it returns False and
>> this can be used to set the error flag. By being defined this way,
>> this is no ability for the node to transform itself, but it can set
>> private fields based on the syntax it finds (by setting private
>> fields, the "first pass" won't have to repeat some of the work needed
>> to determine how to transform the nodes).
>
> "pass_syntax" is not a good name, because it does *not* do syntax
> checking (that was done by the parser). Instead it checks the
> semantic, so "pass_semantic" would be a more correct name.
>
> Also I don't think a Boolean result is needed. Take a look at
> tgotonode.pass_1 which is after all the one which would need to be
> moved to pass_semantic: it uses CGMessage*() to write its messages (as
> all nodes do) which in turn sets the codegenerror flag if it wasn't
> set already. So after a call to a node's pass_semantic method all that
> needs to be checked is codegenerror to decide how to proceed further.
> Thus the semantic pass could simply be "procedure
> pass_semantic;virtual;".
>
>> On the surface, the first implementation suggestion feels like the
>> cleaner option, but I don't know how much of a penalty it will add to
>> the compiler. Personally I would like to attempt a design for the
>> second implementation to keep the number of passes down to a minimum
>> and the compiler reasonably fast (also my motivation behind the
>> x86_64 peephole optimizer overhaul). But that's just my opinion.
>
> In my opinion a clean, easily maintainable solution is preferrable.
>
>> On an additional note, I do wonder if it's possible to merge "pass_1"
>> and "simplify", since they are treated pretty much identically in the
>> "firstpass" routine - if either of them return something other than
>> nil, it is considered to be a node transformation, running this block
>> of code (there are two copies, one for each call):
>>
>> p.free;
>> p := hp;
>> firstpass(p);
>>
>> (hp contains the return value of whatever method was just called)
>> This may be impractical because "simplify" is called elsewhere for
>> some nodes.
>>
>
> I don't think combining the two passes is necessary. The ideas behind
> the two passes are after all different.
>
> Regards,
> Sven
> _______________________________________________
> fpc-devel maillist - fpc-devel at lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
>
>
---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
More information about the fpc-devel
mailing list