* store the used tabstractprocdef when generating an llvm call instruction,

because due to aliasing symbols a single symbol may be called using
    different procdefs (e.g. FPC_ANSISTR_UNIQUE in the system unit is defined
    as an alias for a function and called as a procedure). This means we have
    to insert extra type conversions for llvm, which requires both the source
    and destination type

git-svn-id: trunk@30776 -
This commit is contained in:
Jonas Maebe 2015-05-03 16:50:43 +00:00
parent 6662cb6dd5
commit 72277f5098
3 changed files with 37 additions and 24 deletions

View File

@ -105,9 +105,9 @@ interface
constructor getelementptr_reg_tai_size_const(dst:tregister;const ai:tai;indextype:tdef;index1:ptrint;indirect:boolean); constructor getelementptr_reg_tai_size_const(dst:tregister;const ai:tai;indextype:tdef;index1:ptrint;indirect:boolean);
{ e.g. dst = call retsize name (paras) } { e.g. dst = call retsize name (paras) }
constructor call_size_name_paras(dst: tregister;retsize: tdef;name:tasmsymbol;paras: tfplist); constructor call_size_name_paras(callpd: tdef; dst: tregister;retsize: tdef;name:tasmsymbol;paras: tfplist);
{ e.g. dst = call retsize reg (paras) } { e.g. dst = call retsize reg (paras) }
constructor call_size_reg_paras(dst: tregister;retsize: tdef;reg:tregister;paras: tfplist); constructor call_size_reg_paras(callpd: tdef; dst: tregister;retsize: tdef;reg:tregister;paras: tfplist);
procedure loadoper(opidx: longint; o: toper); override; procedure loadoper(opidx: longint; o: toper); override;
procedure clearop(opidx: longint); override; procedure clearop(opidx: longint); override;
@ -924,25 +924,32 @@ uses
end; end;
constructor taillvm.call_size_name_paras(dst: tregister; retsize: tdef; name:tasmsymbol; paras: tfplist); constructor taillvm.call_size_name_paras(callpd: tdef; dst: tregister; retsize: tdef; name:tasmsymbol; paras: tfplist);
begin begin
create_llvm(la_call); create_llvm(la_call);
ops:=4; ops:=5;
loadreg(0,dst); { we need this in case the call symbol is an alias for a symbol with a
loaddef(1,retsize); different def in the same module (via "external"), because then we
loadsymbol(2,name,0); have to insert a type conversion later from the alias def to the
loadparas(3,paras); call def here; we can't always do that at the point the call itself
is generated, because the alias declaration may occur anywhere }
loaddef(0,callpd);
loadreg(1,dst);
loaddef(2,retsize);
loadsymbol(3,name,0);
loadparas(4,paras);
end; end;
constructor taillvm.call_size_reg_paras(dst: tregister; retsize: tdef; reg: tregister; paras: tfplist); constructor taillvm.call_size_reg_paras(callpd: tdef; dst: tregister; retsize: tdef; reg: tregister; paras: tfplist);
begin begin
create_llvm(la_call); create_llvm(la_call);
ops:=4; ops:=5;
loadreg(0,dst); loaddef(0,callpd);
loaddef(1,retsize); loadreg(1,dst);
loadreg(2,reg); loaddef(2,retsize);
loadparas(3,paras); loadreg(3,reg);
loadparas(4,paras);
end; end;
end. end.

View File

@ -374,10 +374,10 @@ implementation
end; end;
la_call: la_call:
begin begin
if taillvm(hp).oper[0]^.reg<>NR_NO then if taillvm(hp).oper[1]^.reg<>NR_NO then
owner.AsmWrite(getregisterstring(taillvm(hp).oper[0]^.reg)+' = '); owner.AsmWrite(getregisterstring(taillvm(hp).oper[1]^.reg)+' = ');
sep:=' '; sep:=' ';
opstart:=1; opstart:=2;
end; end;
la_alloca: la_alloca:
begin begin

View File

@ -314,6 +314,16 @@ implementation
end; end;
function get_call_pd(pd: tabstractprocdef): tdef;
begin
if (pd.typ=procdef) or
not pd.is_addressonly then
result:=pd.getcopyas(procvardef,pc_address_only)
else
result:=pd
end;
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 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); procedure load_ref_anyreg(def: tdef; const ref: treference; reg: tregister; var callpara: pllvmcallpara);
@ -417,11 +427,7 @@ implementation
((pd.proccalloption in cdecl_pocalls) and ((pd.proccalloption in cdecl_pocalls) and
(pd.paras.count>0) and (pd.paras.count>0) and
is_array_of_const(tparavarsym(pd.paras[pd.paras.count-1]).vardef)) then is_array_of_const(tparavarsym(pd.paras[pd.paras.count-1]).vardef)) then
if (pd.typ=procdef) or calldef:=get_call_pd(pd)
not pd.is_addressonly then
calldef:=pd.getcopyas(procvardef,pc_address_only)
else
calldef:=pd
else else
calldef:=llvmretdef; calldef:=llvmretdef;
end; end;
@ -445,7 +451,7 @@ implementation
current_asmdata.AsmLists[al_imports].Concat(taillvmdecl.create(asmsym,pd,nil,sec_code,pd.alignment)); current_asmdata.AsmLists[al_imports].Concat(taillvmdecl.create(asmsym,pd,nil,sec_code,pd.alignment));
end; end;
a_call_common(list,pd,paras,forceresdef,res,calldef,hlretdef,llvmretdef,callparas); 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)); list.concat(taillvm.call_size_name_paras(get_call_pd(pd),res,calldef,current_asmdata.RefAsmSymbol(pd.mangledname),callparas));
result:=get_call_result_cgpara(pd,forceresdef); result:=get_call_result_cgpara(pd,forceresdef);
set_call_function_result(list,pd,llvmretdef,hlretdef,res,result); set_call_function_result(list,pd,llvmretdef,hlretdef,res,result);
end; end;
@ -460,7 +466,7 @@ implementation
res: tregister; res: tregister;
begin begin
a_call_common(list,pd,paras,nil,res,calldef,hlretdef,llvmretdef,callparas); a_call_common(list,pd,paras,nil,res,calldef,hlretdef,llvmretdef,callparas);
list.concat(taillvm.call_size_reg_paras(res,calldef,reg,callparas)); list.concat(taillvm.call_size_reg_paras(get_call_pd(pd),res,calldef,reg,callparas));
result:=get_call_result_cgpara(pd,nil); result:=get_call_result_cgpara(pd,nil);
set_call_function_result(list,pd,llvmretdef,hlretdef,res,result); set_call_function_result(list,pd,llvmretdef,hlretdef,res,result);
end; end;