mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-06 15:07:27 +01:00
* instead of a flags field generate a table with all Initialize operators of all fields (nested or not, parent class or not) for class types; objects and records don't use this (yet)
git-svn-id: trunk@39690 -
This commit is contained in:
parent
21e7ddaac7
commit
a076677336
@ -65,7 +65,7 @@ interface
|
|||||||
procedure write_callconv(tcb:ttai_typedconstbuilder;def:tabstractprocdef);
|
procedure write_callconv(tcb:ttai_typedconstbuilder;def:tabstractprocdef);
|
||||||
procedure write_paralocs(tcb:ttai_typedconstbuilder;para:pcgpara);
|
procedure write_paralocs(tcb:ttai_typedconstbuilder;para:pcgpara);
|
||||||
procedure write_param_flag(tcb:ttai_typedconstbuilder;parasym:tparavarsym);
|
procedure write_param_flag(tcb:ttai_typedconstbuilder;parasym:tparavarsym);
|
||||||
procedure write_record_init_flag(tcb:ttai_typedconstbuilder;value:longword);
|
procedure write_mop_offset_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef;mop:tmanagementoperator);
|
||||||
public
|
public
|
||||||
constructor create;
|
constructor create;
|
||||||
procedure write_rtti(def:tdef;rt:trttitype);
|
procedure write_rtti(def:tdef;rt:trttitype);
|
||||||
@ -175,7 +175,6 @@ implementation
|
|||||||
TRTTIWriter
|
TRTTIWriter
|
||||||
***************************************************************************}
|
***************************************************************************}
|
||||||
|
|
||||||
|
|
||||||
procedure TRTTIWriter.write_methods(tcb:ttai_typedconstbuilder;st:tsymtable;visibilities:tvisibilities);
|
procedure TRTTIWriter.write_methods(tcb:ttai_typedconstbuilder;st:tsymtable;visibilities:tvisibilities);
|
||||||
var
|
var
|
||||||
rtticount,
|
rtticount,
|
||||||
@ -454,13 +453,79 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TRTTIWriter.write_record_init_flag(tcb:ttai_typedconstbuilder;value:longword);
|
function compare_mop_offset_entry(item1,item2:pointer):longint;
|
||||||
|
var
|
||||||
|
entry1: pmanagementoperator_offset_entry absolute item1;
|
||||||
|
entry2: pmanagementoperator_offset_entry absolute item2;
|
||||||
begin
|
begin
|
||||||
{ keep this in sync with the type declaration of TRecordInfoInitFlag(s)
|
if entry1^.offset<entry2^.offset then
|
||||||
in both rttidecl.inc and typinfo.pp }
|
result:=-1
|
||||||
if target_info.endian=endian_big then
|
else if entry1^.offset>entry2^.offset then
|
||||||
value:=reverse_longword(value);
|
result:=1
|
||||||
tcb.emit_ord_const(value,u32inttype);
|
else
|
||||||
|
result:=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TRTTIWriter.write_mop_offset_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef;mop:tmanagementoperator);
|
||||||
|
var
|
||||||
|
list : tfplist;
|
||||||
|
datatcb : ttai_typedconstbuilder;
|
||||||
|
tbllbl : TAsmLabel;
|
||||||
|
entry : pmanagementoperator_offset_entry;
|
||||||
|
datadef,entrydef : tdef;
|
||||||
|
i : longint;
|
||||||
|
pdef : tobjectdef;
|
||||||
|
begin
|
||||||
|
list:=tfplist.create;
|
||||||
|
tabstractrecordsymtable(def.symtable).get_managementoperator_offset_list(mop,list);
|
||||||
|
if (def.typ=objectdef) then
|
||||||
|
begin
|
||||||
|
pdef:=tobjectdef(def).childof;
|
||||||
|
while assigned(pdef) do
|
||||||
|
begin
|
||||||
|
tabstractrecordsymtable(pdef.symtable).get_managementoperator_offset_list(mop,list);
|
||||||
|
pdef:=pdef.childof;
|
||||||
|
end;
|
||||||
|
list.sort(@compare_mop_offset_entry);
|
||||||
|
end;
|
||||||
|
if list.count=0 then
|
||||||
|
tcb.emit_tai(tai_const.create_nil_dataptr,voidpointertype)
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
tcb.start_internal_data_builder(current_asmdata.AsmLists[al_rtti],sec_rodata,'',datatcb,tbllbl);
|
||||||
|
|
||||||
|
datatcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
|
||||||
|
targetinfos[target_info.system]^.alignment.recordalignmin,
|
||||||
|
targetinfos[target_info.system]^.alignment.maxCrecordalign);
|
||||||
|
datatcb.emit_ord_const(list.count,u32inttype);
|
||||||
|
|
||||||
|
entrydef:=get_recorddef(itp_init_mop_offset_entry,[voidcodepointertype,sizeuinttype],defaultpacking);
|
||||||
|
|
||||||
|
for i:=0 to list.count-1 do
|
||||||
|
begin
|
||||||
|
entry:=pmanagementoperator_offset_entry(list[i]);
|
||||||
|
|
||||||
|
datatcb.maybe_begin_aggregate(entrydef);
|
||||||
|
|
||||||
|
datatcb.queue_init(voidcodepointertype);
|
||||||
|
datatcb.queue_emit_proc(entry^.pd);
|
||||||
|
|
||||||
|
datatcb.queue_init(sizeuinttype);
|
||||||
|
datatcb.queue_emit_ordconst(entry^.offset,sizeuinttype);
|
||||||
|
|
||||||
|
datatcb.maybe_end_aggregate(entrydef);
|
||||||
|
|
||||||
|
dispose(entry);
|
||||||
|
end;
|
||||||
|
|
||||||
|
datadef:=datatcb.end_anonymous_record;
|
||||||
|
|
||||||
|
tcb.finish_internal_data_builder(datatcb,tbllbl,datadef,sizeof(pint));
|
||||||
|
|
||||||
|
tcb.emit_tai(tai_const.Create_sym(tbllbl),voidpointertype);
|
||||||
|
end;
|
||||||
|
list.free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -1251,10 +1316,8 @@ implementation
|
|||||||
{ store rtti management operators only for init table }
|
{ store rtti management operators only for init table }
|
||||||
if (rt=initrtti) then
|
if (rt=initrtti) then
|
||||||
begin
|
begin
|
||||||
riif:=0;
|
{ for now records don't have the initializer table }
|
||||||
if def.has_non_trivial_init_child(false) then
|
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
|
||||||
riif:=riif or riifNonTrivialChild;
|
|
||||||
write_record_init_flag(tcb,riif);
|
|
||||||
if (trecordsymtable(def.symtable).managementoperators=[]) then
|
if (trecordsymtable(def.symtable).managementoperators=[]) then
|
||||||
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype)
|
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype)
|
||||||
else
|
else
|
||||||
@ -1407,12 +1470,11 @@ implementation
|
|||||||
{ pointer to management operators available only for initrtti }
|
{ pointer to management operators available only for initrtti }
|
||||||
if (rt=initrtti) then
|
if (rt=initrtti) then
|
||||||
begin
|
begin
|
||||||
riif:=0;
|
{ initializer table only available for classes currently }
|
||||||
if def.has_non_trivial_init_child(false) then
|
if def.objecttype=odt_class then
|
||||||
riif:=riif or riifNonTrivialChild;
|
write_mop_offset_table(tcb,def,mop_initialize)
|
||||||
if assigned(def.childof) and def.childof.has_non_trivial_init_child(true) then
|
else
|
||||||
riif:=riif or riifParentHasNonTrivialChild;
|
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
|
||||||
write_record_init_flag(tcb,riif);
|
|
||||||
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
|
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
|
||||||
end;
|
end;
|
||||||
{ enclosing record takes care of alignment }
|
{ enclosing record takes care of alignment }
|
||||||
|
|||||||
@ -734,6 +734,7 @@ type
|
|||||||
itp_rtti_set_outer,
|
itp_rtti_set_outer,
|
||||||
itp_rtti_set_inner,
|
itp_rtti_set_inner,
|
||||||
itp_init_record_operators,
|
itp_init_record_operators,
|
||||||
|
itp_init_mop_offset_entry,
|
||||||
itp_threadvar_record,
|
itp_threadvar_record,
|
||||||
itp_objc_method_list,
|
itp_objc_method_list,
|
||||||
itp_objc_proto_list,
|
itp_objc_proto_list,
|
||||||
@ -873,6 +874,7 @@ inherited_objectoptions : tobjectoptions = [oo_has_virtual,oo_has_private,oo_has
|
|||||||
'$rtti_set_outer$',
|
'$rtti_set_outer$',
|
||||||
'$rtti_set_inner$',
|
'$rtti_set_inner$',
|
||||||
'$init_record_operators$',
|
'$init_record_operators$',
|
||||||
|
'$init_mop_offset_entry$',
|
||||||
'$threadvar_record$',
|
'$threadvar_record$',
|
||||||
'$objc_method_list$',
|
'$objc_method_list$',
|
||||||
'$objc_proto_list$',
|
'$objc_proto_list$',
|
||||||
|
|||||||
@ -382,8 +382,9 @@
|
|||||||
{$ifndef VER3_0}
|
{$ifndef VER3_0}
|
||||||
var
|
var
|
||||||
vmt : PVmt;
|
vmt : PVmt;
|
||||||
temp : pointer;
|
inittable : pointer;
|
||||||
flags : TRecordInfoInitFlags;
|
mopinittable : PRTTIRecordOpOffsetTable;
|
||||||
|
i : longint;
|
||||||
{$endif VER3_0}
|
{$endif VER3_0}
|
||||||
begin
|
begin
|
||||||
{ the size is saved at offset 0 }
|
{ the size is saved at offset 0 }
|
||||||
@ -397,23 +398,22 @@
|
|||||||
{$ifndef VER3_0}
|
{$ifndef VER3_0}
|
||||||
{ for management operators like initialize call int_initialize }
|
{ for management operators like initialize call int_initialize }
|
||||||
vmt := PVmt(self);
|
vmt := PVmt(self);
|
||||||
while vmt<>nil do
|
if assigned(vmt) then
|
||||||
begin
|
begin
|
||||||
Temp:= vmt^.vInitTable;
|
inittable:=vmt^.vInitTable;
|
||||||
if assigned(Temp) then
|
if assigned(inittable) then
|
||||||
begin
|
begin
|
||||||
flags:=RecordRTTIInitFlags(Temp);
|
mopinittable:=RTTIRecordMopInitTable(inittable);
|
||||||
if riifNonTrivialChild in flags then
|
if assigned(mopinittable) then
|
||||||
{ The RTTI format matches one for records, except the type
|
begin
|
||||||
is tkClass. Since RecordRTTI does not check the type,
|
{$push}
|
||||||
calling it yields the desired result. }
|
{ ensure that no range check errors pop up with the [0..0] array }
|
||||||
RecordRTTI(Instance,Temp,@int_initialize);
|
{$R-}
|
||||||
{ no need to continue complex initializing up the inheritance
|
for i:=0 to mopinittable^.Count-1 do
|
||||||
tree if none of the parents require it anyway }
|
TRTTIRecVarOp(mopinittable^.Entries[i].ManagmentOperator)(PByte(Instance)+mopinittable^.Entries[i].FieldOffset);
|
||||||
if not (riifParentHasNonTrivialChild in flags) then
|
{$pop}
|
||||||
break;
|
end;
|
||||||
end;
|
end;
|
||||||
vmt:= vmt^.vParent;
|
|
||||||
end;
|
end;
|
||||||
{$endif VER3_0}
|
{$endif VER3_0}
|
||||||
|
|
||||||
|
|||||||
@ -138,10 +138,10 @@ end;
|
|||||||
|
|
||||||
|
|
||||||
{$ifndef VER3_0}
|
{$ifndef VER3_0}
|
||||||
function RecordRTTIInitFlags(ti: Pointer): TRecordInfoInitFlags;
|
function RTTIRecordMopInitTable(ti: Pointer): PRTTIRecordOpOffsetTable;
|
||||||
begin
|
begin
|
||||||
ti:=aligntoqword(ti+2+PByte(ti)[1]);
|
ti:=aligntoqword(ti+2+PByte(ti)[1]);
|
||||||
Result:=PRecordInfoInit(ti)^.Flags;
|
Result:=PRecordInfoInit(ti)^.InitRecordOpTable;
|
||||||
end;
|
end;
|
||||||
{$endif VER3_0}
|
{$endif VER3_0}
|
||||||
|
|
||||||
|
|||||||
@ -92,24 +92,24 @@ type
|
|||||||
Copy: TRTTIRecCopyOp;
|
Copy: TRTTIRecCopyOp;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{$ifndef VER3_0}
|
TRTTIRecordOpOffsetEntry =
|
||||||
{$push}
|
{$ifdef USE_PACKED}
|
||||||
|
packed
|
||||||
|
{$endif USE_PACKED}
|
||||||
|
record
|
||||||
|
ManagmentOperator: CodePointer;
|
||||||
|
FieldOffset: SizeUInt;
|
||||||
|
end;
|
||||||
|
|
||||||
{ better alignment for TRecordInfoInit }
|
TRTTIRecordOpOffsetTable =
|
||||||
{ keep in sync with ncgrtti.TRTTIWriter.write_record_init_flag() and typinfo.pp }
|
{$ifdef USE_PACKED}
|
||||||
{ ToDo: different values for 8/16-bit platforms? }
|
packed
|
||||||
{$minenumsize 4}
|
{$endif USE_PACKED}
|
||||||
{$packset 4}
|
record
|
||||||
|
Count: LongWord;
|
||||||
TRecordInfoInitFlag = (
|
Entries: array[0..0] of TRTTIRecordOpOffsetEntry;
|
||||||
riifNonTrivialChild,
|
end;
|
||||||
{ only relevant for classes }
|
PRTTIRecordOpOffsetTable = ^TRTTIRecordOpOffsetTable;
|
||||||
riifParentHasNonTrivialChild
|
|
||||||
);
|
|
||||||
TRecordInfoInitFlags = set of TRecordInfoInitFlag;
|
|
||||||
|
|
||||||
{$pop}
|
|
||||||
{$endif}
|
|
||||||
|
|
||||||
TRecordInfoInit=
|
TRecordInfoInit=
|
||||||
{$ifdef USE_PACKED}
|
{$ifdef USE_PACKED}
|
||||||
@ -119,7 +119,7 @@ type
|
|||||||
Terminator: Pointer;
|
Terminator: Pointer;
|
||||||
Size: Longint;
|
Size: Longint;
|
||||||
{$ifndef VER3_0}
|
{$ifndef VER3_0}
|
||||||
Flags: TRecordInfoInitFlags;
|
InitRecordOpTable: PRTTIRecordOpOffsetTable;
|
||||||
RecordOp: PRTTIRecordOpVMT;
|
RecordOp: PRTTIRecordOpVMT;
|
||||||
{$endif VER3_0}
|
{$endif VER3_0}
|
||||||
Count: Longint;
|
Count: Longint;
|
||||||
@ -148,7 +148,7 @@ type
|
|||||||
|
|
||||||
|
|
||||||
{$ifndef VER3_0}
|
{$ifndef VER3_0}
|
||||||
function RecordRTTIInitFlags(ti: Pointer): TRecordInfoInitFlags; forward;
|
function RTTIRecordMopInitTable(ti: Pointer): PRTTIRecordOpOffsetTable; forward;
|
||||||
{$endif VER3_0}
|
{$endif VER3_0}
|
||||||
|
|
||||||
{$ifdef VER3_0}
|
{$ifdef VER3_0}
|
||||||
|
|||||||
@ -410,25 +410,24 @@ unit TypInfo;
|
|||||||
Entries: array[0..0] of TVmtMethodEntry;
|
Entries: array[0..0] of TVmtMethodEntry;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TRecOpOffsetEntry =
|
||||||
|
{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
|
||||||
|
packed
|
||||||
|
{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
|
||||||
|
record
|
||||||
|
ManagementOperator: CodePointer;
|
||||||
|
FieldOffset: SizeUInt;
|
||||||
|
end;
|
||||||
|
|
||||||
{$ifndef VER3_0}
|
TRecOpOffsetTable =
|
||||||
{$push}
|
{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
|
||||||
|
packed
|
||||||
{ better alignment for TRecordInfoInit }
|
{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
|
||||||
{ keep in sync with ncgrtti.TRTTIWriter.write_record_init_flag() and rttidecl.inc }
|
record
|
||||||
{ ToDo: different values for 8/16-bit platforms? }
|
Count: LongWord;
|
||||||
{$minenumsize 4}
|
Entries: array[0..0] of TRecOpOffsetEntry;
|
||||||
{$packset 4}
|
end;
|
||||||
|
PRecOpOffsetTable = ^TRecOpOffsetTable;
|
||||||
TRecordInfoInitFlag = (
|
|
||||||
riifNonTrivialChild,
|
|
||||||
{ only relevant for classes }
|
|
||||||
riifParentHasNonTrivialChild
|
|
||||||
);
|
|
||||||
TRecordInfoInitFlags = set of TRecordInfoInitFlag;
|
|
||||||
|
|
||||||
{$pop}
|
|
||||||
{$endif}
|
|
||||||
|
|
||||||
PRecInitData = ^TRecInitData;
|
PRecInitData = ^TRecInitData;
|
||||||
TRecInitData =
|
TRecInitData =
|
||||||
@ -439,7 +438,7 @@ unit TypInfo;
|
|||||||
Terminator: Pointer;
|
Terminator: Pointer;
|
||||||
Size: Integer;
|
Size: Integer;
|
||||||
{$ifndef VER3_0}
|
{$ifndef VER3_0}
|
||||||
Flags: TRecordInfoInitFlags;
|
InitOffsetOp: PRecOpOffsetTable;
|
||||||
ManagementOp: Pointer;
|
ManagementOp: Pointer;
|
||||||
{$endif}
|
{$endif}
|
||||||
ManagedFieldCount: Integer;
|
ManagedFieldCount: Integer;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user