Browse Source

* migrated the handling of ansi/unicodestring constants to the high level
typed constant builder + llvm implementation

git-svn-id: branches/hlcgllvm@28327 -

Jonas Maebe 11 years ago
parent
commit
9e074d036b

+ 0 - 1
.gitattributes

@@ -106,7 +106,6 @@ compiler/arm/rarmstd.inc svneol=native#text/plain
 compiler/arm/rarmsup.inc svneol=native#text/plain
 compiler/arm/rarmsup.inc svneol=native#text/plain
 compiler/arm/rgcpu.pas svneol=native#text/plain
 compiler/arm/rgcpu.pas svneol=native#text/plain
 compiler/arm/symcpu.pas svneol=native#text/plain
 compiler/arm/symcpu.pas svneol=native#text/plain
-compiler/asmutils.pas svneol=native#text/plain
 compiler/assemble.pas svneol=native#text/plain
 compiler/assemble.pas svneol=native#text/plain
 compiler/avr/aasmcpu.pas svneol=native#text/plain
 compiler/avr/aasmcpu.pas svneol=native#text/plain
 compiler/avr/agavrgas.pas svneol=native#text/plain
 compiler/avr/agavrgas.pas svneol=native#text/plain

+ 161 - 0
compiler/aasmcnst.pas

@@ -95,6 +95,11 @@ type
    end;
    end;
 
 
 
 
+    tasmlabofs = record
+      lab: tasmlabel;
+      ofs: asizeint;
+    end;
+
    { Warning: never directly create a ttai_typedconstbuilder instance,
    { Warning: never directly create a ttai_typedconstbuilder instance,
      instead create a cai_typedconstbuilder (this class can be overridden) }
      instead create a cai_typedconstbuilder (this class can be overridden) }
    ttai_lowleveltypedconstbuilder = class abstract
    ttai_lowleveltypedconstbuilder = class abstract
@@ -124,6 +129,17 @@ type
        want to use it explicitly as a procdef (i.e., not as a record with a
        want to use it explicitly as a procdef (i.e., not as a record with a
        code and data pointer in case of a complex procvardef) }
        code and data pointer in case of a complex procvardef) }
      procedure emit_tai_procvar2procdef(p: tai; pvdef: tprocvardef); virtual;
      procedure emit_tai_procvar2procdef(p: tai; pvdef: tprocvardef); virtual;
