mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 15:49:26 +02:00
* 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:
parent
6dcf61f057
commit
bfa94ae908
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user