Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2020-08

Procedural generics question

10 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Unknown author

Inside a generic procedure (no objects used just a procedure) is there a way to check which type the code is being used for such as:

generic procedure Add<integer, string>();
begin
   if type = integer then...
   if type = string then...
   begin
     // specialized code for that type only
   end
end;

I remember something like this in RTTI though but can't find it in your docs yet for generics.

The current way might be to code up separate procedures for each type, but that's kind of defeating the purpose of generics since that would simply be an overloaded regular function.

Reply by email

Benito van der Zander
to leledumbo

Hi,

that is generating rather odd code (r40721)

project1.lpr:9                            begin 0000000000401090 55                       push   %rbp 0000000000401091 4889e5                   mov    %rsp,%rbp 0000000000401094 488d6424f0               lea -0x10(%rsp),%rsp 0000000000401099 48895df8                 mov    %rbx,-0x8(%rbp) project1.lpr:10                           if TypeInfo(T) = TypeInfo(Integer) then WriteLn('an integer');
000000000040109D 488d1584af0700           lea 0x7af84(%rip),%rdx        # 0x47c028 <RTTI_$SYSTEM_$$_LONGINT>
00000000004010A4 488d057daf0700           lea 0x7af7d(%rip),%rax        # 0x47c028 <RTTI_$SYSTEM_$$_LONGINT>
00000000004010AB 4839c2                   cmp    %rax,%rdx 00000000004010AE 752b                     jne    0x4010db <ADD$1$CRC713F463B+75>
00000000004010B0 e8cbcf0100               callq  0x41e080 <fpc_get_output> 00000000004010B5 4889c3                   mov    %rax,%rbx 00000000004010B8 488d15412f0600           lea 0x62f41(%rip),%rdx        # 0x464000 <_$PROJECT1$_Ld1>
00000000004010BF 4889de                   mov    %rbx,%rsi 00000000004010C2 31ff                     xor    %edi,%edi 00000000004010C4 e867d30100               callq  0x41e430 <fpc_write_text_shortstr>
00000000004010C9 e8d2700100               callq  0x4181a0 <fpc_iocheck> 00000000004010CE 4889df                   mov    %rbx,%rdi 00000000004010D1 e85ad20100               callq  0x41e330 <fpc_writeln_end> 00000000004010D6 e8c5700100               callq  0x4181a0 <fpc_iocheck> project1.lpr:11                           if TypeInfo(T) = TypeInfo(String) then WriteLn('a string');
00000000004010DB 488d0546af0700           lea 0x7af46(%rip),%rax        # 0x47c028 <RTTI_$SYSTEM_$$_LONGINT>
00000000004010E2 488d1537b20700           lea 0x7b237(%rip),%rdx        # 0x47c320 <RTTI_$SYSTEM_$$_SHORTSTRING>
00000000004010E9 4839d0                   cmp    %rdx,%rax 00000000004010EC 752b                     jne    0x401119 <ADD$1$CRC713F463B+137>
00000000004010EE e88dcf0100               callq  0x41e080 <fpc_get_output> 00000000004010F3 4889c3                   mov    %rax,%rbx 00000000004010F6 488d15132f0600           lea 0x62f13(%rip),%rdx        # 0x464010 <_$PROJECT1$_Ld2>
00000000004010FD 4889de                   mov    %rbx,%rsi 0000000000401100 31ff                     xor    %edi,%edi 0000000000401102 e829d30100               callq  0x41e430 <fpc_write_text_shortstr>
0000000000401107 e894700100               callq  0x4181a0 <fpc_iocheck> 000000000040110C 4889df                   mov    %rbx,%rdi 000000000040110F e81cd20100               callq  0x41e330 <fpc_writeln_end> 0000000000401114 e887700100               callq  0x4181a0 <fpc_iocheck> project1.lpr:12                           end;

The compiler should know everything about TypeInfo(T) and optimize it away where possible