+
+    protected
+     function emit_string_const_common(list: TAsmList; stringtype: tstringtype; len: asizeint; encoding: tstringencoding; out startlab: tasmlabel):tasmlabofs;
+    public
+     class function get_dynstring_rec_name(typ: tstringtype; winlike: boolean; len: asizeint): string;
+     { class functions and an extra list parameter, because emitting the data
+       for the strings has to happen via a separate typed const builder (which
+       will be created/destroyed internally by these methods) }
+     class function emit_ansistring_const(list: TAsmList; data: pchar; len: asizeint; encoding: tstringencoding; newsection: boolean): tasmlabofs;
+     class function emit_unicodestring_const(list: TAsmList; data: pointer; encoding: tstringencoding; winlike: boolean):tasmlabofs;
+
      { begin a potential aggregate type. Must be called for any type
      { begin a potential aggregate type. Must be called for any type
        that consists of multiple tai constant data entries, or that
        that consists of multiple tai constant data entries, or that
        represents an aggregate at the Pascal level (a record, a non-dynamic
        represents an aggregate at the Pascal level (a record, a non-dynamic
@@ -515,6 +531,151 @@ implementation
      end;
      end;
 
 
 
 
+   function ttai_lowleveltypedconstbuilder.emit_string_const_common(list: TAsmList; stringtype: tstringtype; len: asizeint; encoding: tstringencoding; out startlab: tasmlabel): tasmlabofs;
+     var
+       string_symofs: asizeint;
+       elesize: word;
+     begin
+       current_asmdata.getdatalabel(result.lab);
+       startlab:=result.lab;
+       result.ofs:=0;
+       begin_anonymous_record;
+       string_symofs:=get_string_symofs(stringtype,false);
+       { encoding }
+       emit_tai(tai_const.create_16bit(encoding),u16inttype);
+       inc(result.ofs,2);
+       { element size }
+       case stringtype of
+         st_ansistring:
+           elesize:=1;
+         st_unicodestring:
+           elesize:=2;
+         else
+           internalerror(2014080401);
+       end;
+       emit_tai(tai_const.create_16bit(elesize),u16inttype);
+       inc(result.ofs,2);
+{$ifdef cpu64bitaddr}
+       { dummy for alignment }
+       emit_tai(tai_const.create_32bit(0),u32inttype);
+       inc(result.ofs,4);
+{$endif cpu64bitaddr}
+       emit_tai(tai_const.create_pint(-1),ptrsinttype);
+       inc(result.ofs,sizeof(pint));
+       emit_tai(tai_const.create_pint(len),ptrsinttype);
+       inc(result.ofs,sizeof(pint));
+       if string_symofs=0 then
+         begin
+           { results in slightly more efficient code }
+           list.concat(tai_label.create(result.lab));
+           result.ofs:=0;
+           current_asmdata.getdatalabel(startlab);
+         end;
+       { sanity check }
+       if result.ofs<>string_symofs then
+         internalerror(2012051701);
+     end;
+
+
+   class function ttai_lowleveltypedconstbuilder.get_dynstring_rec_name(typ: tstringtype; winlike: boolean; len: asizeint): string;
+     begin
+       case typ of
+         st_ansistring:
+           result:='ansistrrec';
+         st_unicodestring,
+         st_widestring:
+           if (typ=st_unicodestring) or
+              not winlike then
+             result:='unicodestrrec'
+           else
+             result:='widestrrec';
+         else
+           internalerror(2014080402);
+       end;
+       result:=result+tostr(len);
+     end;
+
+
+   class function ttai_lowleveltypedconstbuilder.emit_ansistring_const(list: TAsmList; data: pchar; len: asizeint; encoding: tstringencoding; newsection: boolean): tasmlabofs;
+     var
+       s: PChar;
+       startlab: tasmlabel;
+       sectype: TAsmSectiontype;
+       ansistrrecdef: trecorddef;
+       datadef: tdef;
+       datatcb: ttai_lowleveltypedconstbuilder;
+     begin
+       datatcb:=self.create;
+       result:=datatcb.emit_string_const_common(list,st_ansistring,len,encoding,startlab);
+
+       getmem(s,len+1);
+       move(data^,s^,len);
+       s[len]:=#0;
+       { terminating zero included }
+       datadef:=getarraydef(cansichartype,len+1);
+       datatcb.maybe_begin_aggregate(datadef);
+       datatcb.emit_tai(tai_string.create_pchar(s,len+1),datadef);
+       datatcb.maybe_end_aggregate(datadef);
+       ansistrrecdef:=datatcb.end_anonymous_record('$'+get_dynstring_rec_name(st_ansistring,false,len),sizeof(pint));
+       if NewSection then
+         sectype:=sec_rodata_norel
+       else
+         sectype:=sec_none;
+       list.concatlist(datatcb.get_final_asmlist(startlab,ansistrrecdef,sectype,startlab.name,const_align(sizeof(pint)),true));
+       datatcb.free;
+     end;
+
+
+   class function ttai_lowleveltypedconstbuilder.emit_unicodestring_const(list: TAsmList; data: pointer; encoding: tstringencoding; winlike: boolean):tasmlabofs;
+     var
+       i, strlength: longint;
+       string_symofs: asizeint;
+       startlab: tasmlabel;
+       datadef: tdef;
+       uniwidestrrecdef: trecorddef;
+       datatcb: ttai_lowleveltypedconstbuilder;
+     begin
+       datatcb:=self.create;
+       strlength:=getlengthwidestring(pcompilerwidestring(data));
+       if winlike then
+         begin
+           current_asmdata.getdatalabel(result.lab);
+           datatcb.emit_tai(Tai_const.Create_32bit(strlength*cwidechartype.size),s32inttype);
+           { can we optimise by placing the string constant label at the
+             required offset? }
+           string_symofs:=get_string_symofs(st_widestring,true);
+           if string_symofs=0 then
+             begin
+               { yes }
+               datatcb.emit_tai(Tai_label.Create(result.lab),widecharpointertype);
+               { allocate a separate label for the start of the data }
+               current_asmdata.getdatalabel(startlab);
+             end;
+           result.ofs:=string_symofs;
+         end
+       else
+         begin
+           result:=datatcb.emit_string_const_common(list,st_unicodestring,strlength,encoding,startlab);
+         end;
+       if cwidechartype.size = 2 then
+         begin
+           datadef:=getarraydef(cwidechartype,strlength+1);
+           datatcb.maybe_begin_aggregate(datadef);
+           for i:=0 to strlength-1 do
+             datatcb.emit_tai(Tai_const.Create_16bit(pcompilerwidestring(data)^.data[i]),cwidechartype);
+           { ending #0 }
+           datatcb.emit_tai(Tai_const.Create_16bit(0),cwidechartype);
+           datatcb.maybe_end_aggregate(datadef);
+           uniwidestrrecdef:=datatcb.end_anonymous_record('$'+get_dynstring_rec_name(st_widestring,winlike,strlength),sizeof(pint));
+         end
+       else
+         { code generation for other sizes must be written }
+         internalerror(200904271);
+       list.concatlist(datatcb.get_final_asmlist(startlab,uniwidestrrecdef,sec_rodata_norel,startlab.name,const_align(sizeof(pint)),true));
+       datatcb.free;
+     end;
+
+
    procedure ttai_lowleveltypedconstbuilder.maybe_begin_aggregate(def: tdef);
    procedure ttai_lowleveltypedconstbuilder.maybe_begin_aggregate(def: tdef);
      begin
      begin
        { do nothing }
        { do nothing }

+ 0 - 157
compiler/asmutils.pas

@@ -1,157 +0,0 @@
-{
-    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
-  globtype,
-  aasmbase,
-  aasmdata,
-  symconst;
-
-    type
-      tasmlabofs = record
-        lab: tasmlabel;
-        ofs: pint;
-      end;
-
-    function emit_ansistring_const(list:TAsmList;data:PChar;len:LongInt;encoding:tstringencoding;NewSection:Boolean=True):tasmlabofs;
-    function emit_unicodestring_const(list:TAsmList;data:Pointer;encoding:tstringencoding;Winlike:Boolean):tasmlabofs;
-
-
-implementation
-
-uses
-  globals,
-  systems,
-  verbose,
-  aasmtai,aasmcnst,
-  widestr,
-  symdef;
-
-    function emit_ansistring_const(list:TAsmList;data:PChar;len:LongInt;encoding:tstringencoding;NewSection:Boolean): tasmlabofs;
-      var
-        s: PChar;
-      begin
-        current_asmdata.getdatalabel(result.lab);
-        result.ofs:=0;
-        if NewSection then
-          begin
-            maybe_new_object_file(list);
-            new_section(list,sec_rodata_norel,result.lab.name,const_align(sizeof(pint)));
-          end;
-        { put label before header on Darwin, because there the linker considers
-          a global symbol to be the start of a new subsection }
-        if target_info.system in systems_darwin then
-          list.concat(tai_label.create(result.lab));
-        list.concat(tai_const.create_16bit(encoding));
-        inc(result.ofs,2);
-        list.concat(tai_const.create_16bit(1));
-        inc(result.ofs,2);
-{$ifdef cpu64bitaddr}
-        { dummy for alignment }
-        list.concat(tai_const.create_32bit(0));
-        inc(result.ofs,4);
-{$endif cpu64bitaddr}
-        list.concat(tai_const.create_pint(-1));
-        inc(result.ofs,sizeof(pint));
-        list.concat(tai_const.create_pint(len));
-        inc(result.ofs,sizeof(pint));
-        if not(target_info.system in systems_darwin) then
-          begin
-            { results in slightly more efficient code }
-            list.concat(tai_label.create(result.lab));
-            result.ofs:=0;
-          end;
-        { sanity check }
-        if result.ofs<>ctai_typedconstbuilder.get_string_symofs(st_ansistring,false) then
-          internalerror(2012051701);
-
-        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;encoding:tstringencoding;Winlike:Boolean):tasmlabofs;
-      var
-        i, strlength: SizeInt;
-      begin
-        current_asmdata.getdatalabel(result.lab);
-        result.ofs:=0;
-        maybe_new_object_file(list);
-        new_section(list,sec_rodata_norel,result.lab.name,const_align(sizeof(pint)));
-        strlength := getlengthwidestring(pcompilerwidestring(data));
-        if Winlike then
-          begin
-            list.concat(Tai_const.Create_32bit(strlength*cwidechartype.size));
-            { don't increase result.ofs, this is how Windows widestrings are
-              defined by the OS: a pointer 4 bytes past the length of the
-              string }
-            list.concat(Tai_label.Create(result.lab));
-          end
-        else
-          begin
-            { put label before header on Darwin, because there the linker considers
-              a global symbol to be the start of a new subsection }
-            if target_info.system in systems_darwin then
-              list.concat(Tai_label.Create(result.lab));
-            list.concat(tai_const.create_16bit(encoding));
-            inc(result.ofs,2);
-            list.concat(tai_const.create_16bit(2));
-            inc(result.ofs,2);
-    {$ifdef cpu64bitaddr}
-            { dummy for alignment }
-            list.concat(Tai_const.Create_32bit(0));
-            inc(result.ofs,4);
-    {$endif cpu64bitaddr}
-            list.concat(Tai_const.Create_pint(-1));
-            inc(result.ofs,sizeof(pint));
-            list.concat(Tai_const.Create_pint(strlength));
-            inc(result.ofs,sizeof(pint));
-            if not(target_info.system in systems_darwin) then
-              begin
-                { results in slightly more efficient code }
-                list.concat(tai_label.create(result.lab));
-                result.ofs:=0;
-              end;
-            { sanity check }
-            if result.ofs<>ctai_typedconstbuilder.get_string_symofs(st_unicodestring,false) then
-              internalerror(2012051702);
-          end;
-        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.

+ 8 - 9
compiler/cresstr.pas

@@ -32,16 +32,15 @@ implementation
 
 
 uses
 uses
    SysUtils,
    SysUtils,
+{$if FPC_FULLVERSION<20700}
+   ccharset,
+{$endif}
    cclasses,widestr,
    cclasses,widestr,
    cutils,globtype,globals,systems,
    cutils,globtype,globals,systems,
    symconst,symtype,symdef,symsym,
    symconst,symtype,symdef,symsym,
    verbose,fmodule,ppu,
    verbose,fmodule,ppu,
-   aasmbase,aasmtai,aasmdata,
-   aasmcpu,
-{$if FPC_FULLVERSION<20700}
-   ccharset,
-{$endif}
-   asmutils;
+   aasmbase,aasmtai,aasmdata,aasmcnst,
+   aasmcpu;
 
 
     Type
     Type
       { These are used to form a singly-linked list, ordered by hash value }
       { These are used to form a singly-linked list, ordered by hash value }
@@ -150,7 +149,7 @@ uses
           make_mangledname('RESSTR',current_module.localsymtable,'START'),AT_DATA,0));
           make_mangledname('RESSTR',current_module.localsymtable,'START'),AT_DATA,0));
 
 
         { Write unitname entry }
         { Write unitname entry }
-        namelab:=emit_ansistring_const(current_asmdata.asmlists[al_const],@current_module.localsymtable.name^[1],length(current_module.localsymtable.name^),getansistringcodepage,False);
+        namelab:=ctai_typedconstbuilder.emit_ansistring_const(current_asmdata.asmlists[al_const],@current_module.localsymtable.name^[1],length(current_module.localsymtable.name^),getansistringcodepage,False);
         current_asmdata.asmlists[al_resourcestrings].concat(tai_const.Create_sym_offset(namelab.lab,namelab.ofs));
         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_nil_dataptr);
         current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_nil_dataptr);
