From db40e1575d06330258dff3478c1062d5fd411b52 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Fri, 2 Dec 2016 12:33:05 +0000 Subject: [PATCH] + 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 - --- compiler/fmodule.pas | 10 +++++++++ compiler/llvm/nllvmtcon.pas | 15 +++++++++++-- compiler/llvm/nllvmutil.pas | 44 +++++++++++++++++++++++++++++++++++-- 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/compiler/fmodule.pas b/compiler/fmodule.pas index 7bf8f2ece5..d2e1ea190d 100644 --- a/compiler/fmodule.pas +++ b/compiler/fmodule.pas @@ -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; diff --git a/compiler/llvm/nllvmtcon.pas b/compiler/llvm/nllvmtcon.pas index 672f4d41a4..e493ab4aad 100644 --- a/compiler/llvm/nllvmtcon.pas +++ b/compiler/llvm/nllvmtcon.pas @@ -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; diff --git a/compiler/llvm/nllvmutil.pas b/compiler/llvm/nllvmutil.pas index a414316880..3b45f194c6 100644 --- a/compiler/llvm/nllvmutil.pas +++ b/compiler/llvm/nllvmutil.pas @@ -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