Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 06/08/20 in all areas

  1. David Heffernan

    Byte and Integer

    Couldn't take the traffic of tens of devs trying to vote for range checking enabled by default
  2. Hello there, In the previous topic about Strange behavior for literals @Lars Fosdal asked himself a very interesting question about typed-constant. I quote : In this topic, I'll try to answer the following questions: - What is a typed-constant ? - How internally is handled by the compiler ? - Why a typed-constant can't act as a compile-time constant ? - What's the relationship between typed-constant and optimization ? What's a typed constant ? It is a constant that has a type associated with it. const NotTypedConstant = StaticExpression; const TypedConstant : ConstantType = StaticExpression; // e.g: const A = 5; // not typed constant. const B: Integer = 5; // typed constant. As you can see, all constants must be initialized with a static expression (an expression that the compiler can evaluate at compile time). However, no-typed-constant can be used in static expression, but a typed-constant can't ! const A = 5; // Ok. B = A + 1; // Ok. C: Integer = B; // Ok. D: Integer = C; // Error. Wondering why ? this is because the compiler is seeing C and D as variables (not static-compile-time constant) and it treats them same way as it does with pure variables ! You may think that this kind of behavior is unacceptable ? In fact there is a good reason for that ! How internally is handled by the compiler ? Please, consider the following example : // ---------------------------- Unit1 ---------------------------- unit Unit1; interface // public constants: const MIN = 0; MAX = 1000; MyData: array [MIN .. MAX] of Integer = (...); implementation // ... end. // ---------------------------- Unit2 ---------------------------- unit Unit2; interface implementation uses Unit1; // using Unit1. function ValidateData : Boolean; begin var First := MyData[MIN]; // first item. var Last := MyData[MAX]; // last item. // ... end; end. Would not be just perfect to be able to declare First and Last as constants ? const First: Integer = MyData[MIN]; const Last : Integer = MyData[MAX]; // or const First = MyData[MIN]; const Last = MyData[MAX]; This is not possible ! because when compiling Unit1, the compiler produce a .dcu file that contains two things : an interface and an implementation (obj) section for Unit1: // ---------------------------- Unit1.dcu ---------------------------- // Note that a .dcu file is a binary format ... I'm just using text format for demonstration ! interface section: // static-compile-time constant with definition: // ---------------------------------------------- const MIN = 0; const MAX = 1000; // constant WITHOUT definition: // ----------------------------- const MyData: array [MIN .. MAX] of Integer; implementation section: DataSection: MyData = [0, 1, ...]; ... CodeSection: ... When compiling Unit2. the compiler sees uses Unit1; and opens Unit1.dcu file and only going to read the interface section. Meaning the compiler only sees the declaration of MyData, but does not know about the data itself (data inside MyData): // unit2: // ------ // knowing the type and size of MyData is more important than knowing whats inside var value : Integer := MyData[MAX + 100]; // Error violating MyData bounds. Now, because the compiler does not know about the data. MyData can't be used in a static expression. However you can query it's type and size: // Unit2 const First = MyData[MIN]; // error. compiler does not know what MyData holds. const Size = SizeOf(MyData); // Ok. compiler knows the type and size. Why a typed-constant can't act as a compile-time constant ? Now, if the compiler is able to read the implementation section from the .dcu file, it will also able to access/read MyData definition and allows using typed-constant inside a static expression ... and much better, it will do a very good job for optimization (constant folding && constant propagation). Excited ? Don't be ! If it does such a thing... It will certainly come at a cost of compilation time : a very long compilation time ! That's because for each unit, the compiler must read both section (interface and implementation) and must process all the data inside the implementation section. Delphi is a fast compiler and allowing the use of typed-constant inside a static-expression will break that theory. What's the relationship between typed-constant and optimization ? So, Is Delphi typed-constant behavior correct ? From my point of view yes ! Is Delphi handling it smoothly ? Absolutely no !!! In fact the compiler does not do any kind of optimization (constant folding & propagation) even if the definition is available (constant declared in the same unit) : implementation {$O+} // this is a private declaration. compiler can access to the definition ! const MyData: array [0 .. 3] of Integer = (5, 16, 7, 10); var First: Integer; initialization // since it can access to the definition, it can generate much better code for : // First := MyData[0]; // mov reg, 5 // MyData[0] = 5. // but it just generated : // mov reg, [@MyData + offset] // ... end. The sad reason behind the above generated code is that typed-constant in Delphi is volatile ! Improving optimization: 1) Always declaring ordinal type as a non-typed-constant whenever its possible : const First = ...; // compile time constant. const Last = ...; // compile time constant. const MyData: array [MIN .. MAX] of Integer = (First, ..., Last); 2) Using a Link-Time-Code-Generation (LTCG*): This is some how hard to implement but definitely is the best way to improve optimization one for all ! This gives a full view of the program ... meaning the code-generator will have much opportunity to do function in-lining, constant folding & propagation, ... The good thing, its just an option (so you can just use it when doing a Release build). LTCG* = is not supported by Delphi. Perhaps its supported with C++Builder (I'm not sure about that). If anyone has a clean info, please make a comment. Conclusion: The purpose of typed-constants is to hold a non-ordinal-data(array, record, ...), and a way to share data between units and speed-up compilation-time. For ordinal-type (integer,...), you should always use a non-typed-constant.
  3. Stefan Glienke

    Modern TColorDialog

    Afaik the dialog used by Delphi is just what the winapi offers.
  4. David Heffernan

    SendMessage From DLL

    Wait a minute. If its a 64 bit add in then why are you casting the pointer to a 32 bit integer?
  5. Tom F

    Your RAD Studio 10.4 Sydney issues

    If you're waiting for Raize Konopka KSVC like I am, please vote for this issue: https://quality.embarcadero.com/browse/RSP-29400.
  6. Cristian Peța

    Your RAD Studio 10.4 Sydney issues

    Fixed (see report).
  7. Stefan Glienke

    Byte and Integer

    Give some more votes to https://quality.embarcadero.com/browse/RSP-16751 maybe we get it some day...
  8. Dave Nottage

    StoryBoard launch screen - Delphi 10.4

    Renaming the app has the same effect. Certainly saves on having to restart the device 🙂
  9. David Heffernan

    Byte and Integer

    You should enable both range checking and overflow checking. Then you'll see your exceptions.
  10. Lars Fosdal

    Your RAD Studio 10.4 Sydney issues

    What I did to get my favorite color scheme from 10.3 to 10.4 and have it stick. In 10.4, go to Options | User Interface | Editor | Color With the current colors, just click on [Save As] and and give your personal scheme a name. I called mine Lars. This creates a Registry branch, named HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Editor\Highlight\Custom themes\Lars In RegEdit, go to HKEY_CURRENT_USER\Software\Embarcadero\BDS\20.0\Editor\Highlight (i.e. the Rio branch) Export to a file, f.x. MyColors.reg In MyColors.reg, you'll see Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Embarcadero\BDS\20.0\Editor\Highlight] [HKEY_CURRENT_USER\Software\Embarcadero\BDS\20.0\Editor\Highlight\Additional search match highlight] ... and so on Now, Open MyColors.reg in Notepad, search for "20.0\Editor\Highlight\" and replace it with "21.0\Editor\Highlight\Custom themes\Lars\". Add the two branch paths for good measure. Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Editor\Highlight] [HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Editor\Highlight\Custom themes] [HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Editor\Highlight\Custom themes\Lars] [HKEY_CURRENT_USER\Software\Embarcadero\BDS\21.0\Editor\Highlight\Custom themes\Lars\Additional search match highlight] ... and so on Import the file into the registry, Restart the 10.4, go to Options | User Interface | Editor | Color and pick the custom theme "Lars".
  11. @Yaron I use this library https://github.com/CMCHTPC/DelphiDX12 This was made to be used with FPC firstly, you will see many hints and warnings compiling to Delphi. But it still works for me.
×