mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 02:32:51 +02:00
* support for implementing interface method wrappers at the node tree
level, used by LLVM git-svn-id: trunk@31636 -
This commit is contained in:
parent
be2ec5be59
commit
c7a418829b
@ -110,15 +110,14 @@ implementation
|
||||
cutils,cclasses,
|
||||
globtype,globals,verbose,constexp,
|
||||
systems,fmodule,
|
||||
symsym,symtable,defutil,
|
||||
symsym,symtable,symcreat,defutil,
|
||||
{$ifdef cpuhighleveltarget}
|
||||
pparautl,
|
||||
{$endif cpuhighleveltarget}
|
||||
aasmtai,
|
||||
wpobase,
|
||||
nobj,
|
||||
cgbase,parabase,paramgr,cgobj,cgcpu,hlcgobj,hlcgcpu,
|
||||
{$ifdef llvm}
|
||||
{ override create_hlcodegen from hlcgcpu }
|
||||
hlcgllvm,
|
||||
{$endif}
|
||||
ncgrtti;
|
||||
|
||||
|
||||
@ -1239,6 +1238,10 @@ implementation
|
||||
tmps : string;
|
||||
pd : TProcdef;
|
||||
ImplIntf : TImplementedInterface;
|
||||
{$ifdef cpuhighleveltarget}
|
||||
wrapperpd: tprocdef;
|
||||
wrapperinfo: pskpara_interface_wrapper;
|
||||
{$endif cpuhighleveltarget}
|
||||
begin
|
||||
for i:=0 to _class.ImplementedInterfaces.count-1 do
|
||||
begin
|
||||
@ -1257,11 +1260,34 @@ implementation
|
||||
tobjectdef(tprocdef(pd).struct).register_vmt_call(tprocdef(pd).extnumber);
|
||||
tmps:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+
|
||||
ImplIntf.IntfDef.objname^+'_$_'+tostr(j)+'_$_'+pd.mangledname);
|
||||
{$ifdef cpuhighleveltarget}
|
||||
{ bare copy so we don't copy the aliasnames }
|
||||
wrapperpd:=tprocdef(pd.getcopyas(procdef,pc_bareproc));
|
||||
{ set the mangled name to the wrapper name }
|
||||
wrapperpd.setmangledname(tmps);
|
||||
{ insert the wrapper procdef in the current unit's local
|
||||
symbol table, but set the owning "struct" to the current
|
||||
class (so self will have the correct type) }
|
||||
finish_copied_procdef(wrapperpd,tmps,current_module.localsymtable,_class);
|
||||
{ now insert self/vmt }
|
||||
insert_self_and_vmt_para(wrapperpd);
|
||||
{ and the function result }
|
||||
insert_funcret_para(wrapperpd);
|
||||
{ recalculate the parameters now that we've added the above }
|
||||
wrapperpd.calcparas;
|
||||
{ set the info required to generate the implementation }
|
||||
wrapperpd.synthetickind:=tsk_interface_wrapper;
|
||||
new(wrapperinfo);
|
||||
wrapperinfo^.pd:=pd;
|
||||
wrapperinfo^.offset:=ImplIntf.ioffset;
|
||||
wrapperpd.skpara:=wrapperinfo;
|
||||
{$else cpuhighleveltarget}
|
||||
{ create wrapper code }
|
||||
new_section(list,sec_code,tmps,target_info.alignment.procalign);
|
||||
hlcg.init_register_allocators;
|
||||
hlcg.g_intf_wrapper(list,pd,tmps,ImplIntf.ioffset);
|
||||
hlcg.done_register_allocators;
|
||||
{$endif cpuhighleveltarget}
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -1317,9 +1343,15 @@ implementation
|
||||
|
||||
procedure write_vmts(st:tsymtable;is_global:boolean);
|
||||
begin
|
||||
{ high level targets use synthetic procdefs to create the inteface
|
||||
wrappers }
|
||||
{$ifndef cpuhighleveltarget}
|
||||
create_hlcodegen;
|
||||
{$endif}
|
||||
do_write_vmts(st,is_global);
|
||||
{$ifndef cpuhighleveltarget}
|
||||
destroy_hlcodegen;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -401,9 +401,17 @@ type
|
||||
tsk_jvm_virtual_clmethod, // Java wrapper for virtual class method
|
||||
tsk_field_getter, // getter for a field (callthrough property is passed in skpara)
|
||||
tsk_field_setter, // Setter for a field (callthrough property is passed in skpara)
|
||||
tsk_block_invoke_procvar // Call a procvar to invoke inside a block
|
||||
tsk_block_invoke_procvar, // Call a procvar to invoke inside a block
|
||||
tsk_interface_wrapper // Call through to a method from an interface wrapper
|
||||
);
|
||||
|
||||
{ synthetic procdef supplementary information (tprocdef.skpara) }
|
||||
tskpara_interface_wrapper = record
|
||||
pd: pointer;
|
||||
offset: longint;
|
||||
end;
|
||||
pskpara_interface_wrapper = ^tskpara_interface_wrapper;
|
||||
|
||||
{ options for objects and classes }
|
||||
tobjecttyp = (odt_none,
|
||||
odt_class,
|
||||
|
@ -935,6 +935,32 @@ implementation
|
||||
str_parse_method_impl(str,pd,false);
|
||||
end;
|
||||
|
||||
|
||||
procedure implement_interface_wrapper(pd: tprocdef);
|
||||
var
|
||||
wrapperinfo: pskpara_interface_wrapper;
|
||||
callthroughpd: tprocdef;
|
||||
str: ansistring;
|
||||
begin
|
||||
wrapperinfo:=pskpara_interface_wrapper(pd.skpara);
|
||||
if not assigned(wrapperinfo) then
|
||||
internalerror(2015090801);
|
||||
callthroughpd:=tprocdef(wrapperinfo^.pd);
|
||||
str:='begin ';
|
||||
{ self right now points to the VMT of interface inside the instance ->
|
||||
adjust so it points to the start of the instance }
|
||||
str:=str+'pointer(self):=pointer(self) - '+tostr(wrapperinfo^.offset)+';';
|
||||
{ now call through to the actual method }
|
||||
if pd.returndef<>voidtype then
|
||||
str:=str+'result:=';
|
||||
str:=str+callthroughpd.procsym.realname+'(';
|
||||
addvisibibleparameters(str,callthroughpd);
|
||||
str:=str+') end;';
|
||||
str_parse_method_impl(str,pd,false);
|
||||
dispose(wrapperinfo);
|
||||
pd.skpara:=nil;
|
||||
end;
|
||||
|
||||
procedure add_synthetic_method_implementations_for_st(st: tsymtable);
|
||||
var
|
||||
i : longint;
|
||||
@ -1007,6 +1033,8 @@ implementation
|
||||
implement_field_setter(pd);
|
||||
tsk_block_invoke_procvar:
|
||||
implement_block_invoke_procvar(pd);
|
||||
tsk_interface_wrapper:
|
||||
implement_interface_wrapper(pd);
|
||||
else
|
||||
internalerror(2011032801);
|
||||
end;
|
||||
|
@ -539,7 +539,8 @@ const
|
||||
'jvm enum fpcvalueof', 'jvm enum long2set',
|
||||
'jvm enum bitset2set', 'jvm enum set2set',
|
||||
'jvm procvar invoke', 'jvm procvar intf constructor',
|
||||
'jvm virtual class method', 'jvm field getter', 'jvm field setter', 'block invoke');
|
||||
'jvm virtual class method', 'jvm field getter', 'jvm field setter',
|
||||
'block invoke','interface wrapper');
|
||||
begin
|
||||
if w<=ord(high(syntheticName)) then
|
||||
result:=syntheticName[tsynthetickind(w)]
|
||||
|
Loading…
Reference in New Issue
Block a user