* only add hidden parameters for objectdef methods after generating the vmt,

so that they take into account inherited calling conventions (mantis #35233)
   o don't needlessly calculate the paraloc info when generating a JVM mangled
     name

git-svn-id: trunk@41716 -
This commit is contained in:
Jonas Maebe 2019-03-16 19:14:14 +00:00
parent 9cf243ad38
commit ed2ae508d0
14 changed files with 121 additions and 42 deletions

1
.gitattributes vendored
View File

@ -16566,6 +16566,7 @@ tests/webtbs/tw35139a.pp svneol=native#text/plain
tests/webtbs/tw35149.pp svneol=native#text/plain tests/webtbs/tw35149.pp svneol=native#text/plain
tests/webtbs/tw35187.pp svneol=native#text/pascal tests/webtbs/tw35187.pp svneol=native#text/pascal
tests/webtbs/tw3523.pp svneol=native#text/plain tests/webtbs/tw3523.pp svneol=native#text/plain
tests/webtbs/tw35233.pp svneol=native#text/plain
tests/webtbs/tw3529.pp svneol=native#text/plain tests/webtbs/tw3529.pp svneol=native#text/plain
tests/webtbs/tw3531.pp svneol=native#text/plain tests/webtbs/tw3531.pp svneol=native#text/plain
tests/webtbs/tw3533.pp svneol=native#text/plain tests/webtbs/tw3533.pp svneol=native#text/plain

View File

@ -1121,10 +1121,11 @@ implementation
pd.visibility:=vis_public; pd.visibility:=vis_public;
{ result type } { result type }
pd.returndef:=obj; pd.returndef:=obj;
{ calling convention, self, ... (not for advanced records, for those { calling convention }
this is handled later) } if assigned(current_structdef) or
if obj.typ=recorddef then (assigned(pd.owner.defowner) and
handle_calling_convention(pd,[hcc_declaration,hcc_check]) (pd.owner.defowner.typ=recorddef)) then
handle_calling_convention(pd,hcc_default_actions_intf_struct)
else else
handle_calling_convention(pd,hcc_default_actions_intf); handle_calling_convention(pd,hcc_default_actions_intf);
{ register forward declaration with procsym } { register forward declaration with procsym }

View File

@ -322,6 +322,7 @@ implementation
vmtbuilder:=TVMTBuilder.Create(enumclass); vmtbuilder:=TVMTBuilder.Create(enumclass);
vmtbuilder.generate_vmt; vmtbuilder.generate_vmt;
vmtbuilder.free; vmtbuilder.free;
insert_struct_hidden_paras(enumclass);
restore_after_new_class(sstate,islocal,oldsymtablestack); restore_after_new_class(sstate,islocal,oldsymtablestack);
current_structdef:=old_current_structdef; current_structdef:=old_current_structdef;
@ -376,8 +377,6 @@ implementation
then wraps them and calls through to JLRMethod.invoke } then wraps them and calls through to JLRMethod.invoke }
methoddef:=tprocdef(tprocvardef(def).getcopyas(procdef,pc_bareproc,'')); methoddef:=tprocdef(tprocvardef(def).getcopyas(procdef,pc_bareproc,''));
finish_copied_procdef(methoddef,'invoke',pvclass.symtable,pvclass); finish_copied_procdef(methoddef,'invoke',pvclass.symtable,pvclass);
insert_self_and_vmt_para(methoddef);
insert_funcret_para(methoddef);
methoddef.synthetickind:=tsk_jvm_procvar_invoke; methoddef.synthetickind:=tsk_jvm_procvar_invoke;
methoddef.calcparas; methoddef.calcparas;
@ -411,8 +410,6 @@ implementation
symtablestack.push(pvintf.symtable); symtablestack.push(pvintf.symtable);
methoddef:=tprocdef(tprocvardef(def).getcopyas(procdef,pc_bareproc,'')); methoddef:=tprocdef(tprocvardef(def).getcopyas(procdef,pc_bareproc,''));
finish_copied_procdef(methoddef,name+'Callback',pvintf.symtable,pvintf); finish_copied_procdef(methoddef,name+'Callback',pvintf.symtable,pvintf);
insert_self_and_vmt_para(methoddef);
insert_funcret_para(methoddef);
{ can't be final/static/private/protected, and must be virtual { can't be final/static/private/protected, and must be virtual
since it's an interface method } since it's an interface method }
methoddef.procoptions:=methoddef.procoptions-[po_staticmethod,po_finalmethod]; methoddef.procoptions:=methoddef.procoptions-[po_staticmethod,po_finalmethod];
@ -436,6 +433,7 @@ implementation
vmtbuilder:=TVMTBuilder.Create(pvclass); vmtbuilder:=TVMTBuilder.Create(pvclass);
vmtbuilder.generate_vmt; vmtbuilder.generate_vmt;
vmtbuilder.free; vmtbuilder.free;
insert_struct_hidden_paras(pvclass);
restore_after_new_class(sstate,islocal,oldsymtablestack); restore_after_new_class(sstate,islocal,oldsymtablestack);
end; end;
@ -477,7 +475,7 @@ implementation
{ wrapper is part of the same symtable as the original procdef } { wrapper is part of the same symtable as the original procdef }
symtablestack.push(pd.owner); symtablestack.push(pd.owner);
{ get a copy of the virtual class method } { get a copy of the virtual class method }
wrapperpd:=tprocdef(pd.getcopy); wrapperpd:=tprocdef(pd.getcopyas(procdef,pc_normal_no_hidden,''));
{ this one is not virtual nor override } { this one is not virtual nor override }
exclude(wrapperpd.procoptions,po_virtualmethod); exclude(wrapperpd.procoptions,po_virtualmethod);
exclude(wrapperpd.procoptions,po_overridingmethod); exclude(wrapperpd.procoptions,po_overridingmethod);
@ -508,8 +506,8 @@ implementation
wrapperpd.synthetickind:=tsk_jvm_virtual_clmethod; wrapperpd.synthetickind:=tsk_jvm_virtual_clmethod;
wrapperpd.skpara:=pd; wrapperpd.skpara:=pd;
{ also create procvar type that we can use in the implementation } { also create procvar type that we can use in the implementation }
wrapperpv:=tcpuprocvardef(pd.getcopyas(procvardef,pc_normal,'')); wrapperpv:=tcpuprocvardef(pd.getcopyas(procvardef,pc_normal_no_hidden,''));
wrapperpv.calcparas; handle_calling_convention(wrapperpv,hcc_default_actions_intf);
{ no use in creating a callback wrapper here, this procvar type isn't { no use in creating a callback wrapper here, this procvar type isn't
for public consumption } for public consumption }
jvm_create_procvar_class_intern('__fpc_virtualclassmethod_pv_t'+wrapperpd.unique_id_str,wrapperpv,true); jvm_create_procvar_class_intern('__fpc_virtualclassmethod_pv_t'+wrapperpd.unique_id_str,wrapperpv,true);
@ -551,11 +549,6 @@ implementation
in callnodes, we will have to replace the calls to virtual in callnodes, we will have to replace the calls to virtual
constructors with calls to the wrappers) } constructors with calls to the wrappers) }
finish_copied_procdef(wrapperpd,pd.procsym.realname+'__fpcvirtconstrwrapper__',pd.owner,tabstractrecorddef(pd.owner.defowner)); finish_copied_procdef(wrapperpd,pd.procsym.realname+'__fpcvirtconstrwrapper__',pd.owner,tabstractrecorddef(pd.owner.defowner));
{ since it was a bare copy, insert the self parameter (we can't just
copy the vmt parameter from the constructor, that's different) }
insert_self_and_vmt_para(wrapperpd);
insert_funcret_para(wrapperpd);
wrapperpd.calcparas;
{ implementation: call through to the constructor { implementation: call through to the constructor
Exception: if the current class is abstract, do not call the Exception: if the current class is abstract, do not call the
constructor, since abstract class cannot be constructed (and the constructor, since abstract class cannot be constructed (and the

View File

@ -334,7 +334,7 @@ implementation
proc_add_definition will give an error } proc_add_definition will give an error }
end; end;
{ add method with the correct visibility } { add method with the correct visibility }
pd:=tprocdef(parentpd.getcopy); pd:=tprocdef(parentpd.getcopyas(procdef,pc_normal_no_hidden,''));
{ get rid of the import accessorname for inherited virtual class methods, { get rid of the import accessorname for inherited virtual class methods,
it has to be regenerated rather than amended } it has to be regenerated rather than amended }
if [po_classmethod,po_virtualmethod]<=pd.procoptions then if [po_classmethod,po_virtualmethod]<=pd.procoptions then
@ -394,7 +394,7 @@ implementation
begin begin
{ getter/setter could have parameters in case of indexed access { getter/setter could have parameters in case of indexed access
-> copy original procdef } -> copy original procdef }
pd:=tprocdef(orgaccesspd.getcopy); pd:=tprocdef(orgaccesspd.getcopyas(procdef,pc_normal_no_hidden,''));
exclude(pd.procoptions,po_abstractmethod); exclude(pd.procoptions,po_abstractmethod);
exclude(pd.procoptions,po_overridingmethod); exclude(pd.procoptions,po_overridingmethod);
{ can only construct the artificial accessorname now, because it requires { can only construct the artificial accessorname now, because it requires
@ -488,11 +488,8 @@ implementation
done already } done already }
if not assigned(orgaccesspd) then if not assigned(orgaccesspd) then
begin begin
{ calling convention, self, ... } { calling convention }
if obj.typ=recorddef then handle_calling_convention(pd,hcc_default_actions_intf_struct);
handle_calling_convention(pd,[hcc_declaration,hcc_check])
else
handle_calling_convention(pd,hcc_default_actions_intf);
{ register forward declaration with procsym } { register forward declaration with procsym }
proc_add_definition(pd); proc_add_definition(pd);
end; end;
@ -692,7 +689,6 @@ implementation
the JVM, this only sets the importname, however) } the JVM, this only sets the importname, however) }
if assigned(paras) then if assigned(paras) then
begin begin
init_paraloc_info(callerside);
for i:=0 to paras.count-1 do for i:=0 to paras.count-1 do
begin begin
vs:=tparavarsym(paras[i]); vs:=tparavarsym(paras[i]);

