|
@@ -50,9 +50,10 @@ interface
|
|
procedure methods_write_rtti(st:tsymtable;rt:trttitype;visibilities:tvisibilities;allow_hidden:boolean);
|
|
procedure methods_write_rtti(st:tsymtable;rt:trttitype;visibilities:tvisibilities;allow_hidden:boolean);
|
|
procedure write_rtti_extrasyms(def:Tdef;rt:Trttitype;mainrtti:Tasmsymbol);
|
|
procedure write_rtti_extrasyms(def:Tdef;rt:Trttitype;mainrtti:Tasmsymbol);
|
|
procedure published_write_rtti(st:tsymtable;rt:trttitype);
|
|
procedure published_write_rtti(st:tsymtable;rt:trttitype);
|
|
- function published_properties_count(st:tsymtable):longint;
|
|
|
|
- procedure published_properties_write_rtti_data(tcb: ttai_typedconstbuilder; propnamelist: TFPHashObjectList; st: tsymtable);
|
|
|
|
- procedure collect_propnamelist(propnamelist:TFPHashObjectList;objdef:tobjectdef);
|
|
|
|
|
|
+ procedure properties_write_rtti_data(tcb:ttai_typedconstbuilder;propnamelist:TFPHashObjectList;st:tsymtable;extended_rtti:boolean;visibilities:tvisibilities);
|
|
|
|
+ procedure write_extended_method_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef;packrecords:longint);
|
|
|
|
+ procedure write_extended_field_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef;packrecords:longint);
|
|
|
|
+ procedure collect_propnamelist(propnamelist:TFPHashObjectList;def:tabstractrecorddef;visibilities:tvisibilities);
|
|
{ only use a direct reference if the referenced type can *only* reside
|
|
{ only use a direct reference if the referenced type can *only* reside
|
|
in the same unit as the current one }
|
|
in the same unit as the current one }
|
|
function ref_rtti(def:tdef;rt:trttitype;indirect:boolean;suffix:tsymstr):tasmsymbol;
|
|
function ref_rtti(def:tdef;rt:trttitype;indirect:boolean;suffix:tsymstr):tasmsymbol;
|
|
@@ -62,7 +63,7 @@ interface
|
|
procedure write_attribute_data(tcb: ttai_typedconstbuilder;attr_list:trtti_attribute_list);
|
|
procedure write_attribute_data(tcb: ttai_typedconstbuilder;attr_list:trtti_attribute_list);
|
|
procedure write_child_rtti_data(def:tdef;rt:trttitype);
|
|
procedure write_child_rtti_data(def:tdef;rt:trttitype);
|
|
procedure write_rtti_reference(tcb: ttai_typedconstbuilder; def: tdef; rt: trttitype);
|
|
procedure write_rtti_reference(tcb: ttai_typedconstbuilder; def: tdef; rt: trttitype);
|
|
- procedure write_methods(tcb:ttai_typedconstbuilder;st:tsymtable;visibilities:tvisibilities);
|
|
|
|
|
|
+ procedure write_methods(tcb:ttai_typedconstbuilder;st:tsymtable;extended_rtti:boolean;visibilities:tvisibilities);
|
|
procedure write_header(tcb: ttai_typedconstbuilder; def: tdef; typekind: byte);
|
|
procedure write_header(tcb: ttai_typedconstbuilder; def: tdef; typekind: byte);
|
|
function write_methodkind(tcb:ttai_typedconstbuilder;def:tabstractprocdef):byte;
|
|
function write_methodkind(tcb:ttai_typedconstbuilder;def:tabstractprocdef):byte;
|
|
procedure write_callconv(tcb:ttai_typedconstbuilder;def:tabstractprocdef);
|
|
procedure write_callconv(tcb:ttai_typedconstbuilder;def:tabstractprocdef);
|
|
@@ -73,6 +74,8 @@ interface
|
|
public
|
|
public
|
|
constructor create;
|
|
constructor create;
|
|
procedure write_rtti(def:tdef;rt:trttitype);
|
|
procedure write_rtti(def:tdef;rt:trttitype);
|
|
|
|
+ procedure write_extended_method_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef); inline;
|
|
|
|
+ procedure write_extended_field_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef); inline;
|
|
function get_rtti_label(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol; inline;
|
|
function get_rtti_label(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol; inline;
|
|
function get_rtti_label_ord2str(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol; inline;
|
|
function get_rtti_label_ord2str(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol; inline;
|
|
function get_rtti_label_str2ord(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol; inline;
|
|
function get_rtti_label_str2ord(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol; inline;
|
|
@@ -117,6 +120,35 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
+ function visibility_to_rtti_flags(vis: tvisibility): byte;
|
|
|
|
+ begin
|
|
|
|
+ case vis of
|
|
|
|
+ vis_private:
|
|
|
|
+ result:=byte(rv_private);
|
|
|
|
+ vis_strictprivate:
|
|
|
|
+ begin
|
|
|
|
+ result:=byte(rv_private);
|
|
|
|
+ // add bit to indicate "strict"
|
|
|
|
+ result:=result or (1 shl 2);
|
|
|
|
+ end;
|
|
|
|
+ vis_protected:
|
|
|
|
+ result:=byte(rv_protected);
|
|
|
|
+ vis_strictprotected:
|
|
|
|
+ begin
|
|
|
|
+ result:=byte(rv_protected);
|
|
|
|
+ // add bit to indicate "strict"
|
|
|
|
+ result:=result or (1 shl 2);
|
|
|
|
+ end;
|
|
|
|
+ vis_public:
|
|
|
|
+ result:=byte(rv_public);
|
|
|
|
+ vis_published:
|
|
|
|
+ result:=byte(rv_published);
|
|
|
|
+ otherwise
|
|
|
|
+ internalerror(2021061301);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
procedure write_persistent_type_info(st: tsymtable; is_global: boolean);
|
|
procedure write_persistent_type_info(st: tsymtable; is_global: boolean);
|
|
var
|
|
var
|
|
i : longint;
|
|
i : longint;
|
|
@@ -207,11 +239,12 @@ implementation
|
|
result:=ref_rtti(def,rt,indirect,'_s2o');
|
|
result:=ref_rtti(def,rt,indirect,'_s2o');
|
|
end;
|
|
end;
|
|
|
|
|
|
- procedure TRTTIWriter.write_methods(tcb:ttai_typedconstbuilder;st:tsymtable;visibilities:tvisibilities);
|
|
|
|
|
|
+ procedure TRTTIWriter.write_methods(tcb:ttai_typedconstbuilder;st:tsymtable;extended_rtti:boolean;visibilities:tvisibilities);
|
|
var
|
|
var
|
|
rtticount,
|
|
rtticount,
|
|
totalcount,
|
|
totalcount,
|
|
i,j,k : longint;
|
|
i,j,k : longint;
|
|
|
|
+ vmt_index : integer;
|
|
sym : tprocsym;
|
|
sym : tprocsym;
|
|
def : tprocdef;
|
|
def : tprocdef;
|
|
para : tparavarsym;
|
|
para : tparavarsym;
|
|
@@ -232,88 +265,114 @@ implementation
|
|
inc(rtticount);
|
|
inc(rtticount);
|
|
end;
|
|
end;
|
|
|
|
|
|
- maybe_add_comment(tcb,#9'count');
|
|
|
|
- tcb.emit_ord_const(totalcount,u16inttype);
|
|
|
|
- maybe_add_comment(tcb,#9'RTTI count');
|
|
|
|
- if rtticount = 0 then
|
|
|
|
- tcb.emit_ord_const($FFFF,u16inttype)
|
|
|
|
- else
|
|
|
|
|
|
+ { write the count section for non-extended methods }
|
|
|
|
+ if not extended_rtti then
|
|
begin
|
|
begin
|
|
- tcb.emit_ord_const(rtticount,u16inttype);
|
|
|
|
-
|
|
|
|
- for i:=0 to st.symlist.count-1 do
|
|
|
|
- if tsym(st.symlist[i]).typ=procsym then
|
|
|
|
- begin
|
|
|
|
- sym:=tprocsym(st.symlist[i]);
|
|
|
|
- for j:=0 to sym.procdeflist.count-1 do
|
|
|
|
- begin
|
|
|
|
- def:=tprocdef(sym.procdeflist[j]);
|
|
|
|
-
|
|
|
|
- if not (def.visibility in visibilities) then
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- def.init_paraloc_info(callerside);
|
|
|
|
-
|
|
|
|
- maybe_add_comment(tcb,'RTTI: begin method '+def.fullprocname(false));
|
|
|
|
- tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
|
|
|
|
- targetinfos[target_info.system]^.alignment.recordalignmin);
|
|
|
|
-
|
|
|
|
- maybe_add_comment(tcb,#9'return type');
|
|
|
|
- write_rtti_reference(tcb,def.returndef,fullrtti);
|
|
|
|
- maybe_add_comment(tcb,#9'calling convention');
|
|
|
|
- write_callconv(tcb,def);
|
|
|
|
- maybe_add_comment(tcb,#9'method kind');
|
|
|
|
- write_methodkind(tcb,def);
|
|
|
|
- maybe_add_comment(tcb,#9'param count');
|
|
|
|
- tcb.emit_ord_const(def.paras.count,u16inttype);
|
|
|
|
- maybe_add_comment(tcb,#9'caller args size');
|
|
|
|
- tcb.emit_ord_const(def.callerargareasize,sizesinttype);
|
|
|
|
- maybe_add_comment(tcb,#9'invoke helper');
|
|
|
|
- if def.invoke_helper=nil then
|
|
|
|
- tcb.emit_tai(Tai_const.Create_nil_dataptr,voidcodepointertype)
|
|
|
|
- else
|
|
|
|
- tcb.emit_procdef_const(def.invoke_helper);
|
|
|
|
- maybe_add_comment(tcb,#9'name');
|
|
|
|
- tcb.emit_pooled_shortstring_const_ref(sym.realname);
|
|
|
|
-
|
|
|
|
- for k:=0 to def.paras.count-1 do
|
|
|
|
- begin
|
|
|
|
- para:=tparavarsym(def.paras[k]);
|
|
|
|
- maybe_add_comment(tcb,'RTTI: begin param '+para.prettyname);
|
|
|
|
- tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
|
|
|
|
- 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
|
|
|
|
- write_rtti_reference(tcb,tarraydef(para.vardef).elementdef,fullrtti)
|
|
|
|
- else if para.vardef=cformaltype then
|
|
|
|
- write_rtti_reference(tcb,nil,fullrtti)
|
|
|
|
- else
|
|
|
|
- write_rtti_reference(tcb,para.vardef,fullrtti);
|
|
|
|
- maybe_add_comment(tcb,#9'flags');
|
|
|
|
- write_param_flag(tcb,para);
|
|
|
|
-
|
|
|
|
- maybe_add_comment(tcb,#9'name');
|
|
|
|
- tcb.emit_pooled_shortstring_const_ref(para.realname);
|
|
|
|
-
|
|
|
|
- maybe_add_comment(tcb,#9'locs');
|
|
|
|
- write_paralocs(tcb,@para.paraloc[callerside]);
|
|
|
|
-
|
|
|
|
- tcb.end_anonymous_record;
|
|
|
|
- maybe_add_comment(tcb,'RTTI: end param '+para.prettyname);
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
- if not is_void(def.returndef) then
|
|
|
|
- begin
|
|
|
|
- maybe_add_comment(tcb,#9'return loc');
|
|
|
|
- write_paralocs(tcb,@def.funcretloc[callerside]);
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
- tcb.end_anonymous_record;
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
|
|
+ maybe_add_comment(tcb,#9'count');
|
|
|
|
+ tcb.emit_ord_const(totalcount,u16inttype);
|
|
|
|
+ maybe_add_comment(tcb,#9'RTTI count');
|
|
|
|
+ if rtticount=0 then
|
|
|
|
+ tcb.emit_ord_const($FFFF,u16inttype)
|
|
|
|
+ else
|
|
|
|
+ tcb.emit_ord_const(rtticount,u16inttype);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+ if rtticount>0 then
|
|
|
|
+ for i:=0 to st.symlist.count-1 do
|
|
|
|
+ if tsym(st.symlist[i]).typ=procsym then
|
|
|
|
+ begin
|
|
|
|
+ sym:=tprocsym(st.symlist[i]);
|
|
|
|
+ for j:=0 to sym.procdeflist.count-1 do
|
|
|
|
+ begin
|
|
|
|
+ def:=tprocdef(sym.procdeflist[j]);
|
|
|
|
+
|
|
|
|
+ if not (def.visibility in visibilities) then
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ def.init_paraloc_info(callerside);
|
|
|
|
+
|
|
|
|
+ maybe_add_comment(tcb,'RTTI: begin method '+def.fullprocname(false));
|
|
|
|
+ tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
|
|
|
|
+ targetinfos[target_info.system]^.alignment.recordalignmin);
|
|
|
|
+
|
|
|
|
+ maybe_add_comment(tcb,#9'return type');
|
|
|
|
+ write_rtti_reference(tcb,def.returndef,fullrtti);
|
|
|
|
+ maybe_add_comment(tcb,#9'calling convention');
|
|
|
|
+ write_callconv(tcb,def);
|
|
|
|
+ maybe_add_comment(tcb,#9'method kind');
|
|
|
|
+ write_methodkind(tcb,def);
|
|
|
|
+ maybe_add_comment(tcb,#9'param count');
|
|
|
|
+ tcb.emit_ord_const(def.paras.count,u16inttype);
|
|
|
|
+ maybe_add_comment(tcb,#9'caller args size');
|
|
|
|
+ tcb.emit_ord_const(def.callerargareasize,sizesinttype);
|
|
|
|
+ maybe_add_comment(tcb,#9'invoke helper');
|
|
|
|
+ if def.invoke_helper=nil then
|
|
|
|
+ tcb.emit_tai(Tai_const.Create_nil_dataptr,voidcodepointertype)
|
|
|
|
+ else
|
|
|
|
+ tcb.emit_procdef_const(def.invoke_helper);
|
|
|
|
+ maybe_add_comment(tcb,#9'name');
|
|
|
|
+ tcb.emit_pooled_shortstring_const_ref(sym.realname);
|
|
|
|
+
|
|
|
|
+ if extended_rtti then
|
|
|
|
+ begin
|
|
|
|
+ { write visibility section for extended RTTI }
|
|
|
|
+ maybe_add_comment(tcb,#9'visibility');
|
|
|
|
+ tcb.emit_ord_const(visibility_to_rtti_flags(def.visibility),u8inttype);
|
|
|
|
+ { for classes write a VMT index }
|
|
|
|
+ if st.defowner.typ=objectdef then
|
|
|
|
+ begin
|
|
|
|
+ vmt_index:=-1;
|
|
|
|
+ if po_virtualmethod in def.procoptions then
|
|
|
|
+ for k:=0 to tobjectdef(st.defowner).vmtentries.count-1 do
|
|
|
|
+ if pvmtentry(tobjectdef(st.defowner).vmtentries[k])^.procdef=def then
|
|
|
|
+ begin
|
|
|
|
+ vmt_index:=k;
|
|
|
|
+ break;
|
|
|
|
+ end;
|
|
|
|
+ maybe_add_comment(tcb,#9'VMT index');
|
|
|
|
+ tcb.emit_ord_const(vmt_index,s16inttype);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ for k:=0 to def.paras.count-1 do
|
|
|
|
+ begin
|
|
|
|
+ para:=tparavarsym(def.paras[k]);
|
|
|
|
+
|
|
|
|
+ maybe_add_comment(tcb,'RTTI: begin param '+para.prettyname);
|
|
|
|
+ tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
|
|
|
|
+ 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
|
|
|
|
+ write_rtti_reference(tcb,tarraydef(para.vardef).elementdef,fullrtti)
|
|
|
|
+ else if para.vardef=cformaltype then
|
|
|
|
+ write_rtti_reference(tcb,nil,fullrtti)
|
|
|
|
+ else
|
|
|
|
+ write_rtti_reference(tcb,para.vardef,fullrtti);
|
|
|
|
+ maybe_add_comment(tcb,#9'flags');
|
|
|
|
+ write_param_flag(tcb,para);
|
|
|
|
+
|
|
|
|
+ maybe_add_comment(tcb,#9'name');
|
|
|
|
+ tcb.emit_pooled_shortstring_const_ref(para.realname);
|
|
|
|
+
|
|
|
|
+ maybe_add_comment(tcb,#9'locs');
|
|
|
|
+ write_paralocs(tcb,@para.paraloc[callerside]);
|
|
|
|
+
|
|
|
|
+ tcb.end_anonymous_record;
|
|
|
|
+ maybe_add_comment(tcb,'RTTI: end param '+para.prettyname);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ if not is_void(def.returndef) then
|
|
|
|
+ begin
|
|
|
|
+ maybe_add_comment(tcb,#9'return loc');
|
|
|
|
+ write_paralocs(tcb,@def.funcretloc[callerside]);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ tcb.end_anonymous_record;
|
|
|
|
+ maybe_add_comment(tcb,'RTTI: end method '+def.fullprocname(false));
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
tcb.end_anonymous_record;
|
|
tcb.end_anonymous_record;
|
|
maybe_add_comment(tcb,'RTTI: end methods');
|
|
maybe_add_comment(tcb,'RTTI: end methods');
|
|
end;
|
|
end;
|
|
@@ -724,6 +783,97 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
+ procedure TRTTIWriter.write_extended_method_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef;packrecords:longint);
|
|
|
|
+ var
|
|
|
|
+ methodcount,
|
|
|
|
+ i, j: longint;
|
|
|
|
+ sym: tprocsym;
|
|
|
|
+ begin
|
|
|
|
+ { count methods }
|
|
|
|
+ methodcount:=0;
|
|
|
|
+ for i:=0 to def.symtable.symlist.count-1 do
|
|
|
|
+ if tsym(def.symtable.symlist[i]).typ=procsym then
|
|
|
|
+ begin
|
|
|
|
+ sym:=tprocsym(def.symtable.symlist[i]);
|
|
|
|
+ for j:=0 to sym.procdeflist.count-1 do
|
|
|
|
+ if def.is_visible_for_rtti(ro_methods,tprocdef(sym.procdeflist[j]).visibility) then
|
|
|
|
+ inc(methodcount);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ tcb.begin_anonymous_record('',packrecords,min(reqalign,SizeOf(PInt)),
|
|
|
|
+ targetinfos[target_info.system]^.alignment.recordalignmin);
|
|
|
|
+ { emit method count }
|
|
|
|
+ tcb.emit_ord_const(methodcount,u16inttype);
|
|
|
|
+ { emit method entries (array) }
|
|
|
|
+ if methodcount>0 then
|
|
|
|
+ write_methods(tcb,def.symtable,true,def.rtti_visibilities_for_option(ro_methods));
|
|
|
|
+ tcb.end_anonymous_record;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ procedure TRTTIWriter.write_extended_method_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef);
|
|
|
|
+ begin
|
|
|
|
+ write_extended_method_table(tcb,def,defaultpacking);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ procedure TRTTIWriter.write_extended_field_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef;packrecords:longint);
|
|
|
|
+ var
|
|
|
|
+ i: integer;
|
|
|
|
+ sym: tsym;
|
|
|
|
+ list: TFPList;
|
|
|
|
+ begin
|
|
|
|
+ list:=TFPList.Create;
|
|
|
|
+ { build list of visible fields }
|
|
|
|
+ for i:=0 to def.symtable.symlist.Count-1 do
|
|
|
|
+ begin
|
|
|
|
+ sym:=tsym(def.symtable.symlist[i]);
|
|
|
|
+ if (sym.typ=fieldvarsym) and
|
|
|
|
+ not(sp_static in sym.symoptions) and
|
|
|
|
+ def.is_visible_for_rtti(ro_fields, sym.visibility) then
|
|
|
|
+ list.add(sym);
|
|
|
|
+ end;
|
|
|
|
+ {
|
|
|
|
+ TExtendedFieldTable = record
|
|
|
|
+ FieldCount: Word;
|
|
|
|
+ Fields: array[0..0] of TExtendedFieldInfo;
|
|
|
|
+ end;
|
|
|
|
+ }
|
|
|
|
+ tcb.begin_anonymous_record(internaltypeprefixName[itp_extended_rtti_table]+tostr(list.count),packrecords,min(reqalign,SizeOf(PInt)),targetinfos[target_info.system]^.alignment.recordalignmin);
|
|
|
|
+ tcb.emit_ord_const(list.count,u16inttype);
|
|
|
|
+ for i := 0 to list.count-1 do
|
|
|
|
+ begin
|
|
|
|
+ sym:=tsym(list[i]);
|
|
|
|
+ {
|
|
|
|
+ TExtendedFieldInfo = record
|
|
|
|
+ FieldOffset: SizeUInt;
|
|
|
|
+ FieldType: Pointer;
|
|
|
|
+ FieldVisibility: Byte;
|
|
|
|
+ Name: PShortString;
|
|
|
|
+ end;
|
|
|
|
+ }
|
|
|
|
+ tcb.begin_anonymous_record(internaltypeprefixName[itp_extended_rtti_field]+tostr(tfieldvarsym(sym).fieldoffset),packrecords,min(reqalign,SizeOf(PInt)),targetinfos[target_info.system]^.alignment.recordalignmin);
|
|
|
|
+ { FieldOffset }
|
|
|
|
+ tcb.emit_tai(Tai_const.Create_sizeint(tfieldvarsym(sym).fieldoffset),sizeuinttype);
|
|
|
|
+ { FieldType: PPTypeInfo }
|
|
|
|
+ tcb.emit_tai(Tai_const.Create_sym(RTTIWriter.get_rtti_label(tfieldvarsym(sym).vardef,fullrtti,true)),voidpointertype);
|
|
|
|
+ { FieldVisibility }
|
|
|
|
+ tcb.emit_ord_const(visibility_to_rtti_flags(tfieldvarsym(sym).visibility),u8inttype);
|
|
|
|
+ { Name }
|
|
|
|
+ tcb.emit_pooled_shortstring_const_ref(sym.realname);
|
|
|
|
+ tcb.end_anonymous_record;
|
|
|
|
+ end;
|
|
|
|
+ tcb.end_anonymous_record;
|
|
|
|
+ list.free;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ procedure TRTTIWriter.write_extended_field_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef);
|
|
|
|
+ begin
|
|
|
|
+ write_extended_field_table(tcb,def,defaultpacking);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
procedure TRTTIWriter.published_write_rtti(st:tsymtable;rt:trttitype);
|
|
procedure TRTTIWriter.published_write_rtti(st:tsymtable;rt:trttitype);
|
|
var
|
|
var
|
|
i : longint;
|
|
i : longint;
|
|
@@ -747,35 +897,23 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
- function TRTTIWriter.published_properties_count(st:tsymtable):longint;
|
|
|
|
|
|
+ procedure TRTTIWriter.collect_propnamelist(propnamelist:TFPHashObjectList;def:tabstractrecorddef;visibilities:tvisibilities);
|
|
var
|
|
var
|
|
i : longint;
|
|
i : longint;
|
|
sym : tsym;
|
|
sym : tsym;
|
|
|
|
+ pn : tpropnamelistitem;
|
|
begin
|
|
begin
|
|
- result:=0;
|
|
|
|
- for i:=0 to st.SymList.Count-1 do
|
|
|
|
|
|
+ { search into parent for objects }
|
|
|
|
+ if def.typ=objectdef then
|
|
begin
|
|
begin
|
|
- sym:=tsym(st.SymList[i]);
|
|
|
|
- if (tsym(sym).typ=propertysym) and
|
|
|
|
- (sym.visibility=vis_published) then
|
|
|
|
- inc(result);
|
|
|
|
|
|
+ if assigned(tobjectdef(def).childof) then
|
|
|
|
+ collect_propnamelist(propnamelist,tobjectdef(def).childof,visibilities);
|
|
end;
|
|
end;
|
|
- end;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- procedure TRTTIWriter.collect_propnamelist(propnamelist:TFPHashObjectList;objdef:tobjectdef);
|
|
|
|
- var
|
|
|
|
- i : longint;
|
|
|
|
- sym : tsym;
|
|
|
|
- pn : tpropnamelistitem;
|
|
|
|
- begin
|
|
|
|
- if assigned(objdef.childof) then
|
|
|
|
- collect_propnamelist(propnamelist,objdef.childof);
|
|
|
|
- for i:=0 to objdef.symtable.SymList.Count-1 do
|
|
|
|
|
|
+ for i:=0 to def.symtable.SymList.Count-1 do
|
|
begin
|
|
begin
|
|
- sym:=tsym(objdef.symtable.SymList[i]);
|
|
|
|
|
|
+ sym:=tsym(def.symtable.SymList[i]);
|
|
if (tsym(sym).typ=propertysym) and
|
|
if (tsym(sym).typ=propertysym) and
|
|
- (sym.visibility=vis_published) then
|
|
|
|
|
|
+ (sym.visibility in visibilities) then
|
|
begin
|
|
begin
|
|
pn:=TPropNameListItem(propnamelist.Find(tsym(sym).name));
|
|
pn:=TPropNameListItem(propnamelist.Find(tsym(sym).name));
|
|
if not assigned(pn) then
|
|
if not assigned(pn) then
|
|
@@ -789,15 +927,18 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
- procedure TRTTIWriter.published_properties_write_rtti_data(tcb: ttai_typedconstbuilder; propnamelist:TFPHashObjectList;st:tsymtable);
|
|
|
|
|
|
+ procedure TRTTIWriter.properties_write_rtti_data(tcb: ttai_typedconstbuilder; propnamelist:TFPHashObjectList; st:tsymtable; extended_rtti:boolean; visibilities:tvisibilities);
|
|
var
|
|
var
|
|
i : longint;
|
|
i : longint;
|
|
sym : tsym;
|
|
sym : tsym;
|
|
proctypesinfo : byte;
|
|
proctypesinfo : byte;
|
|
propnameitem : tpropnamelistitem;
|
|
propnameitem : tpropnamelistitem;
|
|
propdefname : string;
|
|
propdefname : string;
|
|
|
|
+ tbltcb : ttai_typedconstbuilder;
|
|
|
|
+ tbllab : tasmlabel;
|
|
|
|
+ tbldef : tdef;
|
|
|
|
|
|
- procedure writeaccessproc(pap:tpropaccesslisttypes; shiftvalue : byte; unsetvalue: byte);
|
|
|
|
|
|
+ procedure writeaccessproc(tcb: ttai_typedconstbuilder; pap:tpropaccesslisttypes; shiftvalue : byte; unsetvalue: byte);
|
|
var
|
|
var
|
|
typvalue : byte;
|
|
typvalue : byte;
|
|
hp : ppropaccesslistitem;
|
|
hp : ppropaccesslistitem;
|
|
@@ -893,73 +1034,134 @@ implementation
|
|
proctypesinfo:=proctypesinfo or (typvalue shl shiftvalue);
|
|
proctypesinfo:=proctypesinfo or (typvalue shl shiftvalue);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+ function properties_count(st:tsymtable):longint;
|
|
|
|
+ var
|
|
|
|
+ i : longint;
|
|
|
|
+ sym : tsym;
|
|
|
|
+ begin
|
|
|
|
+ result:=0;
|
|
|
|
+ for i:=0 to st.SymList.Count-1 do
|
|
|
|
+ begin
|
|
|
|
+ sym:=tsym(st.SymList[i]);
|
|
|
|
+ if (tsym(sym).typ=propertysym) and
|
|
|
|
+ (sym.visibility in visibilities) then
|
|
|
|
+ inc(result);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ function write_propinfo_data(tcb: ttai_typedconstbuilder; sym: tpropertysym): tdef;
|
|
|
|
+ begin
|
|
|
|
+ { we can only easily reuse defs if the property is not stored,
|
|
|
|
+ because otherwise the rtti layout depends on how the "stored"
|
|
|
|
+ is defined (field, indexed expression, virtual method, ...) }
|
|
|
|
+ if not(ppo_stored in sym.propoptions) then
|
|
|
|
+ propdefname:=internaltypeprefixName[itp_rtti_prop]+tostr(length(sym.realname))
|
|
|
|
+ else
|
|
|
|
+ propdefname:='';
|
|
|
|
+ { TPropInfo is a packed record (even on targets that require
|
|
|
|
+ alignment), but it starts aligned }
|
|
|
|
+ if addcomments then
|
|
|
|
+ tcb.emit_comment('RTTI: begin propinfo record '+sym.realname);
|
|
|
|
+ tcb.begin_anonymous_record(
|
|
|
|
+ propdefname,
|
|
|
|
+ 1,min(reqalign,SizeOf(PInt)),
|
|
|
|
+ targetinfos[target_info.system]^.alignment.recordalignmin);
|
|
|
|
+ if ppo_indexed in sym.propoptions then
|
|
|
|
+ proctypesinfo:=$40
|
|
|
|
+ else
|
|
|
|
+ proctypesinfo:=0;
|
|
|
|
+ if addcomments then
|
|
|
|
+ tcb.emit_comment(#9'type info');
|
|
|
|
+ write_rtti_reference(tcb,sym.propdef,fullrtti);
|
|
|
|
+ if addcomments then
|
|
|
|
+ tcb.emit_comment(#9'read access');
|
|
|
|
+ writeaccessproc(tcb,palt_read,0,0);
|
|
|
|
+ if addcomments then
|
|
|
|
+ tcb.emit_comment(#9'write access');
|
|
|
|
+ writeaccessproc(tcb,palt_write,2,0);
|
|
|
|
+ { is it stored ? }
|
|
|
|
+ if addcomments then
|
|
|
|
+ tcb.emit_comment(#9'stored ?');
|
|
|
|
+ if not(ppo_stored in sym.propoptions) then
|
|
|
|
+ begin
|
|
|
|
+ { no, so put a constant zero }
|
|
|
|
+ tcb.emit_tai(Tai_const.Create_nil_codeptr,codeptruinttype);
|
|
|
|
+ proctypesinfo:=proctypesinfo or (3 shl 4);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ writeaccessproc(tcb,palt_stored,4,1); { maybe; if no procedure put a constant 1 (=true) }
|
|
|
|
+ if addcomments then
|
|
|
|
+ tcb.emit_comment(#9'Index');
|
|
|
|
+ tcb.emit_ord_const(sym.index,u32inttype);
|
|
|
|
+ if addcomments then
|
|
|
|
+ tcb.emit_comment(#9'default');
|
|
|
|
+ tcb.emit_ord_const(sym.default,u32inttype);
|
|
|
|
+ propnameitem:=TPropNameListItem(propnamelist.Find(sym.name));
|
|
|
|
+ if not assigned(propnameitem) then
|
|
|
|
+ internalerror(200512201);
|
|
|
|
+ if addcomments then
|
|
|
|
+ tcb.emit_comment(#9'property index');
|
|
|
|
+ tcb.emit_ord_const(propnameitem.propindex,u16inttype);
|
|
|
|
+ if addcomments then
|
|
|
|
+ tcb.emit_comment(#9'proc types');
|
|
|
|
+ tcb.emit_ord_const(proctypesinfo,u8inttype);
|
|
|
|
+ { write reference to attribute table }
|
|
|
|
+ if addcomments then
|
|
|
|
+ tcb.emit_comment(#9'attributes');
|
|
|
|
+ write_attribute_data(tcb,sym.rtti_attribute_list);
|
|
|
|
+ { write property name }
|
|
|
|
+ if addcomments then
|
|
|
|
+ tcb.emit_comment(#9'name');
|
|
|
|
+ tcb.emit_shortstring_const(sym.realname);
|
|
|
|
+ result:=tcb.end_anonymous_record;
|
|
|
|
+ if addcomments then
|
|
|
|
+ tcb.emit_comment('RTTI: End propinfo record '+sym.realname);
|
|
|
|
+ end;
|
|
|
|
+
|
|
begin
|
|
begin
|
|
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);
|
|
- tcb.emit_ord_const(published_properties_count(st),u16inttype);
|
|
|
|
|
|
+ tcb.emit_ord_const(properties_count(st),u16inttype);
|
|
for i:=0 to st.SymList.Count-1 do
|
|
for i:=0 to st.SymList.Count-1 do
|
|
begin
|
|
begin
|
|
sym:=tsym(st.SymList[i]);
|
|
sym:=tsym(st.SymList[i]);
|
|
if (sym.typ=propertysym) and
|
|
if (sym.typ=propertysym) and
|
|
- (sym.visibility=vis_published) then
|
|
|
|
|
|
+ (sym.visibility in visibilities) then
|
|
begin
|
|
begin
|
|
- { we can only easily reuse defs if the property is not stored,
|
|
|
|
- because otherwise the rtti layout depends on how the "stored"
|
|
|
|
- is defined (field, indexed expression, virtual method, ...) }
|
|
|
|
- if not(ppo_stored in tpropertysym(sym).propoptions) then
|
|
|
|
- propdefname:=internaltypeprefixName[itp_rtti_prop]+tostr(length(tpropertysym(sym).realname))
|
|
|
|
- else
|
|
|
|
- propdefname:='';
|
|
|
|
- { TPropInfo is a packed record (even on targets that require
|
|
|
|
- alignment), but it starts aligned }
|
|
|
|
- maybe_add_comment(tcb,'RTTI: begin property '+sym.prettyname);
|
|
|
|
- tcb.begin_anonymous_record(
|
|
|
|
- propdefname,
|
|
|
|
- 1,min(reqalign,SizeOf(PInt)),
|
|
|
|
- targetinfos[target_info.system]^.alignment.recordalignmin);
|
|
|
|
- if ppo_indexed in tpropertysym(sym).propoptions then
|
|
|
|
- proctypesinfo:=$40
|
|
|
|
- else
|
|
|
|
- proctypesinfo:=0;
|
|
|
|
- maybe_add_comment(tcb,#9'type info');
|
|
|
|
- write_rtti_reference(tcb,tpropertysym(sym).propdef,fullrtti);
|
|
|
|
- maybe_add_comment(tcb,#9'read access');
|
|
|
|
- writeaccessproc(palt_read,0,0);
|
|
|
|
- maybe_add_comment(tcb,#9'write access');
|
|
|
|
- writeaccessproc(palt_write,2,0);
|
|
|
|
- { is it stored ? }
|
|
|
|
- maybe_add_comment(tcb,#9'stored ?');
|
|
|
|
- if not(ppo_stored in tpropertysym(sym).propoptions) then
|
|
|
|
|
|
+ if extended_rtti then
|
|
begin
|
|
begin
|
|
- { no, so put a constant zero }
|
|
|
|
- tcb.emit_tai(Tai_const.Create_nil_codeptr,codeptruinttype);
|
|
|
|
- proctypesinfo:=proctypesinfo or (3 shl 4);
|
|
|
|
|
|
+ {
|
|
|
|
+ TPropInfoEx = record
|
|
|
|
+ Flags: Byte;
|
|
|
|
+ Info: PPropInfo;
|
|
|
|
+ // AttrData: TAttrData
|
|
|
|
+ end;
|
|
|
|
+ }
|
|
|
|
+ maybe_add_comment(tcb,'RTTI: begin property '+sym.prettyname);
|
|
|
|
+ tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
|
|
|
|
+ targetinfos[target_info.system]^.alignment.recordalignmin);
|
|
|
|
+ { write visiblity flags for extended RTTI }
|
|
|
|
+ maybe_add_comment(tcb,#9'visibility flags');
|
|
|
|
+ tcb.emit_ord_const(byte(visibility_to_rtti_flags(sym.visibility)),u8inttype);
|
|
|
|
+ { create separate constant builder }
|
|
|
|
+ current_asmdata.getglobaldatalabel(tbllab);
|
|
|
|
+ tbltcb:=ctai_typedconstbuilder.create([tcalo_is_lab,tcalo_make_dead_strippable]);
|
|
|
|
+ { write TPropInfo record }
|
|
|
|
+ tbldef:=write_propinfo_data(tbltcb,tpropertysym(sym));
|
|
|
|
+ current_asmdata.asmlists[al_rtti].concatlist(
|
|
|
|
+ tbltcb.get_final_asmlist(tbllab,tbldef,sec_rodata,tbllab.name,const_align(sizeof(pint)))
|
|
|
|
+ );
|
|
|
|
+ tbltcb.free;
|
|
|
|
+ { write the pointer to the prop info }
|
|
|
|
+ maybe_add_comment(tcb,#9'property info reference');
|
|
|
|
+ tcb.emit_tai(Tai_const.Create_sym(tbllab),voidpointertype);
|
|
|
|
+ { end record }
|
|
|
|
+ tcb.end_anonymous_record;
|
|
|
|
+ maybe_add_comment(tcb,'RTTI: end property '+sym.prettyname);
|
|
end
|
|
end
|
|
else
|
|
else
|
|
- 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);
|
|
|
|
- maybe_add_comment(tcb,#9'default');
|
|
|
|
- tcb.emit_ord_const(tpropertysym(sym).default,u32inttype);
|
|
|
|
- maybe_add_comment(tcb,#9'property index');
|
|
|
|
- propnameitem:=TPropNameListItem(propnamelist.Find(tpropertysym(sym).name));
|
|
|
|
- if not assigned(propnameitem) then
|
|
|
|
- internalerror(200512201);
|
|
|
|
- tcb.emit_ord_const(propnameitem.propindex,u16inttype);
|
|
|
|
- maybe_add_comment(tcb,#9'proc types');
|
|
|
|
- tcb.emit_ord_const(proctypesinfo,u8inttype);
|
|
|
|
-
|
|
|
|
- { write reference to attribute table }
|
|
|
|
- maybe_add_comment(tcb,#9'attributes');
|
|
|
|
- write_attribute_data(tcb,tpropertysym(sym).rtti_attribute_list);
|
|
|
|
-
|
|
|
|
- { Write property name }
|
|
|
|
- maybe_add_comment(tcb,#9'name');
|
|
|
|
- tcb.emit_shortstring_const(tpropertysym(sym).realname);
|
|
|
|
-
|
|
|
|
- tcb.end_anonymous_record;
|
|
|
|
- maybe_add_comment(tcb,'RTTI: end property '+sym.prettyname);
|
|
|
|
- end;
|
|
|
|
|
|
+ write_propinfo_data(tcb,tpropertysym(sym));
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
tcb.end_anonymous_record;
|
|
tcb.end_anonymous_record;
|
|
end;
|
|
end;
|
|
@@ -1443,8 +1645,22 @@ implementation
|
|
tcb.free;
|
|
tcb.free;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+
|
|
|
|
+ procedure write_extended_property_table;
|
|
|
|
+ var
|
|
|
|
+ propnamelist: TFPHashObjectList;
|
|
|
|
+ visibilities: tvisibilities;
|
|
|
|
+ begin
|
|
|
|
+ propnamelist:=TFPHashObjectList.Create;
|
|
|
|
+ visibilities:=def.rtti_visibilities_for_option(ro_properties);
|
|
|
|
+ collect_propnamelist(propnamelist,def,visibilities);
|
|
|
|
+ properties_write_rtti_data(tcb,propnamelist,def.symtable,true,visibilities);
|
|
|
|
+ propnamelist.free;
|
|
|
|
+ end;
|
|
|
|
+
|
|
var
|
|
var
|
|
oplab : tasmlabel;
|
|
oplab : tasmlabel;
|
|
|
|
+
|
|
begin
|
|
begin
|
|
write_header(tcb,def,tkRecord);
|
|
write_header(tcb,def,tkRecord);
|
|
{ need extra reqalign record, because otherwise the u32 int will
|
|
{ need extra reqalign record, because otherwise the u32 int will
|
|
@@ -1489,6 +1705,13 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
fields_write_rtti_data(tcb,def,rt);
|
|
fields_write_rtti_data(tcb,def,rt);
|
|
|
|
+ { write extended rtti }
|
|
|
|
+ if rt=fullrtti then
|
|
|
|
+ begin
|
|
|
|
+ write_extended_field_table(tcb,def,defaultpacking);
|
|
|
|
+ write_extended_method_table(tcb,def,defaultpacking);
|
|
|
|
+ write_extended_property_table;
|
|
|
|
+ end;
|
|
tcb.end_anonymous_record;
|
|
tcb.end_anonymous_record;
|
|
tcb.end_anonymous_record;
|
|
tcb.end_anonymous_record;
|
|
|
|
|
|
@@ -1658,13 +1881,25 @@ implementation
|
|
tcb.emit_ord_const(def.size, u32inttype);
|
|
tcb.emit_ord_const(def.size, u32inttype);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+ procedure objectdef_extended_rtti_class(def:tobjectdef);
|
|
|
|
+ var
|
|
|
|
+ propnamelist : TFPHashObjectList;
|
|
|
|
+ visibilities : tvisibilities;
|
|
|
|
+ begin
|
|
|
|
+ propnamelist:=TFPHashObjectList.Create;
|
|
|
|
+ visibilities:=def.rtti_visibilities_for_option(ro_properties);
|
|
|
|
+ collect_propnamelist(propnamelist,def,visibilities);
|
|
|
|
+ properties_write_rtti_data(tcb,propnamelist,def.symtable,true,visibilities);
|
|
|
|
+ propnamelist.free;
|
|
|
|
+ end;
|
|
|
|
+
|
|
procedure objectdef_rtti_class_full(def:tobjectdef);
|
|
procedure objectdef_rtti_class_full(def:tobjectdef);
|
|
var
|
|
var
|
|
propnamelist : TFPHashObjectList;
|
|
propnamelist : TFPHashObjectList;
|
|
begin
|
|
begin
|
|
{ Collect unique property names with nameindex }
|
|
{ Collect unique property names with nameindex }
|
|
propnamelist:=TFPHashObjectList.Create;
|
|
propnamelist:=TFPHashObjectList.Create;
|
|
- collect_propnamelist(propnamelist,def);
|
|
|
|
|
|
+ collect_propnamelist(propnamelist,def,[vis_published]);
|
|
|
|
|
|
tcb.begin_anonymous_record('',defaultpacking,reqalign,
|
|
tcb.begin_anonymous_record('',defaultpacking,reqalign,
|
|
targetinfos[target_info.system]^.alignment.recordalignmin);
|
|
targetinfos[target_info.system]^.alignment.recordalignmin);
|
|
@@ -1704,7 +1939,10 @@ implementation
|
|
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 }
|
|
- published_properties_write_rtti_data(tcb,propnamelist,def.symtable);
|
|
|
|
|
|
+ properties_write_rtti_data(tcb,propnamelist,def.symtable,false,[vis_published]);
|
|
|
|
+
|
|
|
|
+ { write extended properties }
|
|
|
|
+ objectdef_extended_rtti_class(def);
|
|
|
|
|
|
tcb.end_anonymous_record;
|
|
tcb.end_anonymous_record;
|
|
|
|
|
|
@@ -1721,7 +1959,7 @@ implementation
|
|
begin
|
|
begin
|
|
{ Collect unique property names with nameindex }
|
|
{ Collect unique property names with nameindex }
|
|
propnamelist:=TFPHashObjectList.Create;
|
|
propnamelist:=TFPHashObjectList.Create;
|
|
- collect_propnamelist(propnamelist,def);
|
|
|
|
|
|
+ collect_propnamelist(propnamelist,def,[vis_published]);
|
|
|
|
|
|
tcb.begin_anonymous_record('',defaultpacking,reqalign,
|
|
tcb.begin_anonymous_record('',defaultpacking,reqalign,
|
|
targetinfos[target_info.system]^.alignment.recordalignmin);
|
|
targetinfos[target_info.system]^.alignment.recordalignmin);
|
|
@@ -1765,10 +2003,10 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
{ write published properties for this object }
|
|
{ write published properties for this object }
|
|
- published_properties_write_rtti_data(tcb,propnamelist,def.symtable);
|
|
|
|
|
|
+ properties_write_rtti_data(tcb,propnamelist,def.symtable,false,[vis_published]);
|
|
|
|
|
|
{ write published methods for this interface }
|
|
{ write published methods for this interface }
|
|
- write_methods(tcb,def.symtable,[vis_published]);
|
|
|
|
|
|
+ write_methods(tcb,def.symtable,false,[vis_published]);
|
|
|
|
|
|
tcb.end_anonymous_record;
|
|
tcb.end_anonymous_record;
|
|
tcb.end_anonymous_record;
|
|
tcb.end_anonymous_record;
|