Jump to content

David Heffernan

Members
  • Content Count

    3710
  • Joined

  • Last visited

  • Days Won

    185

Posts posted by David Heffernan


  1. Automating Word for document preparation is known to be somewhat brittle. More robust is to generate Word documents directly without invoking Word at all. There are good libraries for doing that. That's the point.

     

    If you are going to rely on Word for this then it pays to be very careful about the version that you use. Switching to Office 365 is simply asking for trouble. 


  2. You can't have read the documentation. Because you aren't calling ShutdownBlockReasonCreate. 

     

    I know that you want to solve this quickly. But that expectation is unrealistic. It will take you time to wade through this, try it out, read and understand example code, etc.

     

    For sure one of us could write you some examples but unless you understand it will you really be able to integrate it into your code? Just because you don't understand this now does not mean that you can't learn it. It just requires self belief and persistence. 


  3. It's astonishing that Emba's InterlockedCompareExchange128 returns a BOOL, i.e. a 4 byte boolean, LongBool. They are presumably trying to copy this one from MS https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-interlockedcompareexchange128 which is actually implemented as an intrinsic.

     

    But look at the MS function's return type.  Yup, it's BOOLEAN which is a single byte.  The Emba version should use Boolean rather than Bool as the return type.  It's a screw-up from top to bottom.

     

    Anyone might think that they just write this stuff and don't test it ......


  4. 6 minutes ago, Anders Melander said:

    I always start with registers and then refactor the code to use symbols to make it readable. I guess I should keep the register names in a comment.

    To me it is much cleaner to comment at the top of the routine which register each parameter travels in, and then stick to registers. That allows you to see teg register usage directly rather than having an extra level of indirection. 


  5. 7 minutes ago, Anders Melander said:

    Beware that this does not align memory allocated from the heap. For that you can use the following:

    
    {$ifdef CPUX64}
      SetMinimumBlockAlignment(mba16Byte);
    {$else CPUX64}
      SetMinimumBlockAlignment(mba8Byte);
    {$endif CPUX64}

     

    This works for me:

    
    function InterlockedCompareExchange128(Destination: Pointer; ExchangeHigh, ExchangeLow: Int64; ComparandResult: Pointer): Bool; stdcall;
    asm
          .NOFRAME
          .PUSHNV R10
          .PUSHNV RAX
          .PUSHNV RBX
          .PUSHNV RCX
          MOV   R10,Destination
          MOV   RBX,ExchangeLow
          MOV   RCX,ExchangeHigh
          MOV   RDX,[ComparandResult+8]
          MOV   RAX,[ComparandResult]
     LOCK CMPXCHG16B [R10]
          SETZ  AL
    end;

    The PUSHNV RBX is translated to push RBX + pop RBX. The others do nothing.

    You are restoring volatile registers there. That's wrong. Most egregious is where you restore rax which has the return value. 

     

    Ah, i read the bit where you say "the others do nothing". I guess the compiler knows they are volatile / used for param/return passing. I'd remove them all the same. 

     

    You really must stop using parameter names in asm because it obfuscates the fact they they live in registers, and which ones. 


  6. 10 minutes ago, Kas Ob. said:

    It merely does add push REG at the begining and pop REG at the end, for rbx it is saved already in code and doesn't need this.

    Wrong. It also lets the compiler out the meta data, the unwind data, needed to restore the register in case of an exception. Read Allen's article. 


  7. 33 minutes ago, Vandrovnik said:

    I believe Anders is right.

    Class reference is just a pointer - its size is known. When you use this class as a member of another class (fChild: tChild, where tChild is a class), you cannot reference its members in properties (property x: integer read fChild.x). If fChild is a record (fChild: tChild, where tChild is a record), you can reference its members in properties, like in Anders' example (property x: integer read fChild.x).

    Not being able to do that one thing would hardly invalidate the entire enterprise. We'd still be able to use the type as procedure argument which is the main thing we are striving for. 

     

    But the whole argument is predicted on this single pass. It's no big deal to pass over each type section twice to process forward declarations. Won't make a blind bit of difference to performance. 

     

    Bottom line is that it is perfectly possible to do this if Emba wanted to. 


  8. 55 minutes ago, Anders Melander said:

    It isn't. The type and offset of the members needs to be known too:

    
    type
      TMyRecord = record
        Foo: integer;
        Bar: string;
      end;
    
      TMyClass = class
      private
        FFooBar: TMyRecord;
      public
        property Foo: integer read FFooBar.Foo;
        property Bar: string read FFooBar.Bar;
      end;

     

    If what you say were true, then class forward references would not exist.

×