Author Topic: Unleashed Pascal (async/await, parallel for, match, string interpolation & more)  (Read 54339 times)

Fibonacci

  • Hero Member
  • *****
  • Posts: 1082
  • Behold, I bring salvation - Unleashed Pascal
    • fibo.gg
Fixed. Branch: devel.
Unleashed Pascal: async/await, parallel for, match, tuples, string interpolation, inline vars, autofree, no-RTTI & tons more. Star on GitHub

creaothceann

  • Sr. Member
  • ****
  • Posts: 430
Thank you, the errors are gone. :)


What I've noticed in the assembler source is that "goto <pointer>;" generates lots of

Code: ASM  [Select][+][-]
  1.         leaq    .Lj129(%rip),%rdx
  2.         cmpq    %r13,%rdx
  3.         je      .Lj150

lines, probably comparing the pointer value to every label in the subroutine. I now see that this is mentioned in the documentation: "The jump is resolved against the labels of the current routine: the expression value is compared with each label address and control transfers to the match". Unfortunately for my particular purposes this reduces the usefulness of the computed goto, which is controlling the number and placement of dispatch points (jumps). A "goto Op[IR];" is still quite useful though, especially with the recent change.

- - -

Also, another observation: changing the code

Code: Pascal  [Select][+][-]
  1. {from} Op[$B0]:  if (e = 0) then goto BCS_n[   Cycle ] else goto BCS_e[   Cycle ];  // "20. Relative r"
  2. {to}   Op[$B0]:  if (e = 0) then goto BCS_n[u1(Cycle)] else goto BCS_e[u1(Cycle)];  // "20. Relative r"

removes a superfluous comparison in the generated code - a useful optimization for case-of in general. It's just a few bytes, but it can add up.

- - -

Also, I see that Forced Inlining is now available. Might come in handy at some point. (Quite impressive that it also works with assembler blocks / routines.)

Fibonacci

  • Hero Member
  • *****
  • Posts: 1082
  • Behold, I bring salvation - Unleashed Pascal
    • fibo.gg
Yes - I dropped the forceinline modifier and improved plain inline instead, so it now applies in far more cases. The auto-inliner is also more aggressive: if a routine can be elided, it gets elided (under certain conditions).

Still working on it - it will get more aggressive yet, meaning more of the code optimized away.
Unleashed Pascal: async/await, parallel for, match, tuples, string interpolation, inline vars, autofree, no-RTTI & tons more. Star on GitHub

Fibonacci

  • Hero Member
  • *****
  • Posts: 1082
  • Behold, I bring salvation - Unleashed Pascal
    • fibo.gg
@Akira1364:

I see you deleted your post - but I got it by mail ;) Part of the log was in there, and it does point at what could be wrong.

I pushed a fix to the installer, so grab the nightly and give it a try: https://github.com/unleashedpascal/installer/releases/tag/nightly
Unleashed Pascal: async/await, parallel for, match, tuples, string interpolation, inline vars, autofree, no-RTTI & tons more. Star on GitHub

flowCRANE

  • Hero Member
  • *****
  • Posts: 1003
There should be three modifiers for inlining to have fairly strong control over inlining:
  • inline — basic one, compiler decides if inlining is possible and makes sense.
  • forceinline — a given routine must be inlined and if not, compiler emits an error and abort compilation.
  • noinline — a given routine must not be inlined, even if possible.

Stock FPC supports inline only. There is also noinline but apparently it is not implemented, it is colored as keyword/modifier in the code editor but if used, it produce compilation error:

Code: [Select]
project1.lpr(5,19) Warning: Unknown procedure directive had to be ignored: "NOINLINE"
project1.lpr(5,19) Error: Syntax error, "BEGIN" expected but "identifier NOINLINE" found

And there is also {$OPTIMIZATION AUTOINLINE} but for a reason unknown to me, it is not supported on my machine (Windows 11, x64, FPC 3.2.2 stable release):

Code: [Select]
D:\Applications\LazarusDark\fpc\3.2.2\bin\x86_64-win64>fpc -io
REGVAR
STACKFRAME
PEEPHOLE
LOOPUNROLL
TAILREC
CSE
DFA
USERBP
ORDERFIELDS
FASTMATH
REMOVEEMPTYPROCS
CONSTPROP

