* further (final?) reworking of llvm external symbol handling:

o all external symbol definitions are now inserted in the llvmtype post pass
     based on all declarations and types used in llvm instructions
   o this means we don't have to use the workaround with the Pascal mangled
     names anymore for all external names, as we now insert the external
     references only once we know all type information

git-svn-id: trunk@31287 -
This commit is contained in:
Jonas Maebe 2015-08-05 21:06:01 +00:00
parent 6dcf61f057
commit bfa94ae908
3 changed files with 88 additions and 58 deletions

View File

@ -35,9 +35,6 @@ interface
type type
{ taillvm } { taillvm }
taillvm = class(tai_cpu_abstract_sym) taillvm = class(tai_cpu_abstract_sym)
private
procedure maybe_declare(def: tdef; const ref: treference);
public
llvmopcode: tllvmop; llvmopcode: tllvmop;
constructor create_llvm(op: tllvmop); constructor create_llvm(op: tllvmop);
@ -234,23 +231,6 @@ uses
taicpu Constructors taicpu Constructors
*****************************************************************************} *****************************************************************************}
procedure taillvm.maybe_declare(def: tdef; const ref: treference);
begin
{ add llvm declarations for imported symbols }
if not assigned(ref.symbol) or
(ref.symbol.declared) or
not(ref.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) then
exit;
if ref.refaddr<>addr_full then
begin
if def.typ<>pointerdef then
internalerror(2014020701);
def:=tpointerdef(def).pointeddef;
end;
current_asmdata.AsmLists[al_imports].concat(taillvmdecl.create(ref.symbol,def,nil,sec_none,def.alignment));
end;
constructor taillvm.create_llvm(op: tllvmop); constructor taillvm.create_llvm(op: tllvmop);
begin begin
create(a_none); create(a_none);
@ -731,7 +711,6 @@ uses
create_llvm(op); create_llvm(op);
ops:=4; ops:=4;
loadreg(0,dst); loadreg(0,dst);
maybe_declare(fromsize,src);
loaddef(1,fromsize); loaddef(1,fromsize);
loadref(2,src); loadref(2,src);
loaddef(3,tosize); loaddef(3,tosize);
@ -745,7 +724,6 @@ uses
ops:=4; ops:=4;
loaddef(0,fromsize); loaddef(0,fromsize);
loadreg(1,src); loadreg(1,src);
maybe_declare(ptrsize,toref);
loaddef(2,ptrsize); loaddef(2,ptrsize);
loadref(3,toref); loadref(3,toref);
end; end;
@ -755,10 +733,8 @@ uses
begin begin
create_llvm(op); create_llvm(op);
ops:=4; ops:=4;
maybe_declare(fromsize,src);
loaddef(0,fromsize); loaddef(0,fromsize);
loadref(1,src); loadref(1,src);
maybe_declare(ptrsize,toref);
loaddef(2,ptrsize); loaddef(2,ptrsize);
loadref(3,toref); loadref(3,toref);
end; end;
@ -770,7 +746,6 @@ uses
ops:=4; ops:=4;
loaddef(0,fromsize); loaddef(0,fromsize);
loadconst(1,src); loadconst(1,src);
maybe_declare(ptrsize,toref);
loaddef(2,ptrsize); loaddef(2,ptrsize);
loadref(3,toref); loadref(3,toref);
end; end;
@ -781,7 +756,6 @@ uses
create_llvm(op); create_llvm(op);
ops:=3; ops:=3;
loadreg(0,dst); loadreg(0,dst);
maybe_declare(fromsize,fromref);
loaddef(1,fromsize); loaddef(1,fromsize);
loadref(2,fromref); loadref(2,fromref);
end; end;
@ -859,7 +833,6 @@ uses
else else
ops:=5; ops:=5;
loadreg(0,dst); loadreg(0,dst);
maybe_declare(ptrsize,ref);
loaddef(1,ptrsize); loaddef(1,ptrsize);
loadref(2,ref); loadref(2,ref);
if indirect then if indirect then
@ -885,7 +858,6 @@ uses
else else
ops:=5; ops:=5;
loadreg(0,dst); loadreg(0,dst);
maybe_declare(ptrsize,ref);
loaddef(1,ptrsize); loaddef(1,ptrsize);
loadref(2,ref); loadref(2,ref);
if indirect then if indirect then

