Feature: Lightweight Generics #1
Replies: 3 comments 1 reply
-
Application of Indexed Labels to Lightweight GenericsI just discovered the Indexed Labels in FPC Unleashed. In the Witness-Based Generics proposal above, indexed labels could be a dream for the compiler. If you have a shared implementation of a generic list, the compiler might need to handle "Special Cases" for different power-of-two sizes. Instead of bloat, it uses one shared function with an indexed label: procedure SharedGenericAdd(const Witness: PWitnessTable);
label
HandleSize[1, 2, 4, 8];
begin
{ The compiler can jump to the optimal MOV instruction based on size }
goto HandleSize[Witness.TypeSize];
HandleSize[4]:
{ Perform 32-bit optimized copy }
exit;
HandleSize[8]:
{ Perform 64-bit optimized copy }
end; |
Beta Was this translation helpful? Give feedback.
-
|
@Eudox67 - you proposed this and you're the one it matters most to, so you're the best person to test it. The current implementation is on the feat/lightweight-generics branch - could you build it and run it through your use cases? It'd be great to hear whether it matches what you had in mind. |
Beta Was this translation helpful? Give feedback.
-
|
My own implementation suffers from runtime parameters, so i like your goal of keeping away from that. I was able to compile several tests. I made a conformance.pas test and all conformance tests passed with the lightgenerics compiler:
It was also able to compile a functionals.pas unit filled with HOF (Map, Filter, Reduce, Partition, Drop, etc.) that uses generics heavily, so it will be nice to have this as part of the compiler (I only installed it as a branch and compiled with ppcx64 with no optimizations). I guess there won't be any COMDAT deduplication since you don't want to change the object writers? I am happy to stop working on my own implementation since I just want to use it, not develop it. 🙂 Thank you for adding this!! |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
DISCUSSION/PROPOSAL TO FIX GENERICS
The current Generics implementation in Free Pascal (FPC) utilizes a "Template Expansion" model. While providing high performance for specific types, it results in substantial binary bloat and prolonged compilation times due to code duplication. I am asking for the consideration of a Witness-Based Lightweight Generics (WLG) system. By utilizing implicit dictionary passing (Witness Tables), the compiler could generate a single binary implementation for generic procedures, using
specializeonly as a metadata-binding instruction rather than a code-generation trigger.1. The Technical Philosophy
specialize: The keyword is retained to maintain one-pass compilation efficiency and explicit type safety, but its backend behavior is transformed from "Copy-Paste" to "Link-and-Bind."2. The Architecture
2.1 The Witness Table (Internal)
The compiler implicitly defines a structure for every
Tinvolved in a specialization.2.2 Polymorphic Implementation
The body of a generic function is compiled into a "Railed" version. Instead of knowing type
T, the machine code utilizes thePWitnessTableto manipulate memory.3. An Example
3.1 Generic Definition
The definition remains standard Pascal, ensuring no declarations exist within the function parameters.
3.2 Specialization Site
The
specializekeyword now acts as a linker directive.Compiler Action:
Integer.Byte.IntList.AddandByteList.Addto the same memory address of the shared implementation.4. Formal Considerations and Rules
Why: Generics rely on Type Identity. If the compiler allows inline type declarations in the parameter list of a generic specialization, it becomes nearly impossible to verify if two specializations are identical.
Why: In Pascal, a
constis often treated as a "true" constant (substituted at compile time). If a constant within a generic is allowed to be defined by a variable or a non-static result, it becomes a "read-only variable."var Tis unknown at compile time. Allowing for inline variables likevar x: T := ...halfway through a block, forces the compiler to perform "dynamic stack adjustment" or "deferred stack allocation." This does not make compilation impossible, but adds complexity. This is just a note for consideration.5. Verification (FPCUnit)
To prove effectiveness, the following test suite should verify that different specializations maintain data integrity while sharing logic.
6. Recovery of Legacy Performance
To ensure no performance regression for critical paths (e.g., high-performance math), I propose an attribute to opt-out of sharing:
7. Summary of Benefits
specialize.specializesyntax, providing a bridge for existing code bases while fixing the underlying "bloat" bug.Beta Was this translation helpful? Give feedback.
All reactions