Bunch of options but only one actually can be used. :o
« Last Edit: August 05, 2026, 01:31:52 pm by flowCRANE »
Lazarus 4.8 with FPC 3.2.2, Windows 11 — all 64-bit

Working solo on a top-down retro-style action/adventure game (pixel art), programming the engine from scratch, using Free Pascal and SDL3.

Thaddy

  • Hero Member
  • *****
  • Posts: 19628
  • Glad to be alive.
@flowCRANE
You missed the minus sign? Stock fpc supports that afaik. {$inline off} and {$inline-}

Btw:
Quote
FPC 3.2.2
??? It is never going to work...with unleashed...

Unleashed is not for the fainthearted...
« Last Edit: August 05, 2026, 01:29:24 pm by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

flowCRANE

  • Hero Member
  • *****
  • Posts: 1003
AFAIR the noinline modifier is added but it still sits in the trunk. I always use stable FPC, currently 3.2.2, and this modifier cannot be used as it produces compilation errors. And when i list all available optimizations for my installation via fpc.exe -io, I see no AUTOINLINE:

Code: [Select]
D:\Applications\LazarusDark\fpc\3.2.2\bin\x86_64-win64>fpc -io
REGVAR
STACKFRAME
PEEPHOLE
LOOPUNROLL
TAILREC
CSE
DFA
USERBP
ORDERFIELDS
FASTMATH
REMOVEEMPTYPROCS
CONSTPROP

So at the end of the day, if I want to determine the inlining rules in my projects, I have to manually insert basic inline modifier whenever it makes sense, as the compiler itself will not help me with this.

Btw:
Quote
FPC 3.2.2
??? It is never going to work...with unleashed...

Unleashed is not for the fainthearted...

I use stable FPC because I don't have time for dealing with trunks. I just stick with the latest stable version and update it only when the next stable version appears. If I decide to migrate my project to Unleashed Pascal, I have to be sure that the compiler is stable and supports everything I need (language features, platforms and CPU architectures). Currently I'm waiting for this to happen.
« Last Edit: August 05, 2026, 01:47:42 pm by flowCRANE »
Lazarus 4.8 with FPC 3.2.2, Windows 11 — all 64-bit

Working solo on a top-down retro-style action/adventure game (pixel art), programming the engine from scratch, using Free Pascal and SDL3.

creaothceann

  • Sr. Member
  • ****
  • Posts: 430
Speaking of inline, I get some curious results with the following code. Not sure if that's just because I use the devel branch, which includes trunk.

It also happens only in Release mode, not in Debug mode (both have inlining enabled). Might just be an issue with the optimizer.

Code: Pascal  [Select][+][-]
  1. program FileStreamTest;  {$Mode Unleashed}
  2. uses
  3.         Classes;
  4.  
  5.  
  6. procedure MyProc;
  7. begin
  8.         var Stream := TMemoryStream.Create;
  9.         try
  10.                 Stream.SaveToFile('test.bin');
  11.         finally
  12.                 Stream.Free;  // the semicolon is marked
  13.         end;
  14. end;
  15.  
  16.  
  17. begin
  18.         MyProc;
  19. end.

FileStreamTest.lpr(12,14) Note: "assembler" not yet supported inside inline procedure/function
FileStreamTest.lpr(12,14) Hint: Inlining disabled

Fibonacci

  • Hero Member
  • *****
  • Posts: 1082
  • Behold, I bring salvation - Unleashed Pascal
    • fibo.gg
There should be three modifiers for inlining to have fairly strong control over inlining:
  • inline — basic one, compiler decides if inlining is possible and makes sense.
  • forceinline — a given routine must be inlined and if not, compiler emits an error and abort compilation.
  • noinline — a given routine must not be inlined, even if possible.

I would disagree. inline means "inline this routine", not "if you could, I hereby permit you to inline this routine, but only if it is not too much trouble for you". inline = inline, that is all. No forceinline is needed - inline already says enough: this routine is to be inlined, end of story.

noinline - works.

Routines on branch devel are auto-inlined fairly aggressively. You can see it by putting a breakpoint in a body: the debugger will not stop there even though the routine has no inline on it - it was inlined.

These all work and turn it off:

