[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