Sfoglia il codice sorgente

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 -

florian 15 anni fa
parent
commit
b5e7b3e1e7
8 ha cambiato i file con 327 aggiunte e 191 eliminazioni
  1. 1 0
      .gitattributes
  2. 22 0
      compiler/aasmdata.pas
  3. 118 0
      compiler/asmutils.pas
  4. 7 29
      compiler/cresstr.pas
  5. 15 56
      compiler/ncgcon.pas
  6. 67 0
      compiler/pmodules.pas
  7. 2 1
      compiler/ppu.pas
  8. 95 105
      compiler/ptconst.pas

+ 1 - 0
.gitattributes

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

+ 22 - 0
compiler/aasmdata.pas

@@ -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 - 0
compiler/asmutils.pas

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

+ 7 - 29
compiler/cresstr.pas

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

+ 15 - 56
compiler/ncgcon.pas

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

+ 67 - 0
compiler/pmodules.pas

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

+ 2 - 1
compiler/ppu.pas

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

+ 95 - 105
compiler/ptconst.pas

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