View File

@ -888,6 +888,7 @@ implementation
vmtbuilder:=TVMTBuilder.Create(tobjectdef(hdef)); vmtbuilder:=TVMTBuilder.Create(tobjectdef(hdef));
vmtbuilder.generate_vmt; vmtbuilder.generate_vmt;
vmtbuilder.free; vmtbuilder.free;
insert_struct_hidden_paras(tobjectdef(hdef));
end; end;
{ In case of an objcclass, verify that all methods have a message { In case of an objcclass, verify that all methods have a message

View File

@ -72,19 +72,20 @@ implementation
recorddef: recorddef:
begin begin
parse_record_proc_directives(pd); parse_record_proc_directives(pd);
// we can't add hidden params here because record is not yet defined
// and therefore record size which has influence on paramter passing rules may change too
// look at record_dec to see where calling conventions are applied (issue #0021044)
handle_calling_convention(pd,[hcc_declaration,hcc_check]);
end; end;
objectdef: objectdef:
begin begin
parse_object_proc_directives(pd); parse_object_proc_directives(pd);
handle_calling_convention(pd,hcc_default_actions_intf);
end end
else else
internalerror(2011040502); internalerror(2011040502);
end; end;
// We can't add hidden params here because record is not yet defined
// and therefore record size which has influence on paramter passing rules may change too
// look at record_dec to see where calling conventions are applied (issue #0021044).
// The same goes for objects/classes due to the calling convention that may only be set
// later (mantis #35233).
handle_calling_convention(pd,hcc_default_actions_intf_struct);
{ add definition to procsym } { add definition to procsym }
proc_add_definition(pd); proc_add_definition(pd);
@ -923,7 +924,7 @@ implementation
is_classdef and not (po_staticmethod in result.procoptions) then is_classdef and not (po_staticmethod in result.procoptions) then
MessagePos(result.fileinfo,parser_e_class_methods_only_static_in_records); MessagePos(result.fileinfo,parser_e_class_methods_only_static_in_records);
handle_calling_convention(result,hcc_default_actions_intf); handle_calling_convention(result,hcc_default_actions_intf_struct);
{ add definition to procsym } { add definition to procsym }
proc_add_definition(result); proc_add_definition(result);

View File

@ -1696,7 +1696,7 @@ implementation
// we can't add hidden params here because record is not yet defined // we can't add hidden params here because record is not yet defined
// and therefore record size which has influence on paramter passing rules may change too // and therefore record size which has influence on paramter passing rules may change too
// look at record_dec to see where calling conventions are applied (issue #0021044) // look at record_dec to see where calling conventions are applied (issue #0021044)
handle_calling_convention(result,[hcc_declaration,hcc_check]); handle_calling_convention(result,hcc_default_actions_intf_struct);
{ add definition to procsym } { add definition to procsym }
proc_add_definition(result); proc_add_definition(result);

View File

@ -260,7 +260,10 @@ implementation
var var
sym: tprocsym; sym: tprocsym;
begin begin
handle_calling_convention(pd,hcc_default_actions_intf); if not assigned(astruct) then
handle_calling_convention(pd,hcc_default_actions_intf)
else
handle_calling_convention(pd,hcc_default_actions_intf_struct);
sym:=cprocsym.create(prefix+lower(p.realname)); sym:=cprocsym.create(prefix+lower(p.realname));
symtablestack.top.insert(sym); symtablestack.top.insert(sym);
pd.procsym:=sym; pd.procsym:=sym;
@ -539,7 +542,10 @@ implementation
begin begin
readprocdef.returndef:=p.propdef; readprocdef.returndef:=p.propdef;
{ Insert hidden parameters } { Insert hidden parameters }
handle_calling_convention(readprocdef,hcc_default_actions_intf); if assigned(astruct) then
handle_calling_convention(readprocdef,hcc_default_actions_intf_struct)
else
handle_calling_convention(readprocdef,hcc_default_actions_intf);
end; end;
p.add_getter_or_setter_for_sym(palt_read,sym,def,readprocdef); p.add_getter_or_setter_for_sym(palt_read,sym,def,readprocdef);
end; end;
@ -562,7 +568,10 @@ implementation
hparavs:=cparavarsym.create('$value',10*paranr,vs_value,p.propdef,[]); hparavs:=cparavarsym.create('$value',10*paranr,vs_value,p.propdef,[]);
writeprocdef.parast.insert(hparavs); writeprocdef.parast.insert(hparavs);
{ Insert hidden parameters } { Insert hidden parameters }
handle_calling_convention(writeprocdef,hcc_default_actions_intf); if not assigned(astruct) then
handle_calling_convention(writeprocdef,hcc_default_actions_intf)
else
handle_calling_convention(writeprocdef,hcc_default_actions_intf_struct);
end; end;
p.add_getter_or_setter_for_sym(palt_write,sym,def,writeprocdef); p.add_getter_or_setter_for_sym(palt_write,sym,def,writeprocdef);
end; end;
@ -650,7 +659,10 @@ implementation
end; end;
{ Insert hidden parameters } { Insert hidden parameters }
handle_calling_convention(storedprocdef,hcc_default_actions_intf); if not assigned(astruct) then
handle_calling_convention(storedprocdef,hcc_default_actions_intf)
else
handle_calling_convention(storedprocdef,hcc_default_actions_intf_struct);
p.propaccesslist[palt_stored].procdef:=Tprocsym(sym).Find_procdef_bypara(storedprocdef.paras,storedprocdef.returndef,[cpo_allowdefaults,cpo_ignorehidden]); p.propaccesslist[palt_stored].procdef:=Tprocsym(sym).Find_procdef_bypara(storedprocdef.paras,storedprocdef.returndef,[cpo_allowdefaults,cpo_ignorehidden]);
if not assigned(p.propaccesslist[palt_stored].procdef) then if not assigned(p.propaccesslist[palt_stored].procdef) then
message(parser_e_ill_property_storage_sym); message(parser_e_ill_property_storage_sym);

View File

@ -1059,6 +1059,7 @@ uses
vmtbuilder:=TVMTBuilder.Create(tobjectdef(result)); vmtbuilder:=TVMTBuilder.Create(tobjectdef(result));
vmtbuilder.generate_vmt; vmtbuilder.generate_vmt;
vmtbuilder.free; vmtbuilder.free;
insert_struct_hidden_paras(tobjectdef(result));
end; end;
{ handle params, calling convention, etc } { handle params, calling convention, etc }
procvardef: procvardef:

View File

@ -34,7 +34,7 @@ interface
procedure insert_funcret_local(pd:tprocdef); procedure insert_funcret_local(pd:tprocdef);
procedure insert_hidden_para(p:TObject;arg:pointer); procedure insert_hidden_para(p:TObject;arg:pointer);
procedure check_c_para(pd:Tabstractprocdef); procedure check_c_para(pd:Tabstractprocdef);
procedure insert_record_hidden_paras(astruct: trecorddef); procedure insert_struct_hidden_paras(astruct: tabstractrecorddef);
type type
// flags of the *handle_calling_convention routines // flags of the *handle_calling_convention routines
@ -47,6 +47,7 @@ interface
const const
hcc_default_actions_intf=[hcc_declaration,hcc_check,hcc_insert_hidden_paras]; hcc_default_actions_intf=[hcc_declaration,hcc_check,hcc_insert_hidden_paras];
hcc_default_actions_intf_struct=hcc_default_actions_intf-[hcc_insert_hidden_paras];
hcc_default_actions_impl=[hcc_check,hcc_insert_hidden_paras]; hcc_default_actions_impl=[hcc_check,hcc_insert_hidden_paras];
hcc_default_actions_parse=[hcc_check,hcc_insert_hidden_paras]; hcc_default_actions_parse=[hcc_check,hcc_insert_hidden_paras];
PD_VIRTUAL_MUTEXCLPO = [po_interrupt,po_exports,po_overridingmethod,po_inline,po_staticmethod]; PD_VIRTUAL_MUTEXCLPO = [po_interrupt,po_exports,po_overridingmethod,po_inline,po_staticmethod];
@ -448,7 +449,7 @@ implementation
end; end;
procedure insert_record_hidden_paras(astruct: trecorddef); procedure insert_struct_hidden_paras(astruct: tabstractrecorddef);
var var
pd: tdef; pd: tdef;
i: longint; i: longint;
@ -570,6 +571,13 @@ implementation
if hcc_insert_hidden_paras in flags then if hcc_insert_hidden_paras in flags then
begin begin
{ If the paraloc info has been calculated already, it will be missing for
the new parameters we add below. This should never be necessary before
we add them, as users of this information would not process these extra
parameters in that case }
if pd.has_paraloc_info<>callnoside then
internalerror(2019031610);
{ insert hidden high parameters } { insert hidden high parameters }
pd.parast.SymList.ForEachCall(@insert_hidden_para,pd); pd.parast.SymList.ForEachCall(@insert_hidden_para,pd);
@ -1086,7 +1094,7 @@ implementation
representable in source form and we don't need them anyway } representable in source form and we don't need them anyway }
symtablestack.push(trecorddef(nestedvarsdef).symtable); symtablestack.push(trecorddef(nestedvarsdef).symtable);
maybe_add_public_default_java_constructor(trecorddef(nestedvarsdef)); maybe_add_public_default_java_constructor(trecorddef(nestedvarsdef));
insert_record_hidden_paras(trecorddef(nestedvarsdef)); insert_struct_hidden_paras(trecorddef(nestedvarsdef));
symtablestack.pop(trecorddef(nestedvarsdef).symtable); symtablestack.pop(trecorddef(nestedvarsdef).symtable);
{$endif} {$endif}
symtablestack.free; symtablestack.free;

View File

@ -1051,7 +1051,7 @@ implementation
{ don't keep track of procdefs in a separate list, because the { don't keep track of procdefs in a separate list, because the
compiler may add additional procdefs (e.g. property wrappers for compiler may add additional procdefs (e.g. property wrappers for
the jvm backend) } the jvm backend) }
insert_record_hidden_paras(trecorddef(current_structdef)); insert_struct_hidden_paras(trecorddef(current_structdef));
{ restore symtable stack } { restore symtable stack }
symtablestack.pop(recst); symtablestack.pop(recst);
if trecorddef(current_structdef).is_packed and is_managed_type(current_structdef) then if trecorddef(current_structdef).is_packed and is_managed_type(current_structdef) then

