[fpc-devel] Progress on pure functions
J. Gareth Moreton
gareth at moreton-family.com
Wed Dec 14 16:47:40 CET 2022
So progress report on converting "Str(constant, output)"... it's not
easy! Firstly, after the first pass, a call node's parameters can get
reordered so they can be placed into ideal registers or on the stack. I
found a workaround for that by adding a new field that records their
original right-to-left ordering. Despite the headache, I managed to
consistently change it to an assignment of a string literal to the
output variable. Success, right? Wrong! The first pass converts such
an assignment to another call node!
<calln resultdef="$void" pos="12,3" flags="nf_pass1_done" complexity="255">
<procname>$fpc_shortstr_to_shortstr(out OpenString;<const
Int64>;const ShortString);</procname>
<callparan resultdef="ShortString" pos="12,3">
<stringconstn resultdef="ShortString" pos="12,3"
flags="nf_pass1_done" complexity="1">
<stringtype>shortstring</stringtype>
<length>1</length>
<value>5</value>
</stringconstn>
</callparan>
<callparan resultdef="OpenString" pos="12,3">
<loadn resultdef="ShortString" pos="12,3"
flags="nf_pass1_done,nf_write" complexity="1">
<symbol>OUTPUT</symbol>
</loadn>
</callparan>
<callparan resultdef="Int64" pos="12,3">
<ordconstn resultdef="Int64" pos="12,3"
flags="nf_pass1_done,nf_explicit" complexity="0" rangecheck="TRUE">
<value>255</value>
</ordconstn>
</callparan>
</calln>
(The third "255" parameter seems to be some kind of encoding parameter)
Here, the original line of code was "Str(5, Output);". This is actually
pretty difficult to solve.
It might be that I have to find a way to perform purity analysis without
ever calling firstpass on the node tree, which is currently needed for
processing nested pure and inline functions... granted, I can possibly
do that selectively using "foreachnode" or "foreachnodestatic".
Kit
On 14/12/2022 12:21, J. Gareth Moreton via fpc-devel wrote:
>
> So it turns out that an "inlinen" node is created initially, but it is
> transmuted into a "calln" node by the typecheck pass almost as soon as
> it is created. I think the reason it is transmuted so soon is because
> differently-named internal procedures have to be called depending on
> the input types. I think the easiest way I can handle this is to add
> a new optional field to indicate which class of internal functions the
> node was generated from, and pass_1 can perform unique processing on
> it if certain criteria are met... and if they are not met, or the
> field is set to a value the compiler doesn't recognise, it just falls
> back to regular call-node handling.
>
> Kit
>
> On 14/12/2022 11:39, J. Gareth Moreton via fpc-devel wrote:
>>
>>
>> On 14/12/2022 10:18, Sven Barth via fpc-devel wrote:
>>>
>>> Wouldn't it make more sense to ensure that the Str() and Val()
>>> intrinsic work correctly inside "pure" functions? After all the
>>> compiler can then simply evaluate the inlinen nodes and does not
>>> have to "interpret" a ton of other code as well.
>>>
>> So I just tried a simple test with "System.Str(5, Output);" (with
>> Output defined as a string), and it produced the following nodes:
>>
>> <calln resultdef="$void" pos="12,3">
>> ...<procname>$fpc_shortstr_sint(Int64;Int64;out OpenString;<const
>> Int64>);</procname>
>> ...<callparan resultdef="Int64" pos="12,3">
>> ......<ordconstn resultdef="Int64" pos="12,3" flags="nf_explicit"
>> rangecheck="TRUE">
>> .........<value>255</value>
>> ......</ordconstn>
>> ...</callparan>
>> ...<callparan resultdef="OpenString" pos="12,23">
>> ......<loadn resultdef="ShortString" pos="12,23" flags="nf_write">
>> .........<symbol>OUTPUT</symbol>
>> ......</loadn>
>> ...</callparan>
>> ...<callparan resultdef="Int64" pos="12,3">
>> ......<ordconstn resultdef="Int64" pos="12,3" rangecheck="FALSE">
>> .........<value>-1</value>
>> ......</ordconstn>
>> ...</callparan>
>> ...<callparan resultdef="Int64" pos="12,15">
>> ......<ordconstn resultdef="Int64" pos="12,15" rangecheck="FALSE">
>> .........<value>5</value>
>> ......</ordconstn>
>> ...</callparan>
>> </calln>
>>
>> This is before the first pass, so the parser immediately replaces it
>> with a call to the internal compiler procedure.
>>
>> How should I handle this? There are a few problems I need to
>> consider. If I use a new kind of inline node that expands into a
>> regular call after the first pass, I'll still need to handle the case
>> where it is a call node because there are situations during purity
>> analysis where nested pure functions are not analysed because their
>> actual parameters haven't yet been fully calculated (usually requires
>> another found of constant propagation and inline simplification). It
>> may be that I need to add some kind of field to the TCallNode to
>> indicate which internal function it's referring to.
>>
>> I'll try to do a new merge request soon so Str and Val can be
>> simplified at the node level, as this can easily have benefits
>> outside of pure functions.
>>
>> Kit
>>
>>
>> _______________________________________________
>> fpc-devel maillist -fpc-devel at lists.freepascal.org
>> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
>
> _______________________________________________
> fpc-devel maillist -fpc-devel at lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20221214/71df5045/attachment.htm>
More information about the fpc-devel
mailing list