Explorar o código

* synchronize with trunk

git-svn-id: branches/wasm@47877 -
nickysn %!s(int64=4) %!d(string=hai) anos
pai
achega
96de6c4b96
Modificáronse 80 ficheiros con 3272 adicións e 1781 borrados
  1. 12 1
      .gitattributes
  2. 10 8
      compiler/aarch64/ncpumat.pas
  3. 20 1
      compiler/defutil.pas
  4. 6 0
      compiler/dirparse.pas
  5. 4 0
      compiler/i386/aoptcpu.pas
  6. 4 2
      compiler/i386/cpuinfo.pas
  7. 4 4
      compiler/i386/i386prop.inc
  8. 4 4
      compiler/i8086/i8086prop.inc
  9. 4 2
      compiler/m68k/aoptcpu.pas
  10. 4 3
      compiler/m68k/cpuinfo.pas
  11. 2 2
      compiler/ncnv.pas
  12. 48 4
      compiler/nflw.pas
  13. 70 27
      compiler/ninl.pas
  14. 27 1
      compiler/nld.pas
  15. 21 8
      compiler/nmat.pas
  16. 32 74
      compiler/nutils.pas
  17. 2 1
      compiler/optdfa.pas
  18. 1 5
      compiler/pdecsub.pas
  19. 13 7
      compiler/psub.pas
  20. 13 3
      compiler/ptype.pas
  21. 1 1
      compiler/sparcgen/cgsparc.pas
  22. 10 0
      compiler/symbase.pas
  23. 2 2
      compiler/symcreat.pas
  24. 38 32
      compiler/symdef.pas
  25. 3 3
      compiler/symsym.pas
  26. 107 78
      compiler/symtable.pas
  27. 345 103
      compiler/x86/aoptx86.pas
  28. 1 2
      compiler/x86/cpubase.pas
  29. 25 9
      compiler/x86/nx86inl.pas
  30. 1 3
      compiler/x86/nx86mat.pas
  31. 2 0
      compiler/x86/rax86att.pas
  32. 4 4
      compiler/x86/x86ins.dat
  33. 4 0
      compiler/x86_64/aoptcpu.pas
  34. 4 2
      compiler/x86_64/cpuinfo.pas
  35. 4 4
      compiler/x86_64/x8664pro.inc
  36. 38 6
      compiler/xtensa/cgcpu.pas
  37. 8 0
      packages/chm/src/itsftransform.pas
  38. 3 4
      packages/fcl-js/src/jswriter.pp
  39. 263 91
      packages/fcl-passrc/src/pasresolveeval.pas
  40. 72 37
      packages/fcl-passrc/src/pasresolver.pp
  41. 1 1
      packages/fcl-passrc/src/paswrite.pp
  42. 28 0
      packages/fcl-passrc/tests/tcresolvegenerics.pas
  43. 5 5
      packages/fcl-passrc/tests/tcresolver.pas
  44. 866 768
      packages/fcl-res/src/rclex.inc
  45. 2 0
      packages/fcl-res/src/rclex.l
  46. 396 345
      packages/fcl-res/src/rcparser.pas
  47. 16 3
      packages/fcl-res/src/rcparser.y
  48. 3 3
      packages/hash/src/sha1.pp
  49. 7 5
      packages/pastojs/src/fppas2js.pp
  50. 7 1
      packages/pastojs/src/pas2jsfilecache.pp
  51. 126 1
      packages/pastojs/tests/tcmodules.pas
  52. 2 2
      rtl/darwin/aarch64/sighnd.inc
  53. 5 1
      rtl/freertos/xtensa/esp8266.pp
  54. 33 4
      rtl/i386/cpu.pp
  55. 5 5
      rtl/inc/currh.inc
  56. 32 16
      rtl/inc/gencurr.inc
  57. 8 2
      rtl/inc/genmath.inc
  58. 24 24
      rtl/objpas/sysutils/dati.inc
  59. 12 2
      rtl/win/sysutils.pp
  60. 2 2
      rtl/win/wininc/redef.inc
  61. 9 1
      rtl/x86_64/cpu.pp
  62. 8 0
      tests/tbf/tb0273.pp
  63. 23 0
      tests/tbs/tb0681.pp
  64. 17 0
      tests/tbs/tb0682.pp
  65. 22 0
      tests/tbs/tb0683.pp
  66. 31 21
      tests/test/tcas128.pp
  67. 24 0
      tests/test/texception4.pp
  68. 23 0
      tests/test/tgeneric106.pp
  69. 23 0
      tests/test/tgeneric107.pp
  70. 4 4
      tests/test/tminmax.pp
  71. 6 6
      tests/test/tprec8.pp
  72. 42 1
      tests/test/units/linux/tstatx.pp
  73. 78 0
      tests/test/units/math/trndcurr.pp
  74. 13 0
      tests/webtbs/tw38164.pp
  75. 37 0
      tests/webtbs/tw38225.pp
  76. 56 0
      tests/webtbs/tw38238.pp
  77. 9 0
      tests/webtbs/tw38249.pp
  78. 23 11
      utils/fpdoc/dw_chm.pp
  79. 6 9
      utils/fpdoc/dw_html.pp
  80. 2 0
      utils/fpdoc/fpdoc.pp

+ 12 - 1
.gitattributes

@@ -12774,6 +12774,7 @@ tests/tbf/tb0269.pp svneol=native#text/pascal
 tests/tbf/tb0270.pp svneol=native#text/pascal
 tests/tbf/tb0270.pp svneol=native#text/pascal
 tests/tbf/tb0271.pp svneol=native#text/pascal
 tests/tbf/tb0271.pp svneol=native#text/pascal
 tests/tbf/tb0272.pp svneol=native#text/plain
 tests/tbf/tb0272.pp svneol=native#text/plain
+tests/tbf/tb0273.pp svneol=native#text/pascal
 tests/tbf/tb0588.pp svneol=native#text/pascal
 tests/tbf/tb0588.pp svneol=native#text/pascal
 tests/tbf/ub0115.pp svneol=native#text/plain
 tests/tbf/ub0115.pp svneol=native#text/plain
 tests/tbf/ub0149.pp svneol=native#text/plain
 tests/tbf/ub0149.pp svneol=native#text/plain
@@ -13472,6 +13473,9 @@ tests/tbs/tb0677.pp svneol=native#text/pascal
 tests/tbs/tb0678.pp svneol=native#text/pascal
 tests/tbs/tb0678.pp svneol=native#text/pascal
 tests/tbs/tb0679.pp svneol=native#text/pascal
 tests/tbs/tb0679.pp svneol=native#text/pascal
 tests/tbs/tb0680.pp svneol=native#text/pascal
 tests/tbs/tb0680.pp svneol=native#text/pascal
+tests/tbs/tb0681.pp svneol=native#text/pascal
+tests/tbs/tb0682.pp svneol=native#text/pascal
+tests/tbs/tb0683.pp svneol=native#text/plain
 tests/tbs/ub0060.pp svneol=native#text/plain
 tests/tbs/ub0060.pp svneol=native#text/plain
 tests/tbs/ub0069.pp svneol=native#text/plain
 tests/tbs/ub0069.pp svneol=native#text/plain
 tests/tbs/ub0119.pp svneol=native#text/plain
 tests/tbs/ub0119.pp svneol=native#text/plain
@@ -15101,6 +15105,8 @@ tests/test/tgeneric102.pp svneol=native#text/pascal
 tests/test/tgeneric103.pp svneol=native#text/pascal
 tests/test/tgeneric103.pp svneol=native#text/pascal
 tests/test/tgeneric104.pp -text svneol=native#text/pascal
 tests/test/tgeneric104.pp -text svneol=native#text/pascal
 tests/test/tgeneric105.pp svneol=native#text/pascal
 tests/test/tgeneric105.pp svneol=native#text/pascal
+tests/test/tgeneric106.pp svneol=native#text/pascal
+tests/test/tgeneric107.pp svneol=native#text/pascal
 tests/test/tgeneric11.pp svneol=native#text/plain
 tests/test/tgeneric11.pp svneol=native#text/plain
 tests/test/tgeneric12.pp svneol=native#text/plain
 tests/test/tgeneric12.pp svneol=native#text/plain
 tests/test/tgeneric13.pp svneol=native#text/plain
 tests/test/tgeneric13.pp svneol=native#text/plain
@@ -16145,6 +16151,7 @@ tests/test/units/math/tmask2.pp svneol=native#text/plain
 tests/test/units/math/tminmaxconst.pp svneol=native#text/pascal
 tests/test/units/math/tminmaxconst.pp svneol=native#text/pascal
 tests/test/units/math/tnaninf.pp svneol=native#text/plain
 tests/test/units/math/tnaninf.pp svneol=native#text/plain
 tests/test/units/math/tpower.pp svneol=native#text/pascal
 tests/test/units/math/tpower.pp svneol=native#text/pascal
+tests/test/units/math/trndcurr.pp svneol=native#text/plain
 tests/test/units/math/troundm.pp svneol=native#text/plain
 tests/test/units/math/troundm.pp svneol=native#text/plain
 tests/test/units/math/tsincos.pp svneol=native#text/pascal
 tests/test/units/math/tsincos.pp svneol=native#text/pascal
 tests/test/units/math/ttrig1.pp svneol=native#text/plain
 tests/test/units/math/ttrig1.pp svneol=native#text/plain
@@ -18644,8 +18651,12 @@ tests/webtbs/tw3814.pp svneol=native#text/plain
 tests/webtbs/tw38145a.pp svneol=native#text/pascal
 tests/webtbs/tw38145a.pp svneol=native#text/pascal
 tests/webtbs/tw38145b.pp svneol=native#text/pascal
 tests/webtbs/tw38145b.pp svneol=native#text/pascal
 tests/webtbs/tw38151.pp svneol=native#text/pascal
 tests/webtbs/tw38151.pp svneol=native#text/pascal
+tests/webtbs/tw38164.pp svneol=native#text/pascal
 tests/webtbs/tw38201.pp svneol=native#text/pascal
 tests/webtbs/tw38201.pp svneol=native#text/pascal
 tests/webtbs/tw38202.pp svneol=native#text/pascal
 tests/webtbs/tw38202.pp svneol=native#text/pascal
+tests/webtbs/tw38225.pp svneol=native#text/pascal
+tests/webtbs/tw38238.pp svneol=native#text/pascal
+tests/webtbs/tw38249.pp svneol=native#text/pascal
 tests/webtbs/tw3827.pp svneol=native#text/plain
 tests/webtbs/tw3827.pp svneol=native#text/plain
 tests/webtbs/tw3829.pp svneol=native#text/plain
 tests/webtbs/tw3829.pp svneol=native#text/plain
 tests/webtbs/tw3833.pp svneol=native#text/plain
 tests/webtbs/tw3833.pp svneol=native#text/plain
@@ -19314,9 +19325,9 @@ utils/fpdoc/Makefile.fpc.fpcmake svneol=native#text/plain
 utils/fpdoc/README.txt svneol=native#text/plain
 utils/fpdoc/README.txt svneol=native#text/plain
 utils/fpdoc/css.inc svneol=native#text/plain
 utils/fpdoc/css.inc svneol=native#text/plain
 utils/fpdoc/dglobals.pp svneol=native#text/plain
 utils/fpdoc/dglobals.pp svneol=native#text/plain
+utils/fpdoc/dw_chm.pp svneol=native#text/plain
 utils/fpdoc/dw_dxml.pp svneol=native#text/plain
 utils/fpdoc/dw_dxml.pp svneol=native#text/plain
 utils/fpdoc/dw_html.pp svneol=native#text/plain
 utils/fpdoc/dw_html.pp svneol=native#text/plain
-utils/fpdoc/dw_htmlchm.inc svneol=native#text/plain
 utils/fpdoc/dw_ipflin.pas svneol=native#text/plain
 utils/fpdoc/dw_ipflin.pas svneol=native#text/plain
 utils/fpdoc/dw_latex.pp svneol=native#text/plain
 utils/fpdoc/dw_latex.pp svneol=native#text/plain
 utils/fpdoc/dw_linrtf.pp svneol=native#text/plain
 utils/fpdoc/dw_linrtf.pp svneol=native#text/plain

+ 10 - 8
compiler/aarch64/ncpumat.pas

@@ -82,11 +82,13 @@ implementation
          var
          var
            helper1, helper2: TRegister;
            helper1, helper2: TRegister;
            so: tshifterop;
            so: tshifterop;
+           opsize: TCgSize;
          begin
          begin
+           opsize:=def_cgsize(resultdef);
            if tordconstnode(right).value=0 then
            if tordconstnode(right).value=0 then
              internalerror(2020021601)
              internalerror(2020021601)
            else if tordconstnode(right).value=1 then
            else if tordconstnode(right).value=1 then
-             cg.a_load_reg_reg(current_asmdata.CurrAsmList, OS_INT, OS_INT, numerator, resultreg)
+             cg.a_load_reg_reg(current_asmdata.CurrAsmList, opsize, opsize, numerator, resultreg)
            else if (tordconstnode(right).value = int64(-1)) then
            else if (tordconstnode(right).value = int64(-1)) then
              begin
              begin
                // note: only in the signed case possible..., may overflow
                // note: only in the signed case possible..., may overflow
@@ -100,26 +102,26 @@ implementation
              begin
              begin
                if (is_signed(right.resultdef)) then
                if (is_signed(right.resultdef)) then
                  begin
                  begin
-                    helper2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+                    helper2:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
                     if power = 1 then
                     if power = 1 then
                       helper1:=numerator
                       helper1:=numerator
                     else
                     else
                       begin
                       begin
-                        helper1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
-                        cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SAR,OS_INT,63,numerator,helper1);
+                        helper1:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+                        cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SAR,opsize,resultdef.size*8-1,numerator,helper1);
                       end;
                       end;
                     shifterop_reset(so);
                     shifterop_reset(so);
                     so.shiftmode:=SM_LSR;
                     so.shiftmode:=SM_LSR;
-                    so.shiftimm:=64-power;
+                    so.shiftimm:=resultdef.size*8-power;
                     current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_shifterop(A_ADD,helper2,numerator,helper1,so));
                     current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_shifterop(A_ADD,helper2,numerator,helper1,so));
-                    cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SAR,OS_INT,power,helper2,resultreg);
+                    cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SAR,def_cgsize(resultdef),power,helper2,resultreg);
                   end
                   end
                else
                else
-                 cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,power,numerator,resultreg)
+                 cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,opsize,power,numerator,resultreg)
              end
              end
            else
            else
              { Everything else is handled in the generic code }
              { Everything else is handled in the generic code }
-             cg.g_div_const_reg_reg(current_asmdata.CurrAsmList,def_cgsize(resultdef),
+             cg.g_div_const_reg_reg(current_asmdata.CurrAsmList,opsize,
                tordconstnode(right).value.svalue,numerator,resultreg);
                tordconstnode(right).value.svalue,numerator,resultreg);
          end;
          end;
 
 

+ 20 - 1
compiler/defutil.pas

