Parcourir la source

* synchronised with trunk till r41159

git-svn-id: branches/debug_eh@41160 -
Jonas Maebe il y a 6 ans
Parent
commit
a0d796e98d
100 fichiers modifiés avec 5762 ajouts et 2659 suppressions
  1. 1 1
      .gitattributes
  2. 2 0
      compiler/arm/agarmgas.pas
  3. 9 0
      compiler/arm/aoptcpub.pas
  4. 1 0
      compiler/arm/armins.dat
  5. 1 1
      compiler/arm/armnop.inc
  6. 7 0
      compiler/arm/armtab.inc
  7. 27 8
      compiler/arm/cgcpu.pas
  8. 5 0
      compiler/arm/cpupara.pas
  9. 1 1
      compiler/arm/narmld.pas
  10. 1 0
      compiler/arm/raarmgas.pas
  11. 3 0
      compiler/cfileutl.pas
  12. 4 0
      compiler/cgbase.pas
  13. 5 5
      compiler/cgutils.pas
  14. 1 7
      compiler/fpcdefs.inc
  15. 614 5
      compiler/hlcg2ll.pas
  16. 2 2
      compiler/hlcgobj.pas
  17. 4 172
      compiler/i386/aoptcpu.pas
  18. 11 13
      compiler/i386/cpupara.pas
  19. 7 0
      compiler/i386/i386att.inc
  20. 7 0
      compiler/i386/i386atts.inc
  21. 7 0
      compiler/i386/i386int.inc
  22. 1 1
      compiler/i386/i386nop.inc
  23. 7 0
      compiler/i386/i386op.inc
  24. 7 0
      compiler/i386/i386prop.inc
  25. 56 0
      compiler/i386/i386tab.inc
  26. 7 0
      compiler/i8086/i8086att.inc
  27. 7 0
      compiler/i8086/i8086atts.inc
  28. 7 0
      compiler/i8086/i8086int.inc
  29. 1 1
      compiler/i8086/i8086nop.inc
  30. 7 0
      compiler/i8086/i8086op.inc
  31. 7 0
      compiler/i8086/i8086prop.inc
  32. 56 0
      compiler/i8086/i8086tab.inc
  33. 7 1
      compiler/llvm/hlcgllvm.pas
  34. 4 2
      compiler/nadd.pas
  35. 5 5
      compiler/ncgadd.pas
  36. 3 3
      compiler/ncgbas.pas
  37. 1 1
      compiler/ncgcal.pas
  38. 2 2
      compiler/ncgcnv.pas
  39. 3 3
      compiler/ncgcon.pas
  40. 32 32
      compiler/ncginl.pas
  41. 22 27
      compiler/ncgld.pas
  42. 24 24
      compiler/ncgmat.pas
  43. 12 6
      compiler/ncgset.pas
  44. 25 646
      compiler/ncgutil.pas
  45. 6 6
      compiler/ninl.pas
  46. 14 14
      compiler/nmat.pas
  47. 5 3
      compiler/options.pas
  48. 1 1
      compiler/parabase.pas
  49. 2 2
      compiler/symdef.pas
  50. 3 0
      compiler/systems/i_linux.pas
  51. 7 1
      compiler/systems/t_morph.pas
  52. 5 1
      compiler/utils/fpc.pp
  53. 4 0
      compiler/x86/aasmcpu.pas
  54. 10 1
      compiler/x86/agx86att.pas
  55. 170 2
      compiler/x86/aoptx86.pas
  56. 50 0
      compiler/x86/cgx86.pas
  57. 39 0
      compiler/x86/nx86ld.pas
  58. 43 0
      compiler/x86/x86ins.dat
  59. 4 0
      compiler/x86_64/aoptcpu.pas
  60. 1 0
      compiler/x86_64/cpunode.pas
  61. 7 0
      compiler/x86_64/x8664ats.inc
  62. 7 0
      compiler/x86_64/x8664att.inc
  63. 7 0
      compiler/x86_64/x8664int.inc
  64. 1 1
      compiler/x86_64/x8664nop.inc
  65. 7 0
      compiler/x86_64/x8664op.inc
  66. 7 0
      compiler/x86_64/x8664pro.inc
  67. 91 0
      compiler/x86_64/x8664tab.inc
  68. 21 9
      packages/fcl-base/src/uriparser.pp
  69. 13 3
      packages/fcl-image/src/fpreadgif.pas
  70. 54 13
      packages/fcl-js/src/jswriter.pp
  71. 104 30
      packages/fcl-passrc/src/pasresolveeval.pas
  72. 400 163
      packages/fcl-passrc/src/pasresolver.pp
  73. 33 19
      packages/fcl-passrc/src/pastree.pp
  74. 1 1
      packages/fcl-passrc/src/pasuseanalyzer.pas
  75. 68 75
      packages/fcl-passrc/src/pparser.pp
  76. 34 13
      packages/fcl-passrc/src/pscanner.pp
  77. 40 0
      packages/fcl-passrc/tests/tcexprparser.pas
  78. 45 21
      packages/fcl-passrc/tests/tcgenerics.pp
  79. 4 2
      packages/fcl-passrc/tests/tcprocfunc.pas
  80. 1392 74
      packages/fcl-passrc/tests/tcresolver.pas
  81. 3 1
      packages/fcl-passrc/tests/tcstatements.pas
  82. 242 296
      packages/graph/src/go32v2/graph.pp
  83. 33 35
      packages/graph/src/inc/fills.inc
  84. 5 5
      packages/graph/src/inc/graph.inc
  85. 371 375
      packages/graph/src/msdos/graph.pp
  86. 1 1
      packages/graph/src/ptcgraph/ptcgraph.pp
  87. 1 1
      packages/ide/fpviews.pas
  88. 2 3
      packages/ide/weditor.pas
  89. 402 284
      packages/pastojs/src/fppas2js.pp
  90. 42 22
      packages/pastojs/src/pas2jscompiler.pp
  91. 12 6
      packages/pastojs/src/pas2jsfilecache.pp
  92. 33 17
      packages/pastojs/src/pas2jsfiler.pp
  93. 197 87
      packages/pastojs/src/pas2jsfileutils.pp
  94. 10 0
      packages/pastojs/src/pas2jsfileutilsnodejs.inc
  95. 10 0
      packages/pastojs/src/pas2jsfileutilsunix.inc
  96. 50 0
      packages/pastojs/src/pas2jsfileutilswin.inc
  97. 1 1
      packages/pastojs/src/pas2jsfs.pp
  98. 14 1
      packages/pastojs/tests/tcfiler.pas
  99. 548 100
      packages/pastojs/tests/tcmodules.pas
  100. 62 0
      packages/pastojs/tests/tcunitsearch.pas

+ 1 - 1
.gitattributes

@@ -8786,6 +8786,7 @@ rtl/amicommon/README.TXT svneol=native#text/plain
 rtl/amicommon/athreads.pp svneol=native#text/plain
 rtl/amicommon/athreads.pp svneol=native#text/plain
 rtl/amicommon/classes.pp svneol=native#text/plain
 rtl/amicommon/classes.pp svneol=native#text/plain
 rtl/amicommon/dos.pp svneol=native#text/plain
 rtl/amicommon/dos.pp svneol=native#text/plain
+rtl/amicommon/lineinfo.pp svneol=native#text/plain
 rtl/amicommon/osdebug.inc svneol=native#text/plain
 rtl/amicommon/osdebug.inc svneol=native#text/plain
 rtl/amicommon/osdebugh.inc svneol=native#text/plain
 rtl/amicommon/osdebugh.inc svneol=native#text/plain
 rtl/amicommon/paramhandling.inc svneol=native#text/plain
 rtl/amicommon/paramhandling.inc svneol=native#text/plain
@@ -9876,7 +9877,6 @@ rtl/morphos/doslibf.inc svneol=native#text/plain
 rtl/morphos/emuld.inc svneol=native#text/plain
 rtl/morphos/emuld.inc svneol=native#text/plain
 rtl/morphos/execd.inc svneol=native#text/plain
 rtl/morphos/execd.inc svneol=native#text/plain
 rtl/morphos/execf.inc svneol=native#text/plain
 rtl/morphos/execf.inc svneol=native#text/plain
-rtl/morphos/lineinfo.pp svneol=native#text/plain
 rtl/morphos/prt0.as svneol=native#text/plain
 rtl/morphos/prt0.as svneol=native#text/plain
 rtl/morphos/si_prc.pp svneol=native#text/plain
 rtl/morphos/si_prc.pp svneol=native#text/plain
 rtl/morphos/system.pp svneol=native#text/plain
 rtl/morphos/system.pp svneol=native#text/plain

+ 2 - 0
compiler/arm/agarmgas.pas

@@ -205,6 +205,8 @@ unit agarmgas;
                        s:=s+', rrx'
                        s:=s+', rrx'
                      else if shiftmode <> SM_None then
                      else if shiftmode <> SM_None then
                        s:=s+', '+gas_shiftmode2str[shiftmode]+' #'+tostr(shiftimm);
                        s:=s+', '+gas_shiftmode2str[shiftmode]+' #'+tostr(shiftimm);
+                     if offset<>0 then
+                       Internalerror(2019012601);
                   end
                   end
                 else if offset<>0 then
                 else if offset<>0 then
                   s:=s+', #'+tostr(offset);
                   s:=s+', #'+tostr(offset);

+ 9 - 0
compiler/arm/aoptcpub.pas

@@ -119,6 +119,15 @@ Implementation
       i : Longint;
       i : Longint;
     begin
     begin
       result:=false;
       result:=false;
+      case taicpu(p1).opcode of
+        A_LDR:
+          { special handling for LDRD }
+          if (taicpu(p1).oppostfix=PF_D) and (getsupreg(taicpu(p1).oper[0]^.reg)+1=getsupreg(Reg)) then
+            begin
+              result:=true;
+              exit;
+            end;
+      end;
       for i:=0 to taicpu(p1).ops-1 do
       for i:=0 to taicpu(p1).ops-1 do
         case taicpu(p1).oper[i]^.typ of
         case taicpu(p1).oper[i]^.typ of
           top_reg:
           top_reg:

+ 1 - 0
compiler/arm/armins.dat

@@ -402,6 +402,7 @@ reg32,regf          \x10\x01\x0F                        ARM32,ARMv4
 regf,reg32          \x96\xF3\x80\x80\x0                 THUMB32,ARMv6
 regf,reg32          \x96\xF3\x80\x80\x0                 THUMB32,ARMv6
 
 
 regf,reg32          \x12\x01\x20\xF0                    ARM32,ARMv4
 regf,reg32          \x12\x01\x20\xF0                    ARM32,ARMv4
+regs,reg32          \x12\x01\x20\xF0                    ARM32,ARMv4
 regf,immshifter     \x13\x03\x20\xF0                    ARM32,ARMv4
 regf,immshifter     \x13\x03\x20\xF0                    ARM32,ARMv4
 regs,immshifter     \x13\x03\x20\xF0                    ARM32,ARMv4
 regs,immshifter     \x13\x03\x20\xF0                    ARM32,ARMv4
 
 

+ 1 - 1
compiler/arm/armnop.inc

@@ -1,2 +1,2 @@
 { don't edit, this file is generated from armins.dat }
 { don't edit, this file is generated from armins.dat }
-958;
+959;

+ 7 - 0
compiler/arm/armtab.inc

@@ -1351,6 +1351,13 @@
     code    : #18#1#32#240;
     code    : #18#1#32#240;
     flags   : if_arm32 or if_armv4
     flags   : if_arm32 or if_armv4
   ),
   ),
+  (
+    opcode  : A_MSR;
+    ops     : 2;
+    optypes : (ot_regs,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+    code    : #18#1#32#240;
+    flags   : if_arm32 or if_armv4
+  ),
   (
   (
     opcode  : A_MSR;
     opcode  : A_MSR;
     ops     : 2;
     ops     : 2;

+ 27 - 8
compiler/arm/cgcpu.pas

@@ -2686,6 +2686,21 @@ unit cgcpu;
           list.concat(taicpu.op_reg_reg(A_MOV,destreg,destreg));
           list.concat(taicpu.op_reg_reg(A_MOV,destreg,destreg));
         end;
         end;
 
 
+      { save estimation, if a creating a separate ref is needed or
+        if we can keep the original reference while copying }
+      function SimpleRef(const ref : treference) : boolean;
+        begin
+          result:=((ref.base=NR_PC) and (ref.addressmode=AM_OFFSET) and (ref.refaddr=addr_full)) or
+              ((ref.symbol=nil) and
+               (ref.addressmode=AM_OFFSET) and
+               (((ref.offset>=0) and (ref.offset+len<=31)) or
+                (not(GenerateThumbCode) and (ref.offset>=-255) and (ref.offset+len<=255)) or
+                { ldrh has a limited offset range }
+                (not(GenerateThumbCode) and ((len mod 4) in [0,1]) and (ref.offset>=-4095) and (ref.offset+len<=4095))
+               )
+              );
+        end;
+
       { will never be called with count<=4 }
       { will never be called with count<=4 }
       procedure genloop_thumb(count : aword;size : byte);
       procedure genloop_thumb(count : aword;size : byte);
 
 
@@ -2792,17 +2807,15 @@ unit cgcpu;
           begin
           begin
             tmpregi:=0;
             tmpregi:=0;
 
 
-            srcreg:=getintregister(list,OS_ADDR);
-
-            { explicit pc relative addressing, could be
-              e.g. a floating point constant }
-            if source.base=NR_PC then
+            { loading address in a separate register needed? }
+            if SimpleRef(source) then
               begin
               begin
                 { ... then we don't need a loadaddr }
                 { ... then we don't need a loadaddr }
                 srcref:=source;
                 srcref:=source;
               end
               end
             else
             else
               begin
               begin
+                srcreg:=getintregister(list,OS_ADDR);
                 a_loadaddr_ref_reg(list,source,srcreg);
                 a_loadaddr_ref_reg(list,source,srcreg);
                 reference_reset_base(srcref,srcreg,0,source.temppos,source.alignment,source.volatility);
                 reference_reset_base(srcref,srcreg,0,source.temppos,source.alignment,source.volatility);
               end;
               end;
@@ -2816,9 +2829,15 @@ unit cgcpu;
                 dec(len,4);
                 dec(len,4);
               end;
               end;
 
 
-            destreg:=getintregister(list,OS_ADDR);
-            a_loadaddr_ref_reg(list,dest,destreg);
-            reference_reset_base(dstref,destreg,0,dest.temppos,dest.alignment,dest.volatility);
+            { loading address in a separate register needed? }
+            if SimpleRef(dest) then
+              dstref:=dest
+            else
+              begin
+                destreg:=getintregister(list,OS_ADDR);
+                a_loadaddr_ref_reg(list,dest,destreg);
+                reference_reset_base(dstref,destreg,0,dest.temppos,dest.alignment,dest.volatility);
+              end;
             tmpregi2:=1;
             tmpregi2:=1;
             while (tmpregi2<=tmpregi) do
             while (tmpregi2<=tmpregi) do
               begin
               begin

+ 5 - 0
compiler/arm/cpupara.pas

@@ -377,6 +377,11 @@ unit cpupara;
             if (p.proccalloption in cstylearrayofconst) and
             if (p.proccalloption in cstylearrayofconst) and
                is_array_of_const(paradef) then
                is_array_of_const(paradef) then
               begin
               begin
+                hp.paraloc[side].def:=paradef;
+                hp.paraloc[side].size:=OS_NO;
+                hp.paraloc[side].alignment:=std_param_align;
+                hp.paraloc[side].intsize:=0;
+
                 paraloc:=hp.paraloc[side].add_location;
                 paraloc:=hp.paraloc[side].add_location;
                 { hack: the paraloc must be valid, but is not actually used }
                 { hack: the paraloc must be valid, but is not actually used }
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.loc:=LOC_REGISTER;

+ 1 - 1
compiler/arm/narmld.pas

@@ -50,7 +50,7 @@ implementation
       procinfo;
       procinfo;
 
 
 {*****************************************************************************
 {*****************************************************************************
-                            TI386LOADNODE
+                            TARMLOADNODE
 *****************************************************************************}
 *****************************************************************************}
 
 
     procedure tarmloadnode.generate_threadvar_access(gvs: tstaticvarsym);
     procedure tarmloadnode.generate_threadvar_access(gvs: tstaticvarsym);

+ 1 - 0
compiler/arm/raarmgas.pas

@@ -147,6 +147,7 @@ Unit raarmgas;
           end;
           end;
       end;
       end;
 
 
+
     function tarmattreader.is_targetdirective(const s: string): boolean;
     function tarmattreader.is_targetdirective(const s: string): boolean;
       begin
       begin
         case s of
         case s of

+ 3 - 0
compiler/cfileutl.pas

@@ -37,6 +37,9 @@ interface
 {$if defined(go32v2) or defined(watcom)}
 {$if defined(go32v2) or defined(watcom)}
       Dos,
       Dos,
 {$endif}
 {$endif}
+{$ifdef macos}
+      macutils,
+{$endif macos}
 {$IFNDEF USE_FAKE_SYSUTILS}
 {$IFNDEF USE_FAKE_SYSUTILS}
       SysUtils,
       SysUtils,
 {$ELSE}
 {$ELSE}

+ 4 - 0
compiler/cgbase.pas

@@ -130,6 +130,10 @@ interface
          ,addr_ntpoff
          ,addr_ntpoff
          ,addr_tlsgd
          ,addr_tlsgd
          {$ENDIF}
          {$ENDIF}
+{$ifdef x86_64}
+          ,addr_tpoff
+          ,addr_tlsgd
+{$endif x86_64}
          );
          );
 
 
 
 

+ 5 - 5
compiler/cgutils.pas

@@ -135,15 +135,15 @@ unit cgutils;
 {$endif cpuflags}
 {$endif cpuflags}
             LOC_CONSTANT : (
             LOC_CONSTANT : (
               case longint of
               case longint of
-{$ifdef cpu64bitalu}
+{$if defined(cpu64bitalu) or defined(cpuhighleveltarget)}
                 1 : (value : Int64);
                 1 : (value : Int64);
-{$else cpu64bitalu}
+{$else cpu64bitalu or cpuhighleveltarget}
     {$ifdef FPC_BIG_ENDIAN}
     {$ifdef FPC_BIG_ENDIAN}
                 1 : (_valuedummy,value : longint);
                 1 : (_valuedummy,value : longint);
     {$else FPC_BIG_ENDIAN}
     {$else FPC_BIG_ENDIAN}
                 1 : (value : longint);
                 1 : (value : longint);
     {$endif FPC_BIG_ENDIAN}
     {$endif FPC_BIG_ENDIAN}
-{$endif cpu64bitalu}
+{$endif cpu64bitalu or cpuhighleveltarget}
                 2 : (value64 : Int64);
                 2 : (value64 : Int64);
               );
               );
             LOC_CREFERENCE,
             LOC_CREFERENCE,
@@ -164,10 +164,10 @@ unit cgutils;
 {$ifdef cpu64bitalu}
 {$ifdef cpu64bitalu}
                 { overlay a 128 Bit register type }
                 { overlay a 128 Bit register type }
                 2 : (register128 : tregister128);
                 2 : (register128 : tregister128);
-{$else cpu64bitalu}
+{$else if not defined(cpuhighleveltarget}
                 { overlay a 64 Bit register type }
                 { overlay a 64 Bit register type }
                 2 : (register64 : tregister64);
                 2 : (register64 : tregister64);
-{$endif cpu64bitalu}
+{$endif cpu64bitalu and not cpuhighleveltarget}
 {$ifdef cpu8bitalu}
 {$ifdef cpu8bitalu}
                 3 : (registers : array[0..3] of tregister);
                 3 : (registers : array[0..3] of tregister);
 {$endif cpu8bitalu}
 {$endif cpu8bitalu}

+ 1 - 7
compiler/fpcdefs.inc

@@ -298,10 +298,6 @@
   {$define cpurequiresproperalignment}
   {$define cpurequiresproperalignment}
 {$endif riscv64}
 {$endif riscv64}
 
 
-{$IFDEF MACOS}
-{$DEFINE USE_FAKE_SYSUTILS}
-{$ENDIF MACOS}
-
 { Stabs is not officially supported on 64 bit targets by gdb, except on Mac OS X
 { Stabs is not officially supported on 64 bit targets by gdb, except on Mac OS X
   (but there we don't support it)
   (but there we don't support it)
 }
 }
@@ -322,9 +318,7 @@
 }
 }
 {$ifdef llvm}
 {$ifdef llvm}
   {$undef SUPPORT_MMX}
   {$undef SUPPORT_MMX}
-  {$undef cpu16bitalu}
-  {$undef cpu32bitalu}
-  {$define cpu64bitalu}
   {$define cpuhighleveltarget}
   {$define cpuhighleveltarget}
+  {$define cpucg64shiftsupport}
   {$define symansistr}
   {$define symansistr}
 {$endif}
 {$endif}

+ 614 - 5
compiler/hlcg2ll.pas

@@ -330,7 +330,8 @@ implementation
 
 
     uses
     uses
        globals,systems,
        globals,systems,
-       verbose,defutil,
+       verbose,defutil,symsym,
+       procinfo,paramgr,
        cgobj,tgobj,cutils,
        cgobj,tgobj,cutils,
        ncgutil;
        ncgutil;
 
 
@@ -1319,9 +1320,83 @@ implementation
     end;
     end;
 
 
   procedure thlcg2ll.gen_load_para_value(list: TAsmList);
   procedure thlcg2ll.gen_load_para_value(list: TAsmList);
-    begin
-      ncgutil.gen_load_para_value(list);
-    end;
+
+    procedure get_para(const paraloc:TCGParaLocation);
+      begin
+         case paraloc.loc of
+           LOC_REGISTER :
+             begin
+               if getsupreg(paraloc.register)<first_int_imreg then
+                 cg.getcpuregister(list,paraloc.register);
+             end;
+           LOC_MMREGISTER :
+             begin
+               if getsupreg(paraloc.register)<first_mm_imreg then
+                 cg.getcpuregister(list,paraloc.register);
+             end;
+           LOC_FPUREGISTER :
+             begin
+               if getsupreg(paraloc.register)<first_fpu_imreg then
+                 cg.getcpuregister(list,paraloc.register);
+             end;
+         end;
+      end;
+
+   var
+     i : longint;
+     currpara : tparavarsym;
+     paraloc  : pcgparalocation;
+   begin
+     if (po_assembler in current_procinfo.procdef.procoptions) or
+     { exceptfilters have a single hidden 'parentfp' parameter, which
+       is handled by tcg.g_proc_entry. }
+        (current_procinfo.procdef.proctypeoption=potype_exceptfilter) then
+       exit;
+
+     { Allocate registers used by parameters }
+     for i:=0 to current_procinfo.procdef.paras.count-1 do
+       begin
+         currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
+         paraloc:=currpara.paraloc[calleeside].location;
+         while assigned(paraloc) do
+           begin
+             if paraloc^.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER] then
+               get_para(paraloc^);
+             paraloc:=paraloc^.next;
+           end;
+       end;
+
+     { Copy parameters to local references/registers }
+     for i:=0 to current_procinfo.procdef.paras.count-1 do
+       begin
+         currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
+         { don't use currpara.vardef, as this will be wrong in case of
+           call-by-reference parameters (it won't contain the pointerdef) }
+         gen_load_cgpara_loc(list,currpara.paraloc[calleeside].def,currpara.paraloc[calleeside],currpara.initialloc,paramanager.param_use_paraloc(currpara.paraloc[calleeside]));
+         { gen_load_cgpara_loc() already allocated the initialloc
+           -> don't allocate again }
+         if currpara.initialloc.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER] then
+           begin
+             gen_alloc_regvar(list,currpara,false);
+             hlcg.varsym_set_localloc(list,currpara);
+           end;
+       end;
+
+     { generate copies of call by value parameters, must be done before
+       the initialization and body is parsed because the refcounts are
+       incremented using the local copies }
+     current_procinfo.procdef.parast.SymList.ForEachCall(@hlcg.g_copyvalueparas,list);
+     if not(po_assembler in current_procinfo.procdef.procoptions) then
+       begin
+         { initialize refcounted paras, and trash others. Needed here
+           instead of in gen_initialize_code, because when a reference is
+           intialised or trashed while the pointer to that reference is kept
+           in a regvar, we add a register move and that one again has to
+           come after the parameter loading code as far as the register
+           allocator is concerned }
+         current_procinfo.procdef.parast.SymList.ForEachCall(@init_paras,list);
+       end;
+   end;
 
 
   procedure thlcg2ll.gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation; const cgpara: tcgpara; locintsize: longint);
   procedure thlcg2ll.gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation; const cgpara: tcgpara; locintsize: longint);
     var
     var
@@ -1525,8 +1600,542 @@ implementation
     end;
     end;
 
 
   procedure thlcg2ll.gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean);
   procedure thlcg2ll.gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean);
+
+    procedure unget_para(const paraloc:TCGParaLocation);
+      begin
+         case paraloc.loc of
+           LOC_REGISTER :
+             begin
+               if getsupreg(paraloc.register)<first_int_imreg then
+                 cg.ungetcpuregister(list,paraloc.register);
+             end;
+           LOC_MMREGISTER :
+             begin
+               if getsupreg(paraloc.register)<first_mm_imreg then
+                 cg.ungetcpuregister(list,paraloc.register);
+             end;
+           LOC_FPUREGISTER :
+             begin
+               if getsupreg(paraloc.register)<first_fpu_imreg then
+                 cg.ungetcpuregister(list,paraloc.register);
+             end;
+         end;
+      end;
+
+    var
+      paraloc   : pcgparalocation;
+      href      : treference;
+      sizeleft  : aint;
+      tempref   : treference;
+      loadsize  : tcgint;
+      tempreg  : tregister;
+{$ifdef mips}
+      //tmpreg   : tregister;
+{$endif mips}
+{$ifndef cpu64bitalu}
+      reg64    : tregister64;
+{$if defined(cpu8bitalu)}
+      curparaloc : PCGParaLocation;
+{$endif defined(cpu8bitalu)}
+{$endif not cpu64bitalu}
     begin
     begin
-      ncgutil.gen_load_cgpara_loc(list, vardef, para, destloc, reusepara);
+      paraloc:=para.location;
+      if not assigned(paraloc) then
+        internalerror(200408203);
+      { skip e.g. empty records }
+      if (paraloc^.loc = LOC_VOID) then
+        exit;
+      case destloc.loc of
+        LOC_REFERENCE :
+          begin
+            { If the parameter location is reused we don't need to copy
+              anything }
+            if not reusepara then
+              begin
+                href:=destloc.reference;
+                sizeleft:=para.intsize;
+                while assigned(paraloc) do
+                  begin
+                    if (paraloc^.size=OS_NO) then
+                      begin
+                        { Can only be a reference that contains the rest
+                          of the parameter }
+                        if (paraloc^.loc<>LOC_REFERENCE) or
+                           assigned(paraloc^.next) then
+                          internalerror(2005013010);
+                        cg.a_load_cgparaloc_ref(list,paraloc^,href,sizeleft,destloc.reference.alignment);
+                        inc(href.offset,sizeleft);
+                        sizeleft:=0;
+                      end
+                    else
+                      begin
+                        { the min(...) call ensures that we do not store more than place is left as
+                           paraloc^.size could be bigger than destloc.size of a parameter occupies a full register
+                           and as on big endian system the parameters might be left aligned, we have to work
+                           with the full register size for paraloc^.size }
+                        if tcgsize2size[destloc.size]<>0 then
+                          loadsize:=min(min(tcgsize2size[paraloc^.size],tcgsize2size[destloc.size]),sizeleft)
+                        else
+                          loadsize:=min(tcgsize2size[paraloc^.size],sizeleft);
+
+                        cg.a_load_cgparaloc_ref(list,paraloc^,href,loadsize,destloc.reference.alignment);
+                        inc(href.offset,loadsize);
+                        dec(sizeleft,loadsize);
+                      end;
+                    unget_para(paraloc^);
+                    paraloc:=paraloc^.next;
+                  end;
+              end;
+          end;
+        LOC_REGISTER,
+        LOC_CREGISTER :
+          begin
+{$ifdef cpu64bitalu}
+            if (para.size in [OS_128,OS_S128,OS_F128]) and
+               ({ in case of fpu emulation, or abi's that pass fpu values
+                  via integer registers }
+                (vardef.typ=floatdef) or
+                 is_methodpointer(vardef) or
+                 is_record(vardef)) then
+              begin
+                case paraloc^.loc of
+                  LOC_REGISTER,
+                  LOC_MMREGISTER:
+                    begin
+                      if not assigned(paraloc^.next) then
+                        internalerror(200410104);
+                      case tcgsize2size[paraloc^.size] of
+                        8:
+                          begin
+                            if (target_info.endian=ENDIAN_BIG) then
+                              begin
+                                { paraloc^ -> high
+                                  paraloc^.next -> low }
+                                unget_para(paraloc^);
+                                gen_alloc_regloc(list,destloc,vardef);
+                                { reg->reg, alignment is irrelevant }
+                                cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,destloc.register128.reghi,8);
+                                unget_para(paraloc^.next^);
+                                cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^.next^,destloc.register128.reglo,8);
+                              end
+                            else
+                              begin
+                                { paraloc^ -> low
+                                  paraloc^.next -> high }
+                                unget_para(paraloc^);
+                                gen_alloc_regloc(list,destloc,vardef);
+                                cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,destloc.register128.reglo,8);
+                                unget_para(paraloc^.next^);
+                                cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^.next^,destloc.register128.reghi,8);
+                              end;
+                          end;
+                        4:
+                          begin
+                            { The 128-bit parameter is located in 4 32-bit MM registers.
+                              It is needed to copy them to 2 64-bit int registers.
+                              A code generator or a target cpu must support loading of a 32-bit MM register to
+                              a 64-bit int register, zero extending it. }
+                            if target_info.endian=ENDIAN_BIG then
+                              internalerror(2018101702);  // Big endian support not implemented yet
+                            gen_alloc_regloc(list,destloc,vardef);
+                            tempreg:=cg.getintregister(list,OS_64);
+                            // Low part of the 128-bit param
+                            unget_para(paraloc^);
+                            cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,tempreg,4);
+                            paraloc:=paraloc^.next;
+                            if paraloc=nil then
+                              internalerror(2018101703);
+                            unget_para(paraloc^);
+                            cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,destloc.register128.reglo,4);
+                            cg.a_op_const_reg(list,OP_SHL,OS_64,32,destloc.register128.reglo);
+                            cg.a_op_reg_reg(list,OP_OR,OS_64,tempreg,destloc.register128.reglo);
+                            // High part of the 128-bit param
+                            paraloc:=paraloc^.next;
+                            if paraloc=nil then
+                              internalerror(2018101704);
+                            unget_para(paraloc^);
+                            cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,tempreg,4);
+                            paraloc:=paraloc^.next;
+                            if paraloc=nil then
+                              internalerror(2018101705);
+                            unget_para(paraloc^);
+                            cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,destloc.register128.reghi,4);
+                            cg.a_op_const_reg(list,OP_SHL,OS_64,32,destloc.register128.reghi);
+                            cg.a_op_reg_reg(list,OP_OR,OS_64,tempreg,destloc.register128.reghi);
+                          end
+                        else
+                          internalerror(2018101701);
+                      end;
+                    end;
+                  LOC_REFERENCE:
+                    begin
+                      gen_alloc_regloc(list,destloc,vardef);
+                      reference_reset_base(href,cpointerdef.getreusable(vardef),paraloc^.reference.index,paraloc^.reference.offset,ctempposinvalid,para.alignment,[]);
+                      cg128.a_load128_ref_reg(list,href,destloc.register128);
+                      unget_para(paraloc^);
+                    end;
+                  else
+                    internalerror(2012090607);
+                end
+              end
+            else
+{$else cpu64bitalu}
+            if (para.size in [OS_64,OS_S64,OS_F64]) and
+               (is_64bit(vardef) or
+                { in case of fpu emulation, or abi's that pass fpu values
+                  via integer registers }
+                (vardef.typ=floatdef) or
+                 is_methodpointer(vardef) or
+                 is_record(vardef)) then
+              begin
+                case paraloc^.loc of
+                  LOC_REGISTER:
+                    begin
+                      case para.locations_count of
+{$if defined(cpu8bitalu)}
+                        { 8 paralocs? }
+                        8:
+                          if (target_info.endian=ENDIAN_BIG) then
+                            begin
+                              { is there any big endian 8 bit ALU/16 bit Addr CPU? }
+                              internalerror(2015041003);
+                              { paraloc^ -> high
+                                paraloc^.next^.next^.next^.next -> low }
+                              unget_para(paraloc^);
+                              gen_alloc_regloc(list,destloc,vardef);
+                              { reg->reg, alignment is irrelevant }
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^,cg.GetNextReg(destloc.register64.reghi),1);
+                              unget_para(paraloc^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^,destloc.register64.reghi,1);
+                              unget_para(paraloc^.next^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^,cg.GetNextReg(destloc.register64.reglo),1);
+                              unget_para(paraloc^.next^.next^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^.next^,destloc.register64.reglo,1);
+                            end
+                          else
+                            begin
+                              { paraloc^ -> low
+                                paraloc^.next^.next^.next^.next -> high }
+                              curparaloc:=paraloc;
+                              unget_para(curparaloc^);
+                              gen_alloc_regloc(list,destloc,vardef);
+                              cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^,destloc.register64.reglo,2);
+                              unget_para(curparaloc^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^.next^,cg.GetNextReg(destloc.register64.reglo),1);
+                              unget_para(curparaloc^.next^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^.next^.next^,cg.GetNextReg(cg.GetNextReg(destloc.register64.reglo)),1);
+                              unget_para(curparaloc^.next^.next^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^.next^.next^.next^,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(destloc.register64.reglo))),1);
+
+                              curparaloc:=paraloc^.next^.next^.next^.next;
+                              unget_para(curparaloc^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^,destloc.register64.reghi,2);
+                              unget_para(curparaloc^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^.next^,cg.GetNextReg(destloc.register64.reghi),1);
+                              unget_para(curparaloc^.next^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^.next^.next^,cg.GetNextReg(cg.GetNextReg(destloc.register64.reghi)),1);
+                              unget_para(curparaloc^.next^.next^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^.next^.next^.next^,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(destloc.register64.reghi))),1);
+                            end;
+{$endif defined(cpu8bitalu)}
+{$if defined(cpu16bitalu) or defined(cpu8bitalu)}
+                        { 4 paralocs? }
+                        4:
+                          if (target_info.endian=ENDIAN_BIG) then
+                            begin
+                              { paraloc^ -> high
+                                paraloc^.next^.next -> low }
+                              unget_para(paraloc^);
+                              gen_alloc_regloc(list,destloc,vardef);
+                              { reg->reg, alignment is irrelevant }
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^,cg.GetNextReg(destloc.register64.reghi),2);
+                              unget_para(paraloc^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^,destloc.register64.reghi,2);
+                              unget_para(paraloc^.next^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^,cg.GetNextReg(destloc.register64.reglo),2);
+                              unget_para(paraloc^.next^.next^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^.next^,destloc.register64.reglo,2);
+                            end
+                          else
+                            begin
+                              { paraloc^ -> low
+                                paraloc^.next^.next -> high }
+                              unget_para(paraloc^);
+                              gen_alloc_regloc(list,destloc,vardef);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^,destloc.register64.reglo,2);
+                              unget_para(paraloc^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^,cg.GetNextReg(destloc.register64.reglo),2);
+                              unget_para(paraloc^.next^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^,destloc.register64.reghi,2);
+                              unget_para(paraloc^.next^.next^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^.next^,cg.GetNextReg(destloc.register64.reghi),2);
+                            end;
+{$endif defined(cpu16bitalu) or defined(cpu8bitalu)}
+                        2:
+                          if (target_info.endian=ENDIAN_BIG) then
+                            begin
+                              { paraloc^ -> high
+                                paraloc^.next -> low }
+                              unget_para(paraloc^);
+                              gen_alloc_regloc(list,destloc,vardef);
+                              { reg->reg, alignment is irrelevant }
+                              cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,destloc.register64.reghi,4);
+                              unget_para(paraloc^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reglo,4);
+                            end
+                          else
+                            begin
+                              { paraloc^ -> low
+                                paraloc^.next -> high }
+                              unget_para(paraloc^);
+                              gen_alloc_regloc(list,destloc,vardef);
+                              cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,destloc.register64.reglo,4);
+                              unget_para(paraloc^.next^);
+                              cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reghi,4);
+                            end;
+                        else
+                          { unexpected number of paralocs }
+                          internalerror(200410104);
+                      end;
+                    end;
+                  LOC_REFERENCE:
+                    begin
+                      gen_alloc_regloc(list,destloc,vardef);
+                      reference_reset_base(href,cpointerdef.getreusable(vardef),paraloc^.reference.index,paraloc^.reference.offset,ctempposinvalid,para.alignment,[]);
+                      cg64.a_load64_ref_reg(list,href,destloc.register64);
+                      unget_para(paraloc^);
+                    end;
+                  else
+                    internalerror(2005101501);
+                end
+              end
+            else
+{$endif cpu64bitalu}
+              begin
+                if assigned(paraloc^.next) then
+                  begin
+                    if (destloc.size in [OS_PAIR,OS_SPAIR]) and
+                      (para.Size in [OS_PAIR,OS_SPAIR]) then
+                      begin
+                        unget_para(paraloc^);
+                        gen_alloc_regloc(list,destloc,vardef);
+                        cg.a_load_cgparaloc_anyreg(list,OS_INT,paraloc^,destloc.register,sizeof(aint));
+                        unget_para(paraloc^.Next^);
+                        {$if defined(cpu16bitalu) or defined(cpu8bitalu)}
+                          cg.a_load_cgparaloc_anyreg(list,OS_INT,paraloc^.Next^,cg.GetNextReg(destloc.register),sizeof(aint));
+                        {$else}
+                          cg.a_load_cgparaloc_anyreg(list,OS_INT,paraloc^.Next^,destloc.registerhi,sizeof(aint));
+                        {$endif}
+                      end
+{$if defined(cpu8bitalu)}
+                    else if (destloc.size in [OS_32,OS_S32]) and
+                      (para.Size in [OS_32,OS_S32]) then
+                      begin
+                        unget_para(paraloc^);
+                        gen_alloc_regloc(list,destloc,vardef);
+                        cg.a_load_cgparaloc_anyreg(list,OS_8,paraloc^,destloc.register,sizeof(aint));
+                        unget_para(paraloc^.Next^);
+                        cg.a_load_cgparaloc_anyreg(list,OS_8,paraloc^.Next^,cg.GetNextReg(destloc.register),sizeof(aint));
+                        unget_para(paraloc^.Next^.Next^);
+                        cg.a_load_cgparaloc_anyreg(list,OS_8,paraloc^.Next^.Next^,cg.GetNextReg(cg.GetNextReg(destloc.register)),sizeof(aint));
+                        unget_para(paraloc^.Next^.Next^.Next^);
+                        cg.a_load_cgparaloc_anyreg(list,OS_8,paraloc^.Next^.Next^.Next^,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(destloc.register))),sizeof(aint));
+                      end
+{$endif defined(cpu8bitalu)}
+                    else
+                      begin
+                        { this can happen if a parameter is spread over
+                          multiple paralocs, e.g. if a record with two single
+                          fields must be passed in two single precision
+                          registers }
+                        { does it fit in the register of destloc? }
+                        sizeleft:=para.intsize;
+                        if sizeleft<>vardef.size then
+                          internalerror(2014122806);
+                        if sizeleft<>tcgsize2size[destloc.size] then
+                          internalerror(200410105);
+                        { store everything first to memory, then load it in
+                          destloc }
+                        tg.gettemp(list,sizeleft,sizeleft,tt_persistent,tempref);
+                        gen_alloc_regloc(list,destloc,vardef);
+                        while sizeleft>0 do
+                          begin
+                            if not assigned(paraloc) then
+                              internalerror(2014122807);
+                            unget_para(paraloc^);
+                            cg.a_load_cgparaloc_ref(list,paraloc^,tempref,sizeleft,newalignment(para.alignment,para.intsize-sizeleft));
+                            if (paraloc^.size=OS_NO) and
+                               assigned(paraloc^.next) then
+                              internalerror(2014122805);
+                            inc(tempref.offset,tcgsize2size[paraloc^.size]);
+                            dec(sizeleft,tcgsize2size[paraloc^.size]);
+                            paraloc:=paraloc^.next;
+                          end;
+                        dec(tempref.offset,para.intsize);
+                        cg.a_load_ref_reg(list,para.size,para.size,tempref,destloc.register);
+                        tg.ungettemp(list,tempref);
+                      end;
+                  end
+                else
+                  begin
+                    unget_para(paraloc^);
+                    gen_alloc_regloc(list,destloc,vardef);
+                    { we can't directly move regular registers into fpu
+                      registers }
+                    if getregtype(paraloc^.register)=R_FPUREGISTER then
+                      begin
+                        { store everything first to memory, then load it in
+                          destloc }
+                        tg.gettemp(list,tcgsize2size[paraloc^.size],para.intsize,tt_persistent,tempref);
+                        cg.a_load_cgparaloc_ref(list,paraloc^,tempref,tcgsize2size[paraloc^.size],tempref.alignment);
+                        cg.a_load_ref_reg(list,int_cgsize(tcgsize2size[paraloc^.size]),destloc.size,tempref,destloc.register);
+                        tg.ungettemp(list,tempref);
+                      end
+                    else
+                      cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,sizeof(aint));
+                  end;
+              end;
+          end;
+        LOC_FPUREGISTER,
+        LOC_CFPUREGISTER :
+          begin
+{$ifdef mips}
+            if (destloc.size = paraloc^.Size) and
+               (paraloc^.Loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER,LOC_REFERENCE,LOC_CREFERENCE]) then
+              begin
+                unget_para(paraloc^);
+                gen_alloc_regloc(list,destloc,vardef);
+                cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,para.alignment);
+              end
+            else if (destloc.size = OS_F32) and
+               (paraloc^.Loc in [LOC_REGISTER,LOC_CREGISTER]) then
+              begin
+                gen_alloc_regloc(list,destloc,vardef);
+                unget_para(paraloc^);
+                list.Concat(taicpu.op_reg_reg(A_MTC1,paraloc^.register,destloc.register));
+              end
+{ TODO: Produces invalid code, needs fixing together with regalloc setup. }
+{
+            else if (destloc.size = OS_F64) and
+                    (paraloc^.Loc in [LOC_REGISTER,LOC_CREGISTER]) and
+                    (paraloc^.next^.Loc in [LOC_REGISTER,LOC_CREGISTER]) then
+              begin
+                gen_alloc_regloc(list,destloc,vardef);
+
+                tmpreg:=destloc.register;
+                unget_para(paraloc^);
+                list.Concat(taicpu.op_reg_reg(A_MTC1,paraloc^.register,tmpreg));
+                setsupreg(tmpreg,getsupreg(tmpreg)+1);
+                unget_para(paraloc^.next^);
+                list.Concat(taicpu.op_reg_reg(A_MTC1,paraloc^.Next^.register,tmpreg));
+              end
+}
+            else
+              begin
+                sizeleft := TCGSize2Size[destloc.size];
+                tg.GetTemp(list,sizeleft,sizeleft,tt_normal,tempref);
+                href:=tempref;
+                while assigned(paraloc) do
+                  begin
+                    unget_para(paraloc^);
+                    cg.a_load_cgparaloc_ref(list,paraloc^,href,sizeleft,destloc.reference.alignment);
+                    inc(href.offset,TCGSize2Size[paraloc^.size]);
+                    dec(sizeleft,TCGSize2Size[paraloc^.size]);
+                    paraloc:=paraloc^.next;
+                  end;
+                gen_alloc_regloc(list,destloc,vardef);
+                cg.a_loadfpu_ref_reg(list,destloc.size,destloc.size,tempref,destloc.register);
+                tg.UnGetTemp(list,tempref);
+              end;
+{$else mips}
+{$if defined(sparc) or defined(arm)}
+            { Arm and Sparc passes floats in int registers, when loading to fpu register
+              we need a temp }
+            sizeleft := TCGSize2Size[destloc.size];
+            tg.GetTemp(list,sizeleft,sizeleft,tt_normal,tempref);
+            href:=tempref;
+            while assigned(paraloc) do
+              begin
+                unget_para(paraloc^);
+                cg.a_load_cgparaloc_ref(list,paraloc^,href,sizeleft,destloc.reference.alignment);
+                inc(href.offset,TCGSize2Size[paraloc^.size]);
+                dec(sizeleft,TCGSize2Size[paraloc^.size]);
+                paraloc:=paraloc^.next;
+              end;
+            gen_alloc_regloc(list,destloc,vardef);
+            cg.a_loadfpu_ref_reg(list,destloc.size,destloc.size,tempref,destloc.register);
+            tg.UnGetTemp(list,tempref);
+{$else defined(sparc) or defined(arm)}
+            unget_para(paraloc^);
+            gen_alloc_regloc(list,destloc,vardef);
+            { from register to register -> alignment is irrelevant }
+            cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,0);
+            if assigned(paraloc^.next) then
+              internalerror(200410109);
+{$endif defined(sparc) or defined(arm)}
+{$endif mips}
+          end;
+        LOC_MMREGISTER,
+        LOC_CMMREGISTER :
+          begin
+{$ifndef cpu64bitalu}
+            { ARM vfp floats are passed in integer registers }
+            if (para.size=OS_F64) and
+               (paraloc^.size in [OS_32,OS_S32]) and
+               use_vectorfpu(vardef) then
+              begin
+                { we need 2x32bit reg }
+                if not assigned(paraloc^.next) or
+                   assigned(paraloc^.next^.next) then
+                  internalerror(2009112421);
+                unget_para(paraloc^.next^);
+                case paraloc^.next^.loc of
+                  LOC_REGISTER:
+                    tempreg:=paraloc^.next^.register;
+                  LOC_REFERENCE:
+                    begin
+                      tempreg:=cg.getintregister(list,OS_32);
+                      cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,tempreg,4);
+                    end;
+                  else
+                    internalerror(2012051301);
+                end;
+                { don't free before the above, because then the getintregister
+                  could reallocate this register and overwrite it }
+                unget_para(paraloc^);
+                gen_alloc_regloc(list,destloc,vardef);
+                if (target_info.endian=endian_big) then
+                  { paraloc^ -> high
+                    paraloc^.next -> low }
+                  reg64:=joinreg64(tempreg,paraloc^.register)
+                else
+                  reg64:=joinreg64(paraloc^.register,tempreg);
+                cg64.a_loadmm_intreg64_reg(list,OS_F64,reg64,destloc.register);
+              end
+            else
+{$endif not cpu64bitalu}
+              begin
+                if not assigned(paraloc^.next) then
+                  begin
+                    unget_para(paraloc^);
+                    gen_alloc_regloc(list,destloc,vardef);
+                    { from register to register -> alignment is irrelevant }
+                    cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,0);
+                  end
+                else
+                  begin
+                    internalerror(200410108);
+                  end;
+                { data could come in two memory locations, for now
+                  we simply ignore the sanity check (FK)
+                if assigned(paraloc^.next) then
+                  internalerror(200410108);
+                }
+              end;
+          end;
+        else
+          internalerror(2010052903);
+      end;
     end;
     end;
 
 
   function thlcg2ll.getintmmcgsize(reg: tregister; size: tcgsize): tcgsize;
   function thlcg2ll.getintmmcgsize(reg: tregister; size: tcgsize): tcgsize;

+ 2 - 2
compiler/hlcgobj.pas

@@ -991,7 +991,7 @@ implementation
                      { load the value piecewise to get it into the register }
                      { load the value piecewise to get it into the register }
                      orgsizeleft:=sizeleft;
                      orgsizeleft:=sizeleft;
                      reghasvalue:=false;
                      reghasvalue:=false;
-{$ifdef cpu64bitalu}
+{$if defined(cpu64bitalu) or defined(cpuhighleveltarget)}
                      if sizeleft>=4 then
                      if sizeleft>=4 then
                        begin
                        begin
                          a_load_ref_reg(list,u32inttype,location^.def,tmpref,location^.register);
                          a_load_ref_reg(list,u32inttype,location^.def,tmpref,location^.register);
@@ -1001,7 +1001,7 @@ implementation
                          inc(tmpref.offset,4);
                          inc(tmpref.offset,4);
                          reghasvalue:=true;
                          reghasvalue:=true;
                        end;
                        end;
-{$endif cpu64bitalu}
+{$endif defind(cpu64bitalu) or defined(cpuhighleveltarget)}
                      if sizeleft>=2 then
                      if sizeleft>=2 then
                        begin
                        begin
                          tmpreg:=getintregister(list,location^.def);
                          tmpreg:=getintregister(list,location^.def);

+ 4 - 172
compiler/i386/aoptcpu.pas

@@ -40,7 +40,6 @@ unit aoptcpu;
         procedure PeepHoleOptPass1; override;
         procedure PeepHoleOptPass1; override;
         procedure PeepHoleOptPass2; override;
         procedure PeepHoleOptPass2; override;
         procedure PostPeepHoleOpts; override;
         procedure PostPeepHoleOpts; override;
-        function DoFpuLoadStoreOpt(var p : tai) : boolean;
       end;
       end;
 
 
     Var
     Var
@@ -58,74 +57,6 @@ unit aoptcpu;
       { units we should get rid off: }
       { units we should get rid off: }
       symsym,symconst;
       symsym,symconst;
 
 
-    function TCPUAsmoptimizer.DoFpuLoadStoreOpt(var p: tai): boolean;
-    { returns true if a "continue" should be done after this optimization }
-    var hp1, hp2: tai;
-    begin
-      DoFpuLoadStoreOpt := false;
-      if (taicpu(p).oper[0]^.typ = top_ref) and
-         getNextInstruction(p, hp1) and
-         (hp1.typ = ait_instruction) and
-         (((taicpu(hp1).opcode = A_FLD) and
-           (taicpu(p).opcode = A_FSTP)) or
-          ((taicpu(p).opcode = A_FISTP) and
-           (taicpu(hp1).opcode = A_FILD))) and
-         (taicpu(hp1).oper[0]^.typ = top_ref) and
-         (taicpu(hp1).opsize = taicpu(p).opsize) and
-         RefsEqual(taicpu(p).oper[0]^.ref^, taicpu(hp1).oper[0]^.ref^) then
-        begin
-          { replacing fstp f;fld f by fst f is only valid for extended because of rounding }
-          if (taicpu(p).opsize=S_FX) and
-             getNextInstruction(hp1, hp2) and
-             (hp2.typ = ait_instruction) and
-             IsExitCode(hp2) and
-             (taicpu(p).oper[0]^.ref^.base = current_procinfo.FramePointer) and
-             not(assigned(current_procinfo.procdef.funcretsym) and
-                 (taicpu(p).oper[0]^.ref^.offset < tabstractnormalvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset)) and
-             (taicpu(p).oper[0]^.ref^.index = NR_NO) then
-            begin
-              asml.remove(p);
-              asml.remove(hp1);
-              p.free;
-              hp1.free;
-              p := hp2;
-              removeLastDeallocForFuncRes(p);
-              doFPULoadStoreOpt := true;
-            end
-          (* can't be done because the store operation rounds
-          else
-            { fst can't store an extended value! }
-            if (taicpu(p).opsize <> S_FX) and
-               (taicpu(p).opsize <> S_IQ) then
-              begin
-                if (taicpu(p).opcode = A_FSTP) then
-                  taicpu(p).opcode := A_FST
-                else taicpu(p).opcode := A_FIST;
-                asml.remove(hp1);
-                hp1.free;
-              end
-          *)
-        end;
-    end;
-
-
-  { converts a TChange variable to a TRegister }
-  function tch2reg(ch: tinschange): tsuperregister;
-    const
-      ch2reg: array[CH_REAX..CH_REDI] of tsuperregister = (RS_EAX,RS_ECX,RS_EDX,RS_EBX,RS_ESP,RS_EBP,RS_ESI,RS_EDI);
-    begin
-      if (ch <= CH_REDI) then
-        tch2reg := ch2reg[ch]
-      else if (ch <= CH_WEDI) then
-        tch2reg := ch2reg[tinschange(ord(ch) - ord(CH_REDI))]
-      else if (ch <= CH_RWEDI) then
-        tch2reg := ch2reg[tinschange(ord(ch) - ord(CH_WEDI))]
-      else if (ch <= CH_MEDI) then
-        tch2reg := ch2reg[tinschange(ord(ch) - ord(CH_RWEDI))]
-      else
-        InternalError(2016041901)
-    end;
-
 
 
   { Checks if the register is a 32 bit general purpose register }
   { Checks if the register is a 32 bit general purpose register }
   function isgp32reg(reg: TRegister): boolean;
   function isgp32reg(reg: TRegister): boolean;
@@ -475,109 +406,10 @@ begin
                         end
                         end
                     end;
                     end;
                   A_FLD:
                   A_FLD:
-                    begin
-                      if (taicpu(p).oper[0]^.typ = top_reg) and
-                         GetNextInstruction(p, hp1) and
-                         (hp1.typ = Ait_Instruction) and
-                          (taicpu(hp1).oper[0]^.typ = top_reg) and
-                         (taicpu(hp1).oper[1]^.typ = top_reg) and
-                         (taicpu(hp1).oper[0]^.reg = NR_ST) and
-                         (taicpu(hp1).oper[1]^.reg = NR_ST1) then
-                         { change                        to
-                             fld      reg               fxxx reg,st
-                             fxxxp    st, st1 (hp1)
-                           Remark: non commutative operations must be reversed!
-                         }
-                        begin
-                            case taicpu(hp1).opcode Of
-                              A_FMULP,A_FADDP,
-                              A_FSUBP,A_FDIVP,A_FSUBRP,A_FDIVRP:
-                                begin
-                                  case taicpu(hp1).opcode Of
-                                    A_FADDP: taicpu(hp1).opcode := A_FADD;
-                                    A_FMULP: taicpu(hp1).opcode := A_FMUL;
-                                    A_FSUBP: taicpu(hp1).opcode := A_FSUBR;
-                                    A_FSUBRP: taicpu(hp1).opcode := A_FSUB;
-                                    A_FDIVP: taicpu(hp1).opcode := A_FDIVR;
-                                    A_FDIVRP: taicpu(hp1).opcode := A_FDIV;
-                                  end;
-                                  taicpu(hp1).oper[0]^.reg := taicpu(p).oper[0]^.reg;
-                                  taicpu(hp1).oper[1]^.reg := NR_ST;
-                                  asml.remove(p);
-                                  p.free;
-                                  p := hp1;
-                                  continue;
-                                end;
-                            end;
-                        end
-                      else
-                        if (taicpu(p).oper[0]^.typ = top_ref) and
-                           GetNextInstruction(p, hp2) and
-                           (hp2.typ = Ait_Instruction) and
-                           (taicpu(hp2).ops = 2) and
-                           (taicpu(hp2).oper[0]^.typ = top_reg) and
-                           (taicpu(hp2).oper[1]^.typ = top_reg) and
-                           (taicpu(p).opsize in [S_FS, S_FL]) and
-                           (taicpu(hp2).oper[0]^.reg = NR_ST) and
-                           (taicpu(hp2).oper[1]^.reg = NR_ST1) then
-                          if GetLastInstruction(p, hp1) and
-                             (hp1.typ = Ait_Instruction) and
-                             ((taicpu(hp1).opcode = A_FLD) or
-                              (taicpu(hp1).opcode = A_FST)) and
-                             (taicpu(hp1).opsize = taicpu(p).opsize) and
-                             (taicpu(hp1).oper[0]^.typ = top_ref) and
-                             RefsEqual(taicpu(p).oper[0]^.ref^, taicpu(hp1).oper[0]^.ref^) then
-                            if ((taicpu(hp2).opcode = A_FMULP) or
-                                (taicpu(hp2).opcode = A_FADDP)) then
-                            { change                      to
-                                fld/fst   mem1  (hp1)       fld/fst   mem1
-                                fld       mem1  (p)         fadd/
-                                faddp/                       fmul     st, st
-                                fmulp  st, st1 (hp2) }
-                              begin
-                                asml.remove(p);
-                                p.free;
-                                p := hp1;
-                                if (taicpu(hp2).opcode = A_FADDP) then
-                                  taicpu(hp2).opcode := A_FADD
-                                else
-                                  taicpu(hp2).opcode := A_FMUL;
-                                taicpu(hp2).oper[1]^.reg := NR_ST;
-                              end
-                            else
-                            { change              to
-                                fld/fst mem1 (hp1)   fld/fst mem1
-                                fld     mem1 (p)     fld      st}
-                              begin
-                                taicpu(p).changeopsize(S_FL);
-                                taicpu(p).loadreg(0,NR_ST);
-                              end
-                          else
-                            begin
-                              case taicpu(hp2).opcode Of
-                                A_FMULP,A_FADDP,A_FSUBP,A_FDIVP,A_FSUBRP,A_FDIVRP:
-                          { change                        to
-                              fld/fst  mem1    (hp1)      fld/fst    mem1
-                              fld      mem2    (p)        fxxx       mem2
-                              fxxxp    st, st1 (hp2)                      }
-
-                                  begin
-                                    case taicpu(hp2).opcode Of
-                                      A_FADDP: taicpu(p).opcode := A_FADD;
-                                      A_FMULP: taicpu(p).opcode := A_FMUL;
-                                      A_FSUBP: taicpu(p).opcode := A_FSUBR;
-                                      A_FSUBRP: taicpu(p).opcode := A_FSUB;
-                                      A_FDIVP: taicpu(p).opcode := A_FDIVR;
-                                      A_FDIVRP: taicpu(p).opcode := A_FDIV;
-                                    end;
-                                    asml.remove(hp2);
-                                    hp2.free;
-                                  end
-                              end
-                            end
-                    end;
+                    if OptPass1FLD(p) then
+                      continue;
                   A_FSTP,A_FISTP:
                   A_FSTP,A_FISTP:
-                    if doFpuLoadStoreOpt(p) then
+                    if OptPass1FSTP(p) then
                       continue;
                       continue;
                   A_LEA:
                   A_LEA:
                     begin
                     begin
@@ -776,7 +608,7 @@ begin
                 if OptPass2Jcc(p) then
                 if OptPass2Jcc(p) then
                   continue;
                   continue;
               A_FSTP,A_FISTP:
               A_FSTP,A_FISTP:
-                if DoFpuLoadStoreOpt(p) then
+                if OptPass1FSTP(p) then
                   continue;
                   continue;
               A_IMUL:
               A_IMUL:
                 if OptPass2Imul(p) then
                 if OptPass2Imul(p) then

+ 11 - 13
compiler/i386/cpupara.pas

@@ -466,25 +466,23 @@ unit cpupara;
             else
             else
               begin
               begin
                 paralen:=push_size(hp.varspez,paradef,p.proccalloption);
                 paralen:=push_size(hp.varspez,paradef,p.proccalloption);
-                { darwin/x86 requires that parameters < sizeof(aint) are sign/ }
-                { zero extended to sizeof(aint)                                }
-                if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
-                   (side = callerside) and
-                   (paralen > 0) and
-                   (paralen < sizeof(aint)) then
-                  begin
-                    paralen:=sizeof(aint);
-                    paracgsize:=OS_SINT;
-                    paradef:=sinttype;
-                  end
-                else
-                  paracgsize:=def_cgsize(paradef);
+                paracgsize:=def_cgsize(paradef);
               end;
               end;
             hp.paraloc[side].reset;
             hp.paraloc[side].reset;
             hp.paraloc[side].size:=paracgsize;
             hp.paraloc[side].size:=paracgsize;
             hp.paraloc[side].intsize:=paralen;
             hp.paraloc[side].intsize:=paralen;
             hp.paraloc[side].def:=paradef;
             hp.paraloc[side].def:=paradef;
             hp.paraloc[side].Alignment:=paraalign;
             hp.paraloc[side].Alignment:=paraalign;
+            { darwin/x86 requires that parameters < sizeof(aint) are sign/ }
+            { zero extended to sizeof(aint)                                }
+            if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
+               (side = callerside) and
+               (paralen > 0) and
+               (paralen < sizeof(aint)) then
+              begin
+                paracgsize:=OS_SINT;
+                paradef:=sinttype;
+              end;
             { Copy to stack? }
             { Copy to stack? }
             if (paracgsize=OS_NO) or
             if (paracgsize=OS_NO) or
                (use_fixed_stack) then
                (use_fixed_stack) then

+ 7 - 0
compiler/i386/i386att.inc

@@ -684,6 +684,8 @@
 'aesimc',
 'aesimc',
 'aeskeygenassist',
 'aeskeygenassist',
 'rdtscp',
 'rdtscp',
+'movbe',
+'pclmulqdq',
 'vaddpd',
 'vaddpd',
 'vaddps',
 'vaddps',
 'vaddsd',
 'vaddsd',
@@ -1009,6 +1011,9 @@
 'vzeroupper',
 'vzeroupper',
 'andn',
 'andn',
 'bextr',
 'bextr',
+'blsi',
+'blsmsk',
+'blsr',
 'tzcnt',
 'tzcnt',
 'bzhi',
 'bzhi',
 'mulx',
 'mulx',
@@ -1018,6 +1023,8 @@
 'sarx',
 'sarx',
 'shlx',
 'shlx',
 'shrx',
 'shrx',
+'adcx',
+'adox',
 'vbroadcasti128',
 'vbroadcasti128',
 'vextracti128',
 'vextracti128',
 'vinserti128',
 'vinserti128',

+ 7 - 0
compiler/i386/i386atts.inc

@@ -684,6 +684,8 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufINT,
+attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
@@ -1021,6 +1023,11 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,

+ 7 - 0
compiler/i386/i386int.inc

@@ -684,6 +684,8 @@
 'aesimc',
 'aesimc',
 'aeskeygenassist',
 'aeskeygenassist',
 'rdtscp',
 'rdtscp',
+'movbe',
+'pclmulqdq',
 'vaddpd',
 'vaddpd',
 'vaddps',
 'vaddps',
 'vaddsd',
 'vaddsd',
@@ -1009,6 +1011,9 @@
 'vzeroupper',
 'vzeroupper',
 'andn',
 'andn',
 'bextr',
 'bextr',
+'blsi',
+'blsmsk',
+'blsr',
 'tzcnt',
 'tzcnt',
 'bzhi',
 'bzhi',
 'mulx',
 'mulx',
@@ -1018,6 +1023,8 @@
 'sarx',
 'sarx',
 'shlx',
 'shlx',
 'shrx',
 'shrx',
+'adcx',
+'adox',
 'vbroadcasti128',
 'vbroadcasti128',
 'vextracti128',
 'vextracti128',
 'vinserti128',
 'vinserti128',

+ 1 - 1
compiler/i386/i386nop.inc

@@ -1,2 +1,2 @@
 { don't edit, this file is generated from x86ins.dat }
 { don't edit, this file is generated from x86ins.dat }
-2121;
+2129;

+ 7 - 0
compiler/i386/i386op.inc

@@ -684,6 +684,8 @@ A_AESDECLAST,
 A_AESIMC,
 A_AESIMC,
 A_AESKEYGENASSIST,
 A_AESKEYGENASSIST,
 A_RDTSCP,
 A_RDTSCP,
+A_MOVBE,
+A_PCLMULQDQ,
 A_VADDPD,
 A_VADDPD,
 A_VADDPS,
 A_VADDPS,
 A_VADDSD,
 A_VADDSD,
@@ -1009,6 +1011,9 @@ A_VZEROALL,
 A_VZEROUPPER,
 A_VZEROUPPER,
 A_ANDN,
 A_ANDN,
 A_BEXTR,
 A_BEXTR,
+A_BLSI,
+A_BLSMSK,
+A_BLSR,
 A_TZCNT,
 A_TZCNT,
 A_BZHI,
 A_BZHI,
 A_MULX,
 A_MULX,
@@ -1018,6 +1023,8 @@ A_RORX,
 A_SARX,
 A_SARX,
 A_SHLX,
 A_SHLX,
 A_SHRX,
 A_SHRX,
+A_ADCX,
+A_ADOX,
 A_VBROADCASTI128,
 A_VBROADCASTI128,
 A_VEXTRACTI128,
 A_VEXTRACTI128,
 A_VINSERTI128,
 A_VINSERTI128,

+ 7 - 0
compiler/i386/i386prop.inc

@@ -684,6 +684,8 @@
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_WEAX, Ch_WEDX]),
 (Ch: [Ch_WEAX, Ch_WEDX]),
+(Ch: [Ch_Rop1, Ch_Wop2]),
+(Ch: [Ch_All]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
@@ -1009,6 +1011,9 @@
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
+(Ch: [Ch_Rop1, Ch_Wop2, Ch_W0OverflowFlag, Ch_WCarryFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WUParityFlag, Ch_WUAuxiliaryFlag]),
+(Ch: [Ch_Rop1, Ch_Wop2, Ch_W0OverflowFlag, Ch_WCarryFlag, Ch_WSignFlag, Ch_W0ZeroFlag, Ch_WUParityFlag, Ch_WUAuxiliaryFlag]),
+(Ch: [Ch_Rop1, Ch_Wop2, Ch_W0OverflowFlag, Ch_WCarryFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WUParityFlag, Ch_WUAuxiliaryFlag]),
 (Ch: [Ch_Wop2, Ch_WFlags, Ch_Rop1]),
 (Ch: [Ch_Wop2, Ch_WFlags, Ch_Rop1]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_REDX, Ch_Rop1, Ch_Wop2, Ch_Wop3]),
 (Ch: [Ch_REDX, Ch_Rop1, Ch_Wop2, Ch_Wop3]),
@@ -1018,6 +1023,8 @@
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
+(Ch: [Ch_Rop1, Ch_Mop2, Ch_RWCarryFlag]),
+(Ch: [Ch_Rop1, Ch_Mop2, Ch_RWOverflowFlag]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),

+ 56 - 0
compiler/i386/i386tab.inc

@@ -8708,6 +8708,27 @@
     code    : #3#15#1#249;
     code    : #3#15#1#249;
     flags   : [if_sse4,if_sm]
     flags   : [if_sse4,if_sm]
   ),
   ),
+  (
+    opcode  : A_MOVBE;
+    ops     : 2;
+    optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+    code    : #208#3#15#56#240#72;
+    flags   : [if_movbe,if_sm]
+  ),
+  (
+    opcode  : A_MOVBE;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits16 or ot_bits32 or ot_bits64,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+    code    : #209#3#15#56#241#65;
+    flags   : [if_movbe,if_sm]
+  ),
+  (
+    opcode  : A_PCLMULQDQ;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmrm,ot_immediate or ot_bits8,ot_none);
+    code    : #241#3#15#58#68#72#22;
+    flags   : [if_clmul,if_sandybridge]
+  ),
   (
   (
     opcode  : A_VADDPD;
     opcode  : A_VADDPD;
     ops     : 3;
     ops     : 3;
@@ -13608,6 +13629,27 @@
     code    : #242#249#1#247#62#72;
     code    : #242#249#1#247#62#72;
     flags   : [if_bmi1,if_prot]
     flags   : [if_bmi1,if_prot]
   ),
   ),
+  (
+    opcode  : A_BLSI;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #242#249#1#243#60#139;
+    flags   : [if_bmi1,if_prot]
+  ),
+  (
+    opcode  : A_BLSMSK;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #242#249#1#243#60#138;
+    flags   : [if_bmi1,if_prot]
+  ),
+  (
+    opcode  : A_BLSR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #242#249#1#243#60#137;
+    flags   : [if_bmi1,if_prot]
+  ),
   (
   (
     opcode  : A_TZCNT;
     opcode  : A_TZCNT;
     ops     : 2;
     ops     : 2;
@@ -13671,6 +13713,20 @@
     code    : #220#242#249#1#247#62#72;
     code    : #220#242#249#1#247#62#72;
     flags   : [if_bmi2,if_prot]
     flags   : [if_bmi2,if_prot]
   ),
   ),
+  (
+    opcode  : A_ADCX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #241#3#15#56#246#72;
+    flags   : [if_adx]
+  ),
+  (
+    opcode  : A_ADOX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #219#3#15#56#246#72;
+    flags   : [if_adx]
+  ),
   (
   (
     opcode  : A_VBROADCASTI128;
     opcode  : A_VBROADCASTI128;
     ops     : 2;
     ops     : 2;

+ 7 - 0
compiler/i8086/i8086att.inc

@@ -684,6 +684,8 @@
 'aesimc',
 'aesimc',
 'aeskeygenassist',
 'aeskeygenassist',
 'rdtscp',
 'rdtscp',
+'movbe',
+'pclmulqdq',
 'vaddpd',
 'vaddpd',
 'vaddps',
 'vaddps',
 'vaddsd',
 'vaddsd',
@@ -1009,6 +1011,9 @@
 'vzeroupper',
 'vzeroupper',
 'andn',
 'andn',
 'bextr',
 'bextr',
+'blsi',
+'blsmsk',
+'blsr',
 'tzcnt',
 'tzcnt',
 'bzhi',
 'bzhi',
 'mulx',
 'mulx',
@@ -1018,6 +1023,8 @@
 'sarx',
 'sarx',
 'shlx',
 'shlx',
 'shrx',
 'shrx',
+'adcx',
+'adox',
 'vbroadcasti128',
 'vbroadcasti128',
 'vextracti128',
 'vextracti128',
 'vinserti128',
 'vinserti128',

+ 7 - 0
compiler/i8086/i8086atts.inc

@@ -684,6 +684,8 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufINT,
+attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
@@ -1021,6 +1023,11 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,

+ 7 - 0
compiler/i8086/i8086int.inc

@@ -684,6 +684,8 @@
 'aesimc',
 'aesimc',
 'aeskeygenassist',
 'aeskeygenassist',
 'rdtscp',
 'rdtscp',
+'movbe',
+'pclmulqdq',
 'vaddpd',
 'vaddpd',
 'vaddps',
 'vaddps',
 'vaddsd',
 'vaddsd',
@@ -1009,6 +1011,9 @@
 'vzeroupper',
 'vzeroupper',
 'andn',
 'andn',
 'bextr',
 'bextr',
+'blsi',
+'blsmsk',
+'blsr',
 'tzcnt',
 'tzcnt',
 'bzhi',
 'bzhi',
 'mulx',
 'mulx',
@@ -1018,6 +1023,8 @@
 'sarx',
 'sarx',
 'shlx',
 'shlx',
 'shrx',
 'shrx',
+'adcx',
+'adox',
 'vbroadcasti128',
 'vbroadcasti128',
 'vextracti128',
 'vextracti128',
 'vinserti128',
 'vinserti128',

+ 1 - 1
compiler/i8086/i8086nop.inc

@@ -1,2 +1,2 @@
 { don't edit, this file is generated from x86ins.dat }
 { don't edit, this file is generated from x86ins.dat }
-2153;
+2161;

+ 7 - 0
compiler/i8086/i8086op.inc

@@ -684,6 +684,8 @@ A_AESDECLAST,
 A_AESIMC,
 A_AESIMC,
 A_AESKEYGENASSIST,
 A_AESKEYGENASSIST,
 A_RDTSCP,
 A_RDTSCP,
+A_MOVBE,
+A_PCLMULQDQ,
 A_VADDPD,
 A_VADDPD,
 A_VADDPS,
 A_VADDPS,
 A_VADDSD,
 A_VADDSD,
@@ -1009,6 +1011,9 @@ A_VZEROALL,
 A_VZEROUPPER,
 A_VZEROUPPER,
 A_ANDN,
 A_ANDN,
 A_BEXTR,
 A_BEXTR,
+A_BLSI,
+A_BLSMSK,
+A_BLSR,
 A_TZCNT,
 A_TZCNT,
 A_BZHI,
 A_BZHI,
 A_MULX,
 A_MULX,
@@ -1018,6 +1023,8 @@ A_RORX,
 A_SARX,
 A_SARX,
 A_SHLX,
 A_SHLX,
 A_SHRX,
 A_SHRX,
+A_ADCX,
+A_ADOX,
 A_VBROADCASTI128,
 A_VBROADCASTI128,
 A_VEXTRACTI128,
 A_VEXTRACTI128,
 A_VINSERTI128,
 A_VINSERTI128,

+ 7 - 0
compiler/i8086/i8086prop.inc

@@ -684,6 +684,8 @@
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_WEAX, Ch_WEDX]),
 (Ch: [Ch_WEAX, Ch_WEDX]),
+(Ch: [Ch_Rop1, Ch_Wop2]),
+(Ch: [Ch_All]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
@@ -1009,6 +1011,9 @@
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
+(Ch: [Ch_Rop1, Ch_Wop2, Ch_W0OverflowFlag, Ch_WCarryFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WUParityFlag, Ch_WUAuxiliaryFlag]),
+(Ch: [Ch_Rop1, Ch_Wop2, Ch_W0OverflowFlag, Ch_WCarryFlag, Ch_WSignFlag, Ch_W0ZeroFlag, Ch_WUParityFlag, Ch_WUAuxiliaryFlag]),
+(Ch: [Ch_Rop1, Ch_Wop2, Ch_W0OverflowFlag, Ch_WCarryFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WUParityFlag, Ch_WUAuxiliaryFlag]),
 (Ch: [Ch_Wop2, Ch_WFlags, Ch_Rop1]),
 (Ch: [Ch_Wop2, Ch_WFlags, Ch_Rop1]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_REDX, Ch_Rop1, Ch_Wop2, Ch_Wop3]),
 (Ch: [Ch_REDX, Ch_Rop1, Ch_Wop2, Ch_Wop3]),
@@ -1018,6 +1023,8 @@
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
+(Ch: [Ch_Rop1, Ch_Mop2, Ch_RWCarryFlag]),
+(Ch: [Ch_Rop1, Ch_Mop2, Ch_RWOverflowFlag]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),

+ 56 - 0
compiler/i8086/i8086tab.inc

@@ -8736,6 +8736,27 @@
     code    : #3#15#1#249;
     code    : #3#15#1#249;
     flags   : [if_sse4,if_sm]
     flags   : [if_sse4,if_sm]
   ),
   ),
+  (
+    opcode  : A_MOVBE;
+    ops     : 2;
+    optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+    code    : #208#3#15#56#240#72;
+    flags   : [if_movbe,if_sm]
+  ),
+  (
+    opcode  : A_MOVBE;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits16 or ot_bits32 or ot_bits64,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+    code    : #209#3#15#56#241#65;
+    flags   : [if_movbe,if_sm]
+  ),
+  (
+    opcode  : A_PCLMULQDQ;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmrm,ot_immediate or ot_bits8,ot_none);
+    code    : #241#3#15#58#68#72#22;
+    flags   : [if_clmul,if_sandybridge]
+  ),
   (
   (
     opcode  : A_VADDPD;
     opcode  : A_VADDPD;
     ops     : 3;
     ops     : 3;
@@ -13636,6 +13657,27 @@
     code    : #242#249#1#247#62#72;
     code    : #242#249#1#247#62#72;
     flags   : [if_bmi1,if_prot]
     flags   : [if_bmi1,if_prot]
   ),
   ),
+  (
+    opcode  : A_BLSI;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #242#249#1#243#60#139;
+    flags   : [if_bmi1,if_prot]
+  ),
+  (
+    opcode  : A_BLSMSK;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #242#249#1#243#60#138;
+    flags   : [if_bmi1,if_prot]
+  ),
+  (
+    opcode  : A_BLSR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #242#249#1#243#60#137;
+    flags   : [if_bmi1,if_prot]
+  ),
   (
   (
     opcode  : A_TZCNT;
     opcode  : A_TZCNT;
     ops     : 2;
     ops     : 2;
@@ -13699,6 +13741,20 @@
     code    : #220#242#249#1#247#62#72;
     code    : #220#242#249#1#247#62#72;
     flags   : [if_bmi2,if_prot]
     flags   : [if_bmi2,if_prot]
   ),
   ),
+  (
+    opcode  : A_ADCX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #241#3#15#56#246#72;
+    flags   : [if_adx]
+  ),
+  (
+    opcode  : A_ADOX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #219#3#15#56#246#72;
+    flags   : [if_adx]
+  ),
   (
   (
     opcode  : A_VBROADCASTI128;
     opcode  : A_VBROADCASTI128;
     ops     : 2;
     ops     : 2;

+ 7 - 1
compiler/llvm/hlcgllvm.pas

@@ -591,8 +591,14 @@ implementation
 
 
 
 
   procedure thlcgllvm.a_load_const_reg(list: TAsmList; tosize: tdef; a: tcgint; register: tregister);
   procedure thlcgllvm.a_load_const_reg(list: TAsmList; tosize: tdef; a: tcgint; register: tregister);
+    var
+      fromsize: tdef;
     begin
     begin
-      list.concat(taillvm.op_reg_size_const_size(llvmconvop(ptrsinttype,tosize,false),register,ptrsinttype,a,tosize))
+      if tosize.size<=ptrsinttype.size then
+        fromsize:=ptrsinttype
+      else
+        fromsize:=tosize;
+      list.concat(taillvm.op_reg_size_const_size(llvmconvop(fromsize,tosize,false),register,fromsize,a,tosize))
     end;
     end;
 
 
 
 

+ 4 - 2
compiler/nadd.pas

@@ -3694,7 +3694,7 @@ implementation
                    we're done here }
                    we're done here }
                  expectloc:=LOC_REGISTER;
                  expectloc:=LOC_REGISTER;
                end
                end
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
               { is there a 64 bit type ? }
               { is there a 64 bit type ? }
              else if (torddef(ld).ordtype in [s64bit,u64bit,scurrency]) then
              else if (torddef(ld).ordtype in [s64bit,u64bit,scurrency]) then
                begin
                begin
@@ -3706,7 +3706,7 @@ implementation
                   else
                   else
                     expectloc:=LOC_JUMP;
                     expectloc:=LOC_JUMP;
                end
                end
-{$endif cpu64bitalu}
+{$endif not(cpu64bitalu) and not(cpuhighleveltarget)}
              { generic 32bit conversion }
              { generic 32bit conversion }
              else
              else
                begin
                begin
@@ -3740,8 +3740,10 @@ implementation
 {$endif cpuneedsmulhelper}
 {$endif cpuneedsmulhelper}
                   if nodetype in [addn,subn,muln,andn,orn,xorn] then
                   if nodetype in [addn,subn,muln,andn,orn,xorn] then
                     expectloc:=LOC_REGISTER
                     expectloc:=LOC_REGISTER
+{$if not defined(cpuhighleveltarget)}
                   else if torddef(ld).size>sizeof(aint) then
                   else if torddef(ld).size>sizeof(aint) then
                     expectloc:=LOC_JUMP
                     expectloc:=LOC_JUMP
+{$endif}
                   else
                   else
                     expectloc:=LOC_FLAGS;
                     expectloc:=LOC_FLAGS;
               end;
               end;

+ 5 - 5
compiler/ncgadd.pas

@@ -146,7 +146,7 @@ interface
     procedure tcgaddnode.set_result_location_reg;
     procedure tcgaddnode.set_result_location_reg;
       begin
       begin
         location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
         location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
         if location.size in [OS_64,OS_S64] then
         if location.size in [OS_64,OS_S64] then
           begin
           begin
             location.register64.reglo := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
             location.register64.reglo := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
@@ -435,7 +435,7 @@ interface
               else
               else
                  internalerror(200203247);
                  internalerror(200203247);
             end;
             end;
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
             if right.location.size in [OS_64,OS_S64] then
             if right.location.size in [OS_64,OS_S64] then
               begin
               begin
                 if right.location.loc <> LOC_CONSTANT then
                 if right.location.loc <> LOC_CONSTANT then
@@ -522,7 +522,7 @@ interface
           (right.resultdef.typ<>pointerdef) and
           (right.resultdef.typ<>pointerdef) and
           (cs_check_overflow in current_settings.localswitches) and not(nf_internal in flags);
           (cs_check_overflow in current_settings.localswitches) and not(nf_internal in flags);
 
 
-{$ifdef cpu64bitalu}
+{$if defined(cpu64bitalu) or defined(cpuhighleveltarget)}
         case nodetype of
         case nodetype of
           xorn,orn,andn,addn:
           xorn,orn,andn,addn:
             begin
             begin
@@ -563,7 +563,7 @@ interface
           else
           else
             internalerror(2002072803);
             internalerror(2002072803);
         end;
         end;
-{$else cpu64bitalu}
+{$else cpu64bitalu or cpuhighleveltarget}
         case nodetype of
         case nodetype of
           xorn,orn,andn,addn:
           xorn,orn,andn,addn:
             begin
             begin
@@ -609,7 +609,7 @@ interface
           else
           else
             internalerror(2002072803);
             internalerror(2002072803);
         end;
         end;
-{$endif cpu64bitalu}
+{$endif cpu64bitalu or cpuhighleveltarget}
 
 
         { emit overflow check if enabled }
         { emit overflow check if enabled }
         if checkoverflow then
         if checkoverflow then

+ 3 - 3
compiler/ncgbas.pas

@@ -625,14 +625,14 @@ interface
                 begin
                 begin
                   { make sure the register allocator doesn't reuse the }
                   { make sure the register allocator doesn't reuse the }
                   { register e.g. in the middle of a loop              }
                   { register e.g. in the middle of a loop              }
-{$if defined(cpu32bitalu)}
+{$if defined(cpu32bitalu) and not defined(cpuhighleveltarget)}
                   if tempinfo^.location.size in [OS_64,OS_S64] then
                   if tempinfo^.location.size in [OS_64,OS_S64] then
                     begin
                     begin
                       cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
                       cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
                       cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reglo);
                       cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reglo);
                     end
                     end
                   else
                   else
-{$elseif defined(cpu16bitalu)}
+{$elseif defined(cpu16bitalu) and not defined(cpuhighleveltarget)}
                   if tempinfo^.location.size in [OS_64,OS_S64] then
                   if tempinfo^.location.size in [OS_64,OS_S64] then
                     begin
                     begin
                       cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
                       cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
@@ -647,7 +647,7 @@ interface
                       cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register));
                       cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register));
                     end
                     end
                   else
                   else
-{$elseif defined(cpu8bitalu)}
+{$elseif defined(cpu8bitalu) and not defined(cpuhighleveltarget)}
                   if tempinfo^.location.size in [OS_64,OS_S64] then
                   if tempinfo^.location.size in [OS_64,OS_S64] then
                     begin
                     begin
                       cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
                       cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);

+ 1 - 1
compiler/ncgcal.pas

@@ -611,7 +611,7 @@ implementation
             case location.loc of
             case location.loc of
               LOC_REGISTER :
               LOC_REGISTER :
                 begin
                 begin
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                   if location.size in [OS_64,OS_S64] then
                   if location.size in [OS_64,OS_S64] then
                     cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,location.register64,funcretnode.location)
                     cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,location.register64,funcretnode.location)
                   else
                   else

+ 2 - 2
compiler/ncgcnv.pas

@@ -248,7 +248,7 @@ interface
             end;
             end;
           LOC_REGISTER,LOC_CREGISTER :
           LOC_REGISTER,LOC_CREGISTER :
             begin
             begin
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
               if left.location.size in [OS_64,OS_S64] then
               if left.location.size in [OS_64,OS_S64] then
                begin
                begin
                  hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
                  hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
@@ -256,7 +256,7 @@ interface
                  cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reghi,hregister);
                  cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reghi,hregister);
                end
                end
               else
               else
-{$endif cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                begin
                begin
                  cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register);
                  cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register);
                end;
                end;

+ 3 - 3
compiler/ncgcon.pas

@@ -188,11 +188,11 @@ implementation
     procedure tcgordconstnode.pass_generate_code;
     procedure tcgordconstnode.pass_generate_code;
       begin
       begin
          location_reset(location,LOC_CONSTANT,def_cgsize(resultdef));
          location_reset(location,LOC_CONSTANT,def_cgsize(resultdef));
-{$ifdef cpu64bitalu}
+{$if defined(cpu64bitalu) or defined(cpuhighleveltarget)}
          location.value:=value.svalue;
          location.value:=value.svalue;
-{$else cpu64bitalu}
+{$else cpu64bitalu or cpuhighleveltarget}
          location.value64:=value.svalue;
          location.value64:=value.svalue;
-{$endif cpu64bitalu}
+{$endif cpu64bitalu or cpuhighleveltarget}
       end;
       end;
 
 
 
 

+ 32 - 32
compiler/ncginl.pas

@@ -82,9 +82,9 @@ implementation
       ncon,ncal,
       ncon,ncal,
       tgobj,ncgutil,
       tgobj,ncgutil,
       cgutils,cgobj,hlcgobj
       cgutils,cgobj,hlcgobj
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
       ,cg64f32
       ,cg64f32
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
       ;
       ;
 
 
 
 
@@ -322,7 +322,7 @@ implementation
         if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
         if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
           hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
           hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
 
 
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
         if def_cgsize(resultdef) in [OS_64,OS_S64] then
         if def_cgsize(resultdef) in [OS_64,OS_S64] then
           begin
           begin
             location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
             location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
@@ -330,7 +330,7 @@ implementation
             cg64.a_op64_const_reg_reg(current_asmdata.CurrAsmList,cgop,def_cgsize(resultdef),1,left.location.register64,location.register64);
             cg64.a_op64_const_reg_reg(current_asmdata.CurrAsmList,cgop,def_cgsize(resultdef),1,left.location.register64,location.register64);
           end
           end
         else
         else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
           begin
           begin
             location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);
             location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);
             hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,resultdef,1,left.location.register,location.register);
             hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,resultdef,1,left.location.register,location.register);
@@ -352,17 +352,17 @@ implementation
         var
         var
          addvalue : TConstExprInt;
          addvalue : TConstExprInt;
          addconstant : boolean;
          addconstant : boolean;
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
          hregisterhi,
          hregisterhi,
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
          hregister : tregister;
          hregister : tregister;
         begin
         begin
           { set defaults }
           { set defaults }
           addconstant:=true;
           addconstant:=true;
           hregister:=NR_NO;
           hregister:=NR_NO;
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
           hregisterhi:=NR_NO;
           hregisterhi:=NR_NO;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
 
 
           { first secondpass second argument, because if the first arg }
           { first secondpass second argument, because if the first arg }
           { is used in that expression then SSL may move it to another }
           { is used in that expression then SSL may move it to another }
@@ -398,9 +398,9 @@ implementation
                 begin
                 begin
                   hlcg.location_force_reg(current_asmdata.CurrAsmList,tcallparanode(tcallparanode(left).right).left.location,tcallparanode(tcallparanode(left).right).left.resultdef,second_incdec_tempregdef,addvalue<=1);
                   hlcg.location_force_reg(current_asmdata.CurrAsmList,tcallparanode(tcallparanode(left).right).left.location,tcallparanode(tcallparanode(left).right).left.resultdef,second_incdec_tempregdef,addvalue<=1);
                   hregister:=tcallparanode(tcallparanode(left).right).left.location.register;
                   hregister:=tcallparanode(tcallparanode(left).right).left.location.register;
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                   hregisterhi:=tcallparanode(tcallparanode(left).right).left.location.register64.reghi;
                   hregisterhi:=tcallparanode(tcallparanode(left).right).left.location.register64.reghi;
-{$endif not cpu64bitalu}
+{$endif not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                   { insert multiply with addvalue if its >1 }
                   { insert multiply with addvalue if its >1 }
                   if addvalue>1 then
                   if addvalue>1 then
                     hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_IMUL,left.resultdef,addvalue.svalue,hregister);
                     hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_IMUL,left.resultdef,addvalue.svalue,hregister);
@@ -410,11 +410,11 @@ implementation
           { write the add instruction }
           { write the add instruction }
           if addconstant then
           if addconstant then
             begin
             begin
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
               if def_cgsize(left.resultdef) in [OS_64,OS_S64] then
               if def_cgsize(left.resultdef) in [OS_64,OS_S64] then
                 cg64.a_op64_const_loc(current_asmdata.CurrAsmList,addsubop[inlinenumber],def_cgsize(left.resultdef),addvalue,tcallparanode(left).left.location)
                 cg64.a_op64_const_loc(current_asmdata.CurrAsmList,addsubop[inlinenumber],def_cgsize(left.resultdef),addvalue,tcallparanode(left).left.location)
               else
               else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                 hlcg.a_op_const_loc(current_asmdata.CurrAsmList,addsubop[inlinenumber],left.resultdef,
                 hlcg.a_op_const_loc(current_asmdata.CurrAsmList,addsubop[inlinenumber],left.resultdef,
 {$ifdef cpu64bitalu}
 {$ifdef cpu64bitalu}
                   aint(addvalue.svalue),
                   aint(addvalue.svalue),
@@ -425,12 +425,12 @@ implementation
             end
             end
            else
            else
              begin
              begin
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                if def_cgsize(left.resultdef) in [OS_64,OS_S64] then
                if def_cgsize(left.resultdef) in [OS_64,OS_S64] then
                  cg64.a_op64_reg_loc(current_asmdata.CurrAsmList,addsubop[inlinenumber],def_cgsize(left.resultdef),
                  cg64.a_op64_reg_loc(current_asmdata.CurrAsmList,addsubop[inlinenumber],def_cgsize(left.resultdef),
                    joinreg64(hregister,hregisterhi),tcallparanode(left).left.location)
                    joinreg64(hregister,hregisterhi),tcallparanode(left).left.location)
                else
                else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                  hlcg.a_op_reg_loc(current_asmdata.CurrAsmList,addsubop[inlinenumber],left.resultdef,
                  hlcg.a_op_reg_loc(current_asmdata.CurrAsmList,addsubop[inlinenumber],left.resultdef,
                    hregister,tcallparanode(left).left.location);
                    hregister,tcallparanode(left).left.location);
              end;
              end;
@@ -464,18 +464,18 @@ implementation
         var
         var
           maskvalue : TConstExprInt;
           maskvalue : TConstExprInt;
           maskconstant : boolean;
           maskconstant : boolean;
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
           hregisterhi,
           hregisterhi,
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
           hregister : tregister;
           hregister : tregister;
         begin
         begin
           { set defaults }
           { set defaults }
           maskconstant:=true;
           maskconstant:=true;
           hregister:=NR_NO;
           hregister:=NR_NO;
           maskvalue:=0;
           maskvalue:=0;
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
           hregisterhi:=NR_NO;
           hregisterhi:=NR_NO;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
 
 
           { first secondpass first argument, because if the second arg }
           { first secondpass first argument, because if the second arg }
           { is used in that expression then SSL may move it to another }
           { is used in that expression then SSL may move it to another }
@@ -495,9 +495,9 @@ implementation
               else
               else
                 hlcg.location_force_reg(current_asmdata.CurrAsmList,tcallparanode(left).left.location,tcallparanode(left).left.resultdef,tcallparanode(left).right.resultdef,true);
                 hlcg.location_force_reg(current_asmdata.CurrAsmList,tcallparanode(left).left.location,tcallparanode(left).left.resultdef,tcallparanode(left).right.resultdef,true);
               hregister:=tcallparanode(left).left.location.register;
               hregister:=tcallparanode(left).left.location.register;
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
               hregisterhi:=tcallparanode(left).left.location.register64.reghi;
               hregisterhi:=tcallparanode(left).left.location.register64.reghi;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
               maskconstant:=false;
               maskconstant:=false;
             end;
             end;
           { write the and/or/xor/sar/shl/shr/rol/ror instruction }
           { write the and/or/xor/sar/shl/shr/rol/ror instruction }
@@ -508,11 +508,11 @@ implementation
                   maskvalue:=maskvalue and 63
                   maskvalue:=maskvalue and 63
                 else
                 else
                   maskvalue:=maskvalue and 31;
                   maskvalue:=maskvalue and 31;
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
               if def_cgsize(tcallparanode(left).right.resultdef) in [OS_64,OS_S64] then
               if def_cgsize(tcallparanode(left).right.resultdef) in [OS_64,OS_S64] then
                 cg64.a_op64_const_loc(current_asmdata.CurrAsmList,andorxorop[inlinenumber],def_cgsize(tcallparanode(left).right.resultdef),maskvalue.svalue,tcallparanode(tcallparanode(left).right).left.location)
                 cg64.a_op64_const_loc(current_asmdata.CurrAsmList,andorxorop[inlinenumber],def_cgsize(tcallparanode(left).right.resultdef),maskvalue.svalue,tcallparanode(tcallparanode(left).right).left.location)
               else
               else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                 hlcg.a_op_const_loc(current_asmdata.CurrAsmList,andorxorop[inlinenumber],tcallparanode(left).right.resultdef,
                 hlcg.a_op_const_loc(current_asmdata.CurrAsmList,andorxorop[inlinenumber],tcallparanode(left).right.resultdef,
 {$ifdef cpu64bitalu}
 {$ifdef cpu64bitalu}
                   aint(maskvalue.svalue),
                   aint(maskvalue.svalue),
@@ -523,12 +523,12 @@ implementation
             end
             end
            else
            else
              begin
              begin
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                if def_cgsize(tcallparanode(left).right.resultdef) in [OS_64,OS_S64] then
                if def_cgsize(tcallparanode(left).right.resultdef) in [OS_64,OS_S64] then
                  cg64.a_op64_reg_loc(current_asmdata.CurrAsmList,andorxorop[inlinenumber],def_cgsize(tcallparanode(left).right.resultdef),
                  cg64.a_op64_reg_loc(current_asmdata.CurrAsmList,andorxorop[inlinenumber],def_cgsize(tcallparanode(left).right.resultdef),
                    joinreg64(hregister,hregisterhi),tcallparanode(tcallparanode(left).right).left.location)
                    joinreg64(hregister,hregisterhi),tcallparanode(tcallparanode(left).right).left.location)
                else
                else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                  hlcg.a_op_reg_loc(current_asmdata.CurrAsmList,andorxorop[inlinenumber],tcallparanode(left).right.resultdef,
                  hlcg.a_op_reg_loc(current_asmdata.CurrAsmList,andorxorop[inlinenumber],tcallparanode(left).right.resultdef,
                    hregister,tcallparanode(tcallparanode(left).right).left.location);
                    hregister,tcallparanode(tcallparanode(left).right).left.location);
              end;
              end;
@@ -828,33 +828,33 @@ implementation
         hlcg.location_force_reg(current_asmdata.CurrAsmList,op1.location,op1.resultdef,resultdef,true);
         hlcg.location_force_reg(current_asmdata.CurrAsmList,op1.location,op1.resultdef,resultdef,true);
 
 
         location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
         location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
         if def_cgsize(resultdef) in [OS_64,OS_S64] then
         if def_cgsize(resultdef) in [OS_64,OS_S64] then
           begin
           begin
             location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
             location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
             location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
             location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
           end
           end
         else
         else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
           location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
           location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
 
 
         if assigned(op2) then
         if assigned(op2) then
           begin
           begin
              { rotating by a constant directly coded: }
              { rotating by a constant directly coded: }
              if op2.nodetype=ordconstn then
              if op2.nodetype=ordconstn then
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                if def_cgsize(resultdef) in [OS_64,OS_S64] then
                if def_cgsize(resultdef) in [OS_64,OS_S64] then
                  cg64.a_op64_const_reg_reg(current_asmdata.CurrAsmList,op,def_cgsize(resultdef),
                  cg64.a_op64_const_reg_reg(current_asmdata.CurrAsmList,op,def_cgsize(resultdef),
                    tordconstnode(op2).value.uvalue and (resultdef.size*8-1),
                    tordconstnode(op2).value.uvalue and (resultdef.size*8-1),
                    op1.location.register64, location.register64)
                    op1.location.register64, location.register64)
                else
                else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                  hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,resultdef,
                  hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,resultdef,
                    tordconstnode(op2).value.uvalue and (resultdef.size*8-1),
                    tordconstnode(op2).value.uvalue and (resultdef.size*8-1),
                    op1.location.register, location.register)
                    op1.location.register, location.register)
              else
              else
                begin
                begin
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                  if def_cgsize(resultdef) in [OS_64,OS_S64] then
                  if def_cgsize(resultdef) in [OS_64,OS_S64] then
                    begin
                    begin
                      hlcg.location_force_reg(current_asmdata.CurrAsmList,op2.location,
                      hlcg.location_force_reg(current_asmdata.CurrAsmList,op2.location,
@@ -864,7 +864,7 @@ implementation
                                              location.register64);
                                              location.register64);
                    end
                    end
                  else
                  else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                    begin
                    begin
                      hlcg.location_force_reg(current_asmdata.CurrAsmList,op2.location,
                      hlcg.location_force_reg(current_asmdata.CurrAsmList,op2.location,
                                              op2.resultdef,resultdef,true);
                                              op2.resultdef,resultdef,true);
@@ -875,12 +875,12 @@ implementation
                end;
                end;
           end
           end
         else
         else
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
           if def_cgsize(resultdef) in [OS_64,OS_S64] then
           if def_cgsize(resultdef) in [OS_64,OS_S64] then
             cg64.a_op64_const_reg_reg(current_asmdata.CurrAsmList,op,def_cgsize(resultdef),1,
             cg64.a_op64_const_reg_reg(current_asmdata.CurrAsmList,op,def_cgsize(resultdef),1,
                                       op1.location.register64,location.register64)
                                       op1.location.register64,location.register64)
           else
           else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
             hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,resultdef,1,
             hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,resultdef,1,
                                     op1.location.register,location.register);
                                     op1.location.register,location.register);
       end;
       end;

+ 22 - 27
compiler/ncgld.pas

@@ -330,8 +330,9 @@ implementation
                begin
                begin
                  { Load a pointer to the thread var record into a register. }
                  { Load a pointer to the thread var record into a register. }
                  { This register will be used in both multithreaded and non-multithreaded cases. }
                  { This register will be used in both multithreaded and non-multithreaded cases. }
-                 hreg_tv_rec:=hlcg.getaddressregister(current_asmdata.CurrAsmList,fieldptrdef);
-                 hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,fieldptrdef,tvref,hreg_tv_rec);
+                 hreg_tv_rec:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cpointerdef.getreusable(tv_rec));
+                 hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,tv_rec,cpointerdef.getreusable(tv_rec),tvref,hreg_tv_rec);
+                 reference_reset_base(tvref,hreg_tv_rec,0,ctempposinvalid,tvref.alignment,tvref.volatility)
                end;
                end;
              paraloc1.init;
              paraloc1.init;
              paramanager.getintparaloc(current_asmdata.CurrAsmList,tprocvardef(pvd),1,paraloc1);
              paramanager.getintparaloc(current_asmdata.CurrAsmList,tprocvardef(pvd),1,paraloc1);
@@ -346,8 +347,6 @@ implementation
              hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,
              hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,
                tv_rec,
                tv_rec,
                tfieldvarsym(tv_index_field),href);
                tfieldvarsym(tv_index_field),href);
-             if size_opt then
-               hlcg.reference_reset_base(href,tfieldvarsym(tv_index_field).vardef,hreg_tv_rec,href.offset,href.temppos,href.alignment,[]);
              hlcg.a_load_ref_cgpara(current_asmdata.CurrAsmList,tfieldvarsym(tv_index_field).vardef,href,paraloc1);
              hlcg.a_load_ref_cgpara(current_asmdata.CurrAsmList,tfieldvarsym(tv_index_field).vardef,href,paraloc1);
              { Dealloc the threadvar record register before calling the helper function to allow  }
              { Dealloc the threadvar record register before calling the helper function to allow  }
              { the register allocator to assign non-mandatory real registers for hreg_tv_rec. }
              { the register allocator to assign non-mandatory real registers for hreg_tv_rec. }
@@ -377,10 +376,6 @@ implementation
              hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,
              hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,
                tv_rec,
                tv_rec,
                tfieldvarsym(tv_non_mt_data_field),href);
                tfieldvarsym(tv_non_mt_data_field),href);
-             { load in the same "hregister" as above, so after this sequence
-               the address of the threadvar is always in hregister }
-             if size_opt then
-               hlcg.reference_reset_base(href,fieldptrdef,hreg_tv_rec,href.offset,href.temppos,href.alignment,[]);
              hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,fieldptrdef,href,hregister);
              hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,fieldptrdef,href,hregister);
              hlcg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
              hlcg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
 
 
@@ -695,7 +690,7 @@ implementation
          alignmentrequirement,
          alignmentrequirement,
          len : aint;
          len : aint;
          r : tregister;
          r : tregister;
-         {$if not defined(cpu64bitalu)}
+         {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
          r64 : tregister64;
          r64 : tregister64;
          {$endif}
          {$endif}
          oldflowcontrol : tflowcontrol;
          oldflowcontrol : tflowcontrol;
@@ -840,11 +835,11 @@ implementation
             case right.location.loc of
             case right.location.loc of
               LOC_CONSTANT :
               LOC_CONSTANT :
                 begin
                 begin
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                   if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
                   if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
                     cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
                     cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
                   else
                   else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                     hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,right.location.value,left.location);
                     hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,right.location.value,left.location);
                 end;
                 end;
               LOC_REFERENCE,
               LOC_REFERENCE,
@@ -952,11 +947,11 @@ implementation
                       hlcg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sreg);
                       hlcg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sreg);
                     LOC_SUBSETREF,
                     LOC_SUBSETREF,
                     LOC_CSUBSETREF:
                     LOC_CSUBSETREF:
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                       if right.location.size in [OS_64,OS_S64] then
                       if right.location.size in [OS_64,OS_S64] then
                        cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
                        cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
                       else
                       else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                        hlcg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sref);
                        hlcg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sref);
                     else
                     else
                       internalerror(200203284);
                       internalerror(200203284);
@@ -1055,11 +1050,11 @@ implementation
               LOC_SUBSETREF,
               LOC_SUBSETREF,
               LOC_CSUBSETREF:
               LOC_CSUBSETREF:
                 begin
                 begin
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                   if right.location.size in [OS_64,OS_S64] then
                   if right.location.size in [OS_64,OS_S64] then
                    cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
                    cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
                   else
                   else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                   hlcg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
                   hlcg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
                       right.resultdef,left.resultdef,right.location.sref,left.location);
                       right.resultdef,left.resultdef,right.location.sref,left.location);
                 end;
                 end;
@@ -1069,30 +1064,30 @@ implementation
                   hlcg.a_label(current_asmdata.CurrAsmList,right.location.truelabel);
                   hlcg.a_label(current_asmdata.CurrAsmList,right.location.truelabel);
                   if is_pasbool(left.resultdef) then
                   if is_pasbool(left.resultdef) then
                     begin
                     begin
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                       if left.location.size in [OS_64,OS_S64] then
                       if left.location.size in [OS_64,OS_S64] then
                         cg64.a_load64_const_loc(current_asmdata.CurrAsmList,1,left.location)
                         cg64.a_load64_const_loc(current_asmdata.CurrAsmList,1,left.location)
                       else
                       else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                         hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,1,left.location)
                         hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,1,left.location)
                     end
                     end
                   else
                   else
                     begin
                     begin
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                       if left.location.size in [OS_64,OS_S64] then
                       if left.location.size in [OS_64,OS_S64] then
                         cg64.a_load64_const_loc(current_asmdata.CurrAsmList,-1,left.location)
                         cg64.a_load64_const_loc(current_asmdata.CurrAsmList,-1,left.location)
                       else
                       else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                         hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,-1,left.location);
                         hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,-1,left.location);
                     end;
                     end;
 
 
                   hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
                   hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
                   hlcg.a_label(current_asmdata.CurrAsmList,right.location.falselabel);
                   hlcg.a_label(current_asmdata.CurrAsmList,right.location.falselabel);
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                   if left.location.size in [OS_64,OS_S64] then
                   if left.location.size in [OS_64,OS_S64] then
                     cg64.a_load64_const_loc(current_asmdata.CurrAsmList,0,left.location)
                     cg64.a_load64_const_loc(current_asmdata.CurrAsmList,0,left.location)
                   else
                   else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                     hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,0,left.location);
                     hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,0,left.location);
                   hlcg.a_label(current_asmdata.CurrAsmList,hlabel);
                   hlcg.a_label(current_asmdata.CurrAsmList,hlabel);
                 end;
                 end;
@@ -1103,7 +1098,7 @@ implementation
                     begin
                     begin
                       case left.location.loc of
                       case left.location.loc of
                         LOC_REGISTER,LOC_CREGISTER:
                         LOC_REGISTER,LOC_CREGISTER:
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                           if left.location.size in [OS_S64,OS_64] then
                           if left.location.size in [OS_S64,OS_64] then
                             begin
                             begin
                               cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,left.location.register64.reglo);
                               cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,left.location.register64.reglo);
@@ -1111,7 +1106,7 @@ implementation
                               cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,left.location.register64.reghi);
                               cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,left.location.register64.reghi);
                             end
                             end
                           else
                           else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                             begin
                             begin
                               cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.register);
                               cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.register);
                               cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                               cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
@@ -1119,7 +1114,7 @@ implementation
                         LOC_REFERENCE:
                         LOC_REFERENCE:
                         { i8086 and i386 have hacks in their code generators so that they can
                         { i8086 and i386 have hacks in their code generators so that they can
                           deal with 64 bit locations in this parcticular case }
                           deal with 64 bit locations in this parcticular case }
-{$if not defined(cpu64bitalu) and not defined(x86)}
+{$if not defined(cpu64bitalu) and not defined(x86) and not defined(cpuhighleveltarget)}
                           if left.location.size in [OS_S64,OS_64] then
                           if left.location.size in [OS_S64,OS_64] then
                             begin
                             begin
                               r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
                               r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
@@ -1130,7 +1125,7 @@ implementation
                               cg64.a_load64_reg_ref(current_asmdata.CurrAsmList,r64,left.location.reference);
                               cg64.a_load64_reg_ref(current_asmdata.CurrAsmList,r64,left.location.reference);
                             end
                             end
                           else
                           else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not x86 and not cpuhighleveltarget}
                             begin
                             begin
                               cg.g_flags2ref(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.reference);
                               cg.g_flags2ref(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.reference);
                               cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
                               cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
@@ -1148,7 +1143,7 @@ implementation
                     end
                     end
                   else
                   else
                     begin
                     begin
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
                       if left.location.size in [OS_S64,OS_64] then
                       if left.location.size in [OS_S64,OS_64] then
                         begin
                         begin
                           r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
                           r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
@@ -1161,7 +1156,7 @@ implementation
                           cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,r64,left.location);
                           cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,r64,left.location);
                         end
                         end
                       else
                       else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
                         begin
                         begin
                           r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
                           r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
                           cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
                           cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);

+ 24 - 24
compiler/ncgmat.pas

@@ -46,9 +46,9 @@ interface
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
          procedure second_mmx;virtual;abstract;
          procedure second_mmx;virtual;abstract;
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
          procedure second_64bit;virtual;
          procedure second_64bit;virtual;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
          procedure second_integer;virtual;
          procedure second_integer;virtual;
          procedure second_float;virtual;
          procedure second_float;virtual;
          procedure second_float_emulated;virtual;
          procedure second_float_emulated;virtual;
@@ -83,7 +83,7 @@ interface
            been done and emitted, so this should really a do a modulo.
            been done and emitted, so this should really a do a modulo.
          }
          }
          procedure emit_mod_reg_reg(signed: boolean;denum,num : tregister);virtual;abstract;
          procedure emit_mod_reg_reg(signed: boolean;denum,num : tregister);virtual;abstract;
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
          { This routine must do an actual 64-bit division, be it
          { This routine must do an actual 64-bit division, be it
            signed or unsigned. The result must set into the the
            signed or unsigned. The result must set into the the
            @var(num) register.
            @var(num) register.
@@ -98,16 +98,16 @@ interface
            64-bit systems, otherwise a helper is called in 1st pass.
            64-bit systems, otherwise a helper is called in 1st pass.
          }
          }
          procedure emit64_div_reg_reg(signed: boolean;denum,num : tregister64);virtual;
          procedure emit64_div_reg_reg(signed: boolean;denum,num : tregister64);virtual;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
       end;
       end;
 
 
       tcgshlshrnode = class(tshlshrnode)
       tcgshlshrnode = class(tshlshrnode)
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
          procedure second_mmx;virtual;abstract;
          procedure second_mmx;virtual;abstract;
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
          procedure second_64bit;virtual;
          procedure second_64bit;virtual;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
          procedure second_integer;virtual;
          procedure second_integer;virtual;
          procedure pass_generate_code;override;
          procedure pass_generate_code;override;
       end;
       end;
@@ -119,9 +119,9 @@ interface
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
          procedure second_mmx;virtual;abstract;
          procedure second_mmx;virtual;abstract;
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
          procedure second_64bit;virtual;
          procedure second_64bit;virtual;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
          procedure second_integer;virtual;
          procedure second_integer;virtual;
       public
       public
          procedure pass_generate_code;override;
          procedure pass_generate_code;override;
@@ -197,7 +197,7 @@ implementation
       end;
       end;
 
 
 
 
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
     procedure tcgunaryminusnode.second_64bit;
     procedure tcgunaryminusnode.second_64bit;
       var
       var
         tr: tregister;
         tr: tregister;
@@ -223,7 +223,7 @@ implementation
             cg.a_label(current_asmdata.CurrAsmList,hl);
             cg.a_label(current_asmdata.CurrAsmList,hl);
           end;
           end;
       end;
       end;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
 
 
 
 
     procedure tcgunaryminusnode.second_float_emulated;
     procedure tcgunaryminusnode.second_float_emulated;
@@ -319,11 +319,11 @@ implementation
 
 
     procedure tcgunaryminusnode.pass_generate_code;
     procedure tcgunaryminusnode.pass_generate_code;
       begin
       begin
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
          if is_64bit(left.resultdef) then
          if is_64bit(left.resultdef) then
            second_64bit
            second_64bit
          else
          else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}
            if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then
            if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then
              second_mmx
              second_mmx
@@ -345,7 +345,7 @@ implementation
                              TCGMODDIVNODE
                              TCGMODDIVNODE
 *****************************************************************************}
 *****************************************************************************}
 
 
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
     procedure tcgmoddivnode.emit64_div_reg_reg(signed: boolean; denum,num:tregister64);
     procedure tcgmoddivnode.emit64_div_reg_reg(signed: boolean; denum,num:tregister64);
       begin
       begin
         { handled in pass_1 already, unless pass_1 is
         { handled in pass_1 already, unless pass_1 is
@@ -354,7 +354,7 @@ implementation
         { should be handled in pass_1 (JM) }
         { should be handled in pass_1 (JM) }
         internalerror(200109052);
         internalerror(200109052);
       end;
       end;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
 
 
 
 
     procedure tcgmoddivnode.pass_generate_code;
     procedure tcgmoddivnode.pass_generate_code;
@@ -376,7 +376,7 @@ implementation
           exit;
           exit;
          location_copy(location,left.location);
          location_copy(location,left.location);
 
 
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
          if is_64bit(resultdef) then
          if is_64bit(resultdef) then
            begin
            begin
              if is_signed(left.resultdef) then
              if is_signed(left.resultdef) then
@@ -395,7 +395,7 @@ implementation
                joinreg64(location.register64.reglo,location.register64.reghi));
                joinreg64(location.register64.reglo,location.register64.reghi));
            end
            end
          else
          else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
            begin
            begin
               if is_signed(left.resultdef) then
               if is_signed(left.resultdef) then
                 begin
                 begin
@@ -475,13 +475,13 @@ implementation
 *****************************************************************************}
 *****************************************************************************}
 
 
 
 
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
     procedure tcgshlshrnode.second_64bit;
     procedure tcgshlshrnode.second_64bit;
       begin
       begin
          { already hanled in 1st pass }
          { already hanled in 1st pass }
          internalerror(2002081501);
          internalerror(2002081501);
       end;
       end;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
 
 
 
 
     procedure tcgshlshrnode.second_integer;
     procedure tcgshlshrnode.second_integer;
@@ -610,11 +610,11 @@ implementation
              second_mmx
              second_mmx
          else
          else
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
          if is_64bit(left.resultdef) then
          if is_64bit(left.resultdef) then
            second_64bit
            second_64bit
          else
          else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
            second_integer;
            second_integer;
       end;
       end;
 
 
@@ -623,7 +623,7 @@ implementation
                                TCGNOTNODE
                                TCGNOTNODE
 *****************************************************************************}
 *****************************************************************************}
 
 
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
     procedure tcgnotnode.second_64bit;
     procedure tcgnotnode.second_64bit;
       begin
       begin
         secondpass(left);
         secondpass(left);
@@ -635,7 +635,7 @@ implementation
         { perform the NOT operation }
         { perform the NOT operation }
         cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,OP_NOT,location.size,left.location.register64,location.register64);
         cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,OP_NOT,location.size,left.location.register64,location.register64);
       end;
       end;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
 
 
 
 
     procedure tcgnotnode.second_integer;
     procedure tcgnotnode.second_integer;
@@ -676,10 +676,10 @@ implementation
         else if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then
         else if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then
           second_mmx
           second_mmx
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
         else if is_64bit(left.resultdef) then
         else if is_64bit(left.resultdef) then
           second_64bit
           second_64bit
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
         else
         else
           second_integer;
           second_integer;
       end;
       end;

+ 12 - 6
compiler/ncgset.pas

@@ -755,16 +755,17 @@ implementation
 
 
       procedure genitem(t : pcaselabel);
       procedure genitem(t : pcaselabel);
 
 
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
         var
         var
            l1 : tasmlabel;
            l1 : tasmlabel;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
 
 
         begin
         begin
            if assigned(t^.less) then
            if assigned(t^.less) then
              genitem(t^.less);
              genitem(t^.less);
            if t^._low=t^._high then
            if t^._low=t^._high then
              begin
              begin
+{$ifndef cpuhighleveltarget}
 {$if defined(cpu32bitalu)}
 {$if defined(cpu32bitalu)}
                 if def_cgsize(opsize) in [OS_S64,OS_64] then
                 if def_cgsize(opsize) in [OS_S64,OS_64] then
                   begin
                   begin
@@ -824,6 +825,7 @@ implementation
                   end
                   end
                 else
                 else
 {$endif}
 {$endif}
+{$endif cpuhighleveltarget}
                   begin
                   begin
                      hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, OC_EQ, aint(t^._low.svalue),hregister, blocklabel(t^.blockid));
                      hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, OC_EQ, aint(t^._low.svalue),hregister, blocklabel(t^.blockid));
                   end;
                   end;
@@ -838,6 +840,7 @@ implementation
                 { ELSE-label                                }
                 { ELSE-label                                }
                 if not lastwasrange or (t^._low-last>1) then
                 if not lastwasrange or (t^._low-last>1) then
                   begin
                   begin
+{$ifndef cpuhighleveltarget}
 {$if defined(cpu32bitalu)}
 {$if defined(cpu32bitalu)}
                      if def_cgsize(opsize) in [OS_64,OS_S64] then
                      if def_cgsize(opsize) in [OS_64,OS_S64] then
                        begin
                        begin
@@ -929,11 +932,13 @@ implementation
                        end
                        end
                      else
                      else
 {$endif}
 {$endif}
+{$endif cpuhighleveltarget}
                        begin
                        begin
                         hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, jmp_lt, aint(t^._low.svalue), hregister,
                         hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, jmp_lt, aint(t^._low.svalue), hregister,
                            elselabel);
                            elselabel);
                        end;
                        end;
                   end;
                   end;
+{$ifndef cpuhighleveltarget}
 {$if defined(cpu32bitalu)}
 {$if defined(cpu32bitalu)}
                 if def_cgsize(opsize) in [OS_S64,OS_64] then
                 if def_cgsize(opsize) in [OS_S64,OS_64] then
                   begin
                   begin
@@ -1019,6 +1024,7 @@ implementation
                   end
                   end
                 else
                 else
 {$endif}
 {$endif}
+{$endif cpuhighleveltarget}
                   begin
                   begin
                      hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, jmp_le, aint(t^._high.svalue), hregister, blocklabel(t^.blockid));
                      hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, jmp_le, aint(t^._high.svalue), hregister, blocklabel(t^.blockid));
                   end;
                   end;
@@ -1200,14 +1206,14 @@ implementation
          opsize:=left.resultdef;
          opsize:=left.resultdef;
          { copy the case expression to a register }
          { copy the case expression to a register }
          hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opsize,false);
          hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opsize,false);
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu)}
          if def_cgsize(opsize) in [OS_S64,OS_64] then
          if def_cgsize(opsize) in [OS_S64,OS_64] then
            begin
            begin
              hregister:=left.location.register64.reglo;
              hregister:=left.location.register64.reglo;
              hregister2:=left.location.register64.reghi;
              hregister2:=left.location.register64.reghi;
            end
            end
          else
          else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
            hregister:=left.location.register;
            hregister:=left.location.register;
 
 
          { we need the min_label always to choose between }
          { we need the min_label always to choose between }
@@ -1218,11 +1224,11 @@ implementation
 {$ifdef OLDREGVARS}
 {$ifdef OLDREGVARS}
          load_all_regvars(current_asmdata.CurrAsmList);
          load_all_regvars(current_asmdata.CurrAsmList);
 {$endif OLDREGVARS}
 {$endif OLDREGVARS}
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu)}
          if def_cgsize(opsize) in [OS_64,OS_S64] then
          if def_cgsize(opsize) in [OS_64,OS_S64] then
            genlinearcmplist(labels)
            genlinearcmplist(labels)
          else
          else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
            begin
            begin
               labelcnt := 0;
               labelcnt := 0;
               TrueCount := 0;
               TrueCount := 0;

+ 25 - 646
compiler/ncgutil.pas

@@ -31,9 +31,9 @@ interface
       cpubase,cgbase,parabase,cgutils,
       cpubase,cgbase,parabase,cgutils,
       aasmbase,aasmtai,aasmdata,aasmcpu,
       aasmbase,aasmtai,aasmdata,aasmcpu,
       symconst,symbase,symdef,symsym,symtype
       symconst,symbase,symdef,symsym,symtype
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
       ,cg64f32
       ,cg64f32
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
       ;
       ;
 
 
     type
     type
@@ -63,10 +63,6 @@ interface
     procedure location_force_mmreg(list:TAsmList;var l: tlocation;maybeconst:boolean);
     procedure location_force_mmreg(list:TAsmList;var l: tlocation;maybeconst:boolean);
     procedure location_allocate_register(list:TAsmList;out l: tlocation;def: tdef;constant: boolean);
     procedure location_allocate_register(list:TAsmList;out l: tlocation;def: tdef;constant: boolean);
 
 
-    { loads a cgpara into a tlocation; assumes that loc.loc is already
-      initialised }
-    procedure gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean);
-
     { allocate registers for a tlocation; assumes that loc.loc is already
     { allocate registers for a tlocation; assumes that loc.loc is already
       set to LOC_CREGISTER/LOC_CFPUREGISTER/... }
       set to LOC_CREGISTER/LOC_CFPUREGISTER/... }
     procedure gen_alloc_regloc(list:TAsmList;var loc: tlocation;def: tdef);
     procedure gen_alloc_regloc(list:TAsmList;var loc: tlocation;def: tdef);
@@ -80,7 +76,6 @@ interface
     procedure gen_proc_exit_code(list:TAsmList);
     procedure gen_proc_exit_code(list:TAsmList);
     procedure gen_save_used_regs(list:TAsmList);
     procedure gen_save_used_regs(list:TAsmList);
     procedure gen_restore_used_regs(list:TAsmList);
     procedure gen_restore_used_regs(list:TAsmList);
-    procedure gen_load_para_value(list:TAsmList);
 
 
     procedure get_used_regvars(n: tnode; var rv: tusedregvars);
     procedure get_used_regvars(n: tnode; var rv: tusedregvars);
     { adds the regvars used in n and its children to rv.allregvars,
     { adds the regvars used in n and its children to rv.allregvars,
@@ -101,6 +96,9 @@ interface
 
 
     procedure gen_load_frame_for_exceptfilter(list : TAsmList);
     procedure gen_load_frame_for_exceptfilter(list : TAsmList);
 
 
+   procedure gen_alloc_regvar(list:TAsmList;sym: tabstractnormalvarsym; allocreg: boolean);
+
+
 implementation
 implementation
 
 
   uses
   uses
@@ -138,7 +136,7 @@ implementation
           LOC_REGISTER,
           LOC_REGISTER,
           LOC_CREGISTER:
           LOC_CREGISTER:
             begin
             begin
-{$ifdef cpu64bitalu}
+{$if defined(cpu64bitalu)}
                 { x86-64 system v abi:
                 { x86-64 system v abi:
                   structs with up to 16 bytes are returned in registers }
                   structs with up to 16 bytes are returned in registers }
                 if location.size in [OS_128,OS_S128] then
                 if location.size in [OS_128,OS_S128] then
@@ -148,7 +146,8 @@ implementation
                     if getsupreg(location.registerhi)<first_int_imreg then
                     if getsupreg(location.registerhi)<first_int_imreg then
                       cg.ungetcpuregister(list,location.registerhi);
                       cg.ungetcpuregister(list,location.registerhi);
                   end
                   end
-{$else cpu64bitalu}
+                else
+{$elseif not defined(cpuhighleveltarget)}
                 if location.size in [OS_64,OS_S64] then
                 if location.size in [OS_64,OS_S64] then
                   begin
                   begin
                     if getsupreg(location.register64.reglo)<first_int_imreg then
                     if getsupreg(location.register64.reglo)<first_int_imreg then
@@ -156,8 +155,8 @@ implementation
                     if getsupreg(location.register64.reghi)<first_int_imreg then
                     if getsupreg(location.register64.reghi)<first_int_imreg then
                       cg.ungetcpuregister(list,location.register64.reghi);
                       cg.ungetcpuregister(list,location.register64.reghi);
                   end
                   end
-{$endif cpu64bitalu}
                 else
                 else
+{$endif cpu64bitalu and not cpuhighleveltarget}
                   if getsupreg(location.register)<first_int_imreg then
                   if getsupreg(location.register)<first_int_imreg then
                     cg.ungetcpuregister(list,location.register);
                     cg.ungetcpuregister(list,location.register);
             end;
             end;
@@ -292,7 +291,7 @@ implementation
                        end;
                        end;
                      LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
                      LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
                        begin
                        begin
-{$ifdef cpu64bitalu}
+{$if defined(cpu64bitalu)}
                          if opsize in [OS_128,OS_S128] then
                          if opsize in [OS_128,OS_S128] then
                            begin
                            begin
                              hlcg.location_force_reg(list,p.location,p.resultdef,cgsize_orddef(opsize),true);
                              hlcg.location_force_reg(list,p.location,p.resultdef,cgsize_orddef(opsize),true);
@@ -302,7 +301,7 @@ implementation
                              p.location.register:=tmpreg;
                              p.location.register:=tmpreg;
                              opsize:=OS_64;
                              opsize:=OS_64;
                            end;
                            end;
-{$else cpu64bitalu}
+{$elseif not defined(cpuhighleveltarget)}
                          if opsize in [OS_64,OS_S64] then
                          if opsize in [OS_64,OS_S64] then
                            begin
                            begin
                              hlcg.location_force_reg(list,p.location,p.resultdef,cgsize_orddef(opsize),true);
                              hlcg.location_force_reg(list,p.location,p.resultdef,cgsize_orddef(opsize),true);
@@ -312,7 +311,7 @@ implementation
                              p.location.register:=tmpreg;
                              p.location.register:=tmpreg;
                              opsize:=OS_32;
                              opsize:=OS_32;
                            end;
                            end;
-{$endif cpu64bitalu}
+{$endif cpu64bitalu and not cpuhighleveltarget}
                          cg.a_cmp_const_loc_label(list,opsize,OC_NE,0,p.location,truelabel);
                          cg.a_cmp_const_loc_label(list,opsize,OC_NE,0,p.location,truelabel);
                          cg.a_jmp_always(list,falselabel);
                          cg.a_jmp_always(list,falselabel);
                        end;
                        end;
@@ -456,21 +455,21 @@ implementation
               location_reset(l,LOC_CREGISTER,l.size)
               location_reset(l,LOC_CREGISTER,l.size)
             else
             else
               location_reset(l,LOC_REGISTER,l.size);
               location_reset(l,LOC_REGISTER,l.size);
-{$ifdef cpu64bitalu}
+{$if defined(cpu64bitalu)}
             if l.size in [OS_128,OS_S128,OS_F128] then
             if l.size in [OS_128,OS_S128,OS_F128] then
               begin
               begin
                 l.register128.reglo:=cg.getintregister(list,OS_64);
                 l.register128.reglo:=cg.getintregister(list,OS_64);
                 l.register128.reghi:=cg.getintregister(list,OS_64);
                 l.register128.reghi:=cg.getintregister(list,OS_64);
               end
               end
             else
             else
-{$else cpu64bitalu}
+{$elseif not defined(cpuhighleveltarget)}
             if l.size in [OS_64,OS_S64,OS_F64] then
             if l.size in [OS_64,OS_S64,OS_F64] then
               begin
               begin
                 l.register64.reglo:=cg.getintregister(list,OS_32);
                 l.register64.reglo:=cg.getintregister(list,OS_32);
                 l.register64.reghi:=cg.getintregister(list,OS_32);
                 l.register64.reghi:=cg.getintregister(list,OS_32);
               end
               end
             else
             else
-{$endif cpu64bitalu}
+{$endif cpu64bitalu and not cpuhighleveltarget}
             { Note: for widths of records (and maybe objects, classes, etc.) an
             { Note: for widths of records (and maybe objects, classes, etc.) an
                     address register could be set here, but that is later
                     address register could be set here, but that is later
                     changed to an intregister neverthless when in the
                     changed to an intregister neverthless when in the
@@ -556,21 +555,21 @@ implementation
         case loc.loc of
         case loc.loc of
           LOC_CREGISTER:
           LOC_CREGISTER:
             begin
             begin
-{$ifdef cpu64bitalu}
+{$if defined(cpu64bitalu)}
               if loc.size in [OS_128,OS_S128] then
               if loc.size in [OS_128,OS_S128] then
                 begin
                 begin
                   loc.register128.reglo:=cg.getintregister(list,OS_64);
                   loc.register128.reglo:=cg.getintregister(list,OS_64);
                   loc.register128.reghi:=cg.getintregister(list,OS_64);
                   loc.register128.reghi:=cg.getintregister(list,OS_64);
                 end
                 end
               else
               else
-{$else cpu64bitalu}
+{$elseif not defined(cpuhighleveltarget)}
               if loc.size in [OS_64,OS_S64] then
               if loc.size in [OS_64,OS_S64] then
                 begin
                 begin
                   loc.register64.reglo:=cg.getintregister(list,OS_32);
                   loc.register64.reglo:=cg.getintregister(list,OS_32);
                   loc.register64.reghi:=cg.getintregister(list,OS_32);
                   loc.register64.reghi:=cg.getintregister(list,OS_32);
                 end
                 end
               else
               else
-{$endif cpu64bitalu}
+{$endif cpu64bitalu and not cpuhighleveltarget}
                 if hlcg.def2regtyp(def)=R_ADDRESSREGISTER then
                 if hlcg.def2regtyp(def)=R_ADDRESSREGISTER then
                   loc.register:=hlcg.getaddressregister(list,def)
                   loc.register:=hlcg.getaddressregister(list,def)
                 else
                 else
@@ -612,14 +611,14 @@ implementation
                 cg.a_reg_sync(list,sym.initialloc.register128.reghi);
                 cg.a_reg_sync(list,sym.initialloc.register128.reghi);
               end
               end
             else
             else
-{$elseif defined(cpu32bitalu)}
+{$elseif defined(cpu32bitalu) and not defined(cpuhighleveltarget)}
             if sym.initialloc.size in [OS_64,OS_S64] then
             if sym.initialloc.size in [OS_64,OS_S64] then
               begin
               begin
                 cg.a_reg_sync(list,sym.initialloc.register64.reglo);
                 cg.a_reg_sync(list,sym.initialloc.register64.reglo);
                 cg.a_reg_sync(list,sym.initialloc.register64.reghi);
                 cg.a_reg_sync(list,sym.initialloc.register64.reghi);
               end
               end
             else
             else
-{$elseif defined(cpu16bitalu)}
+{$elseif defined(cpu16bitalu) and not defined(cpuhighleveltarget)}
             if sym.initialloc.size in [OS_64,OS_S64] then
             if sym.initialloc.size in [OS_64,OS_S64] then
               begin
               begin
                 cg.a_reg_sync(list,sym.initialloc.register64.reglo);
                 cg.a_reg_sync(list,sym.initialloc.register64.reglo);
@@ -634,7 +633,7 @@ implementation
                 cg.a_reg_sync(list,cg.GetNextReg(sym.initialloc.register));
                 cg.a_reg_sync(list,cg.GetNextReg(sym.initialloc.register));
               end
               end
             else
             else
-{$elseif defined(cpu8bitalu)}
+{$elseif defined(cpu8bitalu) and not defined(cpuhighleveltarget)}
             if sym.initialloc.size in [OS_64,OS_S64] then
             if sym.initialloc.size in [OS_64,OS_S64] then
               begin
               begin
                 cg.a_reg_sync(list,sym.initialloc.register64.reglo);
                 cg.a_reg_sync(list,sym.initialloc.register64.reglo);
@@ -664,640 +663,20 @@ implementation
 {$endif}
 {$endif}
              cg.a_reg_sync(list,sym.initialloc.register);
              cg.a_reg_sync(list,sym.initialloc.register);
           end;
           end;
-{$ifdef cpu64bitalu}
+{$if defined(cpu64bitalu)}
         if (sym.initialloc.size in [OS_128,OS_S128]) then
         if (sym.initialloc.size in [OS_128,OS_S128]) then
           varloc:=tai_varloc.create128(sym,sym.initialloc.register,sym.initialloc.registerhi)
           varloc:=tai_varloc.create128(sym,sym.initialloc.register,sym.initialloc.registerhi)
-{$else cpu64bitalu}
+        else
+{$elseif not defined(cpuhighleveltarget)}
         if (sym.initialloc.size in [OS_64,OS_S64]) then
         if (sym.initialloc.size in [OS_64,OS_S64]) then
           varloc:=tai_varloc.create64(sym,sym.initialloc.register,sym.initialloc.registerhi)
           varloc:=tai_varloc.create64(sym,sym.initialloc.register,sym.initialloc.registerhi)
-{$endif cpu64bitalu}
         else
         else
+{$endif cpu64bitalu and not cpuhighleveltarget}
           varloc:=tai_varloc.create(sym,sym.initialloc.register);
           varloc:=tai_varloc.create(sym,sym.initialloc.register);
         list.concat(varloc);
         list.concat(varloc);
       end;
       end;
 
 
 
 
-    procedure gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean);
-
-      procedure unget_para(const paraloc:TCGParaLocation);
-        begin
-           case paraloc.loc of
-             LOC_REGISTER :
-               begin
-                 if getsupreg(paraloc.register)<first_int_imreg then
-                   cg.ungetcpuregister(list,paraloc.register);
-               end;
-             LOC_MMREGISTER :
-               begin
-                 if getsupreg(paraloc.register)<first_mm_imreg then
-                   cg.ungetcpuregister(list,paraloc.register);
-               end;
-             LOC_FPUREGISTER :
-               begin
-                 if getsupreg(paraloc.register)<first_fpu_imreg then
-                   cg.ungetcpuregister(list,paraloc.register);
-               end;
-           end;
-        end;
-
-      var
-        paraloc   : pcgparalocation;
-        href      : treference;
-        sizeleft  : aint;
-        tempref   : treference;
-        loadsize  : tcgint;
-        tempreg  : tregister;
-{$ifdef mips}
-        //tmpreg   : tregister;
-{$endif mips}
-{$ifndef cpu64bitalu}
-        reg64    : tregister64;
-{$if defined(cpu8bitalu)}
-        curparaloc : PCGParaLocation;
-{$endif defined(cpu8bitalu)}
-{$endif not cpu64bitalu}
-      begin
-        paraloc:=para.location;
-        if not assigned(paraloc) then
-          internalerror(200408203);
-        { skip e.g. empty records }
-        if (paraloc^.loc = LOC_VOID) then
-          exit;
-        case destloc.loc of
-          LOC_REFERENCE :
-            begin
-              { If the parameter location is reused we don't need to copy
-                anything }
-              if not reusepara then
-                begin
-                  href:=destloc.reference;
-                  sizeleft:=para.intsize;
-                  while assigned(paraloc) do
-                    begin
-                      if (paraloc^.size=OS_NO) then
-                        begin
-                          { Can only be a reference that contains the rest
-                            of the parameter }
-                          if (paraloc^.loc<>LOC_REFERENCE) or
-                             assigned(paraloc^.next) then
-                            internalerror(2005013010);
-                          cg.a_load_cgparaloc_ref(list,paraloc^,href,sizeleft,destloc.reference.alignment);
-                          inc(href.offset,sizeleft);
-                          sizeleft:=0;
-                        end
-                      else
-                        begin
-                          { the min(...) call ensures that we do not store more than place is left as
-                             paraloc^.size could be bigger than destloc.size of a parameter occupies a full register
-                             and as on big endian system the parameters might be left aligned, we have to work
-                             with the full register size for paraloc^.size }
-                          if tcgsize2size[destloc.size]<>0 then
-                            loadsize:=min(min(tcgsize2size[paraloc^.size],tcgsize2size[destloc.size]),sizeleft)
-                          else
-                            loadsize:=min(tcgsize2size[paraloc^.size],sizeleft);
-
-                          cg.a_load_cgparaloc_ref(list,paraloc^,href,loadsize,destloc.reference.alignment);
-                          inc(href.offset,loadsize);
-                          dec(sizeleft,loadsize);
-                        end;
-                      unget_para(paraloc^);
-                      paraloc:=paraloc^.next;
-                    end;
-                end;
-            end;
-          LOC_REGISTER,
-          LOC_CREGISTER :
-            begin
-{$ifdef cpu64bitalu}
-              if (para.size in [OS_128,OS_S128,OS_F128]) and
-                 ({ in case of fpu emulation, or abi's that pass fpu values
-                    via integer registers }
-                  (vardef.typ=floatdef) or
-                   is_methodpointer(vardef) or
-                   is_record(vardef)) then
-                begin
-                  case paraloc^.loc of
-                    LOC_REGISTER,
-                    LOC_MMREGISTER:
-                      begin
-                        if not assigned(paraloc^.next) then
-                          internalerror(200410104);
-                        case tcgsize2size[paraloc^.size] of
-                          8:
-                            begin
-                              if (target_info.endian=ENDIAN_BIG) then
-                                begin
-                                  { paraloc^ -> high
-                                    paraloc^.next -> low }
-                                  unget_para(paraloc^);
-                                  gen_alloc_regloc(list,destloc,vardef);
-                                  { reg->reg, alignment is irrelevant }
-                                  cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,destloc.register128.reghi,8);
-                                  unget_para(paraloc^.next^);
-                                  cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^.next^,destloc.register128.reglo,8);
-                                end
-                              else
-                                begin
-                                  { paraloc^ -> low
-                                    paraloc^.next -> high }
-                                  unget_para(paraloc^);
-                                  gen_alloc_regloc(list,destloc,vardef);
-                                  cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,destloc.register128.reglo,8);
-                                  unget_para(paraloc^.next^);
-                                  cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^.next^,destloc.register128.reghi,8);
-                                end;
-                            end;
-                          4:
-                            begin
-                              { The 128-bit parameter is located in 4 32-bit MM registers.
-                                It is needed to copy them to 2 64-bit int registers.
-                                A code generator or a target cpu must support loading of a 32-bit MM register to
-                                a 64-bit int register, zero extending it. }
-                              if target_info.endian=ENDIAN_BIG then
-                                internalerror(2018101702);  // Big endian support not implemented yet
-                              gen_alloc_regloc(list,destloc,vardef);
-                              tempreg:=cg.getintregister(list,OS_64);
-                              // Low part of the 128-bit param
-                              unget_para(paraloc^);
-                              cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,tempreg,4);
-                              paraloc:=paraloc^.next;
-                              if paraloc=nil then
-                                internalerror(2018101703);
-                              unget_para(paraloc^);
-                              cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,destloc.register128.reglo,4);
-                              cg.a_op_const_reg(list,OP_SHL,OS_64,32,destloc.register128.reglo);
-                              cg.a_op_reg_reg(list,OP_OR,OS_64,tempreg,destloc.register128.reglo);
-                              // High part of the 128-bit param
-                              paraloc:=paraloc^.next;
-                              if paraloc=nil then
-                                internalerror(2018101704);
-                              unget_para(paraloc^);
-                              cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,tempreg,4);
-                              paraloc:=paraloc^.next;
-                              if paraloc=nil then
-                                internalerror(2018101705);
-                              unget_para(paraloc^);
-                              cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,destloc.register128.reghi,4);
-                              cg.a_op_const_reg(list,OP_SHL,OS_64,32,destloc.register128.reghi);
-                              cg.a_op_reg_reg(list,OP_OR,OS_64,tempreg,destloc.register128.reghi);
-                            end
-                          else
-                            internalerror(2018101701);
-                        end;
-                      end;
-                    LOC_REFERENCE:
-                      begin
-                        gen_alloc_regloc(list,destloc,vardef);
-                        reference_reset_base(href,paraloc^.reference.index,paraloc^.reference.offset,ctempposinvalid,para.alignment,[]);
-                        cg128.a_load128_ref_reg(list,href,destloc.register128);
-                        unget_para(paraloc^);
-                      end;
-                    else
-                      internalerror(2012090607);
-                  end
-                end
-              else
-{$else cpu64bitalu}
-              if (para.size in [OS_64,OS_S64,OS_F64]) and
-                 (is_64bit(vardef) or
-                  { in case of fpu emulation, or abi's that pass fpu values
-                    via integer registers }
-                  (vardef.typ=floatdef) or
-                   is_methodpointer(vardef) or
-                   is_record(vardef)) then
-                begin
-                  case paraloc^.loc of
-                    LOC_REGISTER:
-                      begin
-                        case para.locations_count of
-{$if defined(cpu8bitalu)}
-                          { 8 paralocs? }
-                          8:
-                            if (target_info.endian=ENDIAN_BIG) then
-                              begin
-                                { is there any big endian 8 bit ALU/16 bit Addr CPU? }
-                                internalerror(2015041003);
-                                { paraloc^ -> high
-                                  paraloc^.next^.next^.next^.next -> low }
-                                unget_para(paraloc^);
-                                gen_alloc_regloc(list,destloc,vardef);
-                                { reg->reg, alignment is irrelevant }
-                                cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^,cg.GetNextReg(destloc.register64.reghi),1);
-                                unget_para(paraloc^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^,destloc.register64.reghi,1);
-                                unget_para(paraloc^.next^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^,cg.GetNextReg(destloc.register64.reglo),1);
-                                unget_para(paraloc^.next^.next^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^.next^,destloc.register64.reglo,1);
-                              end
-                            else
-                              begin
-                                { paraloc^ -> low
-                                  paraloc^.next^.next^.next^.next -> high }
-                                curparaloc:=paraloc;
-                                unget_para(curparaloc^);
-                                gen_alloc_regloc(list,destloc,vardef);
-                                cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^,destloc.register64.reglo,2);
-                                unget_para(curparaloc^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^.next^,cg.GetNextReg(destloc.register64.reglo),1);
-                                unget_para(curparaloc^.next^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^.next^.next^,cg.GetNextReg(cg.GetNextReg(destloc.register64.reglo)),1);
-                                unget_para(curparaloc^.next^.next^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^.next^.next^.next^,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(destloc.register64.reglo))),1);
-
-                                curparaloc:=paraloc^.next^.next^.next^.next;
-                                unget_para(curparaloc^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^,destloc.register64.reghi,2);
-                                unget_para(curparaloc^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^.next^,cg.GetNextReg(destloc.register64.reghi),1);
-                                unget_para(curparaloc^.next^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^.next^.next^,cg.GetNextReg(cg.GetNextReg(destloc.register64.reghi)),1);
-                                unget_para(curparaloc^.next^.next^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_8,curparaloc^.next^.next^.next^,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(destloc.register64.reghi))),1);
-                              end;
-{$endif defined(cpu8bitalu)}
-{$if defined(cpu16bitalu) or defined(cpu8bitalu)}
-                          { 4 paralocs? }
-                          4:
-                            if (target_info.endian=ENDIAN_BIG) then
-                              begin
-                                { paraloc^ -> high
-                                  paraloc^.next^.next -> low }
-                                unget_para(paraloc^);
-                                gen_alloc_regloc(list,destloc,vardef);
-                                { reg->reg, alignment is irrelevant }
-                                cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^,cg.GetNextReg(destloc.register64.reghi),2);
-                                unget_para(paraloc^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^,destloc.register64.reghi,2);
-                                unget_para(paraloc^.next^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^,cg.GetNextReg(destloc.register64.reglo),2);
-                                unget_para(paraloc^.next^.next^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^.next^,destloc.register64.reglo,2);
-                              end
-                            else
-                              begin
-                                { paraloc^ -> low
-                                  paraloc^.next^.next -> high }
-                                unget_para(paraloc^);
-                                gen_alloc_regloc(list,destloc,vardef);
-                                cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^,destloc.register64.reglo,2);
-                                unget_para(paraloc^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^,cg.GetNextReg(destloc.register64.reglo),2);
-                                unget_para(paraloc^.next^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^,destloc.register64.reghi,2);
-                                unget_para(paraloc^.next^.next^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^.next^,cg.GetNextReg(destloc.register64.reghi),2);
-                              end;
-{$endif defined(cpu16bitalu) or defined(cpu8bitalu)}
-                          2:
-                            if (target_info.endian=ENDIAN_BIG) then
-                              begin
-                                { paraloc^ -> high
-                                  paraloc^.next -> low }
-                                unget_para(paraloc^);
-                                gen_alloc_regloc(list,destloc,vardef);
-                                { reg->reg, alignment is irrelevant }
-                                cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,destloc.register64.reghi,4);
-                                unget_para(paraloc^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reglo,4);
-                              end
-                            else
-                              begin
-                                { paraloc^ -> low
-                                  paraloc^.next -> high }
-                                unget_para(paraloc^);
-                                gen_alloc_regloc(list,destloc,vardef);
-                                cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,destloc.register64.reglo,4);
-                                unget_para(paraloc^.next^);
-                                cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reghi,4);
-                              end;
-                          else
-                            { unexpected number of paralocs }
-                            internalerror(200410104);
-                        end;
-                      end;
-                    LOC_REFERENCE:
-                      begin
-                        gen_alloc_regloc(list,destloc,vardef);
-                        reference_reset_base(href,paraloc^.reference.index,paraloc^.reference.offset,ctempposinvalid,para.alignment,[]);
-                        cg64.a_load64_ref_reg(list,href,destloc.register64);
-                        unget_para(paraloc^);
-                      end;
-                    else
-                      internalerror(2005101501);
-                  end
-                end
-              else
-{$endif cpu64bitalu}
-                begin
-                  if assigned(paraloc^.next) then
-                    begin
-                      if (destloc.size in [OS_PAIR,OS_SPAIR]) and
-                        (para.Size in [OS_PAIR,OS_SPAIR]) then
-                        begin
-                          unget_para(paraloc^);
-                          gen_alloc_regloc(list,destloc,vardef);
-                          cg.a_load_cgparaloc_anyreg(list,OS_INT,paraloc^,destloc.register,sizeof(aint));
-                          unget_para(paraloc^.Next^);
-                          {$if defined(cpu16bitalu) or defined(cpu8bitalu)}
-                            cg.a_load_cgparaloc_anyreg(list,OS_INT,paraloc^.Next^,cg.GetNextReg(destloc.register),sizeof(aint));
-                          {$else}
-                            cg.a_load_cgparaloc_anyreg(list,OS_INT,paraloc^.Next^,destloc.registerhi,sizeof(aint));
-                          {$endif}
-                        end
-{$if defined(cpu8bitalu)}
-                      else if (destloc.size in [OS_32,OS_S32]) and
-                        (para.Size in [OS_32,OS_S32]) then
-                        begin
-                          unget_para(paraloc^);
-                          gen_alloc_regloc(list,destloc,vardef);
-                          cg.a_load_cgparaloc_anyreg(list,OS_8,paraloc^,destloc.register,sizeof(aint));
-                          unget_para(paraloc^.Next^);
-                          cg.a_load_cgparaloc_anyreg(list,OS_8,paraloc^.Next^,cg.GetNextReg(destloc.register),sizeof(aint));
-                          unget_para(paraloc^.Next^.Next^);
-                          cg.a_load_cgparaloc_anyreg(list,OS_8,paraloc^.Next^.Next^,cg.GetNextReg(cg.GetNextReg(destloc.register)),sizeof(aint));
-                          unget_para(paraloc^.Next^.Next^.Next^);
-                          cg.a_load_cgparaloc_anyreg(list,OS_8,paraloc^.Next^.Next^.Next^,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(destloc.register))),sizeof(aint));
-                        end
-{$endif defined(cpu8bitalu)}
-                      else
-                        begin
-                          { this can happen if a parameter is spread over
-                            multiple paralocs, e.g. if a record with two single
-                            fields must be passed in two single precision
-                            registers }
-                          { does it fit in the register of destloc? }
-                          sizeleft:=para.intsize;
-                          if sizeleft<>vardef.size then
-                            internalerror(2014122806);
-                          if sizeleft<>tcgsize2size[destloc.size] then
-                            internalerror(200410105);
-                          { store everything first to memory, then load it in
-                            destloc }
-                          tg.gettemp(list,sizeleft,sizeleft,tt_persistent,tempref);
-                          gen_alloc_regloc(list,destloc,vardef);
-                          while sizeleft>0 do
-                            begin
-                              if not assigned(paraloc) then
-                                internalerror(2014122807);
-                              unget_para(paraloc^);
-                              cg.a_load_cgparaloc_ref(list,paraloc^,tempref,sizeleft,newalignment(para.alignment,para.intsize-sizeleft));
-                              if (paraloc^.size=OS_NO) and
-                                 assigned(paraloc^.next) then
-                                internalerror(2014122805);
-                              inc(tempref.offset,tcgsize2size[paraloc^.size]);
-                              dec(sizeleft,tcgsize2size[paraloc^.size]);
-                              paraloc:=paraloc^.next;
-                            end;
-                          dec(tempref.offset,para.intsize);
-                          cg.a_load_ref_reg(list,para.size,para.size,tempref,destloc.register);
-                          tg.ungettemp(list,tempref);
-                        end;
-                    end
-                  else
-                    begin
-                      unget_para(paraloc^);
-                      gen_alloc_regloc(list,destloc,vardef);
-                      { we can't directly move regular registers into fpu
-                        registers }
-                      if getregtype(paraloc^.register)=R_FPUREGISTER then
-                        begin
-                          { store everything first to memory, then load it in
-                            destloc }
-                          tg.gettemp(list,tcgsize2size[paraloc^.size],para.intsize,tt_persistent,tempref);
-                          cg.a_load_cgparaloc_ref(list,paraloc^,tempref,tcgsize2size[paraloc^.size],tempref.alignment);
-                          cg.a_load_ref_reg(list,int_cgsize(tcgsize2size[paraloc^.size]),destloc.size,tempref,destloc.register);
-                          tg.ungettemp(list,tempref);
-                        end
-                      else
-                        cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,sizeof(aint));
-                    end;
-                end;
-            end;
-          LOC_FPUREGISTER,
-          LOC_CFPUREGISTER :
-            begin
-{$ifdef mips}
-              if (destloc.size = paraloc^.Size) and
-                 (paraloc^.Loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER,LOC_REFERENCE,LOC_CREFERENCE]) then
-                begin
-                  unget_para(paraloc^);
-                  gen_alloc_regloc(list,destloc,vardef);
-                  cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,para.alignment);
-                end
-              else if (destloc.size = OS_F32) and
-                 (paraloc^.Loc in [LOC_REGISTER,LOC_CREGISTER]) then
-                begin
-                  gen_alloc_regloc(list,destloc,vardef);
-                  unget_para(paraloc^);
-                  list.Concat(taicpu.op_reg_reg(A_MTC1,paraloc^.register,destloc.register));
-                end
-{ TODO: Produces invalid code, needs fixing together with regalloc setup. }
-{
-              else if (destloc.size = OS_F64) and
-                      (paraloc^.Loc in [LOC_REGISTER,LOC_CREGISTER]) and
-                      (paraloc^.next^.Loc in [LOC_REGISTER,LOC_CREGISTER]) then
-                begin
-                  gen_alloc_regloc(list,destloc,vardef);
-
-                  tmpreg:=destloc.register;
-                  unget_para(paraloc^);
-                  list.Concat(taicpu.op_reg_reg(A_MTC1,paraloc^.register,tmpreg));
-                  setsupreg(tmpreg,getsupreg(tmpreg)+1);
-                  unget_para(paraloc^.next^);
-                  list.Concat(taicpu.op_reg_reg(A_MTC1,paraloc^.Next^.register,tmpreg));
-                end
-}
-              else
-                begin
-                  sizeleft := TCGSize2Size[destloc.size];
-                  tg.GetTemp(list,sizeleft,sizeleft,tt_normal,tempref);
-                  href:=tempref;
-                  while assigned(paraloc) do
-                    begin
-                      unget_para(paraloc^);
-                      cg.a_load_cgparaloc_ref(list,paraloc^,href,sizeleft,destloc.reference.alignment);
-                      inc(href.offset,TCGSize2Size[paraloc^.size]);
-                      dec(sizeleft,TCGSize2Size[paraloc^.size]);
-                      paraloc:=paraloc^.next;
-                    end;
-                  gen_alloc_regloc(list,destloc,vardef);
-                  cg.a_loadfpu_ref_reg(list,destloc.size,destloc.size,tempref,destloc.register);
-                  tg.UnGetTemp(list,tempref);
-                end;
-{$else mips}
-{$if defined(sparc) or defined(arm)}
-              { Arm and Sparc passes floats in int registers, when loading to fpu register
-                we need a temp }
-              sizeleft := TCGSize2Size[destloc.size];
-              tg.GetTemp(list,sizeleft,sizeleft,tt_normal,tempref);
-              href:=tempref;
-              while assigned(paraloc) do
-                begin
-                  unget_para(paraloc^);
-                  cg.a_load_cgparaloc_ref(list,paraloc^,href,sizeleft,destloc.reference.alignment);
-                  inc(href.offset,TCGSize2Size[paraloc^.size]);
-                  dec(sizeleft,TCGSize2Size[paraloc^.size]);
-                  paraloc:=paraloc^.next;
-                end;
-              gen_alloc_regloc(list,destloc,vardef);
-              cg.a_loadfpu_ref_reg(list,destloc.size,destloc.size,tempref,destloc.register);
-              tg.UnGetTemp(list,tempref);
-{$else defined(sparc) or defined(arm)}
-              unget_para(paraloc^);
-              gen_alloc_regloc(list,destloc,vardef);
-              { from register to register -> alignment is irrelevant }
-              cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,0);
-              if assigned(paraloc^.next) then
-                internalerror(200410109);
-{$endif defined(sparc) or defined(arm)}
-{$endif mips}
-            end;
-          LOC_MMREGISTER,
-          LOC_CMMREGISTER :
-            begin
-{$ifndef cpu64bitalu}
-              { ARM vfp floats are passed in integer registers }
-              if (para.size=OS_F64) and
-                 (paraloc^.size in [OS_32,OS_S32]) and
-                 use_vectorfpu(vardef) then
-                begin
-                  { we need 2x32bit reg }
-                  if not assigned(paraloc^.next) or
-                     assigned(paraloc^.next^.next) then
-                    internalerror(2009112421);
-                  unget_para(paraloc^.next^);
-                  case paraloc^.next^.loc of
-                    LOC_REGISTER:
-                      tempreg:=paraloc^.next^.register;
-                    LOC_REFERENCE:
-                      begin
-                        tempreg:=cg.getintregister(list,OS_32);
-                        cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,tempreg,4);
-                      end;
-                    else
-                      internalerror(2012051301);
-                  end;
-                  { don't free before the above, because then the getintregister
-                    could reallocate this register and overwrite it }
-                  unget_para(paraloc^);
-                  gen_alloc_regloc(list,destloc,vardef);
-                  if (target_info.endian=endian_big) then
-                    { paraloc^ -> high
-                      paraloc^.next -> low }
-                    reg64:=joinreg64(tempreg,paraloc^.register)
-                  else
-                    reg64:=joinreg64(paraloc^.register,tempreg);
-                  cg64.a_loadmm_intreg64_reg(list,OS_F64,reg64,destloc.register);
-                end
-              else
-{$endif not cpu64bitalu}
-                begin
-                  if not assigned(paraloc^.next) then
-                    begin
-                      unget_para(paraloc^);
-                      gen_alloc_regloc(list,destloc,vardef);
-                      { from register to register -> alignment is irrelevant }
-                      cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,0);
-                    end
-                  else
-                    begin
-                      internalerror(200410108);
-                    end;
-                  { data could come in two memory locations, for now
-                    we simply ignore the sanity check (FK)
-                  if assigned(paraloc^.next) then
-                    internalerror(200410108);
-                  }
-                end;
-            end;
-          else
-            internalerror(2010052903);
-        end;
-      end;
-
-
-    procedure gen_load_para_value(list:TAsmList);
-
-       procedure get_para(const paraloc:TCGParaLocation);
-         begin
-            case paraloc.loc of
-              LOC_REGISTER :
-                begin
-                  if getsupreg(paraloc.register)<first_int_imreg then
-                    cg.getcpuregister(list,paraloc.register);
-                end;
-              LOC_MMREGISTER :
-                begin
-                  if getsupreg(paraloc.register)<first_mm_imreg then
-                    cg.getcpuregister(list,paraloc.register);
-                end;
-              LOC_FPUREGISTER :
-                begin
-                  if getsupreg(paraloc.register)<first_fpu_imreg then
-                    cg.getcpuregister(list,paraloc.register);
-                end;
-            end;
-         end;
-
-
-      var
-        i : longint;
-        currpara : tparavarsym;
-        paraloc  : pcgparalocation;
-      begin
-        if (po_assembler in current_procinfo.procdef.procoptions) or
-        { exceptfilters have a single hidden 'parentfp' parameter, which
-          is handled by tcg.g_proc_entry. }
-           (current_procinfo.procdef.proctypeoption=potype_exceptfilter) then
-          exit;
-
-        { Allocate registers used by parameters }
-        for i:=0 to current_procinfo.procdef.paras.count-1 do
-          begin
-            currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
-            paraloc:=currpara.paraloc[calleeside].location;
-            while assigned(paraloc) do
-              begin
-                if paraloc^.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER] then
-                  get_para(paraloc^);
-                paraloc:=paraloc^.next;
-              end;
-          end;
-
-        { Copy parameters to local references/registers }
-        for i:=0 to current_procinfo.procdef.paras.count-1 do
-          begin
-            currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
-            { don't use currpara.vardef, as this will be wrong in case of
-              call-by-reference parameters (it won't contain the pointerdef) }
-            gen_load_cgpara_loc(list,currpara.paraloc[calleeside].def,currpara.paraloc[calleeside],currpara.initialloc,paramanager.param_use_paraloc(currpara.paraloc[calleeside]));
-            { gen_load_cgpara_loc() already allocated the initialloc
-              -> don't allocate again }
-            if currpara.initialloc.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER] then
-              begin
-                gen_alloc_regvar(list,currpara,false);
-                hlcg.varsym_set_localloc(list,currpara);
-              end;
-          end;
-
-        { generate copies of call by value parameters, must be done before
-          the initialization and body is parsed because the refcounts are
-          incremented using the local copies }
-        current_procinfo.procdef.parast.SymList.ForEachCall(@hlcg.g_copyvalueparas,list);
-        if not(po_assembler in current_procinfo.procdef.procoptions) then
-          begin
-            { initialize refcounted paras, and trash others. Needed here
-              instead of in gen_initialize_code, because when a reference is
-              intialised or trashed while the pointer to that reference is kept
-              in a regvar, we add a register move and that one again has to
-              come after the parameter loading code as far as the register
-              allocator is concerned }
-            current_procinfo.procdef.parast.SymList.ForEachCall(@init_paras,list);
-          end;
-      end;
-
-
 {****************************************************************************
 {****************************************************************************
                                 Entry/Exit
                                 Entry/Exit
 ****************************************************************************}
 ****************************************************************************}

+ 6 - 6
compiler/ninl.pas

@@ -90,9 +90,9 @@ interface
           function first_seg: tnode; virtual;
           function first_seg: tnode; virtual;
           function first_sar: tnode; virtual;
           function first_sar: tnode; virtual;
           function first_fma : tnode; virtual;
           function first_fma : tnode; virtual;
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
           function first_ShiftRot_assign_64bitint: tnode; virtual;
           function first_ShiftRot_assign_64bitint: tnode; virtual;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
           function first_AndOrXorShiftRot_assign: tnode; virtual;
           function first_AndOrXorShiftRot_assign: tnode; virtual;
           function first_NegNot_assign: tnode; virtual;
           function first_NegNot_assign: tnode; virtual;
           function first_cpu : tnode; virtual;
           function first_cpu : tnode; virtual;
@@ -5235,7 +5235,7 @@ implementation
        end;
        end;
 
 
 
 
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
      function tinlinenode.first_ShiftRot_assign_64bitint: tnode;
      function tinlinenode.first_ShiftRot_assign_64bitint: tnode;
        var
        var
          procname: string[31];
          procname: string[31];
@@ -5273,18 +5273,18 @@ implementation
          tcallparanode(left).left := nil;
          tcallparanode(left).left := nil;
          firstpass(result);
          firstpass(result);
        end;
        end;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and nto cpuhighleveltarget}
 
 
 
 
      function tinlinenode.first_AndOrXorShiftRot_assign: tnode;
      function tinlinenode.first_AndOrXorShiftRot_assign: tnode;
        begin
        begin
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
          { 64 bit ints have their own shift handling }
          { 64 bit ints have their own shift handling }
          if is_64bit(tcallparanode(left).right.resultdef) and
          if is_64bit(tcallparanode(left).right.resultdef) and
             (inlinenumber in [in_sar_assign_x_y,in_shl_assign_x_y,in_shr_assign_x_y,in_rol_assign_x_y,in_ror_assign_x_y]) then
             (inlinenumber in [in_sar_assign_x_y,in_shl_assign_x_y,in_shr_assign_x_y,in_rol_assign_x_y,in_ror_assign_x_y]) then
            result := first_ShiftRot_assign_64bitint
            result := first_ShiftRot_assign_64bitint
          else
          else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
            begin
            begin
              result:=nil;
              result:=nil;
              expectloc:=tcallparanode(tcallparanode(left).right).left.expectloc;
              expectloc:=tcallparanode(tcallparanode(left).right).left.expectloc;

+ 14 - 14
compiler/nmat.pas

@@ -47,14 +47,14 @@ interface
           function pass_1 : tnode;override;
           function pass_1 : tnode;override;
           function pass_typecheck:tnode;override;
           function pass_typecheck:tnode;override;
           function simplify(forinline : boolean) : tnode;override;
           function simplify(forinline : boolean) : tnode;override;
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
           { override the following if you want to implement }
           { override the following if you want to implement }
           { parts explicitely in the code generator (CEC)
           { parts explicitely in the code generator (CEC)
             Should return nil, if everything will be handled
             Should return nil, if everything will be handled
             in the code generator
             in the code generator
           }
           }
           function first_shlshr64bitint: tnode; virtual;
           function first_shlshr64bitint: tnode; virtual;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
        end;
        end;
        tshlshrnodeclass = class of tshlshrnode;
        tshlshrnodeclass = class of tshlshrnode;
 
 
@@ -183,15 +183,15 @@ implementation
         { not with an ifdef around the call to this routine, because e.g. the
         { not with an ifdef around the call to this routine, because e.g. the
           Java VM has a signed 64 bit division opcode, but not an unsigned
           Java VM has a signed 64 bit division opcode, but not an unsigned
           one }
           one }
-{$ifdef cpu64bitalu}
+{$if defined(cpu64bitalu) or defined(cpuhighleveltarget)}
         result:=false;
         result:=false;
-{$else cpu64bitalu}
+{$else cpu64bitalu or cpuhighleveltarget}
         result:=
         result:=
           (left.resultdef.typ=orddef) and
           (left.resultdef.typ=orddef) and
           (right.resultdef.typ=orddef) and
           (right.resultdef.typ=orddef) and
           { include currency as well }
           { include currency as well }
           (is_64bit(left.resultdef) or is_64bit(right.resultdef));
           (is_64bit(left.resultdef) or is_64bit(right.resultdef));
-{$endif cpu64bitaly}
+{$endif cpu64bitalu or cpuhighleveltarget}
       end;
       end;
 
 
 
 
@@ -503,14 +503,14 @@ implementation
         { divide/mod a number by a constant which is a power of 2? }
         { divide/mod a number by a constant which is a power of 2? }
         if (right.nodetype = ordconstn) and
         if (right.nodetype = ordconstn) and
           isabspowerof2(tordconstnode(right).value,power) and
           isabspowerof2(tordconstnode(right).value,power) and
-{$ifdef cpu64bitalu}
+{$if defined(cpu64bitalu) or defined(cpuhighleveltarget)}
           { for 64 bit, we leave the optimization to the cg }
           { for 64 bit, we leave the optimization to the cg }
             (not is_signed(resultdef)) then
             (not is_signed(resultdef)) then
-{$else cpu64bitalu}
+{$else cpu64bitalu or cpuhighleveltarget}
            (((nodetype=divn) and is_oversizedord(resultdef)) or
            (((nodetype=divn) and is_oversizedord(resultdef)) or
             (nodetype=modn) or
             (nodetype=modn) or
             not is_signed(resultdef)) then
             not is_signed(resultdef)) then
-{$endif cpu64bitalu}
+{$endif cpu64bitalu or cpuhighleveltarget}
           begin
           begin
             if nodetype=divn then
             if nodetype=divn then
               begin
               begin
@@ -848,7 +848,7 @@ implementation
       end;
       end;
 
 
 
 
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
     function tshlshrnode.first_shlshr64bitint: tnode;
     function tshlshrnode.first_shlshr64bitint: tnode;
       var
       var
         procname: string[31];
         procname: string[31];
@@ -874,7 +874,7 @@ implementation
         right := nil;
         right := nil;
         firstpass(result);
         firstpass(result);
       end;
       end;
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
 
 
 
 
     function tshlshrnode.pass_1 : tnode;
     function tshlshrnode.pass_1 : tnode;
@@ -887,7 +887,7 @@ implementation
          if codegenerror then
          if codegenerror then
            exit;
            exit;
 
 
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
          { 64 bit ints have their own shift handling }
          { 64 bit ints have their own shift handling }
          if is_64bit(left.resultdef) then
          if is_64bit(left.resultdef) then
            begin
            begin
@@ -897,7 +897,7 @@ implementation
              regs:=2;
              regs:=2;
            end
            end
          else
          else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
            begin
            begin
              regs:=1
              regs:=1
            end;
            end;
@@ -1354,14 +1354,14 @@ implementation
              expectloc:=LOC_MMXREGISTER
              expectloc:=LOC_MMXREGISTER
          else
          else
 {$endif SUPPORT_MMX}
 {$endif SUPPORT_MMX}
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
            if is_64bit(left.resultdef) then
            if is_64bit(left.resultdef) then
              begin
              begin
                 if (expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
                 if (expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
                   expectloc:=LOC_REGISTER;
                   expectloc:=LOC_REGISTER;
              end
              end
          else
          else
-{$endif not cpu64bitalu}
+{$endif not cpu64bitalu and not cpuhighleveltarget}
            if is_integer(left.resultdef) then
            if is_integer(left.resultdef) then
              expectloc:=LOC_REGISTER;
              expectloc:=LOC_REGISTER;
       end;
       end;

+ 5 - 3
compiler/options.pas

@@ -138,7 +138,7 @@ const
                         + [system_i386_wdosx]
                         + [system_i386_wdosx]
                         + [system_riscv32_linux,system_riscv64_linux];
                         + [system_riscv32_linux,system_riscv64_linux];
 
 
-  suppported_targets_x_smallr = systems_linux + systems_solaris
+  suppported_targets_x_smallr = systems_linux + systems_solaris + systems_android
                              + [system_i386_haiku,system_x86_64_haiku]
                              + [system_i386_haiku,system_x86_64_haiku]
                              + [system_i386_beos]
                              + [system_i386_beos]
                              + [system_m68k_amiga];
                              + [system_m68k_amiga];
@@ -4023,8 +4023,10 @@ begin
       Message(option_w_unsupported_debug_format);
       Message(option_w_unsupported_debug_format);
 
 
   { switch assembler if it's binary and we got -a on the cmdline }
   { switch assembler if it's binary and we got -a on the cmdline }
-  if (cs_asm_leave in init_settings.globalswitches) and
-     (af_outputbinary in target_asm.flags) then
+  if ((cs_asm_leave in init_settings.globalswitches) and
+     (af_outputbinary in target_asm.flags)) or
+     { if -s is passed, we shouldn't call the internal assembler }
+     (cs_asm_extern in init_settings.globalswitches) then
    begin
    begin
      Message(option_switch_bin_to_src_assembler);
      Message(option_switch_bin_to_src_assembler);
      set_target_asm(target_info.assemextern);
      set_target_asm(target_info.assemextern);

+ 1 - 1
compiler/parabase.pas

@@ -269,7 +269,7 @@ implementation
         case location^.loc of
         case location^.loc of
           LOC_REGISTER :
           LOC_REGISTER :
             begin
             begin
-{$ifndef cpu64bitalu}
+{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
               if size in [OS_64,OS_S64] then
               if size in [OS_64,OS_S64] then
                 begin
                 begin
                   if not assigned(location^.next) then
                   if not assigned(location^.next) then

+ 2 - 2
compiler/symdef.pas

@@ -5345,8 +5345,8 @@ implementation
             begin
             begin
               p:=tparavarsym(parast.SymList[i]);
               p:=tparavarsym(parast.SymList[i]);
               { check if no parameter is located on the stack }
               { check if no parameter is located on the stack }
-              if is_open_array(p.vardef) or
-                 is_array_of_const(p.vardef) then
+              if (is_open_array(p.vardef) or
+                 is_array_of_const(p.vardef)) and (p.varspez=vs_value) then
                 begin
                 begin
                   result:=true;
                   result:=true;
                   exit;
                   exit;

+ 3 - 0
compiler/systems/i_linux.pas

@@ -380,6 +380,9 @@ unit i_linux;
             name         : 'Linux for x86-64';
             name         : 'Linux for x86-64';
             shortname    : 'Linux';
             shortname    : 'Linux';
             flags        : [tf_smartlink_sections,tf_needs_symbol_size,tf_needs_dwarf_cfi,
             flags        : [tf_smartlink_sections,tf_needs_symbol_size,tf_needs_dwarf_cfi,
+{$ifdef tls_threadvars}
+                            tf_section_threadvars,
+{$endif tls_threadvars}
                             tf_library_needs_pic,tf_needs_symbol_type,tf_files_case_sensitive,
                             tf_library_needs_pic,tf_needs_symbol_type,tf_files_case_sensitive,
                             tf_has_winlike_resources,tf_safecall_exceptions,tf_safecall_clearstack
                             tf_has_winlike_resources,tf_safecall_exceptions,tf_safecall_clearstack
                             {$ifdef llvm},tf_use_psabieh{$endif}];
                             {$ifdef llvm},tf_use_psabieh{$endif}];

+ 7 - 1
compiler/systems/t_morph.pas

@@ -69,7 +69,7 @@ begin
    begin
    begin
     if not UseVLink then
     if not UseVLink then
      begin
      begin
-      ExeCmd[1]:='ld $OPT -o $EXE $RES';
+      ExeCmd[1]:='ld $OPT $GCSECTIONS -o $EXE $RES';
       ExeCmd[2]:='strip --strip-unneeded --remove-section .comment $EXE';
       ExeCmd[2]:='strip --strip-unneeded --remove-section .comment $EXE';
      end
      end
     else
     else
@@ -223,6 +223,11 @@ begin
      StripStr:='-s -P __abox__';
      StripStr:='-s -P __abox__';
     if create_smartlink_sections then
     if create_smartlink_sections then
      GCSectionsStr:='-gc-all -sc -sd';
      GCSectionsStr:='-gc-all -sc -sd';
+   end
+  else
+   begin
+    if create_smartlink_sections then
+     GCSectionsStr:='--gc-sections -e _start';
    end;
    end;
 
 
 { Write used files and libraries }
 { Write used files and libraries }
@@ -242,6 +247,7 @@ begin
    begin
    begin
     Replace(cmdstr,'$EXE',maybequoted(ScriptFixFileName(current_module.exefilename)));
     Replace(cmdstr,'$EXE',maybequoted(ScriptFixFileName(current_module.exefilename)));
     Replace(cmdstr,'$RES',maybequoted(ScriptFixFileName(outputexedir+Info.ResName)));
     Replace(cmdstr,'$RES',maybequoted(ScriptFixFileName(outputexedir+Info.ResName)));
+    Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
    end;
    end;
   success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
   success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
 
 

+ 5 - 1
compiler/utils/fpc.pp

@@ -35,7 +35,11 @@ program fpc;
     {$ifdef NETWARE}
     {$ifdef NETWARE}
       exeext='.nlm';
       exeext='.nlm';
     {$else}
     {$else}
-      exeext='.exe';
+      {$ifdef ATARI}
+        exeext='.ttp';
+      {$else}
+        exeext='.exe';
+      {$endif ATARI}
     {$endif NETWARE}
     {$endif NETWARE}
   {$endif HASAMIGA}
   {$endif HASAMIGA}
 {$endif UNIX}
 {$endif UNIX}

+ 4 - 0
compiler/x86/aasmcpu.pas

@@ -331,10 +331,14 @@ interface
         IF_SSSE3,
         IF_SSSE3,
         IF_SSE41,
         IF_SSE41,
         IF_SSE42,
         IF_SSE42,
+        IF_MOVBE,
+        IF_CLMUL,
         IF_AVX,
         IF_AVX,
         IF_AVX2,
         IF_AVX2,
         IF_BMI1,
         IF_BMI1,
         IF_BMI2,
         IF_BMI2,
+        { Intel ADX (Multi-Precision Add-Carry Instruction Extensions) }
+        IF_ADX,
         IF_16BITONLY,
         IF_16BITONLY,
         IF_FMA,
         IF_FMA,
         IF_FMA4,
         IF_FMA4,

+ 10 - 1
compiler/x86/agx86att.pas

@@ -185,6 +185,12 @@ interface
              addr_tlsgd:
              addr_tlsgd:
                owner.writer.AsmWrite('@tlsgd');
                owner.writer.AsmWrite('@tlsgd');
 {$endif i386}
 {$endif i386}
+{$ifdef x86_64}
+             addr_tpoff:
+               owner.writer.AsmWrite('@tpoff');
+             addr_tlsgd:
+               owner.writer.AsmWrite('@tlsgd');
+{$endif x86_64}
            end;
            end;
 
 
            if offset<0 then
            if offset<0 then
@@ -231,7 +237,10 @@ interface
             else
             else
               owner.writer.AsmWrite(gas_regname(o.reg));
               owner.writer.AsmWrite(gas_regname(o.reg));
           top_ref :
           top_ref :
-            if o.ref^.refaddr in [addr_no,addr_pic,addr_pic_no_got{$ifdef i386},addr_ntpoff,addr_tlsgd{$endif i386}] then
+            if o.ref^.refaddr in [addr_no,addr_pic,addr_pic_no_got
+              {$ifdef i386},addr_ntpoff,addr_tlsgd{$endif i386}
+              {$ifdef x86_64},addr_tpoff,addr_tlsgd{$endif x86_64}
+              ] then
               WriteReference(o.ref^)
               WriteReference(o.ref^)
             else
             else
               begin
               begin

+ 170 - 2
compiler/x86/aoptx86.pas

@@ -71,6 +71,8 @@ unit aoptx86;
         function OptPass1Sub(var p : tai) : boolean;
         function OptPass1Sub(var p : tai) : boolean;
         function OptPass1SHLSAL(var p : tai) : boolean;
         function OptPass1SHLSAL(var p : tai) : boolean;
         function OptPass1SETcc(var p: tai): boolean;
         function OptPass1SETcc(var p: tai): boolean;
+        function OptPass1FSTP(var p: tai): boolean;
+        function OptPass1FLD(var p: tai): boolean;
 
 
         function OptPass2MOV(var p : tai) : boolean;
         function OptPass2MOV(var p : tai) : boolean;
         function OptPass2Imul(var p : tai) : boolean;
         function OptPass2Imul(var p : tai) : boolean;
@@ -948,6 +950,14 @@ unit aoptx86;
           GetNextInstruction(p,hp2) and
           GetNextInstruction(p,hp2) and
           MatchInstruction(hp2,A_RET,[S_NO])
           MatchInstruction(hp2,A_RET,[S_NO])
          ) or
          ) or
+         (((taicpu(p).opcode=A_LEA) and
+           MatchOpType(taicpu(p),top_ref,top_reg) and
+           (taicpu(p).oper[0]^.ref^.base=NR_STACK_POINTER_REG) and
+           (taicpu(p).oper[1]^.reg=NR_STACK_POINTER_REG)
+           ) and
+          GetNextInstruction(p,hp2) and
+          MatchInstruction(hp2,A_RET,[S_NO])
+         ) or
          ((((taicpu(p).opcode=A_MOV) and
          ((((taicpu(p).opcode=A_MOV) and
            MatchOpType(taicpu(p),top_reg,top_reg) and
            MatchOpType(taicpu(p),top_reg,top_reg) and
            (taicpu(p).oper[0]^.reg=current_procinfo.framepointer) and
            (taicpu(p).oper[0]^.reg=current_procinfo.framepointer) and
@@ -1842,7 +1852,7 @@ unit aoptx86;
               end
               end
             else if MatchOpType(taicpu(hp2),top_reg,top_reg) and
             else if MatchOpType(taicpu(hp2),top_reg,top_reg) and
               not(SuperRegistersEqual(taicpu(hp1).oper[0]^.reg,taicpu(hp2).oper[1]^.reg)) and
               not(SuperRegistersEqual(taicpu(hp1).oper[0]^.reg,taicpu(hp2).oper[1]^.reg)) and
-              (not((taicpu(hp1).opsize=S_Q) and (taicpu(hp2).opsize=S_L)) or
+              ((topsize2memsize[taicpu(hp1).opsize]<= topsize2memsize[taicpu(hp2).opsize]) or
                { opsize matters for these opcodes, we could probably work around this, but it is not worth the effort }
                { opsize matters for these opcodes, we could probably work around this, but it is not worth the effort }
                ((taicpu(hp1).opcode<>A_SHL) and (taicpu(hp1).opcode<>A_SHR) and (taicpu(hp1).opcode<>A_SAR))
                ((taicpu(hp1).opcode<>A_SHL) and (taicpu(hp1).opcode<>A_SHR) and (taicpu(hp1).opcode<>A_SAR))
               )
               )
@@ -1879,6 +1889,10 @@ unit aoptx86;
                           debug_op2str(taicpu(p).opcode)+debug_opsize2str(taicpu(p).opsize)+' '+
                           debug_op2str(taicpu(p).opcode)+debug_opsize2str(taicpu(p).opsize)+' '+
                           debug_op2str(taicpu(hp1).opcode)+debug_opsize2str(taicpu(hp1).opsize)+' '+
                           debug_op2str(taicpu(hp1).opcode)+debug_opsize2str(taicpu(hp1).opsize)+' '+
                           debug_op2str(taicpu(hp2).opcode)+debug_opsize2str(taicpu(hp2).opsize),p);
                           debug_op2str(taicpu(hp2).opcode)+debug_opsize2str(taicpu(hp2).opsize),p);
+                    { limit size of constants as well to avoid assembler errors, but
+                      check opsize to avoid overflow when left shifting the 1 }
+                    if (taicpu(p).oper[0]^.typ=top_const) and (topsize2memsize[taicpu(hp2).opsize]<=4) then
+                      taicpu(p).oper[0]^.val:=taicpu(p).oper[0]^.val and ((qword(1) shl (topsize2memsize[taicpu(hp2).opsize]*8))-1);
                     taicpu(hp1).changeopsize(taicpu(hp2).opsize);
                     taicpu(hp1).changeopsize(taicpu(hp2).opsize);
                     taicpu(p).changeopsize(taicpu(hp2).opsize);
                     taicpu(p).changeopsize(taicpu(hp2).opsize);
                     if taicpu(p).oper[0]^.typ=top_reg then
                     if taicpu(p).oper[0]^.typ=top_reg then
@@ -2444,7 +2458,161 @@ unit aoptx86;
       end;
       end;
 
 
 
 
-    function TX86AsmOptimizer.OptPass2MOV(var p : tai) : boolean;
+    function TX86AsmOptimizer.OptPass1FSTP(var p: tai): boolean;
+      { returns true if a "continue" should be done after this optimization }
+      var
+        hp1, hp2: tai;
+      begin
+        Result := false;
+        if MatchOpType(taicpu(p),top_ref) and
+           GetNextInstruction(p, hp1) and
+           (hp1.typ = ait_instruction) and
+           (((taicpu(hp1).opcode = A_FLD) and
+             (taicpu(p).opcode = A_FSTP)) or
+            ((taicpu(p).opcode = A_FISTP) and
+             (taicpu(hp1).opcode = A_FILD))) and
+           MatchOpType(taicpu(hp1),top_ref) and
+           (taicpu(hp1).opsize = taicpu(p).opsize) and
+           RefsEqual(taicpu(p).oper[0]^.ref^, taicpu(hp1).oper[0]^.ref^) then
+          begin
+            { replacing fstp f;fld f by fst f is only valid for extended because of rounding }
+            if (taicpu(p).opsize=S_FX) and
+               GetNextInstruction(hp1, hp2) and
+               (hp2.typ = ait_instruction) and
+               IsExitCode(hp2) and
+               (taicpu(p).oper[0]^.ref^.base = current_procinfo.FramePointer) and
+               not(assigned(current_procinfo.procdef.funcretsym) and
+                   (taicpu(p).oper[0]^.ref^.offset < tabstractnormalvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset)) and
+               (taicpu(p).oper[0]^.ref^.index = NR_NO) then
+              begin
+                asml.remove(p);
+                asml.remove(hp1);
+                p.free;
+                hp1.free;
+                p := hp2;
+                RemoveLastDeallocForFuncRes(p);
+                Result := true;
+              end
+            (* can't be done because the store operation rounds
+            else
+              { fst can't store an extended value! }
+              if (taicpu(p).opsize <> S_FX) and
+                 (taicpu(p).opsize <> S_IQ) then
+                begin
+                  if (taicpu(p).opcode = A_FSTP) then
+                    taicpu(p).opcode := A_FST
+                  else taicpu(p).opcode := A_FIST;
+                  asml.remove(hp1);
+                  hp1.free;
+                end
+            *)
+          end;
+      end;
+
+
+     function TX86AsmOptimizer.OptPass1FLD(var p : tai) : boolean;
+      var
+       hp1, hp2: tai;
+      begin
+        result:=false;
+        if MatchOpType(taicpu(p),top_reg) and
+           GetNextInstruction(p, hp1) and
+           (hp1.typ = Ait_Instruction) and
+           MatchOpType(taicpu(hp1),top_reg,top_reg) and
+           (taicpu(hp1).oper[0]^.reg = NR_ST) and
+           (taicpu(hp1).oper[1]^.reg = NR_ST1) then
+           { change                        to
+               fld      reg               fxxx reg,st
+               fxxxp    st, st1 (hp1)
+             Remark: non commutative operations must be reversed!
+           }
+          begin
+              case taicpu(hp1).opcode Of
+                A_FMULP,A_FADDP,
+                A_FSUBP,A_FDIVP,A_FSUBRP,A_FDIVRP:
+                  begin
+                    case taicpu(hp1).opcode Of
+                      A_FADDP: taicpu(hp1).opcode := A_FADD;
+                      A_FMULP: taicpu(hp1).opcode := A_FMUL;
+                      A_FSUBP: taicpu(hp1).opcode := A_FSUBR;
+                      A_FSUBRP: taicpu(hp1).opcode := A_FSUB;
+                      A_FDIVP: taicpu(hp1).opcode := A_FDIVR;
+                      A_FDIVRP: taicpu(hp1).opcode := A_FDIV;
+                    end;
+                    taicpu(hp1).oper[0]^.reg := taicpu(p).oper[0]^.reg;
+                    taicpu(hp1).oper[1]^.reg := NR_ST;
+                    asml.remove(p);
+                    p.free;
+                    p := hp1;
+                    Result:=true;
+                    exit;
+                  end;
+              end;
+          end
+        else
+          if MatchOpType(taicpu(p),top_ref) and
+             GetNextInstruction(p, hp2) and
+             (hp2.typ = Ait_Instruction) and
+             MatchOpType(taicpu(hp2),top_reg,top_reg) and
+             (taicpu(p).opsize in [S_FS, S_FL]) and
+             (taicpu(hp2).oper[0]^.reg = NR_ST) and
+             (taicpu(hp2).oper[1]^.reg = NR_ST1) then
+            if GetLastInstruction(p, hp1) and
+              MatchInstruction(hp1,A_FLD,A_FST,[taicpu(p).opsize]) and
+              MatchOpType(taicpu(hp1),top_ref) and
+              RefsEqual(taicpu(p).oper[0]^.ref^, taicpu(hp1).oper[0]^.ref^) then
+              if ((taicpu(hp2).opcode = A_FMULP) or
+                  (taicpu(hp2).opcode = A_FADDP)) then
+              { change                      to
+                  fld/fst   mem1  (hp1)       fld/fst   mem1
+                  fld       mem1  (p)         fadd/
+                  faddp/                       fmul     st, st
+                  fmulp  st, st1 (hp2) }
+                begin
+                  asml.remove(p);
+                  p.free;
+                  p := hp1;
+                  if (taicpu(hp2).opcode = A_FADDP) then
+                    taicpu(hp2).opcode := A_FADD
+                  else
+                    taicpu(hp2).opcode := A_FMUL;
+                  taicpu(hp2).oper[1]^.reg := NR_ST;
+                end
+              else
+              { change              to
+                  fld/fst mem1 (hp1)   fld/fst mem1
+                  fld     mem1 (p)     fld      st}
+                begin
+                  taicpu(p).changeopsize(S_FL);
+                  taicpu(p).loadreg(0,NR_ST);
+                end
+            else
+              begin
+                case taicpu(hp2).opcode Of
+                  A_FMULP,A_FADDP,A_FSUBP,A_FDIVP,A_FSUBRP,A_FDIVRP:
+            { change                        to
+                fld/fst  mem1    (hp1)      fld/fst    mem1
+                fld      mem2    (p)        fxxx       mem2
+                fxxxp    st, st1 (hp2)                      }
+
+                    begin
+                      case taicpu(hp2).opcode Of
+                        A_FADDP: taicpu(p).opcode := A_FADD;
+                        A_FMULP: taicpu(p).opcode := A_FMUL;
+                        A_FSUBP: taicpu(p).opcode := A_FSUBR;
+                        A_FSUBRP: taicpu(p).opcode := A_FSUB;
+                        A_FDIVP: taicpu(p).opcode := A_FDIVR;
+                        A_FDIVRP: taicpu(p).opcode := A_FDIV;
+                      end;
+                      asml.remove(hp2);
+                      hp2.free;
+                    end
+                end
+              end
+      end;
+
+
+   function TX86AsmOptimizer.OptPass2MOV(var p : tai) : boolean;
       var
       var
        hp1,hp2: tai;
        hp1,hp2: tai;
 {$ifdef x86_64}
 {$ifdef x86_64}

+ 50 - 0
compiler/x86/cgx86.pas

@@ -1140,6 +1140,38 @@ unit cgx86;
                 end;
                 end;
               end;
               end;
 {$endif i386}
 {$endif i386}
+{$ifdef x86_64}
+            if refaddr=addr_tpoff then
+              begin
+                { Convert thread local address to a process global addres
+                  as we cannot handle far pointers.}
+                case target_info.system of
+                  system_x86_64_linux:
+                    if segment=NR_FS then
+                      begin
+                        reference_reset(tmpref,1,[]);
+                        tmpref.segment:=NR_FS;
+                        tmpreg:=getaddressregister(list);
+                        a_load_ref_reg(list,OS_ADDR,OS_ADDR,tmpref,tmpreg);
+                        reference_reset(tmpref,1,[]);
+                        tmpref.symbol:=symbol;
+                        tmpref.refaddr:=refaddr;
+                        tmpref.base:=tmpreg;
+                        if base<>NR_NO then
+                          tmpref.index:=base;
+                        list.concat(Taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,tmpreg));
+                        segment:=NR_NO;
+                        base:=tmpreg;
+                        symbol:=nil;
+                        refaddr:=addr_no;
+                      end
+                    else
+                      Internalerror(2019012003);
+                  else
+                    Internalerror(2019012004);
+                end;
+              end;
+{$endif x86_64}
             if (base=NR_NO) and (index=NR_NO) then
             if (base=NR_NO) and (index=NR_NO) then
               begin
               begin
                 if assigned(dirref.symbol) then
                 if assigned(dirref.symbol) then
@@ -2814,6 +2846,24 @@ unit cgx86;
            dstref.base:=r;
            dstref.base:=r;
          end;
          end;
 {$endif i386}
 {$endif i386}
+{$ifdef x86_64}
+      { we could handle "far" pointers here, but reloading es/ds is probably much slower
+        than just resolving the tls segment }
+      if (srcref.refaddr=addr_tpoff) and (srcref.segment=NR_FS) then
+        begin
+          r:=getaddressregister(list);
+          a_loadaddr_ref_reg(list,srcref,r);
+          reference_reset(srcref,srcref.alignment,srcref.volatility);
+          srcref.base:=r;
+        end;
+       if (dstref.refaddr=addr_tpoff) and (dstref.segment=NR_FS) then
+         begin
+           r:=getaddressregister(list);
+           a_loadaddr_ref_reg(list,dstref,r);
+           reference_reset(dstref,dstref.alignment,dstref.volatility);
+           dstref.base:=r;
+         end;
+{$endif x86_64}
       cm:=copy_move;
       cm:=copy_move;
       helpsize:=3*sizeof(aword);
       helpsize:=3*sizeof(aword);
       if cs_opt_size in current_settings.optimizerswitches then
       if cs_opt_size in current_settings.optimizerswitches then

+ 39 - 0
compiler/x86/nx86ld.pas

@@ -121,6 +121,45 @@ implementation
                 end;
                 end;
             end;
             end;
 {$endif i386}
 {$endif i386}
+{$ifdef x86_64}
+            case target_info.system of
+              system_x86_64_linux:
+                begin
+                  case current_settings.tlsmodel of
+                    tlsm_local:
+                      begin
+                        location.reference.segment:=NR_FS;
+                        location.reference.refaddr:=addr_tpoff;
+                      end;
+                    tlsm_general:
+                      begin
+                        if not(cs_create_pic in current_settings.moduleswitches) then
+                          Internalerror(2019012001);
+
+                        current_asmdata.CurrAsmList.concat(tai_const.Create_8bit($66));
+                        reference_reset(href,0,[]);
+                        location.reference.base:=NR_RIP;
+                        location.reference.scalefactor:=1;
+                        location.reference.refaddr:=addr_tlsgd;
+                        cg.getcpuregister(current_asmdata.CurrAsmList,NR_RDI);
+                        current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_LEA,S_Q,location.reference,NR_RDI));
+                        current_asmdata.CurrAsmList.concat(tai_const.Create_8bit($66));
+                        current_asmdata.CurrAsmList.concat(tai_const.Create_8bit($66));
+                        current_asmdata.CurrAsmList.concat(tai_const.Create_8bit($48));
+                        cg.g_call(current_asmdata.CurrAsmList,'__tls_get_addr');
+                        cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_RDI);
+                        cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EAX);
+                        hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+                        cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_RAX,hregister);
+                        reference_reset(location.reference,location.reference.alignment,location.reference.volatility);
+                        location.reference.base:=hregister;
+                      end;
+                    else
+                      Internalerror(2019012002);
+                  end;
+                end;
+            end;
+{$endif x86_64}
           end;
           end;
       end;
       end;
 
 

+ 43 - 0
compiler/x86/x86ins.dat

@@ -3582,6 +3582,21 @@ void                   \326\1\xAD                                    X86_64
 (Ch_RWRSI, Ch_RMemEDI, Ch_RWRDI, Ch_RDirFlag, Ch_WOverflowFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WAuxiliaryFlag, Ch_WCarryFlag, Ch_WParityFlag)
 (Ch_RWRSI, Ch_RMemEDI, Ch_RWRDI, Ch_RDirFlag, Ch_WOverflowFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WAuxiliaryFlag, Ch_WCarryFlag, Ch_WParityFlag)
 void                   \326\1\xA7                                    X86_64
 void                   \326\1\xA7                                    X86_64
 
 
+[MOVBE,movbeX]
+(Ch_Rop1, Ch_Wop2)
+reg16|32|64,mem16|32|64              \320\3\xf\x38\xf0\110           MOVBE,SM
+mem16|32|64,reg16|32|64              \321\3\xf\x38\xf1\101           MOVBE,SM
+
+
+;*******************************************************************************
+;********* CLMUL ***************************************************************
+;*******************************************************************************
+
+[PCLMULQDQ]
+(Ch_All)
+xmmreg,xmmrm,imm8                    \361\3\xf\x3A\x44\110\26        CLMUL,SANDYBRIDGE
+
+
 ;*******************************************************************************
 ;*******************************************************************************
 ;****** AVX I ******************************************************************
 ;****** AVX I ******************************************************************
 ;*******************************************************************************
 ;*******************************************************************************
@@ -5285,6 +5300,21 @@ reg64,reg64,rm64                      \362\363\371\1\xf2\75\120           BMI1,P
 reg32,rm32,reg32                      \362\371\1\xf7\76\110               BMI1,PROT
 reg32,rm32,reg32                      \362\371\1\xf7\76\110               BMI1,PROT
 reg64,rm64,reg64                      \362\363\371\1\xf7\76\110           BMI1,PROT,X86_64
 reg64,rm64,reg64                      \362\363\371\1\xf7\76\110           BMI1,PROT,X86_64
 
 
+[BLSI]
+(Ch_Rop1, Ch_Wop2, Ch_W0OverflowFlag, Ch_WCarryFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WUParityFlag, Ch_WUAuxiliaryFlag)
+reg32,rm32                            \362\371\1\xf3\74\213               BMI1,PROT
+reg64,rm64                            \362\363\371\1\xf3\74\213           BMI1,PROT,X86_64
+
+[BLSMSK]
+(Ch_Rop1, Ch_Wop2, Ch_W0OverflowFlag, Ch_WCarryFlag, Ch_WSignFlag, Ch_W0ZeroFlag, Ch_WUParityFlag, Ch_WUAuxiliaryFlag)
+reg32,rm32                            \362\371\1\xf3\74\212               BMI1,PROT
+reg64,rm64                            \362\363\371\1\xf3\74\212           BMI1,PROT,X86_64
+
+[BLSR]
+(Ch_Rop1, Ch_Wop2, Ch_W0OverflowFlag, Ch_WCarryFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WUParityFlag, Ch_WUAuxiliaryFlag)
+reg32,rm32                            \362\371\1\xf3\74\211               BMI1,PROT
+reg64,rm64                            \362\363\371\1\xf3\74\211           BMI1,PROT,X86_64
+
 [TZCNT]
 [TZCNT]
 (Ch_Wop2, Ch_WFlags, Ch_Rop1)
 (Ch_Wop2, Ch_WFlags, Ch_Rop1)
 reg16|32|64,regmem                    \320\333\2\x0F\xBC\110              BMI1,SM
 reg16|32|64,regmem                    \320\333\2\x0F\xBC\110              BMI1,SM
@@ -5333,6 +5363,19 @@ reg64,rm64,reg64                      \361\362\363\371\1\xf7\76\110       BMI2,P
 reg32,rm32,reg32                      \334\362\371\1\xf7\76\110           BMI2,PROT
 reg32,rm32,reg32                      \334\362\371\1\xf7\76\110           BMI2,PROT
 reg64,rm64,reg64                      \334\362\363\371\1\xf7\76\110       BMI2,PROT,X86_64
 reg64,rm64,reg64                      \334\362\363\371\1\xf7\76\110       BMI2,PROT,X86_64
 
 
+;*******************************************************************************
+;********** ADX ****************************************************************
+;*******************************************************************************
+
+[ADCX,adcxX]
+(Ch_Rop1, Ch_Mop2, Ch_RWCarryFlag)
+reg32,rm32                            \361\3\xf\x38\xf6\110               ADX
+reg64,rm64                            \361\326\3\xf\x38\xf6\110           ADX,X86_64
+
+[ADOX,adoxX]
+(Ch_Rop1, Ch_Mop2, Ch_RWOverflowFlag)
+reg32,rm32                            \333\3\xf\x38\xf6\110               ADX
+reg64,rm64                            \333\326\3\xf\x38\xf6\110           ADX,X86_64
 
 
 ;*******************************************************************************
 ;*******************************************************************************
 ;********** AVX2 ***************************************************************
 ;********** AVX2 ***************************************************************

+ 4 - 0
compiler/x86_64/aoptcpu.pas

@@ -118,6 +118,10 @@ uses
                 result:=OptPass1SHLSAL(p);
                 result:=OptPass1SHLSAL(p);
               A_SETcc:
               A_SETcc:
                 result:=OptPass1SETcc(p);
                 result:=OptPass1SETcc(p);
+              A_FSTP,A_FISTP:
+                result:=OptPass1FSTP(p);
+              A_FLD:
+                result:=OptPass1FLD(p);
             end;
             end;
           end;
           end;
         end;
         end;

+ 1 - 0
compiler/x86_64/cpunode.pas

@@ -53,6 +53,7 @@ unit cpunode;
        nx86con,
        nx86con,
        nx86mem,
        nx86mem,
        nx64add,
        nx64add,
+       nx86ld,
        nx64cal,
        nx64cal,
        nx64cnv,
        nx64cnv,
        nx64mat,
        nx64mat,

+ 7 - 0
compiler/x86_64/x8664ats.inc

@@ -680,6 +680,8 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufINT,
+attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
@@ -1017,6 +1019,11 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,

+ 7 - 0
compiler/x86_64/x8664att.inc

@@ -680,6 +680,8 @@
 'stosq',
 'stosq',
 'lodsq',
 'lodsq',
 'cmpsq',
 'cmpsq',
+'movbe',
+'pclmulqdq',
 'vaddpd',
 'vaddpd',
 'vaddps',
 'vaddps',
 'vaddsd',
 'vaddsd',
@@ -1005,6 +1007,9 @@
 'vzeroupper',
 'vzeroupper',
 'andn',
 'andn',
 'bextr',
 'bextr',
+'blsi',
+'blsmsk',
+'blsr',
 'tzcnt',
 'tzcnt',
 'bzhi',
 'bzhi',
 'mulx',
 'mulx',
@@ -1014,6 +1019,8 @@
 'sarx',
 'sarx',
 'shlx',
 'shlx',
 'shrx',
 'shrx',
+'adcx',
+'adox',
 'vbroadcasti128',
 'vbroadcasti128',
 'vextracti128',
 'vextracti128',
 'vinserti128',
 'vinserti128',

+ 7 - 0
compiler/x86_64/x8664int.inc

@@ -680,6 +680,8 @@
 'stosq',
 'stosq',
 'lodsq',
 'lodsq',
 'cmpsq',
 'cmpsq',
+'movbe',
+'pclmulqdq',
 'vaddpd',
 'vaddpd',
 'vaddps',
 'vaddps',
 'vaddsd',
 'vaddsd',
@@ -1005,6 +1007,9 @@
 'vzeroupper',
 'vzeroupper',
 'andn',
 'andn',
 'bextr',
 'bextr',
+'blsi',
+'blsmsk',
+'blsr',
 'tzcnt',
 'tzcnt',
 'bzhi',
 'bzhi',
 'mulx',
 'mulx',
@@ -1014,6 +1019,8 @@
 'sarx',
 'sarx',
 'shlx',
 'shlx',
 'shrx',
 'shrx',
+'adcx',
+'adox',
 'vbroadcasti128',
 'vbroadcasti128',
 'vextracti128',
 'vextracti128',
 'vinserti128',
 'vinserti128',

+ 1 - 1
compiler/x86_64/x8664nop.inc

@@ -1,2 +1,2 @@
 { don't edit, this file is generated from x86ins.dat }
 { don't edit, this file is generated from x86ins.dat }
-2178;
+2191;

+ 7 - 0
compiler/x86_64/x8664op.inc

@@ -680,6 +680,8 @@ A_RDTSCP,
 A_STOSQ,
 A_STOSQ,
 A_LODSQ,
 A_LODSQ,
 A_CMPSQ,
 A_CMPSQ,
+A_MOVBE,
+A_PCLMULQDQ,
 A_VADDPD,
 A_VADDPD,
 A_VADDPS,
 A_VADDPS,
 A_VADDSD,
 A_VADDSD,
@@ -1005,6 +1007,9 @@ A_VZEROALL,
 A_VZEROUPPER,
 A_VZEROUPPER,
 A_ANDN,
 A_ANDN,
 A_BEXTR,
 A_BEXTR,
+A_BLSI,
+A_BLSMSK,
+A_BLSR,
 A_TZCNT,
 A_TZCNT,
 A_BZHI,
 A_BZHI,
 A_MULX,
 A_MULX,
@@ -1014,6 +1019,8 @@ A_RORX,
 A_SARX,
 A_SARX,
 A_SHLX,
 A_SHLX,
 A_SHRX,
 A_SHRX,
+A_ADCX,
+A_ADOX,
 A_VBROADCASTI128,
 A_VBROADCASTI128,
 A_VEXTRACTI128,
 A_VEXTRACTI128,
 A_VINSERTI128,
 A_VINSERTI128,

+ 7 - 0
compiler/x86_64/x8664pro.inc

@@ -680,6 +680,8 @@
 (Ch: [Ch_RRAX, Ch_WMemEDI, Ch_RWRDI, Ch_RDirFlag]),
 (Ch: [Ch_RRAX, Ch_WMemEDI, Ch_RWRDI, Ch_RDirFlag]),
 (Ch: [Ch_WRAX, Ch_RWRSI, Ch_RDirFlag]),
 (Ch: [Ch_WRAX, Ch_RWRSI, Ch_RDirFlag]),
 (Ch: [Ch_RWRSI, Ch_RMemEDI, Ch_RWRDI, Ch_RDirFlag, Ch_WOverflowFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WAuxiliaryFlag, Ch_WCarryFlag, Ch_WParityFlag]),
 (Ch: [Ch_RWRSI, Ch_RMemEDI, Ch_RWRDI, Ch_RDirFlag, Ch_WOverflowFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WAuxiliaryFlag, Ch_WCarryFlag, Ch_WParityFlag]),
+(Ch: [Ch_Rop1, Ch_Wop2]),
+(Ch: [Ch_All]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
 (Ch: [Ch_Wop3, Ch_Rop2, Ch_Rop1]),
@@ -1005,6 +1007,9 @@
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
+(Ch: [Ch_Rop1, Ch_Wop2, Ch_W0OverflowFlag, Ch_WCarryFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WUParityFlag, Ch_WUAuxiliaryFlag]),
+(Ch: [Ch_Rop1, Ch_Wop2, Ch_W0OverflowFlag, Ch_WCarryFlag, Ch_WSignFlag, Ch_W0ZeroFlag, Ch_WUParityFlag, Ch_WUAuxiliaryFlag]),
+(Ch: [Ch_Rop1, Ch_Wop2, Ch_W0OverflowFlag, Ch_WCarryFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WUParityFlag, Ch_WUAuxiliaryFlag]),
 (Ch: [Ch_Wop2, Ch_WFlags, Ch_Rop1]),
 (Ch: [Ch_Wop2, Ch_WFlags, Ch_Rop1]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_REDX, Ch_Rop1, Ch_Wop2, Ch_Wop3]),
 (Ch: [Ch_REDX, Ch_Rop1, Ch_Wop2, Ch_Wop3]),
@@ -1014,6 +1019,8 @@
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
 (Ch: [Ch_Rop1, Ch_Rop2, Ch_Wop3]),
+(Ch: [Ch_Rop1, Ch_Mop2, Ch_RWCarryFlag]),
+(Ch: [Ch_Rop1, Ch_Mop2, Ch_RWOverflowFlag]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),

+ 91 - 0
compiler/x86_64/x8664tab.inc

@@ -9009,6 +9009,27 @@
     code    : #214#1#167;
     code    : #214#1#167;
     flags   : [if_x86_64]
     flags   : [if_x86_64]
   ),
   ),
+  (
+    opcode  : A_MOVBE;
+    ops     : 2;
+    optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+    code    : #208#3#15#56#240#72;
+    flags   : [if_movbe,if_sm]
+  ),
+  (
+    opcode  : A_MOVBE;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits16 or ot_bits32 or ot_bits64,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+    code    : #209#3#15#56#241#65;
+    flags   : [if_movbe,if_sm]
+  ),
+  (
+    opcode  : A_PCLMULQDQ;
+    ops     : 3;
+    optypes : (ot_xmmreg,ot_xmmrm,ot_immediate or ot_bits8,ot_none);
+    code    : #241#3#15#58#68#72#22;
+    flags   : [if_clmul,if_sandybridge]
+  ),
   (
   (
     opcode  : A_VADDPD;
     opcode  : A_VADDPD;
     ops     : 3;
     ops     : 3;
@@ -13951,6 +13972,48 @@
     code    : #242#243#249#1#247#62#72;
     code    : #242#243#249#1#247#62#72;
     flags   : [if_bmi1,if_prot,if_x86_64]
     flags   : [if_bmi1,if_prot,if_x86_64]
   ),
   ),
+  (
+    opcode  : A_BLSI;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #242#249#1#243#60#139;
+    flags   : [if_bmi1,if_prot]
+  ),
+  (
+    opcode  : A_BLSI;
+    ops     : 2;
+    optypes : (ot_reg64,ot_rm_gpr or ot_bits64,ot_none,ot_none);
+    code    : #242#243#249#1#243#60#139;
+    flags   : [if_bmi1,if_prot,if_x86_64]
+  ),
+  (
+    opcode  : A_BLSMSK;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #242#249#1#243#60#138;
+    flags   : [if_bmi1,if_prot]
+  ),
+  (
+    opcode  : A_BLSMSK;
+    ops     : 2;
+    optypes : (ot_reg64,ot_rm_gpr or ot_bits64,ot_none,ot_none);
+    code    : #242#243#249#1#243#60#138;
+    flags   : [if_bmi1,if_prot,if_x86_64]
+  ),
+  (
+    opcode  : A_BLSR;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #242#249#1#243#60#137;
+    flags   : [if_bmi1,if_prot]
+  ),
+  (
+    opcode  : A_BLSR;
+    ops     : 2;
+    optypes : (ot_reg64,ot_rm_gpr or ot_bits64,ot_none,ot_none);
+    code    : #242#243#249#1#243#60#137;
+    flags   : [if_bmi1,if_prot,if_x86_64]
+  ),
   (
   (
     opcode  : A_TZCNT;
     opcode  : A_TZCNT;
     ops     : 2;
     ops     : 2;
@@ -14070,6 +14133,34 @@
     code    : #220#242#243#249#1#247#62#72;
     code    : #220#242#243#249#1#247#62#72;
     flags   : [if_bmi2,if_prot,if_x86_64]
     flags   : [if_bmi2,if_prot,if_x86_64]
   ),
   ),
+  (
+    opcode  : A_ADCX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #241#3#15#56#246#72;
+    flags   : [if_adx]
+  ),
+  (
+    opcode  : A_ADCX;
+    ops     : 2;
+    optypes : (ot_reg64,ot_rm_gpr or ot_bits64,ot_none,ot_none);
+    code    : #241#214#3#15#56#246#72;
+    flags   : [if_adx,if_x86_64]
+  ),
+  (
+    opcode  : A_ADOX;
+    ops     : 2;
+    optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+    code    : #219#3#15#56#246#72;
+    flags   : [if_adx]
+  ),
+  (
+    opcode  : A_ADOX;
+    ops     : 2;
+    optypes : (ot_reg64,ot_rm_gpr or ot_bits64,ot_none,ot_none);
+    code    : #219#214#3#15#56#246#72;
+    flags   : [if_adx,if_x86_64]
+  ),
   (
   (
     opcode  : A_VBROADCASTI128;
     opcode  : A_VBROADCASTI128;
     ops     : 2;
     ops     : 2;

+ 21 - 9
packages/fcl-base/src/uriparser.pp

@@ -40,11 +40,11 @@ function EncodeURI(const URI: TURI): String;
 function ParseURI(const URI: String; Decode : Boolean = True):  TURI; overload;
 function ParseURI(const URI: String; Decode : Boolean = True):  TURI; overload;
 function ParseURI(const URI, DefaultProtocol: String; DefaultPort: Word; Decode : Boolean = True):  TURI; overload;
 function ParseURI(const URI, DefaultProtocol: String; DefaultPort: Word; Decode : Boolean = True):  TURI; overload;
 
 
-function ResolveRelativeURI(const BaseUri, RelUri: WideString;
-  out ResultUri: WideString): Boolean; overload;
-
-function ResolveRelativeURI(const BaseUri, RelUri: AnsiString;
-  out ResultUri: AnsiString): Boolean; overload;
+function ResolveRelativeURI(const BaseUri, RelUri: UnicodeString;out ResultUri: UnicodeString): Boolean; overload;
+{$ifdef WINDOWS}  
+function ResolveRelativeURI(const BaseUri, RelUri: WideString; out ResultUri: WideString): Boolean; overload;
+{$ENDIF}
+function ResolveRelativeURI(const BaseUri, RelUri: AnsiString;  out ResultUri: AnsiString): Boolean; overload;
 
 
 function URIToFilename(const URI: string; out Filename: string): Boolean;
 function URIToFilename(const URI: string; out Filename: string): Boolean;
 function FilenameToURI(const Filename: string; Encode : Boolean = True): string;
 function FilenameToURI(const Filename: string; Encode : Boolean = True): string;
@@ -335,8 +335,7 @@ begin
   end;
   end;
 end;
 end;
 
 
-function ResolveRelativeURI(const BaseUri, RelUri: AnsiString;
-  out ResultUri: AnsiString): Boolean;
+function ResolveRelativeURI(const BaseUri, RelUri: AnsiString; out ResultUri: AnsiString): Boolean;
 var
 var
   Base, Rel: TUri;
   Base, Rel: TUri;
 begin
 begin
@@ -384,8 +383,21 @@ begin
   ResultUri := EncodeUri(Rel);
   ResultUri := EncodeUri(Rel);
 end;
 end;
 
 
-function ResolveRelativeURI(const BaseUri, RelUri: WideString;
-  out ResultUri: WideString): Boolean;
+{$IFDEF WINDOWS}
+function ResolveRelativeURI(const BaseUri, RelUri: WideString; out ResultUri: WideString): Boolean;
+
+Var
+  Res : AnsiString;
+
+begin
+  Result := ResolveRelativeURI(UTF8Encode(BaseUri), UTF8Encode(RelUri), Res);
+  if Result then
+    ResultURI := UTF8Decode(res);
+end;
+{$ENDIF}
+
+function ResolveRelativeURI(const BaseUri, RelUri: UnicodeString;
+  out ResultUri: UnicodeString): Boolean;
 var
 var
   rslt: AnsiString;
   rslt: AnsiString;
 begin
 begin

+ 13 - 3
packages/fcl-image/src/fpreadgif.pas

@@ -211,7 +211,10 @@ begin
     // skip extensions
     // skip extensions
     Repeat
     Repeat
       Introducer:=SkipBlock(Stream);
       Introducer:=SkipBlock(Stream);
-    until (Introducer = $2C) or (Introducer = $3B);
+    until (Introducer = $2C) or (Introducer = $3B) or (Stream.Position>=Stream.Size);
+    
+    if Stream.Position>=Stream.Size then 
+      Exit;
 
 
     // descriptor
     // descriptor
     Stream.Read(FDescriptor, SizeOf(FDescriptor));
     Stream.Read(FDescriptor, SizeOf(FDescriptor));
@@ -298,7 +301,10 @@ begin
         Stream.Seek(B, soFromCurrent);
         Stream.Seek(B, soFromCurrent);
         CodeMask := (1 shl CodeSize) - 1;
         CodeMask := (1 shl CodeSize) - 1;
       end;
       end;
-    until B = 0;
+    until (B = 0)  or (Stream.Position>=Stream.Size);
+    
+    if Stream.Position>=Stream.Size then 
+      Exit(False);
 
 
     Progress(psRunning, trunc(100.0 * (Stream.position / Stream.size)),
     Progress(psRunning, trunc(100.0 * (Stream.position / Stream.size)),
              False, Rect(0,0,0,0), '', ContProgress);
              False, Rect(0,0,0,0), '', ContProgress);
@@ -315,7 +321,11 @@ begin
          Stream.ReadBuffer(SourcePtr^, B);
          Stream.ReadBuffer(SourcePtr^, B);
          Inc(SourcePtr,B);
          Inc(SourcePtr,B);
       end;
       end;
-    until B = 0;
+    until (B = 0) or (Stream.Position>=Stream.Size);
+    
+    if Stream.Position>=Stream.Size then
+       Exit(False);
+              
 
 
     Progress(psRunning, trunc(100.0 * (Stream.position / Stream.size)),
     Progress(psRunning, trunc(100.0 * (Stream.position / Stream.size)),
              False, Rect(0,0,0,0), '', ContProgress);
              False, Rect(0,0,0,0), '', ContProgress);

+ 54 - 13
packages/fcl-js/src/jswriter.pp

@@ -247,6 +247,7 @@ Type
 {$ifdef FPC_HAS_CPSTRING}
 {$ifdef FPC_HAS_CPSTRING}
 Function UTF16ToUTF8(const S: UnicodeString): string;
 Function UTF16ToUTF8(const S: UnicodeString): string;
 {$endif}
 {$endif}
+Function QuoteJSString(const S: TJSString; Quote: TJSChar = #0): TJSString;
 
 
 implementation
 implementation
 
 
@@ -273,6 +274,35 @@ begin
 end;
 end;
 {$endif}
 {$endif}
 
 
+function QuoteJSString(const S: TJSString; Quote: TJSChar): TJSString;
+var
+  i, j, Count: Integer;
+begin
+  if Quote=#0 then
+    begin
+    if Pos('"',S)>0 then
+      Quote:=''''
+    else
+      Quote:='"';
+    end;
+  Result := '' + Quote;
+  Count := length(S);
+  i := 0;
+  j := 0;
+  while i < Count do
+    begin
+    inc(i);
+    if S[i] = Quote then
+      begin
+      Result := Result + copy(S, 1 + j, i - j) + Quote;
+      j := i;
+      end;
+    end;
+  if i <> j then
+    Result := Result + copy(S, 1 + j, i - j);
+  Result := Result + Quote;
+end;
+
 { TBufferWriter }
 { TBufferWriter }
 
 
 function TBufferWriter.GetBufferLength: Integer;
 function TBufferWriter.GetBufferLength: Integer;
@@ -651,7 +681,7 @@ Var
   p, StartP: Integer;
   p, StartP: Integer;
   MinIndent, CurLineIndent, j, Exp, Code: Integer;
   MinIndent, CurLineIndent, j, Exp, Code: Integer;
   i: SizeInt;
   i: SizeInt;
-  D: TJSNumber;
+  D, AsNumber: TJSNumber;
 begin
 begin
   if V.CustomValue<>'' then
   if V.CustomValue<>'' then
     begin
     begin
@@ -706,15 +736,17 @@ begin
       exit;
       exit;
       end;
       end;
     jstNumber :
     jstNumber :
-      if (Frac(V.AsNumber)=0)
-          and (V.AsNumber>=double(MinSafeIntDouble))
-          and (V.AsNumber<=double(MaxSafeIntDouble)) then
+      begin
+      AsNumber:=V.AsNumber;
+      if (Frac(AsNumber)=0)
+          and (AsNumber>=double(MinSafeIntDouble))
+          and (AsNumber<=double(MaxSafeIntDouble)) then
         begin
         begin
-        Str(Round(V.AsNumber),S);
+        Str(Round(AsNumber),S);
         end
         end
       else
       else
         begin
         begin
-        Str(V.AsNumber,S);
+        Str(AsNumber,S);
         if S[1]=' ' then Delete(S,1,1);
         if S[1]=' ' then Delete(S,1,1);
         i:=Pos('E',S);
         i:=Pos('E',S);
         if (i>2) then
         if (i>2) then
@@ -728,7 +760,7 @@ begin
             if s[j]='.' then inc(j);
             if s[j]='.' then inc(j);
             S2:=LeftStr(S,j)+copy(S,i,length(S));
             S2:=LeftStr(S,j)+copy(S,i,length(S));
             val(S2,D,Code);
             val(S2,D,Code);
-            if (Code=0) and (D=V.AsNumber) then
+            if (Code=0) and (D=AsNumber) then
               S:=S2;
               S:=S2;
             end;
             end;
           '9':
           '9':
@@ -766,7 +798,7 @@ begin
                 end;
                 end;
             until false;
             until false;
             val(S2,D,Code);
             val(S2,D,Code);
-            if (Code=0) and (D=V.AsNumber) then
+            if (Code=0) and (D=AsNumber) then
               S:=S2;
               S:=S2;
             end;
             end;
           end;
           end;
@@ -783,6 +815,7 @@ begin
               Delete(S,i,length(S))
               Delete(S,i,length(S))
             else if (Exp>=-6) and (Exp<=6) then
             else if (Exp>=-6) and (Exp<=6) then
               begin
               begin
+              // small exponent -> use notation without E
               Delete(S,i,length(S));
               Delete(S,i,length(S));
               j:=Pos('.',S);
               j:=Pos('.',S);
               if j>0 then
               if j>0 then
@@ -826,12 +859,16 @@ begin
               end
               end
             else
             else
               begin
               begin
-              // e.g. 1.0E+001  -> 1.0E1
+              // e.g. 1.1E+0010  -> 1.1E10
               S:=LeftStr(S,i)+IntToStr(Exp);
               S:=LeftStr(S,i)+IntToStr(Exp);
+              if (i >= 4) and (s[i-1] = '0') and (s[i-2] = '.') then
+                // e.g. 1.0E22 -> 1E22
+                Delete(S, i-2, 2);
               end
               end
             end;
             end;
           end;
           end;
         end;
         end;
+      end;
     jstObject : ;
     jstObject : ;
     jstReference : ;
     jstReference : ;
     jstCompletion : ;
     jstCompletion : ;
@@ -1023,14 +1060,11 @@ end;
 
 
 
 
 procedure TJSWriter.WriteObjectLiteral(El: TJSObjectLiteral);
 procedure TJSWriter.WriteObjectLiteral(El: TJSObjectLiteral);
-
-
 Var
 Var
   i,C : Integer;
   i,C : Integer;
   QE,WC : Boolean;
   QE,WC : Boolean;
   S : TJSString;
   S : TJSString;
   Prop: TJSObjectLiteralElement;
   Prop: TJSObjectLiteralElement;
-
 begin
 begin
   C:=El.Elements.Count-1;
   C:=El.Elements.Count-1;
   QE:=(woQuoteElementNames in Options);
   QE:=(woQuoteElementNames in Options);
@@ -1053,7 +1087,14 @@ begin
    Writer.CurElement:=Prop.Expr;
    Writer.CurElement:=Prop.Expr;
    S:=Prop.Name;
    S:=Prop.Name;
    if QE or not IsValidJSIdentifier(S) then
    if QE or not IsValidJSIdentifier(S) then
-     S:='"'+S+'"';
+     begin
+     if (length(S)>1)
+         and (((S[1]='"') and (S[length(S)]='"'))
+           or ((S[1]='''') and (S[length(S)]=''''))) then
+       // already quoted
+     else
+       S:=QuoteJSString(s);
+     end;
    Write(S+': ');
    Write(S+': ');
    Indent;
    Indent;
    FSkipRoundBrackets:=true;
    FSkipRoundBrackets:=true;

+ 104 - 30
packages/fcl-passrc/src/pasresolveeval.pas

@@ -25,7 +25,7 @@ Works:
 - int/uint
 - int/uint
   - unary +, -
   - unary +, -
   - binary: +, -, *, div, mod, ^^, =, <>, <, >, <=, >=, and, or, xor, not, shl, shr
   - binary: +, -, *, div, mod, ^^, =, <>, <, >, <=, >=, and, or, xor, not, shl, shr
-  - low(), high(), pred(), succ(), ord()
+  - Low(), High(), Pred(), Succ(), Ord(), Lo(), Hi()
   - typecast longint(-1), word(-2), intsingle(-1), uintsingle(1)
   - typecast longint(-1), word(-2), intsingle(-1), uintsingle(1)
 - float:
 - float:
   - typecast single(double), double(single), float(integer)
   - typecast single(double), double(single), float(integer)
@@ -119,7 +119,7 @@ const
   nWrongNumberOfParametersForArray = 3042;
   nWrongNumberOfParametersForArray = 3042;
   nCantAssignValuesToAnAddress = 3043;
   nCantAssignValuesToAnAddress = 3043;
   nIllegalExpression = 3044;
   nIllegalExpression = 3044;
-  nCantAccessPrivateMember = 3045;
+  nCantAccessXMember = 3045;
   nMustBeInsideALoop = 3046;
   nMustBeInsideALoop = 3046;
   nExpectXArrayElementsButFoundY = 3047;
   nExpectXArrayElementsButFoundY = 3047;
   nCannotCreateADescendantOfTheSealedXY = 3048;
   nCannotCreateADescendantOfTheSealedXY = 3048;
@@ -178,6 +178,9 @@ const
   nFunctionHidesIdentifier_NonProc = 3112;
   nFunctionHidesIdentifier_NonProc = 3112;
   nTypeXCannotBeExtendedByATypeHelper = 3113;
   nTypeXCannotBeExtendedByATypeHelper = 3113;
   nDerivedXMustExtendASubClassY = 3114;
   nDerivedXMustExtendASubClassY = 3114;
+  nDefaultPropertyNotAllowedInHelperForX = 3115;
+  nHelpersCannotBeUsedAsTypes = 3116;
+  nBitWiseOperationsAre32Bit = 3117;
 
 
   // using same IDs as FPC
   // using same IDs as FPC
   nVirtualMethodXHasLowerVisibility = 3250; // was 3050
   nVirtualMethodXHasLowerVisibility = 3250; // was 3050
@@ -236,7 +239,7 @@ resourcestring
   sWrongNumberOfParametersForArray = 'Wrong number of parameters for array';
   sWrongNumberOfParametersForArray = 'Wrong number of parameters for array';
   sCantAssignValuesToAnAddress = 'Can''t assign values to an address';
   sCantAssignValuesToAnAddress = 'Can''t assign values to an address';
   sIllegalExpression = 'Illegal expression';
   sIllegalExpression = 'Illegal expression';
-  sCantAccessPrivateMember = 'Can''t access %s member %s';
+  sCantAccessXMember = 'Can''t access %s member %s';
   sMustBeInsideALoop = '%s must be inside a loop';
   sMustBeInsideALoop = '%s must be inside a loop';
   sExpectXArrayElementsButFoundY = 'Expect %s array elements, but found %s';
   sExpectXArrayElementsButFoundY = 'Expect %s array elements, but found %s';
   sCannotCreateADescendantOfTheSealedXY = 'Cannot create a descendant of the sealed %s "%s"';
   sCannotCreateADescendantOfTheSealedXY = 'Cannot create a descendant of the sealed %s "%s"';
@@ -303,6 +306,9 @@ resourcestring
   sIllegalAssignmentToForLoopVar = 'Illegal assignment to for-loop variable "%s"';
   sIllegalAssignmentToForLoopVar = 'Illegal assignment to for-loop variable "%s"';
   sTypeXCannotBeExtendedByATypeHelper = 'Type "%s" cannot be extended by a type helper';
   sTypeXCannotBeExtendedByATypeHelper = 'Type "%s" cannot be extended by a type helper';
   sDerivedXMustExtendASubClassY = 'Derived %s must extend a subclass of "%s" or the class itself';
   sDerivedXMustExtendASubClassY = 'Derived %s must extend a subclass of "%s" or the class itself';
+  sDefaultPropertyNotAllowedInHelperForX = 'Default property not allowed in helper for %s';
+  sHelpersCannotBeUsedAsTypes = 'helpers cannot be used as types';
+  sBitWiseOperationsAre32Bit = 'Bitwise operations are 32-bit';
 
 
 type
 type
   { TResolveData - base class for data stored in TPasElement.CustomData }
   { TResolveData - base class for data stored in TPasElement.CustomData }
@@ -708,6 +714,8 @@ type
     function EvalStrFunc(Params: TParamsExpr; Flags: TResEvalFlags): TResEvalValue; virtual;
     function EvalStrFunc(Params: TParamsExpr; Flags: TResEvalFlags): TResEvalValue; virtual;
     function EvalStringAddExpr(Expr, LeftExpr, RightExpr: TPasExpr;
     function EvalStringAddExpr(Expr, LeftExpr, RightExpr: TPasExpr;
       LeftValue, RightValue: TResEvalValue): TResEvalValue; virtual;
       LeftValue, RightValue: TResEvalValue): TResEvalValue; virtual;
+    function LoHiValue(Value: TResEvalValue; ShiftSize: Integer; Mask: LongWord;
+      ErrorEl: TPasElement): TResEvalValue; virtual;
     function EnumTypeCast(EnumType: TPasEnumType; Expr: TPasExpr;
     function EnumTypeCast(EnumType: TPasEnumType; Expr: TPasExpr;
       Flags: TResEvalFlags): TResEvalEnum; virtual;
       Flags: TResEvalFlags): TResEvalEnum; virtual;
     {$ifdef FPC_HAS_CPSTRING}
     {$ifdef FPC_HAS_CPSTRING}
@@ -729,6 +737,7 @@ type
   TResExprEvaluatorClass = class of TResExprEvaluator;
   TResExprEvaluatorClass = class of TResExprEvaluator;
 
 
 procedure ReleaseEvalValue(var Value: TResEvalValue);
 procedure ReleaseEvalValue(var Value: TResEvalValue);
+function NumberIsFloat(const Value: string): boolean;
 
 
 {$ifdef FPC_HAS_CPSTRING}
 {$ifdef FPC_HAS_CPSTRING}
 function RawStrToCaption(const r: RawByteString; MaxLength: integer): string;
 function RawStrToCaption(const r: RawByteString; MaxLength: integer): string;
@@ -751,6 +760,17 @@ begin
   Value:=nil;
   Value:=nil;
 end;
 end;
 
 
+function NumberIsFloat(const Value: string): boolean;
+var
+  i: Integer;
+begin
+  if Value='' then exit(false);
+  if Value[1] in ['$','%','&'] then exit(false);
+  for i:=2 to length(Value) do
+    if Value[i] in ['.','E','e'] then exit(true);
+  Result:=false;
+end;
+
 {$ifdef FPC_HAS_CPSTRING}
 {$ifdef FPC_HAS_CPSTRING}
 function RawStrToCaption(const r: RawByteString; MaxLength: integer): string;
 function RawStrToCaption(const r: RawByteString; MaxLength: integer): string;
 var
 var
@@ -1861,7 +1881,7 @@ begin
       // float - currency
       // float - currency
       try
       try
         {$Q+}
         {$Q+}
-        aCurrency:=aCurrency - TResEvalCurrency(RightValue).Value;
+        aCurrency:=Flo - TResEvalCurrency(RightValue).Value;
         {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
         {$IFNDEF OverflowCheckOn}{$Q-}{$ENDIF}
         Result:=TResEvalCurrency.CreateValue(aCurrency);
         Result:=TResEvalCurrency.CreateValue(aCurrency);
       except
       except
@@ -3886,6 +3906,8 @@ end;
 
 
 function TResExprEvaluator.ExprStringToOrd(Value: TResEvalValue;
 function TResExprEvaluator.ExprStringToOrd(Value: TResEvalValue;
   PosEl: TPasElement): longword;
   PosEl: TPasElement): longword;
+const
+  Invalid = $12345678; // bigger than $ffff and smaller than $8000000
 var
 var
   {$ifdef FPC_HAS_CPSTRING}
   {$ifdef FPC_HAS_CPSTRING}
   S: RawByteString;
   S: RawByteString;
@@ -3897,11 +3919,29 @@ begin
     begin
     begin
     // ord(ansichar)
     // ord(ansichar)
     S:=TResEvalString(Value).S;
     S:=TResEvalString(Value).S;
-    if length(S)<>1 then
-      RaiseMsg(20170522221143,nXExpectedButYFound,sXExpectedButYFound,
-        ['char','string'],PosEl)
+    if length(S)=1 then
+      Result:=ord(S[1])
+    else if (length(S)=0) or (length(S)>4) then
+      begin
+      if PosEl<>nil then
+        RaiseMsg(20170522221143,nXExpectedButYFound,sXExpectedButYFound,
+          ['char','string'],PosEl)
+      else
+        exit(Invalid);
+      end
     else
     else
-      Result:=ord(S[1]);
+      begin
+      U:=GetUnicodeStr(S,nil);
+      if length(U)<>1 then
+        begin
+        if PosEl<>nil then
+          RaiseMsg(20190124180407,nXExpectedButYFound,sXExpectedButYFound,
+            ['char','string'],PosEl)
+        else
+          exit(Invalid);
+        end;
+      Result:=ord(U[1]);
+      end;
     end
     end
   else
   else
   {$endif}
   {$endif}
@@ -3910,8 +3950,13 @@ begin
     // ord(widechar)
     // ord(widechar)
     U:=TResEvalUTF16(Value).S;
     U:=TResEvalUTF16(Value).S;
     if length(U)<>1 then
     if length(U)<>1 then
-      RaiseMsg(20170522221358,nXExpectedButYFound,sXExpectedButYFound,
-        ['char','string'],PosEl)
+      begin
+      if PosEl<>nil then
+        RaiseMsg(20170522221358,nXExpectedButYFound,sXExpectedButYFound,
+          ['char','string'],PosEl)
+      else
+        exit(Invalid);
+      end
     else
     else
       Result:=ord(U[1]);
       Result:=ord(U[1]);
     end
     end
@@ -3949,12 +3994,12 @@ function TResExprEvaluator.EvalPrimitiveExprString(Expr: TPrimitiveExpr
     {$endif}
     {$endif}
   end;
   end;
 
 
-  procedure AddHash(u: longword);
+  procedure AddHash(u: longword; ForceUTF16: boolean);
   {$ifdef FPC_HAS_CPSTRING}
   {$ifdef FPC_HAS_CPSTRING}
   var
   var
     h: RawByteString;
     h: RawByteString;
   begin
   begin
-    if (u>255) and (Result.Kind=revkString) then
+    if ((u>255) or (ForceUTF16)) and (Result.Kind=revkString) then
       begin
       begin
       // switch to unicodestring
       // switch to unicodestring
       h:=TResEvalString(Result).S;
       h:=TResEvalString(Result).S;
@@ -4056,11 +4101,11 @@ begin
           begin
           begin
           // split into two
           // split into two
           dec(u,$10000);
           dec(u,$10000);
-          AddHash($D800+(u shr 10));
-          AddHash($DC00+(u and $3ff));
+          AddHash($D800+(u shr 10),true);
+          AddHash($DC00+(u and $3ff),true);
           end
           end
         else
         else
-          AddHash(u);
+          AddHash(u,p-StartP>2);
         end
         end
       else
       else
         begin
         begin
@@ -4080,7 +4125,7 @@ begin
           end;
           end;
         if p=StartP then
         if p=StartP then
           RaiseInternalError(20170523123806);
           RaiseInternalError(20170523123806);
-        AddHash(u);
+        AddHash(u,false);
         end;
         end;
       end;
       end;
     '^':
     '^':
@@ -4091,8 +4136,8 @@ begin
         RaiseInternalError(20181016121520);
         RaiseInternalError(20181016121520);
       c:=S[p];
       c:=S[p];
       case c of
       case c of
-      'a'..'z': AddHash(ord(c)-ord('a')+1);
-      'A'..'Z': AddHash(ord(c)-ord('A')+1);
+      'a'..'z': AddHash(ord(c)-ord('a')+1,false);
+      'A'..'Z': AddHash(ord(c)-ord('A')+1,false);
       else RaiseInternalError(20170523123809);
       else RaiseInternalError(20170523123809);
       end;
       end;
       inc(p);
       inc(p);
@@ -4551,35 +4596,35 @@ end;
 
 
 function TResExprEvaluator.OrdValue(Value: TResEvalValue; ErrorEl: TPasElement
 function TResExprEvaluator.OrdValue(Value: TResEvalValue; ErrorEl: TPasElement
   ): TResEvalValue;
   ): TResEvalValue;
+var
+  v: longword;
 begin
 begin
+  Result:=nil;
+  v:=0;
   case Value.Kind of
   case Value.Kind of
     revkBool:
     revkBool:
       if TResEvalBool(Value).B then
       if TResEvalBool(Value).B then
-        Result:=TResEvalInt.CreateValue(1)
+        v:=1
       else
       else
-        Result:=TResEvalInt.CreateValue(0);
+        v:=0;
     revkInt,revkUInt:
     revkInt,revkUInt:
-      Result:=Value;
+      exit(Value);
     {$ifdef FPC_HAS_CPSTRING}
     {$ifdef FPC_HAS_CPSTRING}
     revkString:
     revkString:
-      if length(TResEvalString(Value).S)<>1 then
-        RaiseRangeCheck(20170624160128,ErrorEl)
-      else
-        Result:=TResEvalInt.CreateValue(ord(TResEvalString(Value).S[1]));
+      v:=ExprStringToOrd(Value,ErrorEl);
     {$endif}
     {$endif}
     revkUnicodeString:
     revkUnicodeString:
-      if length(TResEvalUTF16(Value).S)<>1 then
-        RaiseRangeCheck(20170624160129,ErrorEl)
-      else
-        Result:=TResEvalInt.CreateValue(ord(TResEvalUTF16(Value).S[1]));
+      v:=ExprStringToOrd(Value,ErrorEl);
     revkEnum:
     revkEnum:
-      Result:=TResEvalInt.CreateValue(TResEvalEnum(Value).Index);
+      v:=TResEvalEnum(Value).Index;
   else
   else
     {$IFDEF VerbosePasResEval}
     {$IFDEF VerbosePasResEval}
     writeln('TResExprEvaluator.OrdValue ',Value.AsDebugString);
     writeln('TResExprEvaluator.OrdValue ',Value.AsDebugString);
     {$ENDIF}
     {$ENDIF}
     RaiseNotYetImplemented(20170624155932,ErrorEl);
     RaiseNotYetImplemented(20170624155932,ErrorEl);
   end;
   end;
+  if v>$ffff then exit;
+  Result:=TResEvalInt.CreateValue(v);
 end;
 end;
 
 
 procedure TResExprEvaluator.PredValue(Value: TResEvalValue; ErrorEl: TPasElement
 procedure TResExprEvaluator.PredValue(Value: TResEvalValue; ErrorEl: TPasElement
@@ -4818,6 +4863,35 @@ begin
   end;
   end;
 end;
 end;
 
 
+function TResExprEvaluator.LoHiValue(Value: TResEvalValue; ShiftSize: Integer;
+  Mask: LongWord; ErrorEl: TPasElement): TResEvalValue;
+var
+  uint: LongWord;
+begin
+  case Value.Kind of
+    revkInt:
+      {$IFDEF Pas2js}
+      if ShiftSize=32 then
+        uint := longword(TResEvalInt(Value).Int div $100000000)
+      else
+      {$ENDIF}
+        uint := (TResEvalInt(Value).Int shr ShiftSize) and Mask;
+    revkUInt:
+      {$IFDEF Pas2js}
+      if ShiftSize=32 then
+        uint := longword(TResEvalUInt(Value).UInt div $100000000)
+      else
+      {$ENDIF}
+        uint := (TResEvalUInt(Value).UInt shr ShiftSize) and Mask;
+  else
+    {$IFDEF VerbosePasResEval}
+    writeln('TResExprEvaluator.LoHiValue ',Value.AsDebugString);
+    {$ENDIF}
+    RaiseNotYetImplemented(20190129012100,ErrorEl);
+  end;
+  Result := TResEvalInt.CreateValue(uint);
+end;
+
 function TResExprEvaluator.EnumTypeCast(EnumType: TPasEnumType; Expr: TPasExpr;
 function TResExprEvaluator.EnumTypeCast(EnumType: TPasEnumType; Expr: TPasExpr;
   Flags: TResEvalFlags): TResEvalEnum;
   Flags: TResEvalFlags): TResEvalEnum;
 var
 var

Fichier diff supprimé car celui-ci est trop grand
+ 400 - 163
packages/fcl-passrc/src/pasresolver.pp


+ 33 - 19
packages/fcl-passrc/src/pastree.pp

@@ -57,10 +57,10 @@ resourcestring
   SPasTreeObjectType = 'object';
   SPasTreeObjectType = 'object';
   SPasTreeClassType = 'class';
   SPasTreeClassType = 'class';
   SPasTreeInterfaceType = 'interface';
   SPasTreeInterfaceType = 'interface';
-  SPasTreeGenericType = 'generic class';
   SPasTreeSpecializedType = 'specialized class type';
   SPasTreeSpecializedType = 'specialized class type';
-  SPasClassHelperType = 'Class helper type';
-  SPasRecordHelperType = 'Record helper type';
+  SPasClassHelperType = 'class helper type';
+  SPasRecordHelperType = 'record helper type';
+  SPasTypeHelperType = 'type helper type';
   SPasTreeArgument = 'argument';
   SPasTreeArgument = 'argument';
   SPasTreeProcedureType = 'procedure type';
   SPasTreeProcedureType = 'procedure type';
   SPasTreeResultElement = 'function result';
   SPasTreeResultElement = 'function result';
@@ -737,10 +737,16 @@ type
 
 
   TPasObjKind = (
   TPasObjKind = (
     okObject, okClass, okInterface,
     okObject, okClass, okInterface,
-    okGeneric, // MG: what is okGeneric?
+    // okGeneric  removed in FPC 3.3.1  check instead GenericTemplateTypes.Count>0
     // okSpecialize removed in FPC 3.1.1
     // okSpecialize removed in FPC 3.1.1
     okClassHelper,okRecordHelper,okTypeHelper,
     okClassHelper,okRecordHelper,okTypeHelper,
     okDispInterface);
     okDispInterface);
+const
+  okWithFields = [okObject, okClass];
+  okAllHelpers = [okClassHelper,okRecordHelper,okTypeHelper];
+  okWithClassFields = okWithFields+okAllHelpers;
+
+type
 
 
   TPasClassInterfaceType = (
   TPasClassInterfaceType = (
     citCom, // default
     citCom, // default
@@ -772,7 +778,6 @@ type
     ExternalNameSpace : String;
     ExternalNameSpace : String;
     ExternalName : String;
     ExternalName : String;
     InterfaceType: TPasClassInterfaceType;
     InterfaceType: TPasClassInterfaceType;
-    Procedure SetGenericTemplates(AList : TFPList); override;
     Function FindMember(MemberClass : TPTreeElement; Const MemberName : String) : TPasElement;
     Function FindMember(MemberClass : TPTreeElement; Const MemberName : String) : TPasElement;
     Function FindMemberInAncestors(MemberClass : TPTreeElement; Const MemberName : String) : TPasElement;
     Function FindMemberInAncestors(MemberClass : TPTreeElement; Const MemberName : String) : TPasElement;
     Function InterfaceGUID : string;
     Function InterfaceGUID : string;
@@ -1074,11 +1079,25 @@ type
   end;
   end;
 
 
   { TPasOperator }
   { TPasOperator }
-  TOperatorType = (otUnknown,otImplicit,otExplicit,otMul,otPlus, otMinus, otDivision,otLessThan, otEqual,
-                   otGreaterThan, otAssign,otNotEqual,otLessEqualThan,otGreaterEqualThan,otPower,
-                   otSymmetricalDifference, otInc, otDec, otMod, otNegative, otPositive, otBitWiseOr, otDiv,
-                   otLeftShift, otLogicalOr, otBitwiseAnd, otbitwiseXor,otLogicalAnd,otLogicalNot,otLogicalXor,
-                   otRightShift,otEnumerator, otIn);
+  TOperatorType = (
+    otUnknown,
+    otImplicit, otExplicit,
+    otMul, otPlus, otMinus, otDivision,
+    otLessThan, otEqual, otGreaterThan,
+    otAssign, otNotEqual, otLessEqualThan, otGreaterEqualThan,
+    otPower, otSymmetricalDifference,
+    otInc, otDec,
+    otMod,
+    otNegative, otPositive,
+    otBitWiseOr,
+    otDiv,
+    otLeftShift,
+    otLogicalOr,
+    otBitwiseAnd, otbitwiseXor,
+    otLogicalAnd, otLogicalNot, otLogicalXor,
+    otRightShift,
+    otEnumerator, otIn
+    );
   TOperatorTypes = set of TOperatorType;
   TOperatorTypes = set of TOperatorType;
 
 
   TPasOperator = class(TPasFunction)
   TPasOperator = class(TPasFunction)
@@ -1610,8 +1629,9 @@ const
     'strict private', 'strict protected');
     'strict private', 'strict protected');
 
 
   ObjKindNames: array[TPasObjKind] of string = (
   ObjKindNames: array[TPasObjKind] of string = (
-    'object', 'class', 'interface', 'class',
-    'class helper','record helper','type helper','dispinterface');
+    'object', 'class', 'interface',
+    'class helper','record helper','type helper',
+    'dispinterface');
 
 
   InterfaceTypeNames: array[TPasClassInterfaceType] of string = (
   InterfaceTypeNames: array[TPasClassInterfaceType] of string = (
     'COM',
     'COM',
@@ -3017,9 +3037,9 @@ begin
     okObject: Result := SPasTreeObjectType;
     okObject: Result := SPasTreeObjectType;
     okClass: Result := SPasTreeClassType;
     okClass: Result := SPasTreeClassType;
     okInterface: Result := SPasTreeInterfaceType;
     okInterface: Result := SPasTreeInterfaceType;
-    okGeneric : Result := SPasTreeGenericType;
     okClassHelper : Result:=SPasClassHelperType;
     okClassHelper : Result:=SPasClassHelperType;
     okRecordHelper : Result:=SPasRecordHelperType;
     okRecordHelper : Result:=SPasRecordHelperType;
+    okTypeHelper : Result:=SPasTypeHelperType;
   else
   else
     Result:='ObjKind('+IntToStr(ord(ObjKind))+')';
     Result:='ObjKind('+IntToStr(ord(ObjKind))+')';
   end;
   end;
@@ -3039,12 +3059,6 @@ begin
   ForEachChildCall(aMethodCall,Arg,GUIDExpr,false);
   ForEachChildCall(aMethodCall,Arg,GUIDExpr,false);
 end;
 end;
 
 
-procedure TPasClassType.SetGenericTemplates(AList: TFPList);
-begin
-  ObjKind:=okGeneric;
-  inherited SetGenericTemplates(AList);
-end;
-
 function TPasClassType.FindMember(MemberClass: TPTreeElement; const MemberName: String): TPasElement;
 function TPasClassType.FindMember(MemberClass: TPTreeElement; const MemberName: String): TPasElement;
 
 
 Var
 Var

+ 1 - 1
packages/fcl-passrc/src/pasuseanalyzer.pas

@@ -1452,7 +1452,7 @@ begin
       begin
       begin
       if Ref.WithExprScope<>nil then
       if Ref.WithExprScope<>nil then
         begin
         begin
-        if Ref.WithExprScope.Scope is TPasRecordScope then
+        if Ref.WithExprScope.ClassRecScope is TPasRecordScope then
           begin
           begin
           // a record member was accessed -> access the record too
           // a record member was accessed -> access the record too
           UseExprRef(El,Ref.WithExprScope.Expr,Access,false);
           UseExprRef(El,Ref.WithExprScope.Expr,Access,false);

+ 68 - 75
packages/fcl-passrc/src/pparser.pp

@@ -135,7 +135,7 @@ resourcestring
   // free for 2029
   // free for 2029
   SLogStartImplementation = 'Start parsing implementation section.';
   SLogStartImplementation = 'Start parsing implementation section.';
   SLogStartInterface = 'Start parsing interface section';
   SLogStartInterface = 'Start parsing interface section';
-  SParserNoConstructorAllowed = 'Constructors or Destructors are not allowed in Interfaces or Record helpers';
+  SParserNoConstructorAllowed = 'Constructors or Destructors are not allowed in Interfaces or Records';
   SParserNoFieldsAllowedInX = 'Fields are not allowed in %s';
   SParserNoFieldsAllowedInX = 'Fields are not allowed in %s';
   SParserInvalidRecordVisibility = 'Records can only have public and (strict) private as visibility specifiers';
   SParserInvalidRecordVisibility = 'Records can only have public and (strict) private as visibility specifiers';
   SErrRecordConstantsNotAllowed = 'Record constants not allowed at this location.';
   SErrRecordConstantsNotAllowed = 'Record constants not allowed at this location.';
@@ -730,6 +730,8 @@ begin
         Scanner.AddDefine('CPU32');
         Scanner.AddDefine('CPU32');
       end;
       end;
     Parser := TPasParser.Create(Scanner, FileResolver, AEngine);
     Parser := TPasParser.Create(Scanner, FileResolver, AEngine);
+    if (poSkipDefaultDefs in Options) then
+      Parser.ImplicitUses.Clear;
     Filename := '';
     Filename := '';
     Parser.LogEvents:=AEngine.ParserLogEvents;
     Parser.LogEvents:=AEngine.ParserLogEvents;
     Parser.OnLog:=AEngine.Onlog;
     Parser.OnLog:=AEngine.Onlog;
@@ -2166,29 +2168,6 @@ function TPasParser.ParseExprOperand(AParent: TPasElement): TPasExpr;
       end;
       end;
   end;
   end;
 
 
-  Procedure HandleSelf(Var Last: TPasExpr);
-
-  Var
-    b       : TBinaryExpr;
-    optk    : TToken;
-
-  begin
-    NextToken;
-    if CurToken = tkDot then
-      begin // self.Write(EscapeText(AText));
-      optk:=CurToken;
-      NextToken;
-      b:=CreateBinaryExpr(AParent,Last, ParseExprOperand(AParent), TokenToExprOp(optk));
-      if not Assigned(b.right) then
-        begin
-        b.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
-        ParseExcExpectedIdentifier;
-        end;
-      Last:=b;
-      end;
-    UngetToken;
-  end;
-
   function IsSpecialize: boolean;
   function IsSpecialize: boolean;
   var
   var
     LookAhead, i: Integer;
     LookAhead, i: Integer;
@@ -2264,11 +2243,8 @@ begin
       begin
       begin
       CanSpecialize:=true;
       CanSpecialize:=true;
       aName:=CurTokenText;
       aName:=CurTokenText;
-      if CompareText(aName,'self')=0 then
-        begin
-        Last:=CreateSelfExpr(AParent);
-        HandleSelf(Last);
-        end
+      if (CompareText(aName,'self')=0) and not (tkself in Scanner.NonTokens) then
+        Last:=CreateSelfExpr(AParent)
       else
       else
         Last:=CreatePrimitiveExpr(AParent,pekIdent,aName);
         Last:=CreatePrimitiveExpr(AParent,pekIdent,aName);
       end;
       end;
@@ -2299,7 +2275,6 @@ begin
       CanSpecialize:=true;
       CanSpecialize:=true;
       aName:=CurTokenText;
       aName:=CurTokenText;
       Last:=CreateSelfExpr(AParent);
       Last:=CreateSelfExpr(AParent);
-      HandleSelf(Last);
       end;
       end;
     tkprocedure,tkfunction:
     tkprocedure,tkfunction:
       begin
       begin
@@ -2690,7 +2665,6 @@ begin
   end;
   end;
 end;
 end;
 
 
-
 function GetExprIdent(p: TPasExpr): String;
 function GetExprIdent(p: TPasExpr): String;
 begin
 begin
   Result:='';
   Result:='';
@@ -3347,13 +3321,27 @@ end;
 
 
 procedure TPasParser.ParseDeclarations(Declarations: TPasDeclarations);
 procedure TPasParser.ParseDeclarations(Declarations: TPasDeclarations);
 var
 var
+  HadTypeSection: boolean;
   CurBlock: TDeclType;
   CurBlock: TDeclType;
 
 
   procedure SetBlock(NewBlock: TDeclType);
   procedure SetBlock(NewBlock: TDeclType);
   begin
   begin
     if CurBlock=NewBlock then exit;
     if CurBlock=NewBlock then exit;
     if CurBlock=declType then
     if CurBlock=declType then
-      Engine.FinishScope(stTypeSection,Declarations);
+      begin
+      if msDelphi in CurrentModeswitches then
+        // Delphi allows forward types only inside a type section
+        Engine.FinishScope(stTypeSection,Declarations);
+      end;
+    if NewBlock=declType then
+      HadTypeSection:=true
+    else if (NewBlock=declNone) and HadTypeSection then
+      begin
+      HadTypeSection:=false;
+      if not (msDelphi in CurrentModeswitches) then
+        // ObjFPC allows forward types inside a whole section
+        Engine.FinishScope(stTypeSection,Declarations);
+      end;
     CurBlock:=NewBlock;
     CurBlock:=NewBlock;
     Scanner.SetForceCaret(NewBlock=declType);
     Scanner.SetForceCaret(NewBlock=declType);
   end;
   end;
@@ -3377,6 +3365,7 @@ var
   RecordEl: TPasRecordType;
   RecordEl: TPasRecordType;
 begin
 begin
   CurBlock := declNone;
   CurBlock := declNone;
+  HadTypeSection:=false;
   while True do
   while True do
   begin
   begin
     if CurBlock in [DeclNone,declConst,declType] then
     if CurBlock in [DeclNone,declConst,declType] then
@@ -3649,7 +3638,7 @@ begin
         break;
         break;
         end
         end
       else if (Declarations is TInterfaceSection)
       else if (Declarations is TInterfaceSection)
-      or (Declarations is TImplementationSection) then
+          or (Declarations is TImplementationSection) then
         begin
         begin
         SetBlock(declNone);
         SetBlock(declNone);
         ParseInitialization;
         ParseInitialization;
@@ -3675,9 +3664,9 @@ begin
       end;
       end;
     tklabel:
     tklabel:
       begin
       begin
-        SetBlock(declNone);
-        if not (Declarations is TInterfaceSection) then
-          ParseLabels(Declarations);
+      SetBlock(declNone);
+      if not (Declarations is TInterfaceSection) then
+        ParseLabels(Declarations);
       end;
       end;
     tkSquaredBraceOpen:
     tkSquaredBraceOpen:
       if [msPrefixedAttributes,msIgnoreAttributes]*CurrentModeSwitches<>[] then
       if [msPrefixedAttributes,msIgnoreAttributes]*CurrentModeSwitches<>[] then
@@ -3866,8 +3855,6 @@ begin
       finally
       finally
         Scanner.SetForceCaret(OldForceCaret);
         Scanner.SetForceCaret(OldForceCaret);
       end;
       end;
-{      if Result.VarType is TPasRangeType then
-        Ungettoken; // Range type stops on token after last range token}
       end
       end
     else
     else
       begin
       begin
@@ -4008,7 +3995,7 @@ begin
       end;
       end;
     if not (CurToken in [tkComma,tkSemicolon,tkGreaterThan]) then
     if not (CurToken in [tkComma,tkSemicolon,tkGreaterThan]) then
       ParseExc(nParserExpectToken2Error,SParserExpectToken2Error,
       ParseExc(nParserExpectToken2Error,SParserExpectToken2Error,
-        [TokenInfos[tkComma], TokenInfos[tkColon], TokenInfos[tkGreaterThan]]);
+        [TokenInfos[tkComma], TokenInfos[tkGreaterThan]]);
   until CurToken = tkGreaterThan;
   until CurToken = tkGreaterThan;
 end;
 end;
 
 
@@ -4417,7 +4404,7 @@ begin
     TPasVariable(VarList[OldListCount]).Expr:=Value;
     TPasVariable(VarList[OldListCount]).Expr:=Value;
     Value:=nil;
     Value:=nil;
 
 
-    // Note: external members are allowed for non external classes too
+    // Note: external members are allowed for non external classes/records too
     ExternalStruct:=(msExternalClass in CurrentModeSwitches)
     ExternalStruct:=(msExternalClass in CurrentModeSwitches)
                     and (Parent is TPasMembersType);
                     and (Parent is TPasMembersType);
 
 
@@ -5608,14 +5595,13 @@ var
 
 
 var
 var
   SubBlock: TPasImplElement;
   SubBlock: TPasImplElement;
-  Left, Right: TPasExpr;
+  Left, Right, Expr: TPasExpr;
   El : TPasImplElement;
   El : TPasImplElement;
   lt : TLoopType;
   lt : TLoopType;
   SrcPos: TPasSourcePos;
   SrcPos: TPasSourcePos;
   Name: String;
   Name: String;
   TypeEl: TPasType;
   TypeEl: TPasType;
   ImplRaise: TPasImplRaise;
   ImplRaise: TPasImplRaise;
-  Expr: TPasExpr;
 
 
 begin
 begin
   NewImplElement:=nil;
   NewImplElement:=nil;
@@ -5812,12 +5798,11 @@ begin
           SrcPos:=CurTokenPos;
           SrcPos:=CurTokenPos;
           NextToken;
           NextToken;
           El:=TPasImplWithDo(CreateElement(TPasImplWithDo,'',CurBlock,SrcPos));
           El:=TPasImplWithDo(CreateElement(TPasImplWithDo,'',CurBlock,SrcPos));
-          Left:=DoParseExpression(CurBlock);
+          Expr:=DoParseExpression(CurBlock);
           //writeln(i,'WITH Expr="',Expr,'" Token=',CurTokenText);
           //writeln(i,'WITH Expr="',Expr,'" Token=',CurTokenText);
-          TPasImplWithDo(El).AddExpression(Left);
-          Left.Parent:=El;
-          Engine.BeginScope(stWithExpr,Left);
-          Left:=nil;
+          TPasImplWithDo(El).AddExpression(Expr);
+          Expr.Parent:=El;
+          Engine.BeginScope(stWithExpr,Expr);
           CreateBlock(TPasImplWithDo(El));
           CreateBlock(TPasImplWithDo(El));
           El:=nil;
           El:=nil;
           repeat
           repeat
@@ -5825,11 +5810,10 @@ begin
             if CurToken<>tkComma then
             if CurToken<>tkComma then
               ParseExcTokenError(TokenInfos[tkdo]);
               ParseExcTokenError(TokenInfos[tkdo]);
             NextToken;
             NextToken;
-            Left:=DoParseExpression(CurBlock);
+            Expr:=DoParseExpression(CurBlock);
             //writeln(i,'WITH ...,Expr="',Expr,'" Token=',CurTokenText);
             //writeln(i,'WITH ...,Expr="',Expr,'" Token=',CurTokenText);
-            TPasImplWithDo(CurBlock).AddExpression(Left);
-            Engine.BeginScope(stWithExpr,Left);
-            Left:=nil;
+            TPasImplWithDo(CurBlock).AddExpression(Expr);
+            Engine.BeginScope(stWithExpr,Expr);
           until false;
           until false;
         end;
         end;
       tkcase:
       tkcase:
@@ -6088,7 +6072,7 @@ begin
             tkAssignMinus,
             tkAssignMinus,
             tkAssignMul,
             tkAssignMul,
             tkAssignDivision:
             tkAssignDivision:
-            begin
+              begin
               // assign statement
               // assign statement
               El:=TPasImplAssign(CreateElement(TPasImplAssign,'',CurBlock,SrcPos));
               El:=TPasImplAssign(CreateElement(TPasImplAssign,'',CurBlock,SrcPos));
               TPasImplAssign(El).left:=Left;
               TPasImplAssign(El).left:=Left;
@@ -6102,10 +6086,12 @@ begin
               Right:=nil;
               Right:=nil;
               AddStatement(El);
               AddStatement(El);
               El:=nil;
               El:=nil;
-            end;
+              end;
             tkColon:
             tkColon:
-            begin
-              if not (Left is TPrimitiveExpr) then
+              begin
+              if not (bsGoto in Scanner.CurrentBoolSwitches) then
+                ParseExcTokenError(TokenInfos[tkSemicolon])
+              else if not (Left is TPrimitiveExpr) then
                 ParseExcTokenError(TokenInfos[tkSemicolon]);
                 ParseExcTokenError(TokenInfos[tkSemicolon]);
               // label mark. todo: check mark identifier in the list of labels
               // label mark. todo: check mark identifier in the list of labels
               El:=TPasImplLabelMark(CreateElement(TPasImplLabelMark,'', CurBlock,SrcPos));
               El:=TPasImplLabelMark(CreateElement(TPasImplLabelMark,'', CurBlock,SrcPos));
@@ -6114,7 +6100,7 @@ begin
               CurBlock.AddElement(El);
               CurBlock.AddElement(El);
               CmdElem:=TPasImplLabelMark(El);
               CmdElem:=TPasImplLabelMark(El);
               El:=nil;
               El:=nil;
-            end;
+              end;
           else
           else
             // simple statement (function call)
             // simple statement (function call)
             El:=TPasImplSimple(CreateElement(TPasImplSimple,'',CurBlock,SrcPos));
             El:=TPasImplSimple(CreateElement(TPasImplSimple,'',CurBlock,SrcPos));
@@ -6221,7 +6207,7 @@ begin
   ptOperator,ptClassOperator:
   ptOperator,ptClassOperator:
     begin
     begin
     NextToken;
     NextToken;
-    IsTokenBased:=Curtoken<>tkIdentifier;
+    IsTokenBased:=CurToken<>tkIdentifier;
     if IsTokenBased then
     if IsTokenBased then
       OT:=TPasOperator.TokenToOperatorType(CurTokenText)
       OT:=TPasOperator.TokenToOperatorType(CurTokenText)
     else
     else
@@ -6684,8 +6670,8 @@ Type
 Var
 Var
   CurVisibility : TPasMemberVisibility;
   CurVisibility : TPasMemberVisibility;
   CurSection : TSectionType;
   CurSection : TSectionType;
-  haveClass ,
-    IsMethodResolution: Boolean; // true means last token was class keyword
+  haveClass: boolean; // true means last token was class keyword
+  IsMethodResolution: Boolean;
   LastToken: TToken;
   LastToken: TToken;
   PropEl: TPasProperty;
   PropEl: TPasProperty;
   MethodRes: TPasMethodResolution;
   MethodRes: TPasMethodResolution;
@@ -6705,7 +6691,7 @@ begin
       tkType:
       tkType:
         begin
         begin
         case AType.ObjKind of
         case AType.ObjKind of
-        okClass,okObject,okGeneric,
+        okClass,okObject,
         okClassHelper,okRecordHelper,okTypeHelper: ;
         okClassHelper,okRecordHelper,okTypeHelper: ;
         else
         else
           ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['TYPE',ObjKindNames[AType.ObjKind]]);
           ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['TYPE',ObjKindNames[AType.ObjKind]]);
@@ -6718,7 +6704,7 @@ begin
           ParseExc(nParserExpectToken2Error,SParserExpectToken2Error,
           ParseExc(nParserExpectToken2Error,SParserExpectToken2Error,
             ['Procedure','Var']);
             ['Procedure','Var']);
         case AType.ObjKind of
         case AType.ObjKind of
-        okClass,okObject,okGeneric,
+        okClass,okObject,
         okClassHelper,okRecordHelper,okTypeHelper: ;
         okClassHelper,okRecordHelper,okTypeHelper: ;
         else
         else
           ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['CONST',ObjKindNames[AType.ObjKind]]);
           ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['CONST',ObjKindNames[AType.ObjKind]]);
@@ -6728,8 +6714,8 @@ begin
       tkVar:
       tkVar:
         if not (CurSection in [stVar,stClassVar]) then
         if not (CurSection in [stVar,stClassVar]) then
           begin
           begin
-          if (AType.ObjKind in [okClass,okObject,okGeneric])
-          or (haveClass and (AType.ObjKind in [okClassHelper,okRecordHelper,okTypeHelper])) then
+          if (AType.ObjKind in okWithFields)
+          or (haveClass and (AType.ObjKind in okAllHelpers)) then
             // ok
             // ok
           else
           else
             ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['VAR',ObjKindNames[AType.ObjKind]]);
             ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['VAR',ObjKindNames[AType.ObjKind]]);
@@ -6753,14 +6739,14 @@ begin
           stNone,
           stNone,
           stVar:
           stVar:
             begin
             begin
-            if not (AType.ObjKind in [okObject,okClass,okGeneric]) then
+            if not (AType.ObjKind in okWithFields) then
               ParseExc(nParserNoFieldsAllowed,SParserNoFieldsAllowedInX,[ObjKindNames[AType.ObjKind]]);
               ParseExc(nParserNoFieldsAllowed,SParserNoFieldsAllowedInX,[ObjKindNames[AType.ObjKind]]);
             ParseClassFields(AType,CurVisibility,CurSection=stClassVar);
             ParseClassFields(AType,CurVisibility,CurSection=stClassVar);
             HaveClass:=False;
             HaveClass:=False;
             end;
             end;
           stClassVar:
           stClassVar:
             begin
             begin
-            if not (AType.ObjKind in [okObject,okClass,okGeneric,okClassHelper,okRecordHelper,okTypeHelper]) then
+            if not (AType.ObjKind in okWithClassFields) then
               ParseExc(nParserNoFieldsAllowed,SParserNoFieldsAllowedInX,[ObjKindNames[AType.ObjKind]]);
               ParseExc(nParserNoFieldsAllowed,SParserNoFieldsAllowedInX,[ObjKindNames[AType.ObjKind]]);
             ParseClassFields(AType,CurVisibility,CurSection=stClassVar);
             ParseClassFields(AType,CurVisibility,CurSection=stClassVar);
             HaveClass:=False;
             HaveClass:=False;
@@ -6774,12 +6760,19 @@ begin
         curSection:=stNone;
         curSection:=stNone;
         if not haveClass then
         if not haveClass then
           SaveComments;
           SaveComments;
-        if (AType.ObjKind in [okObject,okClass,okGeneric])
-            or ((CurToken=tkconstructor)
-              and (AType.ObjKind in [okClassHelper,okTypeHelper,okRecordHelper])) then
-          // ok
+        case AType.ObjKind of
+        okObject,okClass: ;
+        okClassHelper,okTypeHelper,okRecordHelper:
+          begin
+          if (CurToken=tkdestructor) and not haveClass then
+            ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['destructor',ObjKindNames[AType.ObjKind]]);
+          end;
         else
         else
-          ParseExc(nParserNoConstructorAllowed,SParserNoConstructorAllowed);
+          if CurToken=tkconstructor then
+            ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['constructor',ObjKindNames[AType.ObjKind]])
+          else
+            ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['destructor',ObjKindNames[AType.ObjKind]]);
+        end;
         ProcessMethod(AType,HaveClass,CurVisibility);
         ProcessMethod(AType,HaveClass,CurVisibility);
         haveClass:=False;
         haveClass:=False;
         end;
         end;
@@ -6815,7 +6808,7 @@ begin
       tkclass:
       tkclass:
         begin
         begin
         case AType.ObjKind of
         case AType.ObjKind of
-        okClass,okObject,okGeneric,
+        okClass,okObject,
         okClassHelper,okRecordHelper,okTypeHelper: ;
         okClassHelper,okRecordHelper,okTypeHelper: ;
         else
         else
           ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['CLASS',ObjKindNames[AType.ObjKind]]);
           ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['CLASS',ObjKindNames[AType.ObjKind]]);
@@ -6855,7 +6848,7 @@ var
   Expr: TPasExpr;
   Expr: TPasExpr;
 
 
 begin
 begin
-  if (CurToken=tkIdentifier) and (AType.ObjKind in [okClass,okGeneric]) then
+  if (CurToken=tkIdentifier) and (AType.ObjKind=okClass) then
     begin
     begin
     s := LowerCase(CurTokenString);
     s := LowerCase(CurTokenString);
     if (s = 'sealed') or (s = 'abstract') then
     if (s = 'sealed') or (s = 'abstract') then
@@ -6875,7 +6868,7 @@ begin
       CheckToken(tkend);
       CheckToken(tkend);
     NextToken;
     NextToken;
     AType.AncestorType := ParseTypeReference(AType,false,Expr);
     AType.AncestorType := ParseTypeReference(AType,false,Expr);
-    if AType.ObjKind in [okClass,okGeneric] then
+    if AType.ObjKind=okClass then
       while CurToken=tkComma do
       while CurToken=tkComma do
         begin
         begin
         NextToken;
         NextToken;
@@ -6885,7 +6878,7 @@ begin
     NextToken;
     NextToken;
     AType.IsShortDefinition:=(CurToken=tkSemicolon);
     AType.IsShortDefinition:=(CurToken=tkSemicolon);
     end;
     end;
-  if (AType.ObjKind in [okClassHelper,okRecordHelper,okTypeHelper]) then
+  if (AType.ObjKind in okAllHelpers) then
     begin
     begin
     CheckToken(tkfor);
     CheckToken(tkfor);
     NextToken;
     NextToken;
@@ -6957,7 +6950,7 @@ begin
     AExternalNameSpace:='';
     AExternalNameSpace:='';
     AExternalName:='';
     AExternalName:='';
     end;
     end;
-  if AObjKind in [okClassHelper,okRecordHelper,okTypeHelper] then
+  if AObjKind in okAllHelpers then
     begin
     begin
     if not CurTokenIsIdentifier('Helper') then
     if not CurTokenIsIdentifier('Helper') then
       ParseExcSyntaxError;
       ParseExcSyntaxError;

+ 34 - 13
packages/fcl-passrc/src/pscanner.pp

@@ -294,8 +294,9 @@ type
     msExternalClass,       { Allow external class definitions }
     msExternalClass,       { Allow external class definitions }
     msPrefixedAttributes,  { Allow attributes, disable proc modifier [] }
     msPrefixedAttributes,  { Allow attributes, disable proc modifier [] }
     msIgnoreAttributes,    { workaround til resolver/converter supports attributes }
     msIgnoreAttributes,    { workaround til resolver/converter supports attributes }
-    msOmitRTTI             { treat class section 'published' as 'public' and typeinfo does not work on symbols declared with this switch }
-  );
+    msOmitRTTI,            { treat class section 'published' as 'public' and typeinfo does not work on symbols declared with this switch }
+    msMultipleScopeHelpers { off=only one helper per type, on=all }
+    );
   TModeSwitches = Set of TModeSwitch;
   TModeSwitches = Set of TModeSwitch;
 
 
   // switches, that can be 'on' or 'off'
   // switches, that can be 'on' or 'off'
@@ -333,7 +334,8 @@ type
     bsMacro,
     bsMacro,
     bsScopedEnums,
     bsScopedEnums,
     bsObjectChecks,   // check methods 'Self' and object type casts
     bsObjectChecks,   // check methods 'Self' and object type casts
-    bsPointerMath     // pointer arithmetic
+    bsPointerMath,    // pointer arithmetic
+    bsGoto       // support label and goto, set by {$goto on|off}
     );
     );
   TBoolSwitches = set of TBoolSwitch;
   TBoolSwitches = set of TBoolSwitch;
 const
 const
@@ -369,8 +371,8 @@ const
   bsAll = [low(TBoolSwitch)..high(TBoolSwitch)];
   bsAll = [low(TBoolSwitch)..high(TBoolSwitch)];
   bsFPCMode: TBoolSwitches = [bsPointerMath,bsWriteableConst];
   bsFPCMode: TBoolSwitches = [bsPointerMath,bsWriteableConst];
   bsObjFPCMode: TBoolSwitches = [bsPointerMath,bsWriteableConst];
   bsObjFPCMode: TBoolSwitches = [bsPointerMath,bsWriteableConst];
-  bsDelphiMode: TBoolSwitches = [bsWriteableConst];
-  bsDelphiUnicodeMode: TBoolSwitches = [bsWriteableConst];
+  bsDelphiMode: TBoolSwitches = [bsWriteableConst,bsGoto];
+  bsDelphiUnicodeMode: TBoolSwitches = [bsWriteableConst,bsGoto];
   bsMacPasMode: TBoolSwitches = [bsPointerMath,bsWriteableConst];
   bsMacPasMode: TBoolSwitches = [bsPointerMath,bsWriteableConst];
 
 
 type
 type
@@ -987,7 +989,7 @@ const
     'Tab'
     'Tab'
   );
   );
 
 
-  SModeSwitchNames : array[TModeSwitch] of string{$ifdef fpc}[18]{$endif} =
+  SModeSwitchNames : array[TModeSwitch] of string{$ifdef fpc}[20]{$endif} =
   ( '', // msNone
   ( '', // msNone
     '', // Fpc,
     '', // Fpc,
     '', // Objfpc,
     '', // Objfpc,
@@ -1037,7 +1039,8 @@ const
     'EXTERNALCLASS',
     'EXTERNALCLASS',
     'PREFIXEDATTRIBUTES',
     'PREFIXEDATTRIBUTES',
     'IGNOREATTRIBUTES',
     'IGNOREATTRIBUTES',
-    'OMITRTTI'
+    'OMITRTTI',
+    'MULTIPLESCOPEHELPERS'
     );
     );
 
 
   LetterSwitchNames: array['A'..'Z'] of string=(
   LetterSwitchNames: array['A'..'Z'] of string=(
@@ -1100,7 +1103,8 @@ const
     'Macro',
     'Macro',
     'ScopedEnums',
     'ScopedEnums',
     'ObjectChecks',
     'ObjectChecks',
-    'PointerMath'
+    'PointerMath',
+    'Goto'
     );
     );
 
 
   ValueSwitchNames: array[TValueSwitch] of string = (
   ValueSwitchNames: array[TValueSwitch] of string = (
@@ -1117,7 +1121,7 @@ const
 
 
 const
 const
   // all mode switches supported by FPC
   // all mode switches supported by FPC
-  msAllFPCModeSwitches = [low(TModeSwitch)..High(TModeSwitch)];
+  msAllModeSwitches = [low(TModeSwitch)..High(TModeSwitch)];
 
 
   DelphiModeSwitches = [msDelphi,msClass,msObjpas,msResult,msStringPchar,
   DelphiModeSwitches = [msDelphi,msClass,msObjpas,msResult,msStringPchar,
      msPointer2Procedure,msAutoDeref,msTPProcVar,msInitFinal,msDefaultAnsistring,
      msPointer2Procedure,msAutoDeref,msTPProcVar,msInitFinal,msDefaultAnsistring,
@@ -1128,7 +1132,7 @@ const
 
 
   DelphiUnicodeModeSwitches = delphimodeswitches + [msSystemCodePage,msDefaultUnicodestring];
   DelphiUnicodeModeSwitches = delphimodeswitches + [msSystemCodePage,msDefaultUnicodestring];
 
 
-  // mode switches of $mode FPC, don't confuse with msAllFPCModeSwitches
+  // mode switches of $mode FPC, don't confuse with msAllModeSwitches
   FPCModeSwitches = [msFpc,msStringPchar,msNestedComment,msRepeatForward,
   FPCModeSwitches = [msFpc,msStringPchar,msNestedComment,msRepeatForward,
     msCVarSupport,msInitFinal,msHintDirective,msProperty,msDefaultInline];
     msCVarSupport,msInitFinal,msHintDirective,msProperty,msDefaultInline];
   //FPCBoolSwitches bsObjectChecks
   //FPCBoolSwitches bsObjectChecks
@@ -2663,7 +2667,7 @@ begin
   FMaxIncludeStackDepth:=DefaultMaxIncludeStackDepth;
   FMaxIncludeStackDepth:=DefaultMaxIncludeStackDepth;
 
 
   FCurrentModeSwitches:=FPCModeSwitches;
   FCurrentModeSwitches:=FPCModeSwitches;
-  FAllowedModeSwitches:=msAllFPCModeSwitches;
+  FAllowedModeSwitches:=msAllModeSwitches;
   FCurrentBoolSwitches:=bsFPCMode;
   FCurrentBoolSwitches:=bsFPCMode;
   FAllowedBoolSwitches:=bsAll;
   FAllowedBoolSwitches:=bsAll;
   FAllowedValueSwitches:=vsAllValueSwitches;
   FAllowedValueSwitches:=vsAllValueSwitches;
@@ -3672,6 +3676,8 @@ begin
           DoBoolDirective(bsAssertions);
           DoBoolDirective(bsAssertions);
         'DEFINE':
         'DEFINE':
           HandleDefine(Param);
           HandleDefine(Param);
+        'GOTO':
+          DoBoolDirective(bsGoto);
         'ERROR':
         'ERROR':
           HandleError(Param);
           HandleError(Param);
         'HINT':
         'HINT':
@@ -3786,9 +3792,9 @@ begin
     DoLog(mtWarning,nWarnIllegalCompilerDirectiveX,sWarnIllegalCompilerDirectiveX,
     DoLog(mtWarning,nWarnIllegalCompilerDirectiveX,sWarnIllegalCompilerDirectiveX,
       [BoolSwitchNames[bs]])
       [BoolSwitchNames[bs]])
   else if NewValue then
   else if NewValue then
-    Include(FCurrentBoolSwitches,bs)
+    CurrentBoolSwitches:=CurrentBoolSwitches+[bs]
   else
   else
-    Exclude(FCurrentBoolSwitches,bs);
+    CurrentBoolSwitches:=CurrentBoolSwitches-[bs];
 end;
 end;
 
 
 function TPascalScanner.DoFetchToken: TToken;
 function TPascalScanner.DoFetchToken: TToken;
@@ -4508,9 +4514,24 @@ begin
 end;
 end;
 
 
 procedure TPascalScanner.SetCurrentBoolSwitches(const AValue: TBoolSwitches);
 procedure TPascalScanner.SetCurrentBoolSwitches(const AValue: TBoolSwitches);
+var
+  OldBS, Removed, Added: TBoolSwitches;
 begin
 begin
   if FCurrentBoolSwitches=AValue then Exit;
   if FCurrentBoolSwitches=AValue then Exit;
+  OldBS:=FCurrentBoolSwitches;
   FCurrentBoolSwitches:=AValue;
   FCurrentBoolSwitches:=AValue;
+  Removed:=OldBS-FCurrentBoolSwitches;
+  Added:=FCurrentBoolSwitches-OldBS;
+  if bsGoto in Added then
+    begin
+    UnsetNonToken(tklabel);
+    UnsetNonToken(tkgoto);
+    end;
+  if bsGoto in Removed then
+    begin
+    SetNonToken(tklabel);
+    SetNonToken(tkgoto);
+    end;
 end;
 end;
 
 
 procedure TPascalScanner.SetCurrentModeSwitches(AValue: TModeSwitches);
 procedure TPascalScanner.SetCurrentModeSwitches(AValue: TModeSwitches);

+ 40 - 0
packages/fcl-passrc/tests/tcexprparser.pas

@@ -109,6 +109,8 @@ type
     Procedure TestAPlusBBracketArrayParams;
     Procedure TestAPlusBBracketArrayParams;
     Procedure TestAPlusBBracketDotC;
     Procedure TestAPlusBBracketDotC;
     Procedure TestADotBDotC;
     Procedure TestADotBDotC;
+    Procedure TestADotBBracketC;
+    Procedure TestSelfDotBBracketC;
     Procedure TestRange;
     Procedure TestRange;
     Procedure TestBracketsTotal;
     Procedure TestBracketsTotal;
     Procedure TestBracketsLeft;
     Procedure TestBracketsLeft;
@@ -1249,6 +1251,44 @@ begin
   AssertExpression('right b',SubB.right,pekIdent,'b');
   AssertExpression('right b',SubB.right,pekIdent,'b');
 end;
 end;
 
 
+procedure TTestExpressions.TestADotBBracketC;
+var
+  P: TParamsExpr;
+  B: TBinaryExpr;
+begin
+  ParseExpression('a.b[c]');
+  P:=TParamsExpr(AssertExpression('ArrayParams',TheExpr,pekArrayParams,TParamsExpr));
+
+  B:=TBinaryExpr(AssertExpression('Binary identifier',P.Value,pekBinary,TBinaryExpr));
+  AssertEquals('dot expr',eopSubIdent,B.OpCode);
+  TAssert.AssertSame('B.left.parent=B',B,B.left.Parent);
+  TAssert.AssertSame('B.right.parent=B',B,B.right.Parent);
+  AssertExpression('left a',B.left,pekIdent,'a');
+  AssertExpression('right b',B.right,pekIdent,'b');
+
+  AssertEquals('length(p.Params)',length(p.Params),1);
+  AssertExpression('first param c',p.Params[0],pekIdent,'c');
+end;
+
+procedure TTestExpressions.TestSelfDotBBracketC;
+var
+  P: TParamsExpr;
+  B: TBinaryExpr;
+begin
+  ParseExpression('self.b[c]');
+  P:=TParamsExpr(AssertExpression('ArrayParams',TheExpr,pekArrayParams,TParamsExpr));
+
+  B:=TBinaryExpr(AssertExpression('Binary identifier',P.Value,pekBinary,TBinaryExpr));
+  AssertEquals('dot expr',eopSubIdent,B.OpCode);
+  TAssert.AssertSame('B.left.parent=B',B,B.left.Parent);
+  TAssert.AssertSame('B.right.parent=B',B,B.right.Parent);
+  AssertEquals('left self',TSelfExpr,B.left.classtype);
+  AssertExpression('right b',B.right,pekIdent,'b');
+
+  AssertEquals('length(p.Params)',length(p.Params),1);
+  AssertExpression('first param c',p.Params[0],pekIdent,'c');
+end;
+
 initialization
 initialization
 
 
   RegisterTest(TTestExpressions);
   RegisterTest(TTestExpressions);

+ 45 - 21
packages/fcl-passrc/tests/tcgenerics.pp

@@ -12,20 +12,21 @@ Type
   { TTestGenerics }
   { TTestGenerics }
 
 
   TTestGenerics = Class(TBaseTestTypeParser)
   TTestGenerics = Class(TBaseTestTypeParser)
-  private
   Published
   Published
     Procedure TestObjectGenerics;
     Procedure TestObjectGenerics;
     Procedure TestRecordGenerics;
     Procedure TestRecordGenerics;
     Procedure TestArrayGenerics;
     Procedure TestArrayGenerics;
+    Procedure TestGenericConstraint;
+    Procedure TestDeclarationConstraint;
     Procedure TestSpecializationDelphi;
     Procedure TestSpecializationDelphi;
-    procedure TestDeclarationConstraint;
     Procedure TestDeclarationDelphi;
     Procedure TestDeclarationDelphi;
     Procedure TestDeclarationDelphiSpecialize;
     Procedure TestDeclarationDelphiSpecialize;
-    procedure TestDeclarationFPC;
+    Procedure TestDeclarationFPC;
     Procedure TestMethodImplementation;
     Procedure TestMethodImplementation;
     Procedure TestInlineSpecializationInArgument;
     Procedure TestInlineSpecializationInArgument;
     Procedure TestSpecializeNested;
     Procedure TestSpecializeNested;
     Procedure TestInlineSpecializeInStatement;
     Procedure TestInlineSpecializeInStatement;
+    Procedure TestGenericFunction; // ToDo
   end;
   end;
 
 
 implementation
 implementation
@@ -61,20 +62,25 @@ begin
   ParseDeclarations;
   ParseDeclarations;
 end;
 end;
 
 
-procedure TTestGenerics.TestSpecializationDelphi;
+procedure TTestGenerics.TestGenericConstraint;
 begin
 begin
-  ParseType('TFPGList<integer>',TPasSpecializeType,'');
+  Add([
+    'Type',
+    'Generic TSomeClass<T: TObject> = class',
+    '  b : T;',
+    'end;',
+    '']);
+  ParseDeclarations;
 end;
 end;
 
 
-procedure TTestGenerics.TestDeclarationDelphi;
+procedure TTestGenerics.TestDeclarationConstraint;
 Var
 Var
   T : TPasClassType;
   T : TPasClassType;
 begin
 begin
   Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
   Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
   Source.Add('Type');
   Source.Add('Type');
-  Source.Add('  TSomeClass<T,T2> = Class(TObject)');
+  Source.Add('  TSomeClass<T: T2> = Class(TObject)');
   Source.Add('  b : T;');
   Source.Add('  b : T;');
-  Source.Add('  b2 : T2;');
   Source.Add('end;');
   Source.Add('end;');
   ParseDeclarations;
   ParseDeclarations;
   AssertNotNull('have generic definition',Declarations.Classes);
   AssertNotNull('have generic definition',Declarations.Classes);
@@ -82,18 +88,23 @@ begin
   AssertEquals('Pascal class',TPasClassType,TObject(Declarations.Classes[0]).ClassType);
   AssertEquals('Pascal class',TPasClassType,TObject(Declarations.Classes[0]).ClassType);
   T:=TPasClassType(Declarations.Classes[0]);
   T:=TPasClassType(Declarations.Classes[0]);
   AssertNotNull('have generic templates',T.GenericTemplateTypes);
   AssertNotNull('have generic templates',T.GenericTemplateTypes);
-  AssertEquals('2 template types',2,T.GenericTemplateTypes.Count);
+  AssertEquals('1 template types',1,T.GenericTemplateTypes.Count);
   AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
   AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
-  AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
+  AssertEquals('Type constraint is recorded','T2',TPasGenericTemplateType(T.GenericTemplateTypes[0]).TypeConstraint);
 end;
 end;
 
 
-procedure TTestGenerics.TestDeclarationFPC;
+procedure TTestGenerics.TestSpecializationDelphi;
+begin
+  ParseType('TFPGList<integer>',TPasSpecializeType,'');
+end;
+
+procedure TTestGenerics.TestDeclarationDelphi;
 Var
 Var
   T : TPasClassType;
   T : TPasClassType;
 begin
 begin
   Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
   Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
   Source.Add('Type');
   Source.Add('Type');
-  Source.Add('  TSomeClass<T;T2> = Class(TObject)');
+  Source.Add('  TSomeClass<T,T2> = Class(TObject)');
   Source.Add('  b : T;');
   Source.Add('  b : T;');
   Source.Add('  b2 : T2;');
   Source.Add('  b2 : T2;');
   Source.Add('end;');
   Source.Add('end;');
@@ -108,34 +119,35 @@ begin
   AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
   AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
 end;
 end;
 
 
-
-procedure TTestGenerics.TestDeclarationConstraint;
+procedure TTestGenerics.TestDeclarationDelphiSpecialize;
 Var
 Var
   T : TPasClassType;
   T : TPasClassType;
 begin
 begin
   Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
   Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
   Source.Add('Type');
   Source.Add('Type');
-  Source.Add('  TSomeClass<T: T2> = Class(TObject)');
+  Source.Add('  TSomeClass<T,T2> = Class(TSomeGeneric<Integer,Integer>)');
   Source.Add('  b : T;');
   Source.Add('  b : T;');
+  Source.Add('  b2 : T2;');
   Source.Add('end;');
   Source.Add('end;');
   ParseDeclarations;
   ParseDeclarations;
   AssertNotNull('have generic definition',Declarations.Classes);
   AssertNotNull('have generic definition',Declarations.Classes);
   AssertEquals('have generic definition',1,Declarations.Classes.Count);
   AssertEquals('have generic definition',1,Declarations.Classes.Count);
   AssertEquals('Pascal class',TPasClassType,TObject(Declarations.Classes[0]).ClassType);
   AssertEquals('Pascal class',TPasClassType,TObject(Declarations.Classes[0]).ClassType);
   T:=TPasClassType(Declarations.Classes[0]);
   T:=TPasClassType(Declarations.Classes[0]);
+  AssertEquals('Name is correct','TSomeClass',T.Name);
   AssertNotNull('have generic templates',T.GenericTemplateTypes);
   AssertNotNull('have generic templates',T.GenericTemplateTypes);
-  AssertEquals('1 template types',1,T.GenericTemplateTypes.Count);
+  AssertEquals('2 template types',2,T.GenericTemplateTypes.Count);
   AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
   AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
-  AssertEquals('Type constraint is recorded','T2',TPasGenericTemplateType(T.GenericTemplateTypes[0]).TypeConstraint);
+  AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
 end;
 end;
 
 
-procedure TTestGenerics.TestDeclarationDelphiSpecialize;
+procedure TTestGenerics.TestDeclarationFPC;
 Var
 Var
   T : TPasClassType;
   T : TPasClassType;
 begin
 begin
-  Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
+  Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches;
   Source.Add('Type');
   Source.Add('Type');
-  Source.Add('  TSomeClass<T,T2> = Class(TSomeGeneric<Integer,Integer>)');
+  Source.Add('  TSomeClass<T;T2> = Class(TObject)');
   Source.Add('  b : T;');
   Source.Add('  b : T;');
   Source.Add('  b2 : T2;');
   Source.Add('  b2 : T2;');
   Source.Add('end;');
   Source.Add('end;');
@@ -144,7 +156,6 @@ begin
   AssertEquals('have generic definition',1,Declarations.Classes.Count);
   AssertEquals('have generic definition',1,Declarations.Classes.Count);
   AssertEquals('Pascal class',TPasClassType,TObject(Declarations.Classes[0]).ClassType);
   AssertEquals('Pascal class',TPasClassType,TObject(Declarations.Classes[0]).ClassType);
   T:=TPasClassType(Declarations.Classes[0]);
   T:=TPasClassType(Declarations.Classes[0]);
-  AssertEquals('Name is correct','TSomeClass',T.Name);
   AssertNotNull('have generic templates',T.GenericTemplateTypes);
   AssertNotNull('have generic templates',T.GenericTemplateTypes);
   AssertEquals('2 template types',2,T.GenericTemplateTypes.Count);
   AssertEquals('2 template types',2,T.GenericTemplateTypes.Count);
   AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
   AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
@@ -206,6 +217,19 @@ begin
   ParseModule;
   ParseModule;
 end;
 end;
 
 
+procedure TTestGenerics.TestGenericFunction;
+begin
+  exit; // ToDo
+  Add([
+  'generic function IfThen<T>(val:boolean;const iftrue:T; const iffalse:T) :T; inline; overload;',
+  'begin',
+  'end;',
+  'begin',
+  '  IfThen<word>(true,2,3);',
+  '']);
+  ParseModule;
+end;
+
 initialization
 initialization
   RegisterTest(TTestGenerics);
   RegisterTest(TTestGenerics);
 end.
 end.

+ 4 - 2
packages/fcl-passrc/tests/tcprocfunc.pas

@@ -1273,18 +1273,20 @@ procedure TTestProcedureFunction.TestOperatorNames;
 
 
 Var
 Var
   t : TOperatorType;
   t : TOperatorType;
+  S: String;
 
 
 begin
 begin
   For t:=Succ(otUnknown) to High(TOperatorType) do
   For t:=Succ(otUnknown) to High(TOperatorType) do
       begin
       begin
+      S:=GetEnumName(TypeInfo(TOperatorType),Ord(T));
       ResetParser;
       ResetParser;
       if t in UnaryOperators then
       if t in UnaryOperators then
         AddDeclaration(Format('operator %s (a: Integer) : te',[OperatorNames[t]]))
         AddDeclaration(Format('operator %s (a: Integer) : te',[OperatorNames[t]]))
       else
       else
         AddDeclaration(Format('operator %s (a: Integer; b: integer) : te',[OperatorNames[t]]));
         AddDeclaration(Format('operator %s (a: Integer; b: integer) : te',[OperatorNames[t]]));
       ParseOperator;
       ParseOperator;
-      AssertEquals('Token based',False,FOperator.TokenBased);
-      AssertEquals('Correct operator type',T,FOperator.OperatorType);
+      AssertEquals(S+': Token based',t in [otIn],FOperator.TokenBased);
+      AssertEquals(S+': Correct operator type',T,FOperator.OperatorType);
       if t in UnaryOperators then
       if t in UnaryOperators then
         AssertEquals('Correct operator name',format('%s(Integer):te',[OperatorNames[t]]),FOperator.Name)
         AssertEquals('Correct operator name',format('%s(Integer):te',[OperatorNames[t]]),FOperator.Name)
       else
       else

+ 1392 - 74
packages/fcl-passrc/tests/tcresolver.pas

@@ -256,6 +256,7 @@ type
     // enums and sets
     // enums and sets
     Procedure TestEnums;
     Procedure TestEnums;
     Procedure TestEnumRangeFail;
     Procedure TestEnumRangeFail;
+    Procedure TestEnumDotValueFail;
     Procedure TestSets;
     Procedure TestSets;
     Procedure TestSetOperators;
     Procedure TestSetOperators;
     Procedure TestEnumParams;
     Procedure TestEnumParams;
@@ -347,6 +348,8 @@ type
     Procedure TestForLoopStartIncompFail;
     Procedure TestForLoopStartIncompFail;
     Procedure TestForLoopEndIncompFail;
     Procedure TestForLoopEndIncompFail;
     Procedure TestSimpleStatement_VarFail;
     Procedure TestSimpleStatement_VarFail;
+    Procedure TestLabelStatementFail;
+    Procedure TestLabelStatementDelphiFail;
 
 
     // units
     // units
     Procedure TestUnitForwardOverloads;
     Procedure TestUnitForwardOverloads;
@@ -490,6 +493,7 @@ type
     Procedure TestAdvRecord;
     Procedure TestAdvRecord;
     Procedure TestAdvRecord_Private;
     Procedure TestAdvRecord_Private;
     Procedure TestAdvRecord_StrictPrivate;
     Procedure TestAdvRecord_StrictPrivate;
+    Procedure TestAdvRecord_StrictPrivateFail;
     Procedure TestAdvRecord_MethodImplMissingFail;
     Procedure TestAdvRecord_MethodImplMissingFail;
     Procedure TestAdvRecord_VarConst;
     Procedure TestAdvRecord_VarConst;
     Procedure TestAdvRecord_RecVal_ConstFail;
     Procedure TestAdvRecord_RecVal_ConstFail;
@@ -520,6 +524,9 @@ type
     Procedure TestClassForwardAsAncestorFail;
     Procedure TestClassForwardAsAncestorFail;
     Procedure TestClassForwardNotResolved;
     Procedure TestClassForwardNotResolved;
     Procedure TestClassForwardDuplicateFail;
     Procedure TestClassForwardDuplicateFail;
+    Procedure TestClassForwardDelphiFail;
+    Procedure TestClassForwardObjFPCProgram;
+    Procedure TestClassForwardObjFPCUnit;
     Procedure TestClass_Method;
     Procedure TestClass_Method;
     Procedure TestClass_ConstructorMissingDotFail;
     Procedure TestClass_ConstructorMissingDotFail;
     Procedure TestClass_MethodImplDuplicateFail;
     Procedure TestClass_MethodImplDuplicateFail;
@@ -658,6 +665,8 @@ type
     Procedure TestPropertyReadAccessorFuncWrongResult;
     Procedure TestPropertyReadAccessorFuncWrongResult;
     Procedure TestPropertyReadAccessorFuncWrongArgCount;
     Procedure TestPropertyReadAccessorFuncWrongArgCount;
     Procedure TestPropertyReadAccessorFunc;
     Procedure TestPropertyReadAccessorFunc;
+    Procedure TestPropertyReadAccessorStrictPrivate;
+    Procedure TestPropertyReadAccessorNonClassFail;
     Procedure TestPropertyWriteAccessorVarWrongType;
     Procedure TestPropertyWriteAccessorVarWrongType;
     Procedure TestPropertyWriteAccessorFuncNotProc;
     Procedure TestPropertyWriteAccessorFuncNotProc;
     Procedure TestPropertyWriteAccessorProcWrongArgCount;
     Procedure TestPropertyWriteAccessorProcWrongArgCount;
@@ -861,14 +870,45 @@ type
     Procedure TestHint_Garbage;
     Procedure TestHint_Garbage;
 
 
     // helpers
     // helpers
-    Procedure ClassHelper;
-    Procedure ClassHelper_AncestorIsNotHelperForDescendantFail;
-    Procedure ClassHelper_ForInterfaceFail;
-    Procedure ClassHelper_FieldFail;
-    Procedure ClassHelper_AbstractFail;
-    Procedure ClassHelper_VirtualObjFPCFail;
-    Procedure RecordHelper;
-    Procedure TypeHelper;
+    Procedure TestClassHelper;
+    Procedure TestClassHelper_AncestorIsNotHelperForDescendantFail;
+    Procedure TestClassHelper_HelperForParentFail;
+    Procedure TestClassHelper_ForInterfaceFail;
+    Procedure TestClassHelper_FieldFail;
+    Procedure TestClassHelper_AbstractFail;
+    Procedure TestClassHelper_VirtualObjFPCFail;
+    Procedure TestClassHelper_VirtualDelphiFail;
+    Procedure TestClassHelper_DestructorFail;
+    Procedure TestClassHelper_ClassRefersToTypeHelperOfAncestor;
+    Procedure TestClassHelper_InheritedObjFPC;
+    Procedure TestClassHelper_InheritedObjFPC2;
+    Procedure TestClassHelper_InheritedObjFPCStrictPrivateFail;
+    Procedure TestClassHelper_InheritedClassObjFPC;
+    Procedure TestClassHelper_InheritedDelphi;
+    Procedure TestClassHelper_NestedInheritedParentFail;
+    Procedure TestClassHelper_AccessFields;
+    Procedure TestClassHelper_CallClassMethodFail;
+    Procedure TestClassHelper_WithHelperFail;
+    Procedure TestClassHelper_AsTypeFail;
+    Procedure TestClassHelper_Enumerator;
+    Procedure TestClassHelper_FromUnitInterface;
+    Procedure TestClassHelper_Constructor_NewInstance;
+    Procedure TestClassHelper_ReintroduceHides_CallFail;
+    Procedure TestClassHelper_DefaultProperty;
+    Procedure TestClassHelper_DefaultClassProperty;
+    Procedure TestClassHelper_MultipleScopeHelpers;
+    Procedure TestRecordHelper;
+    Procedure TestRecordHelper_InheritedObjFPC;
+    Procedure TestRecordHelper_Constructor_NewInstance;
+    Procedure TestTypeHelper;
+    Procedure TestTypeHelper_HelperForProcTypeFail;
+    Procedure TestTypeHelper_DefaultPropertyFail;
+    Procedure TestTypeHelper_Enum;
+    Procedure TestTypeHelper_EnumDotValueFail;
+    Procedure TestTypeHelper_EnumHelperDotProcFail;
+    Procedure TestTypeHelper_Enumerator;
+    Procedure TestTypeHelper_Constructor_NewInstance;
+    Procedure TestTypeHelper_InterfaceFail;
 
 
     // attributes
     // attributes
     Procedure TestAttributes_Ignore;
     Procedure TestAttributes_Ignore;
@@ -2757,6 +2797,20 @@ begin
   '  r=low(word)+high(int64);',
   '  r=low(word)+high(int64);',
   '  s=low(longint)+high(integer);',
   '  s=low(longint)+high(integer);',
   '  t=succ(2)+pred(2);',
   '  t=succ(2)+pred(2);',
+  '  lo1:byte=lo(word($1234));',
+  '  hi1:byte=hi(word($1234));',
+  '  lo2:word=lo(longword($1234CDEF));',
+  '  hi2:word=hi(longword($1234CDEF));',
+  '  lo3:word=lo(LongInt(-$1234CDEF));',
+  '  hi3:word=hi(LongInt(-$1234CDEF));',
+  '  lo4:byte=lo(byte($34));',
+  '  hi4:byte=hi(byte($34));',
+  '  lo5:byte=lo(shortint(-$34));',
+  '  hi5:byte=hi(shortint(-$34));',
+  '  lo6:longword=lo($123456789ABCDEF0);',
+  '  hi6:longword=hi($123456789ABCDEF0);',
+  '  lo7:longword=lo(-$123456789ABCDEF0);',
+  '  hi7:longword=hi(-$123456789ABCDEF0);',
   'begin']);
   'begin']);
   ParseProgram;
   ParseProgram;
   CheckResolverUnexpectedHints;
   CheckResolverUnexpectedHints;
@@ -3517,6 +3571,17 @@ begin
   CheckParserException('Const ranges are not allowed',nParserNoConstRangeAllowed);
   CheckParserException('Const ranges are not allowed',nParserNoConstRangeAllowed);
 end;
 end;
 
 
+procedure TTestResolver.TestEnumDotValueFail;
+begin
+  StartProgram(false);
+  Add([
+  'type TFlag = (a,b,c);',
+  'var f: TFlag;',
+  'begin',
+  '  f:=f.a;']);
+  CheckResolverException('illegal qualifier "." after "f:TFlag"',nIllegalQualifierAfter);
+end;
+
 procedure TTestResolver.TestSets;
 procedure TTestResolver.TestSets;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
@@ -4308,6 +4373,10 @@ begin
   Add('  if i>=j then;');
   Add('  if i>=j then;');
   Add('  if i<j then;');
   Add('  if i<j then;');
   Add('  if i<=j then;');
   Add('  if i<=j then;');
+  Add('  i:=lo($1234);');
+  Add('  i:=lo($1234CDEF);');
+  Add('  i:=hi($1234);');
+  Add('  i:=hi($1234CDEF);');
   ParseProgram;
   ParseProgram;
 end;
 end;
 
 
@@ -5250,6 +5319,26 @@ begin
   CheckResolverException('Illegal expression',nIllegalExpression);
   CheckResolverException('Illegal expression',nIllegalExpression);
 end;
 end;
 
 
+procedure TTestResolver.TestLabelStatementFail;
+begin
+  StartProgram(false);
+  Add('var i: longint;');
+  Add('begin');
+  Add('  i: i;');
+  CheckParserException('Expected ";"',nParserExpectTokenError);
+end;
+
+procedure TTestResolver.TestLabelStatementDelphiFail;
+begin
+  StartProgram(false);
+  Add('{$mode delphi}');
+  Add('{$goto off}');
+  Add('var i: longint;');
+  Add('begin');
+  Add('  i: i;');
+  CheckParserException('Expected ";"',nParserExpectTokenError);
+end;
+
 procedure TTestResolver.TestUnitForwardOverloads;
 procedure TTestResolver.TestUnitForwardOverloads;
 begin
 begin
   StartUnit(false);
   StartUnit(false);
@@ -7872,6 +7961,30 @@ begin
 end;
 end;
 
 
 procedure TTestResolver.TestAdvRecord_StrictPrivate;
 procedure TTestResolver.TestAdvRecord_StrictPrivate;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch advancedrecords}',
+  'type',
+  '  TRec = record',
+  '  strict private',
+  '    FSize: longword;',
+  '    function GetSize: longword;',
+  '  public',
+  '    property Size: longword read GetSize write FSize;',
+  '  end;',
+  'function TRec.GetSize: longword;',
+  'begin',
+  '  FSize:=GetSize;',
+  'end;',
+  'var',
+  '  r: TRec;',
+  'begin',
+  '  r.Size:=r.Size;']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestAdvRecord_StrictPrivateFail;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
@@ -7885,7 +7998,7 @@ begin
   '  r: TRec;',
   '  r: TRec;',
   'begin',
   'begin',
   '  r.a:=r.a;']);
   '  r.a:=r.a;']);
-  CheckResolverException('Can''t access strict private member A',nCantAccessPrivateMember);
+  CheckResolverException('Can''t access strict private member A',nCantAccessXMember);
 end;
 end;
 
 
 procedure TTestResolver.TestAdvRecord_MethodImplMissingFail;
 procedure TTestResolver.TestAdvRecord_MethodImplMissingFail;
@@ -8027,8 +8140,16 @@ begin
   'begin',
   'begin',
   '  TRec.{#p}Create(4); // new object',
   '  TRec.{#p}Create(4); // new object',
   '  r:=TRec.{#q}Create(5); // new object',
   '  r:=TRec.{#q}Create(5); // new object',
-  '  r.{#r}Create(6); // normal call',
-  '  r:=r.{#s}Create(7); // normal call',
+  '  with TRec do begin',
+  '    {#r}Create(6); // new object',
+  '    r:={#s}Create(7); // new object',
+  '  end;',
+  '  r.{#t}Create(8); // normal call',
+  '  r:=r.{#u}Create(9); // normal call',
+  '  with r do begin',
+  '    {#v}Create(10); // normal call',
+  '    r:={#w}Create(11); // normal call',
+  '  end;',
   '']);
   '']);
   ParseProgram;
   ParseProgram;
   aMarker:=FirstSrcMarker;
   aMarker:=FirstSrcMarker;
@@ -8053,7 +8174,7 @@ begin
         break;
         break;
         end;
         end;
       case aMarker^.Identifier of
       case aMarker^.Identifier of
-      'a','r','s':// should be normal call
+      'a','t','u','v','w':// should be normal call
         if ActualNewInstance then
         if ActualNewInstance then
           RaiseErrorAtSrcMarker('expected normal call at "#'+aMarker^.Identifier+', but got newinstance"',aMarker);
           RaiseErrorAtSrcMarker('expected normal call at "#'+aMarker^.Identifier+', but got newinstance"',aMarker);
       else // should be newinstance
       else // should be newinstance
@@ -8616,6 +8737,62 @@ begin
   CheckResolverException('Duplicate identifier "TObject" at afile.pp(3,10)',nDuplicateIdentifier);
   CheckResolverException('Duplicate identifier "TObject" at afile.pp(3,10)',nDuplicateIdentifier);
 end;
 end;
 
 
+procedure TTestResolver.TestClassForwardDelphiFail;
+begin
+  StartProgram(false);
+  Add([
+  '{$mode delphi}',
+  'type',
+  '  TObject = class end;',
+  '  TBird = class;',
+  'const k = 1;',
+  'type',
+  '  TBird = class',
+  '  end;',
+  'begin']);
+  CheckResolverException('Forward type not resolved "TBird"',nForwardTypeNotResolved);
+end;
+
+procedure TTestResolver.TestClassForwardObjFPCProgram;
+begin
+  StartProgram(false);
+  Add([
+  '{$mode objfpc}',
+  'type',
+  '  TObject = class end;',
+  '  TBird = class;',
+  'const k = 1;',
+  'type',
+  '  TBird = class',
+  '  end;',
+  'begin']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestClassForwardObjFPCUnit;
+begin
+  StartUnit(false);
+  Add([
+  '{$mode objfpc}',
+  'interface',
+  'type',
+  '  TObject = class end;',
+  '  TBird = class;',
+  'const k = 1;',
+  'type',
+  '  TBird = class',
+  '  end;',
+  'implementation',
+  'type',
+  '  TEagle = class;',
+  'const c = 1;',
+  'type',
+  '  TEagle = class',
+  '  end;',
+  '']);
+  ParseUnit;
+end;
+
 procedure TTestResolver.TestClass_Method;
 procedure TTestResolver.TestClass_Method;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
@@ -9912,7 +10089,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  if o.v=3 then ;');
   Add('  if o.v=3 then ;');
   CheckResolverException('Can''t access private member v',
   CheckResolverException('Can''t access private member v',
-    nCantAccessPrivateMember);
+    nCantAccessXMember);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_PrivateInDescendantFail;
 procedure TTestResolver.TestClass_PrivateInDescendantFail;
@@ -9940,7 +10117,7 @@ begin
   Add('end;');
   Add('end;');
   Add('begin');
   Add('begin');
   CheckResolverException('Can''t access private member v',
   CheckResolverException('Can''t access private member v',
-    nCantAccessPrivateMember);
+    nCantAccessXMember);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_ProtectedInDescendant;
 procedure TTestResolver.TestClass_ProtectedInDescendant;
@@ -10002,7 +10179,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  if o.v=3 then ;');
   Add('  if o.v=3 then ;');
   CheckResolverException('Can''t access strict private member v',
   CheckResolverException('Can''t access strict private member v',
-    nCantAccessPrivateMember);
+    nCantAccessXMember);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_StrictProtectedInMainBeginFail;
 procedure TTestResolver.TestClass_StrictProtectedInMainBeginFail;
@@ -10017,7 +10194,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  if o.v=3 then ;');
   Add('  if o.v=3 then ;');
   CheckResolverException('Can''t access strict protected member v',
   CheckResolverException('Can''t access strict protected member v',
-    nCantAccessPrivateMember);
+    nCantAccessXMember);
 end;
 end;
 
 
 procedure TTestResolver.TestClass_Constructor_NewInstance;
 procedure TTestResolver.TestClass_Constructor_NewInstance;
@@ -10809,7 +10986,7 @@ begin
   '  Arm: TObject.TArm;',
   '  Arm: TObject.TArm;',
   'begin',
   'begin',
   '']);
   '']);
-  CheckResolverException('Can''t access strict private member TArm',nCantAccessPrivateMember);
+  CheckResolverException('Can''t access strict private member TArm',nCantAccessXMember);
 end;
 end;
 
 
 procedure TTestResolver.TestNestedClass_AccessStrictPrivate;
 procedure TTestResolver.TestNestedClass_AccessStrictPrivate;
@@ -11580,6 +11757,42 @@ begin
   ParseProgram;
   ParseProgram;
 end;
 end;
 
 
+procedure TTestResolver.TestPropertyReadAccessorStrictPrivate;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class',
+  '  strict private',
+  '    FSize: word;',
+  '    property Size: word read FSize;',
+  '  strict protected',
+  '    FName: string;',
+  '    property Name: string read FName;',
+  '  end;',
+  '  TBird = class',
+  '  strict protected',
+  '    property Caption: string read FName;',
+  '  end;',
+  'begin',
+  '']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestPropertyReadAccessorNonClassFail;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class',
+  '    FSize: word;',
+  '    class property Size: word read FSize;',
+  '  end;',
+  'begin',
+  '']);
+  CheckResolverException('class var expected, but var found',nXExpectedButYFound);
+end;
+
 procedure TTestResolver.TestPropertyWriteAccessorVarWrongType;
 procedure TTestResolver.TestPropertyWriteAccessorVarWrongType;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
@@ -11665,19 +11878,27 @@ end;
 procedure TTestResolver.TestPropertyTypeless;
 procedure TTestResolver.TestPropertyTypeless;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
-  Add('type');
-  Add('  {#TOBJ}TObject = class');
-  Add('    {#FB}FB: longint;');
-  Add('    property {#TOBJ_B}B: longint write {@FB}FB;');
-  Add('  end;');
-  Add('  {#TA}TClassA = class');
-  Add('    {#FC}FC: longint;');
-  Add('    property {#TA_B}{@TOBJ_B}B write {@FC}FC;');
-  Add('  end;');
-  Add('var');
-  Add('  {#v}{=TA}v: TClassA;');
-  Add('begin');
-  Add('  {@v}v.{@TA_B}B:=3;');
+  Add([
+  'type',
+  '  {#TOBJ}TObject = class',
+  '    {#FB}FB: longint;',
+  '    property {#TOBJ_B}B: longint write {@FB}FB;',
+  '    property {#TOBJ_D}D: longint write {@FB}FB;',
+  '  end;',
+  '  {#TA}TClassA = class',
+  '    {#FC}FC: longint;',
+  '    property {#TA_B}{@TOBJ_B}B write {@FC}FC;',
+  '  end;',
+  '  {#TB}TClassB = class(TClassA)',
+  '  published',
+  '    property {#TB_D}{@TOBJ_D}D;',
+  '  end;',
+  'var',
+  '  {#v}{=TA}v: TClassA;',
+  'begin',
+  '  {@v}v.{@TA_B}B:=3;',
+  '  {@v}v.{@TObj_D}D:=4;',
+  '']);
   ParseProgram;
   ParseProgram;
 end;
 end;
 
 
@@ -12024,25 +12245,26 @@ end;
 procedure TTestResolver.TestDefaultProperty;
 procedure TTestResolver.TestDefaultProperty;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
-  Add('type');
-  Add('  TObject = class');
-  Add('    function GetB(Index: longint): longint;');
-  Add('    procedure SetB(Index: longint; Value: longint);');
-  Add('    property B[Index: longint]: longint read GetB write SetB; default;');
-  Add('  end;');
-  Add('function TObject.GetB(Index: longint): longint;');
-  Add('begin');
-  Add('end;');
-  Add('procedure TObject.SetB(Index: longint; Value: longint);');
-  Add('begin');
-  Add('  if Value=Self[Index] then ;');
-  Add('  Self[Index]:=Value;');
-  Add('end;');
-  Add('var o: TObject;');
-  Add('begin');
-  Add('  o[3]:=4;');
-  Add('  if o[5]=6 then;');
-  Add('  if 7=o[8] then;');
+  Add([
+  'type',
+  '  TObject = class',
+  '    function GetB(Index: longint): longint;',
+  '    procedure SetB(Index: longint; Value: longint);',
+  '    property B[Index: longint]: longint read GetB write SetB; default;',
+  '  end;',
+  'function TObject.GetB(Index: longint): longint;',
+  'begin',
+  'end;',
+  'procedure TObject.SetB(Index: longint; Value: longint);',
+  'begin',
+  '  if Value=Self[Index] then ;',
+  '  Self[Index]:=Value;',
+  'end;',
+  'var o: TObject;',
+  'begin',
+  '  o[3]:=4;',
+  '  if o[5]=6 then;',
+  '  if 7=o[8] then;']);
   ParseProgram;
   ParseProgram;
 end;
 end;
 
 
@@ -12219,7 +12441,7 @@ begin
   '    constructor Create;',
   '    constructor Create;',
   '  end;',
   '  end;',
   'begin']);
   'begin']);
-  CheckParserException(SParserNoConstructorAllowed,nParserNoConstructorAllowed);
+  CheckParserException('constructor is not allowed in interface',nParserXNotAllowedInY);
 end;
 end;
 
 
 procedure TTestResolver.TestClassInterface_DelphiClassAncestorIntfFail;
 procedure TTestResolver.TestClassInterface_DelphiClassAncestorIntfFail;
@@ -15203,7 +15425,6 @@ begin
   '  PInteger = ^integer;',
   '  PInteger = ^integer;',
   'var',
   'var',
   '  i: integer;',
   '  i: integer;',
-  '  p1: PInteger;',
   'begin',
   'begin',
   '']);
   '']);
   CheckResolverException('identifier not found "integer"',nIdentifierNotFound);
   CheckResolverException('identifier not found "integer"',nIdentifierNotFound);
@@ -15496,7 +15717,7 @@ begin
   CheckResolverUnexpectedHints(true);
   CheckResolverUnexpectedHints(true);
 end;
 end;
 
 
-procedure TTestResolver.ClassHelper;
+procedure TTestResolver.TestClassHelper;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
@@ -15523,7 +15744,7 @@ begin
   ParseProgram;
   ParseProgram;
 end;
 end;
 
 
-procedure TTestResolver.ClassHelper_AncestorIsNotHelperForDescendantFail;
+procedure TTestResolver.TestClassHelper_AncestorIsNotHelperForDescendantFail;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
@@ -15544,7 +15765,25 @@ begin
     nDerivedXMustExtendASubClassY);
     nDerivedXMustExtendASubClassY);
 end;
 end;
 
 
-procedure TTestResolver.ClassHelper_ForInterfaceFail;
+procedure TTestResolver.TestClassHelper_HelperForParentFail;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class',
+  '  end;',
+  '  TBird = class(TObject)',
+  '  type',
+  '    TBirdHelper = class helper for TBird',
+  '    end;',
+  '  end;',
+  'begin',
+  '']);
+  CheckResolverException(sTypeXIsNotYetCompletelyDefined,
+    nTypeXIsNotYetCompletelyDefined);
+end;
+
+procedure TTestResolver.TestClassHelper_ForInterfaceFail;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
@@ -15560,7 +15799,7 @@ begin
     nXExpectedButYFound);
     nXExpectedButYFound);
 end;
 end;
 
 
-procedure TTestResolver.ClassHelper_FieldFail;
+procedure TTestResolver.TestClassHelper_FieldFail;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
@@ -15576,7 +15815,7 @@ begin
     nParserNoFieldsAllowed);
     nParserNoFieldsAllowed);
 end;
 end;
 
 
-procedure TTestResolver.ClassHelper_AbstractFail;
+procedure TTestResolver.TestClassHelper_AbstractFail;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
@@ -15593,7 +15832,7 @@ begin
     nInvalidXModifierY);
     nInvalidXModifierY);
 end;
 end;
 
 
-procedure TTestResolver.ClassHelper_VirtualObjFPCFail;
+procedure TTestResolver.TestClassHelper_VirtualObjFPCFail;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
@@ -15611,47 +15850,1126 @@ begin
     nInvalidXModifierY);
     nInvalidXModifierY);
 end;
 end;
 
 
-procedure TTestResolver.RecordHelper;
+procedure TTestResolver.TestClassHelper_VirtualDelphiFail;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
   '{$mode delphi}',
   '{$mode delphi}',
   'type',
   'type',
-  '  TRec = record',
+  '  TObject = class',
   '  end;',
   '  end;',
-  '  TRecHelper = record helper for TRec',
-  '  type T = word;',
-  '  const',
-  '    c: T = 3;',
-  '    k: T = 4;',
-  '  class var',
-  '    v: T;',
-  '    w: T;',
+  '  TObjHelper = class helper for TObject',
+  '    procedure DoIt; virtual;',
   '  end;',
   '  end;',
-  '  TAnt = word;',
-  '  TAntHelper = record helper for TAnt',
+  'procedure TObjHelper.DoIt;',
+  'begin end;',
+  'begin',
+  '']);
+  CheckResolverException('Invalid class helper procedure modifier virtual',
+    nInvalidXModifierY);
+end;
+
+procedure TTestResolver.TestClassHelper_DestructorFail;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class',
+  '  end;',
+  '  TObjHelper = class helper for TObject',
+  '    destructor Destroyer;',
+  '  end;',
+  'destructor TObjHelper.Destroyer;',
+  'begin end;',
+  'begin',
+  '']);
+  CheckParserException('destructor is not allowed in class helper',
+    nParserXNotAllowedInY);
+end;
+
+procedure TTestResolver.TestClassHelper_ClassRefersToTypeHelperOfAncestor;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class',
+  '  end;',
+  '  TObjHelper = class helper for TObject',
+  '  type',
+  '    TInt = word;',
+  '    function GetSize: TInt;',
   '  end;',
   '  end;',
+  '  TAnt = class',
+  '    procedure SetSize(Value: TInt);',
+  '    property Size: TInt read GetSize write SetSize;',
+  '  end;',
+  'function Tobjhelper.getSize: TInt;',
+  'begin',
+  'end;',
+  'procedure TAnt.SetSize(Value: TInt);',
+  'begin',
+  'end;',
   'begin',
   'begin',
   '']);
   '']);
   ParseProgram;
   ParseProgram;
 end;
 end;
 
 
-procedure TTestResolver.TypeHelper;
+procedure TTestResolver.TestClassHelper_InheritedObjFPC;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
-  '{$modeswitch typehelpers}',
   'type',
   'type',
-  '  TStringHelper = type helper for string',
+  '  TObject = class',
+  '    procedure {#TObject_Fly}Fly;',
   '  end;',
   '  end;',
-  '  TCaption = string;',
-  '  TCapHelper = type helper(TStringHelper) for TCaption',
+  '  TObjHelper = class helper for TObject',
+  '    procedure {#TObjHelper_Fly}Fly;',
+  '  end;',
+  '  TBird = class',
+  '    procedure {#TBird_Fly}Fly;',
+  '  end;',
+  '  TBirdHelper = class helper for TBird',
+  '    procedure {#TBirdHelper_Fly}Fly;',
+  '    procedure {#TBirdHelper_Walk}Walk;',
+  '  end;',
+  '  TEagleHelper = class helper(TBirdHelper) for TBird',
+  '    procedure {#TEagleHelper_Fly}Fly;',
+  '    procedure {#TEagleHelper_Walk}Walk;',
   '  end;',
   '  end;',
+  'procedure Tobject.fly;',
+  'begin',
+  '  inherited;', // ignore
+  'end;',
+  'procedure Tobjhelper.fly;',
   'begin',
   'begin',
+  '  {@TObject_Fly}inherited;',
+  '  inherited {@TObject_Fly}Fly;',
+  'end;',
+  'procedure Tbird.fly;',
+  'begin',
+  '  {@TObjHelper_Fly}inherited;',
+  '  inherited {@TObjHelper_Fly}Fly;',
+  'end;',
+  'procedure Tbirdhelper.fly;',
+  'begin',
+  '  {@TBird_Fly}inherited;',
+  '  inherited {@TBird_Fly}Fly;',
+  'end;',
+  'procedure Tbirdhelper.walk;',
+  'begin',
+  'end;',
+  'procedure teagleHelper.fly;',
+  'begin',
+  '  {@TBird_Fly}inherited;',
+  '  inherited {@TBird_Fly}Fly;',
+  'end;',
+  'procedure teagleHelper.walk;',
+  'begin',
+  '  {@TBirdHelper_Walk}inherited;',
+  '  inherited {@TBirdHelper_Walk}Walk;',
+  'end;',
+  'var',
+  '  o: TObject;',
+  '  b: TBird;',
+  'begin',
+  '  o.{@TObjHelper_Fly}Fly;',
+  '  b.{@TEagleHelper_Fly}Fly;',
   '']);
   '']);
   ParseProgram;
   ParseProgram;
 end;
 end;
 
 
+procedure TTestResolver.TestClassHelper_InheritedObjFPC2;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class',
+  '    procedure {#TObject_Fly}Fly;',
+  '  end;',
+  '  TObjHelper = class helper for TObject',
+  '    procedure {#TObjHelper_Walk}Walk;',
+  '  end;',
+  '  TBird = class',
+  '    procedure {#TBird_Fly}Fly;',
+  '  end;',
+  '  TBirdHelper = class helper for TBird',
+  '    procedure {#TBirdHelper_Walk}Walk;',
+  '  end;',
+  '  TEagleHelper = class helper(TBirdHelper) for TBird',
+  '    procedure {#TEagleHelper_Walk}Walk;',
+  '  end;',
+  'procedure Tobject.fly;',
+  'begin',
+  '  inherited;', // ignore
+  'end;',
+  'procedure Tobjhelper.walk;',
+  'begin',
+  '  inherited;', // ignore
+  'end;',
+  'procedure Tbird.fly;',
+  'begin',
+  '  {@TObject_Fly}inherited;', // no helper, search further in ancestor
+  '  inherited {@TObject_Fly}Fly;', // no helper, search further in ancestor
+  'end;',
+  'procedure Tbirdhelper.walk;',
+  'begin',
+  '  {@TObjHelper_Walk}inherited;',
+  '  inherited {@TObjHelper_Walk}Walk;',
+  'end;',
+  'procedure teagleHelper.walk;',
+  'begin',
+  '  {@TObjHelper_Walk}inherited;',
+  '  inherited {@TObjHelper_Walk}Walk;',
+  'end;',
+  'begin',
+  '']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestClassHelper_InheritedObjFPCStrictPrivateFail;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class',
+  '  strict private i: word;',
+  '  end;',
+  '  THelper = class helper for TObject',
+  '    property a: word read i;',
+  '  end;',
+  'begin',
+  '']);
+  CheckResolverException('Can''t access strict private member i',nCantAccessXMember);
+end;
+
+procedure TTestResolver.TestClassHelper_InheritedClassObjFPC;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class',
+  '    class procedure {#TObject_Fly}Fly;',
+  '  end;',
+  '  TObjHelper = class helper for TObject',
+  '    class procedure {#TObjHelper_Fly}Fly;',
+  '  end;',
+  '  TBird = class',
+  '    class procedure {#TBird_Fly}Fly;',
+  '  end;',
+  '  TBirdHelper = class helper for TBird',
+  '    class procedure {#TBirdHelper_Fly}Fly;',
+  '    class procedure {#TBirdHelper_Walk}Walk;',
+  '  end;',
+  '  TEagleHelper = class helper(TBirdHelper) for TBird',
+  '    class procedure {#TEagleHelper_Fly}Fly;',
+  '    class procedure {#TEagleHelper_Walk}Walk;',
+  '  end;',
+  'class procedure Tobject.fly;',
+  'begin',
+  '  inherited;', // ignore
+  'end;',
+  'class procedure Tobjhelper.fly;',
+  'begin',
+  '  {@TObject_Fly}inherited;',
+  '  inherited {@TObject_Fly}Fly;',
+  'end;',
+  'class procedure Tbird.fly;',
+  'begin',
+  '  {@TObjHelper_Fly}inherited;',
+  '  inherited {@TObjHelper_Fly}Fly;',
+  'end;',
+  'class procedure Tbirdhelper.fly;',
+  'begin',
+  '  {@TBird_Fly}inherited;',
+  '  inherited {@TBird_Fly}Fly;',
+  'end;',
+  'class procedure Tbirdhelper.walk;',
+  'begin',
+  'end;',
+  'class procedure teagleHelper.fly;',
+  'begin',
+  '  {@TBird_Fly}inherited;',
+  '  inherited {@TBird_Fly}Fly;',
+  'end;',
+  'class procedure teagleHelper.walk;',
+  'begin',
+  '  {@TBirdHelper_Walk}inherited;',
+  '  inherited {@TBirdHelper_Walk}Walk;',
+  'end;',
+  'var',
+  '  o: TObject;',
+  '  b: TBird;',
+  'begin',
+  '  o.{@TObjHelper_Fly}Fly;',
+  '  TObject.{@TObjHelper_Fly}Fly;',
+  '  b.{@TEagleHelper_Fly}Fly;',
+  '  TBird.{@TEagleHelper_Fly}Fly;',
+  '']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestClassHelper_InheritedDelphi;
+begin
+  StartProgram(false);
+  Add([
+  '{$mode delphi}',
+  'type',
+  '  TObject = class',
+  '    procedure {#TObject_Fly}Fly;',
+  '  end;',
+  '  TObjHelper = class helper for TObject',
+  '    procedure {#TObjHelper_Fly}Fly;',
+  '  end;',
+  '  TBird = class',
+  '    procedure {#TBird_Fly}Fly;',
+  '  end;',
+  '  TBirdHelper = class helper for TBird',
+  '    procedure {#TBirdHelper_Fly}Fly;',
+  '    procedure {#TBirdHelper_Walk}Walk;',
+  '  end;',
+  '  TEagleHelper = class helper(TBirdHelper) for TBird',
+  '    procedure {#TEagleHelper_Fly}Fly;',
+  '    procedure {#TEagleHelper_Walk}Walk;',
+  '  end;',
+  'procedure Tobject.fly;',
+  'begin',
+  '  inherited;', // ignore
+  'end;',
+  'procedure Tobjhelper.fly;',
+  'begin',
+  '  inherited;', // ignore
+  '  inherited {@TObject_Fly}Fly;',
+  'end;',
+  'procedure Tbird.fly;',
+  'begin',
+  '  {@TObjHelper_Fly}inherited;',
+  '  inherited {@TObjHelper_Fly}Fly;',
+  'end;',
+  'procedure Tbirdhelper.fly;',
+  'begin',
+  '  {@TObjHelper_Fly}inherited;',// skip helperfortype too
+  '  inherited {@TBird_Fly}Fly;',
+  'end;',
+  'procedure Tbirdhelper.walk;',
+  'begin',
+  'end;',
+  'procedure teagleHelper.fly;',
+  'begin',
+  '  {@TObjHelper_Fly}inherited;',// skip helperfortype too
+  '  inherited {@TBird_Fly}Fly;',
+  'end;',
+  'procedure teagleHelper.walk;',
+  'begin',
+  '  inherited;', // ignore
+  '  inherited {@TBirdHelper_Walk}Walk;',
+  'end;',
+  'var',
+  '  o: TObject;',
+  '  b: TBird;',
+  'begin',
+  '  o.{@TObjHelper_Fly}Fly;',
+  '  b.{@TEagleHelper_Fly}Fly;',
+  '']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestClassHelper_NestedInheritedParentFail;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class',
+  '  end;',
+  '  TBird = class',
+  '    procedure Fly;',
+  '  type',
+  '    TBirdHelper = class helper for TObject',
+  '      procedure Fly;',
+  '    end;',
+  '  end;',
+  'procedure TBird.fly;',
+  'begin',
+  'end;',
+  'procedure TBird.Tbirdhelper.fly;',
+  'begin',
+  '  inherited Fly;',
+  'end;',
+  'begin',
+  '']);
+  CheckResolverException('identifier not found "Fly"',nIdentifierNotFound);
+end;
+
+procedure TTestResolver.TestClassHelper_AccessFields;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class end;',
+  '  TBird = class',
+  '    Size: word;',
+  '    FItems: array of word;',
+  '  end;',
+  '  TBirdHelper = class helper for TBird',
+  '    procedure Fly;',
+  '  end;',
+  'procedure TBirdHelper.Fly;',
+  'begin',
+  '  Size:=FItems[0];',
+  '  Self.Size:=Self.FItems[0];',
+  'end;',
+  'var',
+  '  b: TBird;',
+  'begin',
+  '  b.Fly;',
+  '  b.Fly()',
+  '']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestClassHelper_CallClassMethodFail;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class end;',
+  '  THelper = class helper for TObject',
+  '    class procedure Fly;',
+  '  end;',
+  'class procedure THelper.Fly;',
+  'begin',
+  'end;',
+  'begin',
+  '  THelper.Fly;',
+  '']);
+  CheckResolverException(sHelpersCannotBeUsedAsTypes,nHelpersCannotBeUsedAsTypes);
+end;
+
+procedure TTestResolver.TestClassHelper_WithHelperFail;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class end;',
+  '  THelper = class helper for TObject',
+  '  end;',
+  'begin',
+  '  with THelper do ;',
+  '']);
+  CheckResolverException(sHelpersCannotBeUsedAsTypes,nHelpersCannotBeUsedAsTypes);
+end;
+
+procedure TTestResolver.TestClassHelper_AsTypeFail;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class end;',
+  '  THelper = class helper for TObject',
+  '  end;',
+  'var h: THelper;',
+  'begin',
+  '']);
+  CheckResolverException(sHelpersCannotBeUsedAsTypes,nHelpersCannotBeUsedAsTypes);
+end;
+
+procedure TTestResolver.TestClassHelper_Enumerator;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class end;',
+  '  TItem = TObject;',
+  '  TEnumerator = class',
+  '    FCurrent: TItem;',
+  '    property Current: TItem read FCurrent;',
+  '    function MoveNext: boolean;',
+  '  end;',
+  '  TBird = class',
+  '    FItems: array of TItem;',
+  '  end;',
+  '  TBirdHelper = class helper for TBird',
+  '    function GetEnumerator: TEnumerator;',
+  '  end;',
+  'function TEnumerator.MoveNext: boolean;',
+  'begin',
+  'end;',
+  'function TBirdHelper.GetEnumerator: TEnumerator;',
+  'begin',
+  '  Result.FCurrent:=FItems[0];',
+  '  Result.FCurrent:=Self.FItems[0];',
+  'end;',
+  'var',
+  '  b: TBird;',
+  '  i: TItem;',
+  '  {#i2}i2: TItem;',
+  'begin',
+  '  for i in b do {@i2}i2:=i;']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestClassHelper_FromUnitInterface;
+begin
+  AddModuleWithIntfImplSrc('unit2.pas',
+    LinesToStr([
+    'type',
+    '  TObject = class',
+    '  public',
+    '    Id: word;',
+    '  end;',
+    '  TObjHelper = class helper for TObject',
+    '    property Size: word read ID write ID;',
+    '  end;',
+    '']),
+    '');
+  AddModuleWithIntfImplSrc('unit3.pas',
+    LinesToStr([
+    'uses unit2;',
+    'type',
+    '  TObjHelper = class helper for TObject',
+    '    property Size: word read ID write ID;',
+    '  end;',
+    '']),
+    '');
+  StartProgram(true);
+  Add([
+  'uses unit2, unit3;',
+  'var o: TObject;',
+  'begin',
+  '  o.Size:=o.Size;']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestClassHelper_Constructor_NewInstance;
+var
+  aMarker: PSrcMarker;
+  Elements: TFPList;
+  i: Integer;
+  El: TPasElement;
+  Ref: TResolvedReference;
+  ActualNewInstance, ActualImplicitCallWithoutParams: Boolean;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class',
+  '  end;',
+  '  THelper = class helper for TObject',
+  '    constructor Create;',
+  '    class function DoSome: TObject;',
+  '  end;',
+  'constructor THelper.Create;',
+  'begin',
+  '  {#a}Create; // normal call',
+  '  TObject.{#b}Create; // new instance',
+  'end;',
+  'class function THelper.DoSome: TObject;',
+  'begin',
+  '  Result:={#c}Create; // new instance',
+  'end;',
+  'var',
+  '  o: TObject;',
+  'begin',
+  '  TObject.{#p}Create; // new object',
+  '  o:=TObject.{#q}Create; // new object',
+  '  with TObject do begin',
+  '    {#r}Create; // new object',
+  '    o:={#s}Create; // new object',
+  '  end;',
+  '  o.{#t}Create; // normal call',
+  '  o:=o.{#u}Create; // normal call',
+  '  with o do begin',
+  '    {#v}Create; // normal call',
+  '    o:={#w}Create; // normal call',
+  '  end;',
+  '']);
+  ParseProgram;
+  aMarker:=FirstSrcMarker;
+  while aMarker<>nil do
+    begin
+    //writeln('TTestResolver.TestClassHelper_Constructor_NewInstance ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
+    Elements:=FindElementsAt(aMarker);
+    try
+      ActualNewInstance:=false;
+      ActualImplicitCallWithoutParams:=false;
+      for i:=0 to Elements.Count-1 do
+        begin
+        El:=TPasElement(Elements[i]);
+        //writeln('TTestResolver.TestClassHelper_Constructor_NewInstance ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
+        if not (El.CustomData is TResolvedReference) then continue;
+        Ref:=TResolvedReference(El.CustomData);
+        if not (Ref.Declaration is TPasProcedure) then continue;
+        //writeln('TTestResolver.TestClassHelper_Constructor_NewInstance ',GetObjName(Ref.Declaration),' rrfNewInstance=',rrfNewInstance in Ref.Flags);
+        if (Ref.Declaration is TPasConstructor) then
+          ActualNewInstance:=rrfNewInstance in Ref.Flags;
+        ActualImplicitCallWithoutParams:=rrfImplicitCallWithoutParams in Ref.Flags;
+        break;
+        end;
+      if not ActualImplicitCallWithoutParams then
+        RaiseErrorAtSrcMarker('expected implicit call at "#'+aMarker^.Identifier+', but got function ref"',aMarker);
+      case aMarker^.Identifier of
+      'a','t','u','v','w':// should be normal call
+        if ActualNewInstance then
+          RaiseErrorAtSrcMarker('expected normal call at "#'+aMarker^.Identifier+', but got newinstance"',aMarker);
+      else // should be newinstance
+        if not ActualNewInstance then
+          RaiseErrorAtSrcMarker('expected newinstance at "#'+aMarker^.Identifier+', but got normal call"',aMarker);
+      end;
+    finally
+      Elements.Free;
+    end;
+    aMarker:=aMarker^.Next;
+    end;
+end;
+
+procedure TTestResolver.TestClassHelper_ReintroduceHides_CallFail;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class',
+  '    constructor Create(o: tobject);',
+  '  end;',
+  '  TBird = class helper for TObject',
+  '    constructor Create(i: longint); reintroduce;',
+  '  end;',
+  'constructor tobject.Create(o: tobject); begin end;',
+  'constructor tbird.Create(i: longint); begin end;',
+  'var o: TObject;',
+  'begin',
+  '  o:=TObject.Create(nil);',
+  '']);
+  CheckResolverException('Incompatible type arg no. 1: Got "Nil", expected "Longint"',
+    nIncompatibleTypeArgNo);
+end;
+
+procedure TTestResolver.TestClassHelper_DefaultProperty;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class',
+  '    function GetB(Index: longint): longint;',
+  '    procedure SetB(Index: longint; Value: longint);',
+  '  end;',
+  '  THelper = class helper for TObject',
+  '    property B[Index: longint]: longint read GetB write SetB; default;',
+  '  end;',
+  'function TObject.GetB(Index: longint): longint;',
+  'begin',
+  'end;',
+  'procedure TObject.SetB(Index: longint; Value: longint);',
+  'begin',
+  '  if Value=Self[Index] then ;',
+  '  Self[Index]:=Value;',
+  'end;',
+  'var o: TObject;',
+  'begin',
+  '  o[3]:=4;',
+  '  if o[5]=6 then;',
+  '  if 7=o[8] then;',
+  '']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestClassHelper_DefaultClassProperty;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TClass = class of TObject;',
+  '  TObject = class',
+  '    class function GetB(Index: longint): longint; static;',
+  '    class procedure SetB(Index: longint; Value: longint); static;',
+  '  end;',
+  '  THelper = class helper for TObject',
+  '    class property B[Index: longint]: longint read GetB write SetB; default;',
+  '  end;',
+  'class function TObject.GetB(Index: longint): longint;',
+  'begin',
+  'end;',
+  'class procedure TObject.SetB(Index: longint; Value: longint);',
+  'begin',
+  '  if Value=TObject[Index] then ;',
+  '  TObject[Index]:=Value;',
+  'end;',
+  'var c: TClass;',
+  'begin',
+  '  c[3]:=4;',
+  '  if c[5]=6 then;',
+  '  if 7=c[8] then;',
+  '']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestClassHelper_MultipleScopeHelpers;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch multiplescopehelpers}',
+  'type',
+  '  TObject = class',
+  '  end;',
+  '  TFlyHelper = class helper for TObject',
+  '    procedure {#Fly}Fly;',
+  '    procedure {#FlyMove}Move;',
+  '  end;',
+  '  TRunHelper = class helper for TObject',
+  '    procedure {#Run}Run;',
+  '    procedure {#RunMove}Move;',
+  '    procedure {#RunBack}Back;',
+  '  end;',
+  '  TSwimHelper = class helper for TObject',
+  '    procedure {#Swim}Swim;',
+  '    procedure {#SwimBack}Back;',
+  '  end;',
+  'procedure TFlyHelper.Fly; begin end;',
+  'procedure TFlyHelper.Move; begin end;',
+  'procedure TRunHelper.Run; begin end;',
+  'procedure TRunHelper.Move; begin end;',
+  'procedure TRunHelper.Back; begin end;',
+  'procedure TSwimHelper.Swim; begin end;',
+  'procedure TSwimHelper.Back; begin end;',
+  'var o: TObject;',
+  'begin',
+  '  o.{@Fly}Fly;',
+  '  o.{@Run}Run;',
+  '  o.{@Swim}Swim;',
+  '  o.{@RunMove}Move;',
+  '  o.{@SwimBack}Back;',
+  '']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestRecordHelper;
+begin
+  StartProgram(false);
+  Add([
+  '{$mode delphi}',
+  'type',
+  '  TProc = procedure of object;',
+  '  TRec = record',
+  '    x: word;',
+  '  end;',
+  '  TRecHelper = record helper for TRec',
+  '  type T = word;',
+  '  const',
+  '    c: T = 3;',
+  '    k: T = 4;',
+  '  class var',
+  '    v: T;',
+  '    w: T;',
+  '    procedure Fly;',
+  '  end;',
+  '  TAnt = word;',
+  '  TAntHelper = record helper for TAnt',
+  '  end;',
+  'procedure TRecHelper.Fly;',
+  'var',
+  '  r: TRec;',
+  '  p: TProc;',
+  'begin',
+  '  Self:=r;',
+  '  r:=Self;',
+  '  c:=v+x;',
+  '  x:=k+w;',
+  '  p:=Fly;',
+  'end;',
+  'var',
+  '  r: TRec;',
+  '  p: TProc;',
+  'begin',
+  '  p:=r.Fly;',
+  '']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestRecordHelper_InheritedObjFPC;
+begin
+  StartProgram(false);
+  Add([
+  '{$mode objfpc}',
+  '{$modeswitch advancedrecords}',
+  'type',
+  '  TRec = record',
+  '    procedure {#TRec_Fly}Fly;',
+  '  end;',
+  '  TRecHelper = record helper for TRec',
+  '    procedure {#TRecHelper_Fly}Fly;',
+  '    procedure {#TRecHelper_Walk}Walk;',
+  '    procedure {#TRecHelper_Run}Run;',
+  '  end;',
+  '  TEagleHelper = record helper(TRecHelper) for TRec',
+  '    procedure {#TEagleHelper_Fly}Fly;',
+  '    procedure {#TEagleHelper_Run}Run;',
+  '  end;',
+  'procedure TRec.fly;',
+  'begin',
+  'end;',
+  'procedure TRechelper.fly;',
+  'begin',
+  '  {@TRec_Fly}inherited;',
+  '  inherited {@TRec_Fly}Fly;',
+  'end;',
+  'procedure TRechelper.walk;',
+  'begin',
+  '  inherited;', // ignore
+  'end;',
+  'procedure TRechelper.run;',
+  'begin',
+  '  inherited;', // ignore
+  'end;',
+  'procedure teagleHelper.fly;',
+  'begin',
+  '  {@TRec_Fly}inherited;',
+  '  inherited {@TRec_Fly}Fly;',
+  'end;',
+  'procedure teagleHelper.run;',
+  'begin',
+  '  {@TRecHelper_Run}inherited;',
+  '  inherited {@TRecHelper_Run}Run;',
+  'end;',
+  'var',
+  '  r: TRec;',
+  'begin',
+  '  r.{@TEagleHelper_Fly}Fly;',
+  '  r.{@TRecHelper_Walk}Walk;',
+  '  r.{@TEagleHelper_Run}Run;',
+  '']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestRecordHelper_Constructor_NewInstance;
+var
+  aMarker: PSrcMarker;
+  Elements: TFPList;
+  ActualNewInstance: Boolean;
+  i: Integer;
+  El: TPasElement;
+  Ref: TResolvedReference;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch advancedrecords}',
+  '{$modeswitch typehelpers}',
+  'type',
+  '  TRec = record',
+  '    constructor Create(w: word);',
+  '    class function DoSome: TRec; static;',
+  '  end;',
+  'constructor TRec.Create(w: word);',
+  'begin',
+  '  {#a}Create(1); // normal call',
+  '  TRec.{#b}Create(2); // new instance',
+  'end;',
+  'class function TRec.DoSome: TRec;',
+  'begin',
+  '  Result:={#c}Create(3); // new instance',
+  'end;',
+  'var',
+  '  r: TRec;',
+  'begin',
+  '  TRec.{#p}Create(4); // new object',
+  '  r:=TRec.{#q}Create(5); // new object',
+  '  with TRec do begin',
+  '    {#r}Create(6); // new object',
+  '    r:={#s}Create(7); // new object',
+  '  end;',
+  '  r.{#t}Create(8); // normal call',
+  '  r:=r.{#u}Create(9); // normal call',
+  '  with r do begin',
+  '    {#v}Create(10); // normal call',
+  '    r:={#w}Create(11); // normal call',
+  '  end;',
+  '']);
+  ParseProgram;
+  aMarker:=FirstSrcMarker;
+  while aMarker<>nil do
+    begin
+    //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
+    Elements:=FindElementsAt(aMarker);
+    try
+      ActualNewInstance:=false;
+      for i:=0 to Elements.Count-1 do
+        begin
+        El:=TPasElement(Elements[i]);
+        //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
+        if not (El.CustomData is TResolvedReference) then continue;
+        Ref:=TResolvedReference(El.CustomData);
+        if not (Ref.Declaration is TPasProcedure) then continue;
+        //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',GetObjName(Ref.Declaration),' rrfNewInstance=',rrfNewInstance in Ref.Flags);
+        if (Ref.Declaration is TPasConstructor) then
+          ActualNewInstance:=rrfNewInstance in Ref.Flags;
+        if rrfImplicitCallWithoutParams in Ref.Flags then
+          RaiseErrorAtSrcMarker('unexpected implicit call at "#'+aMarker^.Identifier+' ref"',aMarker);
+        break;
+        end;
+      case aMarker^.Identifier of
+      'a','t','u','v','w':// should be normal call
+        if ActualNewInstance then
+          RaiseErrorAtSrcMarker('expected normal call at "#'+aMarker^.Identifier+', but got newinstance"',aMarker);
+      else // should be newinstance
+        if not ActualNewInstance then
+          RaiseErrorAtSrcMarker('expected newinstance at "#'+aMarker^.Identifier+', but got normal call"',aMarker);
+      end;
+    finally
+      Elements.Free;
+    end;
+    aMarker:=aMarker^.Next;
+    end;
+end;
+
+procedure TTestResolver.TestTypeHelper;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch typehelpers}',
+  'type',
+  '  TStringHelper = type helper for string',
+  '  end;',
+  '  TCaption = string;',
+  '  TCapHelper = type helper(TStringHelper) for TCaption',
+  '    procedure Fly;',
+  '  end;',
+  '  TProc = procedure of object;',
+  'procedure TCapHelper.Fly; begin end;',
+  'var',
+  '  c: TCaption;',
+  '  p: TProc;',
+  'begin',
+  '  c.Fly;',
+  '  p:[email protected];',
+  '']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestTypeHelper_HelperForProcTypeFail;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch typehelpers}',
+  'type',
+  '  TProc = procedure;',
+  '  THelper = type helper for TProc',
+  '  end;',
+  'begin',
+  '']);
+  CheckResolverException('Type "TProc" cannot be extended by a type helper',
+    nTypeXCannotBeExtendedByATypeHelper);
+end;
+
+procedure TTestResolver.TestTypeHelper_DefaultPropertyFail;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch typehelpers}',
+  'type',
+  '  TStringHelper = type helper for string',
+  '  end;',
+  '  TCaption = string;',
+  '  TCapHelper = type helper(TStringHelper) for TCaption',
+  '    function GetItems(Index: boolean): boolean;',
+  '    property Items[Index: boolean]: boolean read GetItems; default;',
+  '  end;',
+  'function TCapHelper.GetItems(Index: boolean): boolean; begin end;',
+  'begin',
+  '']);
+  CheckResolverException('Default property not allowed in helper for TCaption',
+    nDefaultPropertyNotAllowedInHelperForX);
+end;
+
+procedure TTestResolver.TestTypeHelper_Enum;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch typehelpers}',
+  'type',
+  '  TFlag = (Red, Green, Blue);',
+  '  THelper = type helper for TFlag',
+  '    function toString: string;',
+  '    class procedure Fly;',
+  '  end;',
+  'function THelper.toString: string;',
+  'begin',
+  '  Self:=Red;',
+  '  if Self=TFlag.Blue then ;',
+  '  Result:=str(Self);',
+  'end;',
+  'class procedure THelper.Fly;',
+  'begin',
+  'end;',
+  'var',
+  '  f: TFlag;',
+  'begin',
+  '  f.toString;',
+  '  TFlag.Fly;',
+  '']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestTypeHelper_EnumDotValueFail;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch typehelpers}',
+  'type',
+  '  TFlag = (Red, Green, Blue);',
+  '  THelper = type helper for TFlag',
+  '  end;',
+  'var',
+  '  f: TFlag;',
+  'begin',
+  '  f:=f.red;',
+  '']);
+  CheckResolverException('identifier not found "red"',nIdentifierNotFound);
+end;
+
+procedure TTestResolver.TestTypeHelper_EnumHelperDotProcFail;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch typehelpers}',
+  'type',
+  '  TFlag = (Red, Green, Blue);',
+  '  THelper = type helper for TFlag',
+  '    procedure Fly;',
+  '  end;',
+  'procedure THelper.Fly;',
+  'begin',
+  'end;',
+  'begin',
+  '  TFlag.Fly;',
+  '']);
+  CheckResolverException('Cannot access this member from a type helper',nCannotAccessThisMemberFromAX);
+end;
+
+procedure TTestResolver.TestTypeHelper_Enumerator;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch typehelpers}',
+  'type',
+  '  TObject = class end;',
+  '  TItem = byte;',
+  '  TEnumerator = class',
+  '    FCurrent: TItem;',
+  '    property Current: TItem read FCurrent;',
+  '    function MoveNext: boolean;',
+  '  end;',
+  '  TWordHelper = type helper for Word',
+  '    function GetEnumerator: TEnumerator;',
+  '  end;',
+  'function TEnumerator.MoveNext: boolean;',
+  'begin',
+  'end;',
+  'function TWordHelper.GetEnumerator: TEnumerator;',
+  'begin',
+  '  if Self=2 then ;',
+  '  Self:=Self+3;',
+  'end;',
+  'var',
+  '  w: word;',
+  '  i: TItem;',
+  '  {#i2}i2: TItem;',
+  'begin',
+  '  w.GetEnumerator;',
+  '  for i in w do {@i2}i2:=i;']);
+  ParseProgram;
+end;
+
+procedure TTestResolver.TestTypeHelper_Constructor_NewInstance;
+var
+  aMarker: PSrcMarker;
+  Elements: TFPList;
+  ActualNewInstance: Boolean;
+  i: Integer;
+  El: TPasElement;
+  Ref: TResolvedReference;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch typehelpers}',
+  'type',
+  '  TInt = type word;',
+  '  THelper = type helper for TInt',
+  '    constructor Create(w: TInt);',
+  '    class function DoSome: TInt; static;',
+  '  end;',
+  'constructor THelper.Create(w: TInt);',
+  'begin',
+  '  {#a}Create(1); // normal call',
+  '  TInt.{#b}Create(2); // new instance',
+  'end;',
+  'class function THelper.DoSome: TInt;',
+  'begin',
+  '  Result:={#c}Create(3); // new instance',
+  'end;',
+  'var',
+  '  r: TInt;',
+  'begin',
+  '  TInt.{#p}Create(4); // new object',
+  '  r:=TInt.{#q}Create(5); // new object',
+  '  with TInt do begin',
+  '    {#r}Create(6); // new object',
+  '    r:={#s}Create(7); // new object',
+  '  end;',
+  '  r.{#t}Create(8); // normal call',
+  '  r:=r.{#u}Create(9); // normal call',
+  '  with r do begin',
+  '    {#v}Create(10); // normal call',
+  '    r:={#w}Create(11); // normal call',
+  '  end;',
+  '']);
+  ParseProgram;
+  aMarker:=FirstSrcMarker;
+  while aMarker<>nil do
+    begin
+    //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
+    Elements:=FindElementsAt(aMarker);
+    try
+      ActualNewInstance:=false;
+      for i:=0 to Elements.Count-1 do
+        begin
+        El:=TPasElement(Elements[i]);
+        //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
+        if not (El.CustomData is TResolvedReference) then continue;
+        Ref:=TResolvedReference(El.CustomData);
+        if not (Ref.Declaration is TPasProcedure) then continue;
+        //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',GetObjName(Ref.Declaration),' rrfNewInstance=',rrfNewInstance in Ref.Flags);
+        if (Ref.Declaration is TPasConstructor) then
+          ActualNewInstance:=rrfNewInstance in Ref.Flags;
+        if rrfImplicitCallWithoutParams in Ref.Flags then
+          RaiseErrorAtSrcMarker('unexpected implicit call at "#'+aMarker^.Identifier+' ref"',aMarker);
+        break;
+        end;
+      case aMarker^.Identifier of
+      'a','t','u','v','w':// should be normal call
+        if ActualNewInstance then
+          RaiseErrorAtSrcMarker('expected normal call at "#'+aMarker^.Identifier+', but got newinstance"',aMarker);
+      else // should be newinstance
+        if not ActualNewInstance then
+          RaiseErrorAtSrcMarker('expected newinstance at "#'+aMarker^.Identifier+', but got normal call"',aMarker);
+      end;
+    finally
+      Elements.Free;
+    end;
+    aMarker:=aMarker^.Next;
+    end;
+end;
+
+procedure TTestResolver.TestTypeHelper_InterfaceFail;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch typehelpers}',
+  'type',
+  '  IUnknown = interface end;',
+  '  THelper = type helper for IUnknown',
+  '  end;',
+  'begin',
+  '']);
+  CheckResolverException('Type "IUnknown" cannot be extended by a type helper',nTypeXCannotBeExtendedByATypeHelper);
+end;
+
 procedure TTestResolver.TestAttributes_Ignore;
 procedure TTestResolver.TestAttributes_Ignore;
 begin
 begin
   StartProgram(false);
   StartProgram(false);

+ 3 - 1
packages/fcl-passrc/tests/tcstatements.pas

@@ -1794,7 +1794,9 @@ end;
 procedure TTestStatementParser.TestGotoInIfThen;
 procedure TTestStatementParser.TestGotoInIfThen;
 
 
 begin
 begin
-  AddStatements(['if expr then',
+  AddStatements([
+  '{$goto on}',
+  'if expr then',
   '  dosomething',
   '  dosomething',
   '   else if expr2 then',
   '   else if expr2 then',
   '    goto try_qword',
   '    goto try_qword',

+ 242 - 296
packages/graph/src/go32v2/graph.pp

@@ -155,9 +155,13 @@ const
      ScrWidth : word absolute $40:$4a;
      ScrWidth : word absolute $40:$4a;
      inWindows: boolean;
      inWindows: boolean;
 
 
-{$ifndef tp}
   Procedure seg_bytemove(sseg : word;source : longint;dseg : word;dest : longint;count : longint); assembler;
   Procedure seg_bytemove(sseg : word;source : longint;dseg : word;dest : longint;count : longint); assembler;
     asm
     asm
+      {# Var sseg located in register ax
+       # Var source located in register edx
+       # Var dseg located in register cx
+       # Var dest located at ebp+12, size=OS_S32
+       # Var count located at ebp+8, size=OS_S32 }
       push edi
       push edi
       push esi
       push esi
       push es
       push es
@@ -173,14 +177,11 @@ const
       pop es
       pop es
       pop esi
       pop esi
       pop edi
       pop edi
-    end ['ECX'];
-{$endif tp}
+    end;
 
 
  Procedure CallInt10(val_ax : word); assembler;
  Procedure CallInt10(val_ax : word); assembler;
    asm
    asm
-{$IFNDEF REGCALL}
-     mov ax,val_ax
-{$ENDIF REGCALL}
+      {# Var val_ax located in register ax }
       push ebp
       push ebp
       push esi
       push esi
       push edi
       push edi
@@ -190,114 +191,125 @@ const
       pop edi
       pop edi
       pop esi
       pop esi
       pop ebp
       pop ebp
-   end ['EAX'];
+   end;
 
 
-  procedure seg_xorword(segment : word;ofs : longint;count : longint;w : word);
-    begin
-      asm
-         push edi
-         mov edi, [ofs]
-         mov ecx, [count]
-         movzx edx, word ptr [w]
-         { load segment }
-         push es
-         mov ax, [segment]
-         mov es, ax
-         { fill eax }
-         mov eax, edx
-         shl eax, 16
-         or eax, edx
-         test edi, 3
-         jz @@aligned
-         xor word ptr es:[edi], ax
-         add edi, 2
-         dec ecx
-         jz @@done
+ Procedure InitInt10hMode(mode : byte);
+   begin
+     if DontClearGraphMemory then
+       CallInt10(mode or $80)
+     else
+       CallInt10(mode);
+   end;
+
+  procedure seg_xorword(segment : word;ofs : longint;count : longint;w : word); assembler;
+    asm
+      {# Var segment located in register ax
+       # Var ofs located in register edx
+       # Var count located in register ecx
+       # Var w located at ebp+8, size=OS_16 }
+      push edi
+      mov edi, edx
+      { load segment }
+      push es
+      mov es, ax
+      { fill eax }
+      movzx edx, word ptr [w]
+      mov eax, edx
+      shl eax, 16
+      or eax, edx
+      test edi, 3
+      jz @@aligned
+      xor word ptr es:[edi], ax
+      add edi, 2
+      dec ecx
+      jz @@done
 @@aligned:
 @@aligned:
-         mov edx, ecx
-         shr ecx, 1
-@@lp:    xor dword ptr es:[edi], eax
-         add edi, 4
-         dec ecx
-         jnz @@lp
-         test edx, 1
-         jz @@done
-         xor word ptr es:[edi], ax
-@@done:  pop es
-         pop edi
-      end;
+      mov edx, ecx
+      shr ecx, 1
+@@lp: xor dword ptr es:[edi], eax
+      add edi, 4
+      dec ecx
+      jnz @@lp
+      test edx, 1
+      jz @@done
+      xor word ptr es:[edi], ax
+@@done:
+      pop es
+      pop edi
     end;
     end;
 
 
-  procedure seg_orword(segment : word;ofs : longint;count : longint;w : word);
-    begin
-      asm
-         push edi
-         mov edi, [ofs]
-         mov ecx, [count]
-         movzx edx, word ptr [w]
-         { load segment }
-         push es
-         mov ax, [segment]
-         mov es, ax
-         { fill eax }
-         mov eax, edx
-         shl eax, 16
-         or eax, edx
-         test edi, 3
-         jz @@aligned
-         or word ptr es:[edi], ax
-         add edi, 2
-         dec ecx
-         jz @@done
+  procedure seg_orword(segment : word;ofs : longint;count : longint;w : word); assembler;
+    asm
+      {# Var segment located in register ax
+       # Var ofs located in register edx
+       # Var count located in register ecx
+       # Var w located at ebp+8, size=OS_16 }
+      push edi
+      mov edi, edx
+      { load segment }
+      push es
+      mov es, ax
+      { fill eax }
+      movzx edx, word ptr [w]
+      mov eax, edx
+      shl eax, 16
+      or eax, edx
+      test edi, 3
+      jz @@aligned
+      or word ptr es:[edi], ax
+      add edi, 2
+      dec ecx
+      jz @@done
 @@aligned:
 @@aligned:
-         mov edx, ecx
-         shr ecx, 1
-@@lp:    or dword ptr es:[edi], eax
-         add edi, 4
-         dec ecx
-         jnz @@lp
-         test edx, 1
-         jz @@done
-         or word ptr es:[edi], ax
-@@done:  pop es
-         pop edi
-      end;
+      mov edx, ecx
+      shr ecx, 1
+@@lp: or dword ptr es:[edi], eax
+      add edi, 4
+      dec ecx
+      jnz @@lp
+      test edx, 1
+      jz @@done
+      or word ptr es:[edi], ax
+@@done:
+      pop es
+      pop edi
     end;
     end;
 
 
-  procedure seg_andword(segment : word;ofs : longint;count : longint;w : word);
-    begin
-      asm
-         push edi
-         mov edi, [ofs]
-         mov ecx, [count]
-         movzx edx, word ptr [w]
-         { load segment }
-         push es
-         mov ax, [segment]
-         mov es, ax
-         { fill eax }
-         mov eax, edx
-         shl eax, 16
-         or eax, edx
-         test edi, 3
-         jz @@aligned
-         and word ptr es:[edi], ax
-         add edi, 2
-         dec ecx
-         jz @@done
+  procedure seg_andword(segment : word;ofs : longint;count : longint;w : word); assembler;
+    asm
+      {# Var segment located in register ax
+       # Var ofs located in register edx
+       # Var count located in register ecx
+       # Var w located at ebp+8, size=OS_16 }
+      push edi
+      mov edi, edx
+      { load segment }
+      push es
+      mov es, ax
+      { fill eax }
+      movzx edx, word ptr [w]
+      mov eax, edx
+      shl eax, 16
+      or eax, edx
+      test edi, 3
+      jz @@aligned
+      and word ptr es:[edi], ax
+      add edi, 2
+      dec ecx
+      jz @@done
 @@aligned:
 @@aligned:
-         mov edx, ecx
-         shr ecx, 1
-@@lp:    and dword ptr es:[edi], eax
-         add edi, 4
-         dec ecx
-         jnz @@lp
-         test edx, 1
-         jz @@done
-         and word ptr es:[edi], ax
-@@done:  pop es
-         pop edi
-      end;
+      mov edx, ecx
+      shr ecx, 1
+@@lp: and dword ptr es:[edi], eax
+      add edi, 4
+      dec ecx
+      jnz @@lp
+      test edx, 1
+      jz @@done
+      and word ptr es:[edi], ax
+@@done:
+      pop es
+      pop edi
     end;
     end;
 
 
 {************************************************************************}
 {************************************************************************}
@@ -671,9 +683,7 @@ var
 
 
 procedure SetCGAPalette(CGAPaletteID: Byte); assembler;
 procedure SetCGAPalette(CGAPaletteID: Byte); assembler;
 asm
 asm
-{$IFNDEF REGCALL}
-  mov ax,val_ax
-{$ENDIF REGCALL}
+  {# Var CGAPaletteID located in register al }
   push ebp
   push ebp
   push esi
   push esi
   push edi
   push edi
@@ -690,9 +700,7 @@ end;
 
 
 procedure SetCGABorder(CGABorder: Byte); assembler;
 procedure SetCGABorder(CGABorder: Byte); assembler;
 asm
 asm
-{$IFNDEF REGCALL}
-  mov ax,val_ax
-{$ENDIF REGCALL}
+  {# Var CGABorder located in register al }
   push ebp
   push ebp
   push esi
   push esi
   push edi
   push edi
@@ -722,10 +730,7 @@ end;
 
 
 procedure InitCGA320C0;
 procedure InitCGA320C0;
 begin
 begin
-  if DontClearGraphMemory then
-    CallInt10($84)
-  else
-    CallInt10($04);
+  InitInt10hMode($04);
   VideoOfs := 0;
   VideoOfs := 0;
   SetCGAPalette(0);
   SetCGAPalette(0);
   SetCGABorder(16);
   SetCGABorder(16);
@@ -734,10 +739,7 @@ end;
 
 
 procedure InitCGA320C1;
 procedure InitCGA320C1;
 begin
 begin
-  if DontClearGraphMemory then
-    CallInt10($84)
-  else
-    CallInt10($04);
+  InitInt10hMode($04);
   VideoOfs := 0;
   VideoOfs := 0;
   SetCGAPalette(1);
   SetCGAPalette(1);
   SetCGABorder(16);
   SetCGABorder(16);
@@ -746,10 +748,7 @@ end;
 
 
 procedure InitCGA320C2;
 procedure InitCGA320C2;
 begin
 begin
-  if DontClearGraphMemory then
-    CallInt10($84)
-  else
-    CallInt10($04);
+  InitInt10hMode($04);
   VideoOfs := 0;
   VideoOfs := 0;
   SetCGAPalette(2);
   SetCGAPalette(2);
   SetCGABorder(0);
   SetCGABorder(0);
@@ -758,10 +757,7 @@ end;
 
 
 procedure InitCGA320C3;
 procedure InitCGA320C3;
 begin
 begin
-  if DontClearGraphMemory then
-    CallInt10($84)
-  else
-    CallInt10($04);
+  InitInt10hMode($04);
   VideoOfs := 0;
   VideoOfs := 0;
   SetCGAPalette(3);
   SetCGAPalette(3);
   SetCGABorder(0);
   SetCGABorder(0);
@@ -1054,10 +1050,7 @@ end;
 
 
 procedure InitCGA640;
 procedure InitCGA640;
 begin
 begin
-  if DontClearGraphMemory then
-    CallInt10($86)
-  else
-    CallInt10($06);
+  InitInt10hMode($06);
   VideoOfs := 0;
   VideoOfs := 0;
   CurrentCGABorder := 0; {yes, TP7 CGA.BGI behaves *exactly* like that}
   CurrentCGABorder := 0; {yes, TP7 CGA.BGI behaves *exactly* like that}
 end;
 end;
@@ -1365,10 +1358,7 @@ end;
 
 
 procedure InitMCGA640;
 procedure InitMCGA640;
 begin
 begin
-  if DontClearGraphMemory then
-    CallInt10($91)
-  else
-    CallInt10($11);
+  InitInt10hMode($11);
   VideoOfs := 0;
   VideoOfs := 0;
   CurrentCGABorder := 0; {yes, TP7 CGA.BGI behaves *exactly* like that}
   CurrentCGABorder := 0; {yes, TP7 CGA.BGI behaves *exactly* like that}
 end;
 end;
@@ -1664,20 +1654,14 @@ end;
 
 
   Procedure Init640x200x16;
   Procedure Init640x200x16;
     begin
     begin
-      if DontClearGraphMemory then
-        CallInt10($8e)
-      else
-        CallInt10($e);
+      InitInt10hMode($e);
       VideoOfs := 0;
       VideoOfs := 0;
     end;
     end;
 
 
 
 
    Procedure Init640x350x16;
    Procedure Init640x350x16;
     begin
     begin
-      if DontClearGraphMemory then
-        CallInt10($90)
-      else
-        CallInt10($10);
+      InitInt10hMode($10);
       VideoOfs := 0;
       VideoOfs := 0;
     end;
     end;
 
 
@@ -1685,21 +1669,17 @@ end;
 
 
   Procedure Init640x480x16;
   Procedure Init640x480x16;
     begin
     begin
-      if DontClearGraphMemory then
-        CallInt10($92)
-      else
-        CallInt10($12);
+      InitInt10hMode($12);
       VideoOfs := 0;
       VideoOfs := 0;
     end;
     end;
 
 
 
 
 
 
 
 
- Procedure PutPixel16(X,Y : smallint; Pixel: Word);
 {$ifndef asmgraph}
 {$ifndef asmgraph}
+ Procedure PutPixel16(X,Y : smallint; Pixel: Word);
  var offset: word;
  var offset: word;
      dummy: byte;
      dummy: byte;
-{$endif asmgraph}
   Begin
   Begin
     X:= X + StartXViewPort;
     X:= X + StartXViewPort;
     Y:= Y + StartYViewPort;
     Y:= Y + StartYViewPort;
@@ -1711,7 +1691,6 @@ end;
        if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
        if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
          exit;
          exit;
      end;
      end;
-{$ifndef asmgraph}
      offset := y * 80 + (x shr 3) + VideoOfs;
      offset := y * 80 + (x shr 3) + VideoOfs;
      PortW[$3ce] := $0f01;       { Index 01 : Enable ops on all 4 planes }
      PortW[$3ce] := $0f01;       { Index 01 : Enable ops on all 4 planes }
      PortW[$3ce] := (Pixel and $ff) shl 8; { Index 00 : Enable correct plane and write color }
      PortW[$3ce] := (Pixel and $ff) shl 8; { Index 00 : Enable correct plane and write color }
@@ -1721,7 +1700,20 @@ end;
      Mem[Sega000: offset] := dummy;  { Write the data into video memory }
      Mem[Sega000: offset] := dummy;  { Write the data into video memory }
      PortW[$3ce] := $ff08;         { Enable all bit planes.           }
      PortW[$3ce] := $ff08;         { Enable all bit planes.           }
      PortW[$3ce] := $0001;         { Index 01 : Disable ops on all four planes.         }
      PortW[$3ce] := $0001;         { Index 01 : Disable ops on all four planes.         }
+   end;
 {$else asmgraph}
 {$else asmgraph}
+ Procedure PutPixel16(X,Y : smallint; Pixel: Word);
+  Begin
+    X:= X + StartXViewPort;
+    Y:= Y + StartYViewPort;
+    { convert to absolute coordinates and then verify clipping...}
+    if ClipPixels then
+     Begin
+       if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
+         exit;
+       if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
+         exit;
+     end;
       asm
       asm
         push eax
         push eax
         push ebx
         push ebx
@@ -1776,19 +1768,17 @@ end;
         pop ebx
         pop ebx
         pop eax
         pop eax
       end;
       end;
-{$endif asmgraph}
    end;
    end;
+{$endif asmgraph}
 
 
 
 
- Function GetPixel16(X,Y: smallint):word;
 {$ifndef asmgraph}
 {$ifndef asmgraph}
+ Function GetPixel16(X,Y: smallint):word;
  Var dummy, offset: Word;
  Var dummy, offset: Word;
      shift: byte;
      shift: byte;
-{$endif asmgraph}
   Begin
   Begin
     X:= X + StartXViewPort;
     X:= X + StartXViewPort;
     Y:= Y + StartYViewPort;
     Y:= Y + StartYViewPort;
-{$ifndef asmgraph}
     offset := Y * 80 + (x shr 3) + VideoOfs;
     offset := Y * 80 + (x shr 3) + VideoOfs;
     PortW[$3ce] := $0004;
     PortW[$3ce] := $0004;
     shift := 7 - (X and 7);
     shift := 7 - (X and 7);
@@ -1800,7 +1790,12 @@ end;
     Port[$3cf] := 3;
     Port[$3cf] := 3;
     dummy := dummy or (((Mem[Sega000:offset] shr shift) and 1) shl 3);
     dummy := dummy or (((Mem[Sega000:offset] shr shift) and 1) shl 3);
     GetPixel16 := dummy;
     GetPixel16 := dummy;
+  end;
 {$else asmgraph}
 {$else asmgraph}
+ Function GetPixel16(X,Y: smallint):word;
+  Begin
+    X:= X + StartXViewPort;
+    Y:= Y + StartYViewPort;
     asm
     asm
       push eax
       push eax
       push ebx
       push ebx
@@ -1876,8 +1871,8 @@ end;
       pop ebx
       pop ebx
       pop eax
       pop eax
     end;
     end;
-{$endif asmgraph}
   end;
   end;
+{$endif asmgraph}
 
 
 Procedure GetScanLine16(x1, x2, y: smallint; var data);
 Procedure GetScanLine16(x1, x2, y: smallint; var data);
 
 
@@ -2006,14 +2001,13 @@ Begin
 {$Endif logging}
 {$Endif logging}
 End;
 End;
 
 
+{$ifndef asmgraph}
  Procedure DirectPutPixel16(X,Y : smallint);
  Procedure DirectPutPixel16(X,Y : smallint);
  { x,y -> must be in global coordinates. No clipping. }
  { x,y -> must be in global coordinates. No clipping. }
   var
   var
    color: word;
    color: word;
-{$ifndef asmgraph}
   offset: word;
   offset: word;
   dummy: byte;
   dummy: byte;
-{$endif asmgraph}
  begin
  begin
     If CurrentWriteMode <> NotPut Then
     If CurrentWriteMode <> NotPut Then
       Color := CurrentColor
       Color := CurrentColor
@@ -2032,7 +2026,6 @@ End;
        else
        else
          PortW[$3ce]:=$0003}
          PortW[$3ce]:=$0003}
     end;
     end;
-{$ifndef asmgraph}
     offset := Y * 80 + (X shr 3) + VideoOfs;
     offset := Y * 80 + (X shr 3) + VideoOfs;
     PortW[$3ce] := $f01;
     PortW[$3ce] := $f01;
     PortW[$3ce] := Color shl 8;
     PortW[$3ce] := Color shl 8;
@@ -2045,7 +2038,30 @@ End;
        (CurrentWriteMode = ANDPut) or
        (CurrentWriteMode = ANDPut) or
        (CurrentWriteMode = ORPut) then
        (CurrentWriteMode = ORPut) then
       PortW[$3ce] := $0003;
       PortW[$3ce] := $0003;
+ end;
 {$else asmgraph}
 {$else asmgraph}
+ Procedure DirectPutPixel16(X,Y : smallint);
+ { x,y -> must be in global coordinates. No clipping. }
+  var
+   color: word;
+ begin
+    If CurrentWriteMode <> NotPut Then
+      Color := CurrentColor
+    else Color := not CurrentColor;
+
+    case CurrentWriteMode of
+       XORPut:
+         PortW[$3ce]:=((3 shl 3) shl 8) or 3;
+       ANDPut:
+         PortW[$3ce]:=((1 shl 3) shl 8) or 3;
+       ORPut:
+         PortW[$3ce]:=((2 shl 3) shl 8) or 3;
+       {not needed, this is the default state (e.g. PutPixel16 requires it)}
+       {NormalPut, NotPut:
+         PortW[$3ce]:=$0003
+       else
+         PortW[$3ce]:=$0003}
+    end;
 { note: still needs xor/or/and/notput support !!!!! (JM) }
 { note: still needs xor/or/and/notput support !!!!! (JM) }
     asm
     asm
       push eax
       push eax
@@ -2101,8 +2117,8 @@ End;
       pop ebx
       pop ebx
       pop eax
       pop eax
     end;
     end;
-{$endif asmgraph}
  end;
  end;
+{$endif asmgraph}
 
 
 
 
   procedure HLine16(x,x2,y: smallint);
   procedure HLine16(x,x2,y: smallint);
@@ -2172,11 +2188,7 @@ End;
          if HLength>0 then
          if HLength>0 then
            begin
            begin
               Port[$3cf]:=$ff;
               Port[$3cf]:=$ff;
-{$ifndef tp}
               seg_bytemove(dosmemselector,$a0000+ScrOfs,dosmemselector,$a0000+ScrOfs,HLength);
               seg_bytemove(dosmemselector,$a0000+ScrOfs,dosmemselector,$a0000+ScrOfs,HLength);
-{$else}
-              move(Ptr(SegA000,ScrOfs)^, Ptr(SegA000,ScrOfs)^, HLength);
-{$endif}
               ScrOfs:=ScrOfs+HLength;
               ScrOfs:=ScrOfs+HLength;
            end;
            end;
          Port[$3cf]:=RMask;
          Port[$3cf]:=RMask;
@@ -2254,78 +2266,32 @@ End;
   End;
   End;
 
 
 
 
- procedure SetVisual200(page: word);
-  { four page support... }
+ procedure SetVisual200_350(page: word);
   begin
   begin
     if page > HardwarePages then exit;
     if page > HardwarePages then exit;
     asm
     asm
-      mov ax,[page]    { only lower byte is supPorted. }
+      mov ax,[page]    { only lower byte is supported. }
       mov ah,05h
       mov ah,05h
-      push ebp
-      push esi
-      push edi
-      push ebx
       int 10h
       int 10h
-      pop ebx
-      pop edi
-      pop esi
-      pop ebp
-
-      { read start address }
-      mov dx,3d4h
-      mov al,0ch
-      out dx,al
-      inc dx
-      in  al,dx
-      mov ah,al
-      dec dx
-      mov al,0dh
-      out dx,al
-      in  al,dx
-    end ['EDX','EAX'];
+    end ['EAX','EBX','ECX','EDX','ESI','EDI','EBP'];
   end;
   end;
 
 
  procedure SetActive200(page: word);
  procedure SetActive200(page: word);
   { four page support... }
   { four page support... }
   begin
   begin
-    case page of
-     0 : VideoOfs := 0;
-     1 : VideoOfs := 16384;
-     2 : VideoOfs := 32768;
-     3 : VideoOfs := 49152;
+    if (page >= 0) and (page <= 3) then
+      VideoOfs := page shl 14
     else
     else
       VideoOfs := 0;
       VideoOfs := 0;
-    end;
-  end;
-
- procedure SetVisual350(page: word);
-  { one page supPort... }
-  begin
-    if page > HardwarePages then exit;
-    asm
-      mov ax,[page]    { only lower byte is supPorted. }
-      mov ah,05h
-      push ebp
-      push esi
-      push edi
-      push ebx
-      int 10h
-      pop ebx
-      pop edi
-      pop esi
-      pop ebp
-    end ['EAX'];
   end;
   end;
 
 
  procedure SetActive350(page: word);
  procedure SetActive350(page: word);
   { one page supPort... }
   { one page supPort... }
   begin
   begin
-    case page of
-     0 : VideoOfs := 0;
-     1 : VideoOfs := 32768;
+    if page = 1 then
+      VideoOfs := 32768
     else
     else
       VideoOfs := 0;
       VideoOfs := 0;
-    end;
   end;
   end;
 
 
 
 
@@ -2338,31 +2304,21 @@ End;
 
 
  Procedure Init320;
  Procedure Init320;
     begin
     begin
-      if DontClearGraphMemory then
-        CallInt10($93)
-      else
-        CallInt10($13);
-      VideoOfs := 0;
+      InitInt10hMode($13);
     end;
     end;
 
 
 
 
 
 
- Procedure PutPixel320(X,Y : smallint; Pixel: Word);
+ Procedure PutPixel320(X,Y : smallint; Pixel: Word); assembler;
  { x,y -> must be in local coordinates. Clipping if required. }
  { x,y -> must be in local coordinates. Clipping if required. }
-  assembler;
   asm
   asm
-      push eax
+      {# Var X located in register ax
+       # Var Y located in register dx
+       # Var Pixel located in register cx }
       push ebx
       push ebx
-      push ecx
       push edi
       push edi
-{$IFDEF REGCALL}
       movsx  edi, ax
       movsx  edi, ax
       movsx  ebx, dx
       movsx  ebx, dx
-      mov    al, cl
-{$ELSE REGCALL}
-      movsx  edi, x
-      movsx  ebx, y
-{$ENDIF REGCALL}
       cmp    clippixels, 0
       cmp    clippixels, 0
       je     @putpix320noclip
       je     @putpix320noclip
       test   edi, edi
       test   edi, edi
@@ -2374,62 +2330,45 @@ End;
       cmp    bx, ViewHeight
       cmp    bx, ViewHeight
       jg     @putpix320done
       jg     @putpix320done
 @putpix320noclip:
 @putpix320noclip:
-      movsx  ecx, StartYViewPort
+      movsx  eax, StartYViewPort
       movsx  edx, StartXViewPort
       movsx  edx, StartXViewPort
-      add    ebx, ecx
+      add    ebx, eax
       add    edi, edx
       add    edi, edx
-{    add    edi, [VideoOfs]      no multiple pages in 320*200*256 }
-{$IFNDEF REGCALL}
-      mov    ax, [pixel]
-{$ENDIF REGCALL}
       shl    ebx, 6
       shl    ebx, 6
       add    edi, ebx
       add    edi, ebx
-      mov    fs:[edi+ebx*4+$a0000], al
+      mov    fs:[edi+ebx*4+$a0000], cl
 @putpix320done:
 @putpix320done:
       pop edi
       pop edi
-      pop ecx
       pop ebx
       pop ebx
-      pop eax
  end;
  end;
 
 
 
 
- Function GetPixel320(X,Y: smallint):word;
-  assembler;
+ Function GetPixel320(X,Y: smallint):word; assembler;
   asm
   asm
+    {# Var X located in register ax
+     # Var Y located in register dx }
     push ebx
     push ebx
-    push ecx
-    push edx
-    push edi
-{$IFDEF REGCALL}
-    movsx  edi, ax
+    movsx  eax, ax
     movsx  ebx, dx
     movsx  ebx, dx
-{$ELSE REGCALL}
-    movsx  edi, x
-    movsx  ebx, y
-{$ENDIF REGCALL}
     movsx  ecx, StartYViewPort
     movsx  ecx, StartYViewPort
     movsx  edx, StartXViewPort
     movsx  edx, StartXViewPort
     add    ebx, ecx
     add    ebx, ecx
-    add    edi, edx
- {   add    edi, [VideoOfs]       no multiple pages in 320*200*256 }
+    add    eax, edx
     shl    ebx, 6
     shl    ebx, 6
-    add    edi, ebx
-    movzx  eax, byte ptr fs:[edi+ebx*4+$a0000]
-    pop edi
-    pop edx
-    pop ecx
+    add    eax, ebx
+    movzx  eax, byte ptr fs:[eax+ebx*4+$a0000]
     pop ebx
     pop ebx
   end;
   end;
 
 
 
 
+{$ifndef asmgraph}
  Procedure DirectPutPixel320(X,Y : smallint);
  Procedure DirectPutPixel320(X,Y : smallint);
  { x,y -> must be in global coordinates. No clipping. }
  { x,y -> must be in global coordinates. No clipping. }
-{$ifndef asmgraph}
  var offset: word;
  var offset: word;
      dummy: Byte;
      dummy: Byte;
  begin
  begin
    dummy := CurrentColor;
    dummy := CurrentColor;
-   offset := y * 320 + x + VideoOfs;
+   offset := y * 320 + x;
    case CurrentWriteMode of
    case CurrentWriteMode of
      XorPut: dummy := dummy xor Mem[Sega000:offset];
      XorPut: dummy := dummy xor Mem[Sega000:offset];
      OrPut: dummy := dummy or Mem[Sega000:offset];
      OrPut: dummy := dummy or Mem[Sega000:offset];
@@ -2439,8 +2378,9 @@ End;
    Mem[SegA000:offset] := dummy;
    Mem[SegA000:offset] := dummy;
  end;
  end;
 {$else asmgraph}
 {$else asmgraph}
+ Procedure DirectPutPixel320(X,Y : smallint); assembler;
+ { x,y -> must be in global coordinates. No clipping. }
 { note: still needs or/and/notput support !!!!! (JM) }
 { note: still needs or/and/notput support !!!!! (JM) }
-  assembler;
     asm
     asm
       push eax
       push eax
       push ebx
       push ebx
@@ -2452,7 +2392,6 @@ End;
       movzx  edi, x
       movzx  edi, x
       movzx  ebx, y
       movzx  ebx, y
 {$ENDIF REGCALL}
 {$ENDIF REGCALL}
-   {   add    edi, [VideoOfs]       no multiple pages in 320*200*256 }
       shl    ebx, 6
       shl    ebx, 6
       add    edi, ebx
       add    edi, ebx
       mov    ax, [CurrentColor]
       mov    ax, [CurrentColor]
@@ -2471,19 +2410,19 @@ End;
  procedure SetVisual320(page: word);
  procedure SetVisual320(page: word);
   { no page supPort... }
   { no page supPort... }
   begin
   begin
-    VideoOfs := 0;
   end;
   end;
 
 
  procedure SetActive320(page: word);
  procedure SetActive320(page: word);
   { no page supPort... }
   { no page supPort... }
   begin
   begin
-    VideoOfs := 0;
   end;
   end;
 
 
  {************************************************************************}
  {************************************************************************}
  {*                       Mode-X related routines                        *}
  {*                       Mode-X related routines                        *}
  {************************************************************************}
  {************************************************************************}
-const CrtAddress: word = 0;
+const
+  CrtAddress: word = 0;
+  ModeXVideoPageStart: array [0..3] of longint = (0,16000,32000,48000);
 
 
  procedure InitModeX;
  procedure InitModeX;
   begin
   begin
@@ -2560,18 +2499,21 @@ const CrtAddress: word = 0;
  end;
  end;
 
 
 
 
- Function GetPixelX(X,Y: smallint): word;
 {$ifndef asmgraph}
 {$ifndef asmgraph}
+ Function GetPixelX(X,Y: smallint): word;
  var offset: word;
  var offset: word;
-{$endif asmgraph}
   begin
   begin
      X:= X + StartXViewPort;
      X:= X + StartXViewPort;
      Y:= Y + StartYViewPort;
      Y:= Y + StartYViewPort;
-{$ifndef asmgraph}
      offset := y * 80 + x shr 2 + VideoOfs;
      offset := y * 80 + x shr 2 + VideoOfs;
      PortW[$3ce] := ((x and 3) shl 8) + 4;
      PortW[$3ce] := ((x and 3) shl 8) + 4;
      GetPixelX := Mem[SegA000:offset];
      GetPixelX := Mem[SegA000:offset];
+ end;
 {$else asmgraph}
 {$else asmgraph}
+ Function GetPixelX(X,Y: smallint): word;
+  begin
+     X:= X + StartXViewPort;
+     Y:= Y + StartYViewPort;
     asm
     asm
      push eax
      push eax
      push ebx
      push ebx
@@ -2606,11 +2548,11 @@ const CrtAddress: word = 0;
     pop ebx
     pop ebx
     pop eax
     pop eax
    end;
    end;
-{$endif asmgraph}
  end;
  end;
+{$endif asmgraph}
 
 
  procedure SetVisualX(page: word);
  procedure SetVisualX(page: word);
-  { 4 page supPort... }
+  { 4 page support... }
 
 
    Procedure SetVisibleStart(AOffset: word); Assembler;
    Procedure SetVisibleStart(AOffset: word); Assembler;
    (* Select where the left corner of the screen will be *)
    (* Select where the left corner of the screen will be *)
@@ -2663,33 +2605,24 @@ const CrtAddress: word = 0;
 {$undef asmgraph}
 {$undef asmgraph}
 
 
   begin
   begin
-    Case page of
-      0: SetVisibleStart(0);
-      1: SetVisibleStart(16000);
-      2: SetVisibleStart(32000);
-      3: SetVisibleStart(48000);
+    if (page >= 0) and (page <= 3) then
+      SetVisibleStart(ModeXVideoPageStart[page])
     else
     else
       SetVisibleStart(0);
       SetVisibleStart(0);
-    end;
   end;
   end;
 
 
  procedure SetActiveX(page: word);
  procedure SetActiveX(page: word);
-  { 4 page supPort... }
+  { 4 page support... }
   begin
   begin
-   case page of
-     0: VideoOfs := 0;
-     1: VideoOfs := 16000;
-     2: VideoOfs := 32000;
-     3: VideoOfs := 48000;
-   else
-     VideoOfs:=0;
-   end;
+    if (page >= 0) and (page <= 3) then
+      VideoOfs := ModeXVideoPageStart[page]
+    else
+      VideoOfs := 0;
   end;
   end;
 
 
- Procedure PutPixelX(X,Y: smallint; color:word);
 {$ifndef asmgraph}
 {$ifndef asmgraph}
+ Procedure PutPixelX(X,Y: smallint; color:word);
  var offset: word;
  var offset: word;
-{$endif asmgraph}
   begin
   begin
     X:= X + StartXViewPort;
     X:= X + StartXViewPort;
     Y:= Y + StartYViewPort;
     Y:= Y + StartYViewPort;
@@ -2701,11 +2634,23 @@ const CrtAddress: word = 0;
        if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
        if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
          exit;
          exit;
      end;
      end;
-{$ifndef asmgraph}
     offset := y * 80 + x shr 2 + VideoOfs;
     offset := y * 80 + x shr 2 + VideoOfs;
     PortW[$3c4] := (hi(word(FirstPlane)) shl 8) shl (x and 3)+ lo(word(FirstPlane));
     PortW[$3c4] := (hi(word(FirstPlane)) shl 8) shl (x and 3)+ lo(word(FirstPlane));
     Mem[SegA000:offset] := color;
     Mem[SegA000:offset] := color;
+  end;
 {$else asmgraph}
 {$else asmgraph}
+ Procedure PutPixelX(X,Y: smallint; color:word);
+  begin
+    X:= X + StartXViewPort;
+    Y:= Y + StartYViewPort;
+    { convert to absolute coordinates and then verify clipping...}
+    if ClipPixels then
+     Begin
+       if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
+         exit;
+       if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
+         exit;
+     end;
      asm
      asm
       push ax
       push ax
       push bx
       push bx
@@ -2748,13 +2693,13 @@ const CrtAddress: word = 0;
       pop bx
       pop bx
       pop ax
       pop ax
     end;
     end;
-{$endif asmgraph}
   end;
   end;
+{$endif asmgraph}
 
 
 
 
+{$ifndef asmgraph}
  Procedure DirectPutPixelX(X,Y: smallint);
  Procedure DirectPutPixelX(X,Y: smallint);
  { x,y -> must be in global coordinates. No clipping. }
  { x,y -> must be in global coordinates. No clipping. }
-{$ifndef asmgraph}
  Var offset: Word;
  Var offset: Word;
      dummy: Byte;
      dummy: Byte;
  begin
  begin
@@ -2782,8 +2727,9 @@ const CrtAddress: word = 0;
    Mem[Sega000: offset] := Dummy;
    Mem[Sega000: offset] := Dummy;
  end;
  end;
 {$else asmgraph}
 {$else asmgraph}
+ Procedure DirectPutPixelX(X,Y: smallint); Assembler;
+ { x,y -> must be in global coordinates. No clipping. }
 { note: still needs or/and/notput support !!!!! (JM) }
 { note: still needs or/and/notput support !!!!! (JM) }
- Assembler;
  asm
  asm
    push ax
    push ax
    push bx
    push bx
@@ -3607,7 +3553,7 @@ const CrtAddress: word = 0;
          mode.MaxX := 639;
          mode.MaxX := 639;
          mode.MaxY := 199;
          mode.MaxY := 199;
          mode.HardwarePages := 3;
          mode.HardwarePages := 3;
-         mode.SetVisualPage := @SetVisual200;
+         mode.SetVisualPage := @SetVisual200_350;
          mode.SetActivePage := @SetActive200;
          mode.SetActivePage := @SetActive200;
          mode.InitMode := @Init640x200x16;
          mode.InitMode := @Init640x200x16;
          mode.XAspect := 4500;
          mode.XAspect := 4500;
@@ -3622,7 +3568,7 @@ const CrtAddress: word = 0;
          mode.MaxX := 639;
          mode.MaxX := 639;
          mode.MaxY := 349;
          mode.MaxY := 349;
          mode.HardwarePages := 1;
          mode.HardwarePages := 1;
-         mode.SetVisualPage := @SetVisual350;
+         mode.SetVisualPage := @SetVisual200_350;
          mode.SetActivePage := @SetActive350;
          mode.SetActivePage := @SetActive350;
          mode.InitMode := @Init640x350x16;
          mode.InitMode := @Init640x350x16;
          mode.XAspect := 7750;
          mode.XAspect := 7750;
@@ -3780,7 +3726,7 @@ const CrtAddress: word = 0;
          mode.MaxX := 639;
          mode.MaxX := 639;
          mode.MaxY := 199;
          mode.MaxY := 199;
          mode.HardwarePages := 3;
          mode.HardwarePages := 3;
-         mode.SetVisualPage := @SetVisual200;
+         mode.SetVisualPage := @SetVisual200_350;
          mode.SetActivePage := @SetActive200;
          mode.SetActivePage := @SetActive200;
          mode.InitMode := @Init640x200x16;
          mode.InitMode := @Init640x200x16;
          mode.XAspect := 4500;
          mode.XAspect := 4500;
@@ -3795,7 +3741,7 @@ const CrtAddress: word = 0;
          mode.MaxX := 639;
          mode.MaxX := 639;
          mode.MaxY := 349;
          mode.MaxY := 349;
          mode.HardwarePages := 1;
          mode.HardwarePages := 1;
-         mode.SetVisualPage := @SetVisual350;
+         mode.SetVisualPage := @SetVisual200_350;
          mode.SetActivePage := @SetActive350;
          mode.SetActivePage := @SetActive350;
          mode.InitMode := @Init640x350x16;
          mode.InitMode := @Init640x350x16;
          mode.XAspect := 7750;
          mode.XAspect := 7750;

+ 33 - 35
packages/graph/src/inc/fills.inc

@@ -433,36 +433,45 @@ var
    Cont : Boolean;
    Cont : Boolean;
    BackupColor : ColorType;
    BackupColor : ColorType;
    x1, x2, prevy: smallint;
    x1, x2, prevy: smallint;
+   SBufferSize, DrawnListSize: SizeUInt;
   Begin
   Begin
-    GetMem(DrawnList,sizeof(PFloodLine)*((ViewHeight div YResDiv) + 1));
-    FillChar(DrawnList^,sizeof(PFloodLine)*((ViewHeight div YResDiv) + 1),0);
-    { init prevy }
-    prevy := 32767;
-    { Save current drawing color }
-    BackupColor := CurrentColor;
-    CurrentColor := FillSettings.Color;
+    If (x<0) Or (y<0) Or
+       (x>ViewWidth) Or (y>ViewHeight) then Exit;
+    DrawnListSize:=sizeof(PFloodLine)*((ViewHeight div YResDiv) + 1);
     { MaxX is based on zero index }
     { MaxX is based on zero index }
 {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR}
 {$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR}
     if MaxColor > 65536 then
     if MaxColor > 65536 then
-    begin
-      GetMem (s1,(ViewWidth+1)*4);  { A pixel color represents a word }
-      GetMem (s2,(ViewWidth+1)*4);  { A pixel color represents a word }
-      GetMem (s3,(ViewWidth+1)*4);  { A pixel color represents a word }
-    end
+      SBufferSize := (ViewWidth+1)*4   { A pixel color is represented by a longword }
     else
     else
 {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR}
 {$endif FPC_GRAPH_SUPPORTS_TRUECOLOR}
-    begin
-      GetMem (s1,(ViewWidth+1)*2);  { A pixel color represents a word }
-      GetMem (s2,(ViewWidth+1)*2);  { A pixel color represents a word }
-      GetMem (s3,(ViewWidth+1)*2);  { A pixel color represents a word }
-    end;
-    if (not assigned(s1)) or (not assigned(s2)) or (not assigned(s3)) then
+      SBufferSize := (ViewWidth+1)*2;  { A pixel color is represented by a word }
+    DrawnList:=nil;
+    s1:=nil;
+    s2:=nil;
+    s3:=nil;
+    GetMem(DrawnList,DrawnListSize);
+    GetMem (s1,SBufferSize);
+    GetMem (s2,SBufferSize);
+    GetMem (s3,SBufferSize);
+    if (not assigned(DrawnList)) or (not assigned(s1)) or (not assigned(s2)) or (not assigned(s3)) then
       begin
       begin
         _GraphResult := grNoFloodMem;
         _GraphResult := grNoFloodMem;
+        if assigned(s1) then
+          System.FreeMem (s1,SBufferSize);
+        if assigned(s2) then
+          System.FreeMem (s2,SBufferSize);
+        if assigned(s3) then
+          System.FreeMem (s3,SBufferSize);
+        if assigned(DrawnList) then
+          System.FreeMem(DrawnList,DrawnListSize);
         exit;
         exit;
       end;
       end;
-    If (x<0) Or (y<0) Or
-       (x>ViewWidth) Or (y>ViewHeight) then Exit;
+    FillChar(DrawnList^,DrawnListSize,0);
+    { init prevy }
+    prevy := 32767;
+    { Save current drawing color }
+    BackupColor := CurrentColor;
+    CurrentColor := FillSettings.Color;
     { Index of points to check  }
     { Index of points to check  }
     Buffer.WordIndex:=0;
     Buffer.WordIndex:=0;
     PushPoint (x,y);
     PushPoint (x,y);
@@ -591,22 +600,11 @@ var
        PatternLine (x1,x2,y);
        PatternLine (x1,x2,y);
      End; { end while }
      End; { end while }
 
 
-{$ifdef FPC_GRAPH_SUPPORTS_TRUECOLOR}
-    if MaxColor > 65536 then
-    begin
-      System.FreeMem (s1,(ViewWidth+1)*4);
-      System.FreeMem (s2,(ViewWidth+1)*4);
-      System.FreeMem (s3,(ViewWidth+1)*4);
-    end
-    else
-{$endif FPC_GRAPH_SUPPORTS_TRUECOLOR}
-    begin
-      System.FreeMem (s1,(ViewWidth+1)*2);
-      System.FreeMem (s2,(ViewWidth+1)*2);
-      System.FreeMem (s3,(ViewWidth+1)*2);
-    end;
+    System.FreeMem (s1,SBufferSize);
+    System.FreeMem (s2,SBufferSize);
+    System.FreeMem (s3,SBufferSize);
     CleanUpDrawnList;
     CleanUpDrawnList;
-    System.FreeMem(DrawnList,sizeof(PFloodLine)*((ViewHeight div YResDiv) + 1));
+    System.FreeMem(DrawnList,DrawnListSize);
     CurrentColor := BackUpColor;
     CurrentColor := BackUpColor;
   End;
   End;
 
 

+ 5 - 5
packages/graph/src/inc/graph.inc

@@ -1312,28 +1312,28 @@ end;
      Halt(1);
      Halt(1);
    end;
    end;
 
 
-  procedure DirectPutPixelDefault(X,Y: smallint);
+  procedure DirectPutPixelDefault(X,Y: smallint); noreturn;
    begin
    begin
      NotInGraphicsMode;
      NotInGraphicsMode;
    end;
    end;
 
 
-  function GetPixelDefault(X,Y: smallint): ColorType;
+  function GetPixelDefault(X,Y: smallint): ColorType; noreturn;
    begin
    begin
      NotInGraphicsMode;
      NotInGraphicsMode;
    end;
    end;
 
 
-  procedure PutPixelDefault(X,Y: smallint; Color: ColorType);
+  procedure PutPixelDefault(X,Y: smallint; Color: ColorType); noreturn;
    begin
    begin
      NotInGraphicsMode;
      NotInGraphicsMode;
    end;
    end;
 
 
-  procedure SetRGBPaletteDefault(ColorNum, RedValue, GreenValue, BlueValue: smallint);
+  procedure SetRGBPaletteDefault(ColorNum, RedValue, GreenValue, BlueValue: smallint); noreturn;
    begin
    begin
      NotInGraphicsMode;
      NotInGraphicsMode;
    end;
    end;
 
 
   procedure GetRGBPaletteDefault(ColorNum: smallint; var
   procedure GetRGBPaletteDefault(ColorNum: smallint; var
-            RedValue, GreenValue, BlueValue: smallint);
+            RedValue, GreenValue, BlueValue: smallint); noreturn;
    begin
    begin
      NotInGraphicsMode;
      NotInGraphicsMode;
    end;
    end;

Fichier diff supprimé car celui-ci est trop grand
+ 371 - 375
packages/graph/src/msdos/graph.pp


+ 1 - 1
packages/graph/src/ptcgraph/ptcgraph.pp

@@ -17,7 +17,7 @@
 unit ptcgraph;
 unit ptcgraph;
 
 
 {//$define logging}
 {//$define logging}
-{//$define FPC_GRAPH_SUPPORTS_TRUECOLOR}
+{$define FPC_GRAPH_SUPPORTS_TRUECOLOR}
 
 
 {******************************************************************************}
 {******************************************************************************}
                                     interface
                                     interface

+ 1 - 1
packages/ide/fpviews.pas

@@ -4256,7 +4256,7 @@ begin
   C^.Insert(NewStr(S));
   C^.Insert(NewStr(S));
 end;
 end;
 begin
 begin
-  R.Assign(0,0,58,14{$ifdef NODEBUG}-1{$endif});
+  R.Assign(0,0,58,14{$ifdef USE_GRAPH_SWITCH}+1{$endif});
   inherited Init(R, dialog_about);
   inherited Init(R, dialog_about);
   HelpCtx:=hcAbout;
   HelpCtx:=hcAbout;
   GetExtent(R); R.Grow(-3,-2);
   GetExtent(R); R.Grow(-3,-2);

+ 2 - 3
packages/ide/weditor.pas

@@ -5991,12 +5991,11 @@ begin
 end;
 end;
 
 
 procedure TCustomCodeEditor.GotoLine;
 procedure TCustomCodeEditor.GotoLine;
-var
-  GotoRec: TGotoLineDialogRec;
+const
+  GotoRec: TGotoLineDialogRec = (LineNo:'1';Lines:0);  {keep previous goto line number}
 begin
 begin
   with GotoRec do
   with GotoRec do
   begin
   begin
-    LineNo:='1';
     Lines:=GetLineCount;
     Lines:=GetLineCount;
     {Linecount can be 0, but in that case there still is a cursor blinking in top
     {Linecount can be 0, but in that case there still is a cursor blinking in top
      of the window, which will become line 1 as soon as sometype hits a key.}
      of the window, which will become line 1 as soon as sometype hits a key.}

Fichier diff supprimé car celui-ci est trop grand
+ 402 - 284
packages/pastojs/src/fppas2js.pp


+ 42 - 22
packages/pastojs/src/pas2jscompiler.pp

@@ -136,6 +136,7 @@ type
     // source map
     // source map
     coSourceMapCreate,
     coSourceMapCreate,
     coSourceMapInclude,
     coSourceMapInclude,
+    coSourceMapFilenamesAbsolute,
     coSourceMapXSSIHeader
     coSourceMapXSSIHeader
     );
     );
   TP2jsCompilerOptions = set of TP2jsCompilerOption;
   TP2jsCompilerOptions = set of TP2jsCompilerOption;
@@ -184,6 +185,7 @@ const
     'Keep not used declarations (WPO)',
     'Keep not used declarations (WPO)',
     'Create source map',
     'Create source map',
     'Include Pascal sources in source map',
     'Include Pascal sources in source map',
+    'Do not shorten filenames in source map',
     'Prepend XSSI protection )]} to source map'
     'Prepend XSSI protection )]} to source map'
     );
     );
 
 
@@ -505,6 +507,7 @@ type
     function GetSkipDefaultConfig: Boolean; inline;
     function GetSkipDefaultConfig: Boolean; inline;
     function GetSrcMapEnable: boolean;
     function GetSrcMapEnable: boolean;
     function GetSrcMapInclude: boolean;
     function GetSrcMapInclude: boolean;
+    function GetSrcMapFilenamesAbsolute: boolean;
     function GetSrcMapXSSIHeader: boolean;
     function GetSrcMapXSSIHeader: boolean;
     function GetTargetPlatform: TPasToJsPlatform;
     function GetTargetPlatform: TPasToJsPlatform;
     function GetTargetProcessor: TPasToJsProcessor;
     function GetTargetProcessor: TPasToJsProcessor;
@@ -532,6 +535,7 @@ type
     procedure SetSrcMapBaseDir(const AValue: string);
     procedure SetSrcMapBaseDir(const AValue: string);
     procedure SetSrcMapEnable(const AValue: boolean);
     procedure SetSrcMapEnable(const AValue: boolean);
     procedure SetSrcMapInclude(const AValue: boolean);
     procedure SetSrcMapInclude(const AValue: boolean);
+    procedure SetSrcMapFilenamesAbsolute(const AValue: boolean);
     procedure SetSrcMapXSSIHeader(const AValue: boolean);
     procedure SetSrcMapXSSIHeader(const AValue: boolean);
     procedure SetTargetPlatform(const AValue: TPasToJsPlatform);
     procedure SetTargetPlatform(const AValue: TPasToJsPlatform);
     procedure SetTargetProcessor(const AValue: TPasToJsProcessor);
     procedure SetTargetProcessor(const AValue: TPasToJsProcessor);
@@ -573,7 +577,7 @@ type
     // Command-line option handling
     // Command-line option handling
     procedure HandleOptionPCUFormat(aValue: String); virtual;
     procedure HandleOptionPCUFormat(aValue: String); virtual;
     function HandleOptionPaths(C: Char; aValue: String; FromCmdLine: Boolean): Boolean; virtual;
     function HandleOptionPaths(C: Char; aValue: String; FromCmdLine: Boolean): Boolean; virtual;
-    function HandleOptionJS(C: Char; aValue: String; Quick,FromCmdLine: Boolean): Boolean; virtual;
+    function HandleOptionJ(C: Char; aValue: String; Quick,FromCmdLine: Boolean): Boolean; virtual;
     procedure HandleOptionConfigFile(aPos: Integer; const aFileName: string); virtual;
     procedure HandleOptionConfigFile(aPos: Integer; const aFileName: string); virtual;
     procedure HandleOptionInfo(aValue: string);
     procedure HandleOptionInfo(aValue: string);
     // DoWriteJSFile: return false to use the default write function.
     // DoWriteJSFile: return false to use the default write function.
@@ -629,7 +633,7 @@ type
     function IsDefined(const aName: String): boolean;
     function IsDefined(const aName: String): boolean;
     procedure SetOption(Flag: TP2jsCompilerOption; Enable: boolean);
     procedure SetOption(Flag: TP2jsCompilerOption; Enable: boolean);
 
 
-    function GetUnitInfo(const UseUnitName, InFileName: String;
+    function GetUnitInfo(const UseUnitName, InFileName, ModuleDir: String;
       PCUSupport: TPCUSupport): TFindUnitInfo;
       PCUSupport: TPCUSupport): TFindUnitInfo;
     function FindFileWithUnitFilename(UnitFilename: string): TPas2jsCompilerFile;
     function FindFileWithUnitFilename(UnitFilename: string): TPas2jsCompilerFile;
     procedure LoadModuleFile(UnitFilename, UseUnitName: string;
     procedure LoadModuleFile(UnitFilename, UseUnitName: string;
@@ -659,6 +663,7 @@ type
     property SrcMapSourceRoot: string read FSrcMapSourceRoot write FSrcMapSourceRoot;
     property SrcMapSourceRoot: string read FSrcMapSourceRoot write FSrcMapSourceRoot;
     property SrcMapInclude: boolean read GetSrcMapInclude write SetSrcMapInclude;
     property SrcMapInclude: boolean read GetSrcMapInclude write SetSrcMapInclude;
     property SrcMapXSSIHeader: boolean read GetSrcMapXSSIHeader write SetSrcMapXSSIHeader;
     property SrcMapXSSIHeader: boolean read GetSrcMapXSSIHeader write SetSrcMapXSSIHeader;
+    property SrcMapFilenamesAbsolute: boolean read GetSrcMapFilenamesAbsolute write SetSrcMapFilenamesAbsolute;
     property ShowDebug: boolean read GetShowDebug write SetShowDebug;
     property ShowDebug: boolean read GetShowDebug write SetShowDebug;
     property ShowFullPaths: boolean read GetShowFullPaths write SetShowFullPaths;
     property ShowFullPaths: boolean read GetShowFullPaths write SetShowFullPaths;
     property ShowLogo: Boolean read GetShowLogo write SetShowLogo;
     property ShowLogo: Boolean read GetShowLogo write SetShowLogo;
@@ -683,9 +688,6 @@ type
     property PostProcessorSupport: TPas2JSPostProcessorSupport Read FPostProcessorSupport Write FPostProcessorSupport;
     property PostProcessorSupport: TPas2JSPostProcessorSupport Read FPostProcessorSupport Write FPostProcessorSupport;
   end;
   end;
 
 
-
-
-
 function GetCompiledDate: string;
 function GetCompiledDate: string;
 function GetCompiledVersion: string;
 function GetCompiledVersion: string;
 function GetCompiledTargetOS: string;
 function GetCompiledTargetOS: string;
@@ -1622,6 +1624,7 @@ var
   aFile: TPas2jsCompilerFile;
   aFile: TPas2jsCompilerFile;
   UnitInfo: TFindUnitInfo;
   UnitInfo: TFindUnitInfo;
   LoadInfo: TLoadUnitInfo;
   LoadInfo: TLoadUnitInfo;
+  ModuleDir: String;
 begin
 begin
   Result:=nil;
   Result:=nil;
   aFile:=Nil;
   aFile:=Nil;
@@ -1629,7 +1632,8 @@ begin
   if CompareText(ExtractFilenameOnly(UnitFilename),UseUnitname)=0 then
   if CompareText(ExtractFilenameOnly(UnitFilename),UseUnitname)=0 then
     Parser.RaiseParserError(nUnitCycle,[UseUnitname]);
     Parser.RaiseParserError(nUnitCycle,[UseUnitname]);
 
 
-  UnitInfo:=Compiler.GetUnitInfo(UseUnitName,InFileName,PCUSupport);
+  ModuleDir:=ExtractFilePath(PasFileName);
+  UnitInfo:=Compiler.GetUnitInfo(UseUnitName,InFileName,ModuleDir,PCUSupport);
   if UnitInfo.FileName<>'' then
   if UnitInfo.FileName<>'' then
     begin
     begin
     LoadInfo.UseFilename:=UnitInfo.FileName;
     LoadInfo.UseFilename:=UnitInfo.FileName;
@@ -1655,8 +1659,6 @@ begin
   // if Result=nil resolver will give a nice error position, so don't do it here
   // if Result=nil resolver will give a nice error position, so don't do it here
 end;
 end;
 
 
-
-
 { TPas2jsCompiler }
 { TPas2jsCompiler }
 
 
 procedure TPas2jsCompiler.SetFS(AValue: TPas2jsFS);
 procedure TPas2jsCompiler.SetFS(AValue: TPas2jsFS);
@@ -2009,7 +2011,8 @@ begin
       SrcMap.SourceContents[i]:=aFile.Source;
       SrcMap.SourceContents[i]:=aFile.Source;
     end;
     end;
     // translate local file name
     // translate local file name
-    if BaseDir<>'' then
+    MapFilename:=LocalFilename;
+    if (BaseDir<>'') and not SrcMapFilenamesAbsolute then
     begin
     begin
       if not FS.TryCreateRelativePath(LocalFilename,BaseDir,true,MapFilename) then
       if not FS.TryCreateRelativePath(LocalFilename,BaseDir,true,MapFilename) then
       begin
       begin
@@ -2024,12 +2027,14 @@ begin
         // the source is included, do not translate the filename
         // the source is included, do not translate the filename
         MapFilename:=LocalFilename;
         MapFilename:=LocalFilename;
       end;
       end;
-      {$IFNDEF Unix}
-      // use / as PathDelim
+    end;
+    {$IFNDEF Unix}
+    // use / as PathDelim
+    if PathDelim<>'/' then
       MapFilename:=StringReplace(MapFilename,PathDelim,'/',[rfReplaceAll]);
       MapFilename:=StringReplace(MapFilename,PathDelim,'/',[rfReplaceAll]);
-      {$ENDIF}
+    {$ENDIF}
+    if LocalFilename<>MapFilename then
       SrcMap.SourceTranslatedFiles[i]:=MapFilename;
       SrcMap.SourceTranslatedFiles[i]:=MapFilename;
-    end;
   end;
   end;
 end;
 end;
 
 
@@ -2483,6 +2488,11 @@ begin
   Result:=coSourceMapInclude in FOptions;
   Result:=coSourceMapInclude in FOptions;
 end;
 end;
 
 
+function TPas2jsCompiler.GetSrcMapFilenamesAbsolute: boolean;
+begin
+  Result:=coSourceMapFilenamesAbsolute in FOptions;
+end;
+
 function TPas2jsCompiler.GetSrcMapXSSIHeader: boolean;
 function TPas2jsCompiler.GetSrcMapXSSIHeader: boolean;
 begin
 begin
   Result:=coSourceMapXSSIHeader in FOptions;
   Result:=coSourceMapXSSIHeader in FOptions;
@@ -2588,6 +2598,11 @@ begin
   SetOption(coSourceMapInclude,AValue);
   SetOption(coSourceMapInclude,AValue);
 end;
 end;
 
 
+procedure TPas2jsCompiler.SetSrcMapFilenamesAbsolute(const AValue: boolean);
+begin
+  SetOption(coSourceMapFilenamesAbsolute,AValue);
+end;
+
 procedure TPas2jsCompiler.SetSrcMapXSSIHeader(const AValue: boolean);
 procedure TPas2jsCompiler.SetSrcMapXSSIHeader(const AValue: boolean);
 begin
 begin
   SetOption(coSourceMapXSSIHeader,AValue);
   SetOption(coSourceMapXSSIHeader,AValue);
@@ -3010,7 +3025,7 @@ begin
 
 
 end;
 end;
 
 
-function TPas2jsCompiler.HandleOptionJS(C: Char; aValue: String;
+function TPas2jsCompiler.HandleOptionJ(C: Char; aValue: String;
   Quick, FromCmdLine: Boolean): Boolean;
   Quick, FromCmdLine: Boolean): Boolean;
 
 
 Var
 Var
@@ -3084,6 +3099,10 @@ begin
         SrcMapInclude:=true;
         SrcMapInclude:=true;
       'include-':
       'include-':
         SrcMapInclude:=false;
         SrcMapInclude:=false;
+      'absolute':
+        SrcMapFilenamesAbsolute:=true;
+      'absolute-':
+        SrcMapFilenamesAbsolute:=false;
       'xssiheader':
       'xssiheader':
         SrcMapXSSIHeader:=true;
         SrcMapXSSIHeader:=true;
       'xssiheader-':
       'xssiheader-':
@@ -3092,7 +3111,7 @@ begin
         begin
         begin
         i:=Pos('=',aValue);
         i:=Pos('=',aValue);
         if i<1 then
         if i<1 then
-          result:=false
+          ParamFatal('unknown -Jm parameter "'+aValue+'"')
         else
         else
           begin
           begin
           S:=LeftStr(aValue,i-1);
           S:=LeftStr(aValue,i-1);
@@ -3101,7 +3120,7 @@ begin
             'sourceroot': SrcMapSourceRoot:=aValue;
             'sourceroot': SrcMapSourceRoot:=aValue;
             'basedir': SrcMapBaseDir:=aValue;
             'basedir': SrcMapBaseDir:=aValue;
           else
           else
-            Result:=False;
+            ParamFatal('unknown -Jm parameter "'+s+'"')
           end;
           end;
           end;
           end;
         end;
         end;
@@ -3403,7 +3422,7 @@ begin
             UnknownParam;
             UnknownParam;
           c:=aValue[1];
           c:=aValue[1];
           Delete(aValue,1,1);
           Delete(aValue,1,1);
-          if not HandleOptionJS(c,aValue,Quick,FromCmdLine) then
+          if not HandleOptionJ(c,aValue,Quick,FromCmdLine) then
             UnknownParam;
             UnknownParam;
         end;
         end;
       'M': // syntax mode
       'M': // syntax mode
@@ -4214,8 +4233,9 @@ begin
   w('   -Jl   : lower case identifiers');
   w('   -Jl   : lower case identifiers');
   w('   -Jm   : generate source maps');
   w('   -Jm   : generate source maps');
   w('     -Jmsourceroot=<x>: use x as "sourceRoot", prefix URL for source file names.');
   w('     -Jmsourceroot=<x>: use x as "sourceRoot", prefix URL for source file names.');
-  w('     -Jmbasedir=<x>: write source file names relative to directory x.');
+  w('     -Jmbasedir=<x>: write source file names relative to directory x, default is map file folder.');
   w('     -Jminclude: include Pascal sources in source map.');
   w('     -Jminclude: include Pascal sources in source map.');
+  w('     -Jmabsolute: store absolute filenames, not relative.');
   w('     -Jmxssiheader: start source map with XSSI protection )]}'', default.');
   w('     -Jmxssiheader: start source map with XSSI protection )]}'', default.');
   w('     -Jm-: disable generating source maps');
   w('     -Jm-: disable generating source maps');
   w('   -Jo<x>: Enable or disable extra option. The x is case insensitive:');
   w('   -Jo<x>: Enable or disable extra option. The x is case insensitive:');
@@ -4637,8 +4657,8 @@ begin
   Result:=FMainJSFileResolved;
   Result:=FMainJSFileResolved;
 end;
 end;
 
 
-function TPas2jsCompiler.GetUnitInfo(const UseUnitName, InFileName: String;
-  PCUSupport: TPCUSupport): TFindUnitInfo;
+function TPas2jsCompiler.GetUnitInfo(const UseUnitName, InFileName,
+  ModuleDir: String; PCUSupport: TPCUSupport): TFindUnitInfo;
 
 
 var
 var
   FoundPasFilename, FoundPasUnitName: string;
   FoundPasFilename, FoundPasUnitName: string;
@@ -4667,7 +4687,7 @@ var
         end;
         end;
       end else begin
       end else begin
         // search pas in unit path
         // search pas in unit path
-        FoundPasFilename:=FS.FindUnitFileName(TestUnitName,'',FoundPasIsForeign);
+        FoundPasFilename:=FS.FindUnitFileName(TestUnitName,'',ModuleDir,FoundPasIsForeign);
         if FoundPasFilename<>'' then
         if FoundPasFilename<>'' then
           FoundPasUnitName:=TestUnitName;
           FoundPasUnitName:=TestUnitName;
       end;
       end;
@@ -4725,7 +4745,7 @@ begin
     end;
     end;
   end else begin
   end else begin
     // search Pascal file with InFilename
     // search Pascal file with InFilename
-    FoundPasFilename:=FS.FindUnitFileName(UseUnitname,InFilename,FoundPasIsForeign);
+    FoundPasFilename:=FS.FindUnitFileName(UseUnitname,InFilename,ModuleDir,FoundPasIsForeign);
     if FoundPasFilename='' then
     if FoundPasFilename='' then
       exit; // an in-filename unit source is missing -> stop
       exit; // an in-filename unit source is missing -> stop
     FoundPasUnitName:=ExtractFilenameOnly(InFilename);
     FoundPasUnitName:=ExtractFilenameOnly(InFilename);

+ 12 - 6
packages/pastojs/src/pas2jsfilecache.pp

@@ -256,7 +256,7 @@ type
     function SearchLowUpCase(var Filename: string): boolean;
     function SearchLowUpCase(var Filename: string): boolean;
     function FindCustomJSFileName(const aFilename: string): String; override;
     function FindCustomJSFileName(const aFilename: string): String; override;
     function FindUnitJSFileName(const aUnitFilename: string): String; override;
     function FindUnitJSFileName(const aUnitFilename: string): String; override;
-    function FindUnitFileName(const aUnitname, InFilename: string; out IsForeign: boolean): String; override;
+    function FindUnitFileName(const aUnitname, InFilename, ModuleDir: string; out IsForeign: boolean): String; override;
     function FindIncludeFileName(const aFilename: string): String; override;
     function FindIncludeFileName(const aFilename: string): String; override;
     function AddIncludePaths(const Paths: string; FromCmdLine: boolean; out ErrorMsg: string): boolean;
     function AddIncludePaths(const Paths: string; FromCmdLine: boolean; out ErrorMsg: string): boolean;
     function AddUnitPaths(const Paths: string; FromCmdLine: boolean; out ErrorMsg: string): boolean;
     function AddUnitPaths(const Paths: string; FromCmdLine: boolean; out ErrorMsg: string): boolean;
@@ -1805,10 +1805,11 @@ begin
   AddSrcUnitPaths(aValue,FromCmdLine,Result);
   AddSrcUnitPaths(aValue,FromCmdLine,Result);
 end;
 end;
 
 
-function TPas2jsFilesCache.TryCreateRelativePath(const Filename, BaseDirectory: String; UsePointDirectory: boolean; out
-  RelPath: String): Boolean;
+function TPas2jsFilesCache.TryCreateRelativePath(const Filename, BaseDirectory: String;
+  UsePointDirectory: boolean; out RelPath: String): Boolean;
 begin
 begin
-  Result:=Pas2jsFileUtils.TryCreateRelativePath(Filename, BaseDirectory, UsePointDirectory, RelPath);
+  Result:=Pas2jsFileUtils.TryCreateRelativePath(Filename, BaseDirectory,
+    UsePointDirectory, true, RelPath);
 end;
 end;
 
 
 function TPas2jsFilesCache.FindIncludeFileName(const aFilename: string): String;
 function TPas2jsFilesCache.FindIncludeFileName(const aFilename: string): String;
@@ -1888,7 +1889,8 @@ begin
 end;
 end;
 
 
 
 
-function TPas2jsFilesCache.FindUnitFileName(const aUnitname, InFilename: string; out IsForeign: boolean): String;
+function TPas2jsFilesCache.FindUnitFileName(const aUnitname, InFilename,
+  ModuleDir: string; out IsForeign: boolean): String;
 var
 var
   SearchedDirs: TStringList;
   SearchedDirs: TStringList;
 
 
@@ -1924,7 +1926,7 @@ begin
         if SearchLowUpCase(Result) then exit;
         if SearchLowUpCase(Result) then exit;
       end else
       end else
       begin
       begin
-        Result:=ResolveDots(BaseDirectory+Result);
+        Result:=ResolveDots(ModuleDir+Result);
         if SearchLowUpCase(Result) then exit;
         if SearchLowUpCase(Result) then exit;
       end;
       end;
       exit('');
       exit('');
@@ -1939,6 +1941,10 @@ begin
         exit;
         exit;
       end;
       end;
 
 
+    // then in ModuleDir
+    IsForeign:=false;
+    if SearchInDir(ModuleDir,Result) then exit;
+
     // then in BaseDirectory
     // then in BaseDirectory
     IsForeign:=false;
     IsForeign:=false;
     if SearchInDir(BaseDirectory,Result) then exit;
     if SearchInDir(BaseDirectory,Result) then exit;

+ 33 - 17
packages/pastojs/src/pas2jsfiler.pp

@@ -169,7 +169,8 @@ const
     'ExternalClass',
     'ExternalClass',
     'PrefixedAttributes',
     'PrefixedAttributes',
     'IgnoreAttributes',
     'IgnoreAttributes',
-    'OmitRTTI'
+    'OmitRTTI',
+    'MultipleScopeHelpers'
     );
     );
 
 
   PCUDefaultBoolSwitches: TBoolSwitches = [
   PCUDefaultBoolSwitches: TBoolSwitches = [
@@ -206,7 +207,8 @@ const
     'Macro',
     'Macro',
     'ScopedEnums',
     'ScopedEnums',
     'ObjectChecks',
     'ObjectChecks',
-    'PointerMath'
+    'PointerMath',
+    'Goto'
     );
     );
 
 
   PCUDefaultConverterOptions: TPasToJsConverterOptions = [coUseStrict];
   PCUDefaultConverterOptions: TPasToJsConverterOptions = [coUseStrict];
@@ -348,7 +350,6 @@ const
     'Object',
     'Object',
     'Class',
     'Class',
     'Interface',
     'Interface',
-    'Generic',
     'ClassHelper',
     'ClassHelper',
     'RecordHelper',
     'RecordHelper',
     'TypeHelper',
     'TypeHelper',
@@ -2636,6 +2637,9 @@ begin
   WriteIdentifierScope(Obj,Scope,aContext);
   WriteIdentifierScope(Obj,Scope,aContext);
 
 
   // not needed: Scope ElevatedLocals
   // not needed: Scope ElevatedLocals
+  // not needed: Scope Helpers
+  if (length(Scope.Helpers)>0) and not (Scope.Element is TInterfaceSection) then
+    RaiseMsg(20190119122007,Section);
 
 
   WriteDeclarations(Obj,Section,aContext);
   WriteDeclarations(Obj,Section,aContext);
   if Section is TInterfaceSection then
   if Section is TInterfaceSection then
@@ -3711,7 +3715,7 @@ begin
     RaiseMsg(20180219135933,Scope.Element);
     RaiseMsg(20180219135933,Scope.Element);
   AddReferenceToObj(Obj,'ImplProc',Scope.ImplProc);
   AddReferenceToObj(Obj,'ImplProc',Scope.ImplProc);
   AddReferenceToObj(Obj,'Overridden',Scope.OverriddenProc);
   AddReferenceToObj(Obj,'Overridden',Scope.OverriddenProc);
-  // ClassScope: TPasClassScope; auto derived
+  // ClassOrRecordScope: TPasClassScope; auto derived
   if Scope.SelfArg<>nil then
   if Scope.SelfArg<>nil then
     RaiseMsg(20180211180457,Scope.Element); // SelfArg only valid for method implementation
     RaiseMsg(20180211180457,Scope.Element); // SelfArg only valid for method implementation
   // Mode: TModeSwitch: auto derived
   // Mode: TModeSwitch: auto derived
@@ -3733,8 +3737,7 @@ begin
   WritePasElement(Obj,El,aContext);
   WritePasElement(Obj,El,aContext);
   Scope:=El.CustomData as TPas2JSProcedureScope;
   Scope:=El.CustomData as TPas2JSProcedureScope;
   //writeln('TPCUWriter.WriteProcedure ',GetObjName(El),' ',GetObjName(Scope),' ',Resolver.GetElementSourcePosStr(El));
   //writeln('TPCUWriter.WriteProcedure ',GetObjName(El),' ',GetObjName(Scope),' ',Resolver.GetElementSourcePosStr(El));
-  // BEWARE: Scope can be nil for ignored methods of an interface (msIgnoreInterfaces)
-  if (Scope=nil) or (Scope.DeclarationProc=nil) then
+  if Scope.DeclarationProc=nil then
     begin
     begin
     WriteElementProperty(Obj,El,'ProcType',El.ProcType,aContext);
     WriteElementProperty(Obj,El,'ProcType',El.ProcType,aContext);
     WriteExpr(Obj,El,'Public',El.PublicName,aContext);
     WriteExpr(Obj,El,'Public',El.PublicName,aContext);
@@ -3752,12 +3755,6 @@ begin
       if El.MessageType<>pmtInteger then
       if El.MessageType<>pmtInteger then
         Obj.Add('MessageType',PCUProcedureMessageTypeNames[El.MessageType]);
         Obj.Add('MessageType',PCUProcedureMessageTypeNames[El.MessageType]);
       end;
       end;
-
-    if Scope=nil then
-      begin
-      Obj.Add('Scope',false); // msIgnoreInterfaces
-      exit;
-      end;
     WriteProcedureScope(Obj,Scope,aContext);
     WriteProcedureScope(Obj,Scope,aContext);
     end
     end
   else
   else
@@ -5401,6 +5398,7 @@ procedure TPCUReader.ReadSectionScope(Obj: TJSONObject;
 begin
 begin
   ReadIdentifierScope(Obj,Scope,aContext);
   ReadIdentifierScope(Obj,Scope,aContext);
   // not needed: Scope ElevatedLocals
   // not needed: Scope ElevatedLocals
+  // not needed: Scope Helpers, autogenerated in ReadClassType
   Scope.BoolSwitches:=ReadBoolSwitches(Obj,Scope.Element,'BoolSwitches',aContext.BoolSwitches);
   Scope.BoolSwitches:=ReadBoolSwitches(Obj,Scope.Element,'BoolSwitches',aContext.BoolSwitches);
   Scope.ModeSwitches:=ReadModeSwitches(Obj,Scope.Element,'ModeSwitches',aContext.ModeSwitches);
   Scope.ModeSwitches:=ReadModeSwitches(Obj,Scope.Element,'ModeSwitches',aContext.ModeSwitches);
 end;
 end;
@@ -5696,7 +5694,6 @@ begin
     'Object': CreateClassType(okObject,Name);
     'Object': CreateClassType(okObject,Name);
     'Class': CreateClassType(okClass,Name);
     'Class': CreateClassType(okClass,Name);
     'Interface': CreateClassType(okInterface,Name);
     'Interface': CreateClassType(okInterface,Name);
-    'Generic': CreateClassType(okGeneric,Name);
     'ClassHelper': CreateClassType(okClassHelper,Name);
     'ClassHelper': CreateClassType(okClassHelper,Name);
     'RecordHelper': CreateClassType(okRecordHelper,Name);
     'RecordHelper': CreateClassType(okRecordHelper,Name);
     'TypeHelper': CreateClassType(okTypeHelper,Name);
     'TypeHelper': CreateClassType(okTypeHelper,Name);
@@ -6925,6 +6922,8 @@ var
   Data: TJSONData;
   Data: TJSONData;
   Scope: TPas2JSClassScope;
   Scope: TPas2JSClassScope;
   Ref: TResolvedReference;
   Ref: TResolvedReference;
+  Parent: TPasElement;
+  SectionScope: TPasSectionScope;
 begin
 begin
   ReadBoolean(Obj,'Forward',El.IsForward,El);
   ReadBoolean(Obj,'Forward',El.IsForward,El);
 
 
@@ -6986,6 +6985,22 @@ begin
     begin
     begin
     ReadClassScopeAbstractProcs(Obj,Scope);
     ReadClassScopeAbstractProcs(Obj,Scope);
     ReadClassScopeInterfaces(Obj,Scope);
     ReadClassScopeInterfaces(Obj,Scope);
+
+    if El.ObjKind in okAllHelpers then
+      begin
+      // restore cached helpers in interface
+      Parent:=El.Parent;
+      while Parent<>nil do
+        begin
+        if Parent.ClassType=TInterfaceSection then
+          begin
+          SectionScope:=Parent.CustomData as TPasSectionScope;
+          Resolver.AddHelper(El,SectionScope.Helpers);
+          break;
+          end;
+        Parent:=Parent.Parent;
+        end;
+      end;
     end;
     end;
 end;
 end;
 
 
@@ -7328,8 +7343,9 @@ begin
   ReadElementReference(Obj,Scope,'ImplProc',@Set_ProcedureScope_ImplProc);
   ReadElementReference(Obj,Scope,'ImplProc',@Set_ProcedureScope_ImplProc);
   ReadElementReference(Obj,Scope,'Overridden',@Set_ProcedureScope_Overridden);
   ReadElementReference(Obj,Scope,'Overridden',@Set_ProcedureScope_Overridden);
   if Proc.Parent is TPasMembersType then
   if Proc.Parent is TPasMembersType then
-    Scope.ClassOrRecordScope:=Proc.Parent.CustomData as TPasClassOrRecordScope; // no AddRef
-  // ClassScope: TPasClassScope; auto derived
+    Scope.ClassRecScope:=Proc.Parent.CustomData as TPasClassOrRecordScope // no AddRef
+  else
+    ; // set via Set_ProcedureScope_ImplProc
   // Scope.SelfArg only valid for method implementation
   // Scope.SelfArg only valid for method implementation
 
 
   Scope.Flags:=ReadProcScopeFlags(Obj,Proc,'SFlags',[]);
   Scope.Flags:=ReadProcScopeFlags(Obj,Proc,'SFlags',[]);
@@ -7346,8 +7362,8 @@ var
   DeclProc: TPasProcedure;
   DeclProc: TPasProcedure;
 begin
 begin
   // Note: the References are stored in the scope object of the declaration proc,
   // Note: the References are stored in the scope object of the declaration proc,
-  //       OTOH in the JSON they are stored in the scope of the implementation
-  //       proc, so that all references can be resolved immediately.
+  //       But TPCUWriter stores them in the implementation scope, so that all
+  //       references can be resolved immediately.
   if ImplScope.ImplProc<>nil then
   if ImplScope.ImplProc<>nil then
     RaiseMsg(20180318212631,ImplScope.Element);
     RaiseMsg(20180318212631,ImplScope.Element);
   DeclProc:=ImplScope.DeclarationProc;
   DeclProc:=ImplScope.DeclarationProc;

+ 197 - 87
packages/pastojs/src/pas2jsfileutils.pp

@@ -40,8 +40,15 @@ function FileIsInPath(const Filename, Path: string): boolean;
 function ChompPathDelim(const Path: string): string;
 function ChompPathDelim(const Path: string): string;
 function ExpandFileNamePJ(const FileName: string; {const} BaseDir: string = ''): string;
 function ExpandFileNamePJ(const FileName: string; {const} BaseDir: string = ''): string;
 function ExpandDirectory(const aDirectory: string): string;
 function ExpandDirectory(const aDirectory: string): string;
-function TryCreateRelativePath(const Filename, BaseDirectory: String;
-  UsePointDirectory: boolean; out RelPath: String): Boolean;
+function IsUNCPath(const {%H-}Path: String): Boolean;
+function ExtractUNCVolume(const {%H-}Path: String): String;
+function ExtractFileRoot(FileName: String): String;
+function TryCreateRelativePath(
+  const Dest: String; // Filename
+  const Source: String; // Directory
+  UsePointDirectory: boolean; // True = return '.' for the current directory instead of ''
+  AlwaysRequireSharedBaseFolder: Boolean;// true = only shorten if at least one shared folder
+  out RelPath: String): Boolean;
 function ResolveDots(const AFilename: string): string;
 function ResolveDots(const AFilename: string): string;
 procedure ForcePathDelims(Var FileName: string);
 procedure ForcePathDelims(Var FileName: string);
 function GetForcedPathDelims(Const FileName: string): String;
 function GetForcedPathDelims(Const FileName: string): String;
@@ -201,8 +208,47 @@ begin
   Result:=IncludeTrailingPathDelimiter(Result);
   Result:=IncludeTrailingPathDelimiter(Result);
 end;
 end;
 
 
-function TryCreateRelativePath(const Filename, BaseDirectory: String;
-  UsePointDirectory: boolean; out RelPath: String): Boolean;
+{
+  Returns
+  - DriveLetter + : + PathDelim on Windows (if present) or
+  - UNC Share on Windows if present or
+  - PathDelim if FileName starts with PathDelim on Unix or Wince or
+  - Empty string of non eof the above applies
+}
+function ExtractFileRoot(FileName: String): String;
+var
+  Len: Integer;
+begin
+  Result := '';
+  Len := Length(FileName);
+  if (Len > 0) then
+  begin
+    if IsUncPath(FileName) then
+    begin
+      Result := ExtractUNCVolume(FileName);
+      // is it like \\?\C:\Directory?  then also include the "C:\" part
+      if (Result = '\\?\') and (Length(FileName) > 6) and
+         (FileName[5] in ['a'..'z','A'..'Z']) and (FileName[6] = ':') and (FileName[7] in AllowDirectorySeparators)
+      then
+        Result := Copy(FileName, 1, 7);
+    end
+    else
+    begin
+      {$if defined(unix) or defined(wince)}
+      if (FileName[1] = PathDelim) then Result := PathDelim;
+      {$else}
+        {$ifdef HASAMIGA}
+        if Pos(':', FileName) > 1 then
+          Result := Copy(FileName, 1, Pos(':', FileName));
+        {$else}
+        if (Len > 2) and (FileName[1] in ['a'..'z','A'..'Z']) and (FileName[2] = ':') and (FileName[3] in AllowDirectorySeparators) then
+          Result := UpperCase(Copy(FileName,1,3));
+        {$endif}
+      {$endif}
+    end;
+  end;
+end;
+
 {
 {
   Returns True if it is possible to create a relative path from Source to Dest
   Returns True if it is possible to create a relative path from Source to Dest
   Function must be thread safe, so no expanding of filenames is done, since this
   Function must be thread safe, so no expanding of filenames is done, since this
@@ -221,104 +267,168 @@ function TryCreateRelativePath(const Filename, BaseDirectory: String;
     no PathDelimiter is appended to the end of RelPath
     no PathDelimiter is appended to the end of RelPath
 
 
   Examples:
   Examples:
-  - Filename = /foo/bar BaseDirectory = /foo Result = True RelPath = bar
-  - Filename = /foo///bar BaseDirectory = /foo// Result = True RelPath = bar
-  - Filename = /foo BaseDirectory = /foo/bar Result = True RelPath = ../
-  - Filename = /foo/bar BaseDirectory = /bar Result = False (no shared base directory)
-  - Filename = foo/bar BaseDirectory = foo/foo Result = True RelPath = ../bar
-  - Filename = foo/bar BaseDirectory = bar/foo Result = False (no shared base directory)
-  - Filename = /foo BaseDirectory = bar Result = False (mixed absolute and relative)
+  - Dest = /foo/bar Source = /foo Result = True RelPath = bar
+  - Dest = /foo///bar Source = /foo// Result = True RelPath = bar
+  - Dest = /foo Source = /foo/bar Result = True RelPath = ../
+  - Dest = /foo/bar Source = /bar Result = True RelPath = ../foo/bar
+  - Dest = foo/bar Source = foo/foo Result = True RelPath = ../bar
+  - Dest = foo/bar Source = bar/foo Result = False (no shared base directory)
+  - Dest = /foo Source = bar Result = False (mixed absolute and relative)
+  - Dest = c:foo Source = c:bar Result = False (no expanding)
+  - Dest = c:\foo Source = d:\bar Result is False (different drives)
+  - Dest = \foo Source = foo (Windows) Result is False (too ambiguous to guess what this should mean)
+  - Dest = /foo Source = /bar AlwaysRequireSharedBaseFolder = True Result = False
+  - Dest = /foo Source = /bar AlwaysRequireSharedBaseFolder = False Result = True RelPath = ../foo
 }
 }
-  function IsNameChar(c: char): boolean; inline;
+function TryCreateRelativePath(const Dest: String; const Source: String;
+  UsePointDirectory: boolean; AlwaysRequireSharedBaseFolder: Boolean; out
+  RelPath: String): Boolean;
+Type
+  TDirArr =  TStringArray;
+
+  function SplitDirs(Dir: String; out Dirs: TDirArr): integer;
+  var
+    Start, Stop, Len: Integer;
+    S: String;
   begin
   begin
-    Result:=(c<>#0) and not (c in AllowDirectorySeparators);
+    Result := 0;
+    Len := Length(Dir);
+    Dirs:=nil;
+    if (Len = 0) then Exit;
+    Start := 1;
+    Stop := 1;
+
+    While Start <= Len do
+    begin
+      if (Dir[Start] in AllowDirectorySeparators) then
+      begin
+        S := Copy(Dir,Stop,Start-Stop);
+        //ignore empty strings, they are caused by double PathDelims, which we just ignore
+        if (S <> '') then
+        begin
+          Inc(Result);
+          if Result>length(Dirs) then
+            SetLength(Dirs,length(Dirs)*2+10);
+          Dirs[Result-1] := S;
+        end;
+        Stop := Start + 1;
+      end;
+      Inc(Start);
+    end;
+
+    S := Copy(Dir,Stop,Start-Stop);
+    if (S <> '') then
+    begin
+      Inc(Result);
+      if Result>length(Dirs) then
+        SetLength(Dirs,length(Dirs)*2+10);
+      Dirs[Result-1] := S;
+    end;
   end;
   end;
 
 
 var
 var
-  UpDirCount: Integer;
-  i: Integer;
-  s: string;
-  SharedDirs: Integer;
-  FileP, BaseP, FileEndP, BaseEndP, FileL, BaseL: integer;
+  SourceRoot, DestRoot, CmpDest, CmpSource: String;
+  CmpDestLen, CmpSourceLen, DestCount, SourceCount, i,
+  SharedFolders, LevelsBack, LevelsUp: Integer;
+  SourceDirs, DestDirs: TDirArr;
+  IsAbs: Boolean;
 begin
 begin
-  Result:=false;
-  RelPath:=Filename;
-  if (BaseDirectory='') or (Filename='') then exit;
-  {$IFDEF Windows}
-  // check for different windows file drives
-  if (CompareText(ExtractFileDrive(Filename),
-                     ExtractFileDrive(BaseDirectory))<>0)
-  then
-    exit;
-  {$ENDIF}
+  Result := False;
+  if (Dest = '') or (Source = '') then Exit;
+  if (Pos('..',Dest) > 0) or (Pos('..',Source) > 0) then Exit;
+  SourceRoot := ExtractFileRoot(Source);
+  DestRoot := ExtractFileRoot(Dest);
+  // Root must be same: either both absolute filenames or both relative (and on same drive in Windows)
+  if (CompareFileNames(SourceRoot, DestRoot) <> 0) then Exit;
+  IsAbs := (DestRoot <> '');
+  {$if defined(windows) and not defined(wince)}
+  if not IsAbs then  // relative paths
+  begin
+    //we cannot handle files like c:foo
+    if ((Length(Dest) > 1) and (UpCase(Dest[1]) in ['A'..'Z']) and (Dest[2] = ':')) or
+       ((Length(Source) > 1) and (UpCase(Source[1]) in ['A'..'Z']) and (Source[2] = ':')) then Exit;
+    //we cannot handle combinations like dest=foo source=\bar or the other way around
+    if ((Dest[1] in AllowDirectorySeparators) and not (Source[1] in AllowDirectorySeparators)) or
+       (not (Dest[1] in AllowDirectorySeparators) and (Source[1] in AllowDirectorySeparators)) then Exit;
+  end;
+  {$endif}
 
 
-  FileP:=1;
-  FileL:=length(Filename);
-  BaseP:=1;
-  BaseL:=length(BaseDirectory);
+  CmpSource := Source;
+  CmpDest := Dest;
 
 
-  // skip matching directories
-  SharedDirs:=0;
-  if Filename[FileP] in AllowDirectorySeparators then
+  CmpDest := ChompPathDelim(Dest);
+  CmpSource := ChompPathDelim(Source);
+  if IsAbs then
   begin
   begin
-    if not (BaseDirectory[BaseP] in AllowDirectorySeparators) then exit;
-    repeat
-      while (FileP<=FileL) and (Filename[FileP] in AllowDirectorySeparators) do
-        inc(FileP);
-      while (BaseP<=BaseL) and (BaseDirectory[BaseP] in AllowDirectorySeparators) do
-        inc(BaseP);
-      if (FileP>FileL) or (BaseP>BaseL) then break;
-      //writeln('TryCreateRelativePath check match .. File="',copy(Filename,FileP),'" Base="',copy(BaseDirectory,BaseP),'"');
-      FileEndP:=FileP;
-      BaseEndP:=BaseP;
-      while (FileEndP<=FileL) and IsNameChar(Filename[FileEndP]) do inc(FileEndP);
-      while (BaseEndP<=BaseL) and IsNameChar(BaseDirectory[BaseEndP]) do inc(BaseEndP);
-      if CompareFilenames(copy(Filename,FileP,FileEndP-FileP),
-        copy(BaseDirectory,BaseP,BaseEndP-BaseP))<>0
-      then
-        break;
-      FileP:=FileEndP;
-      BaseP:=BaseEndP;
-      inc(SharedDirs);
-    until false;
-  end else if (BaseDirectory[BaseP] in AllowDirectorySeparators) then
-    exit;
-
-  //writeln('TryCreateRelativePath skipped matches SharedDirs=',SharedDirs,' File="',copy(Filename,FileP),'" Base="',copy(BaseDirectory,BaseP),'"');
-  if SharedDirs=0 then exit;
-
-  // calculate needed '../'
-  UpDirCount:=0;
-  BaseEndP:=BaseP;
-  while (BaseEndP<=BaseL) and IsNameChar(BaseDirectory[BaseEndP]) do begin
-    inc(UpDirCount);
-    while (BaseEndP<=BaseL) and IsNameChar(BaseDirectory[BaseEndP]) do
-      inc(BaseEndP);
-    while (BaseEndP<=BaseL) and (BaseDirectory[BaseEndP] in AllowDirectorySeparators) do
-      inc(BaseEndP);
+    System.Delete(CmpSource,1,Length(SourceRoot));
+    System.Delete(CmpDest,1,Length(DestRoot));
   end;
   end;
 
 
-  //writeln('TryCreateRelativePath UpDirCount=',UpDirCount,' File="',copy(Filename,FileP),'" Base="',copy(BaseDirectory,BaseP),'"');
-  // create relative filename
-  if (FileP>FileL) and (UpDirCount=0) then
+  //Get rid of excessive trailing PathDelims now after (!) we stripped Root
+  while (Length(CmpDest) > 0) and (CmpDest[Length(CmpDest)] in AllowDirectorySeparators) do System.Delete(CmpDest,Length(CmpDest),1);
+  while (Length(CmpSource) > 0) and (CmpSource[Length(CmpSource)] in AllowDirectorySeparators) do System.Delete(CmpSource,Length(CmpSource),1);
+
+  CmpDestLen := Length(CmpDest);
+  CmpSourceLen := Length(CmpSource);
+
+  DestCount := SplitDirs(CmpDest, DestDirs);
+  SourceCount :=  SplitDirs(CmpSource, SourceDirs);
+
+  //writeln('TryCreaterelativePath: DestDirs:');
+  //for i := 1 to DestCount do writeln(i,' "',DestDirs[i-1],'"');
+  //writeln('TryCreaterelativePath: SrcDirs:');
+  //for i := 1 to SourceCount do writeln(i,' "',SourceDirs[i-1],'"');
+
+  i := 0;
+  SharedFolders := 0;
+  while (i < DestCount) and (i < SourceCount) do
   begin
   begin
-    // Filename is the BaseDirectory
-    if UsePointDirectory then
-      RelPath:='.'
+    if CompareFilenames(DestDirs[i], SourceDirs[i]) = 0 then
+    begin
+      Inc(SharedFolders);
+      Inc(i);
+    end
     else
     else
-      RelPath:='';
-    exit(true);
+      Break;
   end;
   end;
 
 
-  s:='';
-  for i:=1 to UpDirCount do
-    s+='..'+PathDelim;
-  if (FileP>FileL) and (UpDirCount>0) then
-    s:=LeftStr(s,length(s)-1)
+  //writeln('TryCreaterelativePath: SharedFolders = ',SharedFolders);
+  if (SharedFolders = 0) and ((not IsAbs) or AlwaysRequireSharedBaseFolder) and not ((CmpDestLen = 0) or (CmpSourceLen = 0)) then
+  begin
+    //debguln('TryCreaterelativePath: FAIL: IsAbs = ',DbgS(IsAs),' AlwaysRequireSharedBaseFolder = ',DbgS(AlwaysRequireSharedBaseFolder),
+    //' SharedFolders = 0, CmpDestLen = ',DbgS(cmpdestlen),' CmpSourceLen = ',DbgS(CmpSourceLen));
+    Exit;
+  end;
+  LevelsBack := SourceCount - SharedFolders;
+  LevelsUp := DestCount - SharedFolders;
+  //writeln('TryCreaterelativePath: LevelsBack = ',Levelsback);
+  //writeln('TryCreaterelativePath: LevelsUp   = ',LevelsUp);
+  if (LevelsBack > 0) then
+  begin
+    RelPath := '';
+    for i := 1 to LevelsBack do RelPath := '..' + PathDelim + Relpath;
+
+    for i := LevelsUp downto 1 do
+    begin
+      if (RelPath <> '') and not (RelPath[Length(RelPath)] in AllowDirectorySeparators) then RelPath := RelPath + PathDelim;
+      RelPath := RelPath + DestDirs[DestCount - i];
+    end;
+    RelPath := ChompPathDelim(RelPath);
+  end
   else
   else
-    s+=copy(Filename,FileP);
-  RelPath:=s;
-  Result:=true;
+  begin
+    RelPath := '';
+    for i := LevelsUp downto 1 do
+    begin
+      if (RelPath <> '') then RelPath := RelPath + PathDelim;
+      RelPath := RelPath + DestDirs[DestCount - i];
+    end;
+  end;
+  if UsePointDirectory and (RelPath = '') then
+    RelPath := '.'; // Dest = Source
+
+  //writeln('TryCreateRelativePath RelPath=',RelPath);
+  Result := True;
 end;
 end;
 
 
 function ResolveDots(const AFilename: string): string;
 function ResolveDots(const AFilename: string): string;
@@ -542,7 +652,7 @@ begin
 end;
 end;
 {$ENDIF}
 {$ENDIF}
 
 
-procedure ForcePathDelims(Var FileName: string);
+procedure ForcePathDelims(var FileName: string);
 begin
 begin
   Filename:=GetForcedPathDelims(Filename);
   Filename:=GetForcedPathDelims(Filename);
 end;
 end;

+ 10 - 0
packages/pastojs/src/pas2jsfileutilsnodejs.inc

@@ -142,6 +142,16 @@ begin
     Result:='';
     Result:='';
 end;
 end;
 
 
+function IsUNCPath(const Path: String): Boolean;
+begin
+  Result := false;
+end;
+
+function ExtractUNCVolume(const Path: String): String;
+begin
+  Result := '';
+end;
+
 function FileIsWritable(const AFilename: string): boolean;
 function FileIsWritable(const AFilename: string): boolean;
 begin
 begin
   try
   try

+ 10 - 0
packages/pastojs/src/pas2jsfileutilsunix.inc

@@ -143,6 +143,16 @@ begin
     Result:='';
     Result:='';
 end;
 end;
 
 
+function IsUNCPath(const Path: String): Boolean;
+begin
+  Result := false;
+end;
+
+function ExtractUNCVolume(const Path: String): String;
+begin
+  Result := '';
+end;
+
 function FileIsWritable(const AFilename: string): boolean;
 function FileIsWritable(const AFilename: string): boolean;
 begin
 begin
   Result := BaseUnix.FpAccess(AFilename, BaseUnix.W_OK) = 0;
   Result := BaseUnix.FpAccess(AFilename, BaseUnix.W_OK) = 0;

+ 50 - 0
packages/pastojs/src/pas2jsfileutilswin.inc

@@ -411,6 +411,56 @@ begin
   Result:=Filename;
   Result:=Filename;
 end;
 end;
 
 
+function IsUNCPath(const Path: String): Boolean;
+begin
+  Result := (Length(Path) > 2)
+    and (Path[1] in AllowDirectorySeparators)
+    and (Path[2] in AllowDirectorySeparators);
+end;
+
+function ExtractUNCVolume(const Path: String): String;
+var
+  I, Len: Integer;
+
+  // the next function reuses Len variable
+  function NextPathDelim(const Start: Integer): Integer;// inline;
+  begin
+    Result := Start;
+    while (Result <= Len) and not (Path[Result] in AllowDirectorySeparators) do
+      inc(Result);
+  end;
+
+begin
+  if not IsUNCPath(Path) then
+    Exit('');
+  I := 3;
+  Len := Length(Path);
+  if Path[I] = '?' then
+  begin
+    // Long UNC path form like:
+    // \\?\UNC\ComputerName\SharedFolder\Resource or
+    // \\?\C:\Directory
+    inc(I);
+    if not (Path[I] in AllowDirectorySeparators) then
+      Exit('');
+    if UpperCase(Copy(Path, I + 1, 3)) = 'UNC' then
+    begin
+      inc(I, 4);
+      if I < Len then
+        I := NextPathDelim(I + 1);
+      if I < Len then
+        I := NextPathDelim(I + 1);
+    end;
+  end
+  else
+  begin
+    I := NextPathDelim(I);
+    if I < Len then
+      I := NextPathDelim(I + 1);
+  end;
+  Result := Copy(Path, 1, I);
+end;
+
 function FileGetAttrUTF8(const FileName: String): Longint;
 function FileGetAttrUTF8(const FileName: String): Longint;
 begin
 begin
   Result:=Integer(Windows.GetFileAttributesW(PWideChar(UTF8Decode(FileName))));
   Result:=Integer(Windows.GetFileAttributesW(PWideChar(UTF8Decode(FileName))));

+ 1 - 1
packages/pastojs/src/pas2jsfs.pp

@@ -101,7 +101,7 @@ Type
     Function FileExists(Const aFileName: String): Boolean; virtual; abstract;
     Function FileExists(Const aFileName: String): Boolean; virtual; abstract;
     function FindUnitJSFileName(const aUnitFilename: string): String; virtual; abstract;
     function FindUnitJSFileName(const aUnitFilename: string): String; virtual; abstract;
     function FindCustomJSFileName(const aFilename: string): String; virtual; abstract;
     function FindCustomJSFileName(const aFilename: string): String; virtual; abstract;
-    function FindUnitFileName(const aUnitname, InFilename: string; out IsForeign: boolean): String; virtual; abstract;
+    function FindUnitFileName(const aUnitname, InFilename, ModuleDir: string; out IsForeign: boolean): String; virtual; abstract;
     procedure SaveToFile(ms: TFPJSStream; Filename: string); virtual; abstract;
     procedure SaveToFile(ms: TFPJSStream; Filename: string); virtual; abstract;
     function PCUExists(var aFileName: string): Boolean; virtual;
     function PCUExists(var aFileName: string): Boolean; virtual;
     procedure GetPCUDirs(aList: TStrings; const aBaseDir: String); virtual;
     procedure GetPCUDirs(aList: TStrings; const aBaseDir: String); virtual;

+ 14 - 1
packages/pastojs/tests/tcfiler.pas

@@ -668,6 +668,7 @@ procedure TCustomTestPrecompile.CheckRestoredSectionScope(const Path: string;
 var
 var
   i: Integer;
   i: Integer;
   OrigUses, RestUses: TPas2JSSectionScope;
   OrigUses, RestUses: TPas2JSSectionScope;
+  OrigHelperEntry, RestHelperEntry: TPRHelperEntry;
 begin
 begin
   if Orig.BoolSwitches<>Rest.BoolSwitches then
   if Orig.BoolSwitches<>Rest.BoolSwitches then
     Fail(Path+'.BoolSwitches Orig='+BoolSwitchesToStr(Orig.BoolSwitches)+' Rest='+BoolSwitchesToStr(Rest.BoolSwitches));
     Fail(Path+'.BoolSwitches Orig='+BoolSwitchesToStr(Orig.BoolSwitches)+' Rest='+BoolSwitchesToStr(Rest.BoolSwitches));
@@ -684,6 +685,18 @@ begin
       Fail(Path+'.UsesScopes['+IntToStr(i)+'] Orig='+GetObjName(OrigUses)+' Rest='+GetObjName(RestUses));
       Fail(Path+'.UsesScopes['+IntToStr(i)+'] Orig='+GetObjName(OrigUses)+' Rest='+GetObjName(RestUses));
     CheckRestoredReference(Path+'.UsesScopes['+IntToStr(i)+']',OrigUses.Element,RestUses.Element);
     CheckRestoredReference(Path+'.UsesScopes['+IntToStr(i)+']',OrigUses.Element,RestUses.Element);
     end;
     end;
+  AssertEquals(Path+' length(Helpers)',length(Orig.Helpers),length(Rest.Helpers));
+  for i:=0 to length(Orig.Helpers)-1 do
+    begin
+    OrigHelperEntry:=TPRHelperEntry(Orig.Helpers[i]);
+    RestHelperEntry:=TPRHelperEntry(Rest.Helpers[i]);
+    if OrigHelperEntry.ClassType<>RestHelperEntry.ClassType then
+      Fail(Path+'.Helpers['+IntToStr(i)+'] Orig='+GetObjName(OrigHelperEntry)+' Rest='+GetObjName(RestHelperEntry));
+    AssertEquals(Path+'.Helpers['+IntToStr(i)+'].Added',OrigHelperEntry.Added,RestHelperEntry.Added);
+    CheckRestoredReference(Path+'.Helpers['+IntToStr(i)+'].Helper',OrigHelperEntry.Helper,RestHelperEntry.Helper);
+    CheckRestoredReference(Path+'.Helpers['+IntToStr(i)+'].HelperForType',OrigHelperEntry.HelperForType,RestHelperEntry.HelperForType);
+    end;
+
   AssertEquals(Path+'.Finished',Orig.Finished,Rest.Finished);
   AssertEquals(Path+'.Finished',Orig.Finished,Rest.Finished);
   CheckRestoredIdentifierScope(Path,Orig,Rest);
   CheckRestoredIdentifierScope(Path,Orig,Rest);
 end;
 end;
@@ -810,7 +823,7 @@ begin
     AssertEquals(Path+'.ResultVarName',Orig.ResultVarName,Rest.ResultVarName);
     AssertEquals(Path+'.ResultVarName',Orig.ResultVarName,Rest.ResultVarName);
     CheckRestoredReference(Path+'.OverriddenProc',Orig.OverriddenProc,Rest.OverriddenProc);
     CheckRestoredReference(Path+'.OverriddenProc',Orig.OverriddenProc,Rest.OverriddenProc);
 
 
-    CheckRestoredScopeReference(Path+'.ClassScope',Orig.ClassOrRecordScope,Rest.ClassOrRecordScope);
+    CheckRestoredScopeReference(Path+'.ClassScope',Orig.ClassRecScope,Rest.ClassRecScope);
     CheckRestoredElement(Path+'.SelfArg',Orig.SelfArg,Rest.SelfArg);
     CheckRestoredElement(Path+'.SelfArg',Orig.SelfArg,Rest.SelfArg);
     if Orig.Flags<>Rest.Flags then
     if Orig.Flags<>Rest.Flags then
       Fail(Path+'.Flags');
       Fail(Path+'.Flags');

+ 548 - 100
packages/pastojs/tests/tcmodules.pas

@@ -257,6 +257,7 @@ type
     Procedure TestInteger;
     Procedure TestInteger;
     Procedure TestIntegerRange;
     Procedure TestIntegerRange;
     Procedure TestIntegerTypecasts;
     Procedure TestIntegerTypecasts;
+    Procedure TestBitwiseAndNativeIntWarn;
     Procedure TestCurrency;
     Procedure TestCurrency;
     Procedure TestForBoolDo;
     Procedure TestForBoolDo;
     Procedure TestForIntDo;
     Procedure TestForIntDo;
@@ -369,6 +370,8 @@ type
     // statements
     // statements
     Procedure TestNestBegin;
     Procedure TestNestBegin;
     Procedure TestIncDec;
     Procedure TestIncDec;
+    Procedure TestLoHiFpcMode;
+    Procedure TestLoHiDelphiMode;
     Procedure TestAssignments;
     Procedure TestAssignments;
     Procedure TestArithmeticOperators1;
     Procedure TestArithmeticOperators1;
     Procedure TestLogicalOperators;
     Procedure TestLogicalOperators;
@@ -393,6 +396,7 @@ type
     Procedure TestCaseOfNoElse_UseSwitch;
     Procedure TestCaseOfNoElse_UseSwitch;
     Procedure TestCaseOfRange;
     Procedure TestCaseOfRange;
     Procedure TestCaseOfString;
     Procedure TestCaseOfString;
+    Procedure TestCaseOfChar;
     Procedure TestCaseOfExternalClassConst;
     Procedure TestCaseOfExternalClassConst;
     Procedure TestDebugger;
     Procedure TestDebugger;
 
 
@@ -448,6 +452,7 @@ type
     Procedure TestRecord_Const;
     Procedure TestRecord_Const;
     Procedure TestRecord_TypecastFail;
     Procedure TestRecord_TypecastFail;
     Procedure TestRecord_InFunction;
     Procedure TestRecord_InFunction;
+    // ToDo: Procedure TestRecord_ExternalField;
     // ToDo: RTTI of local record
     // ToDo: RTTI of local record
     // ToDo: pcu local record, name clash and rtti
     // ToDo: pcu local record, name clash and rtti
 
 
@@ -457,6 +462,7 @@ type
     Procedure TestAdvRecord_PropertyDefault;
     Procedure TestAdvRecord_PropertyDefault;
     Procedure TestAdvRecord_Property_ClassMethod;
     Procedure TestAdvRecord_Property_ClassMethod;
     Procedure TestAdvRecord_Const;
     Procedure TestAdvRecord_Const;
+    Procedure TestAdvRecord_ExternalField;
     Procedure TestAdvRecord_SubRecord;
     Procedure TestAdvRecord_SubRecord;
     Procedure TestAdvRecord_SubClass;
     Procedure TestAdvRecord_SubClass;
     Procedure TestAdvRecord_SubInterfaceFail;
     Procedure TestAdvRecord_SubInterfaceFail;
@@ -621,6 +627,10 @@ type
     Procedure TestClassInterface_GUID;
     Procedure TestClassInterface_GUID;
     Procedure TestClassInterface_GUIDProperty;
     Procedure TestClassInterface_GUIDProperty;
 
 
+    // helpers
+    Procedure TestClassHelper_ClassVar; // ToDo
+    // todo: TestClassHelper_Overload
+
     // proc types
     // proc types
     Procedure TestProcType;
     Procedure TestProcType;
     Procedure TestProcType_Arg;
     Procedure TestProcType_Arg;
@@ -2359,9 +2369,9 @@ begin
   Add('  d2: double = 5.6;');
   Add('  d2: double = 5.6;');
   Add('  i3: longint = $707;');
   Add('  i3: longint = $707;');
   Add('  i4: nativeint = 4503599627370495;');
   Add('  i4: nativeint = 4503599627370495;');
-  Add('  i5: nativeint = -4503599627370496;');
+  Add('  i5: nativeint = -4503599627370495-1;');
   Add('  i6: nativeint =   $fffffffffffff;');
   Add('  i6: nativeint =   $fffffffffffff;');
-  Add('  i7: nativeint = -$10000000000000;');
+  Add('  i7: nativeint = -$fffffffffffff-1;');
   Add('  i8: byte = 00;');
   Add('  i8: byte = 00;');
   Add('  u8: nativeuint =  $fffffffffffff;');
   Add('  u8: nativeuint =  $fffffffffffff;');
   Add('  u9: nativeuint =  $0000000000000;');
   Add('  u9: nativeuint =  $0000000000000;');
@@ -2382,9 +2392,9 @@ begin
     'this.d2 = 5.6;',
     'this.d2 = 5.6;',
     'this.i3 = 0x707;',
     'this.i3 = 0x707;',
     'this.i4 = 4503599627370495;',
     'this.i4 = 4503599627370495;',
-    'this.i5 = -4503599627370496;',
+    'this.i5 = -4503599627370495-1;',
     'this.i6 = 0xfffffffffffff;',
     'this.i6 = 0xfffffffffffff;',
-    'this.i7 =-0x10000000000000;',
+    'this.i7 =-0xfffffffffffff-1;',
     'this.i8 = 0;',
     'this.i8 = 0;',
     'this.u8 = 0xfffffffffffff;',
     'this.u8 = 0xfffffffffffff;',
     'this.u9 = 0x0;',
     'this.u9 = 0x0;',
@@ -2675,6 +2685,154 @@ begin
     ]));
     ]));
 end;
 end;
 
 
+procedure TTestModule.TestLoHiFpcMode;
+begin
+  StartProgram(false);
+  Add([
+  '{$mode objfpc}',
+  'const',
+  '  LoByte1 = Lo(Word($1234));',
+  '  HiByte1 = Hi(Word($1234));',
+  '  LoByte2 = Lo(SmallInt($1234));',
+  '  HiByte2 = Hi(SmallInt($1234));',
+  '  LoWord1 = Lo($1234CDEF);',
+  '  HiWord1 = Hi($1234CDEF);',
+  '  LoWord2 = Lo(-$1234CDEF);',
+  '  HiWord2 = Hi(-$1234CDEF);',
+  '  lo4:byte=lo(byte($34));',
+  '  hi4:byte=hi(byte($34));',
+  '  lo5:byte=lo(shortint(-$34));',
+  '  hi5:byte=hi(shortint(-$34));',
+  '  lo6:longword=lo($123456789ABCD);',
+  '  hi6:longword=hi($123456789ABCD);',
+  '  lo7:longword=lo(-$123456789ABCD);',
+  '  hi7:longword=hi(-$123456789ABCD);',
+  'var',
+  '  b: Byte;',
+  '  ss: shortint;',
+  '  w: Word;',
+  '  si: SmallInt;',
+  '  lw: LongWord;',
+  '  li: LongInt;',
+  '  b2: Byte;',
+  '  ni: nativeint;',
+  'begin',
+  '  w := $1234;',
+  '  ss := -$12;',
+  '  b := lo(ss);',
+  '  b := HI(ss);',
+  '  b := lo(w);',
+  '  b := HI(w);',
+  '  b2 := lo(b);',
+  '  b2 := hi(b);',
+  '  lw := $1234CDEF;',
+  '  w := lo(lw);',
+  '  w := hi(lw);',
+  '  ni := $123456789ABCD;',
+  '  lw := lo(ni);',
+  '  lw := hi(ni);',
+  '']);
+  ConvertProgram;
+  CheckSource('TestLoHiFpcMode',
+    LinesToStr([ // statements
+    'this.LoByte1 = 0x1234 & 0xFF;',
+    'this.HiByte1 = (0x1234 >> 8) & 0xFF;',
+    'this.LoByte2 = 0x1234 & 0xFF;',
+    'this.HiByte2 = (0x1234 >> 8) & 0xFF;',
+    'this.LoWord1 = 0x1234CDEF & 0xFFFF;',
+    'this.HiWord1 = (0x1234CDEF >> 16) & 0xFFFF;',
+    'this.LoWord2 = -0x1234CDEF & 0xFFFF;',
+    'this.HiWord2 = (-0x1234CDEF >> 16) & 0xFFFF;',
+    'this.lo4 = 0x34 & 0xF;',
+    'this.hi4 = (0x34 >> 4) & 0xF;',
+    'this.lo5 = (((-0x34 & 255) << 24) >> 24) & 0xFF;',
+    'this.hi5 = ((((-0x34 & 255) << 24) >> 24) >> 8) & 0xFF;',
+    'this.lo6 = 0x123456789ABCD >>> 0;',
+    'this.hi6 = 74565 >>> 0;',
+    'this.lo7 = -0x123456789ABCD >>> 0;',
+    'this.hi7 = Math.floor(-0x123456789ABCD / 4294967296) >>> 0;',
+    'this.b = 0;',
+    'this.ss = 0;',
+    'this.w = 0;',
+    'this.si = 0;',
+    'this.lw = 0;',
+    'this.li = 0;',
+    'this.b2 = 0;',
+    'this.ni = 0;',
+    '']),
+    LinesToStr([ // this.$main
+    '$mod.w = 0x1234;',
+    '$mod.ss = -0x12;',
+    '$mod.b = $mod.ss & 0xFF;',
+    '$mod.b = ($mod.ss >> 8) & 0xFF;',
+    '$mod.b = $mod.w & 0xFF;',
+    '$mod.b = ($mod.w >> 8) & 0xFF;',
+    '$mod.b2 = $mod.b & 0xF;',
+    '$mod.b2 = ($mod.b >> 4) & 0xF;',
+    '$mod.lw = 0x1234CDEF;',
+    '$mod.w = $mod.lw & 0xFFFF;',
+    '$mod.w = ($mod.lw >> 16) & 0xFFFF;',
+    '$mod.ni = 0x123456789ABCD;',
+    '$mod.lw = $mod.ni >>> 0;',
+    '$mod.lw = Math.floor($mod.ni / 4294967296) >>> 0;',
+    '']));
+end;
+
+procedure TTestModule.TestLoHiDelphiMode;
+begin
+  StartProgram(false);
+  Add([
+  '{$mode delphi}',
+  'const',
+  '  LoByte1 = Lo(Word($1234));',
+  '  HiByte1 = Hi(Word($1234));',
+  '  LoByte2 = Lo(SmallInt($1234));',
+  '  HiByte2 = Hi(SmallInt($1234));',
+  '  LoByte3 = Lo($1234CDEF);',
+  '  HiByte3 = Hi($1234CDEF);',
+  '  LoByte4 = Lo(-$1234CDEF);',
+  '  HiByte4 = Hi(-$1234CDEF);',
+  'var',
+  '  b: Byte;',
+  '  w: Word;',
+  '  si: SmallInt;',
+  '  lw: LongWord;',
+  '  li: LongInt;',
+  'begin',
+  '  w := $1234;',
+  '  b := lo(w);',
+  '  b := HI(w);',
+  '  lw := $1234CDEF;',
+  '  b := lo(lw);',
+  '  b := hi(lw);',
+  '']);
+  ConvertProgram;
+  CheckSource('TestLoHiDelphiMode',
+    LinesToStr([ // statements
+    'this.LoByte1 = 0x1234 & 0xFF;',
+    'this.HiByte1 = (0x1234 >> 8) & 0xFF;',
+    'this.LoByte2 = 0x1234 & 0xFF;',
+    'this.HiByte2 = (0x1234 >> 8) & 0xFF;',
+    'this.LoByte3 = 0x1234CDEF & 0xFF;',
+    'this.HiByte3 = (0x1234CDEF >> 8) & 0xFF;',
+    'this.LoByte4 = -0x1234CDEF & 0xFF;',
+    'this.HiByte4 = (-0x1234CDEF >> 8) & 0xFF;',
+    'this.b = 0;',
+    'this.w = 0;',
+    'this.si = 0;',
+    'this.lw = 0;',
+    'this.li = 0;'
+    ]),
+    LinesToStr([ // this.$main
+    '$mod.w = 0x1234;',
+    '$mod.b = $mod.w & 0xFF;',
+    '$mod.b = ($mod.w >> 8) & 0xFF;',
+    '$mod.lw = 0x1234CDEF;',
+    '$mod.b = $mod.lw & 0xFF;',
+    '$mod.b = ($mod.lw >> 8) & 0xFF;'
+    ]));
+end;
+
 procedure TTestModule.TestAssignments;
 procedure TTestModule.TestAssignments;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
@@ -5853,7 +6011,17 @@ begin
   '  maxdouble = 1.7e+308;',
   '  maxdouble = 1.7e+308;',
   '  mindouble = -1.7e+308;',
   '  mindouble = -1.7e+308;',
   '  MinSafeIntDouble = -$10000000000000;',
   '  MinSafeIntDouble = -$10000000000000;',
+  '  MinSafeIntDouble2 = -$fffffffffffff-1;',
   '  MaxSafeIntDouble =   $fffffffffffff;',
   '  MaxSafeIntDouble =   $fffffffffffff;',
+  '  DZeroResolution = 1E-12;',
+  '  Minus1 = -1E-12;',
+  '  EPS = 1E-9;',
+  '  DELTA = 0.001;',
+  '  Big = 129.789E+100;',
+  '  Test0_15 = 0.15;',
+  '  Test999 = 2.9999999999999;',
+  '  Test111999 = 211199999999999000.0;',
+  '  TestMinus111999 = -211199999999999000.0;',
   'var',
   'var',
   '  d: double = b;',
   '  d: double = b;',
   'begin',
   'begin',
@@ -5864,8 +6032,9 @@ begin
   '  d:=1.7E308;',
   '  d:=1.7E308;',
   '  d:=001.00E00;',
   '  d:=001.00E00;',
   '  d:=002.00E001;',
   '  d:=002.00E001;',
-  '  d:=-003.00E-00;',
-  '  d:=-004.00E-001;',
+  '  d:=003.000E000;',
+  '  d:=-004.00E-00;',
+  '  d:=-005.00E-001;',
   '  d:=10**3;',
   '  d:=10**3;',
   '  d:=10 mod 3;',
   '  d:=10 mod 3;',
   '  d:=10 div 3;',
   '  d:=10 div 3;',
@@ -5885,6 +6054,9 @@ begin
   '  d:=maxdouble;',
   '  d:=maxdouble;',
   '  d:=mindouble;',
   '  d:=mindouble;',
   '  d:=MinSafeIntDouble;',
   '  d:=MinSafeIntDouble;',
+  '  d:=double(MinSafeIntDouble);',
+  '  d:=MinSafeIntDouble2;',
+  '  d:=double(MinSafeIntDouble2);',
   '  d:=MaxSafeIntDouble;',
   '  d:=MaxSafeIntDouble;',
   '  d:=default(double);',
   '  d:=default(double);',
   '']);
   '']);
@@ -5909,7 +6081,17 @@ begin
     'this.maxdouble = 1.7e+308;',
     'this.maxdouble = 1.7e+308;',
     'this.mindouble = -1.7e+308;',
     'this.mindouble = -1.7e+308;',
     'this.MinSafeIntDouble = -0x10000000000000;',
     'this.MinSafeIntDouble = -0x10000000000000;',
+    'this.MinSafeIntDouble2 = -0xfffffffffffff - 1;',
     'this.MaxSafeIntDouble = 0xfffffffffffff;',
     'this.MaxSafeIntDouble = 0xfffffffffffff;',
+    'this.DZeroResolution = 1E-12;',
+    'this.Minus1 = -1E-12;',
+    'this.EPS = 1E-9;',
+    'this.DELTA = 0.001;',
+    'this.Big = 129.789E+100;',
+    'this.Test0_15 = 0.15;',
+    'this.Test999 = 2.9999999999999;',
+    'this.Test111999 = 211199999999999000.0;',
+    'this.TestMinus111999 = -211199999999999000.0;',
     'this.d = 4.4;'
     'this.d = 4.4;'
     ]),
     ]),
     LinesToStr([
     LinesToStr([
@@ -5920,8 +6102,9 @@ begin
     '$mod.d = 1.7E308;',
     '$mod.d = 1.7E308;',
     '$mod.d = 1.00E0;',
     '$mod.d = 1.00E0;',
     '$mod.d = 2.00E1;',
     '$mod.d = 2.00E1;',
-    '$mod.d = -3.00E-0;',
-    '$mod.d = -4.00E-1;',
+    '$mod.d = 3.000E0;',
+    '$mod.d = -4.00E-0;',
+    '$mod.d = -5.00E-1;',
     '$mod.d = Math.pow(10, 3);',
     '$mod.d = Math.pow(10, 3);',
     '$mod.d = 10 % 3;',
     '$mod.d = 10 % 3;',
     '$mod.d = Math.floor(10 / 3);',
     '$mod.d = Math.floor(10 / 3);',
@@ -5941,6 +6124,9 @@ begin
     '$mod.d = 1.7E308;',
     '$mod.d = 1.7E308;',
     '$mod.d = -1.7E308;',
     '$mod.d = -1.7E308;',
     '$mod.d = -4503599627370496;',
     '$mod.d = -4503599627370496;',
+    '$mod.d = -4503599627370496;',
+    '$mod.d = -4503599627370496;',
+    '$mod.d = -4503599627370496;',
     '$mod.d = 4503599627370495;',
     '$mod.d = 4503599627370495;',
     '$mod.d = 0.0;',
     '$mod.d = 0.0;',
     '']));
     '']));
@@ -6069,6 +6255,27 @@ begin
     '']));
     '']));
 end;
 end;
 
 
+procedure TTestModule.TestBitwiseAndNativeIntWarn;
+begin
+  StartProgram(false);
+  Add([
+  'var',
+  '  i,j: nativeint;',
+  'begin',
+  '  i:=i and j;',
+  '']);
+  ConvertProgram;
+  CheckSource('TestBitwiseAndNativeIntWarn',
+    LinesToStr([
+    'this.i = 0;',
+    'this.j = 0;',
+    '']),
+    LinesToStr([
+    '$mod.i = $mod.i & $mod.j;',
+    '']));
+  CheckHint(mtWarning,nBitWiseOperationsAre32Bit,sBitWiseOperationsAre32Bit);
+end;
+
 procedure TTestModule.TestCurrency;
 procedure TTestModule.TestCurrency;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
@@ -6313,33 +6520,35 @@ begin
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
   'const',
   'const',
- '  c: char = ''1'';',
- 'begin',
- '  c:=#0;',
- '  c:=#1;',
- '  c:=#9;',
- '  c:=#10;',
- '  c:=#13;',
- '  c:=#31;',
- '  c:=#32;',
- '  c:=#$A;',
- '  c:=#$0A;',
- '  c:=#$b;',
- '  c:=#$0b;',
- '  c:=^A;',
- '  c:=''"'';',
- '  c:=default(char);',
- '  c:=#$00E4;', // ä
- '  c:=''ä'';',
- '  c:=#$E4;', // ä
- '  c:=#$D800;', // invalid UTF-16
- '  c:=#$DFFF;', // invalid UTF-16
- '  c:=#$FFFF;', // last UCS-2
- '  c:=high(c);', // last UCS-2
- '']);
+  '  a = #$00F3;',
+  '  c: char = ''1'';',
+  'begin',
+  '  c:=#0;',
+  '  c:=#1;',
+  '  c:=#9;',
+  '  c:=#10;',
+  '  c:=#13;',
+  '  c:=#31;',
+  '  c:=#32;',
+  '  c:=#$A;',
+  '  c:=#$0A;',
+  '  c:=#$b;',
+  '  c:=#$0b;',
+  '  c:=^A;',
+  '  c:=''"'';',
+  '  c:=default(char);',
+  '  c:=#$00E4;', // ä
+  '  c:=''ä'';',
+  '  c:=#$E4;', // ä
+  '  c:=#$D800;', // invalid UTF-16
+  '  c:=#$DFFF;', // invalid UTF-16
+  '  c:=#$FFFF;', // last UCS-2
+  '  c:=high(c);', // last UCS-2
+  '']);
   ConvertProgram;
   ConvertProgram;
   CheckSource('TestCharConst',
   CheckSource('TestCharConst',
     LinesToStr([
     LinesToStr([
+    'this.a="ó";',
     'this.c="1";'
     'this.c="1";'
     ]),
     ]),
     LinesToStr([
     LinesToStr([
@@ -6426,6 +6635,9 @@ begin
   '  c:=succ(c);',
   '  c:=succ(c);',
   '  c:=low(c);',
   '  c:=low(c);',
   '  c:=high(c);',
   '  c:=high(c);',
+  '  i:=byte(c);',
+  '  i:=word(c);',
+  '  i:=longint(c);',
   '']);
   '']);
   ConvertProgram;
   ConvertProgram;
   CheckSource('TestChar_BuiltInProcs',
   CheckSource('TestChar_BuiltInProcs',
@@ -6442,6 +6654,9 @@ begin
     '$mod.c = String.fromCharCode($mod.c.charCodeAt() + 1);',
     '$mod.c = String.fromCharCode($mod.c.charCodeAt() + 1);',
     '$mod.c = "\x00";',
     '$mod.c = "\x00";',
     '$mod.c = "\uFFFF";',
     '$mod.c = "\uFFFF";',
+    '$mod.i = $mod.c.charCodeAt() & 255;',
+    '$mod.i = $mod.c.charCodeAt();',
+    '$mod.i = $mod.c.charCodeAt() & 0xFFFFFFFF;',
     '']));
     '']));
 end;
 end;
 
 
@@ -6450,6 +6665,8 @@ begin
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
   '{$H+}',
   '{$H+}',
+  'const',
+  '  a = #$00F3#$017C;', // first <256, then >=256
   'var',
   'var',
   '  s: string = ''abc'';',
   '  s: string = ''abc'';',
   'begin',
   'begin',
@@ -6469,6 +6686,7 @@ begin
   ConvertProgram;
   ConvertProgram;
   CheckSource('TestStringConst',
   CheckSource('TestStringConst',
     LinesToStr([
     LinesToStr([
+    'this.a = "óż";',
     'this.s="abc";'
     'this.s="abc";'
     ]),
     ]),
     LinesToStr([
     LinesToStr([
@@ -6790,6 +7008,7 @@ begin
   'begin',
   'begin',
   '  for c:=''a'' to ''c'' do ;',
   '  for c:=''a'' to ''c'' do ;',
   '  for c:=c downto ''a'' do ;',
   '  for c:=c downto ''a'' do ;',
+  '  for c:=''Б'' to ''Я'' do ;',
   '']);
   '']);
   ConvertProgram;
   ConvertProgram;
   CheckSource('TestForCharDo',
   CheckSource('TestForCharDo',
@@ -6798,6 +7017,7 @@ begin
     LinesToStr([ // this.$main
     LinesToStr([ // this.$main
     'for (var $l1 = 97; $l1 <= 99; $l1++) $mod.c = String.fromCharCode($l1);',
     'for (var $l1 = 97; $l1 <= 99; $l1++) $mod.c = String.fromCharCode($l1);',
     'for (var $l2 = $mod.c.charCodeAt(); $l2 >= 97; $l2--) $mod.c = String.fromCharCode($l2);',
     'for (var $l2 = $mod.c.charCodeAt(); $l2 >= 97; $l2--) $mod.c = String.fromCharCode($l2);',
+    'for (var $l3 = 1041; $l3 <= 1071; $l3++) $mod.c = String.fromCharCode($l3);',
     '']));
     '']));
 end;
 end;
 
 
@@ -7557,6 +7777,7 @@ begin
   '  case s of',
   '  case s of',
   '  ''foo'': s:=h;',
   '  ''foo'': s:=h;',
   '  ''a''..''z'': h:=s;',
   '  ''a''..''z'': h:=s;',
+  '  ''Б''..''Я'': ;',
   '  end;',
   '  end;',
   '']);
   '']);
   ConvertProgram;
   ConvertProgram;
@@ -7569,7 +7790,34 @@ begin
     'var $tmp1 = $mod.s;',
     'var $tmp1 = $mod.s;',
     'if ($tmp1 === "foo") {',
     'if ($tmp1 === "foo") {',
     '  $mod.s = $mod.h}',
     '  $mod.s = $mod.h}',
-    ' else if (($tmp1.length === 1) && ($tmp1 >= "a") && ($tmp1 <= "z")) $mod.h = $mod.s;',
+    ' else if (($tmp1.length === 1) && ($tmp1 >= "a") && ($tmp1 <= "z")) {',
+    '  $mod.h = $mod.s}',
+    ' else if (($tmp1.length === 1) && ($tmp1 >= "Б") && ($tmp1 <= "Я")) ;',
+    '']));
+end;
+
+procedure TTestModule.TestCaseOfChar;
+begin
+  StartProgram(false);
+  Add([
+  'var s,h: char;',
+  'begin',
+  '  case s of',
+  '  ''a''..''z'': h:=s;',
+  '  ''Б''..''Я'': ;',
+  '  end;',
+  '']);
+  ConvertProgram;
+  CheckSource('TestCaseOfString',
+    LinesToStr([ // statements
+    'this.s = "";',
+    'this.h = "";',
+    '']),
+    LinesToStr([ // $mod.$main
+    'var $tmp1 = $mod.s;',
+    'if (($tmp1 >= "a") && ($tmp1 <= "z")) {',
+    '  $mod.h = $mod.s}',
+    ' else if (($tmp1 >= "Б") && ($tmp1 <= "Я")) ;',
     '']));
     '']));
 end;
 end;
 
 
@@ -10169,7 +10417,7 @@ begin
     '  this.SetInt = function (Value) {',
     '  this.SetInt = function (Value) {',
     '  };',
     '  };',
     '  this.DoIt = function () {',
     '  this.DoIt = function () {',
-    '    this.Fy = this.Fx + 1;',
+    '    $mod.TRec.Fy = this.Fx + 1;',
     '    this.SetInt(this.GetInt() + 1);',
     '    this.SetInt(this.GetInt() + 1);',
     '  };',
     '  };',
     '}, true);',
     '}, true);',
@@ -10180,7 +10428,7 @@ begin
     'if ($mod.TRec.GetInt() === 2) ;',
     'if ($mod.TRec.GetInt() === 2) ;',
     '$mod.TRec.SetInt($mod.TRec.GetInt() + 2);',
     '$mod.TRec.SetInt($mod.TRec.GetInt() + 2);',
     '$mod.TRec.SetInt($mod.TRec.Fx);',
     '$mod.TRec.SetInt($mod.TRec.Fx);',
-    '$mod.r.$record.Fy = $mod.r.Fx + 1;',
+    '$mod.TRec.Fy = $mod.r.Fx + 1;',
     'if ($mod.r.$record.GetInt() === 2) ;',
     'if ($mod.r.$record.GetInt() === 2) ;',
     '$mod.r.$record.SetInt($mod.r.$record.GetInt() + 2);',
     '$mod.r.$record.SetInt($mod.r.$record.GetInt() + 2);',
     '$mod.r.$record.SetInt($mod.r.Fx);',
     '$mod.r.$record.SetInt($mod.r.Fx);',
@@ -10276,6 +10524,73 @@ begin
     '']));
     '']));
 end;
 end;
 
 
+procedure TTestModule.TestAdvRecord_ExternalField;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch AdvancedRecords}',
+  '{$modeswitch externalclass}',
+  'type',
+  '  TCar = record',
+  '  public',
+  '    Intern: longint external name ''$Intern'';',
+  '    Intern2: longint external name ''$Intern2'';',
+  '    Bracket: longint external name ''["A B"]'';',
+  '    procedure DoIt;',
+  '  end;',
+  'implementation',
+  'procedure tcar.doit;',
+  'begin',
+  '  Intern:=Intern+1;',
+  '  Intern2:=Intern2+2;',
+  '  Bracket:=Bracket+3;',
+  'end;',
+  'var Rec: TCar = (intern: 11; intern2: 12; bracket: 13);',
+  'begin',
+  '  Rec.intern:=Rec.intern+1;',
+  '  Rec.intern2:=Rec.intern2+2;',
+  '  Rec.Bracket:=Rec.Bracket+3;',
+  '  with Rec do begin',
+  '    intern:=intern+1;',
+  '    intern2:=intern2+2;',
+  '    Bracket:=Bracket+3;',
+  '  end;']);
+  ConvertProgram;
+  CheckSource('TestAdvRecord_ExternalField',
+    LinesToStr([ // statements
+    'rtl.recNewT($mod, "TCar", function () {',
+    '  this.$eq = function (b) {',
+    '    return (this.$Intern === b.$Intern) && (this.$Intern2 === b.$Intern2) && (this["A B"] === b["A B"]);',
+    '  };',
+    '  this.$assign = function (s) {',
+    '    this.$Intern = s.$Intern;',
+    '    this.$Intern2 = s.$Intern2;',
+    '    this["A B"] = s["A B"];',
+    '    return this;',
+    '  };',
+    '  this.DoIt = function () {',
+    '    this.$Intern = this.$Intern + 1;',
+    '    this.$Intern2 = this.$Intern2 + 2;',
+    '    this["A B"] = this["A B"] + 3;',
+    '  };',
+    '});',
+    'this.Rec = $mod.TCar.$clone({',
+    '  $Intern: 11,',
+    '  $Intern2: 12,',
+    '  "A B": 13',
+    '});',
+    '']),
+    LinesToStr([ // $mod.$main
+    '$mod.Rec.$Intern = $mod.Rec.$Intern + 1;',
+    '$mod.Rec.$Intern2 = $mod.Rec.$Intern2 + 2;',
+    '$mod.Rec["A B"] = $mod.Rec["A B"] + 3;',
+    'var $with1 = $mod.Rec;',
+    '$with1.$Intern = $with1.$Intern + 1;',
+    '$with1.$Intern2 = $with1.$Intern2 + 2;',
+    '$with1["A B"] = $with1["A B"] + 3;',
+    '']));
+end;
+
 procedure TTestModule.TestAdvRecord_SubRecord;
 procedure TTestModule.TestAdvRecord_SubRecord;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
@@ -10331,10 +10646,10 @@ begin
     '      return this;',
     '      return this;',
     '    };',
     '    };',
     '    this.DoIt = function () {',
     '    this.DoIt = function () {',
-    '      this.$record.Count = this.Count + 3;',
+    '      $mod.TRec.TPoint.Count = this.Count + 3;',
     '    };',
     '    };',
     '    this.DoThat = function () {',
     '    this.DoThat = function () {',
-    '      this.Count = this.Count + 4;',
+    '      $mod.TRec.TPoint.Count = this.Count + 4;',
     '    };',
     '    };',
     '  }, true);',
     '  }, true);',
     '  this.i = 0;',
     '  this.i = 0;',
@@ -10353,7 +10668,7 @@ begin
     '  };',
     '  };',
     '  this.DoSome = function () {',
     '  this.DoSome = function () {',
     '    this.p.x = this.p.y + 1;',
     '    this.p.x = this.p.y + 1;',
-    '    this.p.$record.Count = this.p.Count + 2;',
+    '    this.TPoint.Count = this.p.Count + 2;',
     '  };',
     '  };',
     '}, true);',
     '}, true);',
     'this.r = $mod.TRec.$clone({',
     'this.r = $mod.TRec.$clone({',
@@ -11436,6 +11751,8 @@ begin
   '    class var Fy: longint;',
   '    class var Fy: longint;',
   '    class function GetInt: longint;',
   '    class function GetInt: longint;',
   '    class procedure SetInt(Value: longint);',
   '    class procedure SetInt(Value: longint);',
+  '  end;',
+  '  TBird = class',
   '    class procedure DoIt;',
   '    class procedure DoIt;',
   '    class property IntA: longint read Fx write Fy;',
   '    class property IntA: longint read Fx write Fy;',
   '    class property IntB: longint read GetInt write SetInt;',
   '    class property IntB: longint read GetInt write SetInt;',
@@ -11447,23 +11764,41 @@ begin
   'class procedure tobject.setint(value: longint);',
   'class procedure tobject.setint(value: longint);',
   'begin',
   'begin',
   'end;',
   'end;',
-  'class procedure tobject.doit;',
+  'class procedure tbird.doit;',
   'begin',
   'begin',
+  '  FX:=3;',
   '  IntA:=IntA+1;',
   '  IntA:=IntA+1;',
   '  Self.IntA:=Self.IntA+1;',
   '  Self.IntA:=Self.IntA+1;',
   '  IntB:=IntB+1;',
   '  IntB:=IntB+1;',
   '  Self.IntB:=Self.IntB+1;',
   '  Self.IntB:=Self.IntB+1;',
+  '  with Self do begin',
+  '    FX:=11;',
+  '    IntA:=IntA+12;',
+  '    IntB:=IntB+13;',
+  '  end;',
   'end;',
   'end;',
-  'var Obj: tobject;',
+  'var Obj: tbird;',
   'begin',
   'begin',
-  '  tobject.inta:=tobject.inta+1;',
-  '  if tobject.intb=2 then;',
-  '  tobject.intb:=tobject.intb+2;',
-  '  tobject.setint(tobject.inta);',
+  '  tbird.fx:=tbird.fx+1;',
+  '  tbird.inta:=tbird.inta+1;',
+  '  if tbird.intb=2 then;',
+  '  tbird.intb:=tbird.intb+2;',
+  '  tbird.setint(tbird.inta);',
   '  obj.inta:=obj.inta+1;',
   '  obj.inta:=obj.inta+1;',
   '  if obj.intb=2 then;',
   '  if obj.intb=2 then;',
   '  obj.intb:=obj.intb+2;',
   '  obj.intb:=obj.intb+2;',
-  '  obj.setint(obj.inta);']);
+  '  obj.setint(obj.inta);',
+  '  with Tbird do begin',
+  '    FX:=FY+1;',
+  '    inta:=inta+2;',
+  '    intb:=intb+3;',
+  '  end;',
+  '  with Obj do begin',
+  '    FX:=FY+1;',
+  '    inta:=inta+2;',
+  '    intb:=intb+3;',
+  '  end;',
+  '']);
   ConvertProgram;
   ConvertProgram;
   CheckSource('TestClass_Property_ClassMethod',
   CheckSource('TestClass_Property_ClassMethod',
     LinesToStr([ // statements
     LinesToStr([ // statements
@@ -11481,25 +11816,40 @@ begin
     '  };',
     '  };',
     '  this.SetInt = function (Value) {',
     '  this.SetInt = function (Value) {',
     '  };',
     '  };',
+    '});',
+    'rtl.createClass($mod, "TBird", $mod.TObject, function () {',
     '  this.DoIt = function () {',
     '  this.DoIt = function () {',
-    '    this.Fy = this.Fx + 1;',
-    '    this.Fy = this.Fx + 1;',
+    '    $mod.TObject.Fx = 3;',
+    '    $mod.TObject.Fy = this.Fx + 1;',
+    '    $mod.TObject.Fy = this.Fx + 1;',
     '    this.SetInt(this.GetInt() + 1);',
     '    this.SetInt(this.GetInt() + 1);',
     '    this.SetInt(this.GetInt() + 1);',
     '    this.SetInt(this.GetInt() + 1);',
+    '    $mod.TObject.Fx = 11;',
+    '    $mod.TObject.Fy = this.Fx + 12;',
+    '    this.SetInt(this.GetInt() + 13);',
     '  };',
     '  };',
     '});',
     '});',
     'this.Obj = null;'
     'this.Obj = null;'
     ]),
     ]),
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main
-    '$mod.TObject.Fy = $mod.TObject.Fx + 1;',
-    'if ($mod.TObject.GetInt() === 2);',
-    '$mod.TObject.SetInt($mod.TObject.GetInt() + 2);',
-    '$mod.TObject.SetInt($mod.TObject.Fx);',
-    '$mod.Obj.$class.Fy = $mod.Obj.Fx + 1;',
+    '$mod.TObject.Fx = $mod.TBird.Fx + 1;',
+    '$mod.TObject.Fy = $mod.TBird.Fx + 1;',
+    'if ($mod.TBird.GetInt() === 2);',
+    '$mod.TBird.SetInt($mod.TBird.GetInt() + 2);',
+    '$mod.TBird.SetInt($mod.TBird.Fx);',
+    '$mod.TObject.Fy = $mod.Obj.Fx + 1;',
     'if ($mod.Obj.$class.GetInt() === 2);',
     'if ($mod.Obj.$class.GetInt() === 2);',
     '$mod.Obj.$class.SetInt($mod.Obj.$class.GetInt() + 2);',
     '$mod.Obj.$class.SetInt($mod.Obj.$class.GetInt() + 2);',
-    '$mod.Obj.$class.SetInt($mod.Obj.Fx);'
-    ]));
+    '$mod.Obj.$class.SetInt($mod.Obj.Fx);',
+    'var $with1 = $mod.TBird;',
+    '$mod.TObject.Fx = $with1.Fy + 1;',
+    '$mod.TObject.Fy = $with1.Fx + 2;',
+    '$with1.SetInt($with1.GetInt() + 3);',
+    'var $with2 = $mod.Obj;',
+    '$mod.TObject.Fx = $with2.Fy + 1;',
+    '$mod.TObject.Fy = $with2.Fx + 2;',
+    '$with2.SetInt($with2.GetInt() + 3);',
+    '']));
 end;
 end;
 
 
 procedure TTestModule.TestClass_Property_Indexed;
 procedure TTestModule.TestClass_Property_Indexed;
@@ -11759,9 +12109,9 @@ begin
   'type',
   'type',
   '  TObject = class end;',
   '  TObject = class end;',
   '  TAlphaList = class',
   '  TAlphaList = class',
-  '    function GetAlphas(Index: longint): Pointer; virtual; abstract;',
-  '    procedure SetAlphas(Index: longint; Value: Pointer); virtual; abstract;',
-  '    property Alphas[Index: longint]: Pointer read getAlphas write setAlphas; default;',
+  '    function GetAlphas(Index: boolean): Pointer; virtual; abstract;',
+  '    procedure SetAlphas(Index: boolean; Value: Pointer); virtual; abstract;',
+  '    property Alphas[Index: boolean]: Pointer read getAlphas write setAlphas; default;',
   '  end;',
   '  end;',
   '  TBetaList = class',
   '  TBetaList = class',
   '    function GetBetas(Index: longint): Pointer; virtual; abstract;',
   '    function GetBetas(Index: longint): Pointer; virtual; abstract;',
@@ -11775,14 +12125,14 @@ begin
   'var',
   'var',
   '  List: TAlphaList;',
   '  List: TAlphaList;',
   'begin',
   'begin',
-  '  if TBetaList(List[2])[3]=nil then ;',
-  '  TBetaList(List[4])[5]:=nil;',
+  '  if TBetaList(List[true])[3]=nil then ;',
+  '  TBetaList(List[false])[5]:=nil;',
   'end;',
   'end;',
   'var',
   'var',
   '  List: TAlphaList;',
   '  List: TAlphaList;',
   'begin',
   'begin',
-  '  if TBetaList(List[2])[3]=nil then ;',
-  '  TBetaList(List[4])[5]:=nil;',
+  '  if TBetaList(List[true])[3]=nil then ;',
+  '  TBetaList(List[false])[5]:=nil;',
   '']);
   '']);
   ConvertProgram;
   ConvertProgram;
   CheckSource('TestClass_PropertyDefault2',
   CheckSource('TestClass_PropertyDefault2',
@@ -11800,15 +12150,15 @@ begin
     'rtl.createClass($mod, "TBird", $mod.TObject, function () {',
     'rtl.createClass($mod, "TBird", $mod.TObject, function () {',
     '  this.DoIt = function () {',
     '  this.DoIt = function () {',
     '    var List = null;',
     '    var List = null;',
-    '    if (List.GetAlphas(2).GetBetas(3) === null) ;',
-    '    List.GetAlphas(4).SetBetas(5, null);',
+    '    if (List.GetAlphas(true).GetBetas(3) === null) ;',
+    '    List.GetAlphas(false).SetBetas(5, null);',
     '  };',
     '  };',
     '});',
     '});',
     'this.List = null;',
     'this.List = null;',
     '']),
     '']),
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main
-    'if ($mod.List.GetAlphas(2).GetBetas(3) === null) ;',
-    '$mod.List.GetAlphas(4).SetBetas(5, null);',
+    'if ($mod.List.GetAlphas(true).GetBetas(3) === null) ;',
+    '$mod.List.GetAlphas(false).SetBetas(5, null);',
     '']));
     '']));
 end;
 end;
 
 
@@ -13780,37 +14130,39 @@ end;
 procedure TTestModule.TestClassOf_ClassProperty;
 procedure TTestModule.TestClassOf_ClassProperty;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
-  Add('type');
-  Add('  TObject = class');
-  Add('    class var FA: longint;');
-  Add('    class function GetA: longint;');
-  Add('    class procedure SetA(Value: longint);');
-  Add('    class property pA: longint read fa write fa;');
-  Add('    class property pB: longint read geta write seta;');
-  Add('  end;');
-  Add('  TObjectClass = class of tobject;');
-  Add('class function tobject.geta: longint; begin end;');
-  Add('class procedure tobject.seta(value: longint); begin end;');
-  Add('var');
-  Add('  b: boolean;');
-  Add('  Obj: tobject;');
-  Add('  Cla: tobjectclass;');
-  Add('begin');
-  Add('  obj.pa:=obj.pa;');
-  Add('  obj.pb:=obj.pb;');
-  Add('  b:=obj.pa=4;');
-  Add('  b:=obj.pb=obj.pb;');
-  Add('  b:=5=obj.pa;');
-  Add('  cla.pa:=6;');
-  Add('  cla.pa:=cla.pa;');
-  Add('  cla.pb:=cla.pb;');
-  Add('  b:=cla.pa=7;');
-  Add('  b:=cla.pb=cla.pb;');
-  Add('  b:=8=cla.pa;');
-  Add('  tobject.pa:=9;');
-  Add('  tobject.pb:=tobject.pb;');
-  Add('  b:=tobject.pa=10;');
-  Add('  b:=11=tobject.pa;');
+  Add([
+  'type',
+  '  TObject = class',
+  '    class var FA: longint;',
+  '    class function GetA: longint;',
+  '    class procedure SetA(Value: longint);',
+  '    class property pA: longint read fa write fa;',
+  '    class property pB: longint read geta write seta;',
+  '  end;',
+  '  TObjectClass = class of tobject;',
+  'class function tobject.geta: longint; begin end;',
+  'class procedure tobject.seta(value: longint); begin end;',
+  'var',
+  '  b: boolean;',
+  '  Obj: tobject;',
+  '  Cla: tobjectclass;',
+  'begin',
+  '  obj.pa:=obj.pa;',
+  '  obj.pb:=obj.pb;',
+  '  b:=obj.pa=4;',
+  '  b:=obj.pb=obj.pb;',
+  '  b:=5=obj.pa;',
+  '  cla.pa:=6;',
+  '  cla.pa:=cla.pa;',
+  '  cla.pb:=cla.pb;',
+  '  b:=cla.pa=7;',
+  '  b:=cla.pb=cla.pb;',
+  '  b:=8=cla.pa;',
+  '  tobject.pa:=9;',
+  '  tobject.pb:=tobject.pb;',
+  '  b:=tobject.pa=10;',
+  '  b:=11=tobject.pa;',
+  '']);
   ConvertProgram;
   ConvertProgram;
   CheckSource('TestClassOf_ClassProperty',
   CheckSource('TestClassOf_ClassProperty',
     LinesToStr([ // statements
     LinesToStr([ // statements
@@ -13832,13 +14184,13 @@ begin
     'this.Cla = null;'
     'this.Cla = null;'
     ]),
     ]),
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main
-    '$mod.Obj.$class.FA = $mod.Obj.FA;',
+    '$mod.TObject.FA = $mod.Obj.FA;',
     '$mod.Obj.$class.SetA($mod.Obj.$class.GetA());',
     '$mod.Obj.$class.SetA($mod.Obj.$class.GetA());',
     '$mod.b = $mod.Obj.FA === 4;',
     '$mod.b = $mod.Obj.FA === 4;',
     '$mod.b = $mod.Obj.$class.GetA() === $mod.Obj.$class.GetA();',
     '$mod.b = $mod.Obj.$class.GetA() === $mod.Obj.$class.GetA();',
     '$mod.b = 5 === $mod.Obj.FA;',
     '$mod.b = 5 === $mod.Obj.FA;',
-    '$mod.Cla.FA = 6;',
-    '$mod.Cla.FA = $mod.Cla.FA;',
+    '$mod.TObject.FA = 6;',
+    '$mod.TObject.FA = $mod.Cla.FA;',
     '$mod.Cla.SetA($mod.Cla.GetA());',
     '$mod.Cla.SetA($mod.Cla.GetA());',
     '$mod.b = $mod.Cla.FA === 7;',
     '$mod.b = $mod.Cla.FA === 7;',
     '$mod.b = $mod.Cla.GetA() === $mod.Cla.GetA();',
     '$mod.b = $mod.Cla.GetA() === $mod.Cla.GetA();',
@@ -16144,7 +16496,7 @@ begin
   '  end;',
   '  end;',
   'begin']);
   'begin']);
   SetExpectedParserError(
   SetExpectedParserError(
-    'Fields are not allowed in Interfaces at token "Identifier external" in file test1.pp at line 6 column 21',
+    'Fields are not allowed in interface at token "Identifier external" in file test1.pp at line 6 column 21',
     nParserNoFieldsAllowed);
     nParserNoFieldsAllowed);
   ConvertProgram;
   ConvertProgram;
 end;
 end;
@@ -18192,6 +18544,102 @@ begin
     '']));
     '']));
 end;
 end;
 
 
+procedure TTestModule.TestClassHelper_ClassVar;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class',
+  '  end;',
+  '  THelper = class helper for TObject',
+  '  const',
+  '    One = 1;',
+  '    Two: word = 2;',
+  '  class var Glob: word;',
+  '  function Foo(w: word): word;',
+  '  class function Bar(w: word): word;',
+  '  end;',
+  'function THelper.foo(w: word): word;',
+  'begin',
+  '  Result:=w;',
+  '  Two:=One+w;',
+  '  Glob:=Glob;',
+  '  Result:=Self.Glob;',
+  '  Self.Glob:=Self.Glob;',
+  '  with Self do Glob:=Glob;',
+  'end;',
+  'class function THelper.bar(w: word): word;',
+  'begin',
+  '  Result:=w;',
+  '  Two:=One;',
+  '  Glob:=Glob;',
+  '  Self.Glob:=Self.Glob;',
+  '  with Self do Glob:=Glob;',
+  'end;',
+  'var o: TObject;',
+  'begin',
+  '  tobject.two:=tobject.one;',
+  '  tobject.Glob:=tobject.Glob;',
+  '  with tobject do begin',
+  '    two:=one;',
+  '    Glob:=Glob;',
+  '  end;',
+  '  o.two:=o.one;',
+  '  o.Glob:=o.Glob;',
+  '  with o do begin',
+  '    two:=one;',
+  '    Glob:=Glob;',
+  '  end;',
+  '']);
+  ConvertProgram;
+  CheckSource('TestClassHelper',
+    LinesToStr([ // statements
+    'rtl.createClass($mod, "TObject", null, function () {',
+    '  this.$init = function () {',
+    '  };',
+    '  this.$final = function () {',
+    '  };',
+    '});',
+    'rtl.createHelper($mod, "THelper", null, function () {',
+    '  this.One = 1;',
+    '  this.Two = 2;',
+    '  this.Glob = 0;',
+    '  this.Foo = function (w) {',
+    '    var Result = 0;',
+    '    Result = w;',
+    '    $mod.THelper.Two = 1 + w;',
+    '    $mod.THelper.Glob = $mod.THelper.Glob;',
+    '    Result = $mod.THelper.Glob;',
+    '    $mod.THelper.Glob = $mod.THelper.Glob;',
+    '    $mod.THelper.Glob = $mod.THelper.Glob;',
+    '    return Result;',
+    '  };',
+    '  this.Bar = function (w) {',
+    '    var Result = 0;',
+    '    Result = w;',
+    '    $mod.THelper.Two = 1;',
+    '    $mod.THelper.Glob = $mod.THelper.Glob;',
+    '    $mod.THelper.Glob = $mod.THelper.Glob;',
+    '    $mod.THelper.Glob = $mod.THelper.Glob;',
+    '    return Result;',
+    '  };',
+    '});',
+    'this.o = null;',
+    '']),
+    LinesToStr([ // $mod.$main
+    '$mod.THelper.Two = 1;',
+    '$mod.THelper.Glob = $mod.THelper.Glob;',
+    'var $with1 = $mod.TObject;',
+    '$mod.THelper.Two = 1;',
+    '$mod.THelper.Glob = $mod.THelper.Glob;',
+    '$mod.THelper.Two = 1;',
+    '$mod.THelper.Glob = $mod.THelper.Glob;',
+    'var $with2 = $mod.o;',
+    '$mod.THelper.Two = 1;',
+    '$mod.THelper.Glob = $mod.THelper.Glob;',
+    '']));
+end;
+
 procedure TTestModule.TestProcType;
 procedure TTestModule.TestProcType;
 begin
 begin
   StartProgram(false);
   StartProgram(false);

+ 62 - 0
packages/pastojs/tests/tcunitsearch.pas

@@ -135,6 +135,8 @@ type
 
 
   TTestCLI_UnitSearch = class(TCustomTestCLI)
   TTestCLI_UnitSearch = class(TCustomTestCLI)
   published
   published
+    procedure TestUS_CreateRelativePath;
+
     procedure TestUS_Program;
     procedure TestUS_Program;
     procedure TestUS_UsesEmptyFileFail;
     procedure TestUS_UsesEmptyFileFail;
     procedure TestUS_Program_o;
     procedure TestUS_Program_o;
@@ -145,6 +147,7 @@ type
     procedure TestUS_UsesInFile;
     procedure TestUS_UsesInFile;
     procedure TestUS_UsesInFile_Duplicate;
     procedure TestUS_UsesInFile_Duplicate;
     procedure TestUS_UsesInFile_IndirectDuplicate;
     procedure TestUS_UsesInFile_IndirectDuplicate;
+    procedure TestUS_UsesInFile_WorkNotEqProgDir;
   end;
   end;
 
 
 function LinesToStr(const Lines: array of string): string;
 function LinesToStr(const Lines: array of string): string;
@@ -584,6 +587,49 @@ end;
 
 
 { TTestCLI_UnitSearch }
 { TTestCLI_UnitSearch }
 
 
+procedure TTestCLI_UnitSearch.TestUS_CreateRelativePath;
+
+  procedure DoTest(Filename, BaseDirectory, Expected: string;
+    UsePointDirectory: boolean = false);
+  var
+    Actual: String;
+  begin
+    ForcePathDelims(Filename);
+    ForcePathDelims(BaseDirectory);
+    ForcePathDelims(Expected);
+    if not TryCreateRelativePath(Filename,BaseDirectory,UsePointDirectory,true,Actual) then
+      Actual:=Filename;
+    AssertEquals('TryCreateRelativePath(File='+Filename+',Base='+BaseDirectory+')',
+      Expected,Actual);
+  end;
+
+begin
+  DoTest('/a','/a','');
+  DoTest('/a','/a','.',true);
+  DoTest('/a','/a/','');
+  DoTest('/a/b','/a/b','');
+  DoTest('/a/b','/a/b/','');
+  DoTest('/a','/a/','');
+  DoTest('/a','','/a');
+  DoTest('/a/b','/a','b');
+  DoTest('/a/b','/a/','b');
+  DoTest('/a/b','/a//','b');
+  DoTest('/a','/a/b','..');
+  DoTest('/a','/a/b/','..');
+  DoTest('/a','/a/b//','..');
+  DoTest('/a/','/a/b','..');
+  DoTest('/a','/a/b/c','../..');
+  DoTest('/a','/a/b//c','../..');
+  DoTest('/a','/a//b/c','../..');
+  DoTest('/a','/a//b/c/','../..');
+  DoTest('/a','/b','/a');
+  DoTest('~/bin','/','~/bin');
+  DoTest('$(HOME)/bin','/','$(HOME)/bin');
+  {$IFDEF MSWindows}
+  DoTest('D:\a\b\c.pas','D:\a\d\','..\b\c.pas');
+  {$ENDIF}
+end;
+
 procedure TTestCLI_UnitSearch.TestUS_Program;
 procedure TTestCLI_UnitSearch.TestUS_Program;
 begin
 begin
   AddUnit('system.pp',[''],['']);
   AddUnit('system.pp',[''],['']);
@@ -707,6 +753,22 @@ begin
   AssertEquals('ErrorMsg','Duplicate file found: "'+WorkDir+'unit1.pas" and "'+WorkDir+'sub/unit1.pas"',ErrorMsg);
   AssertEquals('ErrorMsg','Duplicate file found: "'+WorkDir+'unit1.pas" and "'+WorkDir+'sub/unit1.pas"',ErrorMsg);
 end;
 end;
 
 
+procedure TTestCLI_UnitSearch.TestUS_UsesInFile_WorkNotEqProgDir;
+begin
+  AddUnit('system.pp',[''],['']);
+  AddUnit('sub/unit2.pas',
+  ['var a: longint;'],
+  ['']);
+  AddUnit('sub/unit1.pas',
+  ['uses unit2;'],
+  ['']);
+  AddFile('sub/test1.pas',[
+    'uses foo in ''unit1.pas'';',
+    'begin',
+    'end.']);
+  Compile(['sub/test1.pas','-Jc']);
+end;
+
 Initialization
 Initialization
   RegisterTests([TTestCLI_UnitSearch]);
   RegisterTests([TTestCLI_UnitSearch]);
 end.
 end.

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff