mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-07 12:50:31 +02:00
o patch by Sergei Gorelkin which basically resolves #14308 (still misses some tests):
* constant widestrings must be allocated and copied at program start up through an api call else they couldn't be passed between progam/dlls git-svn-id: trunk@14432 -
This commit is contained in:
parent
a6f673082e
commit
b5e7b3e1e7
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -74,6 +74,7 @@ compiler/arm/rarmsta.inc svneol=native#text/plain
|
||||
compiler/arm/rarmstd.inc svneol=native#text/plain
|
||||
compiler/arm/rarmsup.inc svneol=native#text/plain
|
||||
compiler/arm/rgcpu.pas svneol=native#text/plain
|
||||
compiler/asmutils.pas svneol=native#text/plain
|
||||
compiler/assemble.pas svneol=native#text/plain
|
||||
compiler/avr/aasmcpu.pas svneol=native#text/plain
|
||||
compiler/avr/agavrgas.pas svneol=native#text/plain
|
||||
|
@ -152,6 +152,7 @@ interface
|
||||
{ Assembler lists }
|
||||
AsmLists : array[TAsmListType] of TAsmList;
|
||||
CurrAsmList : TAsmList;
|
||||
WideInits : TLinkedList;
|
||||
{ hash tables for reusing constant storage }
|
||||
ConstPools : array[TConstPoolType] of THashSet;
|
||||
constructor create(const n:string);
|
||||
@ -174,6 +175,13 @@ interface
|
||||
property AsmCFI:TAsmCFI read FAsmCFI;
|
||||
end;
|
||||
|
||||
TTCInitItem = class(TLinkedListItem)
|
||||
sym: tsym;
|
||||
offset: aint;
|
||||
datalabel: TAsmLabel;
|
||||
constructor Create(asym: tsym; aoffset: aint; alabel: TAsmLabel);
|
||||
end;
|
||||
|
||||
var
|
||||
CAsmCFI : TAsmCFIClass;
|
||||
current_asmdata : TAsmData;
|
||||
@ -241,6 +249,18 @@ implementation
|
||||
begin
|
||||
end;
|
||||
|
||||
{*****************************************************************************
|
||||
TTCInitItem
|
||||
*****************************************************************************}
|
||||
|
||||
|
||||
constructor TTCInitItem.Create(asym: tsym; aoffset: aint; alabel: TAsmLabel);
|
||||
begin
|
||||
inherited Create;
|
||||
sym:=asym;
|
||||
offset:=aoffset;
|
||||
datalabel:=alabel;
|
||||
end;
|
||||
|
||||
{*****************************************************************************
|
||||
TAsmList
|
||||
@ -311,6 +331,7 @@ implementation
|
||||
CurrAsmList:=TAsmList.create;
|
||||
for hal:=low(TAsmListType) to high(TAsmListType) do
|
||||
AsmLists[hal]:=TAsmList.create;
|
||||
WideInits :=TLinkedList.create;
|
||||
{ PIC data }
|
||||
if (target_info.system in [system_powerpc_darwin,system_powerpc64_darwin,system_i386_darwin,system_arm_darwin]) then
|
||||
AsmLists[al_picdata].concat(tai_section.create(sec_data_nonlazy,'',sizeof(pint)));
|
||||
@ -345,6 +366,7 @@ implementation
|
||||
{$ifdef MEMDEBUG}
|
||||
memasmlists.start;
|
||||
{$endif}
|
||||
WideInits.free;
|
||||
for hal:=low(TAsmListType) to high(TAsmListType) do
|
||||
AsmLists[hal].free;
|
||||
CurrAsmList.free;
|
||||
|
118
compiler/asmutils.pas
Normal file
118
compiler/asmutils.pas
Normal file
@ -0,0 +1,118 @@
|
||||
{
|
||||
Copyright (c) 1998-2006 by Florian Klaempfl
|
||||
|
||||
This unit contains utility functions for assembler output
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
****************************************************************************
|
||||
}
|
||||
unit asmutils;
|
||||
|
||||
interface
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
uses
|
||||
aasmbase,
|
||||
aasmdata;
|
||||
|
||||
|
||||
function emit_ansistring_const(list:TAsmList;data:PChar;len:LongInt;NewSection:Boolean=True):TAsmLabel;
|
||||
function emit_unicodestring_const(list:TAsmList;data:Pointer;Winlike:Boolean):TAsmLabel;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
globals,
|
||||
globtype,
|
||||
systems,
|
||||
verbose,
|
||||
aasmtai,
|
||||
widestr,
|
||||
symdef;
|
||||
|
||||
function emit_ansistring_const(list:TAsmList;data:PChar;len:LongInt;NewSection:Boolean): TAsmLabel;
|
||||
var
|
||||
referencelab: TAsmLabel;
|
||||
s: PChar;
|
||||
begin
|
||||
current_asmdata.getdatalabel(result);
|
||||
if NewSection then
|
||||
new_section(list,sec_rodata,result.name,const_align(sizeof(pint)));
|
||||
referencelab := nil;
|
||||
if target_info.system in systems_darwin then
|
||||
begin
|
||||
current_asmdata.getdatalabel(referencelab);
|
||||
list.concat(tai_label.create(referencelab));
|
||||
end;
|
||||
list.concat(tai_const.create_pint(-1));
|
||||
list.concat(tai_const.create_pint(len));
|
||||
{ make sure the string doesn't get dead stripped if the header is referenced }
|
||||
if target_info.system in systems_darwin then
|
||||
list.concat(tai_directive.create(asd_reference,result.name));
|
||||
list.concat(tai_label.create(result));
|
||||
{ and vice versa }
|
||||
if target_info.system in systems_darwin then
|
||||
list.concat(tai_directive.create(asd_reference,referencelab.name));
|
||||
|
||||
getmem(s,len+1);
|
||||
move(data^,s^,len);
|
||||
s[len]:=#0;
|
||||
list.concat(tai_string.create_pchar(s,len+1)); { terminating zero included }
|
||||
end;
|
||||
|
||||
function emit_unicodestring_const(list:TAsmList;data:Pointer;Winlike:Boolean):TAsmLabel;
|
||||
var
|
||||
referencelab: TAsmLabel;
|
||||
i, strlength: SizeInt;
|
||||
begin
|
||||
current_asmdata.getdatalabel(result);
|
||||
new_section(list,sec_rodata,result.name,const_align(sizeof(pint)));
|
||||
referencelab := nil;
|
||||
if target_info.system in systems_darwin then
|
||||
begin
|
||||
current_asmdata.getdatalabel(referencelab);
|
||||
list.concat(tai_label.create(referencelab));
|
||||
end;
|
||||
strlength := getlengthwidestring(pcompilerwidestring(data));
|
||||
if Winlike then
|
||||
list.concat(Tai_const.Create_32bit(strlength*cwidechartype.size))
|
||||
else
|
||||
begin
|
||||
list.concat(Tai_const.Create_pint(-1));
|
||||
list.concat(Tai_const.Create_pint(strlength*cwidechartype.size));
|
||||
end;
|
||||
{ make sure the string doesn't get dead stripped if the header is referenced }
|
||||
if (target_info.system in systems_darwin) then
|
||||
list.concat(tai_directive.create(asd_reference,result.name));
|
||||
list.concat(Tai_label.Create(result));
|
||||
{ ... and vice versa }
|
||||
if (target_info.system in systems_darwin) then
|
||||
list.concat(tai_directive.create(asd_reference,referencelab.name));
|
||||
if cwidechartype.size = 2 then
|
||||
begin
|
||||
for i:=0 to strlength-1 do
|
||||
list.concat(Tai_const.Create_16bit(pcompilerwidestring(data)^.data[i]));
|
||||
{ ending #0 }
|
||||
list.concat(Tai_const.Create_16bit(0));
|
||||
end
|
||||
else
|
||||
InternalError(200904271); { codegeneration for other sizes must be written }
|
||||
end;
|
||||
|
||||
|
||||
end.
|
@ -37,7 +37,7 @@ uses
|
||||
symconst,symtype,symdef,symsym,
|
||||
verbose,fmodule,ppu,
|
||||
aasmbase,aasmtai,aasmdata,
|
||||
aasmcpu;
|
||||
aasmcpu,asmutils;
|
||||
|
||||
Type
|
||||
{ These are used to form a singly-linked list, ordered by hash value }
|
||||
@ -127,31 +127,6 @@ uses
|
||||
|
||||
|
||||
procedure Tresourcestrings.CreateResourceStringData;
|
||||
|
||||
function WriteValueString(p:pchar;len:longint):TasmLabel;
|
||||
var
|
||||
s : pchar;
|
||||
referencelab: TAsmLabel;
|
||||
begin
|
||||
if (target_info.system in systems_darwin) then
|
||||
begin
|
||||
current_asmdata.getdatalabel(referencelab);
|
||||
current_asmdata.asmlists[al_const].concat(tai_label.create(referencelab));
|
||||
end;
|
||||
current_asmdata.getdatalabel(result);
|
||||
current_asmdata.asmlists[al_const].concat(tai_align.create(const_align(sizeof(pint))));
|
||||
current_asmdata.asmlists[al_const].concat(tai_const.create_pint(-1));
|
||||
current_asmdata.asmlists[al_const].concat(tai_const.create_pint(len));
|
||||
current_asmdata.asmlists[al_const].concat(tai_label.create(result));
|
||||
if (target_info.system in systems_darwin) then
|
||||
current_asmdata.asmlists[al_const].concat(tai_directive.create(asd_reference,referencelab.name));
|
||||
getmem(s,len+1);
|
||||
move(p^,s^,len);
|
||||
s[len]:=#0;
|
||||
current_asmdata.asmlists[al_const].concat(tai_string.create_pchar(s,len));
|
||||
current_asmdata.asmlists[al_const].concat(tai_const.create_8bit(0));
|
||||
end;
|
||||
|
||||
Var
|
||||
namelab,
|
||||
valuelab : tasmlabel;
|
||||
@ -163,13 +138,15 @@ uses
|
||||
makes the linking too dependent on the linker script requiring a SORT(*) for
|
||||
the data sections }
|
||||
maybe_new_object_file(current_asmdata.asmlists[al_const]);
|
||||
new_section(current_asmdata.asmlists[al_const],sec_data,make_mangledname('RESSTRTABLE',current_module.localsymtable,''),sizeof(pint));
|
||||
|
||||
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.createname_global(
|
||||
make_mangledname('RESSTR',current_module.localsymtable,'START'),AT_DATA,0));
|
||||
|
||||
{ Write unitname entry }
|
||||
namelab:=WriteValueString(@current_module.localsymtable.name^[1],length(current_module.localsymtable.name^));
|
||||
namelab:=emit_ansistring_const(current_asmdata.asmlists[al_const],@current_module.localsymtable.name^[1],length(current_module.localsymtable.name^),False);
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(namelab));
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(nil));
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(nil));
|
||||
@ -185,11 +162,12 @@ uses
|
||||
new_section(current_asmdata.asmlists[al_const],sec_rodata,make_mangledname('RESSTR',current_module.localsymtable,'d_'+r.name),sizeof(pint));
|
||||
{ Write default value }
|
||||
if assigned(R.value) and (R.len<>0) then
|
||||
valuelab:=WriteValueString(R.Value,R.Len)
|
||||
valuelab:=emit_ansistring_const(current_asmdata.asmlists[al_const],R.Value,R.Len,False)
|
||||
else
|
||||
valuelab:=nil;
|
||||
{ Append the name as a ansistring. }
|
||||
namelab:=WriteValueString(@R.Name[1],length(R.name));
|
||||
current_asmdata.asmlists[al_const].concat(cai_align.Create(const_align(sizeof(pint))));
|
||||
namelab:=emit_ansistring_const(current_asmdata.asmlists[al_const],@R.Name[1],length(R.name),False);
|
||||
|
||||
{
|
||||
Resourcestring index:
|
||||
|
@ -71,7 +71,7 @@ implementation
|
||||
symconst,symdef,aasmbase,aasmtai,aasmdata,aasmcpu,defutil,
|
||||
cpuinfo,cpubase,
|
||||
cgbase,cgobj,cgutils,
|
||||
ncgutil, cclasses
|
||||
ncgutil, cclasses,asmutils
|
||||
;
|
||||
|
||||
|
||||
@ -306,41 +306,13 @@ implementation
|
||||
{ :-(, we must generate a new entry }
|
||||
if not assigned(entry^.Data) then
|
||||
begin
|
||||
current_asmdata.getdatalabel(lastlabel);
|
||||
lab_str:=lastlabel;
|
||||
entry^.Data := lastlabel;
|
||||
maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
|
||||
if (len=0) or
|
||||
not(cst_type in [cst_ansistring,cst_widestring,cst_unicodestring]) then
|
||||
new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(sizeof(pint)))
|
||||
else
|
||||
new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata,lastlabel.name,const_align(sizeof(pint)));
|
||||
{ generate an ansi string ? }
|
||||
case cst_type of
|
||||
cst_ansistring:
|
||||
begin
|
||||
if len=0 then
|
||||
InternalError(2008032301) { empty string should be handled above }
|
||||
else
|
||||
begin
|
||||
current_asmdata.getdatalabel(l1);
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l1));
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_pint(-1));
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_pint(len));
|
||||
|
||||
{ make sure the string doesn't get dead stripped if the header is referenced }
|
||||
if (target_info.system in systems_darwin) then
|
||||
current_asmdata.asmlists[al_typedconsts].concat(tai_directive.create(asd_reference,lastlabel.name));
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));
|
||||
{ ... and vice versa }
|
||||
if (target_info.system in systems_darwin) then
|
||||
current_asmdata.asmlists[al_typedconsts].concat(tai_directive.create(asd_reference,l1.name));
|
||||
{ include also terminating zero }
|
||||
getmem(pc,len+1);
|
||||
move(value_str^,pc^,len);
|
||||
pc[len]:=#0;
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_string.Create_pchar(pc,len+1));
|
||||
end;
|
||||
lastlabel:=emit_ansistring_const(current_asmdata.AsmLists[al_typedconsts],value_str,len);
|
||||
end;
|
||||
cst_unicodestring,
|
||||
cst_widestring:
|
||||
@ -348,35 +320,16 @@ implementation
|
||||
if len=0 then
|
||||
InternalError(2008032302) { empty string should be handled above }
|
||||
else
|
||||
begin
|
||||
current_asmdata.getdatalabel(l1);
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l1));
|
||||
{ we use always UTF-16 coding for constants }
|
||||
{ at least for now }
|
||||
{ Consts.concat(Tai_const.Create_8bit(2)); }
|
||||
if (cst_type=cst_widestring) and (tf_winlikewidestring in target_info.flags) then
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(len*cwidechartype.size))
|
||||
else
|
||||
begin
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_pint(-1));
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_pint(len*cwidechartype.size));
|
||||
end;
|
||||
|
||||
{ make sure the string doesn't get dead stripped if the header is referenced }
|
||||
if (target_info.system in systems_darwin) then
|
||||
current_asmdata.asmlists[al_typedconsts].concat(tai_directive.create(asd_reference,lastlabel.name));
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));
|
||||
{ ... and vice versa }
|
||||
if (target_info.system in systems_darwin) then
|
||||
current_asmdata.asmlists[al_typedconsts].concat(tai_directive.create(asd_reference,l1.name));
|
||||
for i:=0 to len-1 do
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_16bit(pcompilerwidestring(value_str)^.data[i]));
|
||||
{ terminating zero }
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_16bit(0));
|
||||
end;
|
||||
lastlabel := emit_unicodestring_const(current_asmdata.AsmLists[al_typedconsts],
|
||||
value_str,
|
||||
(cst_type=cst_widestring) and (tf_winlikewidestring in target_info.flags));
|
||||
end;
|
||||
cst_shortstring:
|
||||
begin
|
||||
current_asmdata.getdatalabel(lastlabel);
|
||||
maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
|
||||
new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(sizeof(pint)));
|
||||
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));
|
||||
{ truncate strings larger than 255 chars }
|
||||
if len>255 then
|
||||
@ -392,6 +345,10 @@ implementation
|
||||
end;
|
||||
cst_conststring:
|
||||
begin
|
||||
current_asmdata.getdatalabel(lastlabel);
|
||||
maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
|
||||
new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(sizeof(pint)));
|
||||
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));
|
||||
{ include terminating zero }
|
||||
getmem(pc,len+1);
|
||||
@ -400,6 +357,8 @@ implementation
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_string.Create_pchar(pc,len+1));
|
||||
end;
|
||||
end;
|
||||
lab_str:=lastlabel;
|
||||
entry^.Data:=lastlabel;
|
||||
end;
|
||||
end;
|
||||
if cst_type in [cst_ansistring, cst_widestring, cst_unicodestring] then
|
||||
|
@ -236,6 +236,66 @@ implementation
|
||||
ltvTable.Free;
|
||||
end;
|
||||
|
||||
procedure InsertWideInits;
|
||||
var
|
||||
s: string;
|
||||
item: TTCInitItem;
|
||||
begin
|
||||
item:=TTCInitItem(current_asmdata.WideInits.First);
|
||||
if item=nil then
|
||||
exit;
|
||||
s:=make_mangledname('WIDEINITS',current_module.localsymtable,'');
|
||||
maybe_new_object_file(current_asmdata.asmlists[al_globals]);
|
||||
new_section(current_asmdata.asmlists[al_globals],sec_data,s,sizeof(pint));
|
||||
current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
|
||||
repeat
|
||||
{ address to initialize }
|
||||
current_asmdata.asmlists[al_globals].concat(Tai_const.createname(item.sym.mangledname, item.offset));
|
||||
{ value with which to initialize }
|
||||
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(item.datalabel));
|
||||
item:=TTCInitItem(item.Next);
|
||||
until item=nil;
|
||||
{ end-of-list marker }
|
||||
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
|
||||
current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname(s));
|
||||
current_module.flags:=current_module.flags or uf_wideinits;
|
||||
end;
|
||||
|
||||
procedure InsertWideInitsTablesTable;
|
||||
var
|
||||
hp: tused_unit;
|
||||
lwiTables: TAsmList;
|
||||
count: longint;
|
||||
begin
|
||||
lwiTables:=TAsmList.Create;
|
||||
count:=0;
|
||||
hp:=tused_unit(usedunits.first);
|
||||
while assigned(hp) do
|
||||
begin
|
||||
if (hp.u.flags and uf_wideinits)=uf_wideinits then
|
||||
begin
|
||||
lwiTables.concat(Tai_const.Createname(make_mangledname('WIDEINITS',hp.u.globalsymtable,''),0));
|
||||
inc(count);
|
||||
end;
|
||||
hp:=tused_unit(hp.next);
|
||||
end;
|
||||
{ Add program widestring consts, if any }
|
||||
if (current_module.flags and uf_wideinits)=uf_wideinits then
|
||||
begin
|
||||
lwiTables.concat(Tai_const.Createname(make_mangledname('WIDEINITS',current_module.localsymtable,''),0));
|
||||
inc(count);
|
||||
end;
|
||||
{ Insert TableCount at start }
|
||||
lwiTables.insert(Tai_const.Create_32bit(count));
|
||||
{ insert in data segment }
|
||||
maybe_new_object_file(current_asmdata.asmlists[al_globals]);
|
||||
new_section(current_asmdata.asmlists[al_globals],sec_data,'FPC_WIDEINITTABLES',sizeof(pint));
|
||||
current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('FPC_WIDEINITTABLES',AT_DATA,0));
|
||||
current_asmdata.asmlists[al_globals].concatlist(lwiTables);
|
||||
current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname('FPC_WIDEINITTABLES'));
|
||||
lwiTables.free;
|
||||
end;
|
||||
|
||||
|
||||
Function CheckResourcesUsed : boolean;
|
||||
var
|
||||
@ -1225,6 +1285,9 @@ implementation
|
||||
{ Resource strings }
|
||||
GenerateResourceStrings;
|
||||
|
||||
{ Widestring typed constants }
|
||||
InsertWideInits;
|
||||
|
||||
{ generate debuginfo }
|
||||
if (cs_debuginfo in current_settings.moduleswitches) then
|
||||
current_debuginfo.inserttypeinfo;
|
||||
@ -2193,10 +2256,14 @@ implementation
|
||||
{ Resource strings }
|
||||
GenerateResourceStrings;
|
||||
|
||||
{ Windows widestring needing initialization }
|
||||
InsertWideInits;
|
||||
|
||||
{ insert Tables and StackLength }
|
||||
insertinitfinaltable;
|
||||
InsertThreadvarTablesTable;
|
||||
InsertResourceTablesTable;
|
||||
InsertWideInitsTablesTable;
|
||||
insertmemorysizes;
|
||||
|
||||
{ Insert symbol to resource info }
|
||||
|
@ -43,7 +43,7 @@ type
|
||||
{$endif Test_Double_checksum}
|
||||
|
||||
const
|
||||
CurrentPPUVersion = 106;
|
||||
CurrentPPUVersion = 107;
|
||||
|
||||
{ buffer sizes }
|
||||
maxentrysize = 1024;
|
||||
@ -156,6 +156,7 @@ const
|
||||
uf_has_resourcefiles = $80000; { this unit has external resources (using $R directive)}
|
||||
uf_has_exports = $100000; { this module or a used unit has exports }
|
||||
uf_has_dwarf_debuginfo = $200000; { this unit has dwarf debuginfo generated }
|
||||
uf_wideinits = $400000; { this unit has winlike widestring typed constants }
|
||||
|
||||
|
||||
type
|
||||
|
@ -45,7 +45,7 @@ implementation
|
||||
pbase,pexpr,pdecvar,
|
||||
{ codegen }
|
||||
cpuinfo,cgbase,dbgbase,
|
||||
wpobase
|
||||
wpobase,asmutils
|
||||
;
|
||||
|
||||
{$maxfpuregisters 0}
|
||||
@ -166,9 +166,16 @@ implementation
|
||||
read typed const
|
||||
*****************************************************************************}
|
||||
|
||||
type
|
||||
{ context used for parsing complex types (arrays/records/objects) }
|
||||
threc = record
|
||||
list : tasmlist;
|
||||
origsym: tstaticvarsym;
|
||||
offset: aint;
|
||||
end;
|
||||
|
||||
{ this procedure reads typed constants }
|
||||
procedure read_typed_const_data(list:tasmlist;def:tdef);
|
||||
procedure read_typed_const_data(var hr:threc;def:tdef); forward;
|
||||
|
||||
procedure parse_orddef(list:tasmlist;def:torddef);
|
||||
var
|
||||
@ -408,7 +415,7 @@ implementation
|
||||
else
|
||||
varalign:=0;
|
||||
varalign:=const_align(varalign);
|
||||
current_asmdata.asmlists[al_const].concat(Tai_align.Create(varalign));
|
||||
new_section(current_asmdata.asmlists[al_const], sec_rodata, ll.name, varalign);
|
||||
current_asmdata.asmlists[al_const].concat(Tai_label.Create(ll));
|
||||
if p.nodetype=stringconstn then
|
||||
begin
|
||||
@ -635,15 +642,15 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure parse_stringdef(list:tasmlist;def:tstringdef);
|
||||
procedure parse_stringdef(const hr:threc;def:tstringdef);
|
||||
var
|
||||
n : tnode;
|
||||
i : longint;
|
||||
strlength : aint;
|
||||
strval : pchar;
|
||||
strch : char;
|
||||
ll,ll2 : tasmlabel;
|
||||
ll : tasmlabel;
|
||||
ca : pchar;
|
||||
winlike : boolean;
|
||||
begin
|
||||
n:=comp_expr(true);
|
||||
{ load strval and strlength of the constant tree }
|
||||
@ -690,12 +697,12 @@ implementation
|
||||
message2(parser_w_string_too_long,strpas(strval),tostr(def.size-1));
|
||||
strlength:=def.size-1;
|
||||
end;
|
||||
list.concat(Tai_const.Create_8bit(strlength));
|
||||
hr.list.concat(Tai_const.Create_8bit(strlength));
|
||||
{ this can also handle longer strings }
|
||||
getmem(ca,strlength+1);
|
||||
move(strval^,ca^,strlength);
|
||||
ca[strlength]:=#0;
|
||||
list.concat(Tai_string.Create_pchar(ca,strlength));
|
||||
hr.list.concat(Tai_string.Create_pchar(ca,strlength));
|
||||
{ fillup with spaces if size is shorter }
|
||||
if def.size>strlength then
|
||||
begin
|
||||
@ -705,69 +712,41 @@ implementation
|
||||
fillchar(ca[0],def.size-strlength-1,' ');
|
||||
ca[def.size-strlength-1]:=#0;
|
||||
{ this can also handle longer strings }
|
||||
list.concat(Tai_string.Create_pchar(ca,def.size-strlength-1));
|
||||
hr.list.concat(Tai_string.Create_pchar(ca,def.size-strlength-1));
|
||||
end;
|
||||
end;
|
||||
st_ansistring:
|
||||
begin
|
||||
{ an empty ansi string is nil! }
|
||||
if (strlength=0) then
|
||||
list.concat(Tai_const.Create_sym(nil))
|
||||
ll := nil
|
||||
else
|
||||
begin
|
||||
current_asmdata.getdatalabel(ll);
|
||||
list.concat(Tai_const.Create_sym(ll));
|
||||
current_asmdata.getdatalabel(ll2);
|
||||
current_asmdata.asmlists[al_const].concat(tai_align.create(const_align(sizeof(pint))));
|
||||
current_asmdata.asmlists[al_const].concat(Tai_label.Create(ll2));
|
||||
current_asmdata.asmlists[al_const].concat(Tai_const.Create_pint(-1));
|
||||
current_asmdata.asmlists[al_const].concat(Tai_const.Create_pint(strlength));
|
||||
{ make sure the string doesn't get dead stripped if the header is referenced }
|
||||
if (target_info.system in systems_darwin) then
|
||||
current_asmdata.asmlists[al_const].concat(tai_directive.create(asd_reference,ll.name));
|
||||
current_asmdata.asmlists[al_const].concat(Tai_label.Create(ll));
|
||||
{ ... and vice versa }
|
||||
if (target_info.system in systems_darwin) then
|
||||
current_asmdata.asmlists[al_const].concat(tai_directive.create(asd_reference,ll2.name));
|
||||
getmem(ca,strlength+1);
|
||||
move(strval^,ca^,strlength);
|
||||
{ The terminating #0 to be stored in the .data section (JM) }
|
||||
ca[strlength]:=#0;
|
||||
current_asmdata.asmlists[al_const].concat(Tai_string.Create_pchar(ca,strlength+1));
|
||||
end;
|
||||
ll := emit_ansistring_const(current_asmdata.asmlists[al_const],strval,strlength);
|
||||
hr.list.concat(Tai_const.Create_sym(ll));
|
||||
end;
|
||||
st_unicodestring,
|
||||
st_widestring:
|
||||
begin
|
||||
{ an empty ansi string is nil! }
|
||||
{ an empty wide/unicode string is nil! }
|
||||
if (strlength=0) then
|
||||
list.concat(Tai_const.Create_sym(nil))
|
||||
ll := nil
|
||||
else
|
||||
begin
|
||||
winlike := (def.stringtype=st_widestring) and (tf_winlikewidestring in target_info.flags);
|
||||
ll := emit_unicodestring_const(current_asmdata.asmlists[al_const],
|
||||
strval,
|
||||
winlike);
|
||||
|
||||
{ collect global Windows widestrings }
|
||||
if winlike and (hr.origsym.owner.symtablelevel <= main_program_level) then
|
||||
begin
|
||||
current_asmdata.getdatalabel(ll);
|
||||
list.concat(Tai_const.Create_sym(ll));
|
||||
current_asmdata.getdatalabel(ll2);
|
||||
current_asmdata.asmlists[al_const].concat(tai_align.create(const_align(sizeof(pint))));
|
||||
current_asmdata.asmlists[al_const].concat(Tai_label.Create(ll2));
|
||||
if (def.stringtype=st_widestring) and (tf_winlikewidestring in target_info.flags) then
|
||||
current_asmdata.asmlists[al_const].concat(Tai_const.Create_32bit(strlength*cwidechartype.size))
|
||||
else
|
||||
begin
|
||||
current_asmdata.asmlists[al_const].concat(Tai_const.Create_pint(-1));
|
||||
current_asmdata.asmlists[al_const].concat(Tai_const.Create_pint(strlength*cwidechartype.size));
|
||||
end;
|
||||
{ make sure the string doesn't get dead stripped if the header is referenced }
|
||||
if (target_info.system in systems_darwin) then
|
||||
current_asmdata.asmlists[al_const].concat(tai_directive.create(asd_reference,ll.name));
|
||||
current_asmdata.asmlists[al_const].concat(Tai_label.Create(ll));
|
||||
{ ... and vice versa }
|
||||
if (target_info.system in systems_darwin) then
|
||||
current_asmdata.asmlists[al_const].concat(tai_directive.create(asd_reference,ll2.name));
|
||||
for i:=0 to strlength-1 do
|
||||
current_asmdata.asmlists[al_const].concat(Tai_const.Create_16bit(pcompilerwidestring(strval)^.data[i]));
|
||||
{ ending #0 }
|
||||
current_asmdata.asmlists[al_const].concat(Tai_const.Create_16bit(0))
|
||||
current_asmdata.WideInits.Concat(
|
||||
TTCInitItem.Create(hr.origsym, hr.offset, ll)
|
||||
);
|
||||
ll := nil;
|
||||
end;
|
||||
end;
|
||||
hr.list.concat(Tai_const.Create_sym(ll));
|
||||
end;
|
||||
else
|
||||
internalerror(200107081);
|
||||
@ -838,7 +817,7 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure parse_arraydef(list:tasmlist;def:tarraydef);
|
||||
procedure parse_arraydef(hr:threc;def:tarraydef);
|
||||
var
|
||||
n : tnode;
|
||||
i : longint;
|
||||
@ -851,24 +830,26 @@ implementation
|
||||
begin
|
||||
{ Only allow nil initialization }
|
||||
consume(_NIL);
|
||||
list.concat(Tai_const.Create_sym(nil));
|
||||
hr.list.concat(Tai_const.Create_sym(nil));
|
||||
end
|
||||
{ packed array constant }
|
||||
else if is_packed_array(def) and
|
||||
((def.elepackedbitsize mod 8 <> 0) or
|
||||
not ispowerof2(def.elepackedbitsize div 8,i)) then
|
||||
begin
|
||||
parse_packed_array_def(list,def);
|
||||
parse_packed_array_def(hr.list,def);
|
||||
end
|
||||
{ normal array const between brackets }
|
||||
else if try_to_consume(_LKLAMMER) then
|
||||
begin
|
||||
hr.offset:=0;
|
||||
for i:=def.lowrange to def.highrange-1 do
|
||||
begin
|
||||
read_typed_const_data(list,def.elementdef);
|
||||
read_typed_const_data(hr,def.elementdef);
|
||||
Inc(hr.offset,def.elementdef.size);
|
||||
consume(_COMMA);
|
||||
end;
|
||||
read_typed_const_data(list,def.elementdef);
|
||||
read_typed_const_data(hr,def.elementdef);
|
||||
consume(_RKLAMMER);
|
||||
end
|
||||
{ if array of char then we allow also a string }
|
||||
@ -902,12 +883,12 @@ implementation
|
||||
begin
|
||||
if i+1-def.lowrange<=len then
|
||||
begin
|
||||
list.concat(Tai_const.Create_8bit(byte(ca^)));
|
||||
hr.list.concat(Tai_const.Create_8bit(byte(ca^)));
|
||||
inc(ca);
|
||||
end
|
||||
else
|
||||
{Fill the remaining positions with #0.}
|
||||
list.concat(Tai_const.Create_8bit(0));
|
||||
hr.list.concat(Tai_const.Create_8bit(0));
|
||||
end;
|
||||
n.free;
|
||||
end
|
||||
@ -983,7 +964,7 @@ implementation
|
||||
n.free;
|
||||
end;
|
||||
|
||||
procedure parse_recorddef(list:tasmlist;def:trecorddef);
|
||||
procedure parse_recorddef(hr:threc;def:trecorddef);
|
||||
var
|
||||
n : tnode;
|
||||
symidx : longint;
|
||||
@ -997,6 +978,7 @@ implementation
|
||||
bp : tbitpackedval;
|
||||
error,
|
||||
is_packed: boolean;
|
||||
startoffset: aint;
|
||||
|
||||
procedure handle_stringconstn;
|
||||
var
|
||||
@ -1005,11 +987,11 @@ implementation
|
||||
hs:=strpas(tstringconstnode(n).value_str);
|
||||
if string2guid(hs,tmpguid) then
|
||||
begin
|
||||
list.concat(Tai_const.Create_32bit(longint(tmpguid.D1)));
|
||||
list.concat(Tai_const.Create_16bit(tmpguid.D2));
|
||||
list.concat(Tai_const.Create_16bit(tmpguid.D3));
|
||||
hr.list.concat(Tai_const.Create_32bit(longint(tmpguid.D1)));
|
||||
hr.list.concat(Tai_const.Create_16bit(tmpguid.D2));
|
||||
hr.list.concat(Tai_const.Create_16bit(tmpguid.D3));
|
||||
for i:=Low(tmpguid.D4) to High(tmpguid.D4) do
|
||||
list.concat(Tai_const.Create_8bit(tmpguid.D4[i]));
|
||||
hr.list.concat(Tai_const.Create_8bit(tmpguid.D4[i]));
|
||||
end
|
||||
else
|
||||
Message(parser_e_improper_guid_syntax);
|
||||
@ -1031,11 +1013,11 @@ implementation
|
||||
if n.nodetype=guidconstn then
|
||||
begin
|
||||
tmpguid:=tguidconstnode(n).value;
|
||||
list.concat(Tai_const.Create_32bit(longint(tmpguid.D1)));
|
||||
list.concat(Tai_const.Create_16bit(tmpguid.D2));
|
||||
list.concat(Tai_const.Create_16bit(tmpguid.D3));
|
||||
hr.list.concat(Tai_const.Create_32bit(longint(tmpguid.D1)));
|
||||
hr.list.concat(Tai_const.Create_16bit(tmpguid.D2));
|
||||
hr.list.concat(Tai_const.Create_16bit(tmpguid.D3));
|
||||
for i:=Low(tmpguid.D4) to High(tmpguid.D4) do
|
||||
list.concat(Tai_const.Create_8bit(tmpguid.D4[i]));
|
||||
hr.list.concat(Tai_const.Create_8bit(tmpguid.D4[i]));
|
||||
end
|
||||
else
|
||||
Message(parser_e_illegal_expression);
|
||||
@ -1071,6 +1053,7 @@ implementation
|
||||
sorg:='';
|
||||
srsym:=tsym(def.symtable.SymList[symidx]);
|
||||
recsym := nil;
|
||||
startoffset:=hr.offset;
|
||||
while token<>_RKLAMMER do
|
||||
begin
|
||||
s:=pattern;
|
||||
@ -1136,14 +1119,14 @@ implementation
|
||||
fillbytes:=tfieldvarsym(srsym).fieldoffset-curroffset
|
||||
else
|
||||
begin
|
||||
flush_packed_value(list,bp);
|
||||
flush_packed_value(hr.list,bp);
|
||||
{ curoffset is now aligned to the next byte }
|
||||
curroffset:=align(curroffset,8);
|
||||
{ offsets are in bits in this case }
|
||||
fillbytes:=(tfieldvarsym(srsym).fieldoffset-curroffset) div 8;
|
||||
end;
|
||||
for i:=1 to fillbytes do
|
||||
list.concat(Tai_const.Create_8bit(0))
|
||||
hr.list.concat(Tai_const.Create_8bit(0))
|
||||
end;
|
||||
|
||||
{ new position }
|
||||
@ -1160,15 +1143,16 @@ implementation
|
||||
begin
|
||||
if is_packed then
|
||||
begin
|
||||
flush_packed_value(list,bp);
|
||||
flush_packed_value(hr.list,bp);
|
||||
curroffset:=align(curroffset,8);
|
||||
end;
|
||||
read_typed_const_data(list,tfieldvarsym(srsym).vardef);
|
||||
hr.offset:=startoffset+tfieldvarsym(srsym).fieldoffset;
|
||||
read_typed_const_data(hr,tfieldvarsym(srsym).vardef);
|
||||
end
|
||||
else
|
||||
begin
|
||||
bp.packedbitsize:=tfieldvarsym(srsym).vardef.packedbitsize;
|
||||
parse_single_packed_const(list,tfieldvarsym(srsym).vardef,bp);
|
||||
parse_single_packed_const(hr.list,tfieldvarsym(srsym).vardef,bp);
|
||||
end;
|
||||
|
||||
{ keep previous field for checking whether whole }
|
||||
@ -1201,18 +1185,18 @@ implementation
|
||||
fillbytes:=def.size-curroffset
|
||||
else
|
||||
begin
|
||||
flush_packed_value(list,bp);
|
||||
flush_packed_value(hr.list,bp);
|
||||
curroffset:=align(curroffset,8);
|
||||
fillbytes:=def.size-(curroffset div 8);
|
||||
end;
|
||||
for i:=1 to fillbytes do
|
||||
list.concat(Tai_const.Create_8bit(0));
|
||||
hr.list.concat(Tai_const.Create_8bit(0));
|
||||
|
||||
consume(_RKLAMMER);
|
||||
end;
|
||||
|
||||
|
||||
procedure parse_objectdef(list:tasmlist;def:tobjectdef);
|
||||
{ note: hr is passed by value }
|
||||
procedure parse_objectdef(hr:threc;def:tobjectdef);
|
||||
var
|
||||
n : tnode;
|
||||
i : longint;
|
||||
@ -1222,6 +1206,7 @@ implementation
|
||||
curroffset : aint;
|
||||
s,sorg : TIDString;
|
||||
vmtwritten : boolean;
|
||||
startoffset:aint;
|
||||
begin
|
||||
{ no support for packed object }
|
||||
if is_packed_record_or_object(def) then
|
||||
@ -1240,7 +1225,7 @@ implementation
|
||||
consume_all_until(_SEMICOLON);
|
||||
end
|
||||
else
|
||||
list.concat(Tai_const.Create_sym(nil));
|
||||
hr.list.concat(Tai_const.Create_sym(nil));
|
||||
n.free;
|
||||
exit;
|
||||
end;
|
||||
@ -1254,6 +1239,7 @@ implementation
|
||||
end;
|
||||
|
||||
consume(_LKLAMMER);
|
||||
startoffset:=hr.offset;
|
||||
curroffset:=0;
|
||||
vmtwritten:=false;
|
||||
while token<>_RKLAMMER do
|
||||
@ -1295,8 +1281,8 @@ implementation
|
||||
(def.vmt_offset<fieldoffset) then
|
||||
begin
|
||||
for i:=1 to def.vmt_offset-curroffset do
|
||||
list.concat(tai_const.create_8bit(0));
|
||||
list.concat(tai_const.createname(def.vmt_mangledname,0));
|
||||
hr.list.concat(tai_const.create_8bit(0));
|
||||
hr.list.concat(tai_const.createname(def.vmt_mangledname,0));
|
||||
{ this is more general }
|
||||
curroffset:=def.vmt_offset + sizeof(pint);
|
||||
vmtwritten:=true;
|
||||
@ -1305,13 +1291,14 @@ implementation
|
||||
{ if needed fill }
|
||||
if fieldoffset>curroffset then
|
||||
for i:=1 to fieldoffset-curroffset do
|
||||
list.concat(Tai_const.Create_8bit(0));
|
||||
hr.list.concat(Tai_const.Create_8bit(0));
|
||||
|
||||
{ new position }
|
||||
curroffset:=fieldoffset+vardef.size;
|
||||
|
||||
{ read the data }
|
||||
read_typed_const_data(list,vardef);
|
||||
hr.offset:=startoffset+fieldoffset;
|
||||
read_typed_const_data(hr,vardef);
|
||||
|
||||
if not try_to_consume(_SEMICOLON) then
|
||||
break;
|
||||
@ -1322,16 +1309,17 @@ implementation
|
||||
(def.vmt_offset>=curroffset) then
|
||||
begin
|
||||
for i:=1 to def.vmt_offset-curroffset do
|
||||
list.concat(tai_const.create_8bit(0));
|
||||
list.concat(tai_const.createname(def.vmt_mangledname,0));
|
||||
hr.list.concat(tai_const.create_8bit(0));
|
||||
hr.list.concat(tai_const.createname(def.vmt_mangledname,0));
|
||||
{ this is more general }
|
||||
curroffset:=def.vmt_offset + sizeof(pint);
|
||||
end;
|
||||
for i:=1 to def.size-curroffset do
|
||||
list.concat(Tai_const.Create_8bit(0));
|
||||
hr.list.concat(Tai_const.Create_8bit(0));
|
||||
consume(_RKLAMMER);
|
||||
end;
|
||||
|
||||
procedure read_typed_const_data(var hr:threc;def:tdef);
|
||||
var
|
||||
old_block_type : tblock_type;
|
||||
begin
|
||||
@ -1339,27 +1327,27 @@ implementation
|
||||
block_type:=bt_const;
|
||||
case def.typ of
|
||||
orddef :
|
||||
parse_orddef(list,torddef(def));
|
||||
parse_orddef(hr.list,torddef(def));
|
||||
floatdef :
|
||||
parse_floatdef(list,tfloatdef(def));
|
||||
parse_floatdef(hr.list,tfloatdef(def));
|
||||
classrefdef :
|
||||
parse_classrefdef(list,tclassrefdef(def));
|
||||
parse_classrefdef(hr.list,tclassrefdef(def));
|
||||
pointerdef :
|
||||
parse_pointerdef(list,tpointerdef(def));
|
||||
parse_pointerdef(hr.list,tpointerdef(def));
|
||||
setdef :
|
||||
parse_setdef(list,tsetdef(def));
|
||||
parse_setdef(hr.list,tsetdef(def));
|
||||
enumdef :
|
||||
parse_enumdef(list,tenumdef(def));
|
||||
parse_enumdef(hr.list,tenumdef(def));
|
||||
stringdef :
|
||||
parse_stringdef(list,tstringdef(def));
|
||||
parse_stringdef(hr,tstringdef(def));
|
||||
arraydef :
|
||||
parse_arraydef(list,tarraydef(def));
|
||||
parse_arraydef(hr,tarraydef(def));
|
||||
procvardef:
|
||||
parse_procvardef(list,tprocvardef(def));
|
||||
parse_procvardef(hr.list,tprocvardef(def));
|
||||
recorddef:
|
||||
parse_recorddef(list,trecorddef(def));
|
||||
parse_recorddef(hr,trecorddef(def));
|
||||
objectdef:
|
||||
parse_objectdef(list,tobjectdef(def));
|
||||
parse_objectdef(hr,tobjectdef(def));
|
||||
errordef:
|
||||
begin
|
||||
{ try to consume something useful }
|
||||
@ -1380,7 +1368,7 @@ implementation
|
||||
var
|
||||
storefilepos : tfileposinfo;
|
||||
cursectype : TAsmSectionType;
|
||||
valuelist : tasmlist;
|
||||
hrec : threc;
|
||||
begin
|
||||
{ mark the staticvarsym as typedconst }
|
||||
include(sym.varoptions,vo_is_typed_const);
|
||||
@ -1397,8 +1385,10 @@ implementation
|
||||
else
|
||||
cursectype:=sec_data;
|
||||
maybe_new_object_file(list);
|
||||
valuelist:=tasmlist.create;
|
||||
read_typed_const_data(valuelist,sym.vardef);
|
||||
hrec.list:=tasmlist.create;
|
||||
hrec.origsym:=sym;
|
||||
hrec.offset:=0;
|
||||
read_typed_const_data(hrec,sym.vardef);
|
||||
|
||||
{ Parse hints }
|
||||
try_consume_hintdirective(sym.symoptions,sym.deprecatedmsg);
|
||||
@ -1435,8 +1425,8 @@ implementation
|
||||
list.concat(Tai_symbol.Createname(sym.mangledname,AT_DATA,0));
|
||||
|
||||
{ add the parsed value }
|
||||
list.concatlist(valuelist);
|
||||
valuelist.free;
|
||||
list.concatlist(hrec.list);
|
||||
hrec.list.free;
|
||||
list.concat(tai_symbol_end.Createname(sym.mangledname));
|
||||
current_filepos:=storefilepos;
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user