* 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 -
This commit is contained in:
Jonas Maebe 2015-11-21 12:36:06 +00:00
parent f22c7cc3fc
commit 96b529072a
4 changed files with 125 additions and 37 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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$',