From 96b529072a6d3e05bf3190299eb87e631436c414 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sat, 21 Nov 2015 12:36:06 +0000 Subject: [PATCH] * factored out generating the start and end of a vectorized dead strippable section to the high level typed const builder, and use this functionality for the resource strings (generating items: todo) * fixed dead stripping unused resource strings (all string data was put in the same section since r30342) git-svn-id: trunk@32394 - --- compiler/aasmcnst.pas | 91 +++++++++++++++++++++++++++++++++++++++++-- compiler/cresstr.pas | 65 ++++++++++++++++--------------- compiler/ngenutil.pas | 4 +- compiler/symconst.pas | 2 + 4 files changed, 125 insertions(+), 37 deletions(-) diff --git a/compiler/aasmcnst.pas b/compiler/aasmcnst.pas index ac2d526dc7..a70a650daf 100644 --- a/compiler/aasmcnst.pas +++ b/compiler/aasmcnst.pas @@ -115,7 +115,15 @@ type not necessarily (depends on what the platform requirements are) } tcalo_make_dead_strippable, { this symbol should never be removed by the linker } - tcalo_no_dead_strip + tcalo_no_dead_strip, + { start of a vectorized but individually dead strippable list of elements, + like the resource strings of a unit: they have to stay in this order, + but individual elements can be removed } + tcalo_vectorized_dead_strip_start, + { item in the above list } + tcalo_vectorized_dead_strip_item, + { end of the above list } + tcalo_vectorized_dead_strip_end ); ttcasmlistoptions = set of ttcasmlistoption; @@ -231,12 +239,17 @@ type { ensure that finalize_asmlist is called only once } fasmlist_finalized: boolean; + { ensure that if it's vectorized dead strippable data, we called + finalize_vectorized_dead_strip_asmlist instead of finalize_asmlist } + fvectorized_finalize_called: boolean; { returns whether def must be handled as an aggregate on the current platform } function aggregate_kind(def: tdef): ttypedconstkind; virtual; { finalize the asmlist: add the necessary symbols etc } procedure finalize_asmlist(sym: tasmsymbol; def: tdef; section: TAsmSectiontype; const secname: TSymStr; alignment: shortint; const options: ttcasmlistoptions); virtual; + { functionality of the above for vectorized dead strippable sections } + procedure finalize_vectorized_dead_strip_asmlist(def: tdef; const basename: string; st: tsymtable; alignment: shortint; options: ttcasmlistoptions); virtual; { called by the public emit_tai() routines to actually add the typed constant data; the public ones also take care of adding extra padding @@ -295,10 +308,12 @@ type the anonymous record, and insert the alignment once it's finished } procedure mark_anon_aggregate_alignment; virtual; abstract; procedure insert_marked_aggregate_alignment(def: tdef); virtual; abstract; + class function get_vectorized_dead_strip_section_symbol(const basename: string; st: tsymtable; define, start: boolean): tasmsymbol; virtual; public { get the start/end symbol for a dead stripable vectorized section, such as the resourcestring data of a unit } - class function get_vectorized_dead_strip_section_symbol(const basename: string; st: tsymtable; start: boolean): tasmsymbol; virtual; + class function get_vectorized_dead_strip_section_symbol_start(const basename: string; st: tsymtable; define: boolean): tasmsymbol; virtual; + class function get_vectorized_dead_strip_section_symbol_end(const basename: string; st: tsymtable; define: boolean): tasmsymbol; virtual; class function get_dynstring_rec_name(typ: tstringtype; winlike: boolean; len: asizeint): string; { the datalist parameter specifies where the data for the string constant @@ -393,6 +408,7 @@ type contents to another list first. This property should only be accessed once all data has been added. } function get_final_asmlist(sym: tasmsymbol; def: tdef; section: TAsmSectiontype; const secname: TSymStr; alignment: longint): tasmlist; + function get_final_asmlist_vectorized_dead_strip(def: tdef; const basename: string; st: TSymtable; alignment: longint): tasmlist; { returns the offset of the string data relative to ansi/unicode/widestring constant labels. On most platforms, this is 0 (with the header at a @@ -868,6 +884,14 @@ implementation { in case of syntax errors, the aggregate may not have been finished } (ErrorCount=0) then internalerror(2015072301); + + { must call finalize_vectorized_dead_strip_asmlist() instead } + if (([tcalo_vectorized_dead_strip_start, + tcalo_vectorized_dead_strip_item, + tcalo_vectorized_dead_strip_end]*options)<>[]) and + not fvectorized_finalize_called then + internalerror(2015110602); + prelist:=tasmlist.create; { only now add items based on the symbolname, because it may be modified by the "section" specifier in case of a typed constant } @@ -915,6 +939,44 @@ implementation end; + procedure ttai_typedconstbuilder.finalize_vectorized_dead_strip_asmlist(def: tdef; const basename: string; st: tsymtable; alignment: shortint; options: ttcasmlistoptions); + var + sym: tasmsymbol; + secname: TSymStr; + secend: boolean; + begin + fvectorized_finalize_called:=true; + secend:=false; + if tcalo_vectorized_dead_strip_start in options then + begin + sym:=get_vectorized_dead_strip_section_symbol_start(basename,st,true); + secname:=make_mangledname(basename,st,'1_START'); + end + else if tcalo_vectorized_dead_strip_end in options then + begin + sym:=get_vectorized_dead_strip_section_symbol_end(basename,st,true); + make_mangledname(basename,st,'3_END'); + secend:=true; + end + else if tcalo_vectorized_dead_strip_item in options then + { todo } + internalerror(2015110601); + finalize_asmlist(sym,def,sec_data,secname,alignment,options); + { The darwin/ppc64 assembler or linker seems to have trouble } + { if a section ends with a global label without any data after it. } + { So for safety, just put a dummy value here. } + { Further, the regular linker also kills this symbol when turning } + { on smart linking in case no value appears after it, so put the } + { dummy byte there always } + { Update: the Mac OS X 10.6 linker orders data that needs to be } + { relocated before all other data, so make this data relocatable, } + { otherwise the end label won't be moved with the rest } + if secend and + (target_info.system in (systems_darwin+systems_aix)) then + fasmlist.concat(Tai_const.create_sym(sym)); + end; + + procedure ttai_typedconstbuilder.do_emit_tai(p: tai; def: tdef); begin { by default we don't care about the type } @@ -933,6 +995,17 @@ implementation end; + function ttai_typedconstbuilder.get_final_asmlist_vectorized_dead_strip(def: tdef; const basename: string; st: TSymtable; alignment: longint): tasmlist; + begin + if not fasmlist_finalized then + begin + finalize_vectorized_dead_strip_asmlist(def,basename,st,alignment,foptions); + fasmlist_finalized:=true; + end; + result:=fasmlist; + end; + + class function ttai_typedconstbuilder.get_string_symofs(typ: tstringtype; winlikewidestring: boolean): pint; begin { darwin's linker does not support negative offsets } @@ -1260,7 +1333,7 @@ implementation end; - class function ttai_typedconstbuilder.get_vectorized_dead_strip_section_symbol(const basename: string; st: tsymtable; start: boolean): tasmsymbol; + class function ttai_typedconstbuilder.get_vectorized_dead_strip_section_symbol(const basename: string; st: tsymtable; define, start: boolean): tasmsymbol; begin if start then result:=current_asmdata.DefineAsmSymbol(make_mangledname(basename,st,'START'),AB_GLOBAL,AT_DATA) @@ -1269,6 +1342,18 @@ implementation end; + class function ttai_typedconstbuilder.get_vectorized_dead_strip_section_symbol_start(const basename: string; st: tsymtable; define: boolean): tasmsymbol; + begin + result:=get_vectorized_dead_strip_section_symbol(basename,st,define,true); + end; + + + class function ttai_typedconstbuilder.get_vectorized_dead_strip_section_symbol_end(const basename: string; st: tsymtable; define: boolean): tasmsymbol; + begin + result:=get_vectorized_dead_strip_section_symbol(basename,st,define,false); + end; + + class function ttai_typedconstbuilder.get_dynstring_rec_name(typ: tstringtype; winlike: boolean; len: asizeint): string; begin case typ of diff --git a/compiler/cresstr.pas b/compiler/cresstr.pas index d042550c39..957506c518 100644 --- a/compiler/cresstr.pas +++ b/compiler/cresstr.pas @@ -134,36 +134,40 @@ uses namelab, valuelab : tasmlabofs; resstrlab : tasmsymbol; - endsymlab : tasmsymbol; R : TResourceStringItem; - tcb : ttai_typedconstbuilder; + resstrdef: tdef; + tcb, + datatcb : ttai_typedconstbuilder; begin + resstrdef:=search_system_type('TRESOURCESTRINGRECORD').typedef; + { Put resourcestrings in a new objectfile. Putting it in multiple files makes the linking too dependent on the linker script requiring a SORT(*) for the data sections } - tcb:=ctai_typedconstbuilder.create([tcalo_make_dead_strippable,tcalo_new_section]); - - maybe_new_object_file(current_asmdata.asmlists[al_resourcestrings]); - new_section(current_asmdata.asmlists[al_resourcestrings],sec_data,make_mangledname('RESSTR',current_module.localsymtable,'1_START'),sizeof(pint)); - current_asmdata.AsmLists[al_resourcestrings].concat(tai_symbol.Create_Global( - ctai_typedconstbuilder.get_vectorized_dead_strip_section_symbol('RESSTR',current_module.localsymtable,true),0)); + tcb:=ctai_typedconstbuilder.create([tcalo_make_dead_strippable,tcalo_new_section,tcalo_vectorized_dead_strip_start]); { Write unitname entry } + tcb.maybe_begin_aggregate(resstrdef); namelab:=tcb.emit_ansistring_const(current_asmdata.asmlists[al_const],@current_module.localsymtable.name^[1],length(current_module.localsymtable.name^),getansistringcodepage); - current_asmdata.asmlists[al_resourcestrings].concat(tai_const.Create_sym_offset(namelab.lab,namelab.ofs)); - current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_nil_dataptr); - current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_nil_dataptr); - current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_32bit(0)); -{$ifdef cpu64bitaddr} - current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_32bit(0)); -{$endif cpu64bitaddr} + tcb.emit_string_offset(namelab,length(current_module.localsymtable.name^),st_ansistring,false,charpointertype); + tcb.emit_tai(tai_const.create_nil_dataptr,voidpointertype); + tcb.emit_tai(tai_const.create_nil_dataptr,voidpointertype); + tcb.emit_ord_const(0,u32inttype); + tcb.maybe_end_aggregate(resstrdef); + current_asmdata.asmlists[al_resourcestrings].concatList( + tcb.get_final_asmlist_vectorized_dead_strip( + resstrdef,'RESSTR',current_module.localsymtable,sizeof(pint) + ) + ); + tcb.free; { Add entries } R:=TResourceStringItem(List.First); while assigned(R) do begin + datatcb:=ctai_typedconstbuilder.create([tcalo_make_dead_strippable,tcalo_new_section]); { Write default value } if assigned(R.value) and (R.len<>0) then - valuelab:=tcb.emit_ansistring_const(current_asmdata.asmlists[al_const],R.Value,R.Len,getansistringcodepage) + valuelab:=datatcb.emit_ansistring_const(current_asmdata.asmlists[al_const],R.Value,R.Len,getansistringcodepage) else begin valuelab.lab:=nil; @@ -171,7 +175,7 @@ uses end; { Append the name as a ansistring. } current_asmdata.asmlists[al_const].concat(cai_align.Create(const_align(sizeof(pint)))); - namelab:=tcb.emit_ansistring_const(current_asmdata.asmlists[al_const],@R.Name[1],length(R.name),getansistringcodepage); + namelab:=datatcb.emit_ansistring_const(current_asmdata.asmlists[al_const],@R.Name[1],length(R.name),getansistringcodepage); { Resourcestring index: @@ -194,23 +198,20 @@ uses {$endif cpu64bitaddr} current_asmdata.asmlists[al_resourcestrings].concat(tai_symbol_end.create(resstrlab)); R:=TResourceStringItem(R.Next); + { nothing has been emited to the datatcb itself } + datatcb.free; end; - { nothing has been emited to the tcb itself } + tcb:=ctai_typedconstbuilder.create([tcalo_new_section,tcalo_vectorized_dead_strip_end]); + tcb.begin_anonymous_record(internaltypeprefixName[itp_emptyrec], + default_settings.packrecords,sizeof(pint), + targetinfos[target_info.system]^.alignment.recordalignmin, + targetinfos[target_info.system]^.alignment.maxCrecordalign); + current_asmdata.AsmLists[al_resourcestrings].concatList( + tcb.get_final_asmlist_vectorized_dead_strip( + tcb.end_anonymous_record,'RESSTR',current_module.localsymtable,sizeof(pint) + ) + ); tcb.free; - new_section(current_asmdata.asmlists[al_resourcestrings],sec_data,make_mangledname('RESSTR',current_module.localsymtable,'3_END'),sizeof(pint)); - endsymlab:=ctai_typedconstbuilder.get_vectorized_dead_strip_section_symbol('RESSTR',current_module.localsymtable,false); - current_asmdata.AsmLists[al_resourcestrings].concat(tai_symbol.create_global(endsymlab,0)); - { The darwin/ppc64 assembler or linker seems to have trouble } - { if a section ends with a global label without any data after it. } - { So for safety, just put a dummy value here. } - { Further, the regular linker also kills this symbol when turning } - { on smart linking in case no value appears after it, so put the } - { dummy byte there always } - { Update: the Mac OS X 10.6 linker orders data that needs to be } - { relocated before all other data, so make this data relocatable, } - { otherwise the end label won't be moved with the rest } - if (target_info.system in (systems_darwin+systems_aix)) then - current_asmdata.asmlists[al_resourcestrings].concat(Tai_const.create_sym(endsymlab)); end; procedure Tresourcestrings.WriteRSJFile; diff --git a/compiler/ngenutil.pas b/compiler/ngenutil.pas index ed7ab46b85..cc5d9420b1 100644 --- a/compiler/ngenutil.pas +++ b/compiler/ngenutil.pas @@ -971,10 +971,10 @@ implementation If (hp.flags and uf_has_resourcestrings)=uf_has_resourcestrings then begin ResourceStringTables.concat(Tai_const.Create_sym( - ctai_typedconstbuilder.get_vectorized_dead_strip_section_symbol('RESSTR',hp.localsymtable,true)) + ctai_typedconstbuilder.get_vectorized_dead_strip_section_symbol_start('RESSTR',hp.localsymtable,false)) ); ResourceStringTables.concat(Tai_const.Create_sym( - ctai_typedconstbuilder.get_vectorized_dead_strip_section_symbol('RESSTR',hp.localsymtable,false)) + ctai_typedconstbuilder.get_vectorized_dead_strip_section_symbol_end('RESSTR',hp.localsymtable,false)) ); inc(count); end; diff --git a/compiler/symconst.pas b/compiler/symconst.pas index 7eac8b6b60..48359d2686 100644 --- a/compiler/symconst.pas +++ b/compiler/symconst.pas @@ -668,6 +668,7 @@ type accidental collisions) } tinternaltypeprefix = ( itp_1byte, + itp_emptyrec, itp_llvmstruct, itp_vmtdef, itp_vmt_tstringmesssagetable, @@ -790,6 +791,7 @@ inherited_objectoptions : tobjectoptions = [oo_has_virtual,oo_has_private,oo_has internaltypeprefixName : array[tinternaltypeprefix] of TSymStr = ( '$1byte$', + '$emptyrec', '$llvmstruct$', '$vmtdef$', '$vmt_TStringMesssageTable$',