View File

@ -319,7 +319,14 @@ implementation
begin begin
if (pd.typ=procdef) or if (pd.typ=procdef) or
not pd.is_addressonly then not pd.is_addressonly then
result:=cprocvardef.getreusableprocaddr(pd) { we get a pointerdef rather than a procvardef so that if we have to
insert an external declaration for this procdef in llvmtype, we don't
have to create another procdef from the procvardef we've just created.
With a pointerdef, we can just get the pointeddef again. A pointerdef
is also much cheaper to create, and in llvm a provardef is a "function
pointer", so a pointer to a procdef is the same as a procvar as far
as llvm is concerned }
result:=cpointerdef.getreusable(pd)
else else
result:=pd result:=pd
end; end;
@ -437,19 +444,11 @@ implementation
function thlcgllvm.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; const paras: array of pcgpara; forceresdef: tdef; weak: boolean): tcgpara; function thlcgllvm.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; const paras: array of pcgpara; forceresdef: tdef; weak: boolean): tcgpara;
var var
callparas: tfplist; callparas: tfplist;
asmsym: tasmsymbol;
llvmretdef, llvmretdef,
hlretdef, hlretdef,
calldef: tdef; calldef: tdef;
res: tregister; res: tregister;
begin begin
if not pd.owner.iscurrentunit then
begin
asmsym:=current_asmdata.RefAsmSymbol(tprocdef(pd).mangledname);
if (not asmsym.declared) and
(asmsym.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) then
current_asmdata.AsmLists[al_imports].Concat(taillvmdecl.create(asmsym,pd,nil,sec_code,pd.alignment));
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(get_call_pd(pd),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);

View File

@ -82,10 +82,11 @@ interface
procedure collect_tai_info(deftypelist: tasmlist; p: tai); procedure collect_tai_info(deftypelist: tasmlist; p: tai);
procedure collect_asmlist_info(deftypelist, asmlist: tasmlist); procedure collect_asmlist_info(deftypelist, asmlist: tasmlist);
procedure insert_llvmins_typeconversions(p: taillvm); procedure insert_llvmins_typeconversions(toplevellist: tasmlist; p: taillvm);
procedure insert_typedconst_typeconversion(p: tai_abstracttypedconst); procedure insert_typedconst_typeconversion(toplevellist: tasmlist; p: tai_abstracttypedconst);
procedure insert_tai_typeconversions(p: tai); procedure insert_tai_typeconversions(toplevellist: tasmlist; p: tai);
procedure insert_asmlist_typeconversions(list: tasmlist); procedure insert_asmlist_typeconversions(toplevellist, list: tasmlist);
procedure maybe_insert_extern_sym_decl(toplevellist: tasmlist; sym: tasmsymbol; def: tdef);
procedure update_asmlist_alias_types(list: tasmlist); procedure update_asmlist_alias_types(list: tasmlist);
public public
@ -169,6 +170,7 @@ implementation
end; end;
end; end;
procedure TLLVMTypeInfo.collect_llvmins_info(deftypelist: tasmlist; p: taillvm); procedure TLLVMTypeInfo.collect_llvmins_info(deftypelist: tasmlist; p: taillvm);
var var
opidx, paraidx: longint; opidx, paraidx: longint;
@ -180,6 +182,20 @@ implementation
appenddef(deftypelist,p.oper[opidx]^.def); appenddef(deftypelist,p.oper[opidx]^.def);
top_tai: top_tai:
collect_tai_info(deftypelist,p.oper[opidx]^.ai); collect_tai_info(deftypelist,p.oper[opidx]^.ai);
top_ref:
begin
if (p.llvmopcode<>la_br) and
assigned(p.oper[opidx]^.ref^.symbol) and
(p.oper[opidx]^.ref^.symbol.bind<>AB_TEMP) then
begin
if (opidx=3) and
(p.llvmopcode=la_call) then
record_asmsym_def(p.oper[opidx]^.ref^.symbol,tpointerdef(p.oper[0]^.def).pointeddef,false)
{ not a named register }
else if (p.oper[opidx]^.ref^.refaddr<>addr_full) then
record_asmsym_def(p.oper[opidx]^.ref^.symbol,p.spilling_get_reg_type(opidx),false);
end;
end;
top_para: top_para:
for paraidx:=0 to p.oper[opidx]^.paras.count-1 do for paraidx:=0 to p.oper[opidx]^.paras.count-1 do
begin begin
@ -245,10 +261,11 @@ implementation
end; end;
procedure TLLVMTypeInfo.insert_llvmins_typeconversions(p: taillvm); procedure TLLVMTypeInfo.insert_llvmins_typeconversions(toplevellist: tasmlist; p: taillvm);
var var
symdef, symdef,
opdef: tdef; opdef,
opcmpdef: tdef;
cnv: taillvm; cnv: taillvm;
i: longint; i: longint;
begin begin
@ -256,6 +273,7 @@ implementation
la_call: la_call:
if p.oper[3]^.typ=top_ref then if p.oper[3]^.typ=top_ref then
begin begin
maybe_insert_extern_sym_decl(toplevellist,p.oper[3]^.ref^.symbol,tpointerdef(p.oper[0]^.def).pointeddef);
symdef:=get_asmsym_def(p.oper[3]^.ref^.symbol); symdef:=get_asmsym_def(p.oper[3]^.ref^.symbol);
{ the type used in the call is different from the type used to { the type used in the call is different from the type used to
declare the symbol -> insert a typecast } declare the symbol -> insert a typecast }
@ -278,26 +296,39 @@ implementation
for i:=0 to p.ops-1 do for i:=0 to p.ops-1 do
case p.oper[i]^.typ of case p.oper[i]^.typ of
top_ref: top_ref:
if (p.oper[i]^.ref^.refaddr=addr_full) and if (p.oper[i]^.ref^.refaddr<>addr_full) and
assigned(p.oper[i]^.ref^.symbol) and
(p.oper[i]^.ref^.symbol.bind<>AB_TEMP) then (p.oper[i]^.ref^.symbol.bind<>AB_TEMP) then
begin begin
symdef:=get_asmsym_def(p.oper[i]^.ref^.symbol);
opdef:=p.spilling_get_reg_type(i); opdef:=p.spilling_get_reg_type(i);
if not equal_llvm_defs(symdef,opdef) then case opdef.typ of
pointerdef:
opcmpdef:=tpointerdef(opdef).pointeddef;
procvardef,
procdef:
opcmpdef:=opdef;
else
internalerror(2015073101);
end;
maybe_insert_extern_sym_decl(toplevellist,p.oper[i]^.ref^.symbol,opcmpdef);
symdef:=get_asmsym_def(p.oper[i]^.ref^.symbol);
if not equal_llvm_defs(symdef,opcmpdef) then
begin begin
cnv:=taillvm.op_reg_size_sym_size(la_bitcast,NR_NO,symdef,p.oper[i]^.ref^.symbol,opdef); if symdef.typ=procdef then
symdef:=cpointerdef.getreusable(symdef);
cnv:=taillvm.op_reg_size_sym_size(la_bitcast,NR_NO,cpointerdef.getreusable(symdef),p.oper[i]^.ref^.symbol,opdef);
p.loadtai(i,cnv); p.loadtai(i,cnv);
end; end;
end; end;
top_tai: top_tai:
insert_tai_typeconversions(p.oper[i]^.ai); insert_tai_typeconversions(toplevellist,p.oper[i]^.ai);
end; end;
end; end;
end; end;
end; end;
procedure TLLVMTypeInfo.insert_typedconst_typeconversion(p: tai_abstracttypedconst); procedure TLLVMTypeInfo.insert_typedconst_typeconversion(toplevellist: tasmlist; p: tai_abstracttypedconst);
var var
symdef: tdef; symdef: tdef;
cnv: taillvm; cnv: taillvm;
@ -311,6 +342,7 @@ implementation
if assigned(tai_const(tai_simpletypedconst(p).val).sym) and if assigned(tai_const(tai_simpletypedconst(p).val).sym) and
not assigned(tai_const(tai_simpletypedconst(p).val).endsym) then not assigned(tai_const(tai_simpletypedconst(p).val).endsym) then
begin begin
maybe_insert_extern_sym_decl(toplevellist,tai_const(tai_simpletypedconst(p).val).sym,p.def);
symdef:=get_asmsym_def(tai_const(tai_simpletypedconst(p).val).sym); symdef:=get_asmsym_def(tai_const(tai_simpletypedconst(p).val).sym);
{ all references to symbols in typed constants are { all references to symbols in typed constants are
references to the address of a global symbol (you can't references to the address of a global symbol (you can't
@ -325,36 +357,36 @@ implementation
end; end;
end; end;
else else
insert_tai_typeconversions(tai_simpletypedconst(p).val); insert_tai_typeconversions(toplevellist,tai_simpletypedconst(p).val);
end; end;
end; end;
tck_array, tck_array,
tck_record: tck_record:
begin begin
for elementp in tai_aggregatetypedconst(p) do for elementp in tai_aggregatetypedconst(p) do
insert_typedconst_typeconversion(elementp); insert_typedconst_typeconversion(toplevellist,elementp);
end; end;
end; end;
end; end;
procedure TLLVMTypeInfo.insert_tai_typeconversions(p: tai); procedure TLLVMTypeInfo.insert_tai_typeconversions(toplevellist: tasmlist; p: tai);
begin begin
case p.typ of case p.typ of
ait_llvmins: ait_llvmins:
insert_llvmins_typeconversions(taillvm(p)); insert_llvmins_typeconversions(toplevellist,taillvm(p));
{ can also be necessary in case someone initialises a typed const with { can also be necessary in case someone initialises a typed const with
the address of an external symbol aliasing one declared with a the address of an external symbol aliasing one declared with a
different type in the same mmodule. } different type in the same mmodule. }
ait_typedconst: ait_typedconst:
insert_typedconst_typeconversion(tai_abstracttypedconst(p)); insert_typedconst_typeconversion(toplevellist,tai_abstracttypedconst(p));
ait_llvmdecl: ait_llvmdecl:
insert_asmlist_typeconversions(taillvmdecl(p).initdata); insert_asmlist_typeconversions(toplevellist,taillvmdecl(p).initdata);
end; end;
end; end;
procedure TLLVMTypeInfo.insert_asmlist_typeconversions(list: tasmlist); procedure TLLVMTypeInfo.insert_asmlist_typeconversions(toplevellist, list: tasmlist);
var var
hp: tai; hp: tai;
begin begin
@ -363,11 +395,36 @@ implementation
hp:=tai(list.first); hp:=tai(list.first);
while assigned(hp) do while assigned(hp) do
begin begin
insert_tai_typeconversions(hp); insert_tai_typeconversions(toplevellist,hp);
hp:=tai(hp.next); hp:=tai(hp.next);
end; end;
end; end;
procedure TLLVMTypeInfo.maybe_insert_extern_sym_decl(toplevellist: tasmlist; sym: tasmsymbol; def: tdef);
var
sec: tasmsectiontype;
begin
{ Necessery for "external" declarations for symbols not declared in the
current unit. We can't create these declarations when the alias is
initially generated, because the symbol may still be defined later at
that point.
We also do it for all other external symbol references (e.g.
references to symbols declared in other units), because then this
handling is centralised in one place. }
if not(sym.declared) then
begin
if def.typ=procdef then
sec:=sec_code
else
sec:=sec_data;
toplevellist.Concat(taillvmdecl.create(sym,def,nil,sec,def.alignment));
record_asmsym_def(sym,def,true);
end;
end;
procedure TLLVMTypeInfo.update_asmlist_alias_types(list: tasmlist); procedure TLLVMTypeInfo.update_asmlist_alias_types(list: tasmlist);
var var
hp: tai; hp: tai;
@ -580,7 +637,9 @@ implementation
{ and insert the necessary type conversions } { and insert the necessary type conversions }
for hal:=low(TasmlistType) to high(TasmlistType) do for hal:=low(TasmlistType) to high(TasmlistType) do
if hal<>al_start then if hal<>al_start then
insert_asmlist_typeconversions(current_asmdata.asmlists[hal]); insert_asmlist_typeconversions(
current_asmdata.asmlists[hal],
current_asmdata.asmlists[hal]);
{ write all used defs } { write all used defs }
write_defs_to_write; write_defs_to_write;