Cheers,
Benito

leledumbo wrote 26 lines
> I remember something like this in RTTI though but can't find it in your docs yet for generics. {$mode objfpc} uses typinfo; generic procedure Add<T>; begin if TypeInfo(T) = TypeInfo(Integer) then WriteLn('an integer'); if TypeInfo(T) = TypeInfo(String) then WriteLn('a string'); end; begin specialize Add<Integer>; specialize Add<String>; end. -- Sent from: http://free-pascal-general.1045716.n5.nabble.com/ _______________________________________________ fpc-pascal maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Nico Neumann
to Benito van der Zander

The TypeInfo function checks the code during run-time thus the generated code is 'bloated'. Better use the compiler intrinsic GetTypeKind.

{$mode objfpc}
uses
   typinfo;
generic procedure Add<T>;
begin
    if GetTypeKind(T) = tkInteger then WriteLn('an integer');
    if GetTypeKind(T) = tkString then WriteLn('a string');
end;
begin
   specialize Add<Integer>;
   specialize Add<String>;
end.

for 'specialize Add<Integer>;' the following code is generated:

# [46] if GetTypeKind(T) = tkInteger then WriteLn('an integer'); call fpc_get_output
movq %rax,%rbx
leaq _$VT$_Ld1(%rip),%r8
movq %rbx,%rdx
movl $0,%ecx
call fpc_write_text_shortstr
call fpc_iocheck
movq %rbx,%rcx
call fpc_writeln_end
call fpc_iocheck
# [48] end;

Am Di., 25. Aug. 2020 um 23:54 Uhr schrieb Benito van der Zander via fpc-pascal :

Show quoted text 91 lines
Hi, that is generating rather odd code (r40721) project1.lpr:9 begin 0000000000401090 55 push %rbp 0000000000401091 4889e5 mov %rsp,%rbp 0000000000401094 488d6424f0 lea -0x10(%rsp),%rsp 0000000000401099 48895df8 mov %rbx,-0x8(%rbp) project1.lpr:10 if TypeInfo(T) = TypeInfo(Integer) then WriteLn('an integer'); 000000000040109D 488d1584af0700 lea 0x7af84(%rip),%rdx # 0x47c028 <RTTI_$SYSTEM_$$_LONGINT> 00000000004010A4 488d057daf0700 lea 0x7af7d(%rip),%rax # 0x47c028 <RTTI_$SYSTEM_$$_LONGINT> 00000000004010AB 4839c2 cmp %rax,%rdx 00000000004010AE 752b jne 0x4010db <ADD$1$CRC713F463B+75> 00000000004010B0 e8cbcf0100 callq 0x41e080 <fpc_get_output> 00000000004010B5 4889c3 mov %rax,%rbx 00000000004010B8 488d15412f0600 lea 0x62f41(%rip),%rdx # 0x464000 <_$PROJECT1$_Ld1> 00000000004010BF 4889de mov %rbx,%rsi 00000000004010C2 31ff xor %edi,%edi 00000000004010C4 e867d30100 callq 0x41e430 <fpc_write_text_shortstr> 00000000004010C9 e8d2700100 callq 0x4181a0 <fpc_iocheck> 00000000004010CE 4889df mov %rbx,%rdi 00000000004010D1 e85ad20100 callq 0x41e330 <fpc_writeln_end> 00000000004010D6 e8c5700100 callq 0x4181a0 <fpc_iocheck> project1.lpr:11 if TypeInfo(T) = TypeInfo(String) then WriteLn('a string'); 00000000004010DB 488d0546af0700 lea 0x7af46(%rip),%rax # 0x47c028 <RTTI_$SYSTEM_$$_LONGINT> 00000000004010E2 488d1537b20700 lea 0x7b237(%rip),%rdx # 0x47c320 <RTTI_$SYSTEM_$$_SHORTSTRING> 00000000004010E9 4839d0 cmp %rdx,%rax 00000000004010EC 752b jne 0x401119 <ADD$1$CRC713F463B+137> 00000000004010EE e88dcf0100 callq 0x41e080 <fpc_get_output> 00000000004010F3 4889c3 mov %rax,%rbx 00000000004010F6 488d15132f0600 lea 0x62f13(%rip),%rdx # 0x464010 <_$PROJECT1$_Ld2> 00000000004010FD 4889de mov %rbx,%rsi 0000000000401100 31ff xor %edi,%edi 0000000000401102 e829d30100 callq 0x41e430 <fpc_write_text_shortstr> 0000000000401107 e894700100 callq 0x4181a0 <fpc_iocheck> 000000000040110C 4889df mov %rbx,%rdi 000000000040110F e81cd20100 callq 0x41e330 <fpc_writeln_end> 0000000000401114 e887700100 callq 0x4181a0 <fpc_iocheck> project1.lpr:12 end; The compiler should know everything about TypeInfo(T) and optimize it away where possible Cheers, Benito On 25.08.20 04:32, leledumbo via fpc-pascal wrote: I remember something like this in RTTI though but can't find it in your docs yet for generics. {$mode objfpc} uses typinfo; generic procedure Add<T>; begin if TypeInfo(T) = TypeInfo(Integer) then WriteLn('an integer'); if TypeInfo(T) = TypeInfo(String) then WriteLn('a string'); end; begin specialize Add<Integer>; specialize Add<String>; end. -- Sent from: http://free-pascal-general.1045716.n5.nabble.com/ _______________________________________________ fpc-pascal maillist - _______________________________________________ fpc-pascal maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Ryan Joseph
to Nico Neumann
Show quoted text 7 lines
On Aug 26, 2020, at 5:44 PM, Nico Neumann via fpc-pascal wrote: generic procedure Add<T>; begin if GetTypeKind(T) = tkInteger then WriteLn('an integer'); if GetTypeKind(T) = tkString then WriteLn('a string'); end;