@@ -166,7 +165,7 @@ uses
             new_section(current_asmdata.asmlists[al_const],sec_rodata_norel,make_mangledname('RESSTR',current_module.localsymtable,'d_'+r.name),sizeof(pint));
             new_section(current_asmdata.asmlists[al_const],sec_rodata_norel,make_mangledname('RESSTR',current_module.localsymtable,'d_'+r.name),sizeof(pint));
             { Write default value }
             { Write default value }
             if assigned(R.value) and (R.len<>0) then
             if assigned(R.value) and (R.len<>0) then
-              valuelab:=emit_ansistring_const(current_asmdata.asmlists[al_const],R.Value,R.Len,getansistringcodepage,False)
+              valuelab:=ctai_typedconstbuilder.emit_ansistring_const(current_asmdata.asmlists[al_const],R.Value,R.Len,getansistringcodepage,False)
             else
             else
               begin
               begin
                 valuelab.lab:=nil;
                 valuelab.lab:=nil;
@@ -174,7 +173,7 @@ uses
               end;
               end;
             { Append the name as a ansistring. }
             { Append the name as a ansistring. }
             current_asmdata.asmlists[al_const].concat(cai_align.Create(const_align(sizeof(pint))));
             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),getansistringcodepage,False);
+            namelab:=ctai_typedconstbuilder.emit_ansistring_const(current_asmdata.asmlists[al_const],@R.Name[1],length(R.name),getansistringcodepage,False);
 
 
             {
             {
               Resourcestring index:
               Resourcestring index:

+ 50 - 4
compiler/llvm/nllvmcon.pas

@@ -27,7 +27,8 @@ unit nllvmcon;
 interface
 interface
 
 
     uses
     uses
-       node,ncgcon;
+      symtype,
+      node,ncgcon;
 
 
     type
     type
        tllvmrealconstnode = class(tcgrealconstnode)
        tllvmrealconstnode = class(tcgrealconstnode)
@@ -37,14 +38,16 @@ interface
 
 
        tllvmstringconstnode = class(tcgstringconstnode)
        tllvmstringconstnode = class(tcgstringconstnode)
           procedure pass_generate_code; override;
           procedure pass_generate_code; override;
+       protected
+          procedure load_dynstring(const strpointerdef: tdef; const elementdef: tdef; const winlikewidestring: boolean); override;
        end;
        end;
 
 
 implementation
 implementation
 
 
     uses
     uses
-      globtype,verbose,cutils,
-      symtype,symdef,defutil,
-      aasmdata,
+      globtype,globals,verbose,cutils,
+      symbase,symtable,symconst,symdef,symsym,defutil,
+      aasmdata,aasmcnst,
       ncon,
       ncon,
       llvmbase,aasmllvm,hlcgobj,
       llvmbase,aasmllvm,hlcgobj,
       cgbase,cgutils;
       cgbase,cgutils;
@@ -87,6 +90,49 @@ implementation
           end;
           end;
       end;
       end;
 
 
+
+    procedure tllvmstringconstnode.load_dynstring(const strpointerdef: tdef; const elementdef: tdef; const winlikewidestring: boolean);
+      var
+        stringtype: tstringtype;
+        strrecdef: trecorddef;
+        srsym: tsym;
+        srsymtable: tsymtable;
+        offset: pint;
+        field: tfieldvarsym;
+        dataptrdef: tdef;
+        reg: tregister;
+        href: treference;
+      begin
+        case cst_type of
+          cst_ansistring:
+            stringtype:=st_ansistring;
+          cst_unicodestring:
+            stringtype:=st_unicodestring;
+          cst_widestring:
+            stringtype:=st_widestring;
+          else
+            internalerror(2014040804);
+        end;
+        { get the recorddef for this string constant }
+        if not searchsym_type(ctai_typedconstbuilder.get_dynstring_rec_name(stringtype,winlikewidestring,len),srsym,srsymtable) then
+          internalerror(2014080405);
+        strrecdef:=trecorddef(ttypesym(srsym).typedef);
+        { offset in the record of the the string data }
+        offset:=ctai_typedconstbuilder.get_string_symofs(stringtype,winlikewidestring);
+        { field corresponding to this offset }
+        field:=trecordsymtable(strrecdef.symtable).findfieldbyoffset(offset);
+        { pointerdef to the string data array }
+        dataptrdef:=getpointerdef(field.vardef);
+        { load the address of the string data }
+        reg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,dataptrdef);
+        reference_reset_symbol(href, lab_str, 0, const_align(strpointerdef.size));
+        current_asmdata.CurrAsmList.concat(
+          taillvm.getelementptr_reg_size_ref_size_const(reg,dataptrdef,href,
+          s32inttype,field.llvmfieldnr,true));
+        { convert into a pointer to the individual elements }
+        hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,dataptrdef,strpointerdef,reg,location.register);
+      end;
+
 {*****************************************************************************
 {*****************************************************************************
                            tllvmrealconstnode
                            tllvmrealconstnode
 *****************************************************************************}
 *****************************************************************************}