@@ -229,6 +229,9 @@ interface
     {# Returns true, if def is a currency type }
     {# Returns true, if def is a currency type }
     function is_currency(def : tdef) : boolean;
     function is_currency(def : tdef) : boolean;
 
 
+    {# Returns true, if def is a comp type (handled by the fpu) }
+    function is_fpucomp(def : tdef) : boolean;
+
     {# Returns true, if def is a single type }
     {# Returns true, if def is a single type }
     function is_single(def : tdef) : boolean;
     function is_single(def : tdef) : boolean;
 
 
@@ -265,7 +268,10 @@ interface
     {# Returns true, if def is a 64 bit integer type }
     {# Returns true, if def is a 64 bit integer type }
     function is_64bitint(def : tdef) : boolean;
     function is_64bitint(def : tdef) : boolean;
 
 
-    {# Returns true, if def is a 64 bit type }
+    {# Returns true, if def is a 64 bit signed integer type }
+    function is_s64bitint(def : tdef) : boolean;
+
+    {# Returns true, if def is a 64 bit ordinal type }
     function is_64bit(def : tdef) : boolean;
     function is_64bit(def : tdef) : boolean;
 
 
     { returns true, if def is a longint type }
     { returns true, if def is a longint type }
@@ -408,6 +414,12 @@ implementation
       end;
       end;
 
 
 
 
+    function is_fpucomp(def: tdef): boolean;
+      begin
+        result:=(def.typ=floatdef) and
+           (tfloatdef(def).floattype=s64comp);
+      end;
+
     { returns true, if def is a single type }
     { returns true, if def is a single type }
     function is_single(def : tdef) : boolean;
     function is_single(def : tdef) : boolean;
       begin
       begin
@@ -1009,6 +1021,7 @@ implementation
          result:=(def.typ=orddef) and (torddef(def).ordtype in [u32bit,s32bit,pasbool32,bool32bit])
          result:=(def.typ=orddef) and (torddef(def).ordtype in [u32bit,s32bit,pasbool32,bool32bit])
       end;
       end;
 
 
+
     { true, if def is a 64 bit int type }
     { true, if def is a 64 bit int type }
     function is_64bitint(def : tdef) : boolean;
     function is_64bitint(def : tdef) : boolean;
       begin
       begin
@@ -1016,6 +1029,12 @@ implementation
       end;
       end;
 
 
 
 
+    function is_s64bitint(def: tdef): boolean;
+      begin
+        is_s64bitint:=(def.typ=orddef) and (torddef(def).ordtype=s64bit)
+      end;
+
+
     { true, if def is a 64 bit type }
     { true, if def is a 64 bit type }
     function is_64bit(def : tdef) : boolean;
     function is_64bit(def : tdef) : boolean;
       begin
       begin

+ 6 - 0
compiler/dirparse.pas

@@ -99,6 +99,12 @@ implementation
            end
            end
           else if tok='RECORDMAX' then
           else if tok='RECORDMAX' then
            b.recordalignmax:=l
            b.recordalignmax:=l
+
+{          disabled for now as - as Jonas pointed out - this
+           is a matter of abi
+
+           else if tok='MAXCRECORD' then
+           b.maxCrecordalign:=l }
           else { Error }
           else { Error }
            UpdateAlignmentStr:=false;
            UpdateAlignmentStr:=false;
         until false;
         until false;

+ 4 - 0
compiler/i386/aoptcpu.pas

@@ -238,6 +238,8 @@ unit aoptcpu;
               if InsContainsSegRef(taicpu(p)) then
               if InsContainsSegRef(taicpu(p)) then
                 exit;
                 exit;
               case taicpu(p).opcode Of
               case taicpu(p).opcode Of
+                A_ADD:
+                  Result:=OptPass2ADD(p);
                 A_Jcc:
                 A_Jcc:
                   Result:=OptPass2Jcc(p);
                   Result:=OptPass2Jcc(p);
                 A_Lea:
                 A_Lea:
@@ -334,6 +336,8 @@ unit aoptcpu;
                    end;
                    end;
                 A_TEST, A_OR:
                 A_TEST, A_OR:
                   Result:=PostPeepholeOptTestOr(p);
                   Result:=PostPeepholeOptTestOr(p);
+                A_AND:
+                  Result:=PostPeepholeOptAnd(p);
                 A_MOVSX:
                 A_MOVSX:
                   Result:=PostPeepholeOptMOVSX(p);
                   Result:=PostPeepholeOptMOVSX(p);
                 else
                 else

+ 4 - 2
compiler/i386/cpuinfo.pas

@@ -176,7 +176,9 @@ type
 
 
    tfpuflags =
    tfpuflags =
       (FPUX86_HAS_AVXUNIT,
       (FPUX86_HAS_AVXUNIT,
-       FPUX86_HAS_AVX512F
+       FPUX86_HAS_AVX512F,
+       FPUX86_HAS_AVX512VL,
+       FPUX86_HAS_AVX512DQ
       );
       );
 
 
  const
  const
@@ -205,7 +207,7 @@ type
       { fpu_sse42    } [],
       { fpu_sse42    } [],
       { fpu_avx      } [FPUX86_HAS_AVXUNIT],
       { fpu_avx      } [FPUX86_HAS_AVXUNIT],
       { fpu_avx2     } [FPUX86_HAS_AVXUNIT],
       { fpu_avx2     } [FPUX86_HAS_AVXUNIT],
-      { fpu_avx512   } [FPUX86_HAS_AVXUNIT,FPUX86_HAS_AVX512F]
+      { fpu_avx512   } [FPUX86_HAS_AVXUNIT,FPUX86_HAS_AVX512F,FPUX86_HAS_AVX512VL,FPUX86_HAS_AVX512DQ]
    );
    );
 
 
 Implementation
 Implementation

+ 4 - 4
compiler/i386/i386prop.inc

@@ -1383,10 +1383,10 @@
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
-(Ch: [Ch_All]),
-(Ch: [Ch_All]),
-(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_Rop3, Ch_Wop4]),
+(Ch: [Ch_Rop1, Ch_Rop2, Ch_Rop3, Ch_Wop4]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),

+ 4 - 4
compiler/i8086/i8086prop.inc

@@ -1397,10 +1397,10 @@
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
-(Ch: [Ch_All]),
-(Ch: [Ch_All]),
-(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_Rop3, Ch_Wop4]),
+(Ch: [Ch_Rop1, Ch_Rop2, Ch_Rop3, Ch_Wop4]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),

+ 4 - 2
compiler/m68k/aoptcpu.pas

@@ -380,7 +380,8 @@ unit aoptcpu;
         (taicpu(next).oper[1]^.ref^.base=NR_A7) and
         (taicpu(next).oper[1]^.ref^.base=NR_A7) and
         (taicpu(next).oper[1]^.ref^.index=NR_NO) and
         (taicpu(next).oper[1]^.ref^.index=NR_NO) and
         (taicpu(next).oper[1]^.ref^.symbol=nil) and
         (taicpu(next).oper[1]^.ref^.symbol=nil) and
-        (taicpu(next).oper[1]^.ref^.direction=dir_none) then
+        (taicpu(next).oper[1]^.ref^.direction=dir_none) and 
+        not (current_settings.cputype in cpu_coldfire) then
         begin
         begin
           DebugMsg('Optimizer: LEA, MOVE(M) to MOVE(M) predecremented',p);
           DebugMsg('Optimizer: LEA, MOVE(M) to MOVE(M) predecremented',p);
           taicpu(next).oper[1]^.ref^.direction:=dir_dec;
           taicpu(next).oper[1]^.ref^.direction:=dir_dec;
@@ -409,7 +410,8 @@ unit aoptcpu;
         (taicpu(next).oper[0]^.ref^.index=NR_NO) and
         (taicpu(next).oper[0]^.ref^.index=NR_NO) and
         (taicpu(next).oper[0]^.ref^.symbol=nil) and
         (taicpu(next).oper[0]^.ref^.symbol=nil) and
         (taicpu(next).oper[0]^.ref^.direction=dir_none) and
         (taicpu(next).oper[0]^.ref^.direction=dir_none) and
-        ((taicpu(next).oper[0]^.ref^.offset=(PopCnt(Byte(taicpu(p).oper[1]^.dataregset))+PopCnt(Byte(taicpu(p).oper[1]^.addrregset)))*4)) then
+        ((taicpu(next).oper[0]^.ref^.offset=(PopCnt(Byte(taicpu(p).oper[1]^.dataregset))+PopCnt(Byte(taicpu(p).oper[1]^.addrregset)))*4)) and
+        not (current_settings.cputype in cpu_coldfire) then
         begin
         begin
           DebugMsg('Optimizer: MOVE(M), LEA to MOVE(M) postincremented',p);
           DebugMsg('Optimizer: MOVE(M), LEA to MOVE(M) postincremented',p);
           taicpu(p).oper[0]^.ref^.direction:=dir_inc;
           taicpu(p).oper[0]^.ref^.direction:=dir_inc;

+ 4 - 3
compiler/m68k/cpuinfo.pas

@@ -165,6 +165,7 @@ type
       CPUM68K_HAS_32BITDIV,     { CPU supports DIVS/DIVU 32/32 -> 32bit                     }
       CPUM68K_HAS_32BITDIV,     { CPU supports DIVS/DIVU 32/32 -> 32bit                     }
       CPUM68K_HAS_64BITDIV,     { CPU supports DIVS/DIVU 64/32 -> 32bit                     }
       CPUM68K_HAS_64BITDIV,     { CPU supports DIVS/DIVU 64/32 -> 32bit                     }
       CPUM68K_HAS_REMSREMU,     { CPU supports the REMS/REMU instructions                   }
       CPUM68K_HAS_REMSREMU,     { CPU supports the REMS/REMU instructions                   }
+      CPUM68K_HAS_LONGLINK,     { CPU supports the LINK instruction with 32bit displacement }
       CPUM68K_HAS_UNALIGNED,    { CPU supports unaligned access                             }
       CPUM68K_HAS_UNALIGNED,    { CPU supports unaligned access                             }
       CPUM68K_HAS_BASEDISP,     { CPU supports addressing with 32bit base displacements     }
       CPUM68K_HAS_BASEDISP,     { CPU supports addressing with 32bit base displacements     }
       CPUM68K_HAS_INDEXSCALE,   { CPU supports scaling the index register with 2 or 4       }
       CPUM68K_HAS_INDEXSCALE,   { CPU supports scaling the index register with 2 or 4       }
@@ -187,9 +188,9 @@ const
   cpu_capabilities : array[tcputype] of set of tcpuflags =
   cpu_capabilities : array[tcputype] of set of tcpuflags =
     ( { cpu_none     } [],
     ( { cpu_none     } [],
       { cpu_68000    } [CPUM68K_HAS_DBRA,CPUM68K_HAS_TAS,CPUM68K_HAS_ROLROR,CPUM68K_HAS_MULIMM,CPUM68K_HAS_16BITDIV,CPUM68K_HAS_BYTEWORDMATH],
       { cpu_68000    } [CPUM68K_HAS_DBRA,CPUM68K_HAS_TAS,CPUM68K_HAS_ROLROR,CPUM68K_HAS_MULIMM,CPUM68K_HAS_16BITDIV,CPUM68K_HAS_BYTEWORDMATH],
-      { cpu_68020    } [CPUM68K_HAS_DBRA,CPUM68K_HAS_RTD,CPUM68K_HAS_CAS,CPUM68K_HAS_TAS,CPUM68K_HAS_BRAL,CPUM68K_HAS_ROLROR,CPUM68K_HAS_UNALIGNED,CPUM68K_HAS_BASEDISP,CPUM68K_HAS_MULIMM,CPUM68K_HAS_32BITMUL,CPUM68K_HAS_64BITMUL,CPUM68K_HAS_16BITDIV,CPUM68K_HAS_32BITDIV,CPUM68K_HAS_64BITDIV,CPUM68K_HAS_INDEXSCALE,CPUM68K_HAS_INDEXSCALE8,CPUM68K_HAS_INDEXWORD,CPUM68K_HAS_BYTEWORDMATH,CPUM68K_HAS_BITFIELD],
-      { cpu_68040    } [CPUM68K_HAS_DBRA,CPUM68K_HAS_RTD,CPUM68K_HAS_CAS,CPUM68K_HAS_TAS,CPUM68K_HAS_BRAL,CPUM68K_HAS_ROLROR,CPUM68K_HAS_UNALIGNED,CPUM68K_HAS_BASEDISP,CPUM68K_HAS_MULIMM,CPUM68K_HAS_32BITMUL,CPUM68K_HAS_64BITMUL,CPUM68K_HAS_16BITDIV,CPUM68K_HAS_32BITDIV,CPUM68K_HAS_64BITDIV,CPUM68K_HAS_MOVE16,CPUM68K_HAS_INDEXSCALE,CPUM68K_HAS_INDEXSCALE8,CPUM68K_HAS_INDEXWORD,CPUM68K_HAS_BYTEWORDMATH,CPUM68K_HAS_BITFIELD],
-      { cpu_68060    } [CPUM68K_HAS_DBRA,CPUM68K_HAS_RTD,CPUM68K_HAS_CAS,CPUM68K_HAS_TAS,CPUM68K_HAS_BRAL,CPUM68K_HAS_ROLROR,CPUM68K_HAS_UNALIGNED,CPUM68K_HAS_BASEDISP,CPUM68K_HAS_MULIMM,CPUM68K_HAS_32BITMUL,CPUM68K_HAS_16BITDIV,CPUM68K_HAS_32BITDIV,CPUM68K_HAS_MOVE16,CPUM68K_HAS_INDEXSCALE,CPUM68K_HAS_INDEXSCALE8,CPUM68K_HAS_INDEXWORD,CPUM68K_HAS_BYTEWORDMATH,CPUM68K_HAS_BITFIELD],
+      { cpu_68020    } [CPUM68K_HAS_DBRA,CPUM68K_HAS_RTD,CPUM68K_HAS_CAS,CPUM68K_HAS_TAS,CPUM68K_HAS_BRAL,CPUM68K_HAS_ROLROR,CPUM68K_HAS_UNALIGNED,CPUM68K_HAS_BASEDISP,CPUM68K_HAS_LONGLINK,CPUM68K_HAS_MULIMM,CPUM68K_HAS_32BITMUL,CPUM68K_HAS_64BITMUL,CPUM68K_HAS_16BITDIV,CPUM68K_HAS_32BITDIV,CPUM68K_HAS_64BITDIV,CPUM68K_HAS_INDEXSCALE,CPUM68K_HAS_INDEXSCALE8,CPUM68K_HAS_INDEXWORD,CPUM68K_HAS_BYTEWORDMATH,CPUM68K_HAS_BITFIELD],
+      { cpu_68040    } [CPUM68K_HAS_DBRA,CPUM68K_HAS_RTD,CPUM68K_HAS_CAS,CPUM68K_HAS_TAS,CPUM68K_HAS_BRAL,CPUM68K_HAS_ROLROR,CPUM68K_HAS_UNALIGNED,CPUM68K_HAS_BASEDISP,CPUM68K_HAS_LONGLINK,CPUM68K_HAS_MULIMM,CPUM68K_HAS_32BITMUL,CPUM68K_HAS_64BITMUL,CPUM68K_HAS_16BITDIV,CPUM68K_HAS_32BITDIV,CPUM68K_HAS_64BITDIV,CPUM68K_HAS_MOVE16,CPUM68K_HAS_INDEXSCALE,CPUM68K_HAS_INDEXSCALE8,CPUM68K_HAS_INDEXWORD,CPUM68K_HAS_BYTEWORDMATH,CPUM68K_HAS_BITFIELD],
+      { cpu_68060    } [CPUM68K_HAS_DBRA,CPUM68K_HAS_RTD,CPUM68K_HAS_CAS,CPUM68K_HAS_TAS,CPUM68K_HAS_BRAL,CPUM68K_HAS_ROLROR,CPUM68K_HAS_UNALIGNED,CPUM68K_HAS_BASEDISP,CPUM68K_HAS_LONGLINK,CPUM68K_HAS_MULIMM,CPUM68K_HAS_32BITMUL,CPUM68K_HAS_16BITDIV,CPUM68K_HAS_32BITDIV,CPUM68K_HAS_MOVE16,CPUM68K_HAS_INDEXSCALE,CPUM68K_HAS_INDEXSCALE8,CPUM68K_HAS_INDEXWORD,CPUM68K_HAS_BYTEWORDMATH,CPUM68K_HAS_BITFIELD],
       { cpu_isaa     } [CPUM68K_HAS_UNALIGNED,CPUM68K_HAS_32BITMUL,CPUM68K_HAS_16BITDIV,CPUM68K_HAS_32BITDIV,CPUM68K_HAS_REMSREMU,CPUM68K_HAS_INDEXSCALE],
       { cpu_isaa     } [CPUM68K_HAS_UNALIGNED,CPUM68K_HAS_32BITMUL,CPUM68K_HAS_16BITDIV,CPUM68K_HAS_32BITDIV,CPUM68K_HAS_REMSREMU,CPUM68K_HAS_INDEXSCALE],
       { cpu_isaap    } [CPUM68K_HAS_BRAL,CPUM68K_HAS_BYTEREV,CPUM68K_HAS_UNALIGNED,CPUM68K_HAS_32BITMUL,CPUM68K_HAS_16BITDIV,CPUM68K_HAS_32BITDIV,CPUM68K_HAS_REMSREMU,CPUM68K_HAS_INDEXSCALE],
       { cpu_isaap    } [CPUM68K_HAS_BRAL,CPUM68K_HAS_BYTEREV,CPUM68K_HAS_UNALIGNED,CPUM68K_HAS_32BITMUL,CPUM68K_HAS_16BITDIV,CPUM68K_HAS_32BITDIV,CPUM68K_HAS_REMSREMU,CPUM68K_HAS_INDEXSCALE],
       { cpu_isab     } [CPUM68K_HAS_TAS,CPUM68K_HAS_BRAL,CPUM68K_HAS_MVSMVZ,CPUM68K_HAS_UNALIGNED,CPUM68K_HAS_32BITMUL,CPUM68K_HAS_16BITDIV,CPUM68K_HAS_32BITDIV,CPUM68K_HAS_REMSREMU,CPUM68K_HAS_INDEXSCALE],
       { cpu_isab     } [CPUM68K_HAS_TAS,CPUM68K_HAS_BRAL,CPUM68K_HAS_MVSMVZ,CPUM68K_HAS_UNALIGNED,CPUM68K_HAS_32BITMUL,CPUM68K_HAS_16BITDIV,CPUM68K_HAS_32BITDIV,CPUM68K_HAS_REMSREMU,CPUM68K_HAS_INDEXSCALE],

+ 2 - 2
compiler/ncnv.pas

@@ -3347,14 +3347,14 @@ implementation
 {$if defined(cpu16bitalu)}
 {$if defined(cpu16bitalu)}
                   if (resultdef.size <= 2) and
                   if (resultdef.size <= 2) and
                     (is_32bitint(left.resultdef) or is_64bitint(left.resultdef)) and
                     (is_32bitint(left.resultdef) or is_64bitint(left.resultdef)) and
-                    (left.nodetype in [subn,addn,muln,divn,modn,xorn,andn,orn]) and
+                    (left.nodetype in [subn,addn,muln,divn,modn,xorn,andn,orn,notn,unaryminusn]) and
                     checkremovebiginttypeconvs(left,foundsint,[s8bit,u8bit,s16bit,u16bit],int64(low(smallint)),high(word)) then
                     checkremovebiginttypeconvs(left,foundsint,[s8bit,u8bit,s16bit,u16bit],int64(low(smallint)),high(word)) then
                     doremoveinttypeconvs(left,generrordef,not foundsint,s16inttype,u16inttype);
                     doremoveinttypeconvs(left,generrordef,not foundsint,s16inttype,u16inttype);
 {$endif defined(cpu16bitalu)}
 {$endif defined(cpu16bitalu)}
 {$if defined(cpu8bitalu)}
 {$if defined(cpu8bitalu)}
                  if (resultdef.size<left.resultdef.size) and
                  if (resultdef.size<left.resultdef.size) and
                   is_integer(left.resultdef) and
                   is_integer(left.resultdef) and
-                  (left.nodetype in [subn,addn,muln,divn,modn,xorn,andn,orn]) and
+                  (left.nodetype in [subn,addn,muln,divn,modn,xorn,andn,orn,notn,unaryminusn]) and
                   checkremovebiginttypeconvs(left,foundsint,[s8bit,u8bit],int64(low(shortint)),high(byte)) then
                   checkremovebiginttypeconvs(left,foundsint,[s8bit,u8bit],int64(low(shortint)),high(byte)) then
                     doremoveinttypeconvs(left,generrordef,not foundsint,s8inttype,u8inttype);
                     doremoveinttypeconvs(left,generrordef,not foundsint,s8inttype,u8inttype);
 {$endif defined(cpu8bitalu)}
 {$endif defined(cpu8bitalu)}

+ 48 - 4
compiler/nflw.pas

@@ -1563,6 +1563,7 @@ implementation
         paratype: tdef;
         paratype: tdef;
       begin
       begin
         result:=nil;
         result:=nil;
+        elsestmnt:=nil;
         in_nr:=Default(tinlinenumber);
         in_nr:=Default(tinlinenumber);
         { optimize constant expressions }
         { optimize constant expressions }
         if (left.nodetype=ordconstn) then
         if (left.nodetype=ordconstn) then
@@ -1590,9 +1591,24 @@ implementation
           end;
           end;
 {$ifndef llvm}
 {$ifndef llvm}
 {$if defined(i386) or defined(x86_64) or defined(xtensa)}
 {$if defined(i386) or defined(x86_64) or defined(xtensa)}
-        { use min/max intrinsic? }
+        { use min/max intrinsic?
+          convert (with <op> being <, >, >=, <=
+          if a <op> b then
+            x:=a
+          else
+            x:=b;
+
+          and
+
+          if a <op> b then
+            x:=a;
+
+          into appropriate min/max intrinsics
+
+          }
         if (cs_opt_level2 in current_settings.optimizerswitches) and
         if (cs_opt_level2 in current_settings.optimizerswitches) and
-           (left.nodetype in [gtn,gten,ltn,lten]) and IsSingleStatement(right,thenstmnt) and ((t1=nil) or IsSingleStatement(t1,elsestmnt)) and
+           (left.nodetype in [gtn,gten,ltn,lten]) and IsSingleStatement(right,thenstmnt) and
+           ((t1=nil) or IsSingleStatement(t1,elsestmnt)) and
           (thenstmnt.nodetype=assignn) and ((t1=nil) or (elsestmnt.nodetype=assignn)) and
           (thenstmnt.nodetype=assignn) and ((t1=nil) or (elsestmnt.nodetype=assignn)) and
           not(might_have_sideeffects(left)) and
           not(might_have_sideeffects(left)) and
           ((t1=nil) or tassignmentnode(thenstmnt).left.isequal(tassignmentnode(elsestmnt).left)) and
           ((t1=nil) or tassignmentnode(thenstmnt).left.isequal(tassignmentnode(elsestmnt).left)) and
@@ -1608,8 +1624,36 @@ implementation
 {$if defined(xtensa)}
 {$if defined(xtensa)}
           (CPUXTENSA_HAS_MINMAX in cpu_capabilities[current_settings.cputype]) and is_32bitint(tassignmentnode(thenstmnt).right.resultdef) and
           (CPUXTENSA_HAS_MINMAX in cpu_capabilities[current_settings.cputype]) and is_32bitint(tassignmentnode(thenstmnt).right.resultdef) and
 {$endif defined(xtensa)}
 {$endif defined(xtensa)}
-          ((tassignmentnode(thenstmnt).right.isequal(taddnode(left).left) and ((t1=nil) or (tassignmentnode(elsestmnt).right.isequal(taddnode(left).right)))) or
-           (tassignmentnode(thenstmnt).right.isequal(taddnode(left).right) and ((t1=nil) or (tassignmentnode(elsestmnt).right.isequal(taddnode(left).left))))
+          (
+          { the right size of the assignment in the then clause must either }
+
+          { equal to the left ... }
+           (tassignmentnode(thenstmnt).right.isequal(taddnode(left).left) and
+
+            { ... and the else clause must be either not exist                 }
+            { and the left side of the assignment in the then clause must be   }
+            {  equal to the right operand of the comparison operator           }
+            (
+              ((t1=nil) and (tassignmentnode(thenstmnt).left.isequal(taddnode(left).right))) or
+
+              { or the else clause exists and the right side of the assignment in the else clause }
+              { must be equal to the right side of the comparison operator                        }
+              (assigned(elsestmnt) and tassignmentnode(elsestmnt).right.isequal(taddnode(left).right)))
+           ) or
+           { ... or right operand of the comparison operator }
+
+            (tassignmentnode(thenstmnt).right.isequal(taddnode(left).right) and
+            { ... and the else clause must be either not exist                 }
+            { and the left side of the assignment in the then clause must be   }
+            {  equal to the left operand of the comparison operator            }
+             (
+              ((t1=nil) and (tassignmentnode(thenstmnt).left.isequal(taddnode(left).left))) or
+
+              { or the else clause exists and the right side of the assignment in the else clause }
+              { must be equal to the left side of the comparison operator                         }
+              (assigned(elsestmnt) and tassignmentnode(elsestmnt).right.isequal(taddnode(left).left))
+             )
+           )
           ) then
           ) then
           begin
           begin
             paratype:=tassignmentnode(thenstmnt).left.resultdef;
             paratype:=tassignmentnode(thenstmnt).left.resultdef;

+ 70 - 27
compiler/ninl.pas

@@ -2820,7 +2820,10 @@ implementation
 
 
     function tinlinenode.pass_typecheck:tnode;
     function tinlinenode.pass_typecheck:tnode;
 
 
-      procedure setfloatresultdef;
+      type
+        tfloattypeset = set of tfloattype;
+
+      function removefloatupcasts(var p: tnode; const floattypes: tfloattypeset): tdef;
         var
         var
           hnode: tnode;
           hnode: tnode;
         begin
         begin
@@ -2830,25 +2833,54 @@ implementation
             which typechecks the arguments, possibly inserting conversion to valreal.
             which typechecks the arguments, possibly inserting conversion to valreal.
             To handle smaller types without excess precision, we need to remove
             To handle smaller types without excess precision, we need to remove
             these extra typecasts. }
             these extra typecasts. }
-          if (left.nodetype=typeconvn) and
-            (ttypeconvnode(left).left.resultdef.typ=floatdef) and
-            (left.flags*[nf_explicit,nf_internal]=[]) and
-            (tfloatdef(ttypeconvnode(left).left.resultdef).floattype in [s32real,s64real,s80real,sc80real,s128real]) then
+          if (p.nodetype=typeconvn) and
+             (ttypeconvnode(p).left.resultdef.typ=floatdef) and
+             (p.flags*[nf_explicit,nf_internal]=[]) and
+             (tfloatdef(ttypeconvnode(p).left.resultdef).floattype in (floattypes*[s32real,s64real,s80real,sc80real,s128real])) then
             begin
             begin
-              hnode:=ttypeconvnode(left).left;
-              ttypeconvnode(left).left:=nil;
-              left.free;
-              left:=hnode;
-              resultdef:=left.resultdef;
+              hnode:=ttypeconvnode(p).left;
+              ttypeconvnode(p).left:=nil;
+              p.free;
+              p:=hnode;
+              result:=p.resultdef;
             end
             end
-          else if (left.resultdef.typ=floatdef) and
-            (tfloatdef(left.resultdef).floattype in [s32real,s64real,s80real,sc80real,s128real]) then
-            resultdef:=left.resultdef
+          else if (p.nodetype=typeconvn) and
+             (p.flags*[nf_explicit,nf_internal]=[]) and
+             (ttypeconvnode(p).left.resultdef.typ=floatdef) and
+             (tfloatdef(ttypeconvnode(p).left.resultdef).floattype in (floattypes*[s64currency,s64comp])) then
+            begin
+              hnode:=ttypeconvnode(p).left;
+              ttypeconvnode(p).left:=nil;
+              p.free;
+              p:=hnode;
+              if is_currency(p.resultdef) then
+                begin
+                  if (nf_is_currency in p.flags) and
+                     (p.nodetype=slashn) and
+                     (taddnode(p).right.nodetype=realconstn) and
+                     (trealconstnode(taddnode(p).right).value_real=10000.0) and
+                     not(nf_is_currency in taddnode(p).left.flags) then
+                   begin
+                     hnode:=taddnode(p).left;
+                     taddnode(p).left:=nil;
+                     p.free;
+                     p:=hnode;
+                   end;
+                end;
+              result:=p.resultdef;
+            end
+          { in case the system helper was declared with overloads for different types,
+            keep those }
+          else if (p.resultdef.typ=floatdef) and
+             (tfloatdef(p.resultdef).floattype in (floattypes*[s32real,s64real,s80real,sc80real,s128real])) then
+            result:=p.resultdef
           else
           else
             begin
             begin
-              if (left.nodetype <> ordconstn) then
-                inserttypeconv(left,pbestrealtype^);
-              resultdef:=pbestrealtype^;
+              { for variant parameters; the rest has been converted by the
+                call node already }
+              if not(p.nodetype in [ordconstn,realconstn]) then
+                inserttypeconv(P,pbestrealtype^);
+              result:=p.resultdef
             end;
             end;
         end;
         end;
 
 
@@ -3595,18 +3627,29 @@ implementation
                   { on i8086, the int64 result is returned in a var param, because
                   { on i8086, the int64 result is returned in a var param, because
                     it's too big to fit in a register or a pair of registers. In
                     it's too big to fit in a register or a pair of registers. In
                     that case we have 2 parameters and left.nodetype is a callparan. }
                     that case we have 2 parameters and left.nodetype is a callparan. }
-                  if left.nodetype = callparan then
-                    temp_pnode := @tcallparanode(left).left
+                  if left.nodetype=callparan then
+                    temp_pnode:=@tcallparanode(left).left
                   else
                   else
-                    temp_pnode := @left;
+                    temp_pnode:=@left;
                   set_varstate(temp_pnode^,vs_read,[vsf_must_be_valid]);
                   set_varstate(temp_pnode^,vs_read,[vsf_must_be_valid]);
-                  { for direct float rounding, no best real type cast should be necessary }
-                  if not((temp_pnode^.resultdef.typ=floatdef) and
-                         (tfloatdef(temp_pnode^.resultdef).floattype in [s32real,s64real,s80real,sc80real,s128real])) and
-                     { converting an int64 to double on platforms without }
-                     { extended can cause precision loss                  }
-                     not(temp_pnode^.nodetype in [ordconstn,realconstn]) then
-                    inserttypeconv(temp_pnode^,pbestrealtype^);
+                  { on platforms where comp and currency are "type int64", this is
+                    handled via inlined system helpers (-> no need for special
+                    handling of s64currency/s64comp for them) }
+                  if inlinenumber=in_trunc_real then
+                    removefloatupcasts(temp_pnode^,[s32real,s64real,s80real,sc80real,s128real,s64currency,s64comp])
+                  else
+                    removefloatupcasts(temp_pnode^,[s32real,s64real,s80real,sc80real,s128real,s64comp]);
+                  if (inlinenumber=in_trunc_real) and
+                     is_currency(temp_pnode^.resultdef) then
+                    begin
+                      result:=cmoddivnode.create(divn,ctypeconvnode.create_internal(temp_pnode^.getcopy,s64inttype),genintconstnode(10000));
+                      exit;
+                    end
+                  else if is_fpucomp(temp_pnode^.resultdef) then
+                    begin
+                      result:=ctypeconvnode.create_internal(temp_pnode^.getcopy,s64inttype);
+                      exit;
+                    end;
                   resultdef:=s64inttype;
                   resultdef:=s64inttype;
                 end;
                 end;
 
 
@@ -3633,7 +3676,7 @@ implementation
                   else
                   else
                     temp_pnode := @left;
                     temp_pnode := @left;
                   set_varstate(temp_pnode^,vs_read,[vsf_must_be_valid]);
                   set_varstate(temp_pnode^,vs_read,[vsf_must_be_valid]);
-                  setfloatresultdef;
+                  resultdef:=removefloatupcasts(temp_pnode^,[s32real,s64real,s80real,sc80real,s128real]);
                 end;
                 end;
 
 
 {$ifdef SUPPORT_MMX}
 {$ifdef SUPPORT_MMX}

+ 27 - 1
compiler/nld.pas

@@ -182,6 +182,10 @@ interface
        { Current assignment node }
        { Current assignment node }
        aktassignmentnode : tassignmentnode;
        aktassignmentnode : tassignmentnode;
 
 
+       { Create a node tree to load a variable if symbol is assigned, otherwise an error node.
+         Generates an internalerror if called for an absolutevarsym of the "tovar" kind (those
+         are only supported for expansion in the parser) }
+       function gen_load_var(sym: tabstractvarsym): tnode;
 
 
 implementation
 implementation
 
 
@@ -192,10 +196,32 @@ implementation
       defutil,defcmp,
       defutil,defcmp,
       cpuinfo,
       cpuinfo,
       htypechk,pass_1,procinfo,paramgr,
       htypechk,pass_1,procinfo,paramgr,
-      ncon,nflw,ninl,ncnv,nmem,ncal,nutils,
+      nbas,ncon,nflw,ninl,ncnv,nmem,ncal,nutils,
       cgbase
       cgbase
       ;
       ;
 
 
+
+    function gen_load_var(sym: tabstractvarsym): tnode;
+      begin
+        result:=nil;
+        if assigned(sym) then
+          begin
+            if (sym.typ<>absolutevarsym) or
+               (tabsolutevarsym(sym).abstyp<>tovar) then
+              begin
+                result:=cloadnode.create(sym,sym.owner);
+              end
+            else
+              internalerror(2020122601);
+          end
+        else
+          begin
+            result:=cerrornode.create;
+            CGMessage(parser_e_illegal_expression);
+          end;
+      end;
+
+
 {*****************************************************************************
 {*****************************************************************************
                              TLOADNODE
                              TLOADNODE
 *****************************************************************************}
 *****************************************************************************}

+ 21 - 8
compiler/nmat.pas

@@ -283,19 +283,32 @@ implementation
              (not is_signed(ld) and
              (not is_signed(ld) and
               (rd.size >= ld.size))) then
               (rd.size >= ld.size))) then
            begin
            begin
-             inserttypeconv(left,right.resultdef);
-             ld:=torddef(left.resultdef);
-           end;
-         if (ld.ordtype in [u8bit,u16bit,u32bit,u64bit]) and
+             if rd.size<uinttype.size then
+               begin
+                 inserttypeconv(left,uinttype);
+                 inserttypeconv(right,uinttype);
+               end
+             else
+               inserttypeconv(left,rd);
+             resultdef:=right.resultdef;
+           end
+         else if (ld.ordtype in [u8bit,u16bit,u32bit,u64bit]) and
             ((is_constintnode(right) and
             ((is_constintnode(right) and
               (tordconstnode(right).value >= 0) and
               (tordconstnode(right).value >= 0) and
               (tordconstnode(right).value <= get_max_value(ld))) or
               (tordconstnode(right).value <= get_max_value(ld))) or
              (not is_signed(rd) and
              (not is_signed(rd) and
               (ld.size >= rd.size))) then
               (ld.size >= rd.size))) then
-          begin
-            inserttypeconv(right,left.resultdef);
-            rd:=torddef(right.resultdef);
-          end;
+           begin
+             if ld.size<uinttype.size then
+               begin
+                 inserttypeconv(left,uinttype);
+                 inserttypeconv(right,uinttype);
+               end
+             else
+               inserttypeconv(right,ld);
+             resultdef:=left.resultdef;
+           end
+         else
 
 
          { when there is one currency value, everything is done
          { when there is one currency value, everything is done
            using currency }
            using currency }

+ 32 - 74
compiler/nutils.pas

@@ -78,7 +78,7 @@ interface
     procedure checktreenodetypes(n : tnode;typeset : tnodetypeset);
     procedure checktreenodetypes(n : tnode;typeset : tnodetypeset);
 
 
     procedure load_procvar_from_calln(var p1:tnode);
     procedure load_procvar_from_calln(var p1:tnode);
-    function get_local_or_para_sym(const aname: string): tsym;
+    function get_local_or_para_sym(const aname: string): tabstractvarsym;
     function maybe_call_procvar(var p1:tnode;tponly:boolean):boolean;
     function maybe_call_procvar(var p1:tnode;tponly:boolean):boolean;
     function load_high_value_node(vs:tparavarsym):tnode;
     function load_high_value_node(vs:tparavarsym):tnode;
     function load_self_node:tnode;
     function load_self_node:tnode;
@@ -496,10 +496,12 @@ implementation
       end;
       end;
 
 
 
 
-    function get_local_or_para_sym(const aname: string): tsym;
+    function get_local_or_para_sym(const aname: string): tabstractvarsym;
       var
       var
-        pd : tprocdef;
+        pd: tprocdef;
+        ressym: tsym;
       begin
       begin
+        ressym:=nil;
         result:=nil;
         result:=nil;
         { is not assigned while parsing a property }
         { is not assigned while parsing a property }
         if not assigned(current_procinfo) then
         if not assigned(current_procinfo) then
@@ -509,11 +511,11 @@ implementation
           is run for nested procedures }
           is run for nested procedures }
         pd:=current_procinfo.procdef;
         pd:=current_procinfo.procdef;
         repeat
         repeat
-          result := tsym(pd.localst.Find(aname));
-          if assigned(result) then
+          ressym:=tsym(pd.localst.Find(aname));
+          if assigned(ressym) then
             break;
             break;
-          result := tsym(pd.parast.Find(aname));
-          if assigned(result) then
+          ressym:=tsym(pd.parast.Find(aname));
+          if assigned(ressym) then
             break;
             break;
           { try the parent of a nested function }
           { try the parent of a nested function }
           if assigned(pd.owner.defowner) and
           if assigned(pd.owner.defowner) and
@@ -522,104 +524,60 @@ implementation
           else
           else
             break;
             break;
         until false;
         until false;
+        if assigned(ressym) and
+           not(ressym.typ in [localvarsym,paravarsym]) then
+          internalerror(2020122604);
+        result:=tabstractvarsym(ressym);
       end;
       end;
 
 
 
 
+
     function load_high_value_node(vs:tparavarsym):tnode;
     function load_high_value_node(vs:tparavarsym):tnode;
-      var
-        srsym : tsym;
       begin
       begin
-        result:=nil;
-        srsym:=get_high_value_sym(vs);
-        if assigned(srsym) then
-          begin
-            result:=cloadnode.create(srsym,vs.owner);
-            typecheckpass(result);
-          end
-        else
-          CGMessage(parser_e_illegal_expression);
+        result:=gen_load_var(get_high_value_sym(vs));
+        typecheckpass(result);
       end;
       end;
 
 
 
 
     function load_self_node:tnode;
     function load_self_node:tnode;
-      var
-        srsym : tsym;
       begin
       begin
-        result:=nil;
-
-        srsym:=get_local_or_para_sym('self');
-        if assigned(srsym) then
-          begin
-            result:=cloadnode.create(srsym,srsym.owner);
-            include(tloadnode(result).loadnodeflags,loadnf_is_self);
-          end
-        else
-          begin
-            result:=cerrornode.create;
-            CGMessage(parser_e_illegal_expression);
-          end;
+        result:=gen_load_var(get_local_or_para_sym('self'));
+        if result.nodetype=loadn then
+          include(tloadnode(result).loadnodeflags,loadnf_is_self)
+        else if result.nodetype<>errorn then
+          internalerror(2020122603);
         typecheckpass(result);
         typecheckpass(result);
       end;
       end;
 
 
 
 
     function load_result_node:tnode;
     function load_result_node:tnode;
-      var
-        srsym : tsym;
-        pd : tprocdef;
-       begin
-        result:=nil;
-        srsym:=get_local_or_para_sym('result');
-        if not assigned(srsym) then
-          begin
-            pd:=current_procinfo.procdef;
-            if assigned(pd.procsym) then
-              srsym:=get_local_or_para_sym(pd.procsym.name);
-          end;
-        if assigned(srsym) then
-          result:=cloadnode.create(srsym,srsym.owner)
-        else
-          begin
-            result:=cerrornode.create;
-            CGMessage(parser_e_illegal_expression);
-          end;
+      begin
+        result:=gen_load_var(get_local_or_para_sym('result'));
         typecheckpass(result);
         typecheckpass(result);
       end;
       end;
 
 
 
 
     function load_self_pointer_node:tnode;
     function load_self_pointer_node:tnode;
       var
       var
-        srsym : tsym;
+        srsym : tabstractvarsym;
       begin
       begin
-        result:=nil;
         srsym:=get_local_or_para_sym('self');
         srsym:=get_local_or_para_sym('self');
-        if assigned(srsym) then
+        result:=gen_load_var(srsym);
+        if assigned(srsym) and
+           (is_object(tabstractvarsym(srsym).vardef) or is_record(tabstractvarsym(srsym).vardef)) then
           begin
           begin
-            result:=cloadnode.create(srsym,srsym.owner);
-            if is_object(tabstractvarsym(srsym).vardef) or is_record(tabstractvarsym(srsym).vardef) then
-              include(tloadnode(result).loadnodeflags,loadnf_load_addr);
-          end
-        else
-          begin
-            result:=cerrornode.create;
-            CGMessage(parser_e_illegal_expression);
+            if result.nodetype=loadn then
+              include(tloadnode(result).loadnodeflags,loadnf_load_addr)
+            else if result.nodetype<>errorn then
+              internalerror(2020122602);
           end;
           end;
         typecheckpass(result);
         typecheckpass(result);
       end;
       end;
 
 
 
 
     function load_vmt_pointer_node:tnode;
     function load_vmt_pointer_node:tnode;
-      var
-        srsym : tsym;
       begin
       begin
-        result:=nil;
-        srsym:=get_local_or_para_sym('vmt');
-        if assigned(srsym) then
-          result:=cloadnode.create(srsym,srsym.owner)
-        else
-          begin
-            result:=cerrornode.create;
-            CGMessage(parser_e_illegal_expression);
-          end;
+        result:=gen_load_var(get_local_or_para_sym('vmt'));
         typecheckpass(result);
         typecheckpass(result);
       end;
       end;
 
 

+ 2 - 1
compiler/optdfa.pas

@@ -714,7 +714,8 @@ unit optdfa;
                    ((vo_is_funcret in sym.varoptions) and
                    ((vo_is_funcret in sym.varoptions) and
                     (current_procinfo.procdef.parast.symtablelevel=sym.owner.symtablelevel)
                     (current_procinfo.procdef.parast.symtablelevel=sym.owner.symtablelevel)
                    )
                    )
-                  ) and not(vo_is_external in sym.varoptions)
+                  ) and not(vo_is_external in sym.varoptions) and
+                  not sym.inparentfpstruct;
         end;
         end;
 
 
       var
       var

+ 1 - 5
compiler/pdecsub.pas

@@ -1344,7 +1344,7 @@ implementation
             parse_generic:=(df_generic in pd.defoptions);
             parse_generic:=(df_generic in pd.defoptions);
             if pd.is_generic or pd.is_specialization then
             if pd.is_generic or pd.is_specialization then
               symtablestack.push(pd.parast);
               symtablestack.push(pd.parast);
-            single_type(pd.returndef,[stoAllowSpecialization]);
+            pd.returndef:=result_type([stoAllowSpecialization]);
 
 
             // Issue #24863, enabled only for the main progra commented out for now because it breaks building of RTL and needs extensive
             // Issue #24863, enabled only for the main progra commented out for now because it breaks building of RTL and needs extensive
 // testing and/or RTL patching.
 // testing and/or RTL patching.
@@ -1555,10 +1555,6 @@ implementation
             include(pd.procoptions,po_variadic);
             include(pd.procoptions,po_variadic);
           end;
           end;
 
 
-        { file types can't be function results }
-        if assigned(pd) and
-           (pd.returndef.typ=filedef) then
-          message(parser_e_illegal_function_result);
         { support procedure proc stdcall export; }
         { support procedure proc stdcall export; }
         if not(check_proc_directive(false)) then
         if not(check_proc_directive(false)) then
           begin
           begin

+ 13 - 7
compiler/psub.pas

@@ -369,12 +369,6 @@ implementation
 
 
         if assigned(current_procinfo.procdef.parentfpstruct) then
         if assigned(current_procinfo.procdef.parentfpstruct) then
          begin
          begin
-           { we only do this after the code has been parsed because
-             otherwise for-loop counters moved to the struct cause
-             errors; we still do it nevertheless to prevent false
-             "unused" symbols warnings and to assist debug info
-             generation }
-           redirect_parentfpstruct_local_syms(current_procinfo.procdef);
            { finish the parentfpstruct (add padding, ...) }
            { finish the parentfpstruct (add padding, ...) }
            finish_parentfpstruct(current_procinfo.procdef);
            finish_parentfpstruct(current_procinfo.procdef);
          end;
          end;
@@ -2171,7 +2165,7 @@ implementation
 
 
             { translate imag. register to their real counter parts
             { translate imag. register to their real counter parts
               this is necessary for debuginfo and verbose assembler output
               this is necessary for debuginfo and verbose assembler output
-              when SSA will be implented, this will be more complicated because we've to
+              when SSA will be implemented, this will be more complicated because we've to
               maintain location lists }
               maintain location lists }
             procdef.parast.SymList.ForEachCall(@translate_registers,templist);
             procdef.parast.SymList.ForEachCall(@translate_registers,templist);
             procdef.localst.SymList.ForEachCall(@translate_registers,templist);
             procdef.localst.SymList.ForEachCall(@translate_registers,templist);
@@ -2278,7 +2272,19 @@ implementation
             { insert line debuginfo }
             { insert line debuginfo }
             if (cs_debuginfo in current_settings.moduleswitches) or
             if (cs_debuginfo in current_settings.moduleswitches) or
                (cs_use_lineinfo in current_settings.globalswitches) then
                (cs_use_lineinfo in current_settings.globalswitches) then
+             begin
+               { We only do this after the code generated because
+                 otherwise for-loop counters moved to the struct cause
+                 errors. And doing it before optimisation passes have run
+                 causes problems when they manually look up symbols
+                 like result and self (nutils.load_self_node etc). Still
+                 do it nevertheless to to assist debug info generation
+                 (hide original symbols, add absolutevarsyms that redirect
+                  to their new locations in the parentfpstruct) }
+              if assigned(current_procinfo.procdef.parentfpstruct) then
+                redirect_parentfpstruct_local_syms(current_procinfo.procdef);
               current_debuginfo.insertlineinfo(aktproccode);
               current_debuginfo.insertlineinfo(aktproccode);
+             end;
 
 
             finish_eh;
             finish_eh;
 
 

+ 13 - 3
compiler/ptype.pas

@@ -41,7 +41,9 @@ interface
     procedure resolve_forward_types;
     procedure resolve_forward_types;
 
 
     { reads a string, file type or a type identifier }
     { reads a string, file type or a type identifier }
-    procedure single_type(var def:tdef;options:TSingleTypeOptions);
+    procedure single_type(out def:tdef;options:TSingleTypeOptions);
+    { ... but rejects types that cannot be returned from functions }
+    function result_type(options:TSingleTypeOptions):tdef;
 
 
     { reads any type declaration, where the resulting type will get name as type identifier }
     { reads any type declaration, where the resulting type will get name as type identifier }
     procedure read_named_type(var def:tdef;const newsym:tsym;genericdef:tstoreddef;genericlist:tfphashobjectlist;parseprocvardir:boolean;var hadtypetoken:boolean);
     procedure read_named_type(var def:tdef;const newsym:tsym;genericdef:tstoreddef;genericlist:tfphashobjectlist;parseprocvardir:boolean;var hadtypetoken:boolean);
@@ -454,7 +456,7 @@ implementation
       end;
       end;
 
 
 
 
-    procedure single_type(var def:tdef;options:TSingleTypeOptions);
+    procedure single_type(out def:tdef;options:TSingleTypeOptions);
        var
        var
          t2 : tdef;
          t2 : tdef;
          isspecialize,
          isspecialize,
@@ -645,6 +647,14 @@ implementation
       end;
       end;
 
 
 
 
+    function result_type(options:TSingleTypeOptions):tdef;
+      begin
+        single_type(result,options);
+        { file types cannot be function results }
+        if result.typ=filedef then
+          message(parser_e_illegal_function_result);
+      end;
+
     procedure parse_record_members(recsym:tsym);
     procedure parse_record_members(recsym:tsym);
 
 
       function IsAnonOrLocal: Boolean;
       function IsAnonOrLocal: Boolean;
@@ -1587,7 +1597,7 @@ implementation
             if is_func then
             if is_func then
               begin
               begin
                 consume(_COLON);
                 consume(_COLON);
-                single_type(pd.returndef,[]);
+                pd.returndef:=result_type([stoAllowSpecialization]);
               end;
               end;
             if try_to_consume(_OF) then
             if try_to_consume(_OF) then
               begin
               begin

+ 1 - 1
compiler/sparcgen/cgsparc.pas

@@ -799,7 +799,7 @@ implementation
                   tmpreg1:=GetIntRegister(list,OS_INT);
                   tmpreg1:=GetIntRegister(list,OS_INT);
                   tmpreg2:=GetIntRegister(list,OS_INT);
                   tmpreg2:=GetIntRegister(list,OS_INT);
                   list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
                   list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
-                  list.concat(taicpu.op_reg_const_reg(A_SRL,dst,31,tmpreg2));
+                  list.concat(taicpu.op_reg_const_reg(A_SRA,dst,31,tmpreg2));
                   list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
                   list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
                   ovloc.loc:=LOC_FLAGS;
                   ovloc.loc:=LOC_FLAGS;
                   ovloc.resflags.Init(NR_ICC,F_NE);
                   ovloc.resflags.Init(NR_ICC,F_NE);

+ 10 - 0
compiler/symbase.pas

@@ -72,6 +72,7 @@ interface
       TSymEntry = class(TFPHashObject)
       TSymEntry = class(TFPHashObject)
       private
       private
          FRealName : {$ifdef symansistr}TSymStr{$else}pshortstring{$endif};
          FRealName : {$ifdef symansistr}TSymStr{$else}pshortstring{$endif};
+         function GetEscapedRealName: TSymStr;
          function  GetRealname: TSymStr;
          function  GetRealname: TSymStr;
          procedure SetRealname(const ANewName: TSymStr);
          procedure SetRealname(const ANewName: TSymStr);
       public
       public
@@ -80,6 +81,7 @@ interface
          Owner : TSymtable;
          Owner : TSymtable;
          destructor destroy;override;
          destructor destroy;override;
          property RealName: TSymStr read GetRealName write SetRealName;
          property RealName: TSymStr read GetRealName write SetRealName;
+         property EscapedRealName: TSymStr read GetEscapedRealName;
       end;
       end;
 
 
 {************************************************
 {************************************************
@@ -208,6 +210,14 @@ implementation
       end;
       end;
 
 
 
 
+    function TSymEntry.GetEscapedRealName: TSymStr;
+      begin
+        result:=GetRealname;
+        if result=Name then
+          result:='$'+result;
+      end;
+
+
     procedure TSymEntry.SetRealname(const ANewName:TSymStr);
     procedure TSymEntry.SetRealname(const ANewName:TSymStr);
       begin
       begin
 {$ifndef symansistr}
 {$ifndef symansistr}

+ 2 - 2
compiler/symcreat.pas

@@ -1257,7 +1257,7 @@ implementation
       else
       else
         begin
         begin
           symname:=sym.name;
           symname:=sym.name;
-          symrealname:=sym.realname;
+          symrealname:=sym.EscapedRealName;
         end;
         end;
       result:=search_struct_member(trecorddef(nestedvarsdef),symname);
       result:=search_struct_member(trecorddef(nestedvarsdef),symname);
       if not assigned(result) then
       if not assigned(result) then
@@ -1330,7 +1330,7 @@ implementation
           sl:=tpropaccesslist.create;
           sl:=tpropaccesslist.create;
           sl.addsym(sl_load,pd.parentfpstruct);
           sl.addsym(sl_load,pd.parentfpstruct);
           sl.addsym(sl_subscript,tfieldvarsym(fsym));
           sl.addsym(sl_subscript,tfieldvarsym(fsym));
-          aliassym:=cabsolutevarsym.create_ref(lsym.name,tfieldvarsym(fsym).vardef,sl);
+          aliassym:=cabsolutevarsym.create_ref(lsym.EscapedRealName,tfieldvarsym(fsym).vardef,sl);
           { hide the original variable (can't delete, because there
           { hide the original variable (can't delete, because there
             may be other loadnodes that reference it)
             may be other loadnodes that reference it)
             -- only for locals; hiding parameters changes the
             -- only for locals; hiding parameters changes the

+ 38 - 32
compiler/symdef.pas

@@ -1535,36 +1535,42 @@ implementation
         prefix:='';
         prefix:='';
         if not assigned(st) then
         if not assigned(st) then
          internalerror(200204212);
          internalerror(200204212);
-        { sub procedures }
-        while (st.symtabletype in [localsymtable,parasymtable]) do
-         begin
-           if st.defowner.typ<>procdef then
-            internalerror(200204173);
-           { Add the full mangledname of procedure to prevent
-             conflicts with 2 overloads having both a nested procedure
-             with the same name, see tb0314 (PFV) }
-           s:=tprocdef(st.defowner).procsym.name;
-           s:=s+tprocdef(st.defowner).mangledprocparanames(Length(s));
-           if prefix<>'' then
-             prefix:=s+'_'+prefix
-           else
-             prefix:=s;
-           if length(prefix)>100 then
-             begin
-               crc:=0;
-               crc:=UpdateCrc32(crc,prefix[1],length(prefix));
-               prefix:='$CRC'+hexstr(crc,8);
-             end;
-           st:=st.defowner.owner;
-         end;
-        { object/classes symtable, nested type definitions in classes require the while loop }
-        while st.symtabletype in [ObjectSymtable,recordsymtable] do
-         begin
-           if not (st.defowner.typ in [objectdef,recorddef]) then
-            internalerror(200204174);
-           prefix:=tabstractrecorddef(st.defowner).objname^+'_$_'+prefix;
-           st:=st.defowner.owner;
-         end;
+        repeat
+          { sub procedures }
+          while (st.symtabletype in [localsymtable,parasymtable]) do
+           begin
+             if st.defowner.typ<>procdef then
+              internalerror(200204173);
+             { Add the full mangledname of the routine to prevent
+               conflicts with two overloads both having a local entity
+               -- routine (tb0314), class, interface -- with the same name }
+             s:=tprocdef(st.defowner).procsym.name;
+             s:=s+tprocdef(st.defowner).mangledprocparanames(Length(s));
+             if prefix<>'' then
+               prefix:=s+'_'+prefix
+             else
+               prefix:=s;
+             if length(prefix)>100 then
+               begin
+                 crc:=0;
+                 crc:=UpdateCrc32(crc,prefix[1],length(prefix));
+                 prefix:='$CRC'+hexstr(crc,8);
+               end;
+             st:=st.defowner.owner;
+           end;
+          { object/classes symtable, nested type definitions in classes require the while loop }
+          while st.symtabletype in [ObjectSymtable,recordsymtable] do
+           begin
+             if not (st.defowner.typ in [objectdef,recorddef]) then
+              internalerror(200204174);
+             prefix:=tabstractrecorddef(st.defowner).objname^+'_$_'+prefix;
+             st:=st.defowner.owner;
+           end;
+          { local classes & interfaces are possible (because of closures) }
+          if st.symtabletype<>localsymtable then
+            break;
+          prefix:='$'+prefix;
+        until false;
         { symtable must now be static or global }
         { symtable must now be static or global }
         if not(st.symtabletype in [staticsymtable,globalsymtable]) then
         if not(st.symtabletype in [staticsymtable,globalsymtable]) then
           internalerror(200204175);
           internalerror(200204175);
@@ -5811,7 +5817,7 @@ implementation
 {$endif}
 {$endif}
         if (typ=procdef) and
         if (typ=procdef) and
            (newtyp=procvardef) and
            (newtyp=procvardef) and
-           (owner.symtabletype=ObjectSymtable) then
+           (owner.symtabletype in [ObjectSymtable,recordsymtable]) then
           include(tprocvardef(result).procoptions,po_methodpointer);
           include(tprocvardef(result).procoptions,po_methodpointer);
       end;
       end;
 
 
@@ -6636,7 +6642,7 @@ implementation
       begin
       begin
         { don't check assigned(_class), that's also the case for nested
         { don't check assigned(_class), that's also the case for nested
           procedures inside methods }
           procedures inside methods }
-        result:=(owner.symtabletype=ObjectSymtable)and not no_self_node;
+        result:=(owner.symtabletype in [recordsymtable,ObjectSymtable]) and not no_self_node;
       end;
       end;
 
 
 
 

+ 3 - 3
compiler/symsym.pas

@@ -496,7 +496,7 @@ interface
 
 
     { generate internal static field name based on regular field name }
     { generate internal static field name based on regular field name }
     function internal_static_field_name(const fieldname: TSymStr): TSymStr;
     function internal_static_field_name(const fieldname: TSymStr): TSymStr;
-    function get_high_value_sym(vs: tparavarsym):tsym; { marking it as inline causes IE 200311075 during loading from ppu file }
+    function get_high_value_sym(vs: tparavarsym):tabstractvarsym; { marking it as inline causes IE 200311075 during loading from ppu file }
 
 
     procedure check_hints(const srsym: tsym; const symoptions: tsymoptions; const deprecatedmsg : pshortstring);inline;
     procedure check_hints(const srsym: tsym; const symoptions: tsymoptions; const deprecatedmsg : pshortstring);inline;
     procedure check_hints(const srsym: tsym; const symoptions: tsymoptions; const deprecatedmsg : pshortstring;filepos:tfileposinfo);
     procedure check_hints(const srsym: tsym; const symoptions: tsymoptions; const deprecatedmsg : pshortstring;filepos:tfileposinfo);
@@ -534,9 +534,9 @@ implementation
       end;
       end;
 
 
 
 
-    function get_high_value_sym(vs: tparavarsym):tsym;
+    function get_high_value_sym(vs: tparavarsym):tabstractvarsym;
       begin
       begin
-        result := tsym(vs.owner.Find('high'+vs.name));
+        result := tabstractvarsym(vs.owner.Find('high'+vs.name));
       end;
       end;
 
 
 
 

+ 107 - 78
compiler/symtable.pas

@@ -197,10 +197,10 @@ interface
          procedure generate;
          procedure generate;
          // helpers
          // helpers
          procedure appenddefoffset(vardef:tdef; fieldoffset: aint; derefclass: boolean);
          procedure appenddefoffset(vardef:tdef; fieldoffset: aint; derefclass: boolean);
-         procedure findvariantstarts(variantstarts: tfplist);
+         procedure preprocess(out tempsymlist, variantstarts: tfplist);
          procedure addalignmentpadding(finalsize: aint);
          procedure addalignmentpadding(finalsize: aint);
-         procedure buildmapping(variantstarts: tfplist);
-         procedure buildtable(variantstarts: tfplist);
+         procedure buildmapping(tempsymlist, variantstarts: tfplist);
+         procedure buildtable(tempsymlist, variantstarts: tfplist);
        end;
        end;
 {$endif llvm}
 {$endif llvm}
 
 
@@ -1425,12 +1425,18 @@ implementation
         changed: boolean;
         changed: boolean;
       begin
       begin
         if maybereorder and
         if maybereorder and
-           (cs_opt_reorder_fields in current_settings.optimizerswitches) then
+           (cs_opt_reorder_fields in current_settings.optimizerswitches) and
+           (list.count>1) then
           begin
           begin
             { assign dummy field offsets so we can know their order in the
             { assign dummy field offsets so we can know their order in the
               sorting routine }
               sorting routine }
             for i:=0 to list.count-1 do
             for i:=0 to list.count-1 do
-              tfieldvarsym(list[i]).fieldoffset:=i;
+              begin
+                fieldvs:=tfieldvarsym(list[i]);
+                if sp_static in fieldvs.symoptions then
+                  continue;
+                fieldvs.fieldoffset:=i;
+              end;
             { sort the non-class fields to minimise losses due to alignment }
             { sort the non-class fields to minimise losses due to alignment }
             list.sort(@field_alignment_compare);
             list.sort(@field_alignment_compare);
             { now fill up gaps caused by alignment skips with smaller fields
             { now fill up gaps caused by alignment skips with smaller fields
@@ -1526,7 +1532,12 @@ implementation
         end;
         end;
         { reset the dummy field offsets }
         { reset the dummy field offsets }
         for i:=0 to list.count-1 do
         for i:=0 to list.count-1 do
-          tfieldvarsym(list[i]).fieldoffset:=-1;
+          begin
+            fieldvs:=tfieldvarsym(list[i]);
+            if sp_static in fieldvs.symoptions then
+              continue;
+            fieldvs.fieldoffset:=-1;
+          end;
         { finally, set the actual field offsets }
         { finally, set the actual field offsets }
         for i:=0 to list.count-1 do
         for i:=0 to list.count-1 do
           begin
           begin
@@ -2118,31 +2129,42 @@ implementation
 
 
     procedure tllvmshadowsymtable.addalignmentpadding(finalsize: aint);
     procedure tllvmshadowsymtable.addalignmentpadding(finalsize: aint);
       begin
       begin
-        case equivst.usefieldalignment of
-          { already correct in this case }
-          bit_alignment:
-            ;
-          else if not(df_llvm_no_struct_packing in tdef(equivst.defowner).defoptions) then
-            begin
-              { add padding fields }
-              while (finalsize>curroffset) do
-                begin
-                  symdeflist.add(tllvmshadowsymtableentry.create(u8inttype,curroffset));
-                  inc(curroffset);
-                end;
-            end;
-        end;
+        if not(df_llvm_no_struct_packing in tdef(equivst.defowner).defoptions) then
+          begin
+            if equivst.usefieldalignment=bit_alignment then
+              curroffset:=align(curroffset,8) div 8;
+            { add padding fields }
+            while (finalsize>curroffset) do
+              begin
+                symdeflist.add(tllvmshadowsymtableentry.create(u8inttype,curroffset));
+                inc(curroffset);
+              end;
+          end;
       end;
       end;
 
 
 
 
-    procedure tllvmshadowsymtable.findvariantstarts(variantstarts: tfplist);
+    function field_offset_compare(item1, item2: pointer): integer;
       var
       var
-        sym: tfieldvarsym;
-        lastoffset: aint;
+        field1: tfieldvarsym absolute item1;
+        field2: tfieldvarsym absolute item2;
+      begin
+        result:=field1.fieldoffset-field2.fieldoffset;
+      end;
+
+
+    procedure tllvmshadowsymtable.preprocess(out tempsymlist, variantstarts: tfplist);
+      var
+        fieldvs: tfieldvarsym;
+        lastvariantstartoffset, prevfieldoffset: aint;
         newalignment: aint;
         newalignment: aint;
         i, j: longint;
         i, j: longint;
+        sorttempsymlist: boolean;
       begin
       begin
         i:=0;
         i:=0;
+        variantstarts:=nil;
+        tempsymlist:=tfplist.create;
+        sorttempsymlist:=false;
+        prevfieldoffset:=-1;
         while (i<equivst.symlist.count) do
         while (i<equivst.symlist.count) do
           begin
           begin
             if not is_normal_fieldvarsym(tsym(equivst.symlist[i])) then
             if not is_normal_fieldvarsym(tsym(equivst.symlist[i])) then
@@ -2150,38 +2172,42 @@ implementation
                 inc(i);
                 inc(i);
                 continue;
                 continue;
               end;
               end;
-            sym:=tfieldvarsym(equivst.symlist[i]);
+            fieldvs:=tfieldvarsym(equivst.symlist[i]);
+            tempsymlist.Add(fieldvs);
             { a "better" algorithm might be to use the largest }
             { a "better" algorithm might be to use the largest }
             { variant in case of (bit)packing, since then      }
             { variant in case of (bit)packing, since then      }
             { alignment doesn't matter                         }
             { alignment doesn't matter                         }
-            if (vo_is_first_field in sym.varoptions) then
+            if (vo_is_first_field in fieldvs.varoptions) then
               begin
               begin
                 { we assume that all fields are processed in order. }
                 { we assume that all fields are processed in order. }
-                if (variantstarts.count<>0) then
-                  lastoffset:=tfieldvarsym(variantstarts[variantstarts.count-1]).fieldoffset
+                if assigned(variantstarts) then
+                  lastvariantstartoffset:=tfieldvarsym(variantstarts[variantstarts.count-1]).fieldoffset
                 else
                 else
-                  lastoffset:=-1;
+                  begin
+                    lastvariantstartoffset:=-1;
+                    variantstarts:=tfplist.create;
+                  end;
 
 
                 { new variant at same level as last one: use if higher alignment }
                 { new variant at same level as last one: use if higher alignment }
-                if (lastoffset=sym.fieldoffset) then
+                if (lastvariantstartoffset=fieldvs.fieldoffset) then
                   begin
                   begin
-                    if (equivst.fieldalignment<>bit_alignment) then
-                      newalignment:=used_align(sym.vardef.alignment,equivst.recordalignmin,equivst.fieldalignment)
+                    if (equivst.usefieldalignment<>bit_alignment) then
+                      newalignment:=used_align(fieldvs.vardef.alignment,equivst.recordalignmin,equivst.fieldalignment)
                     else
                     else
                       newalignment:=1;
                       newalignment:=1;
                     if (newalignment>tfieldvarsym(variantstarts[variantstarts.count-1]).vardef.alignment) then
                     if (newalignment>tfieldvarsym(variantstarts[variantstarts.count-1]).vardef.alignment) then
-                      variantstarts[variantstarts.count-1]:=sym;
+                      variantstarts[variantstarts.count-1]:=fieldvs;
                   end
                   end
                 { variant at deeper level than last one -> add }
                 { variant at deeper level than last one -> add }
-                else if (lastoffset<sym.fieldoffset) then
-                  variantstarts.add(sym)
+                else if (lastvariantstartoffset<fieldvs.fieldoffset) then
+                  variantstarts.add(fieldvs)
                 else
                 else
                   begin
                   begin
                     { a variant at a less deep level, so backtrack }
                     { a variant at a less deep level, so backtrack }
                     j:=variantstarts.count-2;
                     j:=variantstarts.count-2;
                     while (j>=0) do
                     while (j>=0) do
                       begin
                       begin
-                        if (tfieldvarsym(variantstarts[j]).fieldoffset=sym.fieldoffset) then
+                        if (tfieldvarsym(variantstarts[j]).fieldoffset=fieldvs.fieldoffset) then
                           break;
                           break;
                         dec(j);
                         dec(j);
                       end;
                       end;
@@ -2189,13 +2215,13 @@ implementation
                       internalerror(2008051003);
                       internalerror(2008051003);
                     { new variant has higher alignment? }
                     { new variant has higher alignment? }
                     if (equivst.fieldalignment<>bit_alignment) then
                     if (equivst.fieldalignment<>bit_alignment) then
-                      newalignment:=used_align(sym.vardef.alignment,equivst.recordalignmin,equivst.fieldalignment)
+                      newalignment:=used_align(fieldvs.vardef.alignment,equivst.recordalignmin,equivst.fieldalignment)
                     else
                     else
                       newalignment:=1;
                       newalignment:=1;
                     { yes, replace and remove previous nested variants }
                     { yes, replace and remove previous nested variants }
                     if (newalignment>tfieldvarsym(variantstarts[j]).vardef.alignment) then
                     if (newalignment>tfieldvarsym(variantstarts[j]).vardef.alignment) then
                       begin
                       begin
-                        variantstarts[j]:=sym;
+                        variantstarts[j]:=fieldvs;
                         variantstarts.count:=j+1;
                         variantstarts.count:=j+1;
                       end
                       end
                    { no, skip this variant }
                    { no, skip this variant }
@@ -2204,91 +2230,95 @@ implementation
                         inc(i);
                         inc(i);
                         while (i<equivst.symlist.count) and
                         while (i<equivst.symlist.count) and
                               (not is_normal_fieldvarsym(tsym(equivst.symlist[i])) or
                               (not is_normal_fieldvarsym(tsym(equivst.symlist[i])) or
-                               (tfieldvarsym(equivst.symlist[i]).fieldoffset>sym.fieldoffset)) do
-                          inc(i);
+                               (tfieldvarsym(equivst.symlist[i]).fieldoffset>fieldvs.fieldoffset)) do
+                          begin
+                            if is_normal_fieldvarsym(tsym(equivst.symlist[i])) then
+                              tempsymlist.Add(equivst.symlist[i]);
+                            inc(i);
+                          end;
                         continue;
                         continue;
                       end;
                       end;
                   end;
                   end;
               end;
               end;
+            if not assigned(variantstarts) and
+               (fieldvs.fieldoffset<prevfieldoffset) then
+              sorttempsymlist:=true;
+            prevfieldoffset:=fieldvs.fieldoffset;
             inc(i);
             inc(i);
           end;
           end;
+        if sorttempsymlist then
+          tempsymlist.Sort(@field_offset_compare);
       end;
       end;
 
 
 
 
-    procedure tllvmshadowsymtable.buildtable(variantstarts: tfplist);
+    procedure tllvmshadowsymtable.buildtable(tempsymlist, variantstarts: tfplist);
       var
       var
         lastvaroffsetprocessed: aint;
         lastvaroffsetprocessed: aint;
-        i, equivcount, varcount: longint;
+        i, symcount, varcount: longint;
+        fieldvs: tfieldvarsym;
       begin
       begin
         { if it's an object/class, the first entry is the parent (if there is one) }
         { if it's an object/class, the first entry is the parent (if there is one) }
         if (equivst.symtabletype=objectsymtable) and
         if (equivst.symtabletype=objectsymtable) and
            assigned(tobjectdef(equivst.defowner).childof) then
            assigned(tobjectdef(equivst.defowner).childof) then
           appenddefoffset(tobjectdef(equivst.defowner).childof,0,is_class_or_interface_or_dispinterface(tobjectdef(equivst.defowner).childof));
           appenddefoffset(tobjectdef(equivst.defowner).childof,0,is_class_or_interface_or_dispinterface(tobjectdef(equivst.defowner).childof));
-        equivcount:=equivst.symlist.count;
+        symcount:=tempsymlist.count;
         varcount:=0;
         varcount:=0;
         i:=0;
         i:=0;
         lastvaroffsetprocessed:=-1;
         lastvaroffsetprocessed:=-1;
-        while (i<equivcount) do
+        while (i<symcount) do
           begin
           begin
-            if not is_normal_fieldvarsym(tsym(equivst.symlist[i])) then
-              begin
-                inc(i);
-                continue;
-              end;
+            fieldvs:=tfieldvarsym(tempsymlist[i]);
             { start of a new variant? }
             { start of a new variant? }
-            if (vo_is_first_field in tfieldvarsym(equivst.symlist[i]).varoptions) then
+            if (vo_is_first_field in fieldvs.varoptions) then
               begin
               begin
                 { if we want to process the same variant offset twice, it means that we  }
                 { if we want to process the same variant offset twice, it means that we  }
                 { got to the end and are trying to process the next variant part -> stop }
                 { got to the end and are trying to process the next variant part -> stop }
-                if (tfieldvarsym(equivst.symlist[i]).fieldoffset<=lastvaroffsetprocessed) then
+                if (fieldvs.fieldoffset<=lastvaroffsetprocessed) then
                   break;
                   break;
 
 
                 if (varcount>=variantstarts.count) then
                 if (varcount>=variantstarts.count) then
                   internalerror(2008051005);
                   internalerror(2008051005);
                 { new variant part -> use the one with the biggest alignment }
                 { new variant part -> use the one with the biggest alignment }
-                i:=equivst.symlist.indexof(tobject(variantstarts[varcount]));
-                lastvaroffsetprocessed:=tfieldvarsym(equivst.symlist[i]).fieldoffset;
+                i:=tempsymlist.indexof(tobject(variantstarts[varcount]));
+                lastvaroffsetprocessed:=fieldvs.fieldoffset;
                 inc(varcount);
                 inc(varcount);
                 if (i<0) then
                 if (i<0) then
                   internalerror(2008051004);
                   internalerror(2008051004);
               end;
               end;
-            appenddefoffset(tfieldvarsym(equivst.symlist[i]).vardef,tfieldvarsym(equivst.symlist[i]).fieldoffset,false);
+            appenddefoffset(fieldvs.vardef,fieldvs.fieldoffset,false);
             inc(i);
             inc(i);
           end;
           end;
         addalignmentpadding(equivst.datasize);
         addalignmentpadding(equivst.datasize);
       end;
       end;
 
 
 
 
-    procedure tllvmshadowsymtable.buildmapping(variantstarts: tfplist);
+    procedure tllvmshadowsymtable.buildmapping(tempsymlist, variantstarts: tfplist);
       var
       var
+        fieldvs: tfieldvarsym;
         i, varcount: longint;
         i, varcount: longint;
         shadowindex: longint;
         shadowindex: longint;
-        equivcount : longint;
+        symcount : longint;
       begin
       begin
         varcount:=0;
         varcount:=0;
         shadowindex:=0;
         shadowindex:=0;
-        equivcount:=equivst.symlist.count;
+        symcount:=tempsymlist.count;
         i:=0;
         i:=0;
-        while (i < equivcount) do
+        while (i<symcount) do
           begin
           begin
-            if not is_normal_fieldvarsym(tsym(equivst.symlist[i])) then
-              begin
-                inc(i);
-                continue;
-              end;
+            fieldvs:=tfieldvarsym(tempsymlist[i]);
             { start of a new variant? }
             { start of a new variant? }
-            if (vo_is_first_field in tfieldvarsym(equivst.symlist[i]).varoptions) then
+            if (vo_is_first_field in fieldvs.varoptions) then
               begin
               begin
                 { back up to a less deeply nested variant level? }
                 { back up to a less deeply nested variant level? }
-                while (tfieldvarsym(equivst.symlist[i]).fieldoffset<tfieldvarsym(variantstarts[varcount]).fieldoffset) do
+                while fieldvs.fieldoffset<tfieldvarsym(variantstarts[varcount]).fieldoffset do
                   dec(varcount);
                   dec(varcount);
                 { it's possible that some variants are more deeply nested than the
                 { it's possible that some variants are more deeply nested than the
                   one we recorded in the shadowsymtable (since we recorded the one
                   one we recorded in the shadowsymtable (since we recorded the one
                   with the biggest alignment, not necessarily the biggest one in size
                   with the biggest alignment, not necessarily the biggest one in size
                 }
                 }
-                if (tfieldvarsym(equivst.symlist[i]).fieldoffset>tfieldvarsym(variantstarts[varcount]).fieldoffset) then
+                if fieldvs.fieldoffset>tfieldvarsym(variantstarts[varcount]).fieldoffset then
                   varcount:=variantstarts.count-1
                   varcount:=variantstarts.count-1
-                else if (tfieldvarsym(equivst.symlist[i]).fieldoffset<>tfieldvarsym(variantstarts[varcount]).fieldoffset) then
+                else if fieldvs.fieldoffset<>tfieldvarsym(variantstarts[varcount]).fieldoffset then
                   internalerror(2008051006);
                   internalerror(2008051006);
                 { reset the shadowindex to the start of this variant. }
                 { reset the shadowindex to the start of this variant. }
                 { in case the llvmfieldnr is not (yet) set for this   }
                 { in case the llvmfieldnr is not (yet) set for this   }
@@ -2300,15 +2330,15 @@ implementation
               end;
               end;
 
 
             { find the last shadowfield whose offset <= the current field's offset }
             { find the last shadowfield whose offset <= the current field's offset }
-            while (tllvmshadowsymtableentry(symdeflist[shadowindex]).fieldoffset<tfieldvarsym(equivst.symlist[i]).fieldoffset) and
+            while (tllvmshadowsymtableentry(symdeflist[shadowindex]).fieldoffset<fieldvs.fieldoffset) and
                   (shadowindex<symdeflist.count-1) and
                   (shadowindex<symdeflist.count-1) and
-                  (tllvmshadowsymtableentry(symdeflist[shadowindex+1]).fieldoffset<=tfieldvarsym(equivst.symlist[i]).fieldoffset) do
+                  (tllvmshadowsymtableentry(symdeflist[shadowindex+1]).fieldoffset<=fieldvs.fieldoffset) do
               inc(shadowindex);
               inc(shadowindex);
             { set the field number and potential offset from that field (in case }
             { set the field number and potential offset from that field (in case }
             { of overlapping variants)                                           }
             { of overlapping variants)                                           }
-            tfieldvarsym(equivst.symlist[i]).llvmfieldnr:=shadowindex;
-            tfieldvarsym(equivst.symlist[i]).offsetfromllvmfield:=
-              tfieldvarsym(equivst.symlist[i]).fieldoffset-tllvmshadowsymtableentry(symdeflist[shadowindex]).fieldoffset;
+            fieldvs.llvmfieldnr:=shadowindex;
+            fieldvs.offsetfromllvmfield:=
+              fieldvs.fieldoffset-tllvmshadowsymtableentry(symdeflist[shadowindex]).fieldoffset;
             inc(i);
             inc(i);
           end;
           end;
       end;
       end;
@@ -2316,23 +2346,22 @@ implementation
 
 
     procedure tllvmshadowsymtable.generate;
     procedure tllvmshadowsymtable.generate;
       var
       var
-        variantstarts: tfplist;
+        variantstarts, tempsymlist: tfplist;
       begin
       begin
-        variantstarts:=tfplist.create;
-
         { first go through the entire record and }
         { first go through the entire record and }
         { store the fieldvarsyms of the variants }
         { store the fieldvarsyms of the variants }
         { with the highest alignment             }
         { with the highest alignment             }
-        findvariantstarts(variantstarts);
+        preprocess(tempsymlist, variantstarts);
 
 
         { now go through the regular fields and the selected variants, }
         { now go through the regular fields and the selected variants, }
-        { and add them to the  llvm shadow record symtable             }
-        buildtable(variantstarts);
+        { and add them to the llvm shadow record symtable             }
+        buildtable(tempsymlist, variantstarts);
 
 
         { finally map all original fields to the llvm definition }
         { finally map all original fields to the llvm definition }
-        buildmapping(variantstarts);
+        buildmapping(tempsymlist, variantstarts);
 
 
         variantstarts.free;
         variantstarts.free;
+        tempsymlist.free;
       end;
       end;
 
 
 {$endif llvm}
 {$endif llvm}

+ 345 - 103
compiler/x86/aoptx86.pas

@@ -146,12 +146,14 @@ unit aoptx86;
         function OptPass2Jcc(var p : tai) : boolean;
         function OptPass2Jcc(var p : tai) : boolean;
         function OptPass2Lea(var p: tai): Boolean;
         function OptPass2Lea(var p: tai): Boolean;
         function OptPass2SUB(var p: tai): Boolean;
         function OptPass2SUB(var p: tai): Boolean;
+        function OptPass2ADD(var p : tai): Boolean;
 
 
         function PostPeepholeOptMov(var p : tai) : Boolean;
         function PostPeepholeOptMov(var p : tai) : Boolean;
 {$ifdef x86_64} { These post-peephole optimisations only affect 64-bit registers. [Kit] }
 {$ifdef x86_64} { These post-peephole optimisations only affect 64-bit registers. [Kit] }
         function PostPeepholeOptMovzx(var p : tai) : Boolean;
         function PostPeepholeOptMovzx(var p : tai) : Boolean;
         function PostPeepholeOptXor(var p : tai) : Boolean;
         function PostPeepholeOptXor(var p : tai) : Boolean;
 {$endif}
 {$endif}
+        function PostPeepholeOptAnd(var p : tai) : boolean;
         function PostPeepholeOptMOVSX(var p : tai) : boolean;
         function PostPeepholeOptMOVSX(var p : tai) : boolean;
         function PostPeepholeOptCmp(var p : tai) : Boolean;
         function PostPeepholeOptCmp(var p : tai) : Boolean;
         function PostPeepholeOptTestOr(var p : tai) : Boolean;
         function PostPeepholeOptTestOr(var p : tai) : Boolean;
@@ -3000,6 +3002,23 @@ unit aoptx86;
                       check opsize to avoid overflow when left shifting the 1 }
                       check opsize to avoid overflow when left shifting the 1 }
                     if (taicpu(p).oper[0]^.typ=top_const) and (topsize2memsize[taicpu(hp2).opsize]<=63) then
                     if (taicpu(p).oper[0]^.typ=top_const) and (topsize2memsize[taicpu(hp2).opsize]<=63) then
                       taicpu(p).oper[0]^.val:=taicpu(p).oper[0]^.val and ((qword(1) shl topsize2memsize[taicpu(hp2).opsize])-1);
                       taicpu(p).oper[0]^.val:=taicpu(p).oper[0]^.val and ((qword(1) shl topsize2memsize[taicpu(hp2).opsize])-1);
+
+{$ifdef x86_64}
+                    { Be careful of, for example:
+                        movl %reg1,%reg2
+                        addl %reg3,%reg2
+                        movq %reg2,%reg4
+
+                      This will cause problems if the upper 32-bits of %reg3 or %reg4 are non-zero
+                    }
+                    if (taicpu(hp1).opsize = S_L) and (taicpu(hp2).opsize = S_Q) then
+                      begin
+                        taicpu(hp2).changeopsize(S_L);
+                        setsubreg(taicpu(hp2).oper[0]^.reg, R_SUBD);
+                        setsubreg(taicpu(hp2).oper[1]^.reg, R_SUBD);
+                      end;
+{$endif x86_64}
+
                     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
@@ -5706,6 +5725,55 @@ unit aoptx86;
             Result := True;
             Result := True;
             Exit;
             Exit;
           end
           end
+        else if reg_and_hp1_is_instr and
+          (taicpu(p).oper[0]^.typ = top_reg) and
+          (
+            ((taicpu(hp1).opcode = A_SHR) and (taicpu(p).opcode = A_MOVZX)) or
+            ((taicpu(hp1).opcode = A_SAR) and (taicpu(p).opcode <> A_MOVZX))
+          ) and
+          (taicpu(hp1).oper[0]^.typ = top_const) and
+          SuperRegistersEqual(taicpu(p).oper[0]^.reg, taicpu(p).oper[1]^.reg) and
+          MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[1]^.reg) and
+          { Minimum shift value allowed is the bit size of the smallest register - 1 }
+          (taicpu(hp1).oper[0]^.val <
+            { Multiply by 8 because tcgsize2size returns bytes, not bits }
+            8 * (
+              tcgsize2size[reg_cgsize(taicpu(p).oper[0]^.reg)]
+            )
+          ) then
+          begin
+            { For:
+                movsx   %reg1,%reg1     movzx   %reg1,%reg1   (same register, just different sizes)
+                sar     ##,   %reg1     shr     ##,   %reg1
+
+              Move the shift to before the movx instruction if the shift value
+              is not too large.
+            }
+            asml.Remove(hp1);
+            asml.InsertBefore(hp1, p);
+
+            taicpu(hp1).oper[1]^.reg := taicpu(p).oper[0]^.reg;
+
+            case taicpu(p).opsize of
+              s_BW, S_BL{$ifdef x86_64}, S_BQ{$endif}:
+                taicpu(hp1).opsize := S_B;
+              S_WL{$ifdef x86_64}, S_WQ{$endif}:
+                taicpu(hp1).opsize := S_W;
+              {$ifdef x86_64}
+              S_LQ:
+                taicpu(hp1).opsize := S_L;
+              {$endif}
+              else
+                InternalError(2020112401);
+            end;
+
+            if (taicpu(hp1).opcode = A_SHR) then
+              DebugMsg(SPeepholeOptimization + 'MovzShr2ShrMovz', hp1)
+            else
+              DebugMsg(SPeepholeOptimization + 'MovsSar2SarMovs', hp1);
+
+            Result := True;
+          end
         else if taicpu(p).opcode=A_MOVZX then
         else if taicpu(p).opcode=A_MOVZX then
           begin
           begin
             { removes superfluous And's after movzx's }
             { removes superfluous And's after movzx's }
@@ -5952,132 +6020,181 @@ unit aoptx86;
 
 
     function TX86AsmOptimizer.OptPass1AND(var p : tai) : boolean;
     function TX86AsmOptimizer.OptPass1AND(var p : tai) : boolean;
       var
       var
-        hp1 : tai;
+        hp1, hp2 : tai;
         MaskLength : Cardinal;
         MaskLength : Cardinal;
+        MaskedBits : TCgInt;
       begin
       begin
         Result:=false;
         Result:=false;
 
 
-        if GetNextInstruction(p, hp1) then
+        { There are no optimisations for reference targets }
+        if (taicpu(p).oper[1]^.typ <> top_reg) then
+          Exit;
+
+        while GetNextInstruction(p, hp1) and
+          (hp1.typ = ait_instruction) do
           begin
           begin
-            if MatchOpType(taicpu(p),top_const,top_reg) and
-              MatchInstruction(hp1,A_AND,[]) and
-              MatchOpType(taicpu(hp1),top_const,top_reg) and
-              (getsupreg(taicpu(p).oper[1]^.reg) = getsupreg(taicpu(hp1).oper[1]^.reg)) and
-              { the second register must contain the first one, so compare their subreg types }
-              (getsubreg(taicpu(p).oper[1]^.reg)<=getsubreg(taicpu(hp1).oper[1]^.reg)) and
-              (abs(taicpu(p).oper[0]^.val and taicpu(hp1).oper[0]^.val)<$80000000) then
-              { change
-                  and const1, reg
-                  and const2, reg
-                to
-                  and (const1 and const2), reg
-              }
+            if (taicpu(p).oper[0]^.typ = top_const) then
               begin
               begin
-                taicpu(hp1).loadConst(0, taicpu(p).oper[0]^.val and taicpu(hp1).oper[0]^.val);
-                DebugMsg(SPeepholeOptimization + 'AndAnd2And done',hp1);
-                RemoveCurrentP(p, hp1);
-                Result:=true;
-                exit;
-              end
-            else if MatchOpType(taicpu(p),top_const,top_reg) and
-              MatchInstruction(hp1,A_MOVZX,[]) and
-              MatchOpType(taicpu(hp1),top_reg,top_reg) and
-              SuperRegistersEqual(taicpu(p).oper[1]^.reg,taicpu(hp1).oper[1]^.reg) and
-              (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(hp1).oper[1]^.reg)) and
-               (((taicpu(p).opsize=S_W) and
-                 (taicpu(hp1).opsize=S_BW)) or
-                ((taicpu(p).opsize=S_L) and
-                 (taicpu(hp1).opsize in [S_WL,S_BL{$ifdef x86_64},S_BQ,S_WQ{$endif x86_64}]))
+                if (taicpu(hp1).opcode = A_AND) and
+                  MatchOpType(taicpu(hp1),top_const,top_reg) and
+                  (getsupreg(taicpu(p).oper[1]^.reg) = getsupreg(taicpu(hp1).oper[1]^.reg)) and
+                  { the second register must contain the first one, so compare their subreg types }
+                  (getsubreg(taicpu(p).oper[1]^.reg)<=getsubreg(taicpu(hp1).oper[1]^.reg)) and
+                  (abs(taicpu(p).oper[0]^.val and taicpu(hp1).oper[0]^.val)<$80000000) then
+                  { change
+                      and const1, reg
+                      and const2, reg
+                    to
+                      and (const1 and const2), reg
+                  }
+                  begin
+                    taicpu(hp1).loadConst(0, taicpu(p).oper[0]^.val and taicpu(hp1).oper[0]^.val);
+                    DebugMsg(SPeepholeOptimization + 'AndAnd2And done',hp1);
+                    RemoveCurrentP(p, hp1);
+                    Result:=true;
+                    exit;
+                  end
+                else if (taicpu(hp1).opcode = A_MOVZX) and
+                  MatchOpType(taicpu(hp1),top_reg,top_reg) and
+                  SuperRegistersEqual(taicpu(p).oper[1]^.reg,taicpu(hp1).oper[1]^.reg) and
+                  (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(hp1).oper[1]^.reg)) and
+                   (((taicpu(p).opsize=S_W) and
+                     (taicpu(hp1).opsize=S_BW)) or
+                    ((taicpu(p).opsize=S_L) and
+                     (taicpu(hp1).opsize in [S_WL,S_BL{$ifdef x86_64},S_BQ,S_WQ{$endif x86_64}]))
 {$ifdef x86_64}
 {$ifdef x86_64}
-                  or
-                 ((taicpu(p).opsize=S_Q) and
-                  (taicpu(hp1).opsize in [S_BQ,S_WQ,S_BL,S_WL]))
+                      or
+                     ((taicpu(p).opsize=S_Q) and
+                      (taicpu(hp1).opsize in [S_BQ,S_WQ,S_BL,S_WL]))
 {$endif x86_64}
 {$endif x86_64}
-                ) then
-                  begin
-                    if (((taicpu(hp1).opsize) in [S_BW,S_BL{$ifdef x86_64},S_BQ{$endif x86_64}]) and
-                        ((taicpu(p).oper[0]^.val and $ff)=taicpu(p).oper[0]^.val)
-                         ) or
-                       (((taicpu(hp1).opsize) in [S_WL{$ifdef x86_64},S_WQ{$endif x86_64}]) and
-                        ((taicpu(p).oper[0]^.val and $ffff)=taicpu(p).oper[0]^.val))
-                    then
+                    ) then
                       begin
                       begin
-                        { Unlike MOVSX, MOVZX doesn't actually have a version that zero-extends a
-                          32-bit register to a 64-bit register, or even a version called MOVZXD, so
-                          code that tests for the presence of AND 0xffffffff followed by MOVZX is
-                          wasted, and is indictive of a compiler bug if it were triggered. [Kit]
+                        if (((taicpu(hp1).opsize) in [S_BW,S_BL{$ifdef x86_64},S_BQ{$endif x86_64}]) and
+                            ((taicpu(p).oper[0]^.val and $ff)=taicpu(p).oper[0]^.val)
+                             ) or
+                           (((taicpu(hp1).opsize) in [S_WL{$ifdef x86_64},S_WQ{$endif x86_64}]) and
+                            ((taicpu(p).oper[0]^.val and $ffff)=taicpu(p).oper[0]^.val))
+                        then
+                          begin
+                            { Unlike MOVSX, MOVZX doesn't actually have a version that zero-extends a
+                              32-bit register to a 64-bit register, or even a version called MOVZXD, so
+                              code that tests for the presence of AND 0xffffffff followed by MOVZX is
+                              wasted, and is indictive of a compiler bug if it were triggered. [Kit]
 
 
-                          NOTE: To zero-extend from 32 bits to 64 bits, simply use the standard MOV.
-                        }
-                        DebugMsg(SPeepholeOptimization + 'AndMovzToAnd done',p);
+                              NOTE: To zero-extend from 32 bits to 64 bits, simply use the standard MOV.
+                            }
+                            DebugMsg(SPeepholeOptimization + 'AndMovzToAnd done',p);
 
 
-                        RemoveInstruction(hp1);
-                        Exit;
-                      end;
-                  end
-            else if MatchOpType(taicpu(p),top_const,top_reg) and
-              MatchInstruction(hp1,A_SHL,[]) and
-              MatchOpType(taicpu(hp1),top_const,top_reg) and
-              (getsupreg(taicpu(p).oper[1]^.reg)=getsupreg(taicpu(hp1).oper[1]^.reg)) then
-              begin
+                            RemoveInstruction(hp1);
+
+                            { See if there are other optimisations possible }
+                            Continue;
+                          end;
+                      end
+                else if (taicpu(hp1).opcode = A_SHL) and
+                  MatchOpType(taicpu(hp1),top_const,top_reg) and
+                  (getsupreg(taicpu(p).oper[1]^.reg)=getsupreg(taicpu(hp1).oper[1]^.reg)) then
+                  begin
 {$ifopt R+}
 {$ifopt R+}
 {$define RANGE_WAS_ON}
 {$define RANGE_WAS_ON}
 {$R-}
 {$R-}
 {$endif}
 {$endif}
-                { get length of potential and mask }
-                MaskLength:=SizeOf(taicpu(p).oper[0]^.val)*8-BsrQWord(taicpu(p).oper[0]^.val)-1;
+                    { get length of potential and mask }
+                    MaskLength:=SizeOf(taicpu(p).oper[0]^.val)*8-BsrQWord(taicpu(p).oper[0]^.val)-1;
 
 
-                { really a mask? }
+                    { really a mask? }
 {$ifdef RANGE_WAS_ON}
 {$ifdef RANGE_WAS_ON}
 {$R+}
 {$R+}
 {$endif}
 {$endif}
-                if (((QWord(1) shl MaskLength)-1)=taicpu(p).oper[0]^.val) and
-                  { unmasked part shifted out? }
-                  ((MaskLength+taicpu(hp1).oper[0]^.val)>=topsize2memsize[taicpu(hp1).opsize]) then
+                    if (((QWord(1) shl MaskLength)-1)=taicpu(p).oper[0]^.val) and
+                      { unmasked part shifted out? }
+                      ((MaskLength+taicpu(hp1).oper[0]^.val)>=topsize2memsize[taicpu(hp1).opsize]) then
+                      begin
+                        DebugMsg(SPeepholeOptimization + 'AndShlToShl done',p);
+                        RemoveCurrentP(p, hp1);
+                        Result:=true;
+                        exit;
+                      end;
+                  end
+                else if (taicpu(hp1).opcode = A_SHR) and
+                  MatchOpType(taicpu(hp1),top_const,top_reg) and
+                  (taicpu(p).oper[1]^.reg = taicpu(hp1).oper[1]^.reg) and
+                  (taicpu(hp1).oper[0]^.val <= 63) then
                   begin
                   begin
-                    DebugMsg(SPeepholeOptimization + 'AndShlToShl done',p);
-                    RemoveCurrentP(p, hp1);
-                    Result:=true;
-                    exit;
-                  end;
-              end
-            else if MatchOpType(taicpu(p),top_const,top_reg) and
-              MatchInstruction(hp1,A_MOVSX{$ifdef x86_64},A_MOVSXD{$endif x86_64},[]) and
-              (taicpu(hp1).oper[0]^.typ = top_reg) and
-              MatchOperand(taicpu(p).oper[1]^,taicpu(hp1).oper[1]^) and
-              (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(hp1).oper[1]^.reg)) and
-               (((taicpu(p).opsize=S_W) and
-                 (taicpu(hp1).opsize=S_BW)) or
-                ((taicpu(p).opsize=S_L) and
-                 (taicpu(hp1).opsize in [S_WL,S_BL]))
+                    { Does SHR combined with the AND cover all the bits?
+
+                      e.g. for "andb $252,%reg; shrb $2,%reg" - the "and" can be removed }
+
+                    MaskedBits := taicpu(p).oper[0]^.val or ((TCgInt(1) shl taicpu(hp1).oper[0]^.val) - 1);
+
+                    if ((taicpu(p).opsize = S_B) and ((MaskedBits and $FF) = $FF)) or
+                      ((taicpu(p).opsize = S_W) and ((MaskedBits and $FFFF) = $FFFF)) or
+                      ((taicpu(p).opsize = S_L) and ((MaskedBits and $FFFFFFFF) = $FFFFFFFF)) then
+                      begin
+                        DebugMsg(SPeepholeOptimization + 'AndShrToShr done', p);
+                        RemoveCurrentP(p, hp1);
+                        Result := True;
+                        Exit;
+                      end;
+                  end
+                else if ((taicpu(hp1).opcode = A_MOVSX){$ifdef x86_64} or (taicpu(hp1).opcode = A_MOVSXD){$endif x86_64}) and
+                  (taicpu(hp1).oper[0]^.typ = top_reg) and
+                  SuperRegistersEqual(taicpu(hp1).oper[0]^.reg, taicpu(hp1).oper[1]^.reg) then
+                    begin
+                      if SuperRegistersEqual(taicpu(p).oper[1]^.reg, taicpu(hp1).oper[1]^.reg) and
+                        (
+                          (
+                            (taicpu(hp1).opsize in [S_BW,S_BL{$ifdef x86_64},S_BQ{$endif x86_64}]) and
+                            ((taicpu(p).oper[0]^.val and $7F) = taicpu(p).oper[0]^.val)
+                          ) or (
+                            (taicpu(hp1).opsize in [S_WL{$ifdef x86_64},S_WQ{$endif x86_64}]) and
+                            ((taicpu(p).oper[0]^.val and $7FFF) = taicpu(p).oper[0]^.val)
 {$ifdef x86_64}
 {$ifdef x86_64}
-                 or
-                 ((taicpu(p).opsize=S_Q) and
-                 (taicpu(hp1).opsize in [S_BQ,S_WQ,S_LQ]))
+                          ) or (
+                            (taicpu(hp1).opsize = S_LQ) and
+                            ((taicpu(p).oper[0]^.val and $7fffffff) = taicpu(p).oper[0]^.val)
 {$endif x86_64}
 {$endif x86_64}
-                ) then
-                  begin
-                    if (((taicpu(hp1).opsize) in [S_BW,S_BL{$ifdef x86_64},S_BQ{$endif x86_64}]) and
-                        ((taicpu(p).oper[0]^.val and $7f)=taicpu(p).oper[0]^.val)
-                         ) or
-                       (((taicpu(hp1).opsize) in [S_WL{$ifdef x86_64},S_WQ{$endif x86_64}]) and
-                        ((taicpu(p).oper[0]^.val and $7fff)=taicpu(p).oper[0]^.val))
+                          )
+                        ) then
+                        begin
+                          if (taicpu(p).oper[1]^.reg = taicpu(hp1).oper[1]^.reg){$ifdef x86_64} or (taicpu(hp1).opsize = S_LQ){$endif x86_64} then
+                            begin
+                              DebugMsg(SPeepholeOptimization + 'AndMovsxToAnd',p);
+                              RemoveInstruction(hp1);
+                              { See if there are other optimisations possible }
+                              Continue;
+                            end;
+
+                          { The super-registers are the same though.
+
+                            Note that this change by itself doesn't improve
+                            code speed, but it opens up other optimisations. }
 {$ifdef x86_64}
 {$ifdef x86_64}
-                       or
-                       (((taicpu(hp1).opsize)=S_LQ) and
-                        ((taicpu(p).oper[0]^.val and $7fffffff)=taicpu(p).oper[0]^.val)
-                       )
+                          { Convert 64-bit register to 32-bit }
+                          case taicpu(hp1).opsize of
+                            S_BQ:
+                              begin
+                                taicpu(hp1).opsize := S_BL;
+                                taicpu(hp1).oper[1]^.reg := newreg(R_INTREGISTER, getsupreg(taicpu(hp1).oper[1]^.reg), R_SUBD);
+                              end;
+                            S_WQ:
+                              begin
+                                taicpu(hp1).opsize := S_WL;
+                                taicpu(hp1).oper[1]^.reg := newreg(R_INTREGISTER, getsupreg(taicpu(hp1).oper[1]^.reg), R_SUBD);
+                              end
+                            else
+                              ;
+                          end;
 {$endif x86_64}
 {$endif x86_64}
-                       then
-                       begin
-                         DebugMsg(SPeepholeOptimization + 'AndMovsxToAnd',p);
-                         RemoveInstruction(hp1);
-                         Exit;
-                       end;
-                  end
-            else if (taicpu(p).oper[1]^.typ = top_reg) and
-              (hp1.typ = ait_instruction) and
-              (taicpu(hp1).is_jmp) and
+                          DebugMsg(SPeepholeOptimization + 'AndMovsxToAndMovzx', hp1);
+                          taicpu(hp1).opcode := A_MOVZX;
+                          { See if there are other optimisations possible }
+                          Continue;
+                        end;
+                    end;
+              end;
+
+            if (taicpu(hp1).is_jmp) and
               (taicpu(hp1).opcode<>A_JMP) and
               (taicpu(hp1).opcode<>A_JMP) and
               not(RegInUsedRegs(taicpu(p).oper[1]^.reg,UsedRegs)) then
               not(RegInUsedRegs(taicpu(p).oper[1]^.reg,UsedRegs)) then
               begin
               begin
@@ -6093,10 +6210,12 @@ unit aoptx86;
                 taicpu(p).opcode := A_TEST;
                 taicpu(p).opcode := A_TEST;
                 Exit;
                 Exit;
               end;
               end;
+
+            Break;
           end;
           end;
 
 
         { Lone AND tests }
         { Lone AND tests }
-        if MatchOpType(taicpu(p),top_const,top_reg) then
+        if (taicpu(p).oper[0]^.typ = top_const) then
           begin
           begin
             {
             {
               - Convert and $0xFF,reg to and reg,reg if reg is 8-bit
               - Convert and $0xFF,reg to and reg,reg if reg is 8-bit
@@ -6116,6 +6235,94 @@ unit aoptx86;
               end;
               end;
           end;
           end;
 
 
+        { Backward check to determine necessity of and %reg,%reg }
+        if (taicpu(p).oper[0]^.typ = top_reg) and
+          (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) and
+          not RegInUsedRegs(NR_DEFAULTFLAGS, UsedRegs) and
+          GetLastInstruction(p, hp2) and
+          RegModifiedByInstruction(taicpu(p).oper[1]^.reg, hp2) and
+          { Check size of adjacent instruction to determine if the AND is
+            effectively a null operation }
+          (
+            (taicpu(p).opsize = taicpu(hp2).opsize) or
+            { Note: Don't include S_Q }
+            ((taicpu(p).opsize = S_L) and (taicpu(hp2).opsize in [S_BL, S_WL])) or
+            ((taicpu(p).opsize = S_W) and (taicpu(hp2).opsize in [S_BW, S_BL, S_WL, S_L])) or
+            ((taicpu(p).opsize = S_B) and (taicpu(hp2).opsize in [S_BW, S_BL, S_WL, S_W, S_L]))
+          ) then
+          begin
+            DebugMsg(SPeepholeOptimization + 'And2Nop', p);
+            { If GetNextInstruction returned False, hp1 will be nil }
+            RemoveCurrentP(p, hp1);
+            Result := True;
+            Exit;
+          end;
+
+      end;
+
+
+    function TX86AsmOptimizer.OptPass2ADD(var p : tai) : boolean;
+      var
+        hp1: tai;
+
+        { This entire nested function is used in an if-statement below, but we
+          want to avoid all the used reg transfers and GetNextInstruction calls
+          until we really have to check }
+        function MemRegisterNotUsedLater: Boolean; inline;
+          var
+            hp2: tai;
+          begin
+            TransferUsedRegs(TmpUsedRegs);
+            hp2 := p;
+            repeat
+              UpdateUsedRegs(TmpUsedRegs, tai(hp2.Next));
+            until not GetNextInstruction(hp2, hp2) or (hp2 = hp1);
+
+            Result := not RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs);
+          end;
+
+      begin
+        Result := False;
+
+        { Change:
+            add     %reg2,%reg1
+            mov/s/z #(%reg1),%reg1  (%reg1 superregisters must be the same)
+
+          To:
+            mov/s/z #(%reg1,%reg2),%reg1
+        }
+
+        if (taicpu(p).opsize in [S_L{$ifdef x86_64}, S_Q{$endif}]) and
+          MatchOpType(taicpu(p), top_reg, top_reg) and
+          GetNextInstruction(p, hp1) and
+          MatchInstruction(hp1, [A_MOV, A_MOVZX, A_MOVSX{$ifdef x86_64}, A_MOVSXD{$endif}], []) and
+          MatchOpType(taicpu(hp1), top_ref, top_reg) and
+          (taicpu(hp1).oper[0]^.ref^.scalefactor <= 1) and
+          (
+            (
+              (taicpu(hp1).oper[0]^.ref^.base = taicpu(p).oper[1]^.reg) and
+              (taicpu(hp1).oper[0]^.ref^.index = NR_NO)
+            ) or (
+              (taicpu(hp1).oper[0]^.ref^.index = taicpu(p).oper[1]^.reg) and
+              (taicpu(hp1).oper[0]^.ref^.base = NR_NO)
+            )
+          ) and (
+            Reg1WriteOverwritesReg2Entirely(taicpu(p).oper[1]^.reg, taicpu(hp1).oper[1]^.reg) or
+            (
+              { If the super registers ARE equal, then this MOV/S/Z does a partial write }
+              not SuperRegistersEqual(taicpu(p).oper[1]^.reg, taicpu(hp1).oper[1]^.reg) and
+              MemRegisterNotUsedLater
+            )
+          ) then
+          begin
+            taicpu(hp1).oper[0]^.ref^.base := taicpu(p).oper[1]^.reg;
+            taicpu(hp1).oper[0]^.ref^.index := taicpu(p).oper[0]^.reg;
+
+            DebugMsg(SPeepholeOptimization + 'AddMov2Mov done', p);
+            RemoveCurrentp(p, hp1);
+            Result := True;
+            Exit;
+          end;
       end;
       end;
 
 
 
 
@@ -6405,6 +6612,41 @@ unit aoptx86;
       end;
       end;
 
 
 
 
+    function TX86AsmOptimizer.PostPeepholeOptAnd(var p : tai) : boolean;
+      var
+        hp1: tai;
+      begin
+        { Detect:
+            andw   x,  %ax (0 <= x < $8000)
+            ...
+            movzwl %ax,%eax
+
+          Change movzwl %ax,%eax to cwtl (shorter encoding for movswl %ax,%eax)
+        }
+
+        Result := False;
+        if MatchOpType(taicpu(p), top_const, top_reg) and
+          (taicpu(p).oper[1]^.reg = NR_AX) and { This is also enough to determine that opsize = S_W }
+          ((taicpu(p).oper[0]^.val and $7FFF) = taicpu(p).oper[0]^.val) and
+          GetNextInstructionUsingReg(p, hp1, NR_EAX) and
+          MatchInstruction(hp1, A_MOVZX, [S_WL]) and
+          MatchOperand(taicpu(hp1).oper[0]^, NR_AX) and
+          MatchOperand(taicpu(hp1).oper[1]^, NR_EAX) then
+          begin
+            DebugMsg(SPeepholeOptimization + 'Converted movzwl %ax,%eax to cwtl (via AndMovz2AndCwtl)', hp1);
+            taicpu(hp1).opcode := A_CWDE;
+            taicpu(hp1).clearop(0);
+            taicpu(hp1).clearop(1);
+            taicpu(hp1).ops := 0;
+
+            { A change was made, but not with p, so move forward 1 }
+            p := tai(p.Next);
+            Result := True;
+          end;
+
+      end;
+
+
     function TX86AsmOptimizer.PostPeepholeOptMOVSX(var p : tai) : boolean;
     function TX86AsmOptimizer.PostPeepholeOptMOVSX(var p : tai) : boolean;
       begin
       begin
         Result := False;
         Result := False;

+ 1 - 2
compiler/x86/cpubase.pas

@@ -960,8 +960,7 @@ implementation
 
 
   function UseAVX512: boolean;
   function UseAVX512: boolean;
     begin
     begin
-      // Result:=(current_settings.fputype in fpu_avx_instructionsets) {$ifndef i8086}or (CPUX86_HAS_AVXUNIT in cpu_capabilities[current_settings.cputype]){$endif i8086};
-      Result:=false;
+      Result:={$ifdef i8086}false{$else i8086}UseAVX and (FPUX86_HAS_AVX512F in fpu_capabilities[current_settings.fputype]){$endif i8086};
     end;
     end;
 
 
 
 

+ 25 - 9
compiler/x86/nx86inl.pas

@@ -1309,21 +1309,35 @@ implementation
           begin
           begin
             secondpass(left);
             secondpass(left);
             hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
             hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
-            location_reset(location,LOC_MMREGISTER,left.location.size);
+            location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
             location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
             location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
             if UseAVX then
             if UseAVX then
-              case tfloatdef(resultdef).floattype of
+              case tfloatdef(left.resultdef).floattype of
                 s32real:
                 s32real:
                   begin
                   begin
-                    { using left.location.register here as 3rd parameter is crucial to break dependency chains }
-                    current_asmdata.CurrAsmList.concat(taicpu.op_const_reg_reg_reg(A_VROUNDSS,S_NO,3,left.location.register,left.location.register,location.register));
-                    current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_VSUBSS,S_NO,location.register,left.location.register,location.register));
+{$ifndef i8086}
+                    if UseAVX512 and (FPUX86_HAS_AVX512DQ in fpu_capabilities[current_settings.fputype]) then
+                      current_asmdata.CurrAsmList.concat(taicpu.op_const_reg_reg_reg(A_VREDUCESS,S_NO,3,left.location.register,left.location.register,location.register))
+                    else
+{$endif not i8086}
+                      begin
+                        { using left.location.register here as 3rd parameter is crucial to break dependency chains }
+                        current_asmdata.CurrAsmList.concat(taicpu.op_const_reg_reg_reg(A_VROUNDSS,S_NO,3,left.location.register,left.location.register,location.register));
+                        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_VSUBSS,S_NO,location.register,left.location.register,location.register));
+                      end;
                   end;
                   end;
                 s64real:
                 s64real:
                   begin
                   begin
-                    { using left.location.register here as 3rd parameter is crucial to break dependency chains }
-                    current_asmdata.CurrAsmList.concat(taicpu.op_const_reg_reg_reg(A_VROUNDSD,S_NO,3,left.location.register,left.location.register,location.register));
-                    current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_VSUBSD,S_NO,location.register,left.location.register,location.register));
+{$ifndef i8086}
+                    if UseAVX512 and (FPUX86_HAS_AVX512DQ in fpu_capabilities[current_settings.fputype]) then
+                      current_asmdata.CurrAsmList.concat(taicpu.op_const_reg_reg_reg(A_VREDUCESD,S_NO,3,left.location.register,left.location.register,location.register))
+                    else
+{$endif not i8086}
+                      begin
+                        { using left.location.register here as 3rd parameter is crucial to break dependency chains }
+                        current_asmdata.CurrAsmList.concat(taicpu.op_const_reg_reg_reg(A_VROUNDSD,S_NO,3,left.location.register,left.location.register,location.register));
+                        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_VSUBSD,S_NO,location.register,left.location.register,location.register));
+                      end;
                   end;
                   end;
                 else
                 else
                   internalerror(2017052102);
                   internalerror(2017052102);
@@ -1332,7 +1346,7 @@ implementation
               begin
               begin
                 extrareg:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
                 extrareg:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
                 cg.a_loadmm_loc_reg(current_asmdata.CurrAsmList,location.size,left.location,location.register,mms_movescalar);
                 cg.a_loadmm_loc_reg(current_asmdata.CurrAsmList,location.size,left.location,location.register,mms_movescalar);
-                case tfloatdef(resultdef).floattype of
+                case tfloatdef(left.resultdef).floattype of
                   s32real:
                   s32real:
                     begin
                     begin
                       current_asmdata.CurrAsmList.concat(taicpu.op_const_reg_reg(A_ROUNDSS,S_NO,3,left.location.register,extrareg));
                       current_asmdata.CurrAsmList.concat(taicpu.op_const_reg_reg(A_ROUNDSS,S_NO,3,left.location.register,extrareg));
@@ -1347,6 +1361,8 @@ implementation
                     internalerror(2017052103);
                     internalerror(2017052103);
                 end;
                 end;
               end;
               end;
+            if tfloatdef(left.resultdef).floattype<>tfloatdef(resultdef).floattype then
+              hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,location.register,location.register,mms_movescalar);
           end
           end
         else
         else
           internalerror(2017052101);
           internalerror(2017052101);

+ 1 - 3
compiler/x86/nx86mat.pas

@@ -386,8 +386,6 @@ interface
         { put numerator in register }
         { put numerator in register }
         cgsize:=def_cgsize(resultdef);
         cgsize:=def_cgsize(resultdef);
         opsize:=TCGSize2OpSize[cgsize];
         opsize:=TCGSize2OpSize[cgsize];
-        if not (cgsize in [OS_32,OS_S32,OS_64,OS_S64]) then
-          InternalError(2013102702);
         rega:=newreg(R_INTREGISTER,RS_EAX,cgsize2subreg(R_INTREGISTER,cgsize));
         rega:=newreg(R_INTREGISTER,RS_EAX,cgsize2subreg(R_INTREGISTER,cgsize));
         regd:=newreg(R_INTREGISTER,RS_EDX,cgsize2subreg(R_INTREGISTER,cgsize));
         regd:=newreg(R_INTREGISTER,RS_EDX,cgsize2subreg(R_INTREGISTER,cgsize));
 
 
@@ -626,7 +624,7 @@ interface
                 cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,cgsize,resultdef.size*8-power,hreg2,hreg2);
                 cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,cgsize,resultdef.size*8-power,hreg2,hreg2);
               end;
               end;
             emit_reg_reg(A_ADD,opsize,hreg1,hreg2);
             emit_reg_reg(A_ADD,opsize,hreg1,hreg2);
-            emit_const_reg(A_AND,opsize,not((aint(1) shl power)-1),hreg2);
+            cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,cgsize,not((aint(1) shl power)-1),hreg2);
             emit_reg_reg(A_SUB,opsize,hreg2,hreg1);
             emit_reg_reg(A_SUB,opsize,hreg2,hreg1);
             location.register:=hreg1;
             location.register:=hreg1;
           end
           end

