+ support for handling the tcalo_no_dead_strip flag when targeting LLVM:

add such symbols to the pseudo-arrays llvm.compiler.used or llvm.used
    depending on their nature (fixes compiling Objective-C programs with
    optimization, and keeps the FPC ident in the linked binary)

git-svn-id: trunk@35041 -
This commit is contained in:
Jonas Maebe 2016-12-02 12:33:05 +00:00
parent e62cb7917e
commit db40e1575d
3 changed files with 65 additions and 4 deletions

View File

@ -147,6 +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) }
{$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 }
@ -588,6 +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);
{$endif llvm}
ansistrdef:=nil;
wpoinfo:=nil;
@ -714,6 +718,8 @@ implementation
procaddrdefs.free;
{$ifdef llvm}
llvmdefs.free;
llvmusedsyms.free;
llvmcompilerusedsyms.free;
{$endif llvm}
ansistrdef:=nil;
wpoinfo.free;
@ -784,6 +790,10 @@ implementation
{$ifdef llvm}
llvmdefs.free;
llvmdefs:=THashSet.Create(64,true,false);
llvmusedsyms.free;
llvmusedsyms:=TFPObjectList.Create(false);
llvmcompilerusedsyms.free;
llvmcompilerusedsyms:=TFPObjectList.Create(false);
{$endif llvm}
wpoinfo.free;
wpoinfo:=nil;

View File

@ -124,7 +124,7 @@ interface
implementation
uses
verbose,systems,
verbose,systems,fmodule,
aasmdata,
cpubase,cpuinfo,llvmbase,
symtable,llvmdef,defutil,defcmp;
@ -202,7 +202,18 @@ implementation
include(decl.flags,ldf_vectorized);
if tcalo_weak in options then
include(decl.flags,ldf_weak);
{ TODO: tcalo_no_dead_strip: add to @llvm.user meta-variable }
if tcalo_no_dead_strip in options then
{ Objective-C section declarations already contain "no_dead_strip"
attributes if none of their symbols need to be stripped -> only
add the symbols to llvm.compiler.used (only affects compiler
optimisations) and not to llvm.used (also affects linker -- which in
this case is already taken care of by the section attribute; not sure
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)
else
current_module.llvmusedsyms.add(decl);
newasmlist.concat(decl);
fasmlist:=newasmlist;
end;

View File

@ -26,7 +26,7 @@ unit nllvmutil;
interface
uses
globtype,
globtype,cclasses,
aasmdata,ngenutil,
symtype,symconst,symsym,symdef;
@ -35,6 +35,7 @@ interface
tllvmnodeutils = class(tnodeutils)
strict protected
class procedure insertbsssym(list: tasmlist; sym: tstaticvarsym; size: asizeint; varalign: shortint); override;
class procedure InsertUsedList(var usedsyms: tfpobjectlist; const usedsymsname: TSymstr);
public
class procedure InsertObjectInfo; override;
end;
@ -45,7 +46,7 @@ implementation
uses
verbose,cutils,globals,fmodule,systems,
aasmbase,aasmtai,cpubase,llvmbase,aasmllvm,
aasmcnst,
aasmcnst,nllvmtcon,
symbase,symtable,defutil,
llvmtype;
@ -70,10 +71,49 @@ implementation
end;
class procedure tllvmnodeutils.InsertUsedList(var usedsyms: tfpobjectlist; const usedsymsname: TSymstr);
var
useddef: tdef;
tcb: ttai_typedconstbuilder;
decl: taillvmdecl;
i: longint;
begin
if usedsyms.count<>0 then
begin
tcb:=ctai_typedconstbuilder.create([tcalo_new_section]);
tllvmtai_typedconstbuilder(tcb).appendingdef:=true;
useddef:=carraydef.getreusable(voidpointertype,usedsyms.count);
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);
end;
tcb.maybe_end_aggregate(useddef);
current_asmdata.AsmLists[al_globals].concatlist(
tcb.get_final_asmlist(
current_asmdata.DefineAsmSymbol(
usedsymsname,AB_GLOBAL,AT_DATA,useddef),useddef,sec_user,
'llvm.metadata',0
)
);
tcb.free;
end;
usedsyms.free;
usedsyms:=nil;
end;
class procedure tllvmnodeutils.InsertObjectInfo;
begin
inherited;
{ add the llvm.compiler.used array }
InsertUsedList(current_module.llvmcompilerusedsyms,'llvm.compiler.used');
{ add the llvm.used array }
InsertUsedList(current_module.llvmusedsyms,'llvm.used');
{ add "type xx = .." statements for all used recorddefs }
with TLLVMTypeInfo.Create do
begin