* converted rest of VMT generation to high level typed const builder

git-svn-id: trunk@30369 -
This commit is contained in:
Jonas Maebe 2015-03-29 18:16:48 +00:00
parent 9bf410e6a0
commit 69e7b06cef

View File

@ -42,6 +42,8 @@ interface
_Class : tobjectdef;
{ message tables }
root : pprocdeftree;
{ implemented interface vtables }
fintfvtablelabels: array of TAsmLabel;
procedure disposeprocdeftree(p : pprocdeftree);
procedure insertmsgint(p:TObject;arg:pointer);
@ -49,7 +51,7 @@ interface
procedure insertint(p : pprocdeftree;var at : pprocdeftree;var count:longint);
procedure insertstr(p : pprocdeftree;var at : pprocdeftree;var count:longint);
function RedirectToEmpty(procdef: tprocdef): boolean;
procedure writenames(list : TAsmList;p : pprocdeftree);
procedure writenames(tcb: ttai_typedconstbuilder; p: pprocdeftree);
procedure writeintentry(tcb: ttai_typedconstbuilder; p: pprocdeftree; entrydef: tdef);
procedure writestrentry(tcb: ttai_typedconstbuilder; p: pprocdeftree; entrydef: tdef);
{$ifdef WITHDMT}
@ -62,12 +64,11 @@ interface
procedure do_count_published_methods(p:TObject;arg:pointer);
procedure do_gen_published_methods(p:TObject;arg:pointer);
{ virtual methods }
procedure writevirtualmethods(List:TAsmList);
procedure writevirtualmethods(tcb: ttai_typedconstbuilder);
{ interface tables }
function intf_get_vtbl_name(AImplIntf:TImplementedInterface): string;
procedure intf_create_vtbl(rawdata: TAsmList;AImplIntf:TImplementedInterface);
procedure intf_gen_intf_ref(tcb: ttai_typedconstbuilder; AImplIntf: TImplementedInterface; interfaceentrydef, interfaceentrytypedef: tdef);
function intf_write_table(list : TAsmList):TAsmLabel;
procedure intf_create_vtbl(tcb: ttai_typedconstbuilder; AImplIntf: TImplementedInterface; intfindex: longint);
procedure intf_gen_intf_ref(tcb: ttai_typedconstbuilder; AImplIntf: TImplementedInterface; intfindex: longint; interfaceentrydef, interfaceentrytypedef: tdef);
procedure intf_write_table(tcb: ttai_typedconstbuilder; out lab: TAsmLabel; out intftabledef: trecorddef);
{ get a table def of the form
record
count: countdef;
@ -78,10 +79,10 @@ interface
procedure gettabledef(const basename: string; countdef, elementdef: tdef; count: longint; packrecords: shortint; out recdef: trecorddef; out arrdef: tarraydef);
function getrecorddef(const name: string; const fields: array of tdef; packrecords: shortint): trecorddef;
{ generates the message tables for a class }
function genstrmsgtab(list : TAsmList) : tasmlabel;
function genintmsgtab(list : TAsmList) : tasmlabel;
function genpublishedmethodstable(list : TAsmList) : tasmlabel;
function generate_field_table(list : TAsmList) : tasmlabel;
procedure genstrmsgtab(tcb: ttai_typedconstbuilder; out lab: tasmlabel; out msgstrtabledef: trecorddef);
procedure genintmsgtab(tcb: ttai_typedconstbuilder; out lab: tasmlabel; out msginttabledef: trecorddef);
procedure genpublishedmethodstable(tcb: ttai_typedconstbuilder; out lab: tasmlabel; out pubmethodsdef: trecorddef);
procedure generate_field_table(tcb: ttai_typedconstbuilder; out lab: tasmlabel; out fieldtabledef: trecorddef);
procedure generate_abstract_stub(list:TAsmList;pd:tprocdef);
{$ifdef WITHDMT}
{ generates a DMT for _class }
@ -229,28 +230,26 @@ implementation
end;
procedure TVMTWriter.writenames(list : TAsmList;p : pprocdeftree);
procedure TVMTWriter.writenames(tcb: ttai_typedconstbuilder; p: pprocdeftree);
var
ca : pchar;
len : byte;
tcb : ttai_typedconstbuilder;
datatcb : ttai_typedconstbuilder;
begin
current_asmdata.getglobaldatalabel(p^.nl);
if assigned(p^.l) then
writenames(list,p^.l);
tcb:=ctai_typedconstbuilder.create([tcalo_is_lab]);
writenames(tcb,p^.l);
tcb.start_internal_data_builder(current_asmdata.AsmLists[al_const],sec_rodata_norel,'',datatcb,p^.nl);
len:=length(p^.data.messageinf.str^);
tcb.maybe_begin_aggregate(getarraydef(cansichartype,len+1));
tcb.emit_tai(tai_const.create_8bit(len),cansichartype);
datatcb.maybe_begin_aggregate(getarraydef(cansichartype,len+1));
datatcb.emit_tai(tai_const.create_8bit(len),cansichartype);
getmem(ca,len+1);
move(p^.data.messageinf.str^[1],ca^,len);
ca[len]:=#0;
tcb.emit_tai(Tai_string.Create_pchar(ca,len),getarraydef(cansichartype,len));
tcb.maybe_end_aggregate(getarraydef(cansichartype,len+1));
list.concatList(tcb.get_final_asmlist(p^.nl,getarraydef(cansichartype,len+1),sec_rodata_norel,'',sizeof(pint)));
tcb.free;
datatcb.emit_tai(Tai_string.Create_pchar(ca,len),getarraydef(cansichartype,len));
datatcb.maybe_end_aggregate(getarraydef(cansichartype,len+1));
tcb.finish_internal_data_builder(datatcb,p^.nl,getarraydef(cansichartype,len+1),sizeof(pint));
if assigned(p^.r) then
writenames(list,p^.r);
writenames(tcb,p^.r);
end;
procedure TVMTWriter.writestrentry(tcb: ttai_typedconstbuilder; p: pprocdeftree; entrydef: tdef);
@ -270,11 +269,10 @@ implementation
end;
function TVMTWriter.genstrmsgtab(list : TAsmList) : tasmlabel;
procedure TVMTWriter.genstrmsgtab(tcb: ttai_typedconstbuilder; out lab: tasmlabel; out msgstrtabledef: trecorddef);
var
count : longint;
tcb: ttai_typedconstbuilder;
msgstrtabdef: trecorddef;
datatcb: ttai_typedconstbuilder;
msgstrentry: tdef;
msgarraydef: tarraydef;
begin
@ -283,13 +281,12 @@ implementation
{ insert all message handlers into a tree, sorted by name }
_class.symtable.SymList.ForEachCall(@insertmsgstr,@count);
tcb:=ctai_typedconstbuilder.create([tcalo_is_lab]);
{ write all names }
if assigned(root) then
writenames(list,root);
writenames(tcb,root);
{ now start writing of the message string table }
current_asmdata.getlabel(result,alt_data);
{ now start writing the message string table }
tcb.start_internal_data_builder(current_asmdata.AsmLists[al_const],sec_rodata,'',datatcb,lab);
{
TStringMessageTable = record
count : longint;
@ -299,21 +296,20 @@ implementation
Instead of 0 as the upper bound, use the actual upper bound
}
msgstrentry:=search_system_type('TMSGSTRTABLE').typedef;
gettabledef('fpc_intern_TStringMessageTable_',s32inttype,msgstrentry,count,0,msgstrtabdef,msgarraydef);
gettabledef('fpc_intern_TStringMessageTable_',s32inttype,msgstrentry,count,0,msgstrtabledef,msgarraydef);
{ outer record (TStringMessageTable) }
tcb.maybe_begin_aggregate(msgstrtabdef);
tcb.emit_tai(Tai_const.Create_32bit(count),s32inttype);
datatcb.maybe_begin_aggregate(msgstrtabledef);
datatcb.emit_tai(Tai_const.Create_32bit(count),s32inttype);
if assigned(root) then
begin
{ array of TMsgStrTable }
tcb.maybe_begin_aggregate(msgarraydef);
writestrentry(tcb,root,msgstrentry);
tcb.maybe_end_aggregate(msgarraydef);
datatcb.maybe_begin_aggregate(msgarraydef);
writestrentry(datatcb,root,msgstrentry);
datatcb.maybe_end_aggregate(msgarraydef);
disposeprocdeftree(root);
end;
tcb.maybe_end_aggregate(msgstrtabdef);
list.concatList(tcb.get_final_asmlist(result,msgstrtabdef,sec_rodata,'',sizeof(pint)));
tcb.free;
datatcb.maybe_end_aggregate(msgstrtabledef);
tcb.finish_internal_data_builder(datatcb,lab,msgstrtabledef,sizeof(pint));
end;
@ -334,13 +330,11 @@ implementation
end;
function TVMTWriter.genintmsgtab(list : TAsmList) : tasmlabel;
procedure TVMTWriter.genintmsgtab(tcb: ttai_typedconstbuilder; out lab: tasmlabel; out msginttabledef: trecorddef);
var
r : tasmlabel;
count : longint;
tcb: ttai_typedconstbuilder;
datatcb: ttai_typedconstbuilder;
msgintdef: trecorddef;
msginttabledef: trecorddef;
msgintarrdef: tarraydef;
begin
root:=nil;
@ -363,22 +357,19 @@ implementation
msgs : array[0..0] of TMsgIntTable;
end;
}
current_asmdata.getlabel(r,alt_data);
tcb:=ctai_typedconstbuilder.create([tcalo_is_lab]);
genintmsgtab:=r;
tcb.start_internal_data_builder(current_asmdata.AsmLists[al_const],sec_rodata,'',datatcb,lab);
gettabledef('fpc_msgint_table_entries_',s32inttype,msginttabledef,count,0,msgintdef,msgintarrdef);
tcb.maybe_begin_aggregate(msgintdef);
tcb.emit_tai(Tai_const.Create_32bit(count),s32inttype);
datatcb.maybe_begin_aggregate(msgintdef);
datatcb.emit_tai(Tai_const.Create_32bit(count),s32inttype);
if assigned(root) then
begin
tcb.maybe_begin_aggregate(msgintarrdef);
writeintentry(tcb,root,msginttabledef);
tcb.maybe_end_aggregate(msgintarrdef);
datatcb.maybe_begin_aggregate(msgintarrdef);
writeintentry(datatcb,root,msginttabledef);
datatcb.maybe_end_aggregate(msgintarrdef);
disposeprocdeftree(root);
end;
tcb.maybe_end_aggregate(msgintdef);
list.concatList(tcb.get_final_asmlist(result,msgintdef,sec_rodata,'',sizeof(pint)));
tcb.free;
datatcb.maybe_end_aggregate(msgintdef);
tcb.finish_internal_data_builder(datatcb,lab,msgintdef,sizeof(pint));
end;
{$ifdef WITHDMT}
@ -490,7 +481,6 @@ implementation
type
tvmtasmoutput = record
pubmethodstcb: ttai_typedconstbuilder;
list: tasmlist;
methodnamerec: trecorddef;
end;
pvmtasmoutput = ^tvmtasmoutput;
@ -501,7 +491,7 @@ implementation
l : tasmlabel;
pd : tprocdef;
lists: pvmtasmoutput absolute arg;
tcb : ttai_typedconstbuilder;
datatcb : ttai_typedconstbuilder;
namedef : tdef;
begin
if (tsym(p).typ<>procsym) then
@ -512,13 +502,10 @@ implementation
if (pd.procsym=tsym(p)) and
(pd.visibility=vis_published) then
begin
current_asmdata.getlabel(l,alt_data);
{ l: name_of_method }
tcb:=ctai_typedconstbuilder.create([tcalo_is_lab]);
namedef:=tcb.emit_shortstring_const(tsym(p).realname);
lists^.list.concatList(tcb.get_final_asmlist(l,namedef,sec_rodata_norel,'',sizeof(pint)));
tcb.free;
lists^.pubmethodstcb.start_internal_data_builder(current_asmdata.AsmLists[al_const],sec_rodata_norel,'',datatcb,l);
namedef:=datatcb.emit_shortstring_const(tsym(p).realname);
lists^.pubmethodstcb.finish_internal_data_builder(datatcb,l,namedef,sizeof(pint));
{ the tmethodnamerec }
lists^.pubmethodstcb.maybe_begin_aggregate(lists^.methodnamerec);
{ convert the pointer to the name into a generic pshortstring,
@ -540,20 +527,16 @@ implementation
end;
function TVMTWriter.genpublishedmethodstable(list : TAsmList) : tasmlabel;
procedure TVMTWriter.genpublishedmethodstable(tcb: ttai_typedconstbuilder; out lab: tasmlabel; out pubmethodsdef: trecorddef);
var
l : tasmlabel;
count : longint;
lists : tvmtasmoutput;
pubmethodsdef: trecorddef;
pubmethodsarraydef: tarraydef;
begin
count:=0;
_class.symtable.SymList.ForEachCall(@do_count_published_methods,@count);
if count>0 then
begin
lists.list:=list;
{ in the list of the published methods (from objpas.inc):
tmethodnamerec = packed record
name : pshortstring;
@ -567,8 +550,7 @@ implementation
entries : packed array[0..0] of tmethodnamerec;
end;
}
lists.pubmethodstcb:=ctai_typedconstbuilder.create([tcalo_is_lab]);
current_asmdata.getlabel(l,alt_data);
tcb.start_internal_data_builder(current_asmdata.AsmLists[al_const],sec_rodata,'',lists.pubmethodstcb,lab);
gettabledef('fpc_intern_tmethodnametable_',u32inttype,lists.methodnamerec,count,1,pubmethodsdef,pubmethodsarraydef);
{ begin tmethodnametable }
lists.pubmethodstcb.maybe_begin_aggregate(pubmethodsdef);
@ -582,29 +564,28 @@ implementation
lists.pubmethodstcb.maybe_end_aggregate(pubmethodsarraydef);
{ end methodnametable }
lists.pubmethodstcb.maybe_end_aggregate(pubmethodsdef);
list.concatlist(lists.pubmethodstcb.get_final_asmlist(l,pubmethodsdef,sec_rodata,'',sizeof(pint)));
lists.pubmethodstcb.free;
genpublishedmethodstable:=l;
tcb.finish_internal_data_builder(lists.pubmethodstcb,lab,pubmethodsdef,sizeof(pint));
end
else
genpublishedmethodstable:=nil;
begin
lab:=nil;
pubmethodsdef:=nil;
end;
end;
function TVMTWriter.generate_field_table(list : TAsmList) : tasmlabel;
procedure TVMTWriter.generate_field_table(tcb: ttai_typedconstbuilder; out lab: tasmlabel; out fieldtabledef: trecorddef);
var
i : longint;
sym : tsym;
fieldtable,
classtable : tasmlabel;
classindex,
fieldcount : longint;
classtablelist : TFPList;
tcb: ttai_typedconstbuilder;
datatcb: ttai_typedconstbuilder;
packrecords: longint;
classdef: tobjectdef;
classtabledef,
fieldtabledef: trecorddef;
classtabledef: trecorddef;
begin
classtablelist:=TFPList.Create;
{ retrieve field info fields }
@ -626,34 +607,30 @@ implementation
if fieldcount>0 then
begin
current_asmdata.getlabel(fieldtable,alt_data);
current_asmdata.getlabel(classtable,alt_data);
if (tf_requires_proper_alignment in target_info.flags) then
packrecords:=0
else
packrecords:=1;
{ generate the class table }
tcb:=ctai_typedconstbuilder.create([tcalo_is_lab]);
tcb.begin_anonymous_record('$fpc_intern_classtable_'+tostr(classtablelist.Count-1),
tcb.start_internal_data_builder(current_asmdata.AsmLists[al_const],sec_rodata,'',datatcb,classtable);
datatcb.begin_anonymous_record('$fpc_intern_classtable_'+tostr(classtablelist.Count-1),
packrecords,
targetinfos[target_info.system]^.alignment.recordalignmin,
targetinfos[target_info.system]^.alignment.maxCrecordalign);
tcb.emit_tai(Tai_const.Create_16bit(classtablelist.count),u16inttype);
datatcb.emit_tai(Tai_const.Create_16bit(classtablelist.count),u16inttype);
for i:=0 to classtablelist.Count-1 do
begin
classdef:=tobjectdef(classtablelist[i]);
{ type of the field }
tcb.queue_init(voidpointertype);
datatcb.queue_init(voidpointertype);
{ reference to the vmt }
tcb.queue_emit_asmsym(
datatcb.queue_emit_asmsym(
current_asmdata.RefAsmSymbol(classdef.vmt_mangledname,AT_DATA),
tfieldvarsym(classdef.vmt_field).vardef);
end;
classtabledef:=tcb.end_anonymous_record;
list.concatlist(tcb.get_final_asmlist(classtable,classtabledef,sec_rodata,'',sizeof(pint)));
tcb.free;
classtabledef:=datatcb.end_anonymous_record;
tcb.finish_internal_data_builder(datatcb,classtable,classtabledef,sizeof(pint));
{ write fields }
{
@ -667,17 +644,17 @@ implementation
Fields: array[0..0] of TFieldInfo
end;
}
tcb:=ctai_typedconstbuilder.create([tcalo_is_lab]);
tcb.start_internal_data_builder(current_asmdata.AsmLists[al_const],sec_rodata,'',datatcb,lab);
{ can't easily specify a name here for reuse of the constructed def,
since it's full of variable length shortstrings (-> all of those
lengths and their order would have to incorporated in the name,
plus there would be very little chance that it could actually be
reused }
tcb.begin_anonymous_record('',packrecords,
datatcb.begin_anonymous_record('',packrecords,
targetinfos[target_info.system]^.alignment.recordalignmin,
targetinfos[target_info.system]^.alignment.maxCrecordalign);
tcb.emit_tai(Tai_const.Create_16bit(fieldcount),u16inttype);
tcb.emit_tai(Tai_const.Create_sym(classtable),getpointerdef(classtabledef));
datatcb.emit_tai(Tai_const.Create_16bit(fieldcount),u16inttype);
datatcb.emit_tai(Tai_const.Create_sym(classtable),getpointerdef(classtabledef));
for i:=0 to _class.symtable.SymList.Count-1 do
begin
sym:=tsym(_class.symtable.SymList[i]);
@ -695,26 +672,26 @@ implementation
Name: ShortString;
end;
}
tcb.begin_anonymous_record('$fpc_intern_fieldinfo_'+tostr(length(tfieldvarsym(sym).realname)),packrecords,
datatcb.begin_anonymous_record('$fpc_intern_fieldinfo_'+tostr(length(tfieldvarsym(sym).realname)),packrecords,
targetinfos[target_info.system]^.alignment.recordalignmin,
targetinfos[target_info.system]^.alignment.maxCrecordalign);
tcb.emit_tai(Tai_const.Create_pint(tfieldvarsym(sym).fieldoffset),ptruinttype);
datatcb.emit_tai(Tai_const.Create_pint(tfieldvarsym(sym).fieldoffset),ptruinttype);
classindex:=classtablelist.IndexOf(tfieldvarsym(sym).vardef);
if classindex=-1 then
internalerror(200611033);
tcb.emit_tai(Tai_const.Create_16bit(classindex+1),u16inttype);
tcb.emit_shortstring_const(tfieldvarsym(sym).realname);
tcb.end_anonymous_record;
datatcb.emit_tai(Tai_const.Create_16bit(classindex+1),u16inttype);
datatcb.emit_shortstring_const(tfieldvarsym(sym).realname);
datatcb.end_anonymous_record;
end;
end;
fieldtabledef:=tcb.end_anonymous_record;
list.concatlist(tcb.get_final_asmlist(fieldtable,fieldtabledef,sec_rodata,'',sizeof(pint)));
tcb.free;
result:=fieldtable;
fieldtabledef:=datatcb.end_anonymous_record;
tcb.finish_internal_data_builder(datatcb,lab,fieldtabledef,sizeof(pint));
end
else
result:=nil;
begin
fieldtabledef:=nil;
lab:=nil;
end;
classtablelist.free;
end;
@ -724,22 +701,17 @@ implementation
Interface tables
**************************************}
function TVMTWriter.intf_get_vtbl_name(AImplIntf:TImplementedInterface): string;
begin
result:=make_mangledname('VTBL',_class.owner,_class.objname^+'_$_'+AImplIntf.IntfDef.objname^);
end;
procedure TVMTWriter.intf_create_vtbl(rawdata: TAsmList;AImplIntf:TImplementedInterface);
procedure TVMTWriter.intf_create_vtbl(tcb: ttai_typedconstbuilder; AImplIntf: TImplementedInterface; intfindex: longint);
var
datatcb : ttai_typedconstbuilder;
pd : tprocdef;
vtblstr,
hs : string;
hs : TSymStr;
i : longint;
begin
vtblstr:=intf_get_vtbl_name(AImplIntf);
rawdata.concat(cai_align.create(const_align(sizeof(pint))));
rawdata.concat(tai_symbol.createname(vtblstr,AT_DATA,0));
tcb.start_internal_data_builder(current_asmdata.AsmLists[al_const],sec_rodata,'',datatcb,fintfvtablelabels[intfindex]);
datatcb.begin_anonymous_record('',0,
targetinfos[target_info.system]^.alignment.recordalignmin,
targetinfos[target_info.system]^.alignment.maxCrecordalign);
if assigned(AImplIntf.procdefs) then
begin
for i:=0 to AImplIntf.procdefs.count-1 do
@ -748,14 +720,18 @@ implementation
hs:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+AImplIntf.IntfDef.objname^+'_$_'+
tostr(i)+'_$_'+pd.mangledname);
{ create reference }
rawdata.concat(Tai_const.Createname(hs,AT_FUNCTION,0));
datatcb.emit_tai(Tai_const.Createname(hs,AT_FUNCTION,0),pd.getcopyas(procvardef,pc_address_only));
end;
end;
rawdata.concat(tai_symbol_end.createname(vtblstr));
end
else
{ can't have an empty symbol on LLVM }
datatcb.emit_tai(tai_const.Create_nil_codeptr,voidpointertype);
tcb.finish_internal_data_builder(datatcb,fintfvtablelabels[intfindex],
datatcb.end_anonymous_record,sizeof(pint));
end;
procedure TVMTWriter.intf_gen_intf_ref(tcb: ttai_typedconstbuilder; AImplIntf: TImplementedInterface; interfaceentrydef, interfaceentrytypedef: tdef);
procedure TVMTWriter.intf_gen_intf_ref(tcb: ttai_typedconstbuilder; AImplIntf: TImplementedInterface; intfindex: longint; interfaceentrydef, interfaceentrytypedef: tdef);
var
pd: tprocdef;
begin
@ -769,7 +745,7 @@ implementation
{ VTable }
tcb.queue_init(voidpointertype);
tcb.queue_emit_asmsym(current_asmdata.RefAsmSymbol(intf_get_vtbl_name(AImplIntf.VtblImplIntf),AT_DATA),AImplIntf.VtblImplIntf.IntfDef);
tcb.queue_emit_asmsym(fintfvtablelabels[intfindex],AImplIntf.VtblImplIntf.IntfDef);
{ IOffset field }
case AImplIntf.VtblImplIntf.IType of
etFieldValue, etFieldValueClass,
@ -799,44 +775,52 @@ implementation
end;
function TVMTWriter.intf_write_table(list : TAsmList):TAsmLabel;
procedure TVMTWriter.intf_write_table(tcb: ttai_typedconstbuilder; out lab: TAsmLabel; out intftabledef: trecorddef);
var
i : longint;
ImplIntf : TImplementedInterface;
tcb : ttai_typedconstbuilder;
tabledef : tdef;
datatcb : ttai_typedconstbuilder;
interfaceentrydef : tdef;
interfaceentrytypedef: tdef;
interfacearray: tdef;
begin
current_asmdata.getlabel(result,alt_data);
tcb:=ctai_typedconstbuilder.create([tcalo_is_lab]);
tcb.begin_anonymous_record('',0,
targetinfos[target_info.system]^.alignment.recordalignmin,
targetinfos[target_info.system]^.alignment.maxCrecordalign);
tcb.emit_tai(Tai_const.Create_pint(_class.ImplementedInterfaces.count),search_system_type('SIZEUINT').typedef);
interfaceentrydef:=search_system_type('TINTERFACEENTRY').typedef;
interfaceentrytypedef:=search_system_type('TINTERFACEENTRYTYPE').typedef;
interfacearray:=getarraydef(interfaceentrydef,_class.ImplementedInterfaces.count);
tcb.maybe_begin_aggregate(interfacearray);
{ Write vtbl references }
for i:=0 to _class.ImplementedInterfaces.count-1 do
begin
ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
intf_gen_intf_ref(tcb,ImplIntf,interfaceentrydef,interfaceentrytypedef);
end;
tcb.maybe_end_aggregate(interfacearray);
tabledef:=tcb.end_anonymous_record;
list.concatlist(tcb.get_final_asmlist(result,tabledef,sec_rodata,'',tabledef.alignment));
setlength(fintfvtablelabels,_class.ImplementedInterfaces.count);
{ Write vtbls }
{ Write unique vtbls }
for i:=0 to _class.ImplementedInterfaces.count-1 do
begin
ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
if ImplIntf.VtblImplIntf=ImplIntf then
intf_create_vtbl(list,ImplIntf);
intf_create_vtbl(tcb,ImplIntf,i)
end;
tcb.free;
{ Set labels for aliased vtbls (after all unique vtbls have been
written, so all labels have been defined already) }
for i:=0 to _class.ImplementedInterfaces.count-1 do
begin
ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
if ImplIntf.VtblImplIntf<>ImplIntf then
fintfvtablelabels[i]:=fintfvtablelabels[_class.ImplementedInterfaces.IndexOf(ImplIntf.VtblImplIntf)];
end;
tcb.start_internal_data_builder(current_asmdata.AsmLists[al_const],sec_rodata,'',datatcb,lab);
datatcb.begin_anonymous_record('',0,
targetinfos[target_info.system]^.alignment.recordalignmin,
targetinfos[target_info.system]^.alignment.maxCrecordalign);
datatcb.emit_tai(Tai_const.Create_pint(_class.ImplementedInterfaces.count),search_system_type('SIZEUINT').typedef);
interfaceentrydef:=search_system_type('TINTERFACEENTRY').typedef;
interfaceentrytypedef:=search_system_type('TINTERFACEENTRYTYPE').typedef;
interfacearray:=getarraydef(interfaceentrydef,_class.ImplementedInterfaces.count);
datatcb.maybe_begin_aggregate(interfacearray);
{ Write vtbl references }
for i:=0 to _class.ImplementedInterfaces.count-1 do
begin
ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
intf_gen_intf_ref(datatcb,ImplIntf,i,interfaceentrydef,interfaceentrytypedef);
end;
datatcb.maybe_end_aggregate(interfacearray);
intftabledef:=datatcb.end_anonymous_record;
tcb.finish_internal_data_builder(datatcb,lab,intftabledef,intftabledef.alignment);
end;
@ -995,7 +979,7 @@ implementation
end;
procedure TVMTWriter.writevirtualmethods(List:TAsmList);
procedure TVMTWriter.writevirtualmethods(tcb: ttai_typedconstbuilder);
var
vmtpd : tprocdef;
vmtentry : pvmtentry;
@ -1025,7 +1009,7 @@ implementation
procname:='FPC_EMPTYMETHOD'
else if not wpoinfomanager.optimized_name_for_vmt(_class,vmtpd,procname) then
procname:=vmtpd.mangledname;
List.concat(Tai_const.createname(procname,AT_FUNCTION,0));
tcb.emit_tai(Tai_const.Createname(procname,AT_FUNCTION,0),vmtpd.getcopyas(procvardef,pc_address_only));
{$ifdef vtentry}
hs:='VTENTRY'+'_'+_class.vmt_mangledname+'$$'+tostr(_class.vmtmethodoffset(i) div sizeof(pint));
current_asmdata.asmlists[al_globals].concat(tai_symbol.CreateName(hs,AT_DATA,0));
@ -1044,9 +1028,13 @@ implementation
dmtlabel : tasmlabel;
{$endif WITHDMT}
interfacetable : tasmlabel;
templist : TAsmList;
tcb: ttai_typedconstbuilder;
tcb, datatcb: ttai_typedconstbuilder;
classnamedef: tdef;
methodnametabledef,
fieldtabledef,
interfacetabledef,
strmessagetabledef,
intmessagetabledef: trecorddef;
begin
{$ifdef WITHDMT}
dmtlabel:=gendmt;
@ -1055,7 +1043,6 @@ implementation
already been removed from the symtablestack -> add it again, so that
newly created defs here end up in the right unit }
symtablestack.push(current_module.localsymtable);
templist:=TAsmList.Create;
strmessagetable:=nil;
interfacetable:=nil;
fieldtablelabel:=nil;
@ -1063,48 +1050,55 @@ implementation
intmessagetable:=nil;
classnamelabel:=nil;
classnamedef:=nil;
methodnametabledef:=nil;
fieldtabledef:=nil;
interfacetabledef:=nil;
strmessagetabledef:=nil;
intmessagetabledef:=nil;
{ generate VMT }
tcb:=ctai_typedconstbuilder.create([tcalo_make_dead_strippable]);
{ write tables for classes, this must be done before the actual
class is written, because we need the labels defined }
if is_class(_class) then
begin
{ write class name }
current_asmdata.getlabel(classnamelabel,alt_data);
tcb:=ctai_typedconstbuilder.create([tcalo_is_lab]);
tcb.start_internal_data_builder(current_asmdata.asmlists[al_const],sec_rodata_norel,'',datatcb,classnamelabel);
hs:=_class.RttiName;
classnamedef:=tcb.emit_shortstring_const(_class.RttiName);
templist.concatlist(tcb.get_final_asmlist(classnamelabel,classnamedef,sec_rodata_norel,'',sizeof(pint)));
tcb.free;
classnamedef:=datatcb.emit_shortstring_const(_class.RttiName);
tcb.finish_internal_data_builder(datatcb,classnamelabel,classnamedef,sizeof(pint));
{ interface table }
if _class.ImplementedInterfaces.count>0 then
interfacetable:=intf_write_table(templist);
intf_write_table(tcb,interfacetable,interfacetabledef);
methodnametable:=genpublishedmethodstable(templist);
fieldtablelabel:=generate_field_table(templist);
genpublishedmethodstable(tcb,methodnametable,methodnametabledef);
generate_field_table(tcb,fieldtablelabel,fieldtabledef);
{ generate message and dynamic tables }
if (oo_has_msgstr in _class.objectoptions) then
strmessagetable:=genstrmsgtab(templist);
genstrmsgtab(tcb,strmessagetable,strmessagetabledef);
if (oo_has_msgint in _class.objectoptions) then
intmessagetable:=genintmsgtab(templist);
genintmsgtab(tcb,intmessagetable,intmessagetabledef);
end;
{ write debug info }
maybe_new_object_file(current_asmdata.asmlists[al_globals]);
new_section(current_asmdata.asmlists[al_globals],sec_rodata,_class.vmt_mangledname,const_align(sizeof(pint)));
current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(_class.vmt_mangledname,AT_DATA,0));
tcb.begin_anonymous_record('',voidpointertype.alignment,
targetinfos[target_info.system]^.alignment.recordalignmin,
targetinfos[target_info.system]^.alignment.maxCrecordalign);
{ determine the size with symtable.datasize, because }
{ size gives back 4 for classes }
current_asmdata.asmlists[al_globals].concat(Tai_const.Create(aitconst_ptr,tObjectSymtable(_class.symtable).datasize));
current_asmdata.asmlists[al_globals].concat(Tai_const.Create(aitconst_ptr,-int64(tObjectSymtable(_class.symtable).datasize)));
tcb.emit_ord_const(tObjectSymtable(_class.symtable).datasize,ptrsinttype);
tcb.emit_ord_const(-int64(tObjectSymtable(_class.symtable).datasize),ptrsinttype);
{$ifdef WITHDMT}
if _class.classtype=ct_object then
begin
if assigned(dmtlabel) then
current_asmdata.asmlists[al_globals].concat(Tai_const_symbol.Create(dmtlabel)))
tcb.emit_tai(dmtlabel,voidpointertype)
else
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_ptr(0));
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
end;
{$endif WITHDMT}
{ write pointer to parent VMT, this isn't implemented in TP }
@ -1113,57 +1107,84 @@ implementation
{ it is not written for parents that don't have any vmt !! }
if assigned(_class.childof) and
(oo_has_vmt in _class.childof.objectoptions) then
current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(_class.childof.vmt_mangledname,AT_DATA,0))
begin
tcb.queue_init(voidpointertype);
tcb.queue_emit_asmsym(
current_asmdata.RefAsmSymbol(_class.childof.vmt_mangledname,AT_DATA),
tfieldvarsym(_class.childof.vmt_field).vardef);
end
else
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_nil_dataptr);
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
{ write extended info for classes, for the order see rtl/inc/objpash.inc }
if is_class(_class) then
begin
{ pointer to class name string }
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(classnamelabel));
tcb.emit_tai(Tai_const.Create_sym(classnamelabel),getpointerdef(classnamedef));
{ pointer to dynamic table or nil }
if (oo_has_msgint in _class.objectoptions) then
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(intmessagetable))
begin
tcb.queue_init(voidpointertype);
tcb.queue_emit_asmsym(intmessagetable,getpointerdef(intmessagetabledef));
end
else
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_nil_dataptr);
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
{ pointer to method table or nil }
if assigned(methodnametable) then
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(methodnametable))
begin
tcb.queue_init(voidpointertype);
tcb.queue_emit_asmsym(methodnametable,getpointerdef(methodnametabledef))
end
else
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_nil_dataptr);
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
{ pointer to field table }
if assigned(fieldtablelabel) then
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(fieldtablelabel))
begin
tcb.queue_init(voidpointertype);
tcb.queue_emit_asmsym(fieldtablelabel,fieldtabledef)
end
else
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_nil_dataptr);
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
{ pointer to type info of published section }
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(RTTIWriter.get_rtti_label(_class,fullrtti)));
tcb.emit_tai(Tai_const.Create_sym(RTTIWriter.get_rtti_label(_class,fullrtti)),voidpointertype);
{ inittable for con-/destruction }
if _class.members_need_inittable then
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(RTTIWriter.get_rtti_label(_class,initrtti)))
tcb.emit_tai(Tai_const.Create_sym(RTTIWriter.get_rtti_label(_class,initrtti)),voidpointertype)
else
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_nil_dataptr);
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
{ auto table }
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_nil_dataptr);
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
{ interface table }
if _class.ImplementedInterfaces.count>0 then
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(interfacetable))
begin
tcb.queue_init(voidpointertype);
tcb.queue_emit_asmsym(interfacetable,interfacetabledef)
end
else if _class.implements_any_interfaces then
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_nil_dataptr)
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype)
else
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(current_asmdata.RefAsmSymbol('FPC_EMPTYINTF',AT_DATA)));
tcb.emit_tai(Tai_const.Create_sym(current_asmdata.RefAsmSymbol('FPC_EMPTYINTF',AT_DATA)),voidpointertype);
{ table for string messages }
if (oo_has_msgstr in _class.objectoptions) then
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(strmessagetable))
begin
tcb.queue_init(voidpointertype);
tcb.queue_emit_asmsym(strmessagetable,strmessagetabledef);
end
else
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_nil_dataptr);
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
end;
{ write virtual methods }
writevirtualmethods(current_asmdata.asmlists[al_globals]);
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_nil_codeptr);
{ write the size of the VMT }
current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname(_class.vmt_mangledname));
writevirtualmethods(tcb);
tcb.emit_tai(Tai_const.Create_nil_codeptr,voidcodepointertype);
{ concatenate the VMT to the asmlist }
current_asmdata.asmlists[al_globals].concatlist(
tcb.get_final_asmlist(
current_asmdata.DefineAsmSymbol(_class.vmt_mangledname,AB_GLOBAL,AT_DATA),
tcb.end_anonymous_record,sec_rodata,_class.vmt_mangledname,const_align(sizeof(pint))
)
);
tcb.free;
{$ifdef vtentry}
{ write vtinherit symbol to notify the linker of the class inheritance tree }
hs:='VTINHERIT'+'_'+_class.vmt_mangledname+'$$';
@ -1173,9 +1194,6 @@ implementation
hs:=hs+_class.vmt_mangledname;
current_asmdata.asmlists[al_globals].concat(tai_symbol.CreateName(hs,AT_DATA,0));
{$endif vtentry}
if is_class(_class) then
current_asmdata.asmlists[al_globals].concatlist(templist);
templist.Free;
symtablestack.pop(current_module.localsymtable);
end;