+ 2 - 0
compiler/x86/rax86att.pas

@@ -649,6 +649,7 @@ Implementation
                  CreateLocalLabel(actasmpattern,hl,false);
                  CreateLocalLabel(actasmpattern,hl,false);
                  Consume(AS_ID);
                  Consume(AS_ID);
                  AddLabelOperand(hl);
                  AddLabelOperand(hl);
+                 MaybeGetPICModifier(oper);
                end
                end
               else
               else
                { Check for label }
                { Check for label }
@@ -656,6 +657,7 @@ Implementation
                 begin
                 begin
                   Consume(AS_ID);
                   Consume(AS_ID);
                   AddLabelOperand(hl);
                   AddLabelOperand(hl);
+                  MaybeGetPICModifier(oper);
                 end
                 end
               else
               else
                { probably a variable or normal expression }
                { probably a variable or normal expression }

+ 4 - 4
compiler/x86/x86ins.dat

@@ -8734,7 +8734,7 @@ xmmreg_mz,xmmreg,mem32		          \350\361\371\1\xCB\75\120                 AVX5
 xmmreg_mz,xmmreg,xmmreg_sae               \350\361\371\1\xCB\75\120                 AVX512
 xmmreg_mz,xmmreg,xmmreg_sae               \350\361\371\1\xCB\75\120                 AVX512
 
 
 [VREDUCEPD]
 [VREDUCEPD]