+ 45 - 0
compiler/llvm/nllvmtcon.pas

@@ -73,6 +73,12 @@ interface
       class function get_string_symofs(typ: tstringtype; winlikewidestring: boolean): pint; override;
       class function get_string_symofs(typ: tstringtype; winlikewidestring: boolean): pint; override;
     end;
     end;
 
 
+
+    tllvmasmlisttypedconstbuilder = class(tasmlisttypedconstbuilder)
+     protected
+      procedure tc_emit_string_offset(const ll: tasmlabofs; const strlength: longint; const st: tstringtype; const winlikewidestring: boolean; const charptrdef: tdef); override;
+    end;
+
 implementation
 implementation
 
 
   uses
   uses
@@ -435,7 +441,46 @@ implementation
     end;
     end;
 
 
 
 
+  { tllvmasmlisttypedconstbuilder }
+
+  procedure tllvmasmlisttypedconstbuilder.tc_emit_string_offset(const ll: tasmlabofs; const strlength: longint; const st: tstringtype; const winlikewidestring: boolean; const charptrdef: tdef);
+    var
+      srsym     : tsym;
+      srsymtable: tsymtable;
+      strrecdef : trecorddef;
+      offset: pint;
+      field: tfieldvarsym;
+      dataptrdef: tdef;
+    begin
+      { if the returned offset is <> 0, then the string data
+        starts at that offset -> translate to a field for the
+        high level code generator }
+      if ll.ofs<>0 then
+        begin
+          { get the recorddef for this string constant }
+          if not searchsym_type(ctai_typedconstbuilder.get_dynstring_rec_name(st,winlikewidestring,strlength),srsym,srsymtable) then
+            internalerror(2014080406);
+          strrecdef:=trecorddef(ttypesym(srsym).typedef);
+          { offset in the record of the the string data }
+          offset:=ctai_typedconstbuilder.get_string_symofs(st,winlikewidestring);
+          { field corresponding to this offset }
+          field:=trecordsymtable(strrecdef.symtable).findfieldbyoffset(offset);
+          { pointerdef to the string data array }
+          dataptrdef:=getpointerdef(field.vardef);
+          ftcb.queue_init(charptrdef);
+          ftcb.queue_addrn(dataptrdef,charptrdef);
+          ftcb.queue_subscriptn(strrecdef,field);
+          ftcb.queue_emit_asmsym(ll.lab,strrecdef);
+        end
+      else
+       { since llvm doesn't support labels in the middle of structs, this
+         offset should never be 0  }
+       internalerror(2014080506);
+    end;
+
+
 begin
 begin
   ctai_typedconstbuilder:=tllvmtai_typedconstbuilder;
   ctai_typedconstbuilder:=tllvmtai_typedconstbuilder;
