* Emit comments in RTTI info for classes/interfaces

This commit is contained in:
Michaël Van Canneyt 2023-05-26 22:45:06 +02:00 committed by Sven/Sarah Barth
parent 0515be62b4
commit 8696ca652d
2 changed files with 80 additions and 3 deletions

View File

@ -407,6 +407,9 @@ type
useful in case you have table preceded by the number of elements, and useful in case you have table preceded by the number of elements, and
you count the elements while building the table } you count the elements while building the table }
function emit_placeholder(def: tdef): ttypedconstplaceholder; virtual; abstract; function emit_placeholder(def: tdef): ttypedconstplaceholder; virtual; abstract;
{ Add a comment line
}
procedure emit_comment(const comment : string);
protected protected
{ common code to check whether a placeholder can be added at the current { common code to check whether a placeholder can be added at the current
position } position }
@ -2029,6 +2032,16 @@ implementation
insert_marked_aggregate_alignment(result); insert_marked_aggregate_alignment(result);
end; end;
procedure ttai_typedconstbuilder.emit_comment(const comment: string);
var
comm: tai_comment;
begin
if (length(comment)=0) then
exit;
comm:=tai_comment.Create(strpnew(comment));
fasmlist.concat(comm);
end;
procedure ttai_typedconstbuilder.check_add_placeholder(def: tdef); procedure ttai_typedconstbuilder.check_add_placeholder(def: tdef);
begin begin

View File