-(Ch_All)
+(Ch_Rop1, Ch_Rop2, Ch_Wop3)
 xmmreg_mz,xmmrm,imm8                      \350\352\361\372\1\x56\110\26             AVX512,TFV
 xmmreg_mz,xmmrm,imm8                      \350\352\361\372\1\x56\110\26             AVX512,TFV
 xmmreg_mz,bmem64,imm8                     \350\352\361\372\1\x56\110\26             AVX512,TFV
 xmmreg_mz,bmem64,imm8                     \350\352\361\372\1\x56\110\26             AVX512,TFV
 ymmreg_mz,ymmrm,imm8                      \350\352\361\364\372\1\x56\110\26         AVX512,TFV
 ymmreg_mz,ymmrm,imm8                      \350\352\361\364\372\1\x56\110\26         AVX512,TFV
@@ -8744,7 +8744,7 @@ zmmreg_mz,bmem64,imm8                     \350\351\352\361\372\1\x56\110\26
 zmmreg_mz,zmmreg_sae,imm8                 \350\351\352\361\372\1\x56\110\26         AVX512
 zmmreg_mz,zmmreg_sae,imm8                 \350\351\352\361\372\1\x56\110\26         AVX512
 
 
 [VREDUCEPS]
 [VREDUCEPS]
-(Ch_All)
+(Ch_Rop1, Ch_Rop2, Ch_Wop3)
 xmmreg_mz,xmmrm,imm8                      \350\361\372\1\x56\110\26                 AVX512,TFV
 xmmreg_mz,xmmrm,imm8                      \350\361\372\1\x56\110\26                 AVX512,TFV
 xmmreg_mz,bmem32,imm8                     \350\361\372\1\x56\110\26                 AVX512,TFV
 xmmreg_mz,bmem32,imm8                     \350\361\372\1\x56\110\26                 AVX512,TFV
 ymmreg_mz,ymmrm,imm8                      \350\361\364\372\1\x56\110\26             AVX512,TFV
 ymmreg_mz,ymmrm,imm8                      \350\361\364\372\1\x56\110\26             AVX512,TFV
@@ -8754,12 +8754,12 @@ zmmreg_mz,bmem32,imm8                     \350\351\361\372\1\x56\110\26
 zmmreg_mz,zmmreg_sae,imm8                 \350\351\361\372\1\x56\110\26             AVX512
 zmmreg_mz,zmmreg_sae,imm8                 \350\351\361\372\1\x56\110\26             AVX512
 
 
 [VREDUCESD]
 [VREDUCESD]
-(Ch_All)
+(Ch_Rop1, Ch_Rop2, Ch_Rop3, Ch_Wop4)
 xmmreg_mz,xmmreg,mem64,imm8               \350\352\361\372\1\x57\75\120\27          AVX512,T1S
 xmmreg_mz,xmmreg,mem64,imm8               \350\352\361\372\1\x57\75\120\27          AVX512,T1S
 xmmreg_mz,xmmreg,xmmreg_sae,imm8          \350\352\361\372\1\x57\75\120\27          AVX512
 xmmreg_mz,xmmreg,xmmreg_sae,imm8          \350\352\361\372\1\x57\75\120\27          AVX512
 
 
 [VREDUCESS]
 [VREDUCESS]
-(Ch_All)
+(Ch_Rop1, Ch_Rop2, Ch_Rop3, Ch_Wop4)
 xmmreg_mz,xmmreg,mem32,imm8               \350\361\372\1\x57\75\120\27              AVX512,T1S
 xmmreg_mz,xmmreg,mem32,imm8               \350\361\372\1\x57\75\120\27              AVX512,T1S
 xmmreg_mz,xmmreg,xmmreg_sae,imm8          \350\361\372\1\x57\75\120\27              AVX512
 xmmreg_mz,xmmreg,xmmreg_sae,imm8          \350\361\372\1\x57\75\120\27              AVX512
 
 

+ 4 - 0
compiler/x86_64/aoptcpu.pas

@@ -173,6 +173,8 @@ uses
                   Result:=OptPass2Lea(p);
                   Result:=OptPass2Lea(p);
                 A_SUB:
                 A_SUB:
                   Result:=OptPass2SUB(p);
                   Result:=OptPass2SUB(p);
+                A_ADD:
+                  Result:=OptPass2ADD(p);
                 else
                 else
                   ;
                   ;
               end;
               end;
@@ -192,6 +194,8 @@ uses
               case taicpu(p).opcode of
               case taicpu(p).opcode of
                 A_MOV:
                 A_MOV:
                   Result:=PostPeepholeOptMov(p);
                   Result:=PostPeepholeOptMov(p);
+                A_AND:
+                  Result:=PostPeepholeOptAnd(p);
                 A_MOVSX:
                 A_MOVSX:
                   Result:=PostPeepholeOptMOVSX(p);
                   Result:=PostPeepholeOptMOVSX(p);
                 A_MOVZX:
                 A_MOVZX:

+ 4 - 2
compiler/x86_64/cpuinfo.pas

@@ -182,7 +182,9 @@ type
    tfpuflags =
    tfpuflags =
       (FPUX86_HAS_AVXUNIT,
       (FPUX86_HAS_AVXUNIT,
        FPUX86_HAS_32MMREGS,
        FPUX86_HAS_32MMREGS,
-       FPUX86_HAS_AVX512F
+       FPUX86_HAS_AVX512F,
+       FPUX86_HAS_AVX512VL,
+       FPUX86_HAS_AVX512DQ
       );
       );
 
 
  const
  const
@@ -203,7 +205,7 @@ type
       { fpu_sse42    } [],
       { fpu_sse42    } [],
       { fpu_avx      } [FPUX86_HAS_AVXUNIT],
       { fpu_avx      } [FPUX86_HAS_AVXUNIT],
       { fpu_avx2     } [FPUX86_HAS_AVXUNIT],
       { fpu_avx2     } [FPUX86_HAS_AVXUNIT],
-      { fpu_avx512   } [FPUX86_HAS_AVXUNIT,FPUX86_HAS_32MMREGS,FPUX86_HAS_AVX512F]
+      { fpu_avx512   } [FPUX86_HAS_AVXUNIT,FPUX86_HAS_32MMREGS,FPUX86_HAS_AVX512F,FPUX86_HAS_AVX512VL,FPUX86_HAS_AVX512DQ]
    );
    );
 
 
 Implementation
 Implementation

+ 4 - 4
compiler/x86_64/x8664pro.inc

@@ -1379,10 +1379,10 @@
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
-(Ch: [Ch_All]),
-(Ch: [Ch_All]),
-(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_Rop3, Ch_Wop4]),
+(Ch: [Ch_Rop1, Ch_Rop2, Ch_Rop3, Ch_Wop4]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),
 (Ch: [Ch_All]),

+ 38 - 6
compiler/xtensa/cgcpu.pas

@@ -688,7 +688,16 @@ implementation
                   if LocalSize<>0 then
                   if LocalSize<>0 then
                     begin
                     begin
                       a_reg_alloc(list,NR_STACK_POINTER_REG);
                       a_reg_alloc(list,NR_STACK_POINTER_REG);
-                      list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-localsize));
+                      { not sure if 32512 is the correct value or if it can be larger }
+                      if Localsize>32512 then
+                        begin
+                          reference_reset(ref,4,[]);
+                          ref.symbol:=create_data_entry(nil,-localsize);
+                          list.concat(taicpu.op_reg_ref(A_L32R,NR_A8,ref));
+                          list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_A8));
+                        end
+                      else
+                        list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-localsize));
                     end;
                     end;
 
 
                   reference_reset(ref,4,[]);
                   reference_reset(ref,4,[]);
@@ -703,8 +712,15 @@ implementation
                           ref.base:=NR_A8;
                           ref.base:=NR_A8;
                         end
                         end
                       else
                       else
-                        { fix me! }
-                        Internalerror(2020031101);
+                        begin
+                          reference_reset(ref,4,[]);
+                          ref.symbol:=create_data_entry(nil,localsize-registerarea);
+                          list.concat(taicpu.op_reg_ref(A_L32R,NR_A8,ref));
+                          list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_A8,NR_A8,NR_STACK_POINTER_REG));
+                          reference_reset(ref,4,[]);
+                          ref.base:=NR_A8;
+                          ref.offset:=registerarea;
+                        end;
                     end;
                     end;
 
 
                   if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
                   if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
@@ -831,8 +847,15 @@ implementation
                               ref.base:=NR_A8;
                               ref.base:=NR_A8;
                             end
                             end
                           else
                           else
-                            { fix me! }
-                            Internalerror(2020031102);
+                            begin
+                              reference_reset(ref,4,[]);
+                              ref.symbol:=create_data_entry(nil,ref.offset);
+                              list.concat(taicpu.op_reg_ref(A_L32R,NR_A8,ref));
+                              list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_A8,NR_A8,NR_STACK_POINTER_REG));
+                              reference_reset(ref,4,[]);
+                              ref.base:=NR_A8;
+                              ref.offset:=0;
+                            end;
                         end;
                         end;
 
 
                       // restore a15 if used
                       // restore a15 if used
@@ -855,7 +878,16 @@ implementation
                         end;
                         end;
 
 
                       // restore stack pointer
                       // restore stack pointer
-                      list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,localsize));
+                      { not sure if 32512 is the correct value or if it can be larger }
+                      if Localsize>32512 then
+                        begin
+                          reference_reset(ref,4,[]);
+                          ref.symbol:=create_data_entry(nil,localsize);
+                          list.concat(taicpu.op_reg_ref(A_L32R,NR_A8,ref));
+                          list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_A8));
+                        end
+                      else
+                        list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,localsize));
                       a_reg_dealloc(list,NR_STACK_POINTER_REG);
                       a_reg_dealloc(list,NR_STACK_POINTER_REG);
                     end;
                     end;
                   end;
                   end;

+ 8 - 0
packages/chm/src/itsftransform.pas

@@ -435,7 +435,15 @@ initialization
 
 
 finalization
 finalization
   if Assigned(LocTransforms) then
   if Assigned(LocTransforms) then
+  begin
+    while LocTransforms.Count > 0 do
+    begin
+      if Assigned(PITSFTranformItem(LocTransforms.Items[0])^.Instance) then
+          (PITSFTranformItem(LocTransforms.Items[0])^.Instance).Free;
+      LocTransforms.Delete(0);
+    end;
     LocTransforms.Free;
     LocTransforms.Free;
+  end
 
 
 end.
 end.
 
 

+ 3 - 4
packages/fcl-js/src/jswriter.pp

@@ -611,10 +611,9 @@ begin
               begin
               begin
               inc(I,2); // surrogate, two char codepoint
               inc(I,2); // surrogate, two char codepoint
               continue;
               continue;
-              end
-            else
-              // invalid UTF-16, cannot be encoded as UTF-8 -> encode as hex
-              R:=R+'\u'+TJSString(HexStr(ord(c),4));
+              end;
+            // invalid UTF-16, cannot be encoded as UTF-8 -> encode as hex
+            R:=R+'\u'+TJSString(HexStr(ord(S[i]),4));
             end
             end
           else
           else
             // invalid UTF-16 at end of string, cannot be encoded as UTF-8 -> encode as hex
             // invalid UTF-16 at end of string, cannot be encoded as UTF-8 -> encode as hex

+ 263 - 91
packages/fcl-passrc/src/pasresolveeval.pas

@@ -564,6 +564,7 @@ type
   TResEvalString = class(TResEvalValue)
   TResEvalString = class(TResEvalValue)
   public
   public
     S: RawByteString;
     S: RawByteString;
+    OnlyASCII: boolean;
     constructor Create; override;
     constructor Create; override;
     constructor CreateValue(const aValue: RawByteString);
     constructor CreateValue(const aValue: RawByteString);
     function Clone: TResEvalValue; override;
     function Clone: TResEvalValue; override;
@@ -692,7 +693,8 @@ type
   private
   private
     FAllowedInts: TResEvalTypedInts;
     FAllowedInts: TResEvalTypedInts;
     {$ifdef FPC_HAS_CPSTRING}
     {$ifdef FPC_HAS_CPSTRING}
-    FDefaultEncoding: TSystemCodePage;
+    FDefaultSourceEncoding: TSystemCodePage;
+    FDefaultStringEncoding: TSystemCodePage;
     {$endif}
     {$endif}
     FOnEvalIdentifier: TPasResEvalIdentHandler;
     FOnEvalIdentifier: TPasResEvalIdentHandler;
     FOnEvalParams: TPasResEvalParamsHandler;
     FOnEvalParams: TPasResEvalParamsHandler;
@@ -779,6 +781,8 @@ type
     function GetUTF8Str(const s: RawByteString; ErrorEl: TPasElement): String;
     function GetUTF8Str(const s: RawByteString; ErrorEl: TPasElement): String;
     function GetUnicodeStr(const s: RawByteString; ErrorEl: TPasElement): UnicodeString;
     function GetUnicodeStr(const s: RawByteString; ErrorEl: TPasElement): UnicodeString;
     function GetWideChar(const s: RawByteString; out w: WideChar): boolean;
     function GetWideChar(const s: RawByteString; out w: WideChar): boolean;
+    function GetExprStringTargetCP(Expr: TPasExpr): TSystemCodePage; virtual; // e.g. var s: String(1234) = 'ä' return 1234
+    function GetExprStringSourceCP(Expr: TPasExpr): TSystemCodePage; virtual; // e.g. {$codepage 123}var s: String = 'ä' return 123
     {$endif}
     {$endif}
     property OnLog: TPasResEvalLogHandler read FOnLog write FOnLog;
     property OnLog: TPasResEvalLogHandler read FOnLog write FOnLog;
     property OnEvalIdentifier: TPasResEvalIdentHandler read FOnEvalIdentifier write FOnEvalIdentifier;
     property OnEvalIdentifier: TPasResEvalIdentHandler read FOnEvalIdentifier write FOnEvalIdentifier;
@@ -786,7 +790,8 @@ type
     property OnRangeCheckEl: TPasResEvalRangeCheckElHandler read FOnRangeCheckEl write FOnRangeCheckEl;
     property OnRangeCheckEl: TPasResEvalRangeCheckElHandler read FOnRangeCheckEl write FOnRangeCheckEl;
     property AllowedInts: TResEvalTypedInts read FAllowedInts write FAllowedInts;
     property AllowedInts: TResEvalTypedInts read FAllowedInts write FAllowedInts;
     {$ifdef FPC_HAS_CPSTRING}
     {$ifdef FPC_HAS_CPSTRING}
-    property DefaultStringCodePage: TSystemCodePage read FDefaultEncoding write FDefaultEncoding;
+    property DefaultSourceCodePage: TSystemCodePage read FDefaultSourceEncoding write FDefaultSourceEncoding;
+    property DefaultStringCodePage: TSystemCodePage read FDefaultStringEncoding write FDefaultStringEncoding;
     {$endif}
     {$endif}
   end;
   end;
   TResExprEvaluatorClass = class of TResExprEvaluator;
   TResExprEvaluatorClass = class of TResExprEvaluator;
@@ -923,6 +928,7 @@ end;
 
 
 function UnicodeStrToCaption(const u: UnicodeString; MaxLength: integer
 function UnicodeStrToCaption(const u: UnicodeString; MaxLength: integer
   ): Unicodestring;
   ): Unicodestring;
+// encode a string as a Pascal string literal using '' and #
 var
 var
   InLit: boolean;
   InLit: boolean;
   Len: integer;
   Len: integer;
@@ -4125,15 +4131,22 @@ end;
 
 
 function TResExprEvaluator.EvalPrimitiveExprString(Expr: TPrimitiveExpr
 function TResExprEvaluator.EvalPrimitiveExprString(Expr: TPrimitiveExpr
   ): TResEvalValue;
   ): TResEvalValue;
