fix(opdf): emit complete recProperty layout (method-name strings)
The OPDF recProperty record written by EmitProperties did not match the reader's TDefProperty layout: it emitted only the property Name and omitted the ReadMethodNameLen / WriteMethodNameLen length words and the two method-name strings the reader expects. A consumer (pdr) therefore read a misaligned record — a garbage property name and an empty getter symbol — so a method-backed property such as `property Bar: String read GetBar` could not be resolved (`print x.Bar` reported "field or property not found"). EmitProperties now writes the full format the reader specifies: the three length words (ReadMethodNameLen, WriteMethodNameLen, NameLen) followed by the ReadMethodName, WriteMethodName and Name strings. For a method-backed accessor the method-name string is the mangled getter/setter symbol — the same symbol written as ReadAddr/WriteAddr and emitted as the recFunctionScope name, so the debugger can resolve it via FindFunctionByName and inject the getter call. Verified end-to-end against the OPDF reference debugger (pdr): `print x.Bar` now invokes the getter and prints the value; the pdr integration suite is green.
This commit is contained in:
parent
43a0f9e4eb
commit
c6d22aac18
|
|
@ -975,6 +975,7 @@ var
|
|||
ReadType, WriteType: Integer;
|
||||
RecSize: Integer;
|
||||
RF: TFieldInfo;
|
||||
ReadMethSym, WriteMethSym: string;
|
||||
begin
|
||||
if AClass.Properties.Count = 0 then Exit;
|
||||
ClassTypeID := GetOrAllocTypeID(AClass.Name);
|
||||
|
|
@ -1002,8 +1003,23 @@ begin
|
|||
else
|
||||
WriteType := PAT_NONE;
|
||||
|
||||
RecSize := 28 + Length(PI.Name);
|
||||
{ 4(ClassTypeID)+4(PropTypeID)+1(ReadType)+1(WriteType)+8(ReadAddr)+8(WriteAddr)+2(NameLen) }
|
||||
{ Method-backed accessors carry the getter/setter SYMBOL name so the
|
||||
debugger can resolve it via FindFunctionByName (which matches against the
|
||||
recFunctionScope name = the mangled symbol) and inject the call. The
|
||||
symbol is the same one written as ReadAddr/WriteAddr below. }
|
||||
if ReadType = PAT_METHOD then
|
||||
ReadMethSym := MangledClassSym(AClass.Name) + '_' + PI.ReadMethod
|
||||
else
|
||||
ReadMethSym := '';
|
||||
if WriteType = PAT_METHOD then
|
||||
WriteMethSym := MangledClassSym(AClass.Name) + '_' + PI.WriteMethod
|
||||
else
|
||||
WriteMethSym := '';
|
||||
|
||||
{ Fixed-size payload (30 bytes) + the three variable-length strings.
|
||||
4(ClassTypeID)+4(PropTypeID)+1(ReadType)+1(WriteType)+8(ReadAddr)+
|
||||
8(WriteAddr)+2(ReadMethodNameLen)+2(WriteMethodNameLen)+2(NameLen). }
|
||||
RecSize := 32 + Length(ReadMethSym) + Length(WriteMethSym) + Length(PI.Name);
|
||||
|
||||
L('');
|
||||
L(' # recProperty: ' + PI.Name);
|
||||
|
|
@ -1041,7 +1057,14 @@ begin
|
|||
else
|
||||
L(' .quad 0 # WriteAddr (none)');
|
||||
|
||||
EmitStrField(PI.Name);
|
||||
{ The reader (TDefProperty) expects all three length words FIRST, then the
|
||||
three strings in order: ReadMethodName, WriteMethodName, Name. }
|
||||
L(' .word ' + IntToStr(Length(ReadMethSym)) + ' # ReadMethodNameLen');
|
||||
L(' .word ' + IntToStr(Length(WriteMethSym)) + ' # WriteMethodNameLen');
|
||||
L(' .word ' + IntToStr(Length(PI.Name)) + ' # NameLen');
|
||||
EmitNameData(ReadMethSym);
|
||||
EmitNameData(WriteMethSym);
|
||||
EmitNameData(PI.Name);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue