* 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
{ taillvm }
taillvm = class(tai_cpu_abstract_sym)
private
procedure maybe_declare(def: tdef; const ref: treference);
public
llvmopcode: tllvmop;
constructor create_llvm(op: tllvmop);
@ -234,23 +231,6 @@ uses
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);
begin
create(a_none);
@ -731,7 +711,6 @@ uses
create_llvm(op);
ops:=4;
loadreg(0,dst);
maybe_declare(fromsize,src);
loaddef(1,fromsize);
loadref(2,src);
loaddef(3,tosize);
@ -745,7 +724,6 @@ uses
ops:=4;
loaddef(0,fromsize);
loadreg(1,src);
maybe_declare(ptrsize,toref);
loaddef(2,ptrsize);
loadref(3,toref);
end;
@ -755,10 +733,8 @@ uses
begin
create_llvm(op);
ops:=4;
maybe_declare(fromsize,src);
loaddef(0,fromsize);
loadref(1,src);
maybe_declare(ptrsize,toref);
loaddef(2,ptrsize);
loadref(3,toref);
end;
@ -770,7 +746,6 @@ uses
ops:=4;
loaddef(0,fromsize);
loadconst(1,src);
maybe_declare(ptrsize,toref);
loaddef(2,ptrsize);
loadref(3,toref);
end;
@ -781,7 +756,6 @@ uses
create_llvm(op);
ops:=3;
loadreg(0,dst);
maybe_declare(fromsize,fromref);
loaddef(1,fromsize);
loadref(2,fromref);
end;
@ -859,7 +833,6 @@ uses
else
ops:=5;
loadreg(0,dst);
maybe_declare(ptrsize,ref);
loaddef(1,ptrsize);
loadref(2,ref);
if indirect then
@ -885,7 +858,6 @@ uses
else
ops:=5;
loadreg(0,dst);
maybe_declare(ptrsize,ref);
loaddef(1,ptrsize);
loadref(2,ref);
if indirect then

View File

@ -319,7 +319,14 @@ implementation
begin
if (pd.typ=procdef) or
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
result:=pd
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;
var
callparas: tfplist;
asmsym: tasmsymbol;
llvmretdef,
hlretdef,
calldef: tdef;
res: tregister;
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);
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);

View File

@ -82,10 +82,11 @@ interface
procedure collect_tai_info(deftypelist: tasmlist; p: tai);
procedure collect_asmlist_info(deftypelist, asmlist: tasmlist);
procedure insert_llvmins_typeconversions(p: taillvm);
procedure insert_typedconst_typeconversion(p: tai_abstracttypedconst);
procedure insert_tai_typeconversions(p: tai);
procedure insert_asmlist_typeconversions(list: tasmlist);
procedure insert_llvmins_typeconversions(toplevellist: tasmlist; p: taillvm);
procedure insert_typedconst_typeconversion(toplevellist: tasmlist; p: tai_abstracttypedconst);
procedure insert_tai_typeconversions(toplevellist: tasmlist; p: tai);
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);
public
@ -169,6 +170,7 @@ implementation
end;
end;
procedure TLLVMTypeInfo.collect_llvmins_info(deftypelist: tasmlist; p: taillvm);
var
opidx, paraidx: longint;
@ -180,6 +182,20 @@ implementation
appenddef(deftypelist,p.oper[opidx]^.def);
top_tai:
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:
for paraidx:=0 to p.oper[opidx]^.paras.count-1 do
begin
@ -245,10 +261,11 @@ implementation
end;
procedure TLLVMTypeInfo.insert_llvmins_typeconversions(p: taillvm);
procedure TLLVMTypeInfo.insert_llvmins_typeconversions(toplevellist: tasmlist; p: taillvm);
var
symdef,
opdef: tdef;
opdef,
opcmpdef: tdef;
cnv: taillvm;
i: longint;
begin
@ -256,6 +273,7 @@ implementation
la_call:
if p.oper[3]^.typ=top_ref then
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);
{ the type used in the call is different from the type used to
declare the symbol -> insert a typecast }
@ -278,26 +296,39 @@ implementation
for i:=0 to p.ops-1 do
case p.oper[i]^.typ of
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
begin
symdef:=get_asmsym_def(p.oper[i]^.ref^.symbol);
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
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);
end;
end;
top_tai:
insert_tai_typeconversions(p.oper[i]^.ai);
insert_tai_typeconversions(toplevellist,p.oper[i]^.ai);
end;
end;
end;
end;
procedure TLLVMTypeInfo.insert_typedconst_typeconversion(p: tai_abstracttypedconst);
procedure TLLVMTypeInfo.insert_typedconst_typeconversion(toplevellist: tasmlist; p: tai_abstracttypedconst);
var
symdef: tdef;
cnv: taillvm;
@ -311,6 +342,7 @@ implementation
if assigned(tai_const(tai_simpletypedconst(p).val).sym) and
not assigned(tai_const(tai_simpletypedconst(p).val).endsym) then
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);
{ all references to symbols in typed constants are
references to the address of a global symbol (you can't
@ -325,36 +357,36 @@ implementation
end;
end;
else
insert_tai_typeconversions(tai_simpletypedconst(p).val);
insert_tai_typeconversions(toplevellist,tai_simpletypedconst(p).val);
end;
end;
tck_array,
tck_record:
begin
for elementp in tai_aggregatetypedconst(p) do
insert_typedconst_typeconversion(elementp);
insert_typedconst_typeconversion(toplevellist,elementp);
end;
end;
end;
procedure TLLVMTypeInfo.insert_tai_typeconversions(p: tai);
procedure TLLVMTypeInfo.insert_tai_typeconversions(toplevellist: tasmlist; p: tai);
begin
case p.typ of
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
the address of an external symbol aliasing one declared with a
different type in the same mmodule. }
ait_typedconst:
insert_typedconst_typeconversion(tai_abstracttypedconst(p));
insert_typedconst_typeconversion(toplevellist,tai_abstracttypedconst(p));
ait_llvmdecl:
insert_asmlist_typeconversions(taillvmdecl(p).initdata);
insert_asmlist_typeconversions(toplevellist,taillvmdecl(p).initdata);
end;
end;
procedure TLLVMTypeInfo.insert_asmlist_typeconversions(list: tasmlist);
procedure TLLVMTypeInfo.insert_asmlist_typeconversions(toplevellist, list: tasmlist);
var
hp: tai;
begin
@ -363,11 +395,36 @@ implementation
hp:=tai(list.first);
while assigned(hp) do
begin
insert_tai_typeconversions(hp);
insert_tai_typeconversions(toplevellist,hp);
hp:=tai(hp.next);
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);
var
hp: tai;
@ -580,7 +637,9 @@ implementation
{ and insert the necessary type conversions }
for hal:=low(TasmlistType) to high(TasmlistType) do
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_defs_to_write;