-{ Extracts the value from a Pascal string literal
-
-  S is a Pascal string literal e.g. 'Line'#10
-    ''  empty string
-    '''' => "'"
-    #decimal
-    #$hex
-    ^l  l is a letter a-z
-}
+ //Extracts the value from a Pascal string literal
+ //
+ // S is a Pascal string literal e.g. 'Line'#10
+ //   ''  empty string
+ //   '''' => "'"
+ //   #decimal
+ //   #$hex
+ //   ^l  l is a letter a-z
+ //
+ // Codepage:
+ //   For example {$codepage utf8}var s: AnsiString(CP_1251) = 'a';
+ //     Source codepage is CP_UTF8, target codepage is CP_1251
+ //
+ //   Source codepage is needed for reading non ASCII string literals 'ä'.
+ //   Target codepage is needed for reading non ASCII # literals.
+ //   Target codepage costs time to compute.
 
 
   procedure RangeError(id: TMaxPrecInt);
   procedure RangeError(id: TMaxPrecInt);
   begin
   begin
@@ -4141,24 +4154,36 @@ function TResExprEvaluator.EvalPrimitiveExprString(Expr: TPrimitiveExpr
     RaiseRangeCheck(id,Expr);
     RaiseRangeCheck(id,Expr);
   end;
   end;
 
 
-  procedure Add(h: String);
+{$IFDEF FPC_HAS_CPSTRING}
+var
+  TargetCPValid: boolean;
+  TargetCP: word;
+  SourceCPValid: boolean;
+  SourceCP: word;
+
+  procedure FetchSourceCP;
   begin
   begin
-    {$ifdef FPC_HAS_CPSTRING}
-    if Result.Kind=revkString then
-      TResEvalString(Result).S:=TResEvalString(Result).S+h
-    else
-      TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+GetUnicodeStr(h,Expr);
-    {$else}
-    TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+h;
-    {$endif}
+    if SourceCPValid then exit;
+    SourceCP:=GetExprStringSourceCP(Expr);
+    if SourceCP=DefaultSystemCodePage then
+      SourceCP:=CP_ACP;
+    SourceCPValid:=true;
   end;
   end;
 
 
-  procedure AddHash(u: longword; ForceUTF16: boolean);
-  {$ifdef FPC_HAS_CPSTRING}
+  procedure FetchTargetCP;
+  begin
+    if TargetCPValid then exit;
+    TargetCP:=GetExprStringTargetCP(Expr);
+    if TargetCP=DefaultSystemCodePage then
+      TargetCP:=CP_ACP;
+    TargetCPValid:=true;
+  end;
+
+  procedure ForceUTF16;
   var
   var
     h: RawByteString;
     h: RawByteString;
   begin
   begin
-    if ((u>255) or (ForceUTF16)) and (Result.Kind=revkString) then
+    if Result.Kind=revkString then
       begin
       begin
       // switch to unicodestring
       // switch to unicodestring
       h:=TResEvalString(Result).S;
       h:=TResEvalString(Result).S;
@@ -4166,22 +4191,202 @@ function TResExprEvaluator.EvalPrimitiveExprString(Expr: TPrimitiveExpr
       Result:=nil; // in case of exception in GetUnicodeStr
       Result:=nil; // in case of exception in GetUnicodeStr
       Result:=TResEvalUTF16.CreateValue(GetUnicodeStr(h,Expr));
       Result:=TResEvalUTF16.CreateValue(GetUnicodeStr(h,Expr));
       end;
       end;
+  end;
+{$ENDIF}
+
+  procedure AddSrc(h: String);
+  {$ifdef FPC_HAS_CPSTRING}
+  var
+    Value: TResEvalString;
+    OnlyASCII: Boolean;
+    i: Integer;
+  {$ENDIF}
+  begin
+    if h='' then exit;
+    //writeln('AddSrc ',length(h),' ',ord(h[1]),' ',stringcodepage(h),' ',defaultsystemcodepage);
+    {$ifdef FPC_HAS_CPSTRING}
+    OnlyASCII:=true;
+    for i:=1 to length(h) do
+      if ord(h[i])>127 then
+        begin
+        // append non ASCII -> needs codepage
+        OnlyASCII:=false;
+        FetchSourceCP;
+        SetCodePage(rawbytestring(h),SourceCP,false);
+        break;
+        end;
+
+    if Result.Kind=revkString then
+      begin
+      Value:=TResEvalString(Result);
+      if OnlyASCII and Value.OnlyASCII then
+        begin
+        // concatenate ascii strings
+        Value.S:=Value.S+h;
+        exit;
+        end;
+
+      // concatenate non ascii strings
+      FetchTargetCP;
+      case TargetCP of
+      CP_UTF16:
+        begin
+        ForceUTF16;
+        TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+GetUnicodeStr(h,Expr);
+        //writeln('AddSrc len(h)=',length(h),' StringCodePage=',StringCodePage(h),' GetCodePage=',GetCodePage(h),' S=',length(TResEvalUTF16(Result).S));
+        end;
+      CP_UTF16BE:
+        RaiseNotYetImplemented(20201220222608,Expr);
+      else
+        begin
+        if Value.S<>'' then
+        begin
+          if Value.OnlyASCII then
+            SetCodePage(Value.S,TargetCP,false);
+          Value.S:=Value.S+h;
+        end else begin
+          Value.S:=h;
+        end;
+        end;
+      end;
+
+      end
+    else
+      TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+GetUnicodeStr(h,Expr);
+    {$else}
+    TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+h;
+    {$endif}
+  end;
+
+  procedure AddHash(u: longword);
+  {$ifdef FPC_HAS_CPSTRING}
+  begin
     if Result.Kind=revkString then
     if Result.Kind=revkString then
-      TResEvalString(Result).S:=TResEvalString(Result).S+Chr(u)
+      TResEvalString(Result).s:=TResEvalString(Result).S+Chr(u)
     else
     else
       TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+WideChar(u);
       TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+WideChar(u);
   end;
   end;
   {$else}
   {$else}
   begin
   begin
     TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+WideChar(u);
     TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+WideChar(u);
-    if ForceUTF16 then ;
   end;
   end;
   {$endif}
   {$endif}
 
 
+  function ReadHash(Value: TResEvalValue; const S: string; p, l: integer): integer;
+  var
+    StartP: Integer;
+    u: longword;
+    c: Char;
+    {$ifdef FPC_HAS_CPSTRING}
+    ValueAnsi: TResEvalString;
+    ValueUTF16: TResEvalUTF16;
+    OldCP: TSystemCodePage;
+    {$ENDIF}
+  begin
+    Result:=p;
+    inc(Result);
+    if Result>l then
+      RaiseInternalError(20181016121354); // error in scanner
+    if S[Result]='$' then
+      begin
+      // #$hexnumber
+      inc(Result);
+      StartP:=Result;
+      u:=0;
+      while Result<=l do
+        begin
+        c:=S[Result];
+        case c of
+        '0'..'9': u:=u*16+longword(ord(c)-ord('0'));
+        'a'..'f': u:=u*16+longword(ord(c)-ord('a'))+10;
+        'A'..'F': u:=u*16+longword(ord(c)-ord('A'))+10;
+        else break;
+        end;
+        if u>$10FFFF then
+          RangeError(20170523115712);
+        inc(Result);
+        end;
+      end
+    else
+      begin
+      // #decimalnumber
+      StartP:=Result;
+      u:=0;
+      while Result<=l do
+        begin
+        c:=S[Result];
+        case c of
+        '0'..'9': u:=u*10+longword(ord(c)-ord('0'));
+        else break;
+        end;
+        if u>$ffff then
+          RangeError(20170523123137);
+        inc(Result);
+        end;
+      end;
+    if Result=StartP then
+      RaiseInternalError(20170523123806);
+    {$IFDEF FPC_HAS_CPSTRING}
+    if u<128 then
+      begin
+      // ASCII
+      AddHash(u);
+      exit;
+      end;
+    // non ASCII
+    FetchTargetCP;
+    if (TargetCP=CP_UTF16) or (TargetCP=CP_UTF16BE) or (u>255) then
+      begin
+      ForceUTF16;
+      ValueUTF16:=TResEvalUTF16(Value);
+      if u>$ffff then
+        begin
+        // split into two
+        dec(u,$10000);
+        ValueUTF16.S:=ValueUTF16.S
+                       +WideChar($D800+(u shr 10))+WideChar($DC00+(u and $3ff));
+        end
+      else
+        ValueUTF16.S:=ValueUTF16.S+WideChar(u);
+      if TargetCP=CP_UTF16BE then
+        RaiseNotYetImplemented(20201220212206,Expr);
+      end
+    else
+      begin
+      // byte encoding
+      ValueAnsi:=TResEvalString(Value);
+      if ValueAnsi.S<>'' then
+        begin
+        // append
+        OldCP:=StringCodePage(ValueAnsi.S);
+        if OldCP<>TargetCP then
+          SetCodePage(ValueAnsi.S,TargetCP,false);
+        ValueAnsi.S:=ValueAnsi.S+Chr(u);
+        end
+      else
+        begin
+        // start
+        ValueAnsi.S:=Chr(u);
+        SetCodePage(ValueAnsi.S,TargetCP,false);
+        end;
+      ValueAnsi.OnlyASCII:=false;
+      end;
+    {$ELSE}
+    if u>$ffff then
+      begin
+      // split into two
+      dec(u,$10000);
+      AddHash($D800+(u shr 10));
+      AddHash($DC00+(u and $3ff));
+      end
+    else
+      AddHash(u);
+    {$ENDIF}
+  end;
+
 var
 var
   p, StartP, l: integer;
   p, StartP, l: integer;
   c: Char;
   c: Char;
-  u: longword;
   S: String;
   S: String;
 begin
 begin
   Result:=nil;
   Result:=nil;
@@ -4193,11 +4398,16 @@ begin
   if l=0 then
   if l=0 then
     RaiseInternalError(20170523113809);
     RaiseInternalError(20170523113809);
   {$ifdef FPC_HAS_CPSTRING}
   {$ifdef FPC_HAS_CPSTRING}
+  TargetCPValid:=false;
+  TargetCP:=CP_ACP;
+  SourceCPValid:=false;
+  SourceCP:=CP_ACP;
   Result:=TResEvalString.Create;
   Result:=TResEvalString.Create;
   {$else}
   {$else}
   Result:=TResEvalUTF16.Create;
   Result:=TResEvalUTF16.Create;
   {$endif}
   {$endif}
   p:=1;
   p:=1;
+  //writeln('TResExprEvaluator.EvalPrimitiveExprString ',GetObjPath(Expr),' ',Expr.SourceFilename,' ',Expr.SourceLinenumber div 2048,' S=[',S,']');
   while p<=l do
   while p<=l do
     case S[p] of
     case S[p] of
     {$ifdef UsePChar}
     {$ifdef UsePChar}
@@ -4215,12 +4425,12 @@ begin
         '''':
         '''':
           begin
           begin
           if p>StartP then
           if p>StartP then
-            Add(copy(S,StartP,p-StartP));
+            AddSrc(copy(S,StartP,p-StartP));
           inc(p);
           inc(p);
           StartP:=p;
           StartP:=p;
           if (p>l) or (S[p]<>'''') then
           if (p>l) or (S[p]<>'''') then
             break;
             break;
-          Add('''');
+          AddSrc('''');
           inc(p);
           inc(p);
           StartP:=p;
           StartP:=p;
           end;
           end;
@@ -4229,65 +4439,10 @@ begin
         end;
         end;
       until false;
       until false;
       if p>StartP then
       if p>StartP then
-        Add(copy(S,StartP,p-StartP));
+        AddSrc(copy(S,StartP,p-StartP));
       end;
       end;
     '#':
     '#':
-      begin
-      inc(p);
-      if p>l then
-        RaiseInternalError(20181016121354);
-      if S[p]='$' then
-        begin
-        // #$hexnumber
-        inc(p);
-        StartP:=p;
-        u:=0;
-        while p<=l do
-          begin
-          c:=S[p];
-          case c of
-          '0'..'9': u:=u*16+longword(ord(c)-ord('0'));
-          'a'..'f': u:=u*16+longword(ord(c)-ord('a'))+10;
-          'A'..'F': u:=u*16+longword(ord(c)-ord('A'))+10;
-          else break;
-          end;
-          if u>$10FFFF then
-            RangeError(20170523115712);
-          inc(p);
-          end;
-        if p=StartP then
-          RaiseInternalError(20170207164956);
-        if u>$ffff then
-          begin
-          // split into two
-          dec(u,$10000);
-          AddHash($D800+(u shr 10),true);
-          AddHash($DC00+(u and $3ff),true);
-          end
-        else
-          AddHash(u,p-StartP>2);
-        end
-      else
-        begin
-        // #decimalnumber
-        StartP:=p;
-        u:=0;
-        while p<=l do
-          begin
-          c:=S[p];
-          case c of
-          '0'..'9': u:=u*10+longword(ord(c)-ord('0'));
-          else break;
-          end;
-          if u>$ffff then
-            RangeError(20170523123137);
-          inc(p);
-          end;
-        if p=StartP then
-          RaiseInternalError(20170523123806);
-        AddHash(u,false);
-        end;
-      end;
+      p:=ReadHash(Result,S,p,l);
     '^':
     '^':
       begin
       begin
       // ^A is #1
       // ^A is #1
@@ -4296,8 +4451,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,false);
-      'A'..'Z': AddHash(ord(c)-ord('A')+1,false);
+      'a'..'z': AddHash(ord(c)-ord('a')+1);
+      'A'..'Z': AddHash(ord(c)-ord('A')+1);
       else RaiseInternalError(20170523123809);
       else RaiseInternalError(20170523123809);
       end;
       end;
       inc(p);
       inc(p);
@@ -4323,7 +4478,8 @@ begin
   inherited Create;
   inherited Create;
   FAllowedInts:=ReitDefaults;
   FAllowedInts:=ReitDefaults;
   {$ifdef FPC_HAS_CPSTRING}
   {$ifdef FPC_HAS_CPSTRING}
-  FDefaultEncoding:=CP_ACP;
+  FDefaultSourceEncoding:=system.DefaultSystemCodePage;
+  FDefaultStringEncoding:=CP_ACP;
   {$endif}
   {$endif}
 end;
 end;
 
 
@@ -5115,11 +5271,11 @@ end;
 
 
 function TResExprEvaluator.GetCodePage(const s: RawByteString): TSystemCodePage;
 function TResExprEvaluator.GetCodePage(const s: RawByteString): TSystemCodePage;
 begin
 begin
-  if s='' then exit(DefaultStringCodePage);
+  if s='' then exit(DefaultSourceCodePage);
   Result:=StringCodePage(s);
   Result:=StringCodePage(s);
   if (Result=CP_ACP) or (Result=CP_NONE) then
   if (Result=CP_ACP) or (Result=CP_NONE) then
     begin
     begin
-    Result:=DefaultStringCodePage;
+    Result:=DefaultSourceCodePage;
     if (Result=CP_ACP) or (Result=CP_NONE) then
     if (Result=CP_ACP) or (Result=CP_NONE) then
       begin
       begin
       Result:=System.DefaultSystemCodePage;
       Result:=System.DefaultSystemCodePage;
@@ -5181,7 +5337,7 @@ var
 begin
 begin
   if s='' then exit('');
   if s='' then exit('');
   CP:=GetCodePage(s);
   CP:=GetCodePage(s);
-  if CP=CP_UTF8 then
+  if (CP=CP_UTF8) or ((CP=CP_ACP) and (DefaultSystemCodePage=CP_UTF8)) then
     begin
     begin
     if ErrorEl<>nil then
     if ErrorEl<>nil then
       CheckValidUTF8(s,ErrorEl);
       CheckValidUTF8(s,ErrorEl);
@@ -5216,6 +5372,20 @@ begin
     Result:=true;
     Result:=true;
     end;
     end;
 end;
 end;
+
+function TResExprEvaluator.GetExprStringTargetCP(Expr: TPasExpr
+  ): TSystemCodePage;
+begin
+  Result:=DefaultStringCodePage;
+  if Expr=nil then ;
+end;
+
+function TResExprEvaluator.GetExprStringSourceCP(Expr: TPasExpr
+  ): TSystemCodePage;
+begin
+  Result:=DefaultSourceCodePage;
+  if Expr=nil then ;
+end;
 {$endif}
 {$endif}
 
 
 procedure TResExprEvaluator.PredBool(Value: TResEvalBool; ErrorEl: TPasElement);
 procedure TResExprEvaluator.PredBool(Value: TResEvalBool; ErrorEl: TPasElement);
@@ -5564,6 +5734,7 @@ end;
 constructor TResEvalString.Create;
 constructor TResEvalString.Create;
 begin
 begin
   inherited Create;
   inherited Create;
+  OnlyASCII:=true;
   Kind:=revkString;
   Kind:=revkString;
 end;
 end;
 
 
@@ -5577,6 +5748,7 @@ function TResEvalString.Clone: TResEvalValue;
 begin
 begin
   Result:=inherited Clone;
   Result:=inherited Clone;
   TResEvalString(Result).S:=S;
   TResEvalString(Result).S:=S;
+  TResEvalString(Result).OnlyASCII:=OnlyASCII;
 end;
 end;
 
 
 function TResEvalString.AsString: string;
 function TResEvalString.AsString: string;

+ 72 - 37
packages/fcl-passrc/src/pasresolver.pp

@@ -1710,7 +1710,8 @@ type
     function CreateClassIntfMap(El: TPasClassType; Index: integer): TPasClassIntfMap;
     function CreateClassIntfMap(El: TPasClassType; Index: integer): TPasClassIntfMap;
     procedure CheckConditionExpr(El: TPasExpr; const ResolvedEl: TPasResolverResult); virtual;
     procedure CheckConditionExpr(El: TPasExpr; const ResolvedEl: TPasResolverResult); virtual;
     procedure CheckProcSignatureMatch(DeclProc, ImplProc: TPasProcedure;
     procedure CheckProcSignatureMatch(DeclProc, ImplProc: TPasProcedure;
-      IsOverride: boolean);
+      IsOverride: boolean // override or class intf implementation
+      );
     procedure CheckPointerCycle(El: TPasPointerType);
     procedure CheckPointerCycle(El: TPasPointerType);
     procedure CheckGenericTemplateTypes(El: TPasGenericType); virtual;
     procedure CheckGenericTemplateTypes(El: TPasGenericType); virtual;
     procedure ComputeUnaryNot(El: TUnaryExpr; var ResolvedEl: TPasResolverResult;
     procedure ComputeUnaryNot(El: TUnaryExpr; var ResolvedEl: TPasResolverResult;
@@ -6453,6 +6454,10 @@ begin
               RaiseMsg(20180322143202,nNoMatchingImplForIntfMethodXFound,
               RaiseMsg(20180322143202,nNoMatchingImplForIntfMethodXFound,
                 sNoMatchingImplForIntfMethodXFound,
                 sNoMatchingImplForIntfMethodXFound,
                 [GetProcTypeDescription(IntfProc.ProcType,[prptdUseName,prptdAddPaths,prptdResolveSimpleAlias])],El); // ToDo: jump to interface list
                 [GetProcTypeDescription(IntfProc.ProcType,[prptdUseName,prptdAddPaths,prptdResolveSimpleAlias])],El); // ToDo: jump to interface list
+            // check calling conventions
+            //writeln('TPasResolver.FinishClassType Intf=',GetObjPath(IntfProc),' Found=',GetObjPath(FindData.Found));
+            CheckProcSignatureMatch(IntfProc,TPasProcedure(FindData.Found),true);
+
             Map.Procs[j]:=FindData.Found;
             Map.Procs[j]:=FindData.Found;
             end;
             end;
           Map:=Map.AncestorMap;
           Map:=Map.AncestorMap;
@@ -9396,7 +9401,7 @@ var
   DeclName, ImplName: String;
   DeclName, ImplName: String;
   ImplResult, DeclResult: TPasType;
   ImplResult, DeclResult: TPasType;
   ImplTemplType, DeclTemplType: TPasGenericTemplateType;
   ImplTemplType, DeclTemplType: TPasGenericTemplateType;
-  NewImplPTMods: TProcTypeModifiers;
+  NewImplPTMods, DeclPTMods, ImplPTMods: TProcTypeModifiers;
   ptm: TProcTypeModifier;
   ptm: TProcTypeModifier;
   NewImplProcMods: TProcedureModifiers;
   NewImplProcMods: TProcedureModifiers;
   pm: TProcedureModifier;
   pm: TProcedureModifier;
@@ -9409,6 +9414,9 @@ begin
   if DeclArgs.Count<>ImplArgs.Count then
   if DeclArgs.Count<>ImplArgs.Count then
     RaiseNotYetImplemented(20190912110642,ImplProc);
     RaiseNotYetImplemented(20190912110642,ImplProc);
 
 
+  DeclPTMods:=DeclProc.ProcType.Modifiers;
+  ImplPTMods:=ImplProc.ProcType.Modifiers;
+
   DeclTemplates:=GetProcTemplateTypes(DeclProc);
   DeclTemplates:=GetProcTemplateTypes(DeclProc);
   ImplTemplates:=GetProcTemplateTypes(ImplProc);
   ImplTemplates:=GetProcTemplateTypes(ImplProc);
   if DeclTemplates<>nil then
   if DeclTemplates<>nil then
@@ -9465,33 +9473,36 @@ begin
     if CheckElTypeCompatibility(ImplResult,DeclResult,prraSimple)>cGenericExact then
     if CheckElTypeCompatibility(ImplResult,DeclResult,prraSimple)>cGenericExact then
       RaiseIncompatibleType(20170216151734,nResultTypeMismatchExpectedButFound,
       RaiseIncompatibleType(20170216151734,nResultTypeMismatchExpectedButFound,
         [],DeclResult,ImplResult,ImplProc);
         [],DeclResult,ImplResult,ImplProc);
-
-    if ImplProc.IsAsync and not DeclProc.IsAsync then
-      RaiseMsg(20200524111856,nXModifierMismatchY,sXModifierMismatchY,['procedure type','async'],ImplProc);
     end;
     end;
 
 
   // calling convention
   // calling convention
   if ImplProc.CallingConvention<>DeclProc.CallingConvention then
   if ImplProc.CallingConvention<>DeclProc.CallingConvention then
     RaiseMsg(20170216151731,nCallingConventionMismatch,sCallingConventionMismatch,[],ImplProc);
     RaiseMsg(20170216151731,nCallingConventionMismatch,sCallingConventionMismatch,[],ImplProc);
 
 
-  // proc modifiers
-  NewImplProcMods:=ImplProc.Modifiers-DeclProc.Modifiers-[pmAssembler];
-  if not IsOverride then
+  // modifiers
+  if IsOverride then
+    begin
+    // override/class-intf-impl: calling conventions must match
+    NewImplPTMods:=ImplPTMods><DeclPTMods;
+    for ptm in NewImplPTMods do
+      RaiseMsg(20201227213020,nXModifierMismatchY,sXModifierMismatchY,
+        ['procedure type',ProcTypeModifiers[ptm]],ImplProc.ProcType);
+    end
+  else
     begin
     begin
     // implementation proc must not add modifiers, except "assembler"
     // implementation proc must not add modifiers, except "assembler"
+    NewImplProcMods:=ImplProc.Modifiers-DeclProc.Modifiers-[pmAssembler];
     if NewImplProcMods<>[] then
     if NewImplProcMods<>[] then
       for pm in NewImplProcMods do
       for pm in NewImplProcMods do
         RaiseMsg(20200518182445,nDirectiveXNotAllowedHere,sDirectiveXNotAllowedHere,
         RaiseMsg(20200518182445,nDirectiveXNotAllowedHere,sDirectiveXNotAllowedHere,
           [ModifierNames[pm]],ImplProc.ProcType);
           [ModifierNames[pm]],ImplProc.ProcType);
+    // implementation proc must not add modifiers
+    NewImplPTMods:=ImplPTMods-DeclPTMods;
+    if NewImplPTMods<>[] then
+      for ptm in NewImplPTMods do
+        RaiseMsg(20200425154821,nDirectiveXNotAllowedHere,sDirectiveXNotAllowedHere,
+          [ProcTypeModifiers[ptm]],ImplProc.ProcType);
     end;
     end;
-
-  // proc type modifiers
-  NewImplPTMods:=ImplProc.ProcType.Modifiers-DeclProc.ProcType.Modifiers;
-  // implementation proc must not add modifiers
-  if NewImplPTMods<>[] then
-    for ptm in NewImplPTMods do
-      RaiseMsg(20200425154821,nDirectiveXNotAllowedHere,sDirectiveXNotAllowedHere,
-        [ProcTypeModifiers[ptm]],ImplProc.ProcType);
 end;
 end;
 
 
 procedure TPasResolver.ResolveImplBlock(Block: TPasImplBlock);
 procedure TPasResolver.ResolveImplBlock(Block: TPasImplBlock);
@@ -10982,7 +10993,7 @@ begin
     FoundEl:=GetSpecializedEl(NameExpr,FoundEl,TemplParams);
     FoundEl:=GetSpecializedEl(NameExpr,FoundEl,TemplParams);
     if FoundEl is TPasProcedure then
     if FoundEl is TPasProcedure then
       begin
       begin
-      // check if params fit the implicit specialized function
+      // check if params fit the explicit specialized function, e.g. Run<Word>()
       CheckCallProcCompatibility(TPasProcedure(FoundEl).ProcType,Params,true);
       CheckCallProcCompatibility(TPasProcedure(FoundEl).ProcType,Params,true);
       end;
       end;
     end
     end
@@ -10996,7 +11007,7 @@ begin
       try
       try
         CheckTemplParams(GenTemplates,InferenceParams);
         CheckTemplParams(GenTemplates,InferenceParams);
         FoundEl:=GetSpecializedEl(NameExpr,FoundEl,InferenceParams);
         FoundEl:=GetSpecializedEl(NameExpr,FoundEl,InferenceParams);
-        // check if params fit the implicit specialized function
+        // check if params fit the implicit specialized function, e.g. Run()
         CheckCallProcCompatibility(TPasProcedure(FoundEl).ProcType,Params,true);
         CheckCallProcCompatibility(TPasProcedure(FoundEl).ProcType,Params,true);
       finally
       finally
         ReleaseElementList(InferenceParams{$IFDEF CheckPasTreeRefCount},RefIdInferenceParamsExpr{$ENDIF});
         ReleaseElementList(InferenceParams{$IFDEF CheckPasTreeRefCount},RefIdInferenceParamsExpr{$ENDIF});
@@ -11023,13 +11034,12 @@ begin
       else
       else
         begin
         begin
         // typecast to user type
         // typecast to user type
-        CheckTypeCast(TypeEl,Params,true); // emit warnings
+        CheckTypeCast(TypeEl,Params,true); // emit warnings, and errors for specializations
         end;
         end;
     end;
     end;
 
 
   // FoundEl compatible element -> create reference
   // FoundEl compatible element -> create reference
   Ref:=CreateReference(FoundEl,NameExpr,rraRead);
   Ref:=CreateReference(FoundEl,NameExpr,rraRead);
-
   if FindCallData.StartScope.ClassType=ScopeClass_WithExpr then
   if FindCallData.StartScope.ClassType=ScopeClass_WithExpr then
     Ref.WithExprScope:=TPasWithExprScope(FindCallData.StartScope);
     Ref.WithExprScope:=TPasWithExprScope(FindCallData.StartScope);
   FindData:=Default(TPRFindData);
   FindData:=Default(TPRFindData);
@@ -15704,7 +15714,7 @@ begin
       end;
       end;
     {$endif}
     {$endif}
     revkUnicodeString:
     revkUnicodeString:
-      if length(TResEvalUTF16(Value).S)=1 then
+      if (length(TResEvalUTF16(Value).S)=1) and (bt in btAllChars) then
         begin
         begin
         w:=TResEvalUTF16(Value).S[1];
         w:=TResEvalUTF16(Value).S[1];
         {$ifdef FPC_HAS_CPSTRING}
         {$ifdef FPC_HAS_CPSTRING}
@@ -16652,8 +16662,28 @@ end;
 
 
 function TPasResolver.CreateSpecializedTypeName(Item: TPRSpecializedItem): string;
 function TPasResolver.CreateSpecializedTypeName(Item: TPRSpecializedItem): string;
 
 
+  function Get_ProcName(aProc: TPasProcedure): string; forward;
   function GetTypeName(aType: TPasType): string; forward;
   function GetTypeName(aType: TPasType): string; forward;
 
 
+  function GetParentName(El: TPasElement): string;
+  begin
+    if El.Parent is TPasType then
+      Result:=GetTypeName(TPasType(El.Parent))
+    else if El is TPasUnresolvedSymbolRef then
+      Result:='System'
+    else if El.Parent is TPasProcedure then
+      Result:=Get_ProcName(TPasProcedure(El.Parent))
+    else
+      Result:=El.GetModule.Name;
+  end;
+
+  function Get_ProcName(aProc: TPasProcedure): string;
+  begin
+    Result:=GetParentName(aProc);
+    if aProc.Name<>'' then
+      Result:=Result+'.'+aProc.Name;
+  end;
+
   function GetSpecParams(Item: TPRSpecializedItem): string;
   function GetSpecParams(Item: TPRSpecializedItem): string;
   var
   var
     i: Integer;
     i: Integer;
@@ -16692,13 +16722,7 @@ function TPasResolver.CreateSpecializedTypeName(Item: TPRSpecializedItem): strin
       end
       end
     else
     else
       begin
       begin
-      if aType.Parent is TPasType then
-        Result:=GetTypeName(TPasType(aType.Parent))
-      else if aType is TPasUnresolvedSymbolRef then
-        Result:='System'
-      else
-        Result:=aType.GetModule.Name;
-      Result:=Result+'.'+aType.Name;
+      Result:=GetParentName(aType)+'.'+aType.Name;
       if (aType.CustomData is TPasGenericScope) and (Pos('<',aType.Name)<1) then
       if (aType.CustomData is TPasGenericScope) and (Pos('<',aType.Name)<1) then
         begin
         begin
         ChildItem:=TPasGenericScope(aType.CustomData).SpecializedFromItem;
         ChildItem:=TPasGenericScope(aType.CustomData).SpecializedFromItem;
@@ -26738,7 +26762,7 @@ function TPasResolver.CheckTypeCastRes(const FromResolved,
   end;
   end;
 
 
 var
 var
-  ToTypeEl, ToType, FromType, FromTypeEl: TPasType;
+  ToTypeEl, FromTypeEl: TPasType;
   ToTypeBaseType: TResolverBaseType;
   ToTypeBaseType: TResolverBaseType;
   C: TClass;
   C: TClass;
   ToProcType, FromProcType: TPasProcedureType;
   ToProcType, FromProcType: TPasProcedureType;
@@ -26763,9 +26787,12 @@ begin
       begin
       begin
       if ToTypeEl.CustomData is TResElDataBaseType then
       if ToTypeEl.CustomData is TResElDataBaseType then
         begin
         begin
-        // base type cast, e.g. double(aninteger)
+        // type cast to base type, e.g. double(aninteger)
         if ToTypeEl=FromResolved.LoTypeEl then
         if ToTypeEl=FromResolved.LoTypeEl then
           exit(cExact);
           exit(cExact);
+        if (FromResolved.BaseType=btContext)
+            and (FromResolved.LoTypeEl.ClassType=TPasGenericTemplateType) then
+          exit(cExact); // e.g. double(T) -> will be checked when specialized
         ToTypeBaseType:=(ToTypeEl.CustomData as TResElDataBaseType).BaseType;
         ToTypeBaseType:=(ToTypeEl.CustomData as TResElDataBaseType).BaseType;
         if ToTypeBaseType=FromResolved.BaseType then
         if ToTypeBaseType=FromResolved.BaseType then
           Result:=cExact
           Result:=cExact
@@ -26950,6 +26977,9 @@ begin
       // e.g. T(var)
       // e.g. T(var)
       TemplType:=TPasGenericTemplateType(ToTypeEl);
       TemplType:=TPasGenericTemplateType(ToTypeEl);
       FromTypeEl:=FromResolved.LoTypeEl;
       FromTypeEl:=FromResolved.LoTypeEl;
+      if (FromTypeEl<>nil)
+          and (FromTypeEl.ClassType=TPasGenericTemplateType) then
+        exit(cExact); // e.g. T(S)  -> will be checked when specialized
       for i:=0 to length(TemplType.Constraints)-1 do
       for i:=0 to length(TemplType.Constraints)-1 do
         begin
         begin
         ConEl:=TemplType.Constraints[i];
         ConEl:=TemplType.Constraints[i];
@@ -26984,9 +27014,9 @@ begin
           if (FromResolved.IdentEl is TPasType) then
           if (FromResolved.IdentEl is TPasType) then
             RaiseMsg(20170404162604,nCannotTypecastAType,sCannotTypecastAType,[],ErrorEl);
             RaiseMsg(20170404162604,nCannotTypecastAType,sCannotTypecastAType,[],ErrorEl);
           // type cast  classof(classof-var)  upwards or downwards
           // type cast  classof(classof-var)  upwards or downwards
-          ToType:=TPasClassOfType(ToTypeEl).DestType;
-          FromType:=TPasClassOfType(FromResolved.LoTypeEl).DestType;
-          Result:=CheckClassesAreRelated(ToType,FromType);
+          ToTypeEl:=TPasClassOfType(ToTypeEl).DestType;
+          FromTypeEl:=TPasClassOfType(FromResolved.LoTypeEl).DestType;
+          Result:=CheckClassesAreRelated(ToTypeEl,FromTypeEl);
           end;
           end;
         end
         end
       else if FromResolved.BaseType=btPointer then
       else if FromResolved.BaseType=btPointer then
@@ -27171,9 +27201,8 @@ begin
             and (ToTypeEl=ToResolved.IdentEl) then
             and (ToTypeEl=ToResolved.IdentEl) then
           begin
           begin
           // for example  class-of(Self) in a class function
           // for example  class-of(Self) in a class function
-          ToType:=TPasClassOfType(ToTypeEl).DestType;
-          FromType:=TPasClassType(FromTypeEl);
-          Result:=CheckClassesAreRelated(ToType,FromType);
+          ToTypeEl:=TPasClassOfType(ToTypeEl).DestType;
+          Result:=CheckClassesAreRelated(ToTypeEl,FromTypeEl);
           end;
           end;
         end;
         end;
       end;
       end;
@@ -27225,6 +27254,11 @@ begin
   {$IFDEF VerbosePasResolver}
   {$IFDEF VerbosePasResolver}
   writeln('TPasResolver.CheckTypeCastArray From=',GetTypeDescription(FromType),' ToType=',GetTypeDescription(ToType));
   writeln('TPasResolver.CheckTypeCastArray From=',GetTypeDescription(FromType),' ToType=',GetTypeDescription(ToType));
   {$ENDIF}
   {$ENDIF}
+  if not RaiseOnError then
+    begin
+    if (ToType.GenericTemplateTypes<>nil) and (ToType.GenericTemplateTypes.Count>0) then
+      exit(cCompatible); // is later checked when specialized
+    end;
   StartFromType:=FromType;
   StartFromType:=FromType;
   StartToType:=ToType;
   StartToType:=ToType;
   Result:=cIncompatible;
   Result:=cIncompatible;
@@ -27254,10 +27288,11 @@ begin
         break; // ToType has more dimensions
         break; // ToType has more dimensions
         end;
         end;
       // have same dimension -> check ElType
       // have same dimension -> check ElType
+      Include(FromElTypeRes.Flags,rrfReadable);
+      FromElTypeRes.IdentEl:=nil;
       {$IFDEF VerbosePasResolver}
       {$IFDEF VerbosePasResolver}
       writeln('TPasResolver.CheckTypeCastArray check ElType From=',GetResolverResultDbg(FromElTypeRes),' To=',GetResolverResultDbg(ToElTypeRes));
       writeln('TPasResolver.CheckTypeCastArray check ElType From=',GetResolverResultDbg(FromElTypeRes),' To=',GetResolverResultDbg(ToElTypeRes));
       {$ENDIF}
       {$ENDIF}
-      Include(FromElTypeRes.Flags,rrfReadable);
       Result:=CheckTypeCastRes(FromElTypeRes,ToElTypeRes,ErrorEl,false);
       Result:=CheckTypeCastRes(FromElTypeRes,ToElTypeRes,ErrorEl,false);
       break;
       break;
       end
       end

+ 1 - 1
packages/fcl-passrc/src/paswrite.pp

@@ -1659,7 +1659,7 @@ procedure WritePasFile(AElement: TPasElement; const AFilename: string);
 var
 var
   Stream: TFileStream;
   Stream: TFileStream;
 begin
 begin
-  Stream := TFileStream.Create(AFilename, fmCreate);
+  Stream := TFileStream.Create(AFilename, fmCreate or fmShareDenyNone);
   try
   try
     WritePasFile(AElement, Stream);
     WritePasFile(AElement, Stream);
   finally
   finally

+ 28 - 0
packages/fcl-passrc/tests/tcresolvegenerics.pas

@@ -185,6 +185,7 @@ type
     procedure TestGenMethod_OverloadTypeParamCntObjFPC;
     procedure TestGenMethod_OverloadTypeParamCntObjFPC;
     procedure TestGenMethod_OverloadTypeParamCntDelphi;
     procedure TestGenMethod_OverloadTypeParamCntDelphi;
     procedure TestGenMethod_OverloadArgs;
     procedure TestGenMethod_OverloadArgs;
+    procedure TestGenMethod_TypeCastParam;
   end;
   end;
 
 
 implementation
 implementation
@@ -2982,6 +2983,33 @@ begin
   ParseProgram;
   ParseProgram;
 end;
 end;
 
 
+procedure TTestResolveGenerics.TestGenMethod_TypeCastParam;
+begin
+  StartUnit(false);
+  Add([
+  '{$mode delphi}',
+  'interface',
+  'type',
+  '  TObject = class end;',
+  '  TAnt = class end;',
+  '  TArray<T> = array of T;',
+  '  TBird = class',
+  '    F: TArray<TObject>;',
+  '    procedure Run<S>(a: TArray<S>);',
+  '  end;',
+  'implementation',
+  'procedure TBird.Run<S>(a: TArray<S>);',
+  'begin',
+  '  a:=TArray<S>(a);',
+  '  F:=TArray<TObject>(a);',
+  'end;',
+  'var B: TBird;',
+  'initialization',
+  '  B.Run<TAnt>(nil);',
+  '']);
+  ParseUnit;
+end;
+
 initialization
 initialization
   RegisterTests([TTestResolveGenerics]);
   RegisterTests([TTestResolveGenerics]);
 
 

+ 5 - 5
packages/fcl-passrc/tests/tcresolver.pas

@@ -299,7 +299,7 @@ type
     Procedure TestIntegerBoolFail;
     Procedure TestIntegerBoolFail;
     Procedure TestBooleanOperators;
     Procedure TestBooleanOperators;
     Procedure TestStringOperators;
     Procedure TestStringOperators;
-    Procedure TestWideCharOperators;
+    Procedure TestWideCharOperators_DelphiUnicode;
     Procedure TestFloatOperators;
     Procedure TestFloatOperators;
     Procedure TestCAssignments;
     Procedure TestCAssignments;
     Procedure TestTypeCastBaseTypes;
     Procedure TestTypeCastBaseTypes;
@@ -2181,6 +2181,8 @@ begin
   Result.OnFindUnit:=@OnPasResolverFindUnit;
   Result.OnFindUnit:=@OnPasResolverFindUnit;
   Result.OnLog:=@OnPasResolverLog;
   Result.OnLog:=@OnPasResolverLog;
   Result.Hub:=Hub;
   Result.Hub:=Hub;
+  Result.ExprEvaluator.DefaultStringCodePage:=CP_UTF8;
+  Result.ExprEvaluator.DefaultSourceCodePage:=CP_UTF8;
   FModules.Add(Result);
   FModules.Add(Result);
 end;
 end;
 
 
@@ -4678,9 +4680,9 @@ begin
   ParseProgram;
   ParseProgram;
 end;
 end;
 
 
-procedure TTestResolver.TestWideCharOperators;
+procedure TTestResolver.TestWideCharOperators_DelphiUnicode;
 begin
 begin
-  ResolverEngine.ExprEvaluator.DefaultStringCodePage:=CP_UTF8;
+  ResolverEngine.ExprEvaluator.DefaultStringCodePage:=CP_UTF16;
   ResolverEngine.BaseTypeChar:=btWideChar;
   ResolverEngine.BaseTypeChar:=btWideChar;
   ResolverEngine.BaseTypeString:=btUnicodeString;
   ResolverEngine.BaseTypeString:=btUnicodeString;
   StartProgram(false);
   StartProgram(false);
@@ -14307,7 +14309,6 @@ end;
 
 
 procedure TTestResolver.TestStaticArrayOfChar;
 procedure TTestResolver.TestStaticArrayOfChar;
 begin
 begin
-  ResolverEngine.ExprEvaluator.DefaultStringCodePage:=CP_UTF8;
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
   'type',
   'type',
@@ -14329,7 +14330,6 @@ end;
 
 
 procedure TTestResolver.TestStaticArrayOfCharDelphi;
 procedure TTestResolver.TestStaticArrayOfCharDelphi;
 begin
 begin
-  ResolverEngine.ExprEvaluator.DefaultStringCodePage:=CP_UTF8;
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
   '{$mode delphi}',
   '{$mode delphi}',

+ 866 - 768
packages/fcl-res/src/rclex.inc

@@ -141,10 +141,12 @@ begin
                               return(_ID);
                               return(_ID);
                          end;
                          end;
   25:
   25:
-                        ;
+                  return(_NSWPSTR);
   26:
   26:
-                        returnc(yytext[1]);
+                        ;
   27:
   27:
+                        returnc(yytext[1]);
+  28:
                         return(_ILLEGAL);
                         return(_ILLEGAL);
   end;
   end;
 end(*yyaction*);
 end(*yyaction*);
@@ -158,14 +160,16 @@ type YYTRec = record
 
 
 const
 const
 
 
-yynmarks   = 62;
-yynmatches = 62;
-yyntrans   = 131;
-yynstates  = 94;
+yynmarks   = 88;
+yynmatches = 88;
+yyntrans   = 156;
+yynstates  = 96;
 
 
 yyk : array [1..yynmarks] of Integer = (
 yyk : array [1..yynmarks] of Integer = (
   { 0: }
   { 0: }
+  25,
   { 1: }
   { 1: }
+  25,
   { 2: }
   { 2: }
   { 3: }
   { 3: }
   { 4: }
   { 4: }
@@ -175,132 +179,153 @@ yyk : array [1..yynmarks] of Integer = (
   { 8: }
   { 8: }
   { 9: }
   { 9: }
   { 10: }
   { 10: }
-  26,
   27,
   27,
+  28,
   { 11: }
   { 11: }
   8,
   8,
-  27,
+  25,
+  28,
   { 12: }
   { 12: }
   8,
   8,
-  27,
+  25,
+  28,
   { 13: }
   { 13: }
   24,
   24,
-  27,
+  25,
+  28,
   { 14: }
   { 14: }
   12,
   12,
-  27,
+  28,
   { 15: }
   { 15: }
   24,
   24,
-  27,
+  25,
+  28,
   { 16: }
   { 16: }
   22,
   22,
-  27,
+  28,
   { 17: }
   { 17: }
   24,
   24,
-  27,
+  25,
+  28,
   { 18: }
   { 18: }
   23,
   23,
-  27,
+  28,
   { 19: }
   { 19: }
   24,
   24,
-  27,
+  25,
+  28,
   { 20: }
   { 20: }
   25,
   25,
+  28,
   { 21: }
   { 21: }
   26,
   26,
-  27,
   { 22: }
   { 22: }
-  25,
   27,
   27,
+  28,
   { 23: }
   { 23: }
-  27,
+  26,
+  28,
   { 24: }
   { 24: }
-  2,
+  28,
   { 25: }
   { 25: }
-  3,
+  2,
   { 26: }
   { 26: }
-  5,
+  3,
   { 27: }
   { 27: }
   5,
   5,
   { 28: }
   { 28: }
-  7,
+  5,
   { 29: }
   { 29: }
-  14,
-  18,
+  7,
   { 30: }
   { 30: }
+  14,
   18,
   18,
   { 31: }
   { 31: }
-  17,
-  { 32: }
   18,
   18,
+  { 32: }
+  17,
   { 33: }
   { 33: }
-  15,
   18,
   18,
   { 34: }
   { 34: }
-  1,
+  15,
+  18,
   { 35: }
   { 35: }
-  4,
+  1,
   { 36: }
   { 36: }
-  8,
+  4,
   { 37: }
   { 37: }
   8,
   8,
+  25,
   { 38: }
   { 38: }
+  8,
+  25,
   { 39: }
   { 39: }
+  25,
   { 40: }
   { 40: }
-  11,
+  25,
   { 41: }
   { 41: }
-  24,
+  25,
   { 42: }
   { 42: }
+  11,
   { 43: }
   { 43: }
+  24,
+  25,
   { 44: }
   { 44: }
   { 45: }
   { 45: }
-  24,
   { 46: }
   { 46: }
-  24,
   { 47: }
   { 47: }
-  6,
+  24,
+  25,
   { 48: }
   { 48: }
-  13,
+  24,
+  25,
   { 49: }
   { 49: }
-  16,
+  6,
   { 50: }
   { 50: }
-  9,
+  13,
   { 51: }
   { 51: }
-  10,
+  16,
   { 52: }
   { 52: }
+  9,
+  25,
   { 53: }
   { 53: }
-  24,
+  10,
+  25,
   { 54: }
   { 54: }
-  23,
-  24,
   { 55: }
   { 55: }
-  9,
   { 56: }
   { 56: }
-  10,
   { 57: }
   { 57: }
+  24,
+  25,
   { 58: }
   { 58: }
+  23,
+  24,
+  25,
   { 59: }
   { 59: }
+  9,
+  25,
   { 60: }
   { 60: }
-  24,
+  10,
+  25,
   { 61: }
   { 61: }
   { 62: }
   { 62: }
-  22,
-  24,
   { 63: }
   { 63: }
   { 64: }
   { 64: }
+  24,
+  25,
   { 65: }
   { 65: }
   { 66: }
   { 66: }
   { 67: }
   { 67: }
   { 68: }
   { 68: }
+  22,
+  24,
+  25,
   { 69: }
   { 69: }
   { 70: }
   { 70: }
   { 71: }
   { 71: }
   { 72: }
   { 72: }
-  20,
   { 73: }
   { 73: }
-  21,
   { 74: }
   { 74: }
-  19
   { 75: }
   { 75: }
   { 76: }
   { 76: }
   { 77: }
   { 77: }
@@ -318,13 +343,20 @@ yyk : array [1..yynmarks] of Integer = (
   { 89: }
   { 89: }
   { 90: }
   { 90: }
   { 91: }
   { 91: }
+  20,
   { 92: }
   { 92: }
+  21,
   { 93: }
   { 93: }
+  { 94: }
+  { 95: }
+  19
 );
 );
 
 
 yym : array [1..yynmatches] of Integer = (
 yym : array [1..yynmatches] of Integer = (
 { 0: }
 { 0: }
+  25,
 { 1: }
 { 1: }
+  25,
 { 2: }
 { 2: }
 { 3: }
 { 3: }
 { 4: }
 { 4: }
@@ -334,132 +366,153 @@ yym : array [1..yynmatches] of Integer = (
 { 8: }
 { 8: }
 { 9: }
 { 9: }
 { 10: }
 { 10: }
-  26,
   27,
   27,
+  28,
 { 11: }
 { 11: }
   8,
   8,
-  27,
+  25,
+  28,
 { 12: }
 { 12: }
   8,
   8,
-  27,
+  25,
+  28,
 { 13: }
 { 13: }
   24,
   24,
-  27,
+  25,
+  28,
 { 14: }
 { 14: }
   12,
   12,
-  27,
+  28,
 { 15: }
 { 15: }
   24,
   24,
-  27,
+  25,
+  28,
 { 16: }
 { 16: }
   22,
   22,
-  27,
+  28,
 { 17: }
 { 17: }
   24,
   24,
-  27,
+  25,
+  28,
 { 18: }
 { 18: }
   23,
   23,
-  27,
+  28,
 { 19: }
 { 19: }
   24,
   24,
-  27,
+  25,
+  28,
 { 20: }
 { 20: }
   25,
   25,
+  28,
 { 21: }
 { 21: }
   26,
   26,
-  27,
 { 22: }
 { 22: }
-  25,
   27,
   27,
+  28,
 { 23: }
 { 23: }
-  27,
+  26,
+  28,
 { 24: }
 { 24: }
-  2,
+  28,
 { 25: }
 { 25: }
-  3,
+  2,
 { 26: }
 { 26: }
-  5,
+  3,
 { 27: }
 { 27: }
   5,
   5,
 { 28: }
 { 28: }
-  7,
+  5,
 { 29: }
 { 29: }
-  14,
-  18,
+  7,
 { 30: }
 { 30: }
+  14,
   18,
   18,
 { 31: }
 { 31: }
-  17,
-{ 32: }
   18,
   18,
+{ 32: }
+  17,
 { 33: }
 { 33: }
-  15,
   18,
   18,
 { 34: }
 { 34: }
-  1,
+  15,
+  18,
 { 35: }
 { 35: }
-  4,
+  1,
 { 36: }
 { 36: }
-  8,
+  4,
 { 37: }
 { 37: }
   8,
   8,
+  25,
 { 38: }
 { 38: }
+  8,
+  25,
 { 39: }
 { 39: }
+  25,
 { 40: }
 { 40: }
-  11,
+  25,
 { 41: }
 { 41: }
-  24,
+  25,
 { 42: }
 { 42: }
+  11,
 { 43: }
 { 43: }
+  24,
+  25,
 { 44: }
 { 44: }
 { 45: }
 { 45: }
-  24,
 { 46: }
 { 46: }
-  24,
 { 47: }
 { 47: }
-  6,
+  24,
+  25,
 { 48: }
 { 48: }
-  13,
+  24,
+  25,
 { 49: }
 { 49: }
-  16,
+  6,
 { 50: }
 { 50: }
-  9,
+  13,
 { 51: }
 { 51: }
-  10,
+  16,
 { 52: }
 { 52: }
+  9,
+  25,
 { 53: }
 { 53: }
-  24,
+  10,
+  25,
 { 54: }
 { 54: }
-  23,
-  24,
 { 55: }
 { 55: }
-  9,
 { 56: }
 { 56: }
-  10,
 { 57: }
 { 57: }
+  24,
+  25,
 { 58: }
 { 58: }
+  23,
+  24,
+  25,
 { 59: }
 { 59: }
+  9,
+  25,
 { 60: }
 { 60: }
-  24,
+  10,
+  25,
 { 61: }
 { 61: }
 { 62: }
 { 62: }
-  22,
-  24,
 { 63: }
 { 63: }
 { 64: }
 { 64: }
+  24,
+  25,
 { 65: }
 { 65: }
 { 66: }
 { 66: }
 { 67: }
 { 67: }
 { 68: }
 { 68: }
+  22,
+  24,
+  25,
 { 69: }
 { 69: }
 { 70: }
 { 70: }
 { 71: }
 { 71: }
 { 72: }
 { 72: }
-  20,
 { 73: }
 { 73: }
-  21,
 { 74: }
 { 74: }
-  19
 { 75: }
 { 75: }
 { 76: }
 { 76: }
 { 77: }
 { 77: }
@@ -477,18 +530,24 @@ yym : array [1..yynmatches] of Integer = (
 { 89: }
 { 89: }
 { 90: }
 { 90: }
 { 91: }
 { 91: }
+  20,
 { 92: }
 { 92: }
+  21,
 { 93: }
 { 93: }
+{ 94: }
+{ 95: }
+  19
 );
 );
 
 
 yyt : array [1..yyntrans] of YYTrec = (
 yyt : array [1..yyntrans] of YYTrec = (
 { 0: }
 { 0: }
   ( cc: [ #1..#8,#11,#13..#31,'!','#','$','''','*','+',
   ( cc: [ #1..#8,#11,#13..#31,'!','#','$','''','*','+',
-            '-','.',':'..'@','['..']','`',#127..#255 ]; s: 23),
-  ( cc: [ #9,#12,' ' ]; s: 22),
-  ( cc: [ #10 ]; s: 20),
+            '-',';'..'@','[',']','`',#127..#255 ]; s: 24),
+  ( cc: [ #9,#12,' ' ]; s: 23),
+  ( cc: [ #10 ]; s: 21),
   ( cc: [ '"' ]; s: 14),
   ( cc: [ '"' ]; s: 14),
-  ( cc: [ '%','&','(',')',',','^','|','~' ]; s: 21),
+  ( cc: [ '%','&','(',')',',','^','|','~' ]; s: 22),
+  ( cc: [ '.',':','\' ]; s: 20),
   ( cc: [ '/' ]; s: 10),
   ( cc: [ '/' ]; s: 10),
   ( cc: [ '0' ]; s: 12),
   ( cc: [ '0' ]; s: 12),
   ( cc: [ '1'..'9' ]; s: 11),
   ( cc: [ '1'..'9' ]; s: 11),
@@ -500,11 +559,12 @@ yyt : array [1..yyntrans] of YYTrec = (
   ( cc: [ '}' ]; s: 18),
   ( cc: [ '}' ]; s: 18),
 { 1: }
 { 1: }
   ( cc: [ #1..#8,#11,#13..#31,'!','#','$','''','*','+',
   ( cc: [ #1..#8,#11,#13..#31,'!','#','$','''','*','+',
-            '-','.',':'..'@','['..']','`',#127..#255 ]; s: 23),
-  ( cc: [ #9,#12,' ' ]; s: 22),
-  ( cc: [ #10 ]; s: 20),
+            '-',';'..'@','[',']','`',#127..#255 ]; s: 24),
+  ( cc: [ #9,#12,' ' ]; s: 23),
+  ( cc: [ #10 ]; s: 21),
   ( cc: [ '"' ]; s: 14),
   ( cc: [ '"' ]; s: 14),
-  ( cc: [ '%','&','(',')',',','^','|','~' ]; s: 21),
+  ( cc: [ '%','&','(',')',',','^','|','~' ]; s: 22),
+  ( cc: [ '.',':','\' ]; s: 20),
   ( cc: [ '/' ]; s: 10),
   ( cc: [ '/' ]; s: 10),
   ( cc: [ '0' ]; s: 12),
   ( cc: [ '0' ]; s: 12),
   ( cc: [ '1'..'9' ]; s: 11),
   ( cc: [ '1'..'9' ]; s: 11),
@@ -515,68 +575,76 @@ yyt : array [1..yyntrans] of YYTrec = (
   ( cc: [ '{' ]; s: 16),
   ( cc: [ '{' ]; s: 16),
   ( cc: [ '}' ]; s: 18),
   ( cc: [ '}' ]; s: 18),
 { 2: }
 { 2: }
-  ( cc: [ #1..#9,#11..#255 ]; s: 25),
-  ( cc: [ #10 ]; s: 24),
+  ( cc: [ #1..#9,#11..#255 ]; s: 26),
+  ( cc: [ #10 ]; s: 25),
 { 3: }
 { 3: }
-  ( cc: [ #1..#9,#11..#255 ]; s: 25),
-  ( cc: [ #10 ]; s: 24),
+  ( cc: [ #1..#9,#11..#255 ]; s: 26),
+  ( cc: [ #10 ]; s: 25),
 { 4: }
 { 4: }
-  ( cc: [ #0 ]; s: 28),
-  ( cc: [ #1..#9,#11..')','+'..#255 ]; s: 26),
-  ( cc: [ '*' ]; s: 27),
+  ( cc: [ #0 ]; s: 29),
+  ( cc: [ #1..#9,#11..')','+'..#255 ]; s: 27),
+  ( cc: [ '*' ]; s: 28),
 { 5: }
 { 5: }
-  ( cc: [ #0 ]; s: 28),
-  ( cc: [ #1..#9,#11..')','+'..#255 ]; s: 26),
-  ( cc: [ '*' ]; s: 27),
+  ( cc: [ #0 ]; s: 29),
+  ( cc: [ #1..#9,#11..')','+'..#255 ]; s: 27),
+  ( cc: [ '*' ]; s: 28),
 { 6: }
 { 6: }
-  ( cc: [ #1..#9,#11..'!','#'..'[',']'..#255 ]; s: 32),
-  ( cc: [ #10 ]; s: 31),
-  ( cc: [ '"' ]; s: 29),
-  ( cc: [ '\' ]; s: 30),
+  ( cc: [ #1..#9,#11..'!','#'..'[',']'..#255 ]; s: 33),
+  ( cc: [ #10 ]; s: 32),
+  ( cc: [ '"' ]; s: 30),
+  ( cc: [ '\' ]; s: 31),
 { 7: }
 { 7: }
-  ( cc: [ #1..#9,#11..'!','#'..'[',']'..#255 ]; s: 32),
-  ( cc: [ #10 ]; s: 31),
-  ( cc: [ '"' ]; s: 29),
-  ( cc: [ '\' ]; s: 30),
+  ( cc: [ #1..#9,#11..'!','#'..'[',']'..#255 ]; s: 33),
+  ( cc: [ #10 ]; s: 32),
+  ( cc: [ '"' ]; s: 30),
+  ( cc: [ '\' ]; s: 31),
 { 8: }
 { 8: }
-  ( cc: [ #1..#9,#11..'!','#'..'[',']'..#255 ]; s: 32),
-  ( cc: [ #10 ]; s: 31),
-  ( cc: [ '"' ]; s: 33),
-  ( cc: [ '\' ]; s: 30),
+  ( cc: [ #1..#9,#11..'!','#'..'[',']'..#255 ]; s: 33),
+  ( cc: [ #10 ]; s: 32),
+  ( cc: [ '"' ]; s: 34),
+  ( cc: [ '\' ]; s: 31),
 { 9: }
 { 9: }
-  ( cc: [ #1..#9,#11..'!','#'..'[',']'..#255 ]; s: 32),
-  ( cc: [ #10 ]; s: 31),
-  ( cc: [ '"' ]; s: 33),
-  ( cc: [ '\' ]; s: 30),
+  ( cc: [ #1..#9,#11..'!','#'..'[',']'..#255 ]; s: 33),
+  ( cc: [ #10 ]; s: 32),
+  ( cc: [ '"' ]; s: 34),
+  ( cc: [ '\' ]; s: 31),
 { 10: }
 { 10: }
-  ( cc: [ '*' ]; s: 35),
-  ( cc: [ '/' ]; s: 34),
+  ( cc: [ '*' ]; s: 36),
+  ( cc: [ '/' ]; s: 35),
 { 11: }
 { 11: }
-  ( cc: [ '0'..'9' ]; s: 36),
-  ( cc: [ 'L' ]; s: 37),
+  ( cc: [ '.',':','A'..'K','M'..'Z','\','_','a'..'z' ]; s: 39),
+  ( cc: [ '0'..'9' ]; s: 37),
+  ( cc: [ 'L' ]; s: 38),
 { 12: }
 { 12: }
-  ( cc: [ '0'..'9' ]; s: 36),
-  ( cc: [ 'L' ]; s: 37),
-  ( cc: [ 'o' ]; s: 39),
-  ( cc: [ 'x' ]; s: 38),
+  ( cc: [ '.',':','A'..'K','M'..'Z','\','_','a'..'n',
+            'p'..'w','y','z' ]; s: 39),
+  ( cc: [ '0'..'9' ]; s: 37),
+  ( cc: [ 'L' ]; s: 38),
+  ( cc: [ 'o' ]; s: 41),
+  ( cc: [ 'x' ]; s: 40),
 { 13: }
 { 13: }
-  ( cc: [ '"' ]; s: 40),
-  ( cc: [ '0'..'9','A'..'Z','_','a'..'z' ]; s: 41),
+  ( cc: [ '"' ]; s: 42),
+  ( cc: [ '.',':','\' ]; s: 39),
+  ( cc: [ '0'..'9','A'..'Z','_','a'..'z' ]; s: 43),
 { 14: }
 { 14: }
-  ( cc: [ 'S' ]; s: 42),
-  ( cc: [ 'T' ]; s: 44),
-  ( cc: [ 'V' ]; s: 43),
+  ( cc: [ 'S' ]; s: 44),
+  ( cc: [ 'T' ]; s: 46),
+  ( cc: [ 'V' ]; s: 45),
 { 15: }
 { 15: }
-  ( cc: [ '0'..'9','A'..'D','F'..'Z','_','a'..'z' ]; s: 41),
-  ( cc: [ 'E' ]; s: 45),
+  ( cc: [ '.',':','\' ]; s: 39),
+  ( cc: [ '0'..'9','A'..'D','F'..'Z','_','a'..'z' ]; s: 43),
+  ( cc: [ 'E' ]; s: 47),
 { 16: }
 { 16: }
 { 17: }
 { 17: }
-  ( cc: [ '0'..'9','A'..'M','O'..'Z','_','a'..'z' ]; s: 41),
-  ( cc: [ 'N' ]; s: 46),
+  ( cc: [ '.',':','\' ]; s: 39),
+  ( cc: [ '0'..'9','A'..'M','O'..'Z','_','a'..'z' ]; s: 43),
+  ( cc: [ 'N' ]; s: 48),
 { 18: }
 { 18: }
 { 19: }
 { 19: }
-  ( cc: [ '0'..'9','A'..'Z','_','a'..'z' ]; s: 41),
+  ( cc: [ '.',':','\' ]; s: 39),
+  ( cc: [ '0'..'9','A'..'Z','_','a'..'z' ]; s: 43),
 { 20: }
 { 20: }
+  ( cc: [ '.','0'..':','A'..'Z','\','_','a'..'z' ]; s: 39),
 { 21: }
 { 21: }
 { 22: }
 { 22: }
 { 23: }
 { 23: }
@@ -584,713 +652,743 @@ yyt : array [1..yyntrans] of YYTrec = (
 { 25: }
 { 25: }
 { 26: }
 { 26: }
 { 27: }
 { 27: }
-  ( cc: [ '/' ]; s: 47),
 { 28: }
 { 28: }
+  ( cc: [ '/' ]; s: 49),
 { 29: }
 { 29: }
-  ( cc: [ '"' ]; s: 48),
 { 30: }
 { 30: }
-  ( cc: [ #10 ]; s: 49),
+  ( cc: [ '"' ]; s: 50),
 { 31: }
 { 31: }
+  ( cc: [ #10 ]; s: 51),
 { 32: }
 { 32: }
 { 33: }
 { 33: }
-  ( cc: [ '"' ]; s: 48),
 { 34: }
 { 34: }
+  ( cc: [ '"' ]; s: 50),
 { 35: }
 { 35: }
 { 36: }
 { 36: }
-  ( cc: [ '0'..'9' ]; s: 36),
-  ( cc: [ 'L' ]; s: 37),
 { 37: }
 { 37: }
+  ( cc: [ '.',':','A'..'K','M'..'Z','\','_','a'..'z' ]; s: 39),
+  ( cc: [ '0'..'9' ]; s: 37),
+  ( cc: [ 'L' ]; s: 38),
 { 38: }
 { 38: }
-  ( cc: [ '0'..'9','A'..'F','a'..'f' ]; s: 50),
+  ( cc: [ '.','0'..':','A'..'Z','\','_','a'..'z' ]; s: 39),
 { 39: }
 { 39: }
-  ( cc: [ '0'..'7' ]; s: 51),
+  ( cc: [ '.','0'..':','A'..'Z','\','_','a'..'z' ]; s: 39),
 { 40: }
 { 40: }
+  ( cc: [ '.',':','G'..'Z','\','_','g'..'z' ]; s: 39),
+  ( cc: [ '0'..'9','A'..'F','a'..'f' ]; s: 52),
 { 41: }
 { 41: }
-  ( cc: [ '0'..'9','A'..'Z','_','a'..'z' ]; s: 41),
+  ( cc: [ '.','8'..':','A'..'Z','\','_','a'..'z' ]; s: 39),
+  ( cc: [ '0'..'7' ]; s: 53),
 { 42: }
 { 42: }
-  ( cc: [ 't' ]; s: 52),
 { 43: }
 { 43: }
-  ( cc: [ 'a' ]; s: 77),
+  ( cc: [ '.',':','\' ]; s: 39),
+  ( cc: [ '0'..'9','A'..'Z','_','a'..'z' ]; s: 43),
 { 44: }
 { 44: }
-  ( cc: [ 'r' ]; s: 76),
+  ( cc: [ 't' ]; s: 54),
 { 45: }
 { 45: }
-  ( cc: [ '0'..'9','A'..'F','H'..'Z','_','a'..'z' ]; s: 41),
-  ( cc: [ 'G' ]; s: 53),
+  ( cc: [ 'a' ]; s: 55),
 { 46: }
 { 46: }
-  ( cc: [ '0'..'9','A'..'C','E'..'Z','_','a'..'z' ]; s: 41),
-  ( cc: [ 'D' ]; s: 54),
+  ( cc: [ 'r' ]; s: 56),
 { 47: }
 { 47: }
+  ( cc: [ '.',':','\' ]; s: 39),
+  ( cc: [ '0'..'9','A'..'F','H'..'Z','_','a'..'z' ]; s: 43),
+  ( cc: [ 'G' ]; s: 57),
 { 48: }
 { 48: }
+  ( cc: [ '.',':','\' ]; s: 39),
+  ( cc: [ '0'..'9','A'..'C','E'..'Z','_','a'..'z' ]; s: 43),
+  ( cc: [ 'D' ]; s: 58),
 { 49: }
 { 49: }
 { 50: }
 { 50: }
-  ( cc: [ '0'..'9','A'..'F','a'..'f' ]; s: 50),
-  ( cc: [ 'L' ]; s: 55),
 { 51: }
 { 51: }
-  ( cc: [ '0'..'7' ]; s: 51),
-  ( cc: [ 'L' ]; s: 56),
 { 52: }
 { 52: }
-  ( cc: [ 'r' ]; s: 57),
+  ( cc: [ '.',':','G'..'K','M'..'Z','\','_','g'..'z' ]; s: 39),
+  ( cc: [ '0'..'9','A'..'F','a'..'f' ]; s: 52),
+  ( cc: [ 'L' ]; s: 59),
 { 53: }
 { 53: }
-  ( cc: [ '0'..'9','A'..'H','J'..'Z','_','a'..'z' ]; s: 41),
-  ( cc: [ 'I' ]; s: 60),
+  ( cc: [ '.','8'..':','A'..'K','M'..'Z','\','_','a'..'z' ]; s: 39),
+  ( cc: [ '0'..'7' ]; s: 53),
+  ( cc: [ 'L' ]; s: 60),
 { 54: }
 { 54: }
-  ( cc: [ '0'..'9','A'..'Z','_','a'..'z' ]; s: 41),
+  ( cc: [ 'r' ]; s: 61),
 { 55: }
 { 55: }
+  ( cc: [ 'r' ]; s: 62),
 { 56: }
 { 56: }
+  ( cc: [ 'a' ]; s: 63),
 { 57: }
 { 57: }
-  ( cc: [ 'i' ]; s: 79),
+  ( cc: [ '.',':','\' ]; s: 39),
+  ( cc: [ '0'..'9','A'..'H','J'..'Z','_','a'..'z' ]; s: 43),
+  ( cc: [ 'I' ]; s: 64),
 { 58: }
 { 58: }
-  ( cc: [ 'F' ]; s: 78),
+  ( cc: [ '.',':','\' ]; s: 39),
+  ( cc: [ '0'..'9','A'..'Z','_','a'..'z' ]; s: 43),
 { 59: }
 { 59: }
-  ( cc: [ 'n' ]; s: 61),
+  ( cc: [ '.','0'..':','A'..'Z','\','_','a'..'z' ]; s: 39),
 { 60: }
 { 60: }
-  ( cc: [ '0'..'9','A'..'M','O'..'Z','_','a'..'z' ]; s: 41),
-  ( cc: [ 'N' ]; s: 62),
+  ( cc: [ '.','0'..':','A'..'Z','\','_','a'..'z' ]; s: 39),
 { 61: }
 { 61: }
-  ( cc: [ 's' ]; s: 80),
+  ( cc: [ 'i' ]; s: 65),
 { 62: }
 { 62: }
-  ( cc: [ '0'..'9','A'..'Z','_','a'..'z' ]; s: 41),
+  ( cc: [ 'F' ]; s: 66),
 { 63: }
 { 63: }
-  ( cc: [ 'g' ]; s: 93),
+  ( cc: [ 'n' ]; s: 67),
 { 64: }
 { 64: }
-  ( cc: [ 'l' ]; s: 65),
+  ( cc: [ '.',':','\' ]; s: 39),
+  ( cc: [ '0'..'9','A'..'M','O'..'Z','_','a'..'z' ]; s: 43),
+  ( cc: [ 'N' ]; s: 68),
 { 65: }
 { 65: }
-  ( cc: [ 'e' ]; s: 67),
+  ( cc: [ 'n' ]; s: 69),
 { 66: }
 { 66: }
-  ( cc: [ 'a' ]; s: 75),
+  ( cc: [ 'i' ]; s: 70),
 { 67: }
 { 67: }
-  ( cc: [ 'I' ]; s: 83),
+  ( cc: [ 's' ]; s: 71),
 { 68: }
 { 68: }
-  ( cc: [ 'f' ]; s: 70),
+  ( cc: [ '.',':','\' ]; s: 39),
+  ( cc: [ '0'..'9','A'..'Z','_','a'..'z' ]; s: 43),
 { 69: }
 { 69: }
-  ( cc: [ 'o' ]; s: 85),
+  ( cc: [ 'g' ]; s: 72),
 { 70: }
 { 70: }
-  ( cc: [ 'o' ]; s: 71),
+  ( cc: [ 'l' ]; s: 73),
 { 71: }
 { 71: }
-  ( cc: [ '"' ]; s: 72),
+  ( cc: [ 'l' ]; s: 74),
 { 72: }
 { 72: }
+  ( cc: [ 'F' ]; s: 75),
 { 73: }
 { 73: }
+  ( cc: [ 'e' ]; s: 76),
 { 74: }
 { 74: }
+  ( cc: [ 'a' ]; s: 77),
 { 75: }
 { 75: }
-  ( cc: [ 't' ]; s: 82),
+  ( cc: [ 'i' ]; s: 78),
 { 76: }
 { 76: }
-  ( cc: [ 'a' ]; s: 59),
+  ( cc: [ 'I' ]; s: 79),
 { 77: }
 { 77: }
-  ( cc: [ 'r' ]; s: 58),
+  ( cc: [ 't' ]; s: 80),
 { 78: }
 { 78: }
-  ( cc: [ 'i' ]; s: 64),
+  ( cc: [ 'l' ]; s: 81),
 { 79: }
 { 79: }
-  ( cc: [ 'n' ]; s: 63),
+  ( cc: [ 'n' ]; s: 82),
 { 80: }
 { 80: }
-  ( cc: [ 'l' ]; s: 66),
+  ( cc: [ 'i' ]; s: 83),
 { 81: }
 { 81: }
-  ( cc: [ '"' ]; s: 73),
+  ( cc: [ 'e' ]; s: 84),
 { 82: }
 { 82: }
-  ( cc: [ 'i' ]; s: 69),
+  ( cc: [ 'f' ]; s: 85),
 { 83: }
 { 83: }
-  ( cc: [ 'n' ]; s: 68),
+  ( cc: [ 'o' ]; s: 86),
 { 84: }
 { 84: }
-  ( cc: [ '"' ]; s: 74),
+  ( cc: [ 'I' ]; s: 87),
 { 85: }
 { 85: }
-  ( cc: [ 'n' ]; s: 81),
+  ( cc: [ 'o' ]; s: 88),
 { 86: }
 { 86: }
-  ( cc: [ 'o' ]; s: 84),
+  ( cc: [ 'n' ]; s: 89),
 { 87: }
 { 87: }
-  ( cc: [ 'f' ]; s: 86),
+  ( cc: [ 'n' ]; s: 90),
 { 88: }
 { 88: }
-  ( cc: [ 'n' ]; s: 87),
+  ( cc: [ '"' ]; s: 91),
 { 89: }
 { 89: }
-  ( cc: [ 'I' ]; s: 88),
+  ( cc: [ '"' ]; s: 92),
 { 90: }
 { 90: }
-  ( cc: [ 'e' ]; s: 89),
+  ( cc: [ 'f' ]; s: 93),
 { 91: }
 { 91: }
-  ( cc: [ 'l' ]; s: 90),
 { 92: }
 { 92: }
-  ( cc: [ 'i' ]; s: 91),
 { 93: }
 { 93: }
-  ( cc: [ 'F' ]; s: 92)
+  ( cc: [ 'o' ]; s: 94),
+{ 94: }
+  ( cc: [ '"' ]; s: 95)
+{ 95: }
 );
 );
 
 
 yykl : array [0..yynstates-1] of Integer = (
 yykl : array [0..yynstates-1] of Integer = (
 { 0: } 1,
 { 0: } 1,
-{ 1: } 1,
-{ 2: } 1,
-{ 3: } 1,
-{ 4: } 1,
-{ 5: } 1,
-{ 6: } 1,
-{ 7: } 1,
-{ 8: } 1,
-{ 9: } 1,
-{ 10: } 1,
-{ 11: } 3,
-{ 12: } 5,
-{ 13: } 7,
-{ 14: } 9,
-{ 15: } 11,
-{ 16: } 13,
-{ 17: } 15,
-{ 18: } 17,
-{ 19: } 19,
-{ 20: } 21,
-{ 21: } 22,
-{ 22: } 24,
-{ 23: } 26,
-{ 24: } 27,
-{ 25: } 28,
-{ 26: } 29,
-{ 27: } 30,
-{ 28: } 31,
-{ 29: } 32,
-{ 30: } 34,
-{ 31: } 35,
-{ 32: } 36,
-{ 33: } 37,
-{ 34: } 39,
-{ 35: } 40,
-{ 36: } 41,
-{ 37: } 42,
-{ 38: } 43,
-{ 39: } 43,
-{ 40: } 43,
-{ 41: } 44,
-{ 42: } 45,
-{ 43: } 45,
-{ 44: } 45,
-{ 45: } 45,
-{ 46: } 46,
-{ 47: } 47,
-{ 48: } 48,
-{ 49: } 49,
-{ 50: } 50,
-{ 51: } 51,
-{ 52: } 52,
-{ 53: } 52,
-{ 54: } 53,
-{ 55: } 55,
-{ 56: } 56,
-{ 57: } 57,
-{ 58: } 57,
-{ 59: } 57,
-{ 60: } 57,
-{ 61: } 58,
-{ 62: } 58,
-{ 63: } 60,
-{ 64: } 60,
-{ 65: } 60,
-{ 66: } 60,
-{ 67: } 60,
-{ 68: } 60,
-{ 69: } 60,
-{ 70: } 60,
-{ 71: } 60,
-{ 72: } 60,
-{ 73: } 61,
-{ 74: } 62,
-{ 75: } 63,
-{ 76: } 63,
-{ 77: } 63,
-{ 78: } 63,
-{ 79: } 63,
-{ 80: } 63,
-{ 81: } 63,
-{ 82: } 63,
-{ 83: } 63,
-{ 84: } 63,
-{ 85: } 63,
-{ 86: } 63,
-{ 87: } 63,
-{ 88: } 63,
-{ 89: } 63,
-{ 90: } 63,
-{ 91: } 63,
-{ 92: } 63,
-{ 93: } 63
+{ 1: } 2,
+{ 2: } 3,
+{ 3: } 3,
+{ 4: } 3,
+{ 5: } 3,
+{ 6: } 3,
+{ 7: } 3,
+{ 8: } 3,
+{ 9: } 3,
+{ 10: } 3,
+{ 11: } 5,
+{ 12: } 8,
+{ 13: } 11,
+{ 14: } 14,
+{ 15: } 16,
+{ 16: } 19,
+{ 17: } 21,
+{ 18: } 24,
+{ 19: } 26,
+{ 20: } 29,
+{ 21: } 31,
+{ 22: } 32,
+{ 23: } 34,
+{ 24: } 36,
+{ 25: } 37,
+{ 26: } 38,
+{ 27: } 39,
+{ 28: } 40,
+{ 29: } 41,
+{ 30: } 42,
+{ 31: } 44,
+{ 32: } 45,
+{ 33: } 46,
+{ 34: } 47,
+{ 35: } 49,
+{ 36: } 50,
+{ 37: } 51,
+{ 38: } 53,
+{ 39: } 55,
+{ 40: } 56,
+{ 41: } 57,
+{ 42: } 58,
+{ 43: } 59,
+{ 44: } 61,
+{ 45: } 61,
+{ 46: } 61,
+{ 47: } 61,
+{ 48: } 63,
+{ 49: } 65,
+{ 50: } 66,
+{ 51: } 67,
+{ 52: } 68,
+{ 53: } 70,
+{ 54: } 72,
+{ 55: } 72,
+{ 56: } 72,
+{ 57: } 72,
+{ 58: } 74,
+{ 59: } 77,
+{ 60: } 79,
+{ 61: } 81,
+{ 62: } 81,
+{ 63: } 81,
+{ 64: } 81,
+{ 65: } 83,
+{ 66: } 83,
+{ 67: } 83,
+{ 68: } 83,
+{ 69: } 86,
+{ 70: } 86,
+{ 71: } 86,
+{ 72: } 86,
+{ 73: } 86,
+{ 74: } 86,
+{ 75: } 86,
+{ 76: } 86,
+{ 77: } 86,
+{ 78: } 86,
+{ 79: } 86,
+{ 80: } 86,
+{ 81: } 86,
+{ 82: } 86,
+{ 83: } 86,
+{ 84: } 86,
+{ 85: } 86,
+{ 86: } 86,
+{ 87: } 86,
+{ 88: } 86,
+{ 89: } 86,
+{ 90: } 86,
+{ 91: } 86,
+{ 92: } 87,
+{ 93: } 88,
+{ 94: } 88,
+{ 95: } 88
 );
 );
 
 
 yykh : array [0..yynstates-1] of Integer = (
 yykh : array [0..yynstates-1] of Integer = (
-{ 0: } 0,
-{ 1: } 0,
-{ 2: } 0,
-{ 3: } 0,
-{ 4: } 0,
-{ 5: } 0,
-{ 6: } 0,
-{ 7: } 0,
-{ 8: } 0,
-{ 9: } 0,
-{ 10: } 2,
-{ 11: } 4,
-{ 12: } 6,
-{ 13: } 8,
-{ 14: } 10,
-{ 15: } 12,
-{ 16: } 14,
-{ 17: } 16,
-{ 18: } 18,
-{ 19: } 20,
-{ 20: } 21,
-{ 21: } 23,
-{ 22: } 25,
-{ 23: } 26,
-{ 24: } 27,
-{ 25: } 28,
-{ 26: } 29,
-{ 27: } 30,
-{ 28: } 31,
-{ 29: } 33,
-{ 30: } 34,
-{ 31: } 35,
-{ 32: } 36,
-{ 33: } 38,
-{ 34: } 39,
-{ 35: } 40,
-{ 36: } 41,
-{ 37: } 42,
-{ 38: } 42,
-{ 39: } 42,
-{ 40: } 43,
-{ 41: } 44,
-{ 42: } 44,
-{ 43: } 44,
-{ 44: } 44,
-{ 45: } 45,
-{ 46: } 46,
-{ 47: } 47,
-{ 48: } 48,
-{ 49: } 49,
-{ 50: } 50,
-{ 51: } 51,
-{ 52: } 51,
-{ 53: } 52,
-{ 54: } 54,
-{ 55: } 55,
-{ 56: } 56,
-{ 57: } 56,
-{ 58: } 56,
-{ 59: } 56,
-{ 60: } 57,
-{ 61: } 57,
-{ 62: } 59,
-{ 63: } 59,
-{ 64: } 59,
-{ 65: } 59,
-{ 66: } 59,
-{ 67: } 59,
-{ 68: } 59,
-{ 69: } 59,
-{ 70: } 59,
-{ 71: } 59,
-{ 72: } 60,
-{ 73: } 61,
-{ 74: } 62,
-{ 75: } 62,
-{ 76: } 62,
-{ 77: } 62,
-{ 78: } 62,
-{ 79: } 62,
-{ 80: } 62,
-{ 81: } 62,
-{ 82: } 62,
-{ 83: } 62,
-{ 84: } 62,
-{ 85: } 62,
-{ 86: } 62,
-{ 87: } 62,
-{ 88: } 62,
-{ 89: } 62,
-{ 90: } 62,
-{ 91: } 62,
-{ 92: } 62,
-{ 93: } 62
+{ 0: } 1,
+{ 1: } 2,
+{ 2: } 2,
+{ 3: } 2,
+{ 4: } 2,
+{ 5: } 2,
+{ 6: } 2,
+{ 7: } 2,
+{ 8: } 2,
+{ 9: } 2,
+{ 10: } 4,
+{ 11: } 7,
+{ 12: } 10,
+{ 13: } 13,
+{ 14: } 15,
+{ 15: } 18,
+{ 16: } 20,
+{ 17: } 23,
+{ 18: } 25,
+{ 19: } 28,
+{ 20: } 30,
+{ 21: } 31,
+{ 22: } 33,
+{ 23: } 35,
+{ 24: } 36,
+{ 25: } 37,
+{ 26: } 38,
+{ 27: } 39,
+{ 28: } 40,
+{ 29: } 41,
+{ 30: } 43,
+{ 31: } 44,
+{ 32: } 45,
+{ 33: } 46,
+{ 34: } 48,
+{ 35: } 49,
+{ 36: } 50,
+{ 37: } 52,
+{ 38: } 54,
+{ 39: } 55,
+{ 40: } 56,
+{ 41: } 57,
+{ 42: } 58,
+{ 43: } 60,
+{ 44: } 60,
+{ 45: } 60,
+{ 46: } 60,
+{ 47: } 62,
+{ 48: } 64,
+{ 49: } 65,
+{ 50: } 66,
+{ 51: } 67,
+{ 52: } 69,
+{ 53: } 71,
+{ 54: } 71,
+{ 55: } 71,
+{ 56: } 71,
+{ 57: } 73,
+{ 58: } 76,
+{ 59: } 78,
+{ 60: } 80,
+{ 61: } 80,
+{ 62: } 80,
+{ 63: } 80,
+{ 64: } 82,
+{ 65: } 82,
+{ 66: } 82,
+{ 67: } 82,
+{ 68: } 85,
+{ 69: } 85,
+{ 70: } 85,
+{ 71: } 85,
+{ 72: } 85,
+{ 73: } 85,
+{ 74: } 85,
+{ 75: } 85,
+{ 76: } 85,
+{ 77: } 85,
+{ 78: } 85,
+{ 79: } 85,
+{ 80: } 85,
+{ 81: } 85,
+{ 82: } 85,
+{ 83: } 85,
+{ 84: } 85,
+{ 85: } 85,
+{ 86: } 85,
+{ 87: } 85,
+{ 88: } 85,
+{ 89: } 85,
+{ 90: } 85,
+{ 91: } 86,
+{ 92: } 87,
+{ 93: } 87,
+{ 94: } 87,
+{ 95: } 88
 );
 );
 
 
 yyml : array [0..yynstates-1] of Integer = (
 yyml : array [0..yynstates-1] of Integer = (
 { 0: } 1,
 { 0: } 1,
-{ 1: } 1,
-{ 2: } 1,
-{ 3: } 1,
-{ 4: } 1,
-{ 5: } 1,
-{ 6: } 1,
-{ 7: } 1,
-{ 8: } 1,
-{ 9: } 1,
-{ 10: } 1,
-{ 11: } 3,
-{ 12: } 5,
-{ 13: } 7,
-{ 14: } 9,
-{ 15: } 11,
-{ 16: } 13,
-{ 17: } 15,
-{ 18: } 17,
-{ 19: } 19,
-{ 20: } 21,
-{ 21: } 22,
-{ 22: } 24,
-{ 23: } 26,
-{ 24: } 27,
-{ 25: } 28,
-{ 26: } 29,
-{ 27: } 30,
-{ 28: } 31,
-{ 29: } 32,
-{ 30: } 34,
-{ 31: } 35,
-{ 32: } 36,
-{ 33: } 37,
-{ 34: } 39,
-{ 35: } 40,
-{ 36: } 41,
-{ 37: } 42,
-{ 38: } 43,
-{ 39: } 43,
-{ 40: } 43,
-{ 41: } 44,
-{ 42: } 45,
-{ 43: } 45,
-{ 44: } 45,
-{ 45: } 45,
-{ 46: } 46,
-{ 47: } 47,
-{ 48: } 48,
-{ 49: } 49,
-{ 50: } 50,
-{ 51: } 51,
-{ 52: } 52,
-{ 53: } 52,
-{ 54: } 53,
-{ 55: } 55,
-{ 56: } 56,
-{ 57: } 57,
-{ 58: } 57,
-{ 59: } 57,
-{ 60: } 57,
-{ 61: } 58,
-{ 62: } 58,
-{ 63: } 60,
-{ 64: } 60,
-{ 65: } 60,
-{ 66: } 60,
-{ 67: } 60,
-{ 68: } 60,
-{ 69: } 60,
-{ 70: } 60,
-{ 71: } 60,
-{ 72: } 60,
-{ 73: } 61,
-{ 74: } 62,
-{ 75: } 63,
-{ 76: } 63,
-{ 77: } 63,
-{ 78: } 63,
-{ 79: } 63,
-{ 80: } 63,
-{ 81: } 63,
-{ 82: } 63,
-{ 83: } 63,
-{ 84: } 63,
-{ 85: } 63,
-{ 86: } 63,
-{ 87: } 63,
-{ 88: } 63,
-{ 89: } 63,
-{ 90: } 63,
-{ 91: } 63,
-{ 92: } 63,
-{ 93: } 63
+{ 1: } 2,
+{ 2: } 3,
+{ 3: } 3,
+{ 4: } 3,
+{ 5: } 3,
+{ 6: } 3,
+{ 7: } 3,
+{ 8: } 3,
+{ 9: } 3,
+{ 10: } 3,
+{ 11: } 5,
+{ 12: } 8,
+{ 13: } 11,
+{ 14: } 14,
+{ 15: } 16,
+{ 16: } 19,
+{ 17: } 21,
+{ 18: } 24,
+{ 19: } 26,
+{ 20: } 29,
+{ 21: } 31,
+{ 22: } 32,
+{ 23: } 34,
+{ 24: } 36,
+{ 25: } 37,
+{ 26: } 38,
+{ 27: } 39,
+{ 28: } 40,
+{ 29: } 41,
+{ 30: } 42,
+{ 31: } 44,
+{ 32: } 45,
+{ 33: } 46,
+{ 34: } 47,
+{ 35: } 49,
+{ 36: } 50,
+{ 37: } 51,
+{ 38: } 53,
+{ 39: } 55,
+{ 40: } 56,
+{ 41: } 57,
+{ 42: } 58,
+{ 43: } 59,
+{ 44: } 61,
+{ 45: } 61,
+{ 46: } 61,
+{ 47: } 61,
+{ 48: } 63,
+{ 49: } 65,
+{ 50: } 66,
+{ 51: } 67,
+{ 52: } 68,
+{ 53: } 70,
+{ 54: } 72,
+{ 55: } 72,
+{ 56: } 72,
+{ 57: } 72,
+{ 58: } 74,
+{ 59: } 77,
+{ 60: } 79,
+{ 61: } 81,
+{ 62: } 81,
+{ 63: } 81,
+{ 64: } 81,
+{ 65: } 83,
+{ 66: } 83,
+{ 67: } 83,
+{ 68: } 83,
+{ 69: } 86,
+{ 70: } 86,
+{ 71: } 86,
+{ 72: } 86,
+{ 73: } 86,
+{ 74: } 86,
+{ 75: } 86,
+{ 76: } 86,
+{ 77: } 86,
+{ 78: } 86,
+{ 79: } 86,
+{ 80: } 86,
+{ 81: } 86,
+{ 82: } 86,
+{ 83: } 86,
+{ 84: } 86,
+{ 85: } 86,
+{ 86: } 86,
+{ 87: } 86,
+{ 88: } 86,
+{ 89: } 86,
+{ 90: } 86,
+{ 91: } 86,
+{ 92: } 87,
+{ 93: } 88,
+{ 94: } 88,
+{ 95: } 88
 );
 );
 
 
 yymh : array [0..yynstates-1] of Integer = (
 yymh : array [0..yynstates-1] of Integer = (
-{ 0: } 0,
-{ 1: } 0,
-{ 2: } 0,
-{ 3: } 0,
-{ 4: } 0,
-{ 5: } 0,
-{ 6: } 0,
-{ 7: } 0,
-{ 8: } 0,
-{ 9: } 0,
-{ 10: } 2,
-{ 11: } 4,
-{ 12: } 6,
-{ 13: } 8,
-{ 14: } 10,
-{ 15: } 12,
-{ 16: } 14,
-{ 17: } 16,
-{ 18: } 18,
-{ 19: } 20,
-{ 20: } 21,
-{ 21: } 23,
-{ 22: } 25,
-{ 23: } 26,
-{ 24: } 27,
-{ 25: } 28,
-{ 26: } 29,
-{ 27: } 30,
-{ 28: } 31,
-{ 29: } 33,
-{ 30: } 34,
-{ 31: } 35,
-{ 32: } 36,
-{ 33: } 38,
-{ 34: } 39,
-{ 35: } 40,
-{ 36: } 41,
-{ 37: } 42,
-{ 38: } 42,
-{ 39: } 42,
-{ 40: } 43,
-{ 41: } 44,
-{ 42: } 44,
-{ 43: } 44,
-{ 44: } 44,
-{ 45: } 45,
-{ 46: } 46,
-{ 47: } 47,
-{ 48: } 48,
-{ 49: } 49,
-{ 50: } 50,
-{ 51: } 51,
-{ 52: } 51,
-{ 53: } 52,
-{ 54: } 54,
-{ 55: } 55,
-{ 56: } 56,
-{ 57: } 56,
-{ 58: } 56,
-{ 59: } 56,
-{ 60: } 57,
-{ 61: } 57,
-{ 62: } 59,
-{ 63: } 59,
-{ 64: } 59,
-{ 65: } 59,
-{ 66: } 59,
-{ 67: } 59,
-{ 68: } 59,
-{ 69: } 59,
-{ 70: } 59,
-{ 71: } 59,
-{ 72: } 60,
-{ 73: } 61,
-{ 74: } 62,
-{ 75: } 62,
-{ 76: } 62,
-{ 77: } 62,
-{ 78: } 62,
-{ 79: } 62,
-{ 80: } 62,
-{ 81: } 62,
-{ 82: } 62,
-{ 83: } 62,
-{ 84: } 62,
-{ 85: } 62,
-{ 86: } 62,
-{ 87: } 62,
-{ 88: } 62,
-{ 89: } 62,
-{ 90: } 62,
-{ 91: } 62,
-{ 92: } 62,
-{ 93: } 62
+{ 0: } 1,
+{ 1: } 2,
+{ 2: } 2,
+{ 3: } 2,
+{ 4: } 2,
+{ 5: } 2,
+{ 6: } 2,
+{ 7: } 2,
+{ 8: } 2,
+{ 9: } 2,
+{ 10: } 4,
+{ 11: } 7,
+{ 12: } 10,
+{ 13: } 13,
+{ 14: } 15,
+{ 15: } 18,
+{ 16: } 20,
+{ 17: } 23,
+{ 18: } 25,
+{ 19: } 28,
+{ 20: } 30,
+{ 21: } 31,
+{ 22: } 33,
+{ 23: } 35,
+{ 24: } 36,
+{ 25: } 37,
+{ 26: } 38,
+{ 27: } 39,
+{ 28: } 40,
+{ 29: } 41,
+{ 30: } 43,
+{ 31: } 44,
+{ 32: } 45,
+{ 33: } 46,
+{ 34: } 48,
+{ 35: } 49,
+{ 36: } 50,
+{ 37: } 52,
+{ 38: } 54,
+{ 39: } 55,
+{ 40: } 56,
+{ 41: } 57,
+{ 42: } 58,
+{ 43: } 60,
+{ 44: } 60,
+{ 45: } 60,
+{ 46: } 60,
+{ 47: } 62,
+{ 48: } 64,
+{ 49: } 65,
+{ 50: } 66,
+{ 51: } 67,
+{ 52: } 69,
+{ 53: } 71,
+{ 54: } 71,
+{ 55: } 71,
+{ 56: } 71,
+{ 57: } 73,
+{ 58: } 76,
+{ 59: } 78,
+{ 60: } 80,
+{ 61: } 80,
+{ 62: } 80,
+{ 63: } 80,
+{ 64: } 82,
+{ 65: } 82,
+{ 66: } 82,
+{ 67: } 82,
+{ 68: } 85,
+{ 69: } 85,
+{ 70: } 85,
+{ 71: } 85,
+{ 72: } 85,
+{ 73: } 85,
+{ 74: } 85,
+{ 75: } 85,
+{ 76: } 85,
+{ 77: } 85,
+{ 78: } 85,
+{ 79: } 85,
+{ 80: } 85,
+{ 81: } 85,
+{ 82: } 85,
+{ 83: } 85,
+{ 84: } 85,
+{ 85: } 85,
+{ 86: } 85,
+{ 87: } 85,
+{ 88: } 85,
+{ 89: } 85,
+{ 90: } 85,
+{ 91: } 86,
+{ 92: } 87,
+{ 93: } 87,
+{ 94: } 87,
+{ 95: } 88
 );
 );
 
 
 yytl : array [0..yynstates-1] of Integer = (
 yytl : array [0..yynstates-1] of Integer = (
 { 0: } 1,
 { 0: } 1,
-{ 1: } 15,
-{ 2: } 29,
-{ 3: } 31,
-{ 4: } 33,
-{ 5: } 36,
-{ 6: } 39,
-{ 7: } 43,
-{ 8: } 47,
-{ 9: } 51,
-{ 10: } 55,
-{ 11: } 57,
-{ 12: } 59,
-{ 13: } 63,
-{ 14: } 65,
-{ 15: } 68,
-{ 16: } 70,
-{ 17: } 70,
-{ 18: } 72,
-{ 19: } 72,
-{ 20: } 73,
-{ 21: } 73,
-{ 22: } 73,
-{ 23: } 73,
-{ 24: } 73,
-{ 25: } 73,
-{ 26: } 73,
-{ 27: } 73,
-{ 28: } 74,
-{ 29: } 74,
-{ 30: } 75,
-{ 31: } 76,
-{ 32: } 76,
-{ 33: } 76,
-{ 34: } 77,
-{ 35: } 77,
-{ 36: } 77,
-{ 37: } 79,
-{ 38: } 79,
-{ 39: } 80,
-{ 40: } 81,
-{ 41: } 81,
-{ 42: } 82,
-{ 43: } 83,
-{ 44: } 84,
-{ 45: } 85,
-{ 46: } 87,
-{ 47: } 89,
-{ 48: } 89,
-{ 49: } 89,
-{ 50: } 89,
-{ 51: } 91,
-{ 52: } 93,
-{ 53: } 94,
-{ 54: } 96,
-{ 55: } 97,
-{ 56: } 97,
-{ 57: } 97,
-{ 58: } 98,
-{ 59: } 99,
-{ 60: } 100,
-{ 61: } 102,
-{ 62: } 103,
-{ 63: } 104,
-{ 64: } 105,
-{ 65: } 106,
-{ 66: } 107,
-{ 67: } 108,
-{ 68: } 109,
-{ 69: } 110,
-{ 70: } 111,
-{ 71: } 112,
-{ 72: } 113,
-{ 73: } 113,
-{ 74: } 113,
-{ 75: } 113,
-{ 76: } 114,
-{ 77: } 115,
-{ 78: } 116,
-{ 79: } 117,
-{ 80: } 118,
-{ 81: } 119,
-{ 82: } 120,
-{ 83: } 121,
-{ 84: } 122,
-{ 85: } 123,
-{ 86: } 124,
-{ 87: } 125,
-{ 88: } 126,
-{ 89: } 127,
-{ 90: } 128,
-{ 91: } 129,
-{ 92: } 130,
-{ 93: } 131
-);
-
-yyth : array [0..yynstates-1] of Integer = (
-{ 0: } 14,
-{ 1: } 28,
-{ 2: } 30,
-{ 3: } 32,
+{ 1: } 16,
+{ 2: } 31,
+{ 3: } 33,
 { 4: } 35,
 { 4: } 35,
 { 5: } 38,
 { 5: } 38,
-{ 6: } 42,
-{ 7: } 46,
-{ 8: } 50,
-{ 9: } 54,
-{ 10: } 56,
-{ 11: } 58,
+{ 6: } 41,
+{ 7: } 45,
+{ 8: } 49,
+{ 9: } 53,
+{ 10: } 57,
+{ 11: } 59,
 { 12: } 62,
 { 12: } 62,
-{ 13: } 64,
-{ 14: } 67,
-{ 15: } 69,
-{ 16: } 69,
-{ 17: } 71,
-{ 18: } 71,
-{ 19: } 72,
-{ 20: } 72,
-{ 21: } 72,
-{ 22: } 72,
-{ 23: } 72,
-{ 24: } 72,
-{ 25: } 72,
-{ 26: } 72,
-{ 27: } 73,
-{ 28: } 73,
-{ 29: } 74,
-{ 30: } 75,
-{ 31: } 75,
-{ 32: } 75,
-{ 33: } 76,
-{ 34: } 76,
-{ 35: } 76,
-{ 36: } 78,
-{ 37: } 78,
-{ 38: } 79,
-{ 39: } 80,
-{ 40: } 80,
-{ 41: } 81,
-{ 42: } 82,
-{ 43: } 83,
-{ 44: } 84,
-{ 45: } 86,
-{ 46: } 88,
-{ 47: } 88,
-{ 48: } 88,
-{ 49: } 88,
-{ 50: } 90,
-{ 51: } 92,
-{ 52: } 93,
-{ 53: } 95,
-{ 54: } 96,
-{ 55: } 96,
-{ 56: } 96,
-{ 57: } 97,
-{ 58: } 98,
-{ 59: } 99,
-{ 60: } 101,
-{ 61: } 102,
-{ 62: } 103,
-{ 63: } 104,
-{ 64: } 105,
-{ 65: } 106,
-{ 66: } 107,
-{ 67: } 108,
-{ 68: } 109,
-{ 69: } 110,
-{ 70: } 111,
-{ 71: } 112,
-{ 72: } 112,
-{ 73: } 112,
-{ 74: } 112,
-{ 75: } 113,
-{ 76: } 114,
-{ 77: } 115,
-{ 78: } 116,
-{ 79: } 117,
-{ 80: } 118,
-{ 81: } 119,
-{ 82: } 120,
-{ 83: } 121,
-{ 84: } 122,
-{ 85: } 123,
-{ 86: } 124,
-{ 87: } 125,
-{ 88: } 126,
-{ 89: } 127,
-{ 90: } 128,
-{ 91: } 129,
-{ 92: } 130,
-{ 93: } 131
+{ 13: } 67,
+{ 14: } 70,
+{ 15: } 73,
+{ 16: } 76,
+{ 17: } 76,
+{ 18: } 79,
+{ 19: } 79,
+{ 20: } 81,
+{ 21: } 82,
+{ 22: } 82,
+{ 23: } 82,
+{ 24: } 82,
+{ 25: } 82,
+{ 26: } 82,
+{ 27: } 82,
+{ 28: } 82,
+{ 29: } 83,
+{ 30: } 83,
+{ 31: } 84,
+{ 32: } 85,
+{ 33: } 85,
+{ 34: } 85,
+{ 35: } 86,
+{ 36: } 86,
+{ 37: } 86,
+{ 38: } 89,
+{ 39: } 90,
+{ 40: } 91,
+{ 41: } 93,
+{ 42: } 95,
+{ 43: } 95,
+{ 44: } 97,
+{ 45: } 98,
+{ 46: } 99,
+{ 47: } 100,
+{ 48: } 103,
+{ 49: } 106,
+{ 50: } 106,
+{ 51: } 106,
+{ 52: } 106,
+{ 53: } 109,
+{ 54: } 112,
+{ 55: } 113,
+{ 56: } 114,
+{ 57: } 115,
+{ 58: } 118,
+{ 59: } 120,
+{ 60: } 121,
+{ 61: } 122,
+{ 62: } 123,
+{ 63: } 124,
+{ 64: } 125,
+{ 65: } 128,
+{ 66: } 129,
+{ 67: } 130,
+{ 68: } 131,
+{ 69: } 133,
+{ 70: } 134,
+{ 71: } 135,
+{ 72: } 136,
+{ 73: } 137,
+{ 74: } 138,
+{ 75: } 139,
+{ 76: } 140,
+{ 77: } 141,
+{ 78: } 142,
+{ 79: } 143,
+{ 80: } 144,
+{ 81: } 145,
+{ 82: } 146,
+{ 83: } 147,
+{ 84: } 148,
+{ 85: } 149,
+{ 86: } 150,
+{ 87: } 151,
+{ 88: } 152,
+{ 89: } 153,
+{ 90: } 154,
+{ 91: } 155,
+{ 92: } 155,
+{ 93: } 155,
+{ 94: } 156,
+{ 95: } 157
+);
+
+yyth : array [0..yynstates-1] of Integer = (
+{ 0: } 15,
+{ 1: } 30,
+{ 2: } 32,
+{ 3: } 34,
+{ 4: } 37,
+{ 5: } 40,
+{ 6: } 44,
+{ 7: } 48,
+{ 8: } 52,
+{ 9: } 56,
+{ 10: } 58,
+{ 11: } 61,
+{ 12: } 66,
+{ 13: } 69,
+{ 14: } 72,
+{ 15: } 75,
+{ 16: } 75,
+{ 17: } 78,
+{ 18: } 78,
+{ 19: } 80,
+{ 20: } 81,
+{ 21: } 81,
+{ 22: } 81,
+{ 23: } 81,
+{ 24: } 81,
+{ 25: } 81,
+{ 26: } 81,
+{ 27: } 81,
+{ 28: } 82,
+{ 29: } 82,
+{ 30: } 83,
+{ 31: } 84,
+{ 32: } 84,
+{ 33: } 84,
+{ 34: } 85,
+{ 35: } 85,
+{ 36: } 85,
+{ 37: } 88,
+{ 38: } 89,
+{ 39: } 90,
+{ 40: } 92,
+{ 41: } 94,
+{ 42: } 94,
+{ 43: } 96,
+{ 44: } 97,
+{ 45: } 98,
+{ 46: } 99,
+{ 47: } 102,
+{ 48: } 105,
+{ 49: } 105,
+{ 50: } 105,
+{ 51: } 105,
+{ 52: } 108,
+{ 53: } 111,
+{ 54: } 112,
+{ 55: } 113,
+{ 56: } 114,
+{ 57: } 117,
+{ 58: } 119,
+{ 59: } 120,
+{ 60: } 121,
+{ 61: } 122,
+{ 62: } 123,
+{ 63: } 124,
+{ 64: } 127,
+{ 65: } 128,
+{ 66: } 129,
+{ 67: } 130,
+{ 68: } 132,
+{ 69: } 133,
+{ 70: } 134,
+{ 71: } 135,
+{ 72: } 136,
+{ 73: } 137,
+{ 74: } 138,
+{ 75: } 139,
+{ 76: } 140,
+{ 77: } 141,
+{ 78: } 142,
+{ 79: } 143,
+{ 80: } 144,
+{ 81: } 145,
+{ 82: } 146,
+{ 83: } 147,
+{ 84: } 148,
+{ 85: } 149,
+{ 86: } 150,
+{ 87: } 151,
+{ 88: } 152,
+{ 89: } 153,
+{ 90: } 154,
+{ 91: } 154,
+{ 92: } 154,
+{ 93: } 155,
+{ 94: } 156,
+{ 95: } 156
 );
 );
 
 
 
 

+ 2 - 0
packages/fcl-res/src/rclex.l

@@ -63,6 +63,7 @@ O [0-7]
 D [0-9]
 D [0-9]
 H [0-9a-fA-F]
 H [0-9a-fA-F]
 IDENT [a-zA-Z_]([a-zA-Z0-9_])*
 IDENT [a-zA-Z_]([a-zA-Z0-9_])*
+NSWPSTR ([a-zA-Z0-9_\:\.\\])*
 
 
 %%
 %%
 
 
@@ -108,6 +109,7 @@ END|}                   return(_END);
                             else
                             else
                               return(_ID);
                               return(_ID);
                          end;
                          end;
+{NSWPSTR}         return(_NSWPSTR);
 [ \t\n\f]               ;
 [ \t\n\f]               ;
 [,()|^&+-*/%~]          returnc(yytext[1]);
 [,()|^&+-*/%~]          returnc(yytext[1]);
 .                       return(_ILLEGAL);
 .                       return(_ILLEGAL);

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 396 - 345
packages/fcl-res/src/rcparser.pas


+ 16 - 3
packages/fcl-res/src/rcparser.y

@@ -12,7 +12,7 @@ unit rcparser;
 %token _ILLEGAL
 %token _ILLEGAL
 %token _NUMBER _QUOTEDSTR _QUOTEDSTRL
 %token _NUMBER _QUOTEDSTR _QUOTEDSTRL
 %token _STR_StringFileInfo _STR_VarFileInfo _STR_Translation
 %token _STR_StringFileInfo _STR_VarFileInfo _STR_Translation
-%token _BEGIN _END _ID
+%token _BEGIN _END _ID _NSWPSTR
 %token _LANGUAGE _CHARACTERISTICS _VERSION _MOVEABLE _FIXED _PURE _IMPURE _PRELOAD _LOADONCALL _DISCARDABLE
 %token _LANGUAGE _CHARACTERISTICS _VERSION _MOVEABLE _FIXED _PURE _IMPURE _PRELOAD _LOADONCALL _DISCARDABLE
 %token _BITMAP _CURSOR _ICON _STRINGTABLE _VERSIONINFO
 %token _BITMAP _CURSOR _ICON _STRINGTABLE _VERSIONINFO
 %token _ANICURSOR _ANIICON _DLGINCLUDE _DLGINIT _HTML _MANIFEST _MESSAGETABLE _PLUGPLAY _RCDATA _VXD
 %token _ANICURSOR _ANIICON _DLGINCLUDE _DLGINIT _HTML _MANIFEST _MESSAGETABLE _PLUGPLAY _RCDATA _VXD
@@ -20,7 +20,7 @@ unit rcparser;
 %token _ACCELERATORS _DIALOG _DIALOGEX _MENU _MENUEX
 %token _ACCELERATORS _DIALOG _DIALOGEX _MENU _MENUEX
 
 
 %type <rcnumtype> numpos numexpr numeral
 %type <rcnumtype> numpos numexpr numeral
-%type <rcstrtype> ident_string long_string
+%type <rcstrtype> ident_string long_string non_whitespace_string long_stringfn
 %type <TResourceDesc> resid rcdataid
 %type <TResourceDesc> resid rcdataid
 %type <TMemoryStream> raw_data raw_item
 %type <TMemoryStream> raw_data raw_item
 %type <TFileStream> filename_string
 %type <TFileStream> filename_string
@@ -188,8 +188,21 @@ ident_string
     | long_string
     | long_string
     ;
     ;
 
 
+non_whitespace_string
+    : _NSWPSTR                                     { string_new($$, yytext, opt_code_page); }
+    ;
+
 filename_string
 filename_string
-    : long_string                                  { $$:= TFileStream.Create($1.v^, fmOpenRead or fmShareDenyWrite); }
+    : long_stringfn                                { $$:= TFileStream.Create($1.v^, fmOpenRead or fmShareDenyWrite); }
+    | non_whitespace_string                        { $$:= TFileStream.Create($1.v^, fmOpenRead or fmShareDenyWrite); }
+    ;
+
+long_stringfn
+    : _QUOTEDSTR                                   { string_new_uni($$, @strbuf[0], strbuflen, opt_code_page, false); }
+    | _QUOTEDSTRL                                  { string_new_uni($$, @strbuf[0], strbuflen, CP_UTF16, false); }
+    | _STR_StringFileInfo                          { string_new($$, yytext, opt_code_page); }
+    | _STR_VarFileInfo                             { string_new($$, yytext, opt_code_page); }
+    | _STR_Translation                             { string_new($$, yytext, opt_code_page); }
     ;
     ;
 
 
 long_string
 long_string

+ 3 - 3
packages/hash/src/sha1.pp

@@ -15,10 +15,10 @@
 
 
 // Normally, if an optimized version is available for OS/CPU, that will be used
 // Normally, if an optimized version is available for OS/CPU, that will be used
 // Define to use existing unoptimized implementation
 // Define to use existing unoptimized implementation
-{ the assembler implementation does not work on darwin }
-{$ifdef darwin}
+{ the i386 assembler implementation does not work on platforms with a fixed stack }
+{$if DEFINED(CPU386) and (defined(darwin) or defined(linux))}
 {$DEFINE SHA1PASCAL}
 {$DEFINE SHA1PASCAL}
-{$endif darwin}
+{$endif}
 
 
 unit sha1;
 unit sha1;
 {$mode objfpc}{$h+}
 {$mode objfpc}{$h+}

+ 7 - 5
packages/pastojs/src/fppas2js.pp

@@ -6198,7 +6198,8 @@ begin
   cInterfaceToString:=cTypeConversion+1;
   cInterfaceToString:=cTypeConversion+1;
 
 
   {$IFDEF FPC_HAS_CPSTRING}
   {$IFDEF FPC_HAS_CPSTRING}
-  ExprEvaluator.DefaultStringCodePage:=CP_UTF8;
+  ExprEvaluator.DefaultSourceCodePage:=CP_UTF8;
+  ExprEvaluator.DefaultStringCodePage:=CP_UTF16;
   {$ENDIF}
   {$ENDIF}
   FExternalNames:=TPasResHashList.Create;
   FExternalNames:=TPasResHashList.Create;
   StoreSrcColumns:=true;
   StoreSrcColumns:=true;
@@ -6517,6 +6518,7 @@ function TPas2JSResolver.ExtractPasStringLiteral(El: TPasElement;
     #decimal
     #decimal
     #$hex
     #$hex
     ^l  l is a letter a-z
     ^l  l is a letter a-z
+    Note that invalid UTF-8 sequences are checked by the scanner
 }
 }
 var
 var
   p, StartP, i, l: integer;
   p, StartP, i, l: integer;
@@ -6544,7 +6546,7 @@ begin
         '''':
         '''':
           begin
           begin
           if p>StartP then
           if p>StartP then
-            Result:=Result+StrToJSString(copy(S,StartP,p-StartP));
+            Result:=Result+StrToJSString(copy(S,StartP,p-StartP)); // todo error on invalid UTF-8 sequence
           inc(p);
           inc(p);
           StartP:=p;
           StartP:=p;
           if (p>l) or (S[p]<>'''') then
           if (p>l) or (S[p]<>'''') then
@@ -6558,10 +6560,11 @@ begin
         end;
         end;
       until false;
       until false;
       if p>StartP then
       if p>StartP then
-        Result:=Result+StrToJSString(copy(S,StartP,p-StartP));
+        Result:=Result+StrToJSString(copy(S,StartP,p-StartP)); // todo error on invalid UTF-8 sequence
       end;
       end;
     '#':
     '#':
       begin
       begin
+      // word sequence
       inc(p);
       inc(p);
       if p>l then
       if p>l then
         RaiseInternalError(20170207155121);
         RaiseInternalError(20170207155121);
@@ -6586,7 +6589,6 @@ begin
           end;
           end;
         if p=StartP then
         if p=StartP then
           RaiseInternalError(20170207164956);
           RaiseInternalError(20170207164956);
-        Result:=Result+CodePointToJSString(i);
         end
         end
       else
       else
         begin
         begin
@@ -6606,8 +6608,8 @@ begin
           end;
           end;
         if p=StartP then
         if p=StartP then
           RaiseInternalError(20170207171148);
           RaiseInternalError(20170207171148);
-        Result:=Result+CodePointToJSString(i);
         end;
         end;
+      Result:=Result+CodePointToJSString(i);
       end;
       end;
     '^':
     '^':
       begin
       begin

+ 7 - 1
packages/pastojs/src/pas2jsfilecache.pp

@@ -1697,6 +1697,7 @@ var
   {$IFDEF FPC}
   {$IFDEF FPC}
   i: Integer;
   i: Integer;
   l: TMaxPrecInt;
   l: TMaxPrecInt;
+  FS: TFileStream;
   {$ENDIF}
   {$ENDIF}
 begin
 begin
   if Assigned(OnWriteFile) then
   if Assigned(OnWriteFile) then
@@ -1726,7 +1727,12 @@ begin
     end;
     end;
     {$ELSE}
     {$ELSE}
     try
     try
-      ms.SaveToFile(Filename);
+      FS:=TFileStream.Create (FileName,fmCreate or fmShareDenyNone);
+      Try
+        ms.SaveToStream(FS);
+      finally
+        FS.free;
+      end;
     except
     except
       on E: Exception do begin
       on E: Exception do begin
         i:=GetLastOSError;
         i:=GetLastOSError;

+ 126 - 1
packages/pastojs/tests/tcmodules.pas

@@ -282,6 +282,7 @@ type
     Procedure TestChar_Compare;
     Procedure TestChar_Compare;
     Procedure TestChar_BuiltInProcs;
     Procedure TestChar_BuiltInProcs;
     Procedure TestStringConst;
     Procedure TestStringConst;
+    Procedure TestStringConst_InvalidUTF16;
     Procedure TestStringConstSurrogate;
     Procedure TestStringConstSurrogate;
     Procedure TestString_Length;
     Procedure TestString_Length;
     Procedure TestString_Compare;
     Procedure TestString_Compare;
@@ -889,6 +890,7 @@ type
     Procedure TestAsync_ProcTypeAsyncModMismatchFail;
     Procedure TestAsync_ProcTypeAsyncModMismatchFail;
     Procedure TestAsync_Inherited;
     Procedure TestAsync_Inherited;
     Procedure TestAsync_ClassInterface;
     Procedure TestAsync_ClassInterface;
+    Procedure TestAsync_ClassInterface_AsyncMissmatchFail;
   end;
   end;
 
 
 function LinesToStr(Args: array of const): string;
 function LinesToStr(Args: array of const): string;
@@ -983,6 +985,28 @@ var
     end;
     end;
   end;
   end;
 
 
+  function HasSpecialChar(s: string): boolean;
+  var
+    i: Integer;
+  begin
+    for i:=1 to length(s) do
+      if s[i] in [#0..#31,#127..#255] then
+        exit(true);
+    Result:=false;
+  end;
+
+  function HashSpecialChars(s: string): string;
+  var
+    i: Integer;
+  begin
+    Result:='';
+    for i:=1 to length(s) do
+      if s[i] in [#0..#31,#127..#255] then
+        Result:=Result+'#'+hexstr(ord(s[i]),2)
+      else
+        Result:=Result+s[i];
+  end;
+
   procedure DiffFound;
   procedure DiffFound;
   var
   var
     ActLineStartP, ActLineEndP, p, StartPos: PChar;
     ActLineStartP, ActLineEndP, p, StartPos: PChar;
@@ -1011,8 +1035,12 @@ var
         ActLineEndP:=FindLineEnd(ActualP);
         ActLineEndP:=FindLineEnd(ActualP);
         ActLine:=copy(Actual,ActLineStartP-PChar(Actual)+1,ActLineEndP-ActLineStartP);
         ActLine:=copy(Actual,ActLineStartP-PChar(Actual)+1,ActLineEndP-ActLineStartP);
         writeln('- ',ActLine);
         writeln('- ',ActLine);
+        if HasSpecialChar(ActLine) then
+          writeln('- ',HashSpecialChars(ActLine));
         // write expected line
         // write expected line
         writeln('+ ',ExpLine);
         writeln('+ ',ExpLine);
+        if HasSpecialChar(ExpLine) then
+          writeln('- ',HashSpecialChars(ExpLine));
         // write empty line with pointer ^
         // write empty line with pointer ^
         for i:=1 to 2+ExpectedP-StartPos do write(' ');
         for i:=1 to 2+ExpectedP-StartPos do write(' ');
         writeln('^');
         writeln('^');
@@ -7467,6 +7495,7 @@ begin
   '  c:=#$DFFF;', // invalid UTF-16
   '  c:=#$DFFF;', // invalid UTF-16
   '  c:=#$FFFF;', // last UCS-2
   '  c:=#$FFFF;', // last UCS-2
   '  c:=high(c);', // last UCS-2
   '  c:=high(c);', // last UCS-2
+  '  c:=#269;',
   '']);
   '']);
   ConvertProgram;
   ConvertProgram;
   CheckSource('TestCharConst',
   CheckSource('TestCharConst',
@@ -7497,6 +7526,7 @@ begin
     '$mod.c="\uDFFF";',
     '$mod.c="\uDFFF";',
     '$mod.c="\uFFFF";',
     '$mod.c="\uFFFF";',
     '$mod.c="\uFFFF";',
     '$mod.c="\uFFFF";',
+    '$mod.c = "č";',
     '']));
     '']));
 end;
 end;
 
 
@@ -7607,9 +7637,16 @@ begin
   '  s:=''"''''"'';',
   '  s:=''"''''"'';',
   '  s:=#$20AC;', // euro
   '  s:=#$20AC;', // euro
   '  s:=#$10437;', // outside BMP
   '  s:=#$10437;', // outside BMP
+  '  s:=''abc''#$20AC;', // ascii,#
+  '  s:=''ä''#$20AC;', // non ascii,#
+  '  s:=#$20AC''abc'';', // #, ascii
+  '  s:=#$20AC''ä'';', // #, non ascii
   '  s:=default(string);',
   '  s:=default(string);',
   '  s:=concat(s);',
   '  s:=concat(s);',
-  '  s:=concat(s,''a'',s)',
+  '  s:=concat(s,''a'',s);',
+  '  s:=#250#269;',
+  //'  s:=#$2F804;',
+  // ToDo: \uD87E\uDC04 -> \u{2F804}
   '']);
   '']);
   ConvertProgram;
   ConvertProgram;
   CheckSource('TestStringConst',
   CheckSource('TestStringConst',
@@ -7631,9 +7668,47 @@ begin
     '$mod.s=''"\''"'';',
     '$mod.s=''"\''"'';',
     '$mod.s="€";',
     '$mod.s="€";',
     '$mod.s="'#$F0#$90#$90#$B7'";',
     '$mod.s="'#$F0#$90#$90#$B7'";',
+    '$mod.s = "abc€";',
+    '$mod.s = "ä€";',
+    '$mod.s = "€abc";',
+    '$mod.s = "ۊ";',
     '$mod.s="";',
     '$mod.s="";',
     '$mod.s = $mod.s;',
     '$mod.s = $mod.s;',
     '$mod.s = $mod.s.concat("a", $mod.s);',
     '$mod.s = $mod.s.concat("a", $mod.s);',
+    '$mod.s = "úč";',
+    '']));
+end;
+
+procedure TTestModule.TestStringConst_InvalidUTF16;
+begin
+  StartProgram(false);
+  Add([
+  'const',
+  '  a: char = #$D87E;',
+  '  b: string = #$D87E;',
+  '  c: string = #$D87E#43;',
+  'begin',
+  '  c:=''abc''#$D87E;',
+  '  c:=#0#1#2;',
+  '  c:=#127;',
+  '  c:=#128;',
+  '  c:=#255;',
+  '  c:=#256;',
+  '']);
+  ConvertProgram;
+  CheckSource('TestStringConst',
+    LinesToStr([
+    'this.a = "\uD87E";',
+    'this.b = "\uD87E";',
+    'this.c = "\uD87E+";',
+    '']),
+    LinesToStr([
+    '$mod.c = "abc\uD87E";',
+    '$mod.c = "\x00\x01\x02";',
+    '$mod.c = "'#127'";',
+    '$mod.c = "'#$c2#$80'";',
+    '$mod.c = "'#$c3#$BF'";',
+    '$mod.c = "'#$c4#$80'";',
     '']));
     '']));
 end;
 end;
 
 
@@ -32868,8 +32943,18 @@ begin
   '    function _AddRef: longint;',
   '    function _AddRef: longint;',
   '    function _Release: longint;',
   '    function _Release: longint;',
   '  end;',
   '  end;',
+  'function Say(i: IUnknown): IUnknown; async;',
+  'begin',
+  'end;',
   'function Run: IUnknown; async;',
   'function Run: IUnknown; async;',
   'begin',
   'begin',
+  '  Result:=await(Run);',
+  '  Result:=await(Run());',
+  '  Result:=await(Run) as IUnknown;',
+  '  Result:=await(Say(nil));',
+  '  Result:=await(Say(await(Run())));',
+  '  Result:=await(Say(await(Run()) as IUnknown));',
+  '  Result:=await(Say(await(Run()) as IUnknown)) as IUnknown;',
   'end;',
   'end;',
   'procedure Fly;',
   'procedure Fly;',
   'var p: TJSPromise;',
   'var p: TJSPromise;',
@@ -32885,8 +32970,25 @@ begin
   CheckSource('TestAsync_ClassInterface',
   CheckSource('TestAsync_ClassInterface',
     LinesToStr([ // statements
     LinesToStr([ // statements
     'rtl.createInterface(this, "IUnknown", "{D7ADB0E1-758A-322B-BDDF-21CD521DDFA9}", ["_AddRef", "_Release"], null);',
     'rtl.createInterface(this, "IUnknown", "{D7ADB0E1-758A-322B-BDDF-21CD521DDFA9}", ["_AddRef", "_Release"], null);',
+    'this.Say = async function (i) {',
+    '  var Result = null;',
+    '  return Result;',
+    '};',
     'this.Run = async function () {',
     'this.Run = async function () {',
     '  var Result = null;',
     '  var Result = null;',
+    '  var $ok = false;',
+    '  try {',
+    '    Result = rtl.setIntfL(Result, await $mod.Run());',
+    '    Result = rtl.setIntfL(Result, await $mod.Run());',
+    '    Result = rtl.setIntfL(Result, rtl.intfAsIntfT(await $mod.Run(), $mod.IUnknown));',
+    '    Result = rtl.setIntfL(Result, await $mod.Say(null));',
+    '    Result = rtl.setIntfL(Result, await $mod.Say(await $mod.Run()));',
+    '    Result = rtl.setIntfL(Result, await $mod.Say(rtl.intfAsIntfT(await $mod.Run(), $mod.IUnknown)));',
+    '    Result = rtl.setIntfL(Result, rtl.intfAsIntfT(await $mod.Say(rtl.intfAsIntfT(await $mod.Run(), $mod.IUnknown)), $mod.IUnknown));',
+    '    $ok = true;',
+    '  } finally {',
+    '    if (!$ok) rtl._Release(Result);',
+    '  };',
     '  return Result;',
     '  return Result;',
     '};',
     '};',
     'this.Fly = function () {',
     'this.Fly = function () {',
@@ -32902,6 +33004,29 @@ begin
   CheckResolverUnexpectedHints();
   CheckResolverUnexpectedHints();
 end;
 end;
 
 
+procedure TTestModule.TestAsync_ClassInterface_AsyncMissmatchFail;
+begin
+  StartProgram(true,[supTInterfacedObject]);
+  Add([
+  '{$mode objfpc}',
+  '{$modeswitch externalclass}',
+  'type',
+  '  TJSPromise = class external name ''Promise''',
+  '  end;',
+  '  IBird = interface',
+  '    procedure Run;',
+  '  end;',
+  '  TBird = class(TInterfacedObject,IBird)',
+  '    procedure Run; async;',
+  '  end;',
+  'procedure TBird.Run;',
+  'begin',
+  'end;',
+  'begin',
+  '  ']);
+  SetExpectedPasResolverError('procedure type modifier "async" mismatch',nXModifierMismatchY);
+  ConvertProgram;
+end;
 
 
 Initialization
 Initialization
   RegisterTests([TTestModule]);
   RegisterTests([TTestModule]);

+ 2 - 2
rtl/darwin/aarch64/sighnd.inc

@@ -32,8 +32,6 @@ begin
           Else
           Else
             Res:=207; {coprocessor error}
             Res:=207; {coprocessor error}
         end;
         end;
-        { clear "exception happened" flags }
-        SigContext^.uc_mcontext^.__fs.__fpsr:=SigContext^.uc_mcontext^.__fs.__fpsr and not(fpu_exception_mask shr fpu_exception_mask_to_status_mask_shift);
       end;
       end;
     SIGBUS:
     SIGBUS:
         res:=214;
         res:=214;
@@ -45,6 +43,8 @@ begin
     SIGQUIT:
     SIGQUIT:
         res:=233;
         res:=233;
   end;
   end;
+  { right now, macOS generates SIGILL signals for fpu exceptions, so always clear the fpu exceptions }
+  SigContext^.uc_mcontext^.__fs.__fpsr:=SigContext^.uc_mcontext^.__fs.__fpsr and not(fpu_exception_mask shr fpu_exception_mask_to_status_mask_shift);
   {$ifdef FPC_USE_SIGPROCMASK}
   {$ifdef FPC_USE_SIGPROCMASK}
    reenable_signal(sig);
    reenable_signal(sig);
   {$endif }
   {$endif }

+ 5 - 1
rtl/freertos/xtensa/esp8266.pp

@@ -81,7 +81,11 @@ unit esp8266;
       begin
       begin
         ReadChar := true;
         ReadChar := true;
         ACh := #0;
         ACh := #0;
-        uart_rx_one_char(@ACh);  // check failure?
+        repeat
+          uart_rx_one_char(@ACh);  // check failure?
+          if ACh = #0 then
+            vTaskDelay(1);
+        until ACh <> #0;
       end;
       end;
 
 
 begin
 begin

+ 33 - 4
rtl/i386/cpu.pp

@@ -14,6 +14,7 @@
 
 
  **********************************************************************}
  **********************************************************************}
 {$mode objfpc}
 {$mode objfpc}
+{$goto on}
 unit cpu;
 unit cpu;
 
 
   interface
   interface
@@ -41,6 +42,7 @@ unit cpu;
     function MOVBESupport: boolean;inline;
     function MOVBESupport: boolean;inline;
     function F16CSupport: boolean;inline;
     function F16CSupport: boolean;inline;
     function RDRANDSupport: boolean;inline;
     function RDRANDSupport: boolean;inline;
+    function RTMSupport: boolean;inline;
 
 
     var
     var
       is_sse3_cpu : boolean = false;
       is_sse3_cpu : boolean = false;
@@ -60,14 +62,33 @@ unit cpu;
       _SSE42Support,
       _SSE42Support,
       _MOVBESupport,
       _MOVBESupport,
       _F16CSupport,
       _F16CSupport,
-      _RDRANDSupport: boolean;
+      _RDRANDSupport,
+      _RTMSupport: boolean;
 
 
+{$ASMMODE ATT}
 
 
     function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
     function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
       begin
       begin
-        RunError(217);
+{$ifndef FPC_PIC}      
+        if _RTMSupport then
+          begin
+            asm
+            .Lretry:
+              xbegin .Lretry
+            end;
+            Result:=Target;
+            if (Result.Lo=Comperand.Lo) and (Result.Hi=Comperand.Hi) then
+              Target:=NewValue;
+            asm
+              xend
+            end;
+          end
+        else
+{$endif FPC_PIC}        
+          RunError(217);
       end;
       end;
 
 
+{$ASMMODE INTEL}
 
 
     function cpuid_support : boolean;assembler;
     function cpuid_support : boolean;assembler;
       {
       {
@@ -163,14 +184,16 @@ unit cpu;
                  popl %ebx
                  popl %ebx
               end;
               end;
               _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
               _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
+              _RTMSupport:=((_ebx and $800)<>0);
            end;
            end;
       end;
       end;
 
 
 
 
     function InterlockedCompareExchange128Support : boolean;
     function InterlockedCompareExchange128Support : boolean;
       begin
       begin
-        { 32 Bit CPUs have no 128 Bit interlocked exchange support }
-        result:=false;
+        { 32 Bit CPUs have no 128 Bit interlocked exchange support,
+          but it can simulated using RTM }
+        result:=_RTMSupport;
       end;
       end;
 
 
 
 
@@ -234,6 +257,12 @@ unit cpu;
       end;
       end;
 
 
 
 
+    function RTMSupport: boolean;inline;
+      begin
+        result:=_RTMSupport;
+      end;
+
+
 begin
 begin
   SetupSupport;
   SetupSupport;
 end.
 end.

+ 5 - 5
rtl/inc/currh.inc

@@ -14,16 +14,16 @@
 
 
 
 
 {$ifdef FPC_CURRENCY_IS_INT64}
 {$ifdef FPC_CURRENCY_IS_INT64}
-    function trunc(c : currency) : int64;
+    function trunc(c : currency) : int64; {$ifdef systeminline} inline; {$endif}
 {$ifndef FPUNONE}
 {$ifndef FPUNONE}
     function round(c : currency) : int64;
     function round(c : currency) : int64;
 {$endif FPUNONE}
 {$endif FPUNONE}
 {$ifndef cpujvm}
 {$ifndef cpujvm}
-    function trunc(c : comp) : int64;
-    function round(c : comp) : int64;
+    function trunc(c : comp) : int64; {$ifdef systeminline} inline; {$endif}
+    function round(c : comp) : int64; {$ifdef systeminline} inline; {$endif}
 {$else not cpujvm}
 {$else not cpujvm}
-    function trunc_comp(c: comp) : int64;
-    function round_comp(c : comp) : int64;
+    function trunc_comp(c: comp) : int64; {$ifdef systeminline} inline; {$endif}
+    function round_comp(c : comp) : int64; {$ifdef systeminline} inline; {$endif}
 {$endif not cpujvm}
 {$endif not cpujvm}
 {$endif FPC_CURRENCY_IS_INT64}
 {$endif FPC_CURRENCY_IS_INT64}
 
 

+ 32 - 16
rtl/inc/gencurr.inc

@@ -14,16 +14,16 @@
 
 
 {$ifdef FPC_CURRENCY_IS_INT64}
 {$ifdef FPC_CURRENCY_IS_INT64}
 
 
-    function trunc(c : currency) : int64;
+    function trunc(c : currency) : int64; {$ifdef systeminline} inline; {$endif}
       begin
       begin
         { the type conversion includes dividing by 10000 }
         { the type conversion includes dividing by 10000 }
         result := int64(c)
         result := int64(c)
       end;
       end;
 
 
 {$ifndef cpujvm}
 {$ifndef cpujvm}
-    function trunc(c : comp) : int64;
+    function trunc(c : comp) : int64; {$ifdef systeminline} inline; {$endif}
 {$else not cpujvm}
 {$else not cpujvm}
-    function trunc_comp(c : comp) : int64;
+    function trunc_comp(c : comp) : int64; {$ifdef systeminline} inline; {$endif}
 {$endif cpujvm}
 {$endif cpujvm}
       begin
       begin
         result := c
         result := c
@@ -34,27 +34,43 @@
       var
       var
         rem, absrem: currency;
         rem, absrem: currency;
       begin
       begin
-        { (int64(tmyrec(c))(+/-)5000) div 10000 can overflow }
         result := int64(c);
         result := int64(c);
         rem := c - currency(result);
         rem := c - currency(result);
-        absrem := rem;
-        if absrem < 0 then
-          absrem := -absrem;
-        if (absrem > 0.5) or
-           ((absrem = 0.5) and
-            (rem > 0)) then
-          if (rem > 0) then
-            inc(result)
-          else
-            dec(result);
+        case softfloat_rounding_mode of
+          rmNearest:
+            begin
+              absrem := abs(rem);
+              if (absrem > 0.5) or
+                 ((absrem = 0.5) and
+                  odd(result)) then
+                if (rem > 0) then
+                  inc(result)
+                else
+                  dec(result)
+            end;
+          rmDown:
+            begin
+              if rem < 0 then
+                dec(result);
+            end;
+          rmUp:
+            begin
+              if rem > 0 then
+                inc(result);
+            end;
+          rmTruncate:
+            begin
+              // result is already ok
+            end;
+        end;
       end;
       end;
 {$endif FPUNONE}
 {$endif FPUNONE}
 
 
 
 
 {$ifndef cpujvm}
 {$ifndef cpujvm}
-    function round(c : comp) : int64;
+    function round(c : comp) : int64; {$ifdef systeminline} inline; {$endif}
 {$else not cpujvm}
 {$else not cpujvm}
-    function round_comp(c : comp) : int64;
+    function round_comp(c : comp) : int64; {$ifdef systeminline} inline; {$endif}
 {$endif cpujvm}
 {$endif cpujvm}
       begin
       begin
         result := c
         result := c

+ 8 - 2
rtl/inc/genmath.inc

@@ -1443,9 +1443,15 @@ end;
       if (hx < $00100000) then              { x < 2**-1022  }
       if (hx < $00100000) then              { x < 2**-1022  }
       begin
       begin
         if (((hx and $7fffffff) or longint(lx))=0) then
         if (((hx and $7fffffff) or longint(lx))=0) then
-          exit(-two54/zero);                { log(+-0)=-inf }
+          begin
+            float_raise(float_flag_divbyzero);
+            exit(-two54/zero);                { log(+-0)=-inf }
+          end;
         if (hx<0) then
         if (hx<0) then
-          exit((d-d)/zero);                 { log(-#) = NaN }
+          begin
+            float_raise(float_flag_invalid);
+            exit((d-d)/zero);                 { log(-#) = NaN }
+          end;
         dec(k, 54); d := d * two54;         { subnormal number, scale up x }
         dec(k, 54); d := d * two54;         { subnormal number, scale up x }
         hx := float64high(d);
         hx := float64high(d);
       end;
       end;

+ 24 - 24
rtl/objpas/sysutils/dati.inc

@@ -352,7 +352,7 @@ end;
 
 
 Const
 Const
   DateTimeToStrFormat : Array[Boolean] of string = ('c','f');
   DateTimeToStrFormat : Array[Boolean] of string = ('c','f');
-  
+
 function DateTimeToStr(DateTime: TDateTime; ForceTimeIfZero : Boolean = False): string;
 function DateTimeToStr(DateTime: TDateTime; ForceTimeIfZero : Boolean = False): string;
 begin
 begin
   DateTimeToString(Result, DateTimeToStrFormat[ForceTimeIfZero], DateTime)
   DateTimeToString(Result, DateTimeToStrFormat[ForceTimeIfZero], DateTime)
@@ -1089,8 +1089,8 @@ var
         end ;
         end ;
         '/': StoreStr(@FormatSettings.DateSeparator, 1);
         '/': StoreStr(@FormatSettings.DateSeparator, 1);
         ':': StoreStr(@FormatSettings.TimeSeparator, 1);
         ':': StoreStr(@FormatSettings.TimeSeparator, 1);
-	'[': if (fdoInterval in Options) then isInterval := true else StoreStr(FormatCurrent, 1);
-	']': if (fdoInterval in Options) then isInterval := false else StoreStr(FormatCurrent, 1);
+        '[': if (fdoInterval in Options) then isInterval := true else StoreStr(FormatCurrent, 1);
+        ']': if (fdoInterval in Options) then isInterval := false else StoreStr(FormatCurrent, 1);
         ' ', 'C', 'D', 'H', 'M', 'N', 'S', 'T', 'Y', 'Z', 'F' {$IFDEF MSWindows}, 'G', 'E'{$ENDIF MSWindows} :
         ' ', 'C', 'D', 'H', 'M', 'N', 'S', 'T', 'Y', 'Z', 'F' {$IFDEF MSWindows}, 'G', 'E'{$ENDIF MSWindows} :
         begin
         begin
           while (P < FormatEnd) and (UpCase(P^) = Token) do
           while (P < FormatEnd) and (UpCase(P^) = Token) do
@@ -1105,9 +1105,9 @@ var
                 StoreInt(Year mod 100, 2);
                 StoreInt(Year mod 100, 2);
             end;
             end;
             'M': begin
             'M': begin
-	      if isInterval and ((prevlasttoken = 'H') or TimeFlag) then
-	        StoreInt(Minute + (Hour + trunc(abs(DateTime))*24)*60, 0)
-	      else
+              if isInterval and ((prevlasttoken = 'H') or TimeFlag) then
+                StoreInt(Minute + (Hour + trunc(abs(DateTime))*24)*60, 0)
+              else
               if (lastformattoken = 'H') or TimeFlag then
               if (lastformattoken = 'H') or TimeFlag then
               begin
               begin
                 if Count = 1 then
                 if Count = 1 then
@@ -1137,11 +1137,11 @@ var
                 StoreFormat(FormatSettings.LongDateFormat, Nesting+1, False);
                 StoreFormat(FormatSettings.LongDateFormat, Nesting+1, False);
               end ;
               end ;
             end ;
             end ;
-            'H': 
-	      if isInterval then
-	        StoreInt(Hour + trunc(abs(DateTime))*24, 0)
-	      else
-	      if Clock12 then
+            'H':
+              if isInterval then
+                StoreInt(Hour + trunc(abs(DateTime))*24, 0)
+              else
+              if Clock12 then
               begin
               begin
                 tmp := hour mod 12;
                 tmp := hour mod 12;
                 if tmp=0 then tmp:=12;
                 if tmp=0 then tmp:=12;
@@ -1152,32 +1152,32 @@ var
               end
               end
               else begin
               else begin
                 if Count = 1 then
                 if Count = 1 then
-		  StoreInt(Hour, 0)
+                  StoreInt(Hour, 0)
                 else
                 else
                   StoreInt(Hour, 2);
                   StoreInt(Hour, 2);
               end;
               end;
             'N': if isInterval then
             'N': if isInterval then
-	           StoreInt(Minute + (Hour + trunc(abs(DateTime))*24)*60, 0)
-		 else
-		 if Count = 1 then
+                   StoreInt(Minute + (Hour + trunc(abs(DateTime))*24)*60, 0)
+                 else
+                 if Count = 1 then
                    StoreInt(Minute, 0)
                    StoreInt(Minute, 0)
                  else
                  else
                    StoreInt(Minute, 2);
                    StoreInt(Minute, 2);
             'S': if isInterval then
             'S': if isInterval then
-	           StoreInt(Second + (Minute + (Hour + trunc(abs(DateTime))*24)*60)*60, 0)
-	         else 
-	         if Count = 1 then
+                   StoreInt(Second + (Minute + (Hour + trunc(abs(DateTime))*24)*60)*60, 0)
+                 else
+                 if Count = 1 then
                    StoreInt(Second, 0)
                    StoreInt(Second, 0)
                  else
                  else
                    StoreInt(Second, 2);
                    StoreInt(Second, 2);
             'Z': if Count = 1 then
             'Z': if Count = 1 then
                    StoreInt(MilliSecond, 0)
                    StoreInt(MilliSecond, 0)
                  else
                  else
-		   StoreInt(MilliSecond, 3);
+                   StoreInt(MilliSecond, 3);
             'T': if Count = 1 then
             'T': if Count = 1 then
-		   StoreFormat(FormatSettings.ShortTimeFormat, Nesting+1, True)
+                   StoreFormat(FormatSettings.ShortTimeFormat, Nesting+1, True)
                  else
                  else
-	           StoreFormat(FormatSettings.LongTimeFormat, Nesting+1, True);
+                   StoreFormat(FormatSettings.LongTimeFormat, Nesting+1, True);
             'C': begin
             'C': begin
                    StoreFormat(FormatSettings.ShortDateFormat, Nesting+1, False);
                    StoreFormat(FormatSettings.ShortDateFormat, Nesting+1, False);
                    if (Hour<>0) or (Minute<>0) or (Second<>0) then
                    if (Hour<>0) or (Minute<>0) or (Second<>0) then
@@ -1203,7 +1203,7 @@ var
                      Count := P - FormatCurrent;
                      Count := P - FormatCurrent;
                      StoreString(ConvertEraYearString(Count,Year,Month,Day));
                      StoreString(ConvertEraYearString(Count,Year,Month,Day));
                    end;
                    end;
-		 prevlasttoken := lastformattoken;  
+                 prevlasttoken := lastformattoken;  
                  lastformattoken:=token;
                  lastformattoken:=token;
                end;
                end;
              'G':
              'G':
@@ -1217,12 +1217,12 @@ var
                      Count := P - FormatCurrent;
                      Count := P - FormatCurrent;
                      StoreString(ConvertEraString(Count,Year,Month,Day));
                      StoreString(ConvertEraString(Count,Year,Month,Day));
                    end;
                    end;
-		 prevlasttoken := lastformattoken;
+                 prevlasttoken := lastformattoken;
                  lastformattoken:=token;
                  lastformattoken:=token;
                end;
                end;
 {$endif win32 or win64}
 {$endif win32 or win64}
           end;
           end;
-	  prevlasttoken := lastformattoken;
+          prevlasttoken := lastformattoken;
           lastformattoken := token;
           lastformattoken := token;
         end;
         end;
         else
         else

+ 12 - 2
rtl/win/sysutils.pp

@@ -917,6 +917,12 @@ begin
 end;
 end;
 
 
 
 
+type
+  TGetTimeZoneInformationForYear = function(wYear: USHORT; lpDynamicTimeZoneInformation: PDynamicTimeZoneInformation;
+    var lpTimeZoneInformation: TTimeZoneInformation): BOOL;stdcall;
+var
+  GetTimeZoneInformationForYear:TGetTimeZoneInformationForYear=nil;
+
 function GetLocalTimeOffset(const DateTime: TDateTime; const InputIsUTC: Boolean; out Offset: Integer): Boolean;
 function GetLocalTimeOffset(const DateTime: TDateTime; const InputIsUTC: Boolean; out Offset: Integer): Boolean;
 var
 var
   Year: Integer;
   Year: Integer;
@@ -961,10 +967,11 @@ var
   DSTStart, DSTEnd: TDateTime;
   DSTStart, DSTEnd: TDateTime;
 
 
 begin
 begin
+  if not Assigned(GetTimeZoneInformationForYear) then
+    Exit(False);
   Year := YearOf(DateTime);
   Year := YearOf(DateTime);
   TZInfo := Default(TTimeZoneInformation);
   TZInfo := Default(TTimeZoneInformation);
-  // GetTimeZoneInformationForYear is supported only on Vista and newer
-  if not ((Win32MajorVersion>=6) and GetTimeZoneInformationForYear(Year, nil, TZInfo)) then
+  if not GetTimeZoneInformationForYear(Year, nil, TZInfo) then
     Exit(False);
     Exit(False);
 
 
   if (TZInfo.StandardDate.Month>0) and (TZInfo.DaylightDate.Month>0) then
   if (TZInfo.StandardDate.Month>0) and (TZInfo.DaylightDate.Month>0) then
@@ -1590,6 +1597,9 @@ begin
      FindExInfoDefaults := FindExInfoStandard; // also searches SFNs. XP only.
      FindExInfoDefaults := FindExInfoStandard; // also searches SFNs. XP only.
   if (Win32MajorVersion>=6) and (Win32MinorVersion>=1) then 
   if (Win32MajorVersion>=6) and (Win32MinorVersion>=1) then 
     FindFirstAdditionalFlags := FIND_FIRST_EX_LARGE_FETCH; // win7 and 2008R2+
     FindFirstAdditionalFlags := FIND_FIRST_EX_LARGE_FETCH; // win7 and 2008R2+
+  // GetTimeZoneInformationForYear is supported only on Vista and newer
+  if (kernel32dll<>0) and (Win32MajorVersion>=6) then
+    GetTimeZoneInformationForYear:=TGetTimeZoneInformationForYear(GetProcAddress(kernel32dll,'GetTimeZoneInformationForYear'));
 end;
 end;
 
 
 Function GetAppConfigDir(Global : Boolean) : String;
 Function GetAppConfigDir(Global : Boolean) : String;

+ 2 - 2
rtl/win/wininc/redef.inc

@@ -623,8 +623,8 @@ function GetThreadPriorityBoost(hThread: THandle; var DisablePriorityBoost: Bool
 function GetThreadSelectorEntry(hThread: THandle; dwSelector: DWORD; var lpSelectorEntry: TLDTEntry): BOOL; external 'kernel32' name 'GetThreadSelectorEntry';
 function GetThreadSelectorEntry(hThread: THandle; dwSelector: DWORD; var lpSelectorEntry: TLDTEntry): BOOL; external 'kernel32' name 'GetThreadSelectorEntry';
 function GetThreadTimes(hThread: THandle; var lpCreationTime, lpExitTime, lpKernelTime, lpUserTime: TFileTime): BOOL; external 'kernel32' name 'GetThreadTimes';
 function GetThreadTimes(hThread: THandle; var lpCreationTime, lpExitTime, lpKernelTime, lpUserTime: TFileTime): BOOL; external 'kernel32' name 'GetThreadTimes';
 function GetTimeZoneInformation(var lpTimeZoneInformation: TTimeZoneInformation): DWORD; external 'kernel32' name 'GetTimeZoneInformation';
 function GetTimeZoneInformation(var lpTimeZoneInformation: TTimeZoneInformation): DWORD; external 'kernel32' name 'GetTimeZoneInformation';
-function GetTimeZoneInformationForYear(wYear: USHORT; lpDynamicTimeZoneInformation: PDynamicTimeZoneInformation;
-  var lpTimeZoneInformation: TTimeZoneInformation): BOOL; external 'kernel32' name 'GetTimeZoneInformationForYear';
+//function GetTimeZoneInformationForYear(wYear: USHORT; lpDynamicTimeZoneInformation: PDynamicTimeZoneInformation;
+//  var lpTimeZoneInformation: TTimeZoneInformation): BOOL; external 'kernel32' name 'GetTimeZoneInformationForYear';
 //function GetTitleBarInfo(hwnd: HWND; var pti: TTitleBarInfo): BOOL;external 'user32' name 'GetTitleBarInfo';
 //function GetTitleBarInfo(hwnd: HWND; var pti: TTitleBarInfo): BOOL;external 'user32' name 'GetTitleBarInfo';
 function GetTokenInformation(TokenHandle: THandle; TokenInformationClass: TTokenInformationClass; TokenInformation: Pointer; TokenInformationLength: DWORD; var ReturnLength: DWORD): BOOL; external 'advapi32' name 'GetTokenInformation';
 function GetTokenInformation(TokenHandle: THandle; TokenInformationClass: TTokenInformationClass; TokenInformation: Pointer; TokenInformationLength: DWORD; var ReturnLength: DWORD): BOOL; external 'advapi32' name 'GetTokenInformation';
 function GetUpdateRect(hWnd: HWND; var lpRect: TRect; bErase: BOOL): BOOL; external 'user32' name 'GetUpdateRect';
 function GetUpdateRect(hWnd: HWND; var lpRect: TRect; bErase: BOOL): BOOL; external 'user32' name 'GetUpdateRect';

+ 9 - 1
rtl/x86_64/cpu.pp

@@ -39,6 +39,7 @@ unit cpu;
     function MOVBESupport: boolean;inline;
     function MOVBESupport: boolean;inline;
     function F16CSupport: boolean;inline;
     function F16CSupport: boolean;inline;
     function RDRANDSupport: boolean;inline;
     function RDRANDSupport: boolean;inline;
+    function RTMSupport: boolean;inline;
 
 
     var
     var
       is_sse3_cpu : boolean = false;
       is_sse3_cpu : boolean = false;
@@ -60,7 +61,8 @@ unit cpu;
       _SSE42Support,
       _SSE42Support,
       _MOVBESupport,
       _MOVBESupport,
       _F16CSupport,
       _F16CSupport,
-      _RDRANDSupport: boolean;
+      _RDRANDSupport,
+      _RTMSupport: boolean;
 
 
     function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec; assembler;
     function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec; assembler;
      {
      {
@@ -179,6 +181,7 @@ unit cpu;
            movl %ebx,_ebx
            movl %ebx,_ebx
         end ['rax','rbx','rcx','rdx'];
         end ['rax','rbx','rcx','rdx'];
         _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
         _AVX2Support:=_AVXSupport and ((_ebx and $20)<>0);
+        _RTMSupport:=((_ebx and $800)<>0);
       end;
       end;
 
 
 
 
@@ -247,6 +250,11 @@ unit cpu;
       end;
       end;
 
 
 
 
+    function RTMSupport: boolean;inline;
+      begin
+        result:=_RTMSupport;
+      end;
+
 begin
 begin
   SetupSupport;
   SetupSupport;
 end.
 end.

+ 8 - 0
tests/tbf/tb0273.pp

@@ -0,0 +1,8 @@
+{ %FAIL }
+
+// EXPECTED: 'Error: Illegal function result type'
+// ACTUAL: gets compiled
+type M = function : file;
+
+begin
+end.

+ 23 - 0
tests/tbs/tb0681.pp

@@ -0,0 +1,23 @@
+program tb0681;
+
+{$Mode Delphi}
+
+type R = record
+    var X: Integer;
+    function Foo: Integer;
+end;
+
+function R.Foo: Integer;
+begin
+    result := X
+end;
+
+var    F: function : Integer of object;
+    Z: R = (X:42);
+begin
+    // EXPECTED: gets compiled
+    // ACTUAL: 'Error: Incompatible types'
+    F := Z.Foo;
+    if F() <> 42 then
+      Halt(1);
+end.

+ 17 - 0
tests/tbs/tb0682.pp

@@ -0,0 +1,17 @@
+{ %target=linux,openbsd,netbsd,freebsd }
+{ %cpu=i386 }
+{ %norun }
+{$goto on }
+label
+  l;
+
+begin
+  asm
+    movl l@GOT(%eax),%eax 
+    l:
+  end;
+  asm
+    movl .Ll@GOT(%eax),%eax 
+    .Ll:
+  end;
+end.

+ 22 - 0
tests/tbs/tb0683.pp

@@ -0,0 +1,22 @@
+{$ifndef SKIP_CURRENCY_TEST}
+var
+  c: currency;
+  co: comp;
+  i: int64;
+begin
+  c:=10.25;
+  co:=12;
+  i:=trunc(c);
+  if i<>10 then
+    halt(1);
+  i:=trunc(co);
+  if i<>12 then
+    halt(2);
+  i:=round(co);
+  if i<>12 then
+   halt(3);
+end.
+{$else}
+begin
+end.
+{$endif}

+ 31 - 21
tests/test/tcas128.pp

@@ -1,4 +1,4 @@
-{ %cpu=x86_64 }
+{ %cpu=x86_64,i386 }
 
 
 {$codealign varmin=16}
 {$codealign varmin=16}
 
 
@@ -9,24 +9,34 @@ var
   i1,i2,i3,i4 : int128rec;
   i1,i2,i3,i4 : int128rec;
 
 
 begin
 begin
-  writeln('Start');
-  i1.lo:=11;
-  i1.hi:=12;
-  i2.lo:=21;
-  i2.hi:=22;
-  i3:=i1;
-  i4.lo:=0;
-  i4.hi:=0;
-  i4:=InterlockedCompareExchange128(i1,i2,i3);
-  {
-  writeln(i4.lo);
-  writeln(i4.hi);
-  writeln(i1.lo);
-  writeln(i1.hi);
-  writeln(i2.lo);
-  writeln(i2.hi);
-  }
-  if (i4.lo<>11) or (i4.hi<>12) or (i1.lo<>i2.lo) or (i1.hi<>i2.hi) then
-    halt(1);
-  writeln('ok');
+{$ifdef cpui386}
+  writeln('RTM Support: ',RTMSupport);
+  if RTMSupport then
+    begin
+{$endif cpui386}
+      writeln('Start');
+      i1.lo:=11;
+      i1.hi:=12;
+      i2.lo:=21;
+      i2.hi:=22;
+      i3:=i1;
+      i4.lo:=0;
+      i4.hi:=0;
+      i4:=InterlockedCompareExchange128(i1,i2,i3);
+      {
+      writeln(i4.lo);
+      writeln(i4.hi);
+      writeln(i1.lo);
+      writeln(i1.hi);
+      writeln(i2.lo);
+      writeln(i2.hi);
+      }
+      if (i4.lo<>11) or (i4.hi<>12) or (i1.lo<>i2.lo) or (i1.hi<>i2.hi) then
+        halt(1);
+      writeln('ok');
+{$ifdef cpui386}
+    end
+  else
+    writeln('No InterlockedCompareExchange128 support available');
+{$endif cpui386}
 end.
 end.

+ 24 - 0
tests/test/texception4.pp

@@ -123,6 +123,30 @@ begin
        end;
        end;
    end;
    end;
    test_exception('ln(-1)');
    test_exception('ln(-1)');
+   try
+   exception_called:=false;
+   i := 0;
+   e := ln(i);
+   except
+     on e : exception do
+       begin
+         Writeln('exception called ',e.message);
+         exception_called:=true;
+       end;
+   end;
+   test_exception('ln(0)');
+   try
+   exception_called:=false;
+   i := -1;
+   e := sqrt(i);
+   except
+     on e : exception do
+       begin
+         Writeln('exception called ',e.message);
+         exception_called:=true;
+       end;
+   end;
+   test_exception('sqrt(-1)');
    if program_has_errors then
    if program_has_errors then
      Halt(1);
      Halt(1);
 end.
 end.

+ 23 - 0
tests/test/tgeneric106.pp

@@ -0,0 +1,23 @@
+program tgeneric106;
+
+{$Mode Delphi}
+
+type G<T> = class
+    var X: T;
+    // EXPECTED: gets compiled
+    // ACTUAL: 'Error: Generics without specialization cannot be used as a type for a variable'
+    class var F: function(const X: T) : G<T> of object;
+    function Foo(const X: T): G<T>;
+end;
+
+function G<T>.Foo(const X: T): G<T>;
+begin
+    result := G<T>.Create;
+    result.X := X
+end;
+
+begin
+    G<Integer>.F := G<Integer>.Create.Foo;
+    if G<Integer>.F(42).X <> 42 then
+      halt(1);
+end.

+ 23 - 0
tests/test/tgeneric107.pp

@@ -0,0 +1,23 @@
+program tgeneric107;
+
+{$Mode ObjFpc}
+
+type generic G<T> = class
+    var X: T;
+    // EXPECTED: gets compiled
+    // ACTUAL: 'Error: Generics without specialization cannot be used as a type for a variable'
+    class var F: function(const X: T) : specialize G<T> of object;
+    function Foo(const aX: T): specialize G<T>;
+end;
+
+function G.Foo(const aX: T): specialize G<T>;
+begin
+    result := specialize G<T>.Create;
+    result.X := aX
+end;
+
+begin
+    specialize G<Integer>.F := @specialize G<Integer>.Create.Foo;
+    if specialize G<Integer>.F(42).X <> 42 then
+      halt(1);
+end.

+ 4 - 4
tests/test/tminmax.pp

@@ -45,7 +45,7 @@ procedure TestSingle;
   function Min3(a, b: Single): Single; inline;
   function Min3(a, b: Single): Single; inline;
     begin
     begin
       Result := b;
       Result := b;
-      if a < b then
+      if a < Result then
         Result := a;
         Result := a;
     end;
     end;
 
 
@@ -53,7 +53,7 @@ procedure TestSingle;
   function Max3(a, b: Single): Single; inline;
   function Max3(a, b: Single): Single; inline;
     begin
     begin
       Result := b;
       Result := b;
-      if a > b then
+      if a > Result then
         Result := a;
         Result := a;
     end;
     end;
 
 
@@ -61,7 +61,7 @@ procedure TestSingle;
   function Min4(a, b: Single): Single; inline;
   function Min4(a, b: Single): Single; inline;
     begin
     begin
       Result := b;
       Result := b;
-      if a <= b then
+      if a <= Result then
         Result := a;
         Result := a;
     end;
     end;
 
 
@@ -69,7 +69,7 @@ procedure TestSingle;
   function Max4(a, b: Single): Single; inline;
   function Max4(a, b: Single): Single; inline;
     begin
     begin
       Result := b;
       Result := b;
-      if a >= b then
+      if a >= Result then
         Result := a;
         Result := a;
     end;
     end;
 
 

+ 6 - 6
tests/test/tprec8.pp

@@ -40,19 +40,19 @@ begin
     halt(1);
     halt(1);
   r.g := 5;
   r.g := 5;
   if (r.g <> 5) then
   if (r.g <> 5) then
-    halt(1);
+    halt(2);
   r.h := 65535;
   r.h := 65535;
   if (r.h <> 65535) then
   if (r.h <> 65535) then
-    halt(1);
+    halt(3);
   r.k := true;
   r.k := true;
   if not (r.k) then
   if not (r.k) then
-    halt(1);
+    halt(4);
   r.j := false;
   r.j := false;
   if r.j then
   if r.j then
-    halt(1);
+    halt(5);
   if b <> 0 then
   if b <> 0 then
-    halt(1);
+    halt(6);
   if sizeof(tr) <> 13 then
   if sizeof(tr) <> 13 then
-    halt(2);
+    halt(7);
 end.
 end.
 
 

+ 42 - 1
tests/test/units/linux/tstatx.pp

@@ -3,11 +3,52 @@ uses
   ctypes,baseunix,linux;
   ctypes,baseunix,linux;
   
   
 var
 var
+  un : utsname;
   mystatx : statx;
   mystatx : statx;
   res : cint;
   res : cint;
   f : text;
   f : text;
-  
+  st,major,minor : string;
+  i,p,e : longint;
+  err : word;
+  major_release, minor_release : longint;
 begin
 begin
+  fpuname(un);
+  st:=un.release;
+  for i:=1 to UTSNAME_LENGTH do
+    if st[i]='.' then
+      begin
+        p:=i;
+        major:=system.copy(st,1,p-1);
+        system.val(major,major_release,err);
+        if err<>0 then
+          begin 
+            writeln('Unable to parse first part of linux version ',st,'(',major,') correctly');
+            halt(2);
+          end;
+        break;
+      end;
+  
+  for i:=p+1 to UTSNAME_LENGTH do
+    if st[i]='.' then
+      begin
+        e:=i;
+        minor:=system.copy(st,p+1,e-p-1);
+        system.val(minor,minor_release,err);
+        if err<>0 then
+          begin 
+            writeln('Unable to second part of parse linux version ',st,'i(',minor,') correctly');
+            halt(2);
+          end;
+        break;
+      end;
+  if (major_release<4) or (minor_release<11) then
+    begin
+      writeln('This version of Linux: ',st,' does not have fstatx syscall');
+      halt(0);
+    end
+  else
+    writeln('This linux version ',st,' should support statx syscall');
+     
   assign(f,'test.txt');
   assign(f,'test.txt');
   rewrite(f);
   rewrite(f);
   write(f,'ccccc');
   write(f,'ccccc');

+ 78 - 0
tests/test/units/math/trndcurr.pp

@@ -0,0 +1,78 @@
+uses
+  Math;
+
+{$ifndef SKIP_CURRENCY_TEST}
+procedure testround(const c, expected: currency; error: longint);
+begin
+  if round(c)<>expected then
+    begin
+      writeln('round(',c,') = ',round(c),' instead of ', expected);
+      halt(error);
+    end;
+end;
+
+{$endif}
+
+
+begin
+{$ifndef SKIP_CURRENCY_TEST}
+  writeln('Rounding mode: rmNearest (even)');
+  testround(0.5,0.0,1);
+  testround(1.5,2.0,2);
+  testround(-0.5,0.0,3);
+  testround(-1.5,-2.0,4);
+  testround(0.6,1.0,101);
+  testround(1.6,2.0,102);
+  testround(-0.6,-1.0,103);
+  testround(-1.6,-2.0,104);
+  testround(0.4,0.0,151);
+  testround(1.4,1.0,152);
+  testround(-0.4,-0.0,153);
+  testround(-1.4,-1.0,154);
+
+  writeln('Rounding mode: rmUp');
+  SetRoundMode(rmUp);
+  testround(0.5,1.0,5);
+  testround(1.5,2.0,6);
+  testround(-0.5,0.0,7);
+  testround(-1.5,-1.0,8);
+  testround(0.6,1.0,105);
+  testround(1.6,2.0,106);
+  testround(-0.6,0.0,107);
+  testround(-1.6,-1.0,108);
+  testround(0.4,1.0,155);
+  testround(1.4,2.0,156);
+  testround(-0.4,0.0,157);
+  testround(-1.4,-1.0,158);
+
+  writeln('Rounding mode: rmDown');
+  SetRoundMode(rmDown);
+  testround(0.5,0.0,9);
+  testround(1.5,1.0,10);
+  testround(-0.5,-1.0,11);
+  testround(-1.5,-2.0,12);
+  testround(0.6,0.0,109);
+  testround(1.6,1.0,110);
+  testround(-0.6,-1.0,111);
+  testround(-1.6,-2.0,112);
+  testround(0.4,0.0,159);
+  testround(1.4,1.0,160);
+  testround(-0.4,-1.0,161);
+  testround(-1.4,-2.0,162);
+
+  writeln('Rounding mode: rmTruncate');
+  SetRoundMode(rmTruncate);
+  testround(0.5,0.0,13);
+  testround(1.5,1.0,14);
+  testround(-0.5,0.0,15);
+  testround(-1.5,-1.0,16);
+  testround(0.6,0.0,113);
+  testround(1.6,1.0,114);
+  testround(-0.6,0.0,115);
+  testround(-1.6,-1.0,116);
+  testround(0.4,0.0,163);
+  testround(1.4,1.0,164);
+  testround(-0.4,0.0,165);
+  testround(-1.4,-1.0,166);
+{$endif}
+end.

+ 13 - 0
tests/webtbs/tw38164.pp

@@ -0,0 +1,13 @@
+program int64modint64bug;
+{$mode delphi}
+const
+   a = int64($100000000);
+ var
+   b: int64 = 123;
+   c: int64;
+begin
+  c := b mod a;
+  if c <> 0 then
+  begin
+  end;
+end.

+ 37 - 0
tests/webtbs/tw38225.pp

@@ -0,0 +1,37 @@
+{$inline on}
+{$mode objfpc}
+uses
+  classes;
+
+operator - (const A: TPoint): TPoint; inline;
+begin
+  Result.X := - A.X;
+  Result.Y := - A.Y;
+end;
+
+operator div(const A: TPoint; ADivisor: Integer): TPoint; inline;
+begin
+  Result.X := A.X div ADivisor;
+  Result.Y := A.Y div ADivisor;
+end;
+
+
+procedure p;
+  var
+    i1,i2 : longint;
+    q1,q2 : int64;
+    d2 : dword;
+    p1,p2 : TPoint;
+
+  begin
+    p2:=-p2 div 2;
+    try
+      p2:=-p2 div 2;
+    except
+      p2:=-p2 div 2;
+    end;
+  end;
+
+begin
+end.
+

+ 56 - 0
tests/webtbs/tw38238.pp

@@ -0,0 +1,56 @@
+program tw38238;
+
+{$mode objfpc}
+{$modeswitch advancedrecords}
+
+type
+  TCallback = procedure(AValue: longint) of object;
+
+  TRec = record
+    Clb: TCallback;
+    procedure AddCallback(ACallback: TCallback);
+    procedure TriggerCallback(AValue: longint);
+  end;
+
+  TRec2 = record
+    Value: longint;
+    Rec: TRec;
+    procedure CLB(AValue: longint);
+    procedure InitStuff;
+  end;
+
+procedure TRec.AddCallback(ACallback: TCallback);
+begin
+  Clb:=ACallback;
+end;
+
+procedure TRec.TriggerCallback(AValue: longint);
+begin
+  if assigned(Clb) then
+    Clb(AValue);
+end;
+
+procedure TRec2.CLB(AValue: longint);
+begin
+  Value:=AValue;
+end;
+
+procedure TRec2.InitStuff;
+begin
+  Rec.AddCallback(@CLB);
+end;
+
+var
+  Rec1, Rec2: TRec2;
+begin
+  Rec1.InitStuff;
+  Rec2.InitStuff;
+
+  Rec1.Rec.TriggerCallback(1234);
+  Rec2.Rec.TriggerCallback($0943);
+
+  if Rec1.Value<>1234 then
+    Halt(1);
+  if Rec2.Value<>$0943 then
+    Halt(2);
+end.

+ 9 - 0
tests/webtbs/tw38249.pp

@@ -0,0 +1,9 @@
+var
+  A: Double = 0.0001;
+  B: Double = 0;
+begin
+  if B >= 0 then
+    A := B;
+  if A<>0 then
+    halt(1);
+end.

+ 23 - 11
utils/fpdoc/dw_htmlchm.inc → utils/fpdoc/dw_chm.pp

@@ -1,5 +1,10 @@
-{%mainunit dw_html}
-{$IFDEF chmInterface}
+unit dw_chm;
+
+interface
+
+uses Classes, DOM, DOM_HTML,
+    dGlobals, PasTree, dwriter, dw_html, ChmWriter, chmtypes;
+
 type
 type
 
 
   { TFpDocChmWriter }
   { TFpDocChmWriter }
@@ -42,7 +47,10 @@ type
     Class Function FileNameExtension : String; override;
     Class Function FileNameExtension : String; override;
     Class procedure SplitImport(var AFilename, ALinkPrefix: String); override;
     Class procedure SplitImport(var AFilename, ALinkPrefix: String); override;
   end;
   end;
-{$ELSE} // implementation
+
+implementation
+
+uses SysUtils, HTMWrite, chmsitemap;
 
 
 { TFpDocChmWriter }
 { TFpDocChmWriter }
 
 
@@ -470,7 +478,7 @@ var
   i: Integer;
   i: Integer;
   PageDoc: TXMLDocument;
   PageDoc: TXMLDocument;
   FileStream: TMemoryStream;
   FileStream: TMemoryStream;
-  FileName: String;
+  IFileName,FileName: String;
   FilePath: String;
   FilePath: String;
 begin
 begin
   FileName := Engine.Output;
   FileName := Engine.Output;
@@ -520,16 +528,16 @@ begin
 
 
   //write any found images to CHM stream
   //write any found images to CHM stream
   FileStream := TMemoryStream.Create;
   FileStream := TMemoryStream.Create;
-  for i := 0 to FImageFileList.Count - 1 do
+  for iFilename in ImageFileList do
   begin
   begin
-{$ifdef imagetest}    DoLog('  adding image: '+FImageFileList[i]); {$endif}
-    if FileExists(FImageFileList[i]) then
+{$ifdef imagetest}    DoLog('  adding image: '+iFileName); {$endif}
+    if FileExists(iFileName) then
     begin
     begin
 {$ifdef imagetest}    DoLog(' - found'); {$endif}
 {$ifdef imagetest}    DoLog(' - found'); {$endif}
-      FileName := ExtractFileName(FImageFileList[i]);
-      FilePath := '/'+FixHTMLpath(ExtractFilePath(FImageFileList[i]));
+      FileName := ExtractFileName(iFileName);
+      FilePath := '/'+FixHTMLpath(ExtractFilePath(iFileName));
 
 
-      FileStream.LoadFromFile(FImageFileList[i]);
+      FileStream.LoadFromFile(iFileName);
       FChm.AddStreamToArchive(FileName, FilePath, FileStream, True);
       FChm.AddStreamToArchive(FileName, FilePath, FileStream, True);
       FileStream.Size := 0;
       FileStream.Size := 0;
     end
     end
@@ -629,4 +637,8 @@ begin
     end;
     end;
 end;
 end;
 
 
-{$ENDIF}
+initialization
+  RegisterWriter(TCHMHTMLWriter,'chm','Compressed HTML file output using fpdoc.css stylesheet.');
+finalization
+  UnRegisterWriter('chm');
+end.

+ 6 - 9
utils/fpdoc/dw_html.pp

@@ -19,7 +19,7 @@ unit dw_html;
 {$WARN 5024 off : Parameter "$1" not used}
 {$WARN 5024 off : Parameter "$1" not used}
 interface
 interface
 
 
-uses Classes, DOM, DOM_HTML, dGlobals, PasTree, dWriter, ChmWriter, chmtypes;
+uses Classes, DOM, DOM_HTML, dGlobals, PasTree, dWriter;
 
 
 const
 const
   // Subpage indices for modules
   // Subpage indices for modules
@@ -273,16 +273,15 @@ type
     Property IndexColCount : Integer Read FIndexColCount write FIndexColCount;
     Property IndexColCount : Integer Read FIndexColCount write FIndexColCount;
     Property BaseImageURL : String Read FBaseImageURL Write FBaseImageURL;
     Property BaseImageURL : String Read FBaseImageURL Write FBaseImageURL;
     Property UseMenuBrackets : Boolean Read FUseMenuBrackets write FUseMenuBrackets;
     Property UseMenuBrackets : Boolean Read FUseMenuBrackets write FUseMenuBrackets;
+    Property ImageFileList : TStrings Read FImageFileList;
   end;
   end;
 
 
-  {$DEFINE chmInterface}
-  {$I dw_htmlchm.inc}
-  {$UNDEF chmInterface}
+
+Function FixHTMLpath(S : String) : STring;
 
 
 implementation
 implementation
 
 
-uses SysUtils, XMLRead, HTMWrite, sh_pas, fpdocclasstree,
-  chmsitemap;
+uses SysUtils, XMLRead, HTMWrite, sh_pas, fpdocclasstree;
 
 
 {$i css.inc}
 {$i css.inc}
 {$i plusimage.inc}
 {$i plusimage.inc}
@@ -294,7 +293,6 @@ begin
   Result:=StringReplace(S,'\','/',[rfReplaceAll]);
   Result:=StringReplace(S,'\','/',[rfReplaceAll]);
 end;
 end;
 
 
-{$I dw_htmlchm.inc}
 
 
 procedure TFileAllocator.AllocFilename(AElement: TPasElement;
 procedure TFileAllocator.AllocFilename(AElement: TPasElement;
   ASubindex: Integer);
   ASubindex: Integer);
@@ -3955,9 +3953,8 @@ end;
 initialization
 initialization
   // Do not localize.
   // Do not localize.
   RegisterWriter(THTMLWriter,'html','HTML output using fpdoc.css stylesheet.');
   RegisterWriter(THTMLWriter,'html','HTML output using fpdoc.css stylesheet.');
-  RegisterWriter(TCHMHTMLWriter,'chm','Compressed HTML file output using fpdoc.css stylesheet.');
 
 
 finalization
 finalization
   UnRegisterWriter('html');
   UnRegisterWriter('html');
-  UnRegisterWriter('chm');
+
 end.
 end.

+ 2 - 0
utils/fpdoc/fpdoc.pp

@@ -31,6 +31,8 @@ uses
   dw_XML,    // XML writer
   dw_XML,    // XML writer
   dw_dxml,   // Delphi XML doc.
   dw_dxml,   // Delphi XML doc.
   dw_HTML,   // HTML writer
   dw_HTML,   // HTML writer
+  dw_chm,    // CHM Writer
+  // dw_markdown, // Markdown writer
   dw_ipflin, // IPF writer (new linear output)
   dw_ipflin, // IPF writer (new linear output)
   dw_man,    // Man page writer
   dw_man,    // Man page writer
   dw_linrtf, // linear RTF writer
   dw_linrtf, // linear RTF writer

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio