Search code examples
delphidocumentationintrinsics

Undocumented intrinsic routines


Delphi has this list: Delphi Intrinsic Routines
But that list is incomplete.

What are the 7 undocumented intrinsic functions, since when and what is their purpose?


Solution

  • I know of the following undocumented intrinsic functions.

    Delphi 2007: here and Hallvard's blog:

    Default

    function Default(T: Typeidentifier): value of T;     
    

    Returns the zero representation of type identifier T.

    The following intrinsics introduced in XE7 are explained in the XE7 beta blog and by Stefan Glienke

    IsManagedType

    function IsManagedType(T: TypeIdentifier): Boolean;   
    

    True if T is a interface, string or dynamic array, or a record containing such. A class containing a managed type will return false.

    In XE6 and older you have to use System.Rtti.IsManaged(TypeInfo(T)).

    HasWeakRef

    function HasWeakRef(T: TypeIdentifier): Boolean;    
    

    True if T has been annotated as [weak]. The compiler keeps a list of [weak] references. You cannot use move and other tricks with these types, because that will prevent the weak-list from getting updated.

    In XE6 and older you have to use System.TypInfo.HasWeakRef(TypeInfo(T)).

    GetTypeKind

    function GetTypeKind(T: TypeIdentifier): TTypeKind;   
    

    Does the same thing as PTypeInfo(System.TypeInfo(T))^.Kind;, however because it is a compiler intrinsic the function is resolved at compiletime and conditional code that evaluates to false will be stripped by the compiler.

    IsConstValue

    function IsConstValue(const Value): Boolean;          
    

    True if Value is a constant, false if not.
    This helps the compiler to eliminate dead code because the function is evaluated at compile time.
    This is only useful in inline functions, where it allows for shorter generated code.

    TypeInfo

    function TypeInfo(T: typeindentifier): PTypeInfo;
    

    This function is not undocumented as such, but what is undocumented is that it is an intrinsic function since XE7.
    That means that the snippet if TypeInfo(T) = TypeInfo(byte) then ... does not generate any code if T is not a byte and the test will be resolved at compiletime.
    However the compile-time resolution only works inside generic routines and only when doing a if (TypeInfo(T) = TypeInfo(sometype) test.
    The test if TypeInfo(byte) = TypeInfo(smallint) then does not get eliminated even though it always evaluates to false.
    Nor does other use of TypeInfo(T).

    ReturnAddress

    The following are used with the raise exception at returnaddress construct.

    function ReturnAddress(Expression): pointer;          //Delphi ?
    function AddressOfReturnAddress(Expression): pointer; //Delphi ?
    

    And as far as I know you can't call them directly from user code.

    Example of IsConstValue

    type
       TFlavor = (Tasty, Nasty);
       TIntegerHelper = record helper for integer
         function GetSomething(Flavor: TFlavor): TPoint; inline;
       private
         function GetTastyPoint: TPoint;
         function GetNastyPoint: TPoint;
       end;
     
     function TIntegerHelper.GetSomething(Flavor: TFlavor): TPoint;
     begin
       if IsConstValue(Flavor) then begin
         if Flavor = Tasty then Result:= Self.GetTastyPoint
         else Result:= Self.GetNastyPoint;
       end else begin
         Assert(1=0, 'This function can only be called with constant parameters');
       end;
     end; 
    
    procedure Test;
    var
      pt: TPoint;
    begin
      pt:= 100000.GetSomething(Tasty); 
    This call will get translated to GetTastyPoint and the if/then sequence will be eliminated by the linker.