Question for the compiler team why doesn't the "is" operator work for types? We should be able to do:

if T is integer then
  ;

and get something which is well optimized.

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph
Ryan Joseph wrote 14 lines
> On Aug 26, 2020, at 5:44 PM, Nico Neumann via fpc-pascal wrote: > > generic procedure Add<T>; > begin > if GetTypeKind(T) = tkInteger then WriteLn('an integer'); > if GetTypeKind(T) = tkString then WriteLn('a string'); > end; Question for the compiler team why doesn't the "is" operator work for types? We should be able to do: if T is integer then ; and get something which is well optimized.

Because there was simply no need for this.

Regards,
Sven

Reply by email

Sven Barth
to Benito van der Zander: that is generating rather odd code (r40721) project1.lpr:9               …
Benito van der Zander wrote 57 lines
Hi, that is generating rather odd code (r40721) project1.lpr:9                            begin 0000000000401090 55                       push   %rbp 0000000000401091 4889e5                   mov    %rsp,%rbp 0000000000401094 488d6424f0               lea -0x10(%rsp),%rsp 0000000000401099 48895df8                 mov %rbx,-0x8(%rbp) project1.lpr:10                           if TypeInfo(T) = TypeInfo(Integer) then WriteLn('an integer'); 000000000040109D 488d1584af0700           lea 0x7af84(%rip),%rdx        # 0x47c028 <RTTI_$SYSTEM_$$_LONGINT> 00000000004010A4 488d057daf0700           lea 0x7af7d(%rip),%rax        # 0x47c028 <RTTI_$SYSTEM_$$_LONGINT> 00000000004010AB 4839c2                   cmp    %rax,%rdx 00000000004010AE 752b                     jne    0x4010db <ADD$1$CRC713F463B+75> 00000000004010B0 e8cbcf0100               callq  0x41e080 <fpc_get_output> 00000000004010B5 4889c3                   mov    %rax,%rbx 00000000004010B8 488d15412f0600           lea 0x62f41(%rip),%rdx        # 0x464000 <_$PROJECT1$_Ld1> 00000000004010BF 4889de                   mov    %rbx,%rsi 00000000004010C2 31ff                     xor    %edi,%edi 00000000004010C4 e867d30100               callq  0x41e430 <fpc_write_text_shortstr> 00000000004010C9 e8d2700100               callq  0x4181a0 <fpc_iocheck> 00000000004010CE 4889df                   mov    %rbx,%rdi 00000000004010D1 e85ad20100               callq  0x41e330 <fpc_writeln_end> 00000000004010D6 e8c5700100               callq  0x4181a0 <fpc_iocheck> project1.lpr:11                           if TypeInfo(T) = TypeInfo(String) then WriteLn('a string'); 00000000004010DB 488d0546af0700           lea 0x7af46(%rip),%rax        # 0x47c028 <RTTI_$SYSTEM_$$_LONGINT> 00000000004010E2 488d1537b20700           lea 0x7b237(%rip),%rdx        # 0x47c320 <RTTI_$SYSTEM_$$_SHORTSTRING> 00000000004010E9 4839d0                   cmp    %rdx,%rax 00000000004010EC 752b                     jne    0x401119 <ADD$1$CRC713F463B+137> 00000000004010EE e88dcf0100               callq  0x41e080 <fpc_get_output> 00000000004010F3 4889c3                   mov    %rax,%rbx 00000000004010F6 488d15132f0600           lea 0x62f13(%rip),%rdx        # 0x464010 <_$PROJECT1$_Ld2> 00000000004010FD 4889de                   mov    %rbx,%rsi 0000000000401100 31ff                     xor    %edi,%edi 0000000000401102 e829d30100               callq  0x41e430 <fpc_write_text_shortstr> 0000000000401107 e894700100               callq  0x4181a0 <fpc_iocheck> 000000000040110C 4889df                   mov    %rbx,%rdi 000000000040110F e81cd20100               callq  0x41e330 <fpc_writeln_end> 0000000000401114 e887700100               callq  0x4181a0 <fpc_iocheck> project1.lpr:12                           end; The compiler should know everything about TypeInfo(T) and optimize it away where possible