View File

@ -352,7 +352,7 @@ implementation
end; end;
{ if we get here, we did not find it in the current objectdef -> { if we get here, we did not find it in the current objectdef ->
add } add }
childpd:=tprocdef(parentpd.getcopy); childpd:=tprocdef(parentpd.getcopyas(procdef,pc_normal_no_hidden,''));
{ get rid of the import name for inherited virtual class methods, { get rid of the import name for inherited virtual class methods,
it has to be regenerated rather than amended } it has to be regenerated rather than amended }
if [po_classmethod,po_virtualmethod]<=childpd.procoptions then if [po_classmethod,po_virtualmethod]<=childpd.procoptions then

View File

@ -590,6 +590,8 @@ interface
pno_mangledname, pno_noparams); pno_mangledname, pno_noparams);
tprocnameoptions = set of tprocnameoption; tprocnameoptions = set of tprocnameoption;
tproccopytyp = (pc_normal, tproccopytyp = (pc_normal,
{ everything except for hidden parameters }
pc_normal_no_hidden,
{ always creates a top-level function, removes all { always creates a top-level function, removes all
special parameters (self, vmt, parentfp, ...) } special parameters (self, vmt, parentfp, ...) }
pc_bareproc, pc_bareproc,
@ -5197,7 +5199,7 @@ implementation
pvs:=tparavarsym(parast.symlist[j]); pvs:=tparavarsym(parast.symlist[j]);
{ in case of bare proc, don't copy self, vmt or framepointer { in case of bare proc, don't copy self, vmt or framepointer
parameters } parameters }
if (copytyp=pc_bareproc) and if (copytyp in [pc_bareproc,pc_normal_no_hidden]) and
(([vo_is_self,vo_is_vmt,vo_is_parentfp,vo_is_result,vo_is_funcret]*pvs.varoptions)<>[]) then (([vo_is_self,vo_is_vmt,vo_is_parentfp,vo_is_result,vo_is_funcret]*pvs.varoptions)<>[]) then
continue; continue;
if paraprefix='' then if paraprefix='' then
@ -6144,7 +6146,7 @@ implementation
{ don't create aliases for bare copies, nor copy the funcretsym as { don't create aliases for bare copies, nor copy the funcretsym as
the function result parameter will be inserted again if necessary the function result parameter will be inserted again if necessary
(e.g. if the calling convention is changed) } (e.g. if the calling convention is changed) }
if copytyp<>pc_bareproc then if not(copytyp in [pc_bareproc,pc_normal_no_hidden]) then
begin begin
tprocdef(result).aliasnames.concatListcopy(aliasnames); tprocdef(result).aliasnames.concatListcopy(aliasnames);
if assigned(funcretsym) then if assigned(funcretsym) then

