fix(debug-opdf): emit recPrimitive for Double and Single

Float-typed variables (Double, Single) were invisible in pdr — locals,
print, gl and every other inspection command failed for floats while
integers, strings, classes and records-of-int-and-string worked. The OPDF
emitter never produced a recPrimitive for tyDouble/tySingle: EmitTypeDesc
did not dispatch the float kinds, so a float variable's GlobalVar/LocalVar
record referenced a TypeID with no corresponding type record, and pdr could
not resolve the type to read the value.

EmitTypeDesc now routes tyDouble/tySingle to EmitPrimitive, which emits the
record with SizeInBytes (8/4), IsSigned=1, and a new SubKind=SK_FLOAT (4).
The pdr side already handled this fully: the adapter maps SubKind skFloat to
Category tcFloat and TFloatEvaluator reads the IEEE 754 value by size — it
was only waiting for the compiler to emit the record.

Verified end to end with pdr: a global, a local, and a Double record field
all print their values (d = 3.14159, s = 2.5, pt.Z = 9.81), and locals lists
them. IR tests assert the Double/Single recPrimitive carries SubKind=4 and
the correct size.
This commit is contained in:
Graeme Geldenhuys 2026-06-29 12:53:25 +01:00
parent 2759a27329
commit c3ed2c89d6
2 changed files with 48 additions and 1 deletions

View file

@ -140,6 +140,8 @@ const
SK_INTEGER = 0;
SK_BOOLEAN = 1;
{ SK_CHAR = 2; SK_WIDECHAR = 3; — reserved by the OPDF spec, not emitted yet }
SK_FLOAT = 4; { Single, Double — pdr renders via TFloatEvaluator }
LOC_RBP = 1;
LOC_RBP_INDIRECT = 3; { frame slot holds the value's address }
@ -369,7 +371,8 @@ begin
if HasBeenEmitted(CName) then Exit;
case AType.Kind of
tyInteger, tyInt64, tyUInt32, tyUInt64,
tySmallInt, tyWord, tyByte, tyBoolean:
tySmallInt, tyWord, tyByte, tyBoolean,
tyDouble, tySingle:
EmitPrimitive(AType);
tyString:
EmitUtf8Str();
@ -407,6 +410,10 @@ begin
tyBoolean: begin SubKind := SK_BOOLEAN; IsSigned := 0; end;
tyInt64, tyInteger, tySmallInt:
begin SubKind := SK_INTEGER; IsSigned := 1; end;
tyDouble, tySingle:
{ Single (4B) / Double (8B) pdr keys off SubKind=skFloat
and reads the IEEE 754 value by SizeInBytes. }
begin SubKind := SK_FLOAT; IsSigned := 1; end;
else
SubKind := SK_INTEGER; IsSigned := 0;
end;

View file

@ -27,6 +27,8 @@ type
procedure TestOPDF_Primitive_Integer;
procedure TestOPDF_Primitive_Boolean;
procedure TestOPDF_Primitive_Int64;
procedure TestOPDF_Primitive_Double_SubKindFloat;
procedure TestOPDF_Primitive_Single_SubKindFloat;
procedure TestOPDF_AnsiStr_Record;
procedure TestOPDF_GlobalVar_QuadLabel;
procedure TestOPDF_GlobalVar_RecType;
@ -175,6 +177,44 @@ begin
AssertTrue('recPrimitive Int64 present', Contains(IR, '# recPrimitive: Int64'));
end;
procedure TOPDFTests.TestOPDF_Primitive_Double_SubKindFloat;
{ Regression: float types emitted NO recPrimitive at all, so a Double/Single
variable referenced a TypeID with no type record and pdr could not print it
(locals/print/gl all failed for floats). A Double must now emit a recPrimitive
with SubKind=SK_FLOAT(4) and SizeInBytes=8 so pdr's TFloatEvaluator
(Category=tcFloat, keyed off SubKind in [skFloat, skCurrency]) renders it. }
var
IR: string;
P: Integer;
begin
IR := GenOPDF('program P; var D: Double; begin D := 1.5 end.');
AssertTrue('recPrimitive Double comment', Contains(IR, '# recPrimitive: Double'));
AssertTrue('Double name emitted', Contains(IR, '.ascii "Double"'));
P := Pos('# recPrimitive: Double', IR);
AssertTrue('Double recPrimitive present', P >= 0);
{ SubKind must be SK_FLOAT (4) and size 8, in the Double record's payload. }
AssertTrue('Double SubKind = 4 (skFloat)',
Pos('.byte 4 # SubKind', Copy(IR, P, 220)) >= 0);
AssertTrue('Double SizeInBytes = 8',
Pos('.byte 8 # SizeInBytes', Copy(IR, P, 220)) >= 0);
end;
procedure TOPDFTests.TestOPDF_Primitive_Single_SubKindFloat;
{ Single is the 4-byte float counterpart; same recPrimitive shape, size 4. }
var
IR: string;
P: Integer;
begin
IR := GenOPDF('program P; var S: Single; begin S := 1.5 end.');
AssertTrue('recPrimitive Single comment', Contains(IR, '# recPrimitive: Single'));
P := Pos('# recPrimitive: Single', IR);
AssertTrue('Single recPrimitive present', P >= 0);
AssertTrue('Single SubKind = 4 (skFloat)',
Pos('.byte 4 # SubKind', Copy(IR, P, 220)) >= 0);
AssertTrue('Single SizeInBytes = 4',
Pos('.byte 4 # SizeInBytes', Copy(IR, P, 220)) >= 0);
end;
procedure TOPDFTests.TestOPDF_AnsiStr_Record;
var
IR: string;