@ -42,7 +42,8 @@ interface
{ required packing of all structures except for ttypeinfo and tpropinfo, { required packing of all structures except for ttypeinfo and tpropinfo,
which always use packrecords 1 } which always use packrecords 1 }
defaultpacking: shortint; defaultpacking: shortint;
{ write comments ? }
addcomments : boolean;
procedure fields_write_rtti(st:tsymtable;rt:trttitype); procedure fields_write_rtti(st:tsymtable;rt:trttitype);
procedure params_write_rtti(def:tabstractprocdef;rt:trttitype;allow_hidden:boolean); procedure params_write_rtti(def:tabstractprocdef;rt:trttitype;allow_hidden:boolean);
procedure fields_write_rtti_data(tcb: ttai_typedconstbuilder; def: tabstractrecorddef; rt: trttitype); procedure fields_write_rtti_data(tcb: ttai_typedconstbuilder; def: tabstractrecorddef; rt: trttitype);
@ -68,6 +69,7 @@ interface
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_mop_offset_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef;mop:tmanagementoperator); procedure write_mop_offset_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef;mop:tmanagementoperator);
procedure maybe_add_comment(tcb:ttai_typedconstbuilder;const comment : string); inline;
public public
constructor create; constructor create;
procedure write_rtti(def:tdef;rt:trttitype); procedure write_rtti(def:tdef;rt:trttitype);
@ -103,6 +105,10 @@ implementation
{ Objective-C related, does not pass here } { Objective-C related, does not pass here }
symconst.ds_none,symconst.ds_none, symconst.ds_none,symconst.ds_none,
symconst.ds_none,symconst.ds_none); symconst.ds_none,symconst.ds_none);
rttitypenames : array[trttitype] of string =
('full','init',
'objcmeta','objcmetaro',
'objcclass','objcclassro');
type type
TPropNameListItem = class(TFPHashObject) TPropNameListItem = class(TFPHashObject)
@ -210,6 +216,7 @@ implementation
def : tprocdef; def : tprocdef;
para : tparavarsym; para : tparavarsym;
begin begin
maybe_add_comment(tcb,'RTTI: begin methods');
tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)), tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
targetinfos[target_info.system]^.alignment.recordalignmin); targetinfos[target_info.system]^.alignment.recordalignmin);
@ -225,7 +232,9 @@ implementation
inc(rtticount); inc(rtticount);
end; end;
maybe_add_comment(tcb,#9'count');
tcb.emit_ord_const(totalcount,u16inttype); tcb.emit_ord_const(totalcount,u16inttype);
maybe_add_comment(tcb,#9'RTTI count');
if rtticount = 0 then if rtticount = 0 then
tcb.emit_ord_const($FFFF,u16inttype) tcb.emit_ord_const($FFFF,u16inttype)
else else
@ -245,40 +254,55 @@ implementation
def.init_paraloc_info(callerside); def.init_paraloc_info(callerside);
maybe_add_comment(tcb,'RTTI: begin method '+def.fullprocname(false));
tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)), tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
targetinfos[target_info.system]^.alignment.recordalignmin); targetinfos[target_info.system]^.alignment.recordalignmin);
maybe_add_comment(tcb,#9'return type');
write_rtti_reference(tcb,def.returndef,fullrtti); write_rtti_reference(tcb,def.returndef,fullrtti);
maybe_add_comment(tcb,#9'calling convention');
write_callconv(tcb,def); write_callconv(tcb,def);
maybe_add_comment(tcb,#9'method kind');
write_methodkind(tcb,def); write_methodkind(tcb,def);
maybe_add_comment(tcb,#9'param count');
tcb.emit_ord_const(def.paras.count,u16inttype); tcb.emit_ord_const(def.paras.count,u16inttype);
maybe_add_comment(tcb,#9'caller args size');
tcb.emit_ord_const(def.callerargareasize,ptrsinttype); tcb.emit_ord_const(def.callerargareasize,ptrsinttype);
maybe_add_comment(tcb,#9'name');
tcb.emit_pooled_shortstring_const_ref(sym.realname); tcb.emit_pooled_shortstring_const_ref(sym.realname);
for k:=0 to def.paras.count-1 do for k:=0 to def.paras.count-1 do
begin begin
para:=tparavarsym(def.paras[k]); para:=tparavarsym(def.paras[k]);
maybe_add_comment(tcb,'RTTI: begin param '+para.prettyname);
tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)), tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
targetinfos[target_info.system]^.alignment.recordalignmin); targetinfos[target_info.system]^.alignment.recordalignmin);
maybe_add_comment(tcb,#9'type');
if is_open_array(para.vardef) or is_array_of_const(para.vardef) then if is_open_array(para.vardef) or is_array_of_const(para.vardef) then
write_rtti_reference(tcb,tarraydef(para.vardef).elementdef,fullrtti) write_rtti_reference(tcb,tarraydef(para.vardef).elementdef,fullrtti)
else if para.vardef=cformaltype then else if para.vardef=cformaltype then
write_rtti_reference(tcb,nil,fullrtti) write_rtti_reference(tcb,nil,fullrtti)
else else
write_rtti_reference(tcb,para.vardef,fullrtti); write_rtti_reference(tcb,para.vardef,fullrtti);
maybe_add_comment(tcb,#9'flags');
write_param_flag(tcb,para); write_param_flag(tcb,para);
maybe_add_comment(tcb,#9'name');
tcb.emit_pooled_shortstring_const_ref(para.realname); tcb.emit_pooled_shortstring_const_ref(para.realname);
maybe_add_comment(tcb,#9'locs');
write_paralocs(tcb,@para.paraloc[callerside]); write_paralocs(tcb,@para.paraloc[callerside]);
tcb.end_anonymous_record; tcb.end_anonymous_record;
maybe_add_comment(tcb,'RTTI: end param '+para.prettyname);
end; end;
if not is_void(def.returndef) then if not is_void(def.returndef) then
begin
maybe_add_comment(tcb,#9'return loc');
write_paralocs(tcb,@def.funcretloc[callerside]); write_paralocs(tcb,@def.funcretloc[callerside]);
end;
tcb.end_anonymous_record; tcb.end_anonymous_record;
end; end;
@ -286,6 +310,7 @@ implementation
end; end;
tcb.end_anonymous_record; tcb.end_anonymous_record;
maybe_add_comment(tcb,'RTTI: end methods');
end; end;
@ -628,8 +653,10 @@ implementation
for i:=0 to fields.count-1 do for i:=0 to fields.count-1 do
begin begin
sym:=tsym(fields[i]); sym:=tsym(fields[i]);
maybe_add_comment(tcb,'RTTI begin field '+tostr(i)+': '+sym.prettyname);
write_rtti_reference(tcb,tfieldvarsym(sym).vardef,rt); write_rtti_reference(tcb,tfieldvarsym(sym).vardef,rt);
tcb.emit_ord_const(tfieldvarsym(sym).fieldoffset,sizeuinttype); tcb.emit_ord_const(tfieldvarsym(sym).fieldoffset,sizeuinttype);
maybe_add_comment(tcb,'RTTI end field '+tostr(i)+': '+sym.prettyname);
end; end;
fields.free; fields.free;
end; end;
@ -880,6 +907,7 @@ implementation
propdefname:=''; propdefname:='';
{ TPropInfo is a packed record (even on targets that require { TPropInfo is a packed record (even on targets that require
alignment), but it starts aligned } alignment), but it starts aligned }
maybe_add_comment(tcb,'RTTI: begin property '+sym.prettyname);
tcb.begin_anonymous_record( tcb.begin_anonymous_record(
propdefname, propdefname,
1,min(reqalign,SizeOf(PInt)), 1,min(reqalign,SizeOf(PInt)),
@ -888,10 +916,14 @@ implementation
proctypesinfo:=$40 proctypesinfo:=$40
else else
proctypesinfo:=0; proctypesinfo:=0;
maybe_add_comment(tcb,#9'type info');
write_rtti_reference(tcb,tpropertysym(sym).propdef,fullrtti); write_rtti_reference(tcb,tpropertysym(sym).propdef,fullrtti);
maybe_add_comment(tcb,#9'read access');
writeaccessproc(palt_read,0,0); writeaccessproc(palt_read,0,0);
maybe_add_comment(tcb,#9'write access');
writeaccessproc(palt_write,2,0); writeaccessproc(palt_write,2,0);
{ is it stored ? } { is it stored ? }
maybe_add_comment(tcb,#9'stored ?');
if not(ppo_stored in tpropertysym(sym).propoptions) then if not(ppo_stored in tpropertysym(sym).propoptions) then
begin begin
{ no, so put a constant zero } { no, so put a constant zero }
@ -900,21 +932,28 @@ implementation
end end
else else
writeaccessproc(palt_stored,4,1); { maybe; if no procedure put a constant 1 (=true) } writeaccessproc(palt_stored,4,1); { maybe; if no procedure put a constant 1 (=true) }
maybe_add_comment(tcb,#9'index');
tcb.emit_ord_const(tpropertysym(sym).index,u32inttype); tcb.emit_ord_const(tpropertysym(sym).index,u32inttype);
maybe_add_comment(tcb,#9'default');
tcb.emit_ord_const(tpropertysym(sym).default,u32inttype); tcb.emit_ord_const(tpropertysym(sym).default,u32inttype);
maybe_add_comment(tcb,#9'property index');
propnameitem:=TPropNameListItem(propnamelist.Find(tpropertysym(sym).name)); propnameitem:=TPropNameListItem(propnamelist.Find(tpropertysym(sym).name));
if not assigned(propnameitem) then if not assigned(propnameitem) then
internalerror(200512201); internalerror(200512201);
tcb.emit_ord_const(propnameitem.propindex,u16inttype); tcb.emit_ord_const(propnameitem.propindex,u16inttype);
maybe_add_comment(tcb,#9'proc types');
tcb.emit_ord_const(proctypesinfo,u8inttype); tcb.emit_ord_const(proctypesinfo,u8inttype);
{ write reference to attribute table } { write reference to attribute table }
maybe_add_comment(tcb,#9'attributes');
write_attribute_data(tcb,tpropertysym(sym).rtti_attribute_list); write_attribute_data(tcb,tpropertysym(sym).rtti_attribute_list);
{ Write property name } { Write property name }
maybe_add_comment(tcb,#9'name');
tcb.emit_shortstring_const(tpropertysym(sym).realname); tcb.emit_shortstring_const(tpropertysym(sym).realname);
tcb.end_anonymous_record; tcb.end_anonymous_record;
maybe_add_comment(tcb,'RTTI: end property '+sym.prettyname);
end; end;
end; end;
tcb.end_anonymous_record; tcb.end_anonymous_record;
@ -1571,6 +1610,7 @@ implementation
procedure objectdef_rtti_fields(def:tobjectdef); procedure objectdef_rtti_fields(def:tobjectdef);
begin begin
maybe_add_comment(tcb,'RTTI begin fields '+def.objname^);
tcb.begin_anonymous_record('',defaultpacking,reqalign, tcb.begin_anonymous_record('',defaultpacking,reqalign,
targetinfos[target_info.system]^.alignment.recordalignmin); targetinfos[target_info.system]^.alignment.recordalignmin);
@ -1605,6 +1645,7 @@ implementation
fields_write_rtti_data(tcb,def,rt); fields_write_rtti_data(tcb,def,rt);
tcb.end_anonymous_record; tcb.end_anonymous_record;
maybe_add_comment(tcb,'RTTI end fields '+def.objname^);
end; end;
procedure objectdef_rtti_interface_init(def:tobjectdef); procedure objectdef_rtti_interface_init(def:tobjectdef);
@ -1624,27 +1665,37 @@ implementation
targetinfos[target_info.system]^.alignment.recordalignmin); targetinfos[target_info.system]^.alignment.recordalignmin);
if not is_objectpascal_helper(def) then if not is_objectpascal_helper(def) then
begin
maybe_add_comment(tcb,#9'Parent type info');
if (oo_has_vmt in def.objectoptions) then if (oo_has_vmt in def.objectoptions) then
tcb.emit_tai( tcb.emit_tai(
Tai_const.Createname(def.vmt_mangledname,AT_DATA_FORCEINDIRECT,0), Tai_const.Createname(def.vmt_mangledname,AT_DATA_FORCEINDIRECT,0),
cpointerdef.getreusable(def.vmt_def)) cpointerdef.getreusable(def.vmt_def))
else else
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype); tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
end;
{ write parent typeinfo } { write parent typeinfo }
maybe_add_comment(tcb,#9'Parent type info');
write_rtti_reference(tcb,def.childof,fullrtti); write_rtti_reference(tcb,def.childof,fullrtti);
{ write typeinfo of extended type } { write typeinfo of extended type }
if is_objectpascal_helper(def) then if is_objectpascal_helper(def) then
if assigned(def.extendeddef) then if assigned(def.extendeddef) then
begin
maybe_add_comment(tcb,#9'helper for type info');
write_rtti_reference(tcb,def.extendeddef,fullrtti) write_rtti_reference(tcb,def.extendeddef,fullrtti)
end
else else
InternalError(2011033001); InternalError(2011033001);
{ total number of unique properties } { total number of unique properties }
maybe_add_comment(tcb,#9'Number of properties');
tcb.emit_ord_const(propnamelist.count,u16inttype); tcb.emit_ord_const(propnamelist.count,u16inttype);
{ write unit name } { write unit name }
maybe_add_comment(tcb, #9'Unit name');
tcb.emit_shortstring_const(current_module.realmodulename^); tcb.emit_shortstring_const(current_module.realmodulename^);
{ write published properties for this object } { write published properties for this object }
@ -2256,8 +2307,10 @@ implementation
end; end;
procedure TRTTIWriter.write_rtti(def:tdef;rt:trttitype); procedure TRTTIWriter.write_rtti(def:tdef;rt:trttitype);
var var
tcb: ttai_typedconstbuilder; tcb: ttai_typedconstbuilder;
opts : ttcasmlistoptions;
rttilab: tasmsymbol; rttilab: tasmsymbol;
rttidef: tdef; rttidef: tdef;
s: TIDString; s: TIDString;
@ -2272,11 +2325,14 @@ implementation
if rttidefstate[rt] in def.defstates then if rttidefstate[rt] in def.defstates then
exit; exit;
include(def.defstates,rttidefstate[rt]); include(def.defstates,rttidefstate[rt]);
{ write first all dependencies } { write first all dependencies }
write_child_rtti_data(def,rt); write_child_rtti_data(def,rt);
{ write rtti data } { write rtti data }
tcb:=ctai_typedconstbuilder.create([tcalo_make_dead_strippable,tcalo_data_force_indirect]); tcb:=ctai_typedconstbuilder.create([tcalo_make_dead_strippable,tcalo_data_force_indirect]);
s:=internaltypeprefixName[itp_rttidef]+tstoreddef(def).rtti_mangledname(rt); s:=internaltypeprefixName[itp_rttidef]+tstoreddef(def).rtti_mangledname(rt);
maybe_add_comment(tcb,'RTTI: begin '+def.GetTypeName+' ('+rttitypenames[rt]+')');
tcb.begin_anonymous_record( tcb.begin_anonymous_record(
s, s,
defaultpacking,reqalign, defaultpacking,reqalign,
@ -2284,6 +2340,7 @@ implementation
); );
write_rtti_data(tcb,def,rt); write_rtti_data(tcb,def,rt);
rttidef:=tcb.end_anonymous_record; rttidef:=tcb.end_anonymous_record;
maybe_add_comment(tcb,'RTTI: end '+def.GetTypeName+' ('+rttitypenames[rt]+')');
rttilab:=current_asmdata.DefineAsmSymbol(tstoreddef(def).rtti_mangledname(rt),AB_GLOBAL,AT_DATA_NOINDIRECT,rttidef); rttilab:=current_asmdata.DefineAsmSymbol(tstoreddef(def).rtti_mangledname(rt),AB_GLOBAL,AT_DATA_NOINDIRECT,rttidef);
current_asmdata.AsmLists[al_rtti].concatList( current_asmdata.AsmLists[al_rtti].concatList(
tcb.get_final_asmlist(rttilab,rttidef,sec_rodata,rttilab.name,min(target_info.alignment.maxCrecordalign,SizeOf(QWord)))); tcb.get_final_asmlist(rttilab,rttidef,sec_rodata,rttilab.name,min(target_info.alignment.maxCrecordalign,SizeOf(QWord))));
@ -2295,9 +2352,16 @@ implementation
write_rtti_extrasyms(def,rt,rttilab); write_rtti_extrasyms(def,rt,rttilab);
end; end;
procedure TRTTIWriter.maybe_add_comment(tcb:ttai_typedconstbuilder;const comment : string);
begin
if addcomments then
tcb.emit_comment(comment);
end;
constructor TRTTIWriter.create; constructor TRTTIWriter.create;
begin begin
addcomments:=cs_asm_rtti_source in current_settings.globalswitches;
if tf_requires_proper_alignment in target_info.flags then if tf_requires_proper_alignment in target_info.flags then
begin begin
reqalign:=min(sizeof(QWord),target_info.alignment.maxCrecordalign); reqalign:=min(sizeof(QWord),target_info.alignment.maxCrecordalign);