FR: allow static arrays for that offsetof-like trick.
Previously on “Offsetof-like Trick”: #39665 (closed).
So far I didn’t need it personally (can’t be sure though, unless used as a constant it works and just results in worse code...), but studying the code involved in #39665 (closed) reveals that it still has no idea about arrays.
type
PBContainer = ^BContainer;
BContainer = record
dummy: int32;
b: int32;
end;
PMyObj = ^MyObj;
MyObj = record
dummy: int32;
bs: array[0 .. 9] of BContainer;
end;
const
// FifthBOfs = PtrUint(@PMyObj(nil)^.bs[5].b); // does not compile
FifthBOfs = PtrUint(@PMyObj(nil)^.bs) + 5 * sizeof(MyObj.bs[0]) + PtrUint(@PBContainer(nil)^.b); // ugly workaround
function MyObjFromFifthB_SubOffsetOf(bPtr: PInt32): PMyObj;
begin
result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
end;
procedure MyObjFromFifthB_SubOffsetOf_End; begin end;
function MyObjFromFifthB_SubConst(bPtr: PInt32): PMyObj;
begin
result := pointer(bPtr) - FifthBOfs;
result := pointer(bPtr) - FifthBOfs;
result := pointer(bPtr) - FifthBOfs;
result := pointer(bPtr) - FifthBOfs;
result := pointer(bPtr) - FifthBOfs;
result := pointer(bPtr) - FifthBOfs;
result := pointer(bPtr) - FifthBOfs;
result := pointer(bPtr) - FifthBOfs;
result := pointer(bPtr) - FifthBOfs;
result := pointer(bPtr) - FifthBOfs;
end;
procedure MyObjFromFifthB_SubConst_End; begin end;
var
mo: MyObj;
begin
writeln('''bs[5].b'' offset in ''MyObj'': ', FifthBOfs);
writeln('@mo: ', HexStr(@mo));
writeln('@mo recovered from @mo.bs[5].b by subtracting "offsetof": ', HexStr(MyObjFromFifthB_SubOffsetOf(@mo.bs[5].b)));
writeln('@mo recovered from @mo.bs[5].b by subtracting constant: ', HexStr(MyObjFromFifthB_SubConst(@mo.bs[5].b)));
writeln('Code size for ten subtractions of "offsetof": ', CodePointer(@MyObjFromFifthB_SubOffsetOf_End) - CodePointer(@MyObjFromFifthB_SubOffsetOf));
writeln('Code size for ten subtractions of constant: ', CodePointer(@MyObjFromFifthB_SubConst_End) - CodePointer(@MyObjFromFifthB_SubConst));
if MyObjFromFifthB_SubOffsetOf(@mo.bs[5].b) <> @mo then
halt(1);
if MyObjFromFifthB_SubConst(@mo.bs[5].b) <> @mo then
halt(2);
if CodePointer(@MyObjFromFifthB_SubOffsetOf_End) - CodePointer(@MyObjFromFifthB_SubOffsetOf)
<> CodePointer(@MyObjFromFifthB_SubConst_End) - CodePointer(@MyObjFromFifthB_SubConst)
then
halt(3);
end.
'bs[5].b' offset in 'MyObj': 24
@mo: 0000000100012010
@mo recovered from @mo.bs[5].b by subtracting "offsetof": 0000000100012010
@mo recovered from @mo.bs[5].b by subtracting constant: 0000000100012010
Code size for ten subtractions of "offsetof": 112
Code size for ten subtractions of constant: 48