mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-10 04:49:07 +02:00
* factored out the common calling code from a_call_name (to reuse in
a_call_reg() git-svn-id: branches/hlcgllvm@28478 -
This commit is contained in:
parent
b6fc2f1542
commit
bd3f0b3ada
@ -27,7 +27,7 @@ unit hlcgllvm;
|
||||
interface
|
||||
|
||||
uses
|
||||
globtype,
|
||||
globtype,cclasses,
|
||||
aasmbase,aasmdata,
|
||||
symbase,symconst,symtype,symdef,symsym,
|
||||
cpubase, hlcgobj, cgbase, cgutils, parabase;
|
||||
@ -48,6 +48,9 @@ uses
|
||||
procedure alloccpuregisters(list: TAsmList; rt: Tregistertype; const r: Tcpuregisterset); override;
|
||||
procedure deallocallcpuregisters(list: TAsmList); override;
|
||||
|
||||
protected
|
||||
procedure a_call_common(list: TAsmList; pd: tabstractprocdef; const paras: array of pcgpara; const forceresdef: tdef; out res: tregister; out calldef: tdef; out hlretdef: tdef; out llvmretdef: tdef; out callparas: tfplist);
|
||||
public
|
||||
function a_call_name(list : TAsmList;pd : tprocdef;const s : TSymStr; const paras: array of pcgpara; forceresdef: tdef; weak: boolean): tcgpara;override;
|
||||
function a_call_reg(list: TAsmList; pd: tabstractprocdef; reg: tregister; const paras: array of pcgpara): tcgpara; override;
|
||||
|
||||
@ -131,7 +134,7 @@ uses
|
||||
implementation
|
||||
|
||||
uses
|
||||
verbose,cutils,cclasses,globals,fmodule,constexp,systems,
|
||||
verbose,cutils,globals,fmodule,constexp,systems,
|
||||
defutil,llvmdef,llvmsym,
|
||||
aasmtai,aasmcpu,
|
||||
aasmllvm,llvmbase,tgllvm,
|
||||
@ -292,7 +295,7 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
function thlcgllvm.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; const paras: array of pcgpara; forceresdef: tdef; weak: boolean): tcgpara;
|
||||
procedure thlcgllvm.a_call_common(list: TAsmList; pd: tabstractprocdef; const paras: array of pcgpara; const forceresdef: tdef; out res: tregister; out calldef: tdef; out hlretdef: tdef; out llvmretdef: tdef; out callparas: tfplist);
|
||||
|
||||
procedure load_ref_anyreg(def: tdef; const ref: treference; reg: tregister; var callpara: pllvmcallpara);
|
||||
begin
|
||||
@ -318,96 +321,107 @@ implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
i: longint;
|
||||
href: treference;
|
||||
callpara: pllvmcallpara;
|
||||
paraloc: pcgparalocation;
|
||||
begin
|
||||
callparas:=tfplist.Create;
|
||||
for i:=0 to high(paras) do
|
||||
begin
|
||||
paraloc:=paras[i]^.location;
|
||||
while assigned(paraloc) and
|
||||
(paraloc^.loc<>LOC_VOID) do
|
||||
begin
|
||||
new(callpara);
|
||||
callpara^.def:=paraloc^.def;
|
||||
llvmextractvalueextinfo(paras[i]^.def, callpara^.def, callpara^.valueext);
|
||||
callpara^.loc:=paraloc^.loc;
|
||||
case callpara^.loc of
|
||||
LOC_REFERENCE:
|
||||
begin
|
||||
if paraloc^.llvmvalueloc then
|
||||
internalerror(2014012307)
|
||||
else
|
||||
begin
|
||||
reference_reset_base(href, getpointerdef(callpara^.def), paraloc^.reference.index, paraloc^.reference.offset, paraloc^.def.alignment);
|
||||
res:=getregisterfordef(list, paraloc^.def);
|
||||
load_ref_anyreg(callpara^.def, href, res, callpara);
|
||||
end;
|
||||
callpara^.reg:=res
|
||||
end;
|
||||
LOC_REGISTER,
|
||||
LOC_FPUREGISTER,
|
||||
LOC_MMREGISTER:
|
||||
begin
|
||||
{ undo explicit value extension }
|
||||
if callpara^.valueext<>lve_none then
|
||||
begin
|
||||
res:=getregisterfordef(list, callpara^.def);
|
||||
a_load_reg_reg(list, paraloc^.def, callpara^.def, paraloc^.register, res);
|
||||
paraloc^.register:=res;
|
||||
end;
|
||||
callpara^.reg:=paraloc^.register
|
||||
end;
|
||||
else
|
||||
internalerror(2014010605);
|
||||
end;
|
||||
callparas.add(callpara);
|
||||
paraloc:=paraloc^.next;
|
||||
end;
|
||||
end;
|
||||
{ the Pascal level may expect a different returndef compared to the
|
||||
declared one }
|
||||
if not assigned(forceresdef) then
|
||||
hlretdef:=pd.returndef
|
||||
else
|
||||
hlretdef:=forceresdef;
|
||||
{ llvm will always expect the original return def }
|
||||
if not paramanager.ret_in_param(hlretdef, pd) then
|
||||
llvmretdef:=llvmgetcgparadef(pd.funcretloc[callerside], true)
|
||||
else
|
||||
llvmretdef:=voidtype;
|
||||
if not is_void(llvmretdef) then
|
||||
res:=getregisterfordef(list, llvmretdef)
|
||||
else
|
||||
res:=NR_NO;
|
||||
|
||||
{ if this is a complex procvar, get the non-tmethod-like equivalent }
|
||||
if (pd.typ=procvardef) and
|
||||
not pd.is_addressonly then
|
||||
pd:=tprocvardef(pd.getcopyas(procvardef,pc_address_only));
|
||||
{ if the function returns a function pointer type or is varargs, we
|
||||
must specify the full function signature, otherwise we can only
|
||||
specify the return type }
|
||||
if (po_varargs in pd.procoptions) or
|
||||
((pd.proccalloption in cdecl_pocalls) and
|
||||
(pd.paras.count>0) and
|
||||
is_array_of_const(tparavarsym(pd.paras[pd.paras.count-1]).vardef)) then
|
||||
calldef:=pd
|
||||
else
|
||||
calldef:=llvmretdef;
|
||||
end;
|
||||
|
||||
|
||||
function thlcgllvm.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; const paras: array of pcgpara; forceresdef: tdef; weak: boolean): tcgpara;
|
||||
var
|
||||
callparas: tfplist;
|
||||
asmsym: tasmsymbol;
|
||||
llvmretdef,
|
||||
hlretdef,
|
||||
calldef: tdef;
|
||||
paraloc: pcgparalocation;
|
||||
callpara: pllvmcallpara;
|
||||
href: treference;
|
||||
res: tregister;
|
||||
i: longint;
|
||||
asmsym: tasmsymbol;
|
||||
begin
|
||||
if not pd.owner.iscurrentunit or
|
||||
(s<>pd.mangledname) or
|
||||
(po_external in pd.procoptions) then
|
||||
begin
|
||||
asmsym:=current_asmdata.RefAsmSymbol(pd.mangledname);
|
||||
asmsym:=current_asmdata.RefAsmSymbol(tprocdef(pd).mangledname);
|
||||
if not asmsym.declared then
|
||||
current_asmdata.AsmLists[al_imports].Concat(taillvmdecl.create(asmsym,pd,nil,sec_code));
|
||||
current_asmdata.AsmLists[al_imports].Concat(taillvmdecl.create(asmsym, pd, nil, sec_code));
|
||||
end;
|
||||
callparas:=tfplist.Create;
|
||||
for i:=0 to high(paras) do
|
||||
begin
|
||||
paraloc:=paras[i]^.location;
|
||||
while assigned(paraloc) and
|
||||
(paraloc^.loc<>LOC_VOID) do
|
||||
begin
|
||||
new(callpara);
|
||||
callpara^.def:=paraloc^.def;
|
||||
llvmextractvalueextinfo(paras[i]^.def,callpara^.def,callpara^.valueext);
|
||||
callpara^.loc:=paraloc^.loc;
|
||||
case callpara^.loc of
|
||||
LOC_REFERENCE:
|
||||
begin
|
||||
if paraloc^.llvmvalueloc then
|
||||
internalerror(2014012307)
|
||||
else
|
||||
begin
|
||||
reference_reset_base(href,getpointerdef(callpara^.def),paraloc^.reference.index,paraloc^.reference.offset,paraloc^.def.alignment);
|
||||
res:=getregisterfordef(list,paraloc^.def);
|
||||
load_ref_anyreg(callpara^.def,href,res,callpara);
|
||||
end;
|
||||
callpara^.reg:=res
|
||||
end;
|
||||
LOC_REGISTER,
|
||||
LOC_FPUREGISTER,
|
||||
LOC_MMREGISTER:
|
||||
begin
|
||||
{ undo explicit value extension }
|
||||
if callpara^.valueext<>lve_none then
|
||||
begin
|
||||
res:=getregisterfordef(list,callpara^.def);
|
||||
a_load_reg_reg(list,paraloc^.def,callpara^.def,paraloc^.register,res);
|
||||
paraloc^.register:=res;
|
||||
end;
|
||||
callpara^.reg:=paraloc^.register
|
||||
end;
|
||||
else
|
||||
internalerror(2014010605);
|
||||
end;
|
||||
callparas.add(callpara);
|
||||
paraloc:=paraloc^.next;
|
||||
end;
|
||||
end;
|
||||
{ the Pascal level may expect a different returndef compared to the
|
||||
declared one }
|
||||
if not assigned(forceresdef) then
|
||||
hlretdef:=pd.returndef
|
||||
else
|
||||
hlretdef:=forceresdef;
|
||||
{ llvm will always expect the original return def }
|
||||
if not paramanager.ret_in_param(hlretdef,pd) then
|
||||
llvmretdef:=llvmgetcgparadef(pd.funcretloc[callerside],true)
|
||||
else
|
||||
llvmretdef:=voidtype;
|
||||
if not is_void(llvmretdef) then
|
||||
res:=getregisterfordef(list,llvmretdef)
|
||||
else
|
||||
res:=NR_NO;
|
||||
|
||||
{ if the function returns a function pointer type or is varargs, we
|
||||
must specify the full function signature, otherwise we can only
|
||||
specify the return type }
|
||||
if (po_varargs in pd.procoptions) or
|
||||
((pd.proccalloption in cdecl_pocalls) and
|
||||
(pd.paras.count>0) and
|
||||
is_array_of_const(tparavarsym(pd.paras[pd.paras.count-1]).vardef)) then
|
||||
calldef:=pd
|
||||
else
|
||||
calldef:=llvmretdef;
|
||||
a_call_common(list,pd,paras,forceresdef,res,calldef,hlretdef,llvmretdef,callparas);
|
||||
list.concat(taillvm.call_size_name_paras(res,calldef,current_asmdata.RefAsmSymbol(pd.mangledname),callparas));
|
||||
result:=get_call_result_cgpara(pd,forceresdef);
|
||||
set_call_function_result(list,pd,llvmretdef,hlretdef,res,result);
|
||||
|
Loading…
Reference in New Issue
Block a user