Brandon Staggs
Brandon Staggs

Reputation: 630

Why does dcc64 say this value is never used?

The code below is from DDetours.pas. When it compiles for 32 bit, there are no warnings emitted. When it compiles for 64-bit, it emits this warning: (Delphi Berlin Update 2)

[dcc64 Hint] DDetours.pas(1019): H2077 Value assigned to 'Prf' never used

Here is the function in question

function GetPrefixesCount(Prefixes: WORD): Byte;

var
  Prf: WORD;
  i: Byte;
begin
  { Get prefixes count used by the instruction. }
  Result := 0;
  if Prefixes = 0 then
    Exit;

  Prf := 0;
  i := 0;
  Prefixes := Prefixes and not Prf_VEX;
  while Prf < $8000 do
  begin
    Prf := (1 shl i);
    if (Prf and Prefixes = Prf) then
      Inc(Result);
    Inc(i);
  end;
end;

It sure looks to me like the very first time Prf is compared against $8000 that initial value is used.

Upvotes: 2

Views: 423

Answers (3)

Remy Lebeau
Remy Lebeau

Reputation: 598174

I suspect the 64bit compiler has a small amount of smarts built-in to allow it to recognize that

  • the variable is initialized and not touched again until the loop is entered.
  • the loop condition is comparing the variable to a literal.
  • the initial value of 0 satisfies the loop condition, thus ensuring the loop will always run at least once at runtime, effectively making it act like a repeat..until loop.

Since the compiler still has to generate code for the initialization, but knows the initial value is not needed at runtime to enter the loop, it can issue a warning that the initial value will be unused.

If you don't initialize the variable, the compiler doesn't know at compile-time whether the loop will be entered or not since the behavior is undefined, so the compiler issues a different warning about the variable being uninitialized.


Viewing the disassembly, you can see that the loop is turned into a repeat..until loop and the Prf := 0; assignment is removed by optimization:

Project87.dpr.17: Result := 0;
00000000004261AA 4833D2           xor rdx,rdx
Project87.dpr.18: if Prefixes = 0 then
00000000004261AD 6685C0           test ax,ax
00000000004261B0 7460             jz GetPrefixesCount + $72
Project87.dpr.22: i := 0;
00000000004261B2 4D33C0           xor r8,r8
Project87.dpr.23: Prefixes := Prefixes and not Prf_VEX;
00000000004261B5 0FB7C0           movzx eax,ax
00000000004261B8 81E02DFBFFFF     and eax,$fffffb2d
00000000004261BE 81F8FFFF0000     cmp eax,$0000ffff
00000000004261C4 7605             jbe GetPrefixesCount + $2B
00000000004261C6 E8050FFEFF       call @BoundErr
Project87.dpr.26: Prf := (1 shl i);
00000000004261CB 41C7C101000000   mov r9d,$00000001
00000000004261D2 418BC8           mov ecx,r8d
00000000004261D5 41D3E1           shl r9d,r9b
00000000004261D8 4489C9           mov ecx,r9d
00000000004261DB 81F9FFFF0000     cmp ecx,$0000ffff
00000000004261E1 7605             jbe GetPrefixesCount + $48
00000000004261E3 E8E80EFEFF       call @BoundErr
Project87.dpr.27: if (Prf and Prefixes = Prf) then
00000000004261E8 448BC9           mov r9d,ecx
00000000004261EB 664423C8         and r9w,ax
00000000004261EF 66443BC9         cmp r9w,cx
00000000004261F3 750A             jnz GetPrefixesCount + $5F
Project87.dpr.28: Inc(Result);
00000000004261F5 80C201           add dl,$01
00000000004261F8 7305             jnb GetPrefixesCount + $5F
00000000004261FA E8F10EFEFF       call @IntOver
Project87.dpr.29: Inc(i);
00000000004261FF 4180C001         add r8b,$01
0000000000426203 7305             jnb GetPrefixesCount + $6A
0000000000426205 E8E60EFEFF       call @IntOver
Project87.dpr.24: while Prf < $8000 do
000000000042620A 6681F90080       cmp cx,$8000
000000000042620F 72BA             jb GetPrefixesCount + $2B 

Upvotes: 2

David Heffernan
David Heffernan

Reputation: 613521

It's a compiler bug. There are a few of this nature. Quite frustrating. Sometimes the 32 bit compiler will complain in an irrational manner and then when you workaround that the 64 bit compiler in turn complains in an irrational manner about your workaround.

I don't think that Embarcadero habitually compiler with hints and warnings enabled, because their library code is full of hints and warnings.

Anyway in this case the compiler sees the two writes to the variable but for some reason does not recognise the intervening read of the variable.

There's not a whole lot that you can do. You could submit a bug report. I expect that you don't want to change the code because it is third party code. If you don't change it then you'll have to put up with the bogus hint.

Notifying the author of the library might allow them to workaround the issue. Perhaps by suppressing hints for that function.

Upvotes: 2

Brandon Staggs
Brandon Staggs

Reputation: 630

well, I guess the answer is that dcc64 is a buggy compiler when it comes to messages. Because if you comment out the offending line, "value never used" becomes "might not have been initialized." Same compiler.

[dcc64 Warning] DDetours.pas(1022): W1036 Variable 'Prf' might not have been initialized

Upvotes: 1

Related Questions