+  ctypedconstbuilder:=tllvmasmlisttypedconstbuilder;
 end.
 end.
 
 

+ 18 - 8
compiler/ncgcon.pas

@@ -28,6 +28,7 @@ interface
 
 
     uses
     uses
        aasmbase,
        aasmbase,
+       symtype,
        node,ncon;
        node,ncon;
 
 
     type
     type
@@ -49,6 +50,8 @@ interface
 
 
        tcgstringconstnode = class(tstringconstnode)
        tcgstringconstnode = class(tstringconstnode)
           procedure pass_generate_code;override;
           procedure pass_generate_code;override;
+       protected
+         procedure load_dynstring(const strpointerdef: tdef; const elementdef: tdef; const winlikewidestring: boolean); virtual;
        end;
        end;
 
 
        tcgsetconstnode = class(tsetconstnode)
        tcgsetconstnode = class(tsetconstnode)
@@ -77,7 +80,7 @@ implementation
       symconst,symdef,aasmtai,aasmdata,aasmcpu,defutil,
       symconst,symdef,aasmtai,aasmdata,aasmcpu,defutil,
       cpuinfo,cpubase,
       cpuinfo,cpubase,
       cgbase,cgobj,cgutils,
       cgbase,cgobj,cgutils,
-      ncgutil,hlcgobj,symtype,cclasses,asmutils,tgobj
+      ncgutil,hlcgobj,cclasses,tgobj
       ;
       ;
 
 
 
 
