#1 2010-08-10 07:24:22

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,620
Website

Writing Delphi code for 64 bits compiler

There will be an upcoming 64 bits Delphi compiler. Embarcadero promised it.

Florian Klämpfl (the FPC's architect) showed a first "Hello world" program for Win64 in March 2006.
This was remarkable since GCC and the binutils didn't even support this target at this time.
In fact, FPC used its Internal linker on Win32 and Win64 platforms, just like Delphi does.


Here are some points on how you could make your code ready to compile under FPC 64 bits, therefore (I hope) under future Delphi 64 bits compiler.

The good news

Under FPC, all common types (like integer, cardinal, etc...) have the same size. They are all 32 bits.
So most of you code don't need to be rewritten.


If you have some assembler

But if you have some asm part in your code, you'll have to write it in pascal.
Use the PUREPASCAL conditional, and always provide a pure pascal version of any asm function. It's therefore a good practice to always code in pascal, then add an optimized asm version only if it's necessary.
Here is one example extracted from our framework:

function IdemPropName(const P1,P2: shortstring): boolean; overload;
{$ifdef PUREPASCAL}
var i: integer;
begin
  result := false;
  if P1[0]<>P2[0] then
    exit;
  for i := 1 to ord(P1[0]) do
    if (ord(P1[i]) xor ord(P2[i])) and $DF<>0 then
      exit;
  result := true;
end;
{$else}
asm // eax=P1 edx=P2
    mov cl,[eax]
    cmp cl,[edx]
    jne @z      // length differs
    or cl,cl
@1: lea eax,[eax+1]
    lea edx,[edx+1]
    jz @ok
    mov ch,[eax]
    xor ch,[edx]
    and ch,$DF   // case insensitive compare
    jne @z
    dec cl
    jmp @1
@ok:mov al,1
    ret
@z: xor eax,eax
end;
{$endif}

The bad news: Pointers size changed

If you use pointer arithmetic, you should use PtrInt instead of integer to typecast pointers.
See http://wiki.freepascal.org/Multiplatfor … 2.2F64_bit

It's perfectly cross-compiler. We defined these types for working with Delphi and FPC on the same code:

{$ifdef FPC}
  {$ifdef CPU64}
    {$define PUREPASCAL}
  {$endif}
{$else}
type
  /// a CPU-dependent unsigned integer type cast of a pointer / register
  // - used for 64 bits compatibility, native under Free Pascal Compiler
  PtrUInt = cardinal;
  /// a CPU-dependent unsigned integer type cast of a pointer of pointer
  // - used for 64 bits compatibility, native under Free Pascal Compiler
  PPtrUInt = ^PtrUInt;
 
  /// a CPU-dependent signed integer type cast of a pointer / register
  // - used for 64 bits compatibility, native under Free Pascal Compiler
  PtrInt = integer;
  /// a CPU-dependent signed integer type cast of a pointer of pointer
  // - used for 64 bits compatibility, native under Free Pascal Compiler
  PPtrInt = ^PtrInt;
 
  /// unsigned Int64 doesn't exist under Delphi, but is defined in FPC
  QWord = Int64;
{$endif}

So it's always a good practice to use these PtrInt instead of integer in any pointer arithmetic, just as you should use AnsiString/AnsiChar/PAnsiChar for any ansi content, even on Delphi 7.

And if you use loop variables like for i := 0 to Lines.Count-1, you should better use var i: PtrInt instead of i: integer

Note that there is a CPU64 define set if you're compiling for a 64 bits CPU.
For example, since PtrInt = Int64 in fact, you can test {$ifdef CPU64} to avoid writing a Int64 specific function, if a PtrInt one has already been defined.

We use all these tips in our SQLite3 Client-Server framework.


Hoping and praying

I just hope that EMB will follow the same rules for their future 64 bits compiler.

They will surely release their compiler 5 years later than FPC's... I hope they will follow the FPC way, just as Intel did about 64 bits instructions, against AMD.

Offline

#2 2010-08-11 19:27:17

Odysseos
Member
Registered: 2010-08-11
Posts: 1

Re: Writing Delphi code for 64 bits compiler

Delphi - at least, Delphi 2007 - has unsigned 64-bit integer type - UInt64.

Offline

#3 2010-08-11 21:43:28

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,620
Website

Re: Writing Delphi code for 64 bits compiler

You're right: UInt64 is defined in Delphi 2007. I didn't notice that because it's used only in System.pas.

But it didn't exist in Delphi 7.

Thanks for pointing this.

Offline

#4 2010-08-12 08:46:45

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,620
Website

Re: Writing Delphi code for 64 bits compiler

http://alex.ciobanu.org/?p=52 wrote:

The "fundamental" Integer types (the ones that have constant sizes on all platforms) are:
- Byte (1 Byte, Unsigned)
- UInt8 (alias for Byte)
- ShortInt (1 Byte, Signed)
- Int8 (alias for ShortInt)
- Word (2 Bytes, Unsigned)
- UInt16 (alias for Word)
- SmallInt (2 Bytes, Signed)
- Int16 (alias for SmallInt)
- LongWord (4 Bytes, Unsigned)
- UInt32 (alias for LongWord)
- LongInt (4 Bytes, Signed)
- Int32 (alias for LongInt)
- UInt64 (8 Bytes, Unsigned)
- Int64 (8 Bytes, Signed)
Previously listed Integer types are fixed in size — meaning that no matter what OS/CPU you're running on, these types will have the same size.

CPU specific Integer types are listed below:
- NativeUInt (Unsigned, depends on CPU register size)
- NativeInt (Signed, depends on CPU register size)
Note that the sizes of this Integer types actually depend on the "target architecture" you're going to compile you program for. So if you are targeting Windows for 64 bit you will get 8 Byte wide native Integers. If you target the 32 bit Windows and you're running your application on 64 bit Windows, NativeInt will still be 4 bytes wide.

And at last, the "generic" data types:
- Cardinal (Unsigned, depends on OS definition of Integer)
- Integer (Signed, depends on OS definition of Integer)
Yes, it might be confusing, but Integer and Cardinal are not CPU specific, but rather OS specific. In the case of Windows for 64 bit, the "int" is still 4 Bytes wide.

So what happens if you want to transition your Delphi application to 64 bit Windows? Not much really. Few things will actually break, the most usual culprits will be:
- Windows API calls. Most Windows APIs that require handles can break down for you if you for  instance consider a HWND to be a Cardinal. HWND will be 64 bit while Cardinal will stay 32 bit wide. The same applies to a lot of other Windows functions.
- Casting a Pointer to an Integer and back. Pointer is actually the same size as the NativeInt type so be sure to fix these issues in your code. Just replace Integer with NativeInt. Many developers cast a Pointer to an Integer to perform some arithmetic so that would be a pretty common case. I hope the compiler guys will add a warning if you cast between Integer and Pointer data types.
- The Tag property. I know a lot of people rely on the Tag property of VCL components to keep some state information in the GUI objects. Because the Tag property is currently defined as an Integer and you need to store an Object there, casting is performed — which brings us to the second point. But no need to worry here as the Tag property will become a NativeInt so nothing will break.

I understand that "integer and cardinal are OS specific". Its value changed from Win16 to Win32. It was necessary. With Win64, as stated, it won't change. So I hope with future Delphi 64 bit compiler, it won't either!

The trick of using HWND instead of cardinal is worth using. A lot of GDI-related code still use cardinal (or even worse integer) instead of HWND. Its always a good practice to use native Windows.pas types instead of their Delphi equivalency. Because Windows API and memory structure may vary. We saw it during the Win16-Win32 and even during the Win32-WinNT transitions.

Offline

#5 2010-08-12 14:14:25

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,620
Website

Re: Writing Delphi code for 64 bits compiler

OK. Here are the updated type definitions we'll use, with the NativeInt/NativeUInt/UInt64 types available since Delphi 2007:

{$ifndef FPC} { make cross-compiler and cross-CPU types available to Delphi }
type
  /// a CPU-dependent unsigned integer type cast of a pointer / register
  // - used for 64 bits compatibility, native under Free Pascal Compiler
  PtrUInt = {$ifdef ISDELPHI2007ANDUP}NativeUInt{$else}cardinal{$endif};
  /// a CPU-dependent unsigned integer type cast of a pointer of pointer
  // - used for 64 bits compatibility, native under Free Pascal Compiler
  PPtrUInt = ^PtrUInt;

  /// a CPU-dependent signed integer type cast of a pointer / register
  // - used for 64 bits compatibility, native under Free Pascal Compiler
  PtrInt = {$ifdef ISDELPHI2007ANDUP}NativeInt{$else}integer{$endif};
  /// a CPU-dependent signed integer type cast of a pointer of pointer
  // - used for 64 bits compatibility, native under Free Pascal Compiler
  PPtrInt = ^PtrInt;

  /// unsigned Int64 doesn't exist under older Delphi, but is defined in FPC
  QWord = {$ifdef ISDELPHI2007ANDUP}UInt64{$else}Int64{$endif};
{$endif}

Our SynCommons.pas unit has been updated.

Offline

#6 2010-08-14 07:57:03

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,620
Website

Re: Writing Delphi code for 64 bits compiler

ab wrote:

Hoping and praying

I just hope that EMB will follow the same rules for their future 64 bits compiler.

They will surely release their compiler 5 years later than FPC's... I hope they will follow the FPC way, just as Intel did about 64 bits instructions, against AMD.

What I was referring to is that AMD was the first to publish a 64 bit x86 CPU, with a new instruction set. Intel released their own 64 bit x86 CPU, following the same instruction set.
There are some variants between AMD and Intel CPU, some dedicated instructions or implementations.
But most instruction set is perfectly compatible.

The main difference between Delphi and FPC is that the first is a business company project (Embarcadero), the second an Open Source solution. They are not two billions dollars companies fighting each other, with some state-level institutions watching about any unfair competition or monopoly... FPC compiler is technically a great and robust project, but EMB follows business rules. I don't think anyone will play "Anti-monopoly" in favor of FPC.

FPC published a 64 bit compiler using the Delphi/object pascal language in 2006.
It could have been fair and less confusing that Delphi engineers just follow the same patterns, for example use PtrInt and PtrUInt.

I guess that in 2006, the 64 bit Delphi compiler was already a R&D project at Borland, (and Codegear since February).
That's why NativeUInt and NativeInt were made available in Delphi 2007.

But FPC published its 64 bit compiler in 2006... and EMB is not able to promise such a working x86-64 compiler before end of 2011.

Marco Cantu wrote:

The preview 64-bit compiler is still indicated with a "first half of 2011" like it was and future versions should have both 64-bit and Mac support, although from the slides it is not clear which features actually go into Pulsar ("Introduction of 64-bit and cross-platform to the RAD Studio product line"), Wheelhouse ("Extending support for 64-bit and additional platforms"), and Commodore ("Full support for 64-bit compilers for Windows, Mac OS, and Linux"). Part of the differentiators comes from the fact Delphi language will be there before C++, according to come of the details.

See http://edn.embarcadero.com/article/39934


Some kind of messy

About the IDE, RadStudio is much more advanced than Lazarus. But there are some newcomers around, like mseide, which is light and powerful.
Newest Delphi compiler have some language enhancements (like generics and attributes, without naming Unicode which is mostly VCL-related), but FPC evolves (it includes generics and in the future some clever property attributes).

But the more it goes, the less compatible.
If you want your code to compile with both Delphi and FPC, you need a lot of {$ifdef} and/or custom types... and a good knowledge of every compiler.

That's quite a mess, and a pity!
Sometimes, I miss a "standardized language", like C#, even if the libraries are not standardized (if you want to work cross-platform, e.g. using Mono, you can't rely simply on latest Microsoft libraries).


Will there be a "fratricidal war"?

If such a war happens (but isn't it already there?) in the object pascal world, we can worry.
My first reaction is to think about "poor little FPC". And imagine me at the compiler graveyard, praying on its tomb.
But after some deeper thinking, it's not so simple.
I'm not able to see which one will be the winner.

First of all, FPC is Open Source: it can't dye, if people have interest in it.
And because of object pascal language strength, even a small team of coders can handle it.

At a glance, Delphi seems more powerful than FPC, because of EMB. But it could be exactly the contrary...
Remember the Delphi for DotNet compiler: it was replaced by Oxygene, a not EMB product, but a more reactive product.

Since FPC is written in pure object pascal code (and the Delphi compiler isn't, by the way), it could be easy for EMB to embed the FPC compiler into their RadStudio XE... And by using wxforms, extending it with DB components, RadStudio could easily cross-compile to both Linux and MacOsX.

So will the Delphi for Win32 compiler dye, just as the Delphi for DotNet did?
Isn't FPC  at the right place, at the right moment?

Offline

#7 2010-08-17 04:56:06

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,620
Website

Re: Writing Delphi code for 64 bits compiler

We need to use NativeInt/NativeUInt in every place where is done pointer arithmetic. That's an obvious and mandatory use of these types.
We have to use it now. And we should use these since Delphi 2007.

Some other questions to Embarcadero:
1. Will the Tag property become NativeInt?
2. Is it a good idea to use NativeInt in loop index, to optimize code generation?
3. In a more general way, what are the compiler guess about integer<->NativeInt conversion (for example in loops)?
4. Are the other types (like Int32/UInt32) to be used anyway?
5. How will the VCL use these types?
6. Will the internal memory layout of low-level types change because of Win64 API change- for example in System.pas, TTextRec/TFileRec uses Handle: integer?
7. Will the internal memory layout of low-level types change because of 64 bits CPU use - for example in System.pas, will the StrRec packed record and refCnt/length remain in longint? What will be the changes in low-level RTII generated?
8. Will there be some conversion to PUREPASCAL or 64 bit asm of the asm functions in System.pas?

It'll be definitively a need to have at least a white paper, ASAP, which details how to write code for the 64 bits compiler, and which modifications have been made to the RTL and the VCL.

Offline

#8 2010-09-01 20:33:44

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,620
Website

Re: Writing Delphi code for 64 bits compiler

It appears in the just released Delphi XE, that the system.pas have a lot of  {$IFDEF CPUX64} blocks inside it.
EMB used another compilation directive than the one used by FPC  {$IFDEF CPU64}

Not a big issue, but it's worth emphasizing that EMB doesn't want to do like FPC. For no reason. Just to have a diverse solution. Just to remain proprietary. It's "happy closing", not "happy coding".

Even Intel and AMD use the same low-level 64 bit instruction set, and AMD was the first to provide a 64 bit CPU.
FPC provided a 64 bit compiler in 2006... and EMB doesn't want to follow its lead.
I really don't like this mentality...

See for historical purpose:
http://www.mail-archive.com/fpc-pascal@ … 05883.html

5 years after FPC, Delphi compiler "could" be 64 bit. But not in a compatible way with FPC.
It's a shame! sad

Offline

#9 2010-09-01 20:46:49

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,620
Website

Re: Writing Delphi code for 64 bits compiler

Or perhaps, EMB is a bit "jealous" about the FPC compiler, and cross-platform capabilities...
And when a woman is jealous of another woman's beauty, the first self-preserving instinct is just the denegation. "She is not here. I don't see her..."
So it's perhaps just the contrary: FPC is a better compiler, and will win the race!
Are you prepared to see the FPC compiler inside the RadStudio IDE, for true cross-platform compilation?
Just like the Oxygene compiler replaced the Delphi for DotNet compiler.
smile

Offline

#10 2010-09-01 20:47:42

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,620
Website

Re: Writing Delphi code for 64 bits compiler

One advantage of FPC is that it's self-compiling.

Whereas the Delphi compiler is written in C++.

Offline

#11 2010-09-05 14:45:05

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,620
Website

Re: Writing Delphi code for 64 bits compiler

I've made a big modification on the framework source code so that it "could" be compatible with the Delphi 64 future compiler:

See http://synopse.info/fossil/fdiff?v1=cac … 21b956af4d

It may sounds funny, but it could be enough for enabling such compatibility... our code was 64 bit ready since the beginning!
smile

Offline

#12 2011-09-03 07:23:50

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,620
Website

Re: Writing Delphi code for 64 bits compiler

And in order to embed the SQLite3 engine as a static library, it will need some work about the C RTL.
It will need recompile with other COFF 64 bit C compiler. E.g. VC++ 2010 - http://msdn.microsoft.com/en-us/library … .100).aspx as http://code.google.com/p/sqlitebot/wiki/VisualStudio (but to retrieve the .obj files).

Just include the sqlite.c in your project and change the file's private properties - set C compile, swith off pre-compiled header and make sure the file compile as native if the project is CLR.

See http://stackoverflow.com/questions/7271 … ject-files

SynCommons will need modification about exception handling and stack trace.
See http://www.delphifeeds.com/go/s/83454

Offline

#13 2012-05-17 21:12:38

dorind
Member
From: Timisoara, Romania
Registered: 2012-05-16
Posts: 1
Website

Re: Writing Delphi code for 64 bits compiler

ab wrote:

One advantage of FPC is that it's self-compiling.

Whereas the Delphi compiler is written in C++.

I actually think it's C, but maybe my info is wrong, anyhu, it just goes to show that open source pawned corporate interest, also, delphi is nothing without it's IDE(which is getting worst with every new release, see DXE2), hopefully they'll fix it really soon.

Offline

Board footer

Powered by FluxBB