mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-12 19:49:31 +02:00
* register static symbols references from assembly code as "used" so that LLVM won't
remove them if there are no references from regular code git-svn-id: branches/debug_eh@40432 -
This commit is contained in:
parent
85702dd263
commit
68ce5dc91f
@ -147,8 +147,8 @@ interface
|
||||
procaddrdefs : THashSet; { list of procvardefs created when getting the address of a procdef (not saved/restored) }
|
||||
{$ifdef llvm}
|
||||
llvmdefs : THashSet; { defs added for llvm-specific reasons (not saved/restored) }
|
||||
llvmusedsyms : TFPObjectList; { a list of tllvmdecls of all symbols that need to be added to llvm.used (so they're not removed by llvm optimisation passes nor by the linker) }
|
||||
llvmcompilerusedsyms : TFPObjectList; { a list of tllvmdecls of all symbols that need to be added to llvm.compiler.used (so they're not removed by llvm optimisation passes) }
|
||||
llvmusedsyms : TFPObjectList; { a list of asmsymbols and their defs that need to be added to llvm.used (so they're not removed by llvm optimisation passes nor by the linker) }
|
||||
llvmcompilerusedsyms : TFPObjectList; { a list of asmsymbols and their defs that need to be added to llvm.compiler.used (so they're not removed by llvm optimisation passes) }
|
||||
{$endif llvm}
|
||||
ansistrdef : tobject; { an ansistring def redefined for the current module }
|
||||
wpoinfo : tunitwpoinfobase; { whole program optimization-related information that is generated during the current run for this unit }
|
||||
@ -590,8 +590,8 @@ implementation
|
||||
procaddrdefs:=THashSet.Create(64,true,false);
|
||||
{$ifdef llvm}
|
||||
llvmdefs:=THashSet.Create(64,true,false);
|
||||
llvmusedsyms:=TFPObjectList.Create(false);
|
||||
llvmcompilerusedsyms:=TFPObjectList.Create(false);
|
||||
llvmusedsyms:=TFPObjectList.Create(true);
|
||||
llvmcompilerusedsyms:=TFPObjectList.Create(true);
|
||||
{$endif llvm}
|
||||
ansistrdef:=nil;
|
||||
wpoinfo:=nil;
|
||||
@ -791,9 +791,9 @@ implementation
|
||||
llvmdefs.free;
|
||||
llvmdefs:=THashSet.Create(64,true,false);
|
||||
llvmusedsyms.free;
|
||||
llvmusedsyms:=TFPObjectList.Create(false);
|
||||
llvmusedsyms:=TFPObjectList.Create(true);
|
||||
llvmcompilerusedsyms.free;
|
||||
llvmcompilerusedsyms:=TFPObjectList.Create(false);
|
||||
llvmcompilerusedsyms:=TFPObjectList.Create(true);
|
||||
{$endif llvm}
|
||||
wpoinfo.free;
|
||||
wpoinfo:=nil;
|
||||
|
@ -128,7 +128,8 @@ implementation
|
||||
verbose,systems,fmodule,
|
||||
aasmdata,
|
||||
cpubase,cpuinfo,llvmbase,
|
||||
symtable,llvmdef,defutil,defcmp;
|
||||
symtable,llvmdef,defutil,defcmp,
|
||||
ngenutil;
|
||||
|
||||
{ tllvmaggregateinformation }
|
||||
|
||||
@ -212,9 +213,9 @@ implementation
|
||||
why it's done like this, but this is how Clang does it) }
|
||||
if (target_info.system in systems_darwin) and
|
||||
(section in [low(TObjCAsmSectionType)..high(TObjCAsmSectionType)]) then
|
||||
current_module.llvmcompilerusedsyms.add(decl)
|
||||
cnodeutils.RegisterUsedAsmSym(sym,def,false)
|
||||
else
|
||||
current_module.llvmusedsyms.add(decl);
|
||||
cnodeutils.RegisterUsedAsmSym(sym,def,true);
|
||||
newasmlist.concat(decl);
|
||||
fasmlist:=newasmlist;
|
||||
end;
|
||||
|
@ -27,7 +27,7 @@ interface
|
||||
|
||||
uses
|
||||
globtype,cclasses,
|
||||
aasmdata,ngenutil,
|
||||
aasmbase,aasmdata,ngenutil,
|
||||
symtype,symconst,symsym,symdef;
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@ interface
|
||||
class procedure InsertUsedList(var usedsyms: tfpobjectlist; const usedsymsname: TSymstr);
|
||||
public
|
||||
class procedure InsertObjectInfo; override;
|
||||
class procedure RegisterUsedAsmSym(sym: TAsmSymbol; def: tdef; compileronly: boolean); override;
|
||||
end;
|
||||
|
||||
|
||||
@ -45,7 +46,7 @@ implementation
|
||||
|
||||
uses
|
||||
verbose,cutils,globals,fmodule,systems,
|
||||
aasmbase,aasmtai,cpubase,llvmbase,aasmllvm,
|
||||
aasmtai,cpubase,llvmbase,aasmllvm,
|
||||
aasmcnst,nllvmtcon,
|
||||
symbase,symtable,defutil,
|
||||
llvmtype;
|
||||
@ -71,24 +72,73 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
type
|
||||
TTypedAsmSym = class
|
||||
sym: TAsmSymbol;
|
||||
def: tdef;
|
||||
constructor Create(s: TAsmSymbol; d: tdef);
|
||||
end;
|
||||
|
||||
|
||||
constructor TTypedAsmSym.Create(s: TAsmSymbol; d: tdef);
|
||||
begin
|
||||
sym:=s;
|
||||
def:=d;
|
||||
end;
|
||||
|
||||
|
||||
function TypedAsmSymComparer(p1, p2: Pointer): Integer;
|
||||
var
|
||||
sym1: TTypedAsmSym absolute p1;
|
||||
sym2: TTypedAsmSym absolute p2;
|
||||
begin
|
||||
result:=CompareStr(sym1.sym.Name,sym2.sym.Name);
|
||||
end;
|
||||
|
||||
|
||||
class procedure tllvmnodeutils.InsertUsedList(var usedsyms: tfpobjectlist; const usedsymsname: TSymstr);
|
||||
var
|
||||
useddef: tdef;
|
||||
tcb: ttai_typedconstbuilder;
|
||||
decl: taillvmdecl;
|
||||
i: longint;
|
||||
prevasmsym: TAsmSymbol;
|
||||
typedsym: TTypedAsmSym;
|
||||
uniquesyms, i: longint;
|
||||
begin
|
||||
if usedsyms.count<>0 then
|
||||
begin
|
||||
{ a symbol can appear multiple times -> sort the list so we can filter out doubles }
|
||||
usedsyms.Sort(@TypedAsmSymComparer);
|
||||
{ count uniques }
|
||||
prevasmsym:=nil;
|
||||
uniquesyms:=0;
|
||||
for i:=0 to usedsyms.count-1 do
|
||||
begin
|
||||
typedsym:=TTypedAsmSym(usedsyms[i]);
|
||||
if (prevasmsym<>typedsym.sym) and
|
||||
{ even though we already filter on pure assembler routines when adding the symbols,
|
||||
some may slip through because of forward definitions that are not yet resolved }
|
||||
not((typedsym.def.typ=procdef) and
|
||||
(po_assembler in tprocdef(typedsym.def).procoptions)) then
|
||||
inc(uniquesyms);
|
||||
prevasmsym:=typedsym.sym;
|
||||
end;
|
||||
{ emit uniques }
|
||||
prevasmsym:=nil;
|
||||
tcb:=ctai_typedconstbuilder.create([tcalo_new_section]);
|
||||
tllvmtai_typedconstbuilder(tcb).appendingdef:=true;
|
||||
useddef:=carraydef.getreusable(voidpointertype,usedsyms.count);
|
||||
useddef:=carraydef.getreusable(voidpointertype,uniquesyms);
|
||||
tcb.maybe_begin_aggregate(useddef);
|
||||
for i:=0 to usedsyms.count-1 do
|
||||
begin
|
||||
decl:=taillvmdecl(usedsyms[i]);
|
||||
tcb.queue_init(voidpointertype);
|
||||
tcb.queue_emit_asmsym(decl.namesym,decl.def);
|
||||
typedsym:=TTypedAsmSym(usedsyms[i]);
|
||||
if (prevasmsym<>typedsym.sym) and
|
||||
not((typedsym.def.typ=procdef) and
|
||||
(po_assembler in tprocdef(typedsym.def).procoptions)) then
|
||||
begin
|
||||
tcb.queue_init(voidpointertype);
|
||||
tcb.queue_emit_asmsym(typedsym.sym,typedsym.def);
|
||||
prevasmsym:=typedsym.sym;
|
||||
end;
|
||||
end;
|
||||
tcb.maybe_end_aggregate(useddef);
|
||||
current_asmdata.AsmLists[al_globals].concatlist(
|
||||
@ -123,6 +173,28 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
class procedure tllvmnodeutils.RegisterUsedAsmSym(sym: TAsmSymbol; def: tdef; compileronly: boolean);
|
||||
var
|
||||
last: TTypedAsmSym;
|
||||
begin
|
||||
if compileronly then
|
||||
begin
|
||||
{ filter multiple adds in succession here already }
|
||||
last:=TTypedAsmSym(current_module.llvmcompilerusedsyms.Last);
|
||||
if not assigned(last) or
|
||||
(last.sym<>sym) then
|
||||
current_module.llvmcompilerusedsyms.Add(TTypedAsmSym.Create(sym,def))
|
||||
end
|
||||
else
|
||||
begin
|
||||
last:=TTypedAsmSym(current_module.llvmusedsyms.Last);
|
||||
if not assigned(last) or
|
||||
(last.sym<>sym) then
|
||||
current_module.llvmusedsyms.Add(TTypedAsmSym.Create(sym,def))
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
cnodeutils:=tllvmnodeutils;
|
||||
end.
|
||||
|
@ -29,7 +29,7 @@ interface
|
||||
uses
|
||||
cclasses,globtype,
|
||||
fmodule,
|
||||
aasmdata,
|
||||
aasmbase,aasmdata,
|
||||
node,nbas,symtype,symsym,symconst,symdef;
|
||||
|
||||
|
||||
@ -138,6 +138,11 @@ interface
|
||||
info) }
|
||||
class procedure InsertObjectInfo; virtual;
|
||||
|
||||
{ register that asm symbol sym with type def has to be considered as "used" even if not
|
||||
references to it can be found. If compileronly, this is only for the compiler, otherwise
|
||||
also for the linker }
|
||||
class procedure RegisterUsedAsmSym(sym: TAsmSymbol; def: tdef; compileronly: boolean); virtual;
|
||||
|
||||
strict protected
|
||||
class procedure add_main_procdef_paras(pd: tdef); virtual;
|
||||
end;
|
||||
@ -152,7 +157,7 @@ implementation
|
||||
uses
|
||||
verbose,version,globals,cutils,constexp,compinnr,
|
||||
systems,procinfo,pparautl,
|
||||
aasmbase,aasmtai,aasmcnst,
|
||||
aasmtai,aasmcnst,
|
||||
symbase,symtable,defutil,
|
||||
nadd,ncal,ncnv,ncon,nflw,ninl,nld,nmem,nutils,
|
||||
ppu,
|
||||
@ -1547,6 +1552,12 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
class procedure tnodeutils.RegisterUsedAsmSym(sym: TAsmSymbol; def: tdef; compileronly: boolean);
|
||||
begin
|
||||
{ don't do anything by default }
|
||||
end;
|
||||
|
||||
|
||||
class procedure tnodeutils.add_main_procdef_paras(pd: tdef);
|
||||
var
|
||||
pvs: tparavarsym;
|
||||
|
@ -217,7 +217,7 @@ uses
|
||||
defutil,systems,verbose,globals,
|
||||
symtable,paramgr,
|
||||
aasmcpu,
|
||||
procinfo;
|
||||
procinfo,ngenutil;
|
||||
|
||||
{*************************************************************************
|
||||
TExprParse
|
||||
@ -1383,6 +1383,22 @@ begin
|
||||
srsym:=tprocdef(srsymtable.defowner).procsym;
|
||||
srsymtable:=srsym.Owner;
|
||||
end;
|
||||
{ llvm can't catch symbol references from inline assembler blocks }
|
||||
if assigned(srsym) then
|
||||
begin
|
||||
case srsym.typ of
|
||||
staticvarsym:
|
||||
cnodeutils.RegisterUsedAsmSym(current_asmdata.RefAsmSymbol(srsym.mangledname,AT_DATA),tstaticvarsym(srsym).vardef,true);
|
||||
procsym:
|
||||
begin
|
||||
{ if it's a pure assembler routine, the definition of the symbol will also
|
||||
be in assembler and it can't be removed by the compiler (and if we mark
|
||||
it as used anyway, clang will get into trouble) }
|
||||
if not(po_assembler in tprocdef(tprocsym(srsym).ProcdefList[0]).procoptions) then
|
||||
cnodeutils.RegisterUsedAsmSym(current_asmdata.RefAsmSymbol(tprocdef(tprocsym(srsym).ProcdefList[0]).mangledname,AT_FUNCTION),tprocdef(tprocsym(srsym).ProcdefList[0]),true);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user