Code: Text  [Select][+][-]
  1. {$optimization autoinline-}
  2. {$inline-}
  3. {$inline off}

Auto-inlining is active from -O3 up and it is more aggressive than you would expect. Side effects are not fully known yet, I am still testing. The IDE builds and runs, and my fairly large projects build, run, are faster and stable, so it looks OK.

It shows up most on routines doing a lot of calls into small bodies where someone "forgot" to write inline - hash functions, for instance. Or a wrapper whose body is a single call to another function: such a routine gets auto-inlined and the target is then called directly, instead of two calls.
Unleashed Pascal: async/await, parallel for, match, tuples, string interpolation, inline vars, autofree, no-RTTI & tons more. Star on GitHub

Fibonacci

  • Hero Member
  • *****
  • Posts: 1082
  • Behold, I bring salvation - Unleashed Pascal
    • fibo.gg
Unleashed Pascal: async/await, parallel for, match, tuples, string interpolation, inline vars, autofree, no-RTTI & tons more. Star on GitHub

creaothceann

  • Sr. Member
  • ****
  • Posts: 430
Inlining is often but not always good for speed: Modern x86 CPUs are RISC under the hood but use the traditional CISC x86 instruction set. So a core translates the program code it's supposed to execute into micro-opcodes (μops) and stores them in its μop cache. As long as the most-often used code fits into the cache, inlining is beneficial.

Inlining can also increase the number of branch points (aka dispatch points / jumps). CPUs have branch prediction that includes branch target buffers, which are limited in size (4096 or so for Haswell).


Speaking of inline (...)

Should be fixed.

Yep.

Fibonacci

  • Hero Member
  • *****
  • Posts: 1082
  • Behold, I bring salvation - Unleashed Pascal
    • fibo.gg
That is why I need testers. Everything is on branch devel - if you are able to check whether anything behaves differently than it should, I would appreciate it.
Unleashed Pascal: async/await, parallel for, match, tuples, string interpolation, inline vars, autofree, no-RTTI & tons more. Star on GitHub

chamfay

  • New member
  • *
  • Posts: 8
I have this code:
Code: Pascal  [Select][+][-]
  1.   chkApp := (Sender as TICheckBox);
  2.   if chkApp.Checked then
  3.     chkApp.Font.Style := [fsUnderline]
  4.   else
  5.     chkApp.Font.Style := [];

And I want to convert it to a statement expression but i got an error:
Code: Pascal  [Select][+][-]
  1. chkApp.Font.Style := if chkApp.Checked then [fsUnderline] else []; // not working
  2. chkApp.Font.Style := if chkApp.Checked then TFontStyles([fsUnderline]) else TFontStyles([]); // working after casting

Error:
Code: Pascal  [Select][+][-]
  1. umain.pas(323,68) Error: Incompatible type for arg no. 1: Got "{Dynamic} Array Of TFontStyle", expected "TFontStyles

The problem solved by casting, but is it possible to do things without casting?

Regards.

Fibonacci

  • Hero Member
  • *****
  • Posts: 1082
  • Behold, I bring salvation - Unleashed Pascal
    • fibo.gg
@chamfay:

Fixed - branch devel for the compiler, main for the IDE.

Had to do it on devel, because the fix touched something inline-related that is already fixed there.
Unleashed Pascal: async/await, parallel for, match, tuples, string interpolation, inline vars, autofree, no-RTTI & tons more. Star on GitHub

flowCRANE

  • Hero Member
  • *****
  • Posts: 1003
I would disagree. inline means "inline this routine", not "if you could, I hereby permit you to inline this routine, but only if it is not too much trouble for you".

But that's exactly how it has worked so far in FPC — the inline modifier was just a hint for the compiler, and the compiler decided whether to inline the routine or not (we are used to that). Have you redefined the meaning of this modifier, and in Unleashed Pascal, is it not a hint but an order to be unconditionally obeyed? If so, then a basic inline modifier is indeed sufficient, and a new one is not needed.

Quote
noinline - works.

Excellent.
Lazarus 4.8 with FPC 3.2.2, Windows 11 — all 64-bit

Working solo on a top-down retro-style action/adventure game (pixel art), programming the engine from scratch, using Free Pascal and SDL3.

 

TinyPortal © 2005-2018