63
tests/webtbs/tw35233.pp Normal file
View File

@ -0,0 +1,63 @@
//
// Submitted by:
//
// Gerrit Moeller
// [private]@gm-software.de
// www.gm-software.de
//
{$MODE DELPHI} // <- Without delphi mode the parser correctly issues an error if stdcall is not repeated
// in overriding method (see below).
program FPCIntfStdcallOverrideCrash;
type
ISomeMethod = interface(IUnknown)
['{DBFB482B-76FB-4DB7-A321-1001755B1F9E}']
function SomeMethod(const AIntArg: Integer; const AStrArg: WideString): IUnknown; stdcall;
end;
TBaseClassImpl = class(TInterfacedObject, ISomeMethod)
public
function SomeMethod(const AIntArg: Integer; const AStrArg: WideString): IUnknown; virtual; stdcall;
end;
TDerivedClassImpl = class(TBaseClassImpl)
public
//
// In delphi mode it is not neccessary to repeat stdcall calling convention in the overriding method.
// But the compiler then generates a call stack with another calling convention for the overriding method!
// If you call the overriding method through an interface this crashes (SIGSEV) since it is supposed to be stdcall!
// Repeating the calling convention in the overriding method fixes the crash.
//
function SomeMethod(const AIntArg: Integer; const AStrArg: WideString): IUnknown; override; // stdcall; // <- uncommenting stdcall fixes the crash
end;
function TBaseClassImpl.SomeMethod(const AIntArg: Integer; const AStrArg: WideString): IUnknown; stdcall;
begin
// Arguments corrupt here due to call stack mismatch!
Result := nil; // <- SIGSEV crash here due to call stack mismatch!
end;
function TDerivedClassImpl.SomeMethod(const AIntArg: Integer; const AStrArg: WideString): IUnknown;
begin
// Arguments corrupt here due to call stack mismatch!
Result := inherited SomeMethod(AIntArg, AStrArg);
end;
procedure Main;
var methodIntf: ISomeMethod; unk: IUnknown;
begin
methodIntf := TDerivedClassImpl.Create;
unk := methodIntf.SomeMethod(100, 'Some string contents');
end;
begin
Main;
end.