For the compiler these are simply ordinary pointers, it does not (yet) have any knowledge about "constant" pointers. Though there is a bug report about that exact problem somewhere...

Regards,
Sven

Reply by email

Unknown author
to Nico Neumann: The TypeInfo function checks the code during run-time thus the generated code is…
Nico Neumann wrote 15 lines
The TypeInfo function checks the code during run-time thus the generated code is 'bloated'. Better use the compiler intrinsic GetTypeKind. {$mode objfpc} uses typinfo; generic procedure Add<T>; begin if GetTypeKind(T) = tkInteger then WriteLn('an integer'); if GetTypeKind(T) = tkString then WriteLn('a string'); end;

That's great but if the type is something like a TRec (custom record) or a class, it won't be possible to check the types AFAICT because those are special built in type kind values for common basic types?

Reply by email

Michael Van Canneyt
to Unknown author
Lars wrote 20 lines
On 2020-08-26 05:44, Nico Neumann via fpc-pascal wrote: > The TypeInfo function checks the code during run-time thus the > generated code is 'bloated'. Better use the compiler intrinsic > GetTypeKind. > > {$mode objfpc} > > uses > typinfo; > > generic procedure Add<T>; > begin > if GetTypeKind(T) = tkInteger then WriteLn('an integer'); > if GetTypeKind(T) = tkString then WriteLn('a string'); > end; > That's great but if the type is something like a TRec (custom record) or a class, it won't be possible to check the types AFAICT because those are special built in type kind values for common basic types?

You will then get tkRecord or tkClass or tkObject. Of course this does not tell you which record/class/object.

Michael.

Reply by email