@@ -261,7 +264,6 @@ implementation
          lastlabel: tasmlabofs;
          lastlabel: tasmlabofs;
          pc: pchar;
          pc: pchar;
          l: longint;
          l: longint;
-         href: treference;
          pool: THashSet;
          pool: THashSet;
          entry: PHashSetItem;
          entry: PHashSetItem;
          winlikewidestring: boolean;
          winlikewidestring: boolean;
@@ -330,7 +332,7 @@ implementation
                              InternalError(2008032301)   { empty string should be handled above }
                              InternalError(2008032301)   { empty string should be handled above }
                            else
                            else
                              begin
                              begin
-                               lastlabel:=emit_ansistring_const(current_asmdata.AsmLists[al_typedconsts],value_str,len,tstringdef(resultdef).encoding);
+                               lastlabel:=ctai_typedconstbuilder.emit_ansistring_const(current_asmdata.AsmLists[al_typedconsts],value_str,len,tstringdef(resultdef).encoding,true);
                                { because we hardcode the offset below due to it
                                { because we hardcode the offset below due to it
                                  not being stored in the hashset, check here }
                                  not being stored in the hashset, check here }
                                if lastlabel.ofs<>ctai_typedconstbuilder.get_string_symofs(st_ansistring,false) then
                                if lastlabel.ofs<>ctai_typedconstbuilder.get_string_symofs(st_ansistring,false) then
@@ -344,7 +346,7 @@ implementation
                              InternalError(2008032302)   { empty string should be handled above }
                              InternalError(2008032302)   { empty string should be handled above }
                            else
                            else
                              begin
                              begin
-                               lastlabel := emit_unicodestring_const(current_asmdata.AsmLists[al_typedconsts],
+                               lastlabel:=ctai_typedconstbuilder.emit_unicodestring_const(current_asmdata.AsmLists[al_typedconsts],
                                                value_str,
                                                value_str,
                                                tstringdef(resultdef).encoding,
                                                tstringdef(resultdef).encoding,
                                                winlikewidestring);
                                                winlikewidestring);
@@ -410,11 +412,8 @@ implementation
          if cst_type in [cst_ansistring, cst_widestring, cst_unicodestring] then
          if cst_type in [cst_ansistring, cst_widestring, cst_unicodestring] then
            begin
            begin
              location_reset(location, LOC_REGISTER, def_cgsize(strpointerdef));
              location_reset(location, LOC_REGISTER, def_cgsize(strpointerdef));
-             reference_reset_symbol(href, lab_str,
-               ctai_typedconstbuilder.get_string_symofs(tstringdef(resultdef).stringtype,winlikewidestring),
-               const_align(strpointerdef.size));
              location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,strpointerdef);
              location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,strpointerdef);
-             hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,elementdef,strpointerdef,href,location.register)
+             load_dynstring(strpointerdef, elementdef, winlikewidestring);
            end
            end
          else
          else
            begin
            begin
@@ -424,6 +423,17 @@ implementation
       end;
       end;
 
 
 
 
+    procedure tcgstringconstnode.load_dynstring(const strpointerdef: tdef; const elementdef: tdef; const winlikewidestring: boolean);
+      var
+        href: treference;
+      begin
+        reference_reset_symbol(href, lab_str,
+          ctai_typedconstbuilder.get_string_symofs(tstringdef(resultdef).stringtype, winlikewidestring),
+          const_align(strpointerdef.size));
+        hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList, elementdef, strpointerdef, href, location.register)
+      end;
+
+
 {*****************************************************************************
 {*****************************************************************************
                            TCGSETCONSTNODE
                            TCGSETCONSTNODE
 *****************************************************************************}
 *****************************************************************************}

+ 15 - 7
compiler/ngtcon.pas

@@ -29,7 +29,7 @@ interface
       globtype,cclasses,constexp,
       globtype,cclasses,constexp,
       aasmbase,aasmdata,aasmtai,aasmcnst,
       aasmbase,aasmdata,aasmtai,aasmcnst,
       node,nbas,
       node,nbas,
-      symtype, symbase, symdef,symsym;
+      symconst, symtype, symbase, symdef,symsym;
 
 
 
 
     type
     type
@@ -99,6 +99,8 @@ interface
         procedure tc_emit_setdef(def: tsetdef; var node: tnode);override;
         procedure tc_emit_setdef(def: tsetdef; var node: tnode);override;
         procedure tc_emit_enumdef(def: tenumdef; var node: tnode);override;
         procedure tc_emit_enumdef(def: tenumdef; var node: tnode);override;
         procedure tc_emit_stringdef(def: tstringdef; var node: tnode);override;
         procedure tc_emit_stringdef(def: tstringdef; var node: tnode);override;
+
+        procedure tc_emit_string_offset(const ll: tasmlabofs; const strlength: longint; const st: tstringtype; const winlikewidestring: boolean; const charptrdef: tdef);virtual;
        public
        public
         constructor create(sym: tstaticvarsym);virtual;
         constructor create(sym: tstaticvarsym);virtual;
         procedure parse_into_asmlist;
         procedure parse_into_asmlist;
@@ -143,7 +145,7 @@ uses
    SysUtils,
    SysUtils,
    systems,tokens,verbose,
    systems,tokens,verbose,
    cutils,globals,widestr,scanner,
    cutils,globals,widestr,scanner,
-   symconst,symtable,
+   symtable,
    aasmcpu,defutil,defcmp,
    aasmcpu,defutil,defcmp,
    { pass 1 }
    { pass 1 }
    htypechk,procinfo,
    htypechk,procinfo,
@@ -152,7 +154,7 @@ uses
    pbase,pexpr,pdecvar,
    pbase,pexpr,pdecvar,
    { codegen }
    { codegen }
    cpuinfo,cgbase,dbgbase,
    cpuinfo,cgbase,dbgbase,
-   wpobase,asmutils
+   wpobase
    ;
    ;
 
 
 {$maxfpuregisters 0}
 {$maxfpuregisters 0}
@@ -444,6 +446,12 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
       end;
       end;
 
 
 
 
+    procedure tasmlisttypedconstbuilder.tc_emit_string_offset(const ll: tasmlabofs; const strlength: longint; const st: tstringtype; const winlikewidestring: boolean; const charptrdef: tdef);
+      begin
+        ftcb.emit_tai(Tai_const.Create_sym_offset(ll.lab,ll.ofs),charptrdef);
+      end;
+
+
     procedure tasmlisttypedconstbuilder.tc_emit_stringdef(def: tstringdef; var node: tnode);
     procedure tasmlisttypedconstbuilder.tc_emit_stringdef(def: tstringdef; var node: tnode);
       var
       var
         strlength : aint;
         strlength : aint;
@@ -551,8 +559,8 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
                        ll.ofs:=0;
                        ll.ofs:=0;
                      end
                      end
                    else
                    else
-                     ll:=emit_ansistring_const(current_asmdata.asmlists[al_const],strval,strlength,def.encoding);
-                   ftcb.emit_tai(Tai_const.Create_sym_offset(ll.lab,ll.ofs),getpointerdef(cansichartype));
+                     ll:=ctai_typedconstbuilder.emit_ansistring_const(current_asmdata.asmlists[al_const],strval,strlength,def.encoding,true);
+                   tc_emit_string_offset(ll,strlength,def.stringtype,false,charpointertype);
                 end;
                 end;
               st_unicodestring,
               st_unicodestring,
               st_widestring:
               st_widestring:
@@ -566,7 +574,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
                    else
                    else
                      begin
                      begin
                        winlike:=(def.stringtype=st_widestring) and (tf_winlikewidestring in target_info.flags);
                        winlike:=(def.stringtype=st_widestring) and (tf_winlikewidestring in target_info.flags);
-                       ll:=emit_unicodestring_const(current_asmdata.asmlists[al_const],
+                       ll:=ctai_typedconstbuilder.emit_unicodestring_const(current_asmdata.asmlists[al_const],
                               strval,
                               strval,
                               def.encoding,
                               def.encoding,
                               winlike);
                               winlike);
@@ -588,7 +596,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
                            Include(tcsym.varoptions,vo_force_finalize);
                            Include(tcsym.varoptions,vo_force_finalize);
                          end;
                          end;
                      end;
                      end;
-                   ftcb.emit_tai(Tai_const.Create_sym_offset(ll.lab,ll.ofs),getpointerdef(cwidechartype));
+                  tc_emit_string_offset(ll,strlength,def.stringtype,winlike,widecharpointertype);
                 end;
                 end;
               else
               else
                 internalerror(200107081);
                 internalerror(200107081);