Browse Source

* synchronize with trunk

git-svn-id: branches/unicodekvm@40297 -
nickysn 6 years ago
parent
commit
1bb1e20042
100 changed files with 849 additions and 686 deletions
  1. 11 1
      .gitattributes
  2. 4 0
      compiler/Makefile
  3. 6 1
      compiler/Makefile.fpc
  4. 4 3
      compiler/aarch64/aasmcpu.pas
  5. 0 2
      compiler/aarch64/aoptcpu.pas
  6. 0 4
      compiler/aarch64/aoptcpub.pas
  7. 1 4
      compiler/aarch64/cgcpu.pas
  8. 0 1
      compiler/aarch64/ncpucnv.pas
  9. 0 1
      compiler/aarch64/ncpuinl.pas
  10. 0 1
      compiler/aarch64/racpugas.pas
  11. 0 1
      compiler/aasmcnst.pas
  12. 28 2
      compiler/aasmtai.pas
  13. 40 11
      compiler/aggas.pas
  14. 6 6
      compiler/aoptobj.pas
  15. 12 1
      compiler/aoptutils.pas
  16. 13 2
      compiler/arm/aoptcpu.pas
  17. 0 4
      compiler/arm/aoptcpub.pas
  18. 24 4
      compiler/arm/cgcpu.pas
  19. 1 0
      compiler/arm/cpunode.pas
  20. 8 0
      compiler/arm/cpupi.pas
  21. 97 0
      compiler/arm/narmld.pas
  22. 7 0
      compiler/assemble.pas
  23. 15 15
      compiler/avr/aoptcpu.pas
  24. 0 4
      compiler/avr/aoptcpub.pas
  25. 1 1
      compiler/avr/cpubase.pas
  26. 101 97
      compiler/avr/raavr.pas
  27. 76 77
      compiler/cclasses.pas
  28. 2 2
      compiler/cfileutl.pas
  29. 10 2
      compiler/cgbase.pas
  30. 8 0
      compiler/cgobj.pas
  31. 9 2
      compiler/cutils.pas
  32. 1 1
      compiler/dbgdwarf.pas
  33. 3 3
      compiler/entfile.pas
  34. 8 1
      compiler/globals.pas
  35. 10 1
      compiler/globtype.pas
  36. 15 2
      compiler/htypechk.pas
  37. 8 223
      compiler/i386/aoptcpu.pas
  38. 0 4
      compiler/i386/aoptcpub.pas
  39. 8 1
      compiler/i386/cpupi.pas
  40. 3 3
      compiler/i386/n386flw.pas
  41. 0 4
      compiler/i8086/aoptcpub.pas
  42. 4 0
      compiler/i8086/cgcpu.pas
  43. 0 4
      compiler/jvm/aoptcpub.pas
  44. 3 3
      compiler/m68k/aoptcpu.pas
  45. 0 4
      compiler/m68k/aoptcpub.pas
  46. 5 5
      compiler/machoutils.pas
  47. 0 4
      compiler/mips/aoptcpub.pas
  48. 1 1
      compiler/msg/errorct.msg
  49. 1 1
      compiler/msg/errord.msg
  50. 1 1
      compiler/msg/errorda.msg
  51. 1 1
      compiler/msg/errordu.msg
  52. 1 1
      compiler/msg/errore.msg
  53. 1 1
      compiler/msg/errores.msg
  54. 1 1
      compiler/msg/errorf.msg
  55. 1 1
      compiler/msg/errorfi.msg
  56. 1 1
      compiler/msg/errorhe.msg
  57. 1 1
      compiler/msg/errorheu.msg
  58. 1 1
      compiler/msg/errorid.msg
  59. 1 1
      compiler/msg/erroriu.msg
  60. 1 1
      compiler/msg/errorn.msg
  61. 1 1
      compiler/msg/errorpl.msg
  62. 1 1
      compiler/msg/errorpli.msg
  63. 1 1
      compiler/msg/errorpt.msg
  64. 1 1
      compiler/msg/errorptu.msg
  65. 1 1
      compiler/msg/errorr.msg
  66. 1 1
      compiler/msg/errorru.msg
  67. 1 1
      compiler/msg/errorues.msg
  68. 1 1
      compiler/msgidx.inc
  69. 1 1
      compiler/msgtxt.inc
  70. 0 2
      compiler/nadd.pas
  71. 16 4
      compiler/ncal.pas
  72. 7 7
      compiler/ncgflw.pas
  73. 2 2
      compiler/ncgld.pas
  74. 15 20
      compiler/ncgrtti.pas
  75. 5 16
      compiler/nflw.pas
  76. 1 1
      compiler/ngtcon.pas
  77. 12 4
      compiler/ninl.pas
  78. 4 1
      compiler/nld.pas
  79. 2 2
      compiler/nutils.pas
  80. 0 1
      compiler/ogbase.pas
  81. 18 9
      compiler/omfbase.pas
  82. 1 1
      compiler/optbase.pas
  83. 1 0
      compiler/optdfa.pas
  84. 10 1
      compiler/options.pas
  85. 4 4
      compiler/optutils.pas
  86. 4 0
      compiler/owomflib.pas
  87. 1 1
      compiler/pass_2.pas
  88. 3 0
      compiler/pdecl.pas
  89. 1 2
      compiler/pdecsub.pas
  90. 48 31
      compiler/pdecvar.pas
  91. 0 4
      compiler/powerpc/aoptcpub.pas
  92. 0 4
      compiler/powerpc64/aoptcpub.pas
  93. 1 1
      compiler/ppu.pas
  94. 13 0
      compiler/procinfo.pas
  95. 93 25
      compiler/psub.pas
  96. 0 1
      compiler/rgobj.pas
  97. 2 0
      compiler/riscv/aasmcpu.pas
  98. 0 4
      compiler/riscv32/aoptcpub.pas
  99. 0 4
      compiler/riscv64/aoptcpub.pas
  100. 11 0
      compiler/scanner.pas

+ 11 - 1
.gitattributes

@@ -85,6 +85,7 @@ compiler/arm/narmcal.pas svneol=native#text/plain
 compiler/arm/narmcnv.pas svneol=native#text/plain
 compiler/arm/narmcon.pas svneol=native#text/plain
 compiler/arm/narminl.pas svneol=native#text/plain
+compiler/arm/narmld.pas svneol=native#text/pascal
 compiler/arm/narmmat.pas svneol=native#text/plain
 compiler/arm/narmmem.pas svneol=native#text/plain
 compiler/arm/narmset.pas svneol=native#text/plain
@@ -11093,6 +11094,13 @@ tests/tbf/tb0256.pp svneol=native#text/pascal
 tests/tbf/tb0257a.pp svneol=native#text/pascal
 tests/tbf/tb0257b.pp svneol=native#text/pascal
 tests/tbf/tb0258.pp svneol=native#text/pascal
+tests/tbf/tb0259.pp svneol=native#text/plain
+tests/tbf/tb0260.pp svneol=native#text/plain
+tests/tbf/tb0261.pp svneol=native#text/pascal
+tests/tbf/tb0262.pp svneol=native#text/pascal
+tests/tbf/tb0263.pp svneol=native#text/pascal
+tests/tbf/tb0264.pp svneol=native#text/pascal
+tests/tbf/tb0265.pp svneol=native#text/pascal
 tests/tbf/ub0115.pp svneol=native#text/plain
 tests/tbf/ub0149.pp svneol=native#text/plain
 tests/tbf/ub0158a.pp svneol=native#text/plain
@@ -11752,6 +11760,7 @@ tests/tbs/tb0649.pp -text svneol=native#text/pascal
 tests/tbs/tb0650.pp svneol=native#text/pascal
 tests/tbs/tb0651.pp svneol=native#text/pascal
 tests/tbs/tb0652.pp svneol=native#text/pascal
+tests/tbs/tb0653.pp svneol=native#text/plain
 tests/tbs/tb205.pp svneol=native#text/plain
 tests/tbs/tb610.pp svneol=native#text/pascal
 tests/tbs/tb613.pp svneol=native#text/plain
@@ -14685,6 +14694,7 @@ tests/webtbf/tw2739.pp svneol=native#text/plain
 tests/webtbf/tw2751.pp svneol=native#text/plain
 tests/webtbf/tw2752.pp svneol=native#text/plain
 tests/webtbf/tw2787.pp svneol=native#text/plain
+tests/webtbf/tw27880.pp svneol=native#text/pascal
 tests/webtbf/tw2795.pp svneol=native#text/plain
 tests/webtbf/tw28338.pp svneol=native#text/plain
 tests/webtbf/tw28355.pp svneol=native#text/plain
@@ -16059,7 +16069,6 @@ tests/webtbs/tw2780.pp svneol=native#text/plain
 tests/webtbs/tw27811.pp svneol=native#text/plain
 tests/webtbs/tw27832.pp svneol=native#text/plain
 tests/webtbs/tw2788.pp svneol=native#text/plain
-tests/webtbs/tw27880.pp svneol=native#text/plain
 tests/webtbs/tw2789.pp svneol=native#text/plain
 tests/webtbs/tw2794.pp svneol=native#text/plain
 tests/webtbs/tw27998.pp svneol=native#text/plain
@@ -16440,6 +16449,7 @@ tests/webtbs/tw3435.pp svneol=native#text/plain
 tests/webtbs/tw34380.pp svneol=native#text/plain
 tests/webtbs/tw3441.pp svneol=native#text/plain
 tests/webtbs/tw3443.pp svneol=native#text/plain
+tests/webtbs/tw34438.pp svneol=native#text/pascal
 tests/webtbs/tw3444.pp svneol=native#text/plain
 tests/webtbs/tw34442.pp svneol=native#text/plain
 tests/webtbs/tw3456.pp svneol=native#text/plain

+ 4 - 0
compiler/Makefile

@@ -4482,6 +4482,10 @@ fullcycle:
 	$(MAKE) distclean
 	$(MAKE) cycle
 	$(MAKE) ppuclean
+ifdef DOWPOCYCLE
+	$(MAKE) rtlclean
+	$(MAKE) rtl 'FPC=$(BASEDIR)/$(EXENAME)'
+endif
 ifndef EXCLUDE_80BIT_TARGETS
 	$(MAKE) $(filter-out $(PPC_TARGET),$(CYCLETARGETS)) 'FPC=$(BASEDIR)/$(EXENAME)'
 else

+ 6 - 1
compiler/Makefile.fpc

@@ -831,7 +831,8 @@ cvstest:
 #
 # 1. build a compiler using cycle
 # 2. remove all .ppufiles
-# 3. build all supported cross compilers except the
+# 3. clean and recompile rtl if DOWPOCYCLE is set
+# 4. build all supported cross compilers except the
 #    current PPC_TARGET which was already build
 # unless FPC_SUPPORT_X87_TYPES_ON_WIN64 is set,
 # win64 cannot compile i386 or i8086 compiler
@@ -852,6 +853,10 @@ fullcycle:
         $(MAKE) distclean
         $(MAKE) cycle
         $(MAKE) ppuclean
+ifdef DOWPOCYCLE
+        $(MAKE) rtlclean
+        $(MAKE) rtl 'FPC=$(BASEDIR)/$(EXENAME)'
+endif
 ifndef EXCLUDE_80BIT_TARGETS
         $(MAKE) $(filter-out $(PPC_TARGET),$(CYCLETARGETS)) 'FPC=$(BASEDIR)/$(EXENAME)'
 else

+ 4 - 3
compiler/aarch64/aasmcpu.pas

@@ -592,7 +592,6 @@ implementation
 
     function simple_ref_type(op: tasmop; size:tcgsize; oppostfix: toppostfix; const ref: treference): tsimplereftype;
       var
-        maxoffs: asizeint;
         accesssize: longint;
       begin
         result:=sr_internal_illegal;
@@ -922,8 +921,8 @@ implementation
 
 
     procedure BuildInsTabCache;
-      var
-        i : longint;
+//      var
+//        i : longint;
       begin
 (*        new(instabcache);
         FillChar(instabcache^,sizeof(tinstabcache),$ff);
@@ -1006,6 +1005,7 @@ implementation
 *)
 
     procedure insertpcrelativedata(list,listtoinsert : TAsmList);
+(*
       var
         curinspos,
         penalty,
@@ -1021,6 +1021,7 @@ implementation
         l : tasmlabel;
         doinsert,
         removeref : boolean;
+*)
       begin
 (*
         curdata:=TAsmList.create;

+ 0 - 2
compiler/aarch64/aoptcpu.pas

@@ -146,8 +146,6 @@ Implementation
 
 
   function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
-    var
-      next1: tai;
     begin
       result := false;
       if p.typ=ait_instruction then

+ 0 - 4
compiler/aarch64/aoptcpub.pas

@@ -76,10 +76,6 @@ Const
 
   MaxCh = 3;
 
-{ the maximum number of operands an instruction has }
-
-  MaxOps = 4;
-
 {Oper index of operand that contains the source (reference) with a load }
 {instruction                                                            }
 

+ 1 - 4
compiler/aarch64/cgcpu.pas

@@ -1127,18 +1127,15 @@ implementation
 
     procedure tcgaarch64.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister);
       var
-        bitsize,
-        signbit: longint;
+        bitsize: longint;
       begin
         if srcsize in [OS_64,OS_S64] then
           begin
             bitsize:=64;
-            signbit:=6;
           end
         else
           begin
             bitsize:=32;
-            signbit:=5;
           end;
         { source is 0 -> dst will have to become 255 }
         list.concat(taicpu.op_reg_const(A_CMP,src,0));

+ 0 - 1
compiler/aarch64/ncpucnv.pas

@@ -142,7 +142,6 @@ implementation
   procedure taarch64typeconvnode.second_int_to_bool;
     var
       resflags: tresflags;
-      hlabel: tasmlabel;
     begin
       if (nf_explicit in flags) and
          not(left.expectloc in [LOC_FLAGS,LOC_JUMP]) then

+ 0 - 1
compiler/aarch64/ncpuinl.pas

@@ -128,7 +128,6 @@ implementation
     procedure taarch64inlinenode.second_abs_long;
       var
         opsize : tcgsize;
-        hp : taicpu;
       begin
         secondpass(left);
         opsize:=def_cgsize(left.resultdef);

+ 0 - 1
compiler/aarch64/racpugas.pas

@@ -933,7 +933,6 @@ Unit racpugas;
         j  : longint;
         hs : string;
         maxlen : longint;
-        icond : tasmcond;
       Begin
         { making s a value parameter would break other assembler readers }
         hs:=s;

+ 0 - 1
compiler/aasmcnst.pas

@@ -1726,7 +1726,6 @@ implementation
    function ttai_typedconstbuilder.begin_dynarray_const(arrdef:tdef;var startlab:tasmlabel;out arrlengthloc:ttypedconstplaceholder):tasmlabofs;
      var
        dynarray_symofs: asizeint;
-       elesize: word;
      begin
        result.lab:=startlab;
        result.ofs:=0;

+ 28 - 2
compiler/aasmtai.pas

@@ -145,7 +145,11 @@ interface
           { offset of symbol's GOT slot in GOT }
           aitconst_got,
           { offset of symbol itself from GOT }
-          aitconst_gotoff_symbol
+          aitconst_gotoff_symbol,
+          { ARM TLS code }
+          aitconst_gottpoff,
+          aitconst_tpoff
+
         );
 
         tairealconsttype = (
@@ -852,11 +856,13 @@ interface
         { alignment for operator }
         tai_align_abstract = class(tai)
            aligntype : byte;   { 1 = no align, 2 = word align, 4 = dword align }
+           maxbytes  : byte;   { if needed bytes would be larger than maxbyes, alignment is ignored }
            fillsize  : byte;   { real size to fill }
            fillop    : byte;   { value to fill with - optional }
            use_op    : boolean;
            constructor Create(b:byte);virtual;
            constructor Create_op(b: byte; _op: byte);virtual;
+           constructor create_max(b: byte; max: byte);virtual;
            constructor Create_zeros(b:byte);
            constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
            procedure ppuwrite(ppufile:tcompilerppufile);override;
@@ -1757,7 +1763,7 @@ implementation
       end;
 
 
-    constructor tai_const.Create_rel_sym_offset(_typ: taiconst_type; _sym,_endsym: tasmsymbol; _ofs: int64);
+    constructor tai_const.Create_rel_sym_offset(_typ: taiconst_type; _sym, _endsym: tasmsymbol; _ofs: int64);
        begin
          self.create_sym_offset(_sym,_ofs);
          consttype:=_typ;
@@ -3093,6 +3099,7 @@ implementation
           fillsize:=0;
           fillop:=0;
           use_op:=false;
+          maxbytes:=aligntype;
        end;
 
 
@@ -3107,6 +3114,22 @@ implementation
           fillsize:=0;
           fillop:=_op;
           use_op:=true;
+          maxbytes:=aligntype;
+       end;
+
+
+     constructor tai_align_abstract.create_max(b : byte; max : byte);
+       begin
+          inherited Create;
+          typ:=ait_align;
+          if b in [1,2,4,8,16,32] then
+            aligntype := b
+          else
+            aligntype := 1;
+          maxbytes:=max;
+          fillsize:=0;
+          fillop:=0;
+          use_op:=false;
        end;
 
 
@@ -3121,6 +3144,7 @@ implementation
          use_op:=true;
          fillsize:=0;
          fillop:=0;
+         maxbytes:=aligntype;
        end;
 
 
@@ -3140,6 +3164,7 @@ implementation
         fillsize:=0;
         fillop:=ppufile.getbyte;
         use_op:=ppufile.getboolean;
+        maxbytes:=ppufile.getbyte;
       end;
 
 
@@ -3149,6 +3174,7 @@ implementation
         ppufile.putbyte(aligntype);
         ppufile.putbyte(fillop);
         ppufile.putboolean(use_op);
+        ppufile.putbyte(maxbytes);
       end;
 
 

+ 40 - 11
compiler/aggas.pas

@@ -347,9 +347,13 @@ implementation
             exit;
           end;
 
-        if (atype=sec_threadvar) and
-          (target_info.system in (systems_windows+systems_wince)) then
-          secname:='.tls';
+        if atype=sec_threadvar then
+          begin
+            if (target_info.system in (systems_windows+systems_wince)) then
+              secname:='.tls'
+            else if (target_info.system in systems_linux) then
+              secname:='.tbss';
+          end;
 
         { go32v2 stub only loads .text and .data sections, and allocates space for .bss.
           Thus, data which normally goes into .rodata and .rodata_norel sections must
@@ -620,9 +624,10 @@ implementation
         end;
 
 
-      procedure doalign(alignment: byte; use_op: boolean; fillop: byte; out last_align: longint;lasthp:tai);
+      procedure doalign(alignment: byte; use_op: boolean; fillop: byte; maxbytes: byte; out last_align: longint;lasthp:tai);
         var
           i: longint;
+          alignment64 : int64;
 {$ifdef m68k}
           instr : string;
 {$endif}
@@ -649,14 +654,33 @@ implementation
                   else
                     begin
 {$endif m68k}
-                  writer.AsmWrite(#9'.balign '+tostr(alignment));
-                  if use_op then
-                    writer.AsmWrite(','+tostr(fillop))
+                      alignment64:=alignment;
+                      if (maxbytes<>alignment) and ispowerof2(alignment64,i) then
+                        begin
+                          if use_op then
+                            begin
+                              writer.AsmWrite(#9'.p2align '+tostr(i)+','+tostr(fillop)+','+tostr(maxbytes));
+                              writer.AsmLn;
+                              writer.AsmWrite(#9'.p2align '+tostr(i-1)+','+tostr(fillop));
+                            end
+                          else
+                            begin
+                              writer.AsmWrite(#9'.p2align '+tostr(i)+',,'+tostr(maxbytes));
+                              writer.AsmLn;
+                              writer.AsmWrite(#9'.p2align '+tostr(i-1));
+                            end
+                        end
+                      else
+                        begin
+                          writer.AsmWrite(#9'.balign '+tostr(alignment));
+                          if use_op then
+                            writer.AsmWrite(','+tostr(fillop))
 {$ifdef x86}
-                  { force NOP as alignment op code }
-                  else if (LastSecType=sec_code) and (asminfo^.id<>as_solaris_as) then
-                    writer.AsmWrite(',0x90');
+                          { force NOP as alignment op code }
+                          else if (LastSecType=sec_code) and (asminfo^.id<>as_solaris_as) then
+                            writer.AsmWrite(',0x90');
 {$endif x86}
+                        end;
 {$ifdef m68k}
                     end;
 {$endif m68k}
@@ -746,7 +770,7 @@ implementation
 
            ait_align :
              begin
-               doalign(tai_align_abstract(hp).aligntype,tai_align_abstract(hp).use_op,tai_align_abstract(hp).fillop,last_align,lasthp);
+               doalign(tai_align_abstract(hp).aligntype,tai_align_abstract(hp).use_op,tai_align_abstract(hp).fillop,tai_align_abstract(hp).maxbytes,last_align,lasthp);
              end;
 
            ait_section :
@@ -923,6 +947,11 @@ implementation
                         WriteAixIntConst(tai_const(hp));
                       writer.AsmLn;
                     end;
+                 aitconst_gottpoff:
+                   begin
+                     writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(gottpoff)+(.-'+tai_const(hp).endsym.name+tostr_with_plus(tai_const(hp).symofs)+')');
+                     writer.Asmln;
+                   end;
 {$endif cpu64bitaddr}
                  aitconst_got:
                    begin

+ 6 - 6
compiler/aoptobj.pas

@@ -327,7 +327,7 @@ Unit AoptObj;
         function RegEndOfLife(reg: TRegister;p: taicpu): boolean;
 
         { removes p from asml, updates registers and replaces it by a valid value, if this is the case true is returned }
-        function RemoveCurrentP(var p : taicpu): boolean;
+        function RemoveCurrentP(var p : tai): boolean;
 
        { traces sucessive jumps to their final destination and sets it, e.g.
          je l1                je l3
@@ -828,7 +828,7 @@ Unit AoptObj;
               If (TInstr(p).oper[Count]^.typ = Top_Ref) Then
                 TmpResult := RefsEq(Ref, PInstr(p)^.oper[Count]^.ref^);
               Inc(Count);
-            Until (Count = MaxOps) or TmpResult;
+            Until (Count = max_operands) or TmpResult;
           End;
         RefInInstruction := TmpResult;
       End;
@@ -1289,7 +1289,7 @@ Unit AoptObj;
       end;
 
 
-    function TAOptObj.RemoveCurrentP(var p : taicpu) : boolean;
+    function TAOptObj.RemoveCurrentP(var p : tai) : boolean;
       var
         hp1 : tai;
       begin
@@ -1299,7 +1299,7 @@ Unit AoptObj;
         UpdateUsedRegs(tai(p.Next));
         AsmL.Remove(p);
         p.Free;
-        p:=taicpu(hp1);
+        p:=hp1;
       end;
 
 
@@ -1551,7 +1551,7 @@ Unit AoptObj;
                                   and (hp1.typ <> ait_jcatch)
 {$endif}
                                   do
-                              if not(hp1.typ in ([ait_label,ait_align]+skipinstr)) then
+                              if not(hp1.typ in ([ait_label]+skipinstr)) then
                                 begin
                                   if (hp1.typ = ait_instruction) and
                                      taicpu(hp1).is_jmp and
@@ -1560,7 +1560,7 @@ Unit AoptObj;
                                      TAsmLabel(JumpTargetOp(taicpu(hp1))^.ref^.symbol).decrefs;
                                   { don't kill start/end of assembler block,
                                     no-line-info-start/end etc }
-                                  if hp1.typ<>ait_marker then
+                                  if not(hp1.typ in [ait_align,ait_marker]) then
                                     begin
 {$ifdef cpudelayslot}
                                       if (hp1.typ=ait_instruction) and (taicpu(hp1).is_jmp) then

+ 12 - 1
compiler/aoptutils.pas

@@ -27,10 +27,13 @@ unit aoptutils;
   interface
 
     uses
-      aasmtai,aasmcpu;
+      cpubase,aasmtai,aasmcpu;
 
     function MatchOpType(const p : taicpu;type0: toptype) : Boolean;
     function MatchOpType(const p : taicpu;type0,type1 : toptype) : Boolean;
+{$if max_operands>2}
+    function MatchOpType(const p : taicpu; type0,type1,type2 : toptype) : Boolean;
+{$endif max_operands>2}
 
     { skips all labels and returns the next "real" instruction }
     function SkipLabels(hp: tai; var hp2: tai): boolean;
@@ -49,6 +52,14 @@ unit aoptutils;
       end;
 
 
+{$if max_operands>2}
+    function MatchOpType(const p : taicpu; type0,type1,type2 : toptype) : Boolean;
+      begin
+        Result:=(p.ops=3) and (p.oper[0]^.typ=type0) and (p.oper[1]^.typ=type1) and (p.oper[2]^.typ=type2);
+      end;
+{$endif max_operands>2}
+
+
     { skips all labels and returns the next "real" instruction }
     function SkipLabels(hp: tai; var hp2: tai): boolean;
       begin

+ 13 - 2
compiler/arm/aoptcpu.pas

@@ -1331,7 +1331,7 @@ Implementation
                         if taicpu(hp1).oper[1]^.ref^.index = taicpu(p).oper[0]^.reg then
                           taicpu(hp1).oper[1]^.ref^.index := taicpu(p).oper[1]^.reg;
 
-                        dealloc:=FindRegDeAlloc(taicpu(p).oper[1]^.reg, taicpu(p.Next));
+                        dealloc:=FindRegDeAlloc(taicpu(p).oper[1]^.reg, tai(p.Next));
                         if Assigned(dealloc) then
                           begin
                             asml.remove(dealloc);
@@ -2516,6 +2516,15 @@ Implementation
 
   { TODO : schedule also forward }
   { TODO : schedule distance > 1 }
+
+    { returns true if p might be a load of a pc relative tls offset }
+    function PossibleTLSLoad(const p: tai) : boolean;
+      begin
+        Result:=(p.typ=ait_instruction) and (taicpu(p).opcode=A_LDR) and (taicpu(p).oper[1]^.typ=top_ref) and (((taicpu(p).oper[1]^.ref^.base=NR_PC) and
+          (taicpu(p).oper[1]^.ref^.index<>NR_NO)) or ((taicpu(p).oper[1]^.ref^.base<>NR_NO) and
+          (taicpu(p).oper[1]^.ref^.index=NR_PC)));
+      end;
+
     var
       hp1,hp2,hp3,hp4,hp5,insertpos : tai;
       list : TAsmList;
@@ -2572,7 +2581,9 @@ Implementation
             ) and
             { if we modify the basereg AND the first instruction used that reg, we can not schedule }
             ((taicpu(hp1).oper[1]^.ref^.addressmode = AM_OFFSET) or
-             not(instructionLoadsFromReg(taicpu(hp1).oper[1]^.ref^.base,p))) then
+             not(instructionLoadsFromReg(taicpu(hp1).oper[1]^.ref^.base,p))) and
+            not(PossibleTLSLoad(p)) and
+            not(PossibleTLSLoad(hp1)) then
             begin
               hp3:=tai(p.Previous);
               hp5:=tai(p.next);

+ 0 - 4
compiler/arm/aoptcpub.pas

@@ -76,10 +76,6 @@ Const
 
   MaxCh = 3;
 
-{ the maximum number of operands an instruction has }
-
-  MaxOps = 4;
-
 {Oper index of operand that contains the source (reference) with a load }
 {instruction                                                            }
 

+ 24 - 4
compiler/arm/cgcpu.pas

@@ -107,13 +107,15 @@ unit cgcpu;
         { try to generate optimized 32 Bit multiplication, returns true if successful generated }
         function try_optimized_mul32_const_reg_reg(list: TAsmList; a: tcgint; src, dst: tregister) : boolean;
 
-        { clear out potential overflow bits from 8 or 16 bit operations  }
-        { the upper 24/16 bits of a register after an operation          }
+        { clear out potential overflow bits from 8 or 16 bit operations
+          the upper 24/16 bits of a register after an operation          }
         procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
 
         { mla for thumb requires that none of the registers is equal to r13/r15, this method ensures this }
         procedure safe_mla(list: TAsmList;op1,op2,op3,op4 : TRegister);
 
+
+        procedure g_maybe_tls_init(list : TAsmList); override;
       end;
 
       { tcgarm is shared between normal arm and thumb-2 }
@@ -241,6 +243,10 @@ unit cgcpu;
        procinfo,cpupi,
        paramgr;
 
+{ Range check must be disabled explicitly as conversions between signed and unsigned
+  32-bit values are done without explicit typecasts }
+{$R-}
+
 
     function get_fpu_postfix(def : tdef) : toppostfix;
       begin
@@ -2110,7 +2116,7 @@ unit cgcpu;
                    end;
                end;
              end;
-        end;
+          end;
       end;
 
 
@@ -2472,6 +2478,8 @@ unit cgcpu;
                     a_op_const_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg);
                 indirection_done:=true;
               end
+            else if ref.refaddr=addr_gottpoff then
+              current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_gottpoff,ref.symbol,ref.relsymbol,ref.offset))
             else if (cs_create_pic in current_settings.moduleswitches) then
               if (tf_pic_uses_got in target_info.flags) then
                 current_procinfo.aktlocaldata.concat(tai_const.Create_type_sym(aitconst_got,ref.symbol))
@@ -3267,6 +3275,15 @@ unit cgcpu;
       end;
 
 
+    procedure tbasecgarm.g_maybe_tls_init(list : TAsmList);
+      begin
+        list.concat(tai_regalloc.alloc(NR_R0,nil));
+        a_call_name(list,'fpc_read_tp',false);
+        a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_R0,current_procinfo.tlsoffset);
+        list.concat(tai_regalloc.dealloc(NR_R0,nil));
+      end;
+
+
     procedure tcg64farm.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
       begin
         case op of
@@ -5022,7 +5039,10 @@ unit cgcpu;
                 cg.a_label(current_procinfo.aktlocaldata,l);
                 tmpref.symboldata:=current_procinfo.aktlocaldata.last;
 
-                current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset));
+                if ref.refaddr=addr_gottpoff then
+                  current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_gottpoff,ref.symbol,ref.relsymbol,ref.offset))
+                else
+                  current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset));
 
                 { load consts entry }
                 tmpref.symbol:=l;

+ 1 - 0
compiler/arm/cpunode.pas

@@ -38,6 +38,7 @@ unit cpunode;
        narmcal,
        narmmat,
        narminl,
+       narmld,
        narmcnv,
        narmcon,
        narmset,

+ 8 - 0
compiler/arm/cpupi.pas

@@ -49,6 +49,8 @@ unit cpupi;
           procedure generate_parameter_info;override;
           procedure allocate_got_register(list : TAsmList);override;
           procedure postprocess_code;override;
+
+          procedure allocate_tls_register(list : TAsmList);override;
        end;
 
 
@@ -276,6 +278,12 @@ unit cpupi;
         finalizearmcode(aktproccode,aktlocaldata);
       end;
 
+
+    procedure tcpuprocinfo.allocate_tls_register(list: TAsmList);
+      begin
+        current_procinfo.tlsoffset:=cg.getaddressregister(list);
+      end;
+
 begin
    cprocinfo:=tcpuprocinfo;
 end.

+ 97 - 0
compiler/arm/narmld.pas

@@ -0,0 +1,97 @@
+{
+    Copyright (c) 1998-2018 by Florian Klaempfl
+
+    Generate arm assembler for load nodes
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit narmld;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      globtype,
+      symsym,
+      node,ncgld,pass_1,aasmbase;
+
+    type
+      tarmloadnode = class(tcgloadnode)
+         procedure generate_threadvar_access(gvs : tstaticvarsym); override;
+      end;
+
+
+implementation
+
+    uses
+      globals,verbose,
+      cgbase,cgobj,cgutils,
+      aasmdata,
+      systems,
+      symcpu,symdef,
+      nld,
+      cpubase,
+      parabase,
+      procinfo;
+
+{*****************************************************************************
+                            TI386LOADNODE
+*****************************************************************************}
+
+    procedure tarmloadnode.generate_threadvar_access(gvs: tstaticvarsym);
+      var
+        paraloc1 : tcgpara;
+        pd: tprocdef;
+        href: treference;
+        hregister : tregister;
+        handled: boolean;
+        l : TAsmLabel;
+      begin
+        handled:=false;
+        if tf_section_threadvars in target_info.flags then
+          begin
+            if target_info.system in [system_arm_linux] then
+              begin
+                if not(pi_uses_threadvar in current_procinfo.flags) then
+                  internalerror(2012012101);
+                current_asmdata.getjumplabel(l);
+                reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_DATA),-8,sizeof(AInt),[]);
+                href.refaddr:=addr_gottpoff;
+                href.relsymbol:=l;
+                hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+                cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
+                cg.a_label(current_asmdata.CurrAsmList,l);
+                reference_reset(href,0,[]);
+                href.base:=NR_PC;
+                href.index:=hregister;
+                hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+                cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
+                location.reference.base:=current_procinfo.tlsoffset;
+                location.reference.index:=hregister;
+                handled:=true;
+              end;
+          end;
+
+        if not handled then
+          inherited;
+      end;
+
+
+begin
+   cloadnode:=tarmloadnode;
+end.

+ 7 - 0
compiler/assemble.pas

@@ -1700,6 +1700,13 @@ Implementation
                      { here we must determine the fillsize which is used in pass2 }
                      Tai_align_abstract(hp).fillsize:=align(ObjData.CurrObjSec.Size,Tai_align_abstract(hp).aligntype)-
                        ObjData.CurrObjSec.Size;
+
+                     { maximum number of bytes for alignment exeeded? }
+                     if (Tai_align_abstract(hp).aligntype<>Tai_align_abstract(hp).maxbytes) and
+                       (Tai_align_abstract(hp).fillsize>Tai_align_abstract(hp).maxbytes) then
+                       Tai_align_abstract(hp).fillsize:=align(ObjData.CurrObjSec.Size,Byte(Tai_align_abstract(hp).aligntype div 2))-
+                         ObjData.CurrObjSec.Size;
+
                      ObjData.alloc(Tai_align_abstract(hp).fillsize);
                    end;
                end;

+ 15 - 15
compiler/avr/aoptcpu.pas

@@ -349,7 +349,7 @@ Implementation
 
                             DebugMsg('Peephole LdiMov/Cp2Ldi/Cpi performed', p);
 
-                            RemoveCurrentP(taicpu(p));
+                            RemoveCurrentP(p);
                           end;
                         ReleaseUsedRegs(TmpUsedRegs);
                       end;
@@ -541,7 +541,7 @@ Implementation
                       begin
                         DebugMsg('Redundant Andi removed', p);
 
-                        result:=RemoveCurrentP(taicpu(p));
+                        result:=RemoveCurrentP(p);
                       end;
                   end;
                 A_ADD:
@@ -552,7 +552,7 @@ Implementation
                     begin
                       DebugMsg('Peephole AddAdc2Add performed', p);
 
-                      result:=RemoveCurrentP(taicpu(p));
+                      result:=RemoveCurrentP(p);
                     end;
                   end;
                 A_SUB:
@@ -565,7 +565,7 @@ Implementation
 
                       taicpu(hp1).opcode:=A_SUB;
 
-                      result:=RemoveCurrentP(taicpu(p));
+                      result:=RemoveCurrentP(p);
                     end;
                   end;
                 A_CLR:
@@ -588,7 +588,7 @@ Implementation
                       begin
                         DebugMsg('Peephole ClrMov2Mov performed', p);
 
-                        result:=RemoveCurrentP(taicpu(p));
+                        result:=RemoveCurrentP(p);
                       end
                     { turn
                       clr rX
@@ -625,7 +625,7 @@ Implementation
                             dealloc.Free;
                           end;
 
-                        result:=RemoveCurrentP(taicpu(p));
+                        result:=RemoveCurrentP(p);
                       end;
                   end;
                 A_PUSH:
@@ -667,9 +667,9 @@ Implementation
 
                            taicpu(hp3).loadreg(1, taicpu(p).oper[0]^.reg);
 
-                           RemoveCurrentP(taicpu(p));
-                           RemoveCurrentP(taicpu(p));
-                           result:=RemoveCurrentP(taicpu(p));
+                           RemoveCurrentP(p);
+                           RemoveCurrentP(p);
+                           result:=RemoveCurrentP(p);
                          end
                        else
                          begin
@@ -757,7 +757,7 @@ Implementation
                           not(MatchInstruction(hp1,[A_CALL,A_RCALL])) then
                           begin
                             DebugMsg('Peephole Mov2Nop performed', p);
-                            result:=RemoveCurrentP(taicpu(p));
+                            result:=RemoveCurrentP(p);
                             ReleaseUsedRegs(TmpUsedRegs);
                             exit;
                           end;
@@ -807,7 +807,7 @@ Implementation
                         { p will be removed, update used register as we continue
                           with the next instruction after p }
 
-                        result:=RemoveCurrentP(taicpu(p));
+                        result:=RemoveCurrentP(p);
                       end
                     { remove
                       mov reg0,reg0
@@ -819,7 +819,7 @@ Implementation
                       begin
                         DebugMsg('Peephole RedundantMov performed', p);
 
-                        result:=RemoveCurrentP(taicpu(p));
+                        result:=RemoveCurrentP(p);
                       end
                     {
                       Turn
@@ -870,7 +870,7 @@ Implementation
                         asml.remove(hp2);
                         hp2.free;
 
-                        result:=RemoveCurrentP(taicpu(p));
+                        result:=RemoveCurrentP(p);
                       end
                     {
                       Turn
@@ -913,7 +913,7 @@ Implementation
                             dealloc.Free;
                           end;
 
-                        result:=RemoveCurrentP(taicpu(p));
+                        result:=RemoveCurrentP(p);
 
                         asml.remove(hp2);
                         hp2.free;
@@ -968,7 +968,7 @@ Implementation
                         begin
                           DebugMsg('Peephole MovMov2Mov performed', p);
 
-                          result:=RemoveCurrentP(taicpu(p));
+                          result:=RemoveCurrentP(p);
 
                           GetNextInstruction(hp1,hp1);
                           if not assigned(hp1) then

+ 0 - 4
compiler/avr/aoptcpub.pas

@@ -75,10 +75,6 @@ Const
 
   MaxCh = 2;
 
-{ the maximum number of operands an instruction has }
-
-  MaxOps = 2;
-
 {Oper index of operand that contains the source (reference) with a load }
 {instruction                                                            }
 

+ 1 - 1
compiler/avr/cpubase.pas

@@ -171,7 +171,7 @@ unit cpubase;
 *****************************************************************************}
 
     const
-      max_operands = 4;
+      max_operands = 2;
 
       maxintregs = 15;
       maxfpuregs = 0;

+ 101 - 97
compiler/avr/raavr.pas

@@ -58,204 +58,208 @@ unit raavr;
         Operands: array[0..max_operands-1] of TAVROpConstraint;
       end;
 
+{$PUSH}
+{$WARN 3177 off : Some fields coming after "$1" were not initialized}
   const
     AVRInstrConstraint: array[TAsmOp] of TAVRInstrConstraint =
       // A_NONE
-      ((numOperands: 0; Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+      ((numOperands: 0; Operands: ((typ: top_none), (typ: top_none))),
       // A_ADD
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
        // A_ADC
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
        // A_ADIW
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_even_24_30), (typ: top_const; max: 63; min: 0), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_even_24_30), (typ: top_const; max: 63; min: 0))),
        // A_SUB
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
        // A_SUBI
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
        // A_SBC
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
        // A_SBCI
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
        // A_SBRC
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 7; min: 0), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 7; min: 0))),
        // A_SBRS
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 7; min: 0), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 7; min: 0))),
        // A_SBIW
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_even_24_30), (typ: top_const; max: 63; min: 0), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_even_24_30), (typ: top_const; max: 63; min: 0))),
        // A_AND
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
        // A_ANDI
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
        // A_OR
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
        // A_ORI
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
        // A_EOR
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
        // A_COM
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
        // A_NEG
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
        // A_SBR
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
        // A_CBR
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
        // A_INC
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
        // A_DEC
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
        // A_TST
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
        // A_MUL
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
        // A_MULS
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_reg; rt: rt_16_31), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_reg; rt: rt_16_31))),
        // A_MULSU
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_23), (typ: top_reg; rt: rt_16_23), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_23), (typ: top_reg; rt: rt_16_23))),
        // A_FMUL
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_23), (typ: top_reg; rt: rt_16_23), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_23), (typ: top_reg; rt: rt_16_23))),
        // A_FMULS
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_23), (typ: top_reg; rt: rt_16_23), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_23), (typ: top_reg; rt: rt_16_23))),
        // A_FMULSU
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_23), (typ: top_reg; rt: rt_16_23), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_23), (typ: top_reg; rt: rt_16_23))),
        // A_RJMP
-       (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 2047; min: -2048), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 2047; min: -2048), (typ: top_reg; rt: rt_all))),
        // A_IJMP
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_EIJMP
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_JMP, max size depends on size op PC
-       (numOperands: (1 shl 1); Operands: ((typ: top_const; max: (1 shl 22 - 1); min: 0), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_const; max: (1 shl 22 - 1); min: 0), (typ: top_none))),
        // A_RCALL
-       (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 2047; min: -2048), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 2047; min: -2048), (typ: top_none))),
        // A_ICALL
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_EICALL
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_CALL, max size depends on size op PC
-       (numOperands: (1 shl 1); Operands: ((typ: top_const; max: (1 shl 22 - 1); min: 0), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_const; max: (1 shl 22 - 1); min: 0), (typ: top_none))),
        // A_RET
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_IRET
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_CPSE
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
        // A_CP
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
        // A_CPC
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
        // A_CPI
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
        // A_SBIC
-       (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 31; min: 0), (typ: top_const; max: 7; min: 0), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 31; min: 0), (typ: top_const; max: 7; min: 0))),
        // A_SBIS
-       (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 31; min: 0), (typ: top_const; max: 7; min: 0), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 31; min: 0), (typ: top_const; max: 7; min: 0))),
        // A_BRxx
-       (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 63; min: -64), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 63; min: -64), (typ: top_none))),
        // A_MOV
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
        // A_MOVW
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_even), (typ: top_reg; rt: rt_even), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_even), (typ: top_reg; rt: rt_even))),
        // A_LDI
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
        // A_LDS TODO: There are 2 versions with different machine codes and constant ranges. Could possibly distinguish based on size of PC?
        // Perhaps handle separately with a check on sub-architecture? Range check only important if smaller instruction code selected on larger arch
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 65535; min: 0), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 65535; min: 0))),
        // A_LD
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_XYZ; am: [AM_UNCHANGED, AM_POSTINCREMENT, AM_PREDRECEMENT]), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_XYZ; am: [AM_UNCHANGED, AM_POSTINCREMENT, AM_PREDRECEMENT]))),
        // A_LDD
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_YZ; am: [AM_UNCHANGED]; minconst: 0; maxconst: 63), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_YZ; am: [AM_UNCHANGED]; minconst: 0; maxconst: 63))),
        // A_STS TODO: See LDS above
-       (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 65535; min: 0), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 65535; min: 0), (typ: top_reg; rt: rt_all))),
        // A_ST
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_XYZ; am: [AM_UNCHANGED, AM_POSTINCREMENT, AM_PREDRECEMENT]), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_XYZ; am: [AM_UNCHANGED, AM_POSTINCREMENT, AM_PREDRECEMENT]), (typ: top_reg; rt: rt_all))),
        // A_STD
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_YZ; am: [AM_UNCHANGED]; minconst: 0; maxconst: 63), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_YZ; am: [AM_UNCHANGED]; minconst: 0; maxconst: 63), (typ: top_reg; rt: rt_all))),
        // A_LPM
-       (numOperands: (1 shl 0 + 1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_Z; am: [AM_UNCHANGED, AM_POSTINCREMENT]), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0 + 1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_Z; am: [AM_UNCHANGED, AM_POSTINCREMENT]))),
        // A_ELPM
-       (numOperands: (1 shl 0 + 1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_Z; am: [AM_UNCHANGED, AM_POSTINCREMENT]), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0 + 1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_Z; am: [AM_UNCHANGED, AM_POSTINCREMENT]))),
        // A_SPM
-       (numOperands: (1 shl 0 + 1 shl 1); Operands: ((typ: top_reg; rt: rt_Z; am: [AM_UNCHANGED, AM_POSTINCREMENT]), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0 + 1 shl 1); Operands: ((typ: top_reg; rt: rt_Z; am: [AM_UNCHANGED, AM_POSTINCREMENT]), (typ: top_none))),
        // A_IN
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 63; min: 0), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 63; min: 0))),
        // A_OUT
-       (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 63; min: 0), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 63; min: 0), (typ: top_reg; rt: rt_all))),
        // A_PUSH
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
        // A_POP
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
        // A_LSL
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
        // A_LSR
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
        // A_ROL
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
        // A_ROR
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
        // A_ASR
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
        // A_SWAP
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
        // A_BSET
-       (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 7; min: 0), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 7; min: 0), (typ: top_none))),
        // A_BCLR
-       (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 7; min: 0), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 7; min: 0), (typ: top_none))),
        // A_SBI
-       (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 32; min: 0), (typ: top_const; max: 7; min: 0), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 32; min: 0), (typ: top_const; max: 7; min: 0))),
        // A_CBI
-       (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 32; min: 0), (typ: top_const; max: 7; min: 0), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 32; min: 0), (typ: top_const; max: 7; min: 0))),
        // A_SEC
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_SEH
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_SEI
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_SEN
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_SER
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_none))),
        // A_SES
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_SET
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_SEV
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_SEZ
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_CLC
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_CLH
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_CLI
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_CLN
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_CLR
-       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
        // A_CLS
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_CLT
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_CLV
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_CLZ
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_BST
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 7; min: 0), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 7; min: 0))),
        // A_BLD
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 7; min: 0), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 7; min: 0))),
        // A_BREAK
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_NOP
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_SLEEP
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_WDR
-       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none), (typ: top_none), (typ: top_none))),
+       (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
        // A_XCH
-       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_Z), (typ: top_reg; rt: rt_all), (typ: top_none), (typ: top_none)))
+       (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_Z), (typ: top_reg; rt: rt_all)))
        );
+{$POP}
+
 
   implementation
     uses

+ 76 - 77
compiler/cclasses.pas

@@ -1053,6 +1053,11 @@ begin
   FFreeObjects := True;
 end;
 
+function TFPObjectList.IndexOf(AObject: TObject): Integer;
+begin
+  Result := FList.IndexOf(Pointer(AObject));
+end;
+
 function TFPObjectList.GetCount: integer;
 begin
   Result := FList.Count;
@@ -1125,11 +1130,6 @@ begin
   end;
 end;
 
-function TFPObjectList.IndexOf(AObject: TObject): Integer;
-begin
-  Result := FList.IndexOf(Pointer(AObject));
-end;
-
 function TFPObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
 var
   I : Integer;
@@ -1764,72 +1764,6 @@ begin
 end;
 
 
-{*****************************************************************************
-                               TFPHashObject
-*****************************************************************************}
-
-procedure TFPHashObject.InternalChangeOwner(HashObjectList:TFPHashObjectList;const s:TSymStr);
-var
-  Index : integer;
-begin
-  FOwner:=HashObjectList;
-  Index:=HashObjectList.Add(s,Self);
-  FStrIndex:=HashObjectList.List.List^[Index].StrIndex;
-end;
-
-
-constructor TFPHashObject.CreateNotOwned;
-begin
-  FStrIndex:=-1;
-end;
-
-
-constructor TFPHashObject.Create(HashObjectList:TFPHashObjectList;const s:TSymStr);
-begin
-  InternalChangeOwner(HashObjectList,s);
-end;
-
-
-procedure TFPHashObject.ChangeOwner(HashObjectList:TFPHashObjectList);
-begin
-  InternalChangeOwner(HashObjectList,PSymStr(@FOwner.List.Strs[FStrIndex])^);
-end;
-
-
-procedure TFPHashObject.ChangeOwnerAndName(HashObjectList:TFPHashObjectList;const s:TSymStr);
-begin
-  InternalChangeOwner(HashObjectList,s);
-end;
-
-
-procedure TFPHashObject.Rename(const ANewName:TSymStr);
-var
-  Index : integer;
-begin
-  Index:=FOwner.Rename(PSymStr(@FOwner.List.Strs[FStrIndex])^,ANewName);
-  if Index<>-1 then
-    FStrIndex:=FOwner.List.List^[Index].StrIndex;
-end;
-
-
-function TFPHashObject.GetName:TSymStr;
-begin
-  if FOwner<>nil then
-    Result:=PSymStr(@FOwner.List.Strs[FStrIndex])^
-  else
-    Result:='';
-end;
-
-
-function TFPHashObject.GetHash:Longword;
-begin
-  if FOwner<>nil then
-    Result:=FPHash(PSymStr(@FOwner.List.Strs[FStrIndex])^)
-  else
-    Result:=$ffffffff;
-end;
-
-
 {*****************************************************************************
             TFPHashObjectList (Copied from rtl/objpas/classes/lists.inc)
 *****************************************************************************}
@@ -1862,6 +1796,11 @@ begin
   FHashList.Clear;
 end;
 
+function TFPHashObjectList.IndexOf(AObject: TObject): Integer;
+begin
+  Result := FHashList.IndexOf(Pointer(AObject));
+end;
+
 function TFPHashObjectList.GetCount: integer;
 begin
   Result := FHashList.Count;
@@ -1944,12 +1883,6 @@ begin
     end;
 end;
 
-function TFPHashObjectList.IndexOf(AObject: TObject): Integer;
-begin
-  Result := FHashList.IndexOf(Pointer(AObject));
-end;
-
-
 function TFPHashObjectList.Find(const s:TSymStr): TObject;
 begin
   result:=TObject(FHashList.Find(s));
@@ -2031,6 +1964,72 @@ begin
 end;
 
 
+{*****************************************************************************
+                               TFPHashObject
+*****************************************************************************}
+
+procedure TFPHashObject.InternalChangeOwner(HashObjectList:TFPHashObjectList;const s:TSymStr);
+var
+  Index : integer;
+begin
+  FOwner:=HashObjectList;
+  Index:=HashObjectList.Add(s,Self);
+  FStrIndex:=HashObjectList.List.List^[Index].StrIndex;
+end;
+
+
+constructor TFPHashObject.CreateNotOwned;
+begin
+  FStrIndex:=-1;
+end;
+
+
+constructor TFPHashObject.Create(HashObjectList:TFPHashObjectList;const s:TSymStr);
+begin
+  InternalChangeOwner(HashObjectList,s);
+end;
+
+
+procedure TFPHashObject.ChangeOwner(HashObjectList:TFPHashObjectList);
+begin
+  InternalChangeOwner(HashObjectList,PSymStr(@FOwner.List.Strs[FStrIndex])^);
+end;
+
+
+procedure TFPHashObject.ChangeOwnerAndName(HashObjectList:TFPHashObjectList;const s:TSymStr);
+begin
+  InternalChangeOwner(HashObjectList,s);
+end;
+
+
+procedure TFPHashObject.Rename(const ANewName:TSymStr);
+var
+  Index : integer;
+begin
+  Index:=FOwner.Rename(PSymStr(@FOwner.List.Strs[FStrIndex])^,ANewName);
+  if Index<>-1 then
+    FStrIndex:=FOwner.List.List^[Index].StrIndex;
+end;
+
+
+function TFPHashObject.GetName:TSymStr;
+begin
+  if FOwner<>nil then
+    Result:=PSymStr(@FOwner.List.Strs[FStrIndex])^
+  else
+    Result:='';
+end;
+
+
+function TFPHashObject.GetHash:Longword;
+begin
+  if FOwner<>nil then
+    Result:=FPHash(PSymStr(@FOwner.List.Strs[FStrIndex])^)
+  else
+    Result:=$ffffffff;
+end;
+
+
 {****************************************************************************
                              TLinkedListItem
  ****************************************************************************}

+ 2 - 2
compiler/cfileutl.pas

@@ -146,7 +146,7 @@ interface
 {$NOTE TODO Amiga: implement PathConv() in System unit, which works with AnsiString}
 function Unix2AmigaPath(path: ShortString): ShortString; external name 'PATHCONV';
 {$ELSE}
-function Unix2AmigaPath(path: String): String;{$IFDEF USEINLINE}inline;{$ENDIF}
+function Unix2AmigaPath(path: String): String;
 {$ENDIF}
 
 {$if FPC_FULLVERSION < 20701}
@@ -191,7 +191,7 @@ implementation
 {$IFNDEF HASAMIGA}
 { Stub function for Unix2Amiga Path conversion functionality, only available in
   Amiga/MorphOS RTL. I'm open for better solutions. (KB) }
-function Unix2AmigaPath(path: String): String;{$IFDEF USEINLINE}inline;{$ENDIF}
+function Unix2AmigaPath(path: String): String;
 begin
   Unix2AmigaPath:=path;
 end;

+ 10 - 2
compiler/cgbase.pas

@@ -63,8 +63,6 @@ interface
        TCGNonRefLoc=low(TCGLoc)..pred(LOC_CREFERENCE);
        TCGRefLoc=LOC_CREFERENCE..LOC_REFERENCE;
 
-       { since we have only 16bit offsets, we need to be able to specify the high
-         and lower 16 bits of the address of a symbol of up to 64 bit }
        trefaddr = (
          addr_no,
          addr_full,
@@ -72,6 +70,8 @@ interface
          addr_pic_no_got
          {$IF defined(POWERPC) or defined(POWERPC64) or defined(SPARC) or defined(MIPS) or defined(SPARC64)}
          ,
+         { since we have only 16bit offsets, we need to be able to specify the high
+           and lower 16 bits of the address of a symbol of up to 64 bit }
          addr_low,         // bits 48-63
          addr_high,        // bits 32-47
          {$IF defined(POWERPC64)}
@@ -122,6 +122,14 @@ interface
          ,addr_gdop_hix22
          ,addr_gdop_lox22
          {$endif SPARC64}
+         {$IFDEF ARM}
+         ,addr_gottpoff
+         ,addr_tpoff
+         {$ENDIF}
+         {$IFDEF i386}
+         ,addr_ntpoff
+         ,addr_tlsgd
+         {$ENDIF}
          );
 
 

+ 8 - 0
compiler/cgobj.pas

@@ -437,6 +437,8 @@ unit cgobj;
 
           { initialize the pic/got register }
           procedure g_maybe_got_init(list: TAsmList); virtual;
+          { initialize the tls register if needed }
+          procedure g_maybe_tls_init(list : TAsmList); virtual;
           { allocallcpuregisters, a_call_name, deallocallcpuregisters sequence }
           procedure g_call(list: TAsmList; const s: string);
           { Generate code to exit an unwind-protected region. The default implementation
@@ -2781,6 +2783,12 @@ implementation
       begin
       end;
 
+
+    procedure tcg.g_maybe_tls_init(list: TAsmList);
+      begin
+      end;
+
+
     procedure tcg.g_call(list: TAsmList;const s: string);
       begin
         allocallcpuregisters(list);

+ 9 - 2
compiler/cutils.pas

@@ -144,7 +144,8 @@ interface
 
     { allocates mem for a copy of s, copies s to this mem and returns }
     { a pointer to this mem                                           }
-    function stringdup(const s : string) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
+    function stringdup(const s : shortstring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
+    function stringdup(const s : ansistring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
 
     {# Allocates memory for the string @var(s) and copies s as zero
        terminated string to that allocated memory and returns a pointer
@@ -1221,13 +1222,19 @@ implementation
       end;
 
 
-    function stringdup(const s : string) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
+    function stringdup(const s : shortstring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
       begin
          getmem(result,length(s)+1);
          result^:=s;
       end;
 
 
+    function stringdup(const s : ansistring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
+      begin
+         getmem(result,length(s)+1);
+         result^:=s;
+      end;
+
     function CompareStr(const S1, S2: string): Integer;
       var
         count, count1, count2: integer;

+ 1 - 1
compiler/dbgdwarf.pas

@@ -2496,7 +2496,7 @@ implementation
             sl_absolutetype,
             sl_typeconv:
               begin
-                currdef:=tfieldvarsym(symlist^.sym).vardef;
+                currdef:=symlist^.def;
                 { ignore, these don't change the address }
               end;
             sl_vec:

+ 3 - 3
compiler/entfile.pas

@@ -196,8 +196,8 @@ type
     compiler : word;
     cpu      : word;
     target   : word;
-    flags    : longint;
-    size     : longint; { size of the ppufile without header }
+    flags    : dword;
+    size     : dword; { size of the ppufile without header }
   end;
   pentryheader=^tentryheader;
 
@@ -668,7 +668,7 @@ begin
    end;
   if bufsize-bufidx>=sizeof(dword) then
     begin
-      result:=Unaligned(plongint(@buf[bufidx])^);
+      result:=Unaligned(pdword(@buf[bufidx])^);
       inc(bufidx,sizeof(longint));
     end
   else

+ 8 - 1
compiler/globals.pas

@@ -164,6 +164,8 @@ interface
 
          disabledircache : boolean;
 
+         tlsmodel : ttlsmodel;
+
 {$if defined(i8086)}
          x86memorymodel  : tx86memorymodel;
 {$endif defined(i8086)}
@@ -404,6 +406,9 @@ interface
           procalign : 0;
           loopalign : 0;
           jumpalign : 0;
+          jumpalignmax    : 0;
+          coalescealign   : 0;
+          coalescealignmax: 0;
           constalignmin : 0;
           constalignmax : 0;
           varalignmin : 0;
@@ -553,6 +558,8 @@ interface
         minfpconstprec : s32real;
 
         disabledircache : false;
+
+        tlsmodel : tlsm_none;
 {$if defined(i8086)}
         x86memorymodel : mm_small;
 {$endif defined(i8086)}
@@ -1417,7 +1424,7 @@ implementation
        if localexepath='' then
         begin
           hs1 := ExtractFileName(exeName);
-          ChangeFileExt(hs1,source_info.exeext);
+	  hs1 := ChangeFileExt(hs1,source_info.exeext);
 {$ifdef macos}
           FindFile(hs1,GetEnvironmentVariable('Commands'),false,localExepath);
 {$else macos}

+ 10 - 1
compiler/globtype.pas

@@ -700,10 +700,19 @@ interface
            for i8086 cpu huge memory model,
            as this changes SP register it requires special handling
            to restore DS segment register  }
-         pi_has_open_array_parameter
+         pi_has_open_array_parameter,
+         { subroutine uses threadvars }
+         pi_uses_threadvar
        );
        tprocinfoflags=set of tprocinfoflag;
 
+       ttlsmodel = (tlsm_none,
+         { elf tls model: works for all kind of code and thread vars }
+         tlsm_general,
+         { elf tls model: works only if the thread vars are declared and used in the same executable }
+         tlsm_local
+       );
+
     type
       { float types -- warning, this enum/order is used internally by the RTL
         as well in rtl/inc/real2str.inc }

+ 15 - 2
compiler/htypechk.pas

@@ -183,7 +183,7 @@ interface
 
     { sets varsym varstate field correctly }
     type
-      tvarstateflag = (vsf_must_be_valid,vsf_use_hints);
+      tvarstateflag = (vsf_must_be_valid,vsf_use_hints,vsf_use_hint_for_string_result);
       tvarstateflags = set of tvarstateflag;
     procedure set_varstate(p:tnode;newstate:tvarstate;varstateflags:tvarstateflags);
 
@@ -1299,7 +1299,20 @@ implementation
                                begin
                                  if (vo_is_funcret in hsym.varoptions) then
                                    begin
-                                     if (vsf_use_hints in varstateflags) then
+                                     { An uninitialized function Result of a managed type needs special handling.
+                                       When passing it as a var parameter a warning need to be emitted, since a user
+                                       may expect Result to be empty (nil) by default as it happens with local vars
+                                       of a managed type. But this is not true for Result and may lead to serious issues.
+
+                                       The only exception is SetLength(Result, ?) for a string Result. A user always
+                                       expects undefined contents of the string after calling SetLength(). In such
+                                       case a hint need to be emitted.
+                                     }
+                                     if is_managed_type(hsym.vardef) then
+                                       if not ( is_string(hsym.vardef) and (vsf_use_hint_for_string_result in varstateflags) ) then
+                                         exclude(varstateflags,vsf_use_hints);
+
+                                     if vsf_use_hints in varstateflags then
                                        begin
                                          if is_managed_type(hsym.vardef) then
                                            CGMessagePos(p.fileinfo,sym_h_managed_function_result_uninitialized)

+ 8 - 223
compiler/i386/aoptcpu.pas

@@ -152,9 +152,7 @@ end;
 
 procedure TCPUAsmOptimizer.PrePeepHoleOpts;
 var
-  p,hp1: tai;
-  l: aint;
-  tmpRef: treference;
+  p: tai;
 begin
   p := BlockStart;
   while (p <> BlockEnd) Do
@@ -169,205 +167,8 @@ begin
               end;
             case taicpu(p).opcode Of
               A_IMUL:
-                {changes certain "imul const, %reg"'s to lea sequences}
-                begin
-                  if (taicpu(p).oper[0]^.typ = Top_Const) and
-                     (taicpu(p).oper[1]^.typ = Top_Reg) and
-                     (taicpu(p).opsize = S_L) then
-                    if (taicpu(p).oper[0]^.val = 1) then
-                      if (taicpu(p).ops = 2) then
-                       {remove "imul $1, reg"}
-                        begin
-                          hp1 := tai(p.Next);
-                          asml.remove(p);
-                          p.free;
-                          p := hp1;
-                          continue;
-                        end
-                      else
-                       {change "imul $1, reg1, reg2" to "mov reg1, reg2"}
-                        begin
-                          hp1 := taicpu.Op_Reg_Reg(A_MOV, S_L, taicpu(p).oper[1]^.reg,taicpu(p).oper[2]^.reg);
-                          InsertLLItem(p.previous, p.next, hp1);
-                          p.free;
-                          p := hp1;
-                        end
-                    else if
-                     ((taicpu(p).ops <= 2) or
-                      (taicpu(p).oper[2]^.typ = Top_Reg)) and
-                     (taicpu(p).oper[0]^.val <= 12) and
-                     not(cs_opt_size in current_settings.optimizerswitches) and
-                     (not(GetNextInstruction(p, hp1)) or
-                       {GetNextInstruction(p, hp1) and}
-                       not((tai(hp1).typ = ait_instruction) and
-                           ((taicpu(hp1).opcode=A_Jcc) and
-                            (taicpu(hp1).condition in [C_O,C_NO])))) then
-                      begin
-                        reference_reset(tmpref,1,[]);
-                        case taicpu(p).oper[0]^.val Of
-                          3: begin
-                             {imul 3, reg1, reg2 to
-                                lea (reg1,reg1,2), reg2
-                              imul 3, reg1 to
-                                lea (reg1,reg1,2), reg1}
-                               TmpRef.base := taicpu(p).oper[1]^.reg;
-                               TmpRef.index := taicpu(p).oper[1]^.reg;
-                               TmpRef.ScaleFactor := 2;
-                               if (taicpu(p).ops = 2) then
-                                 hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg)
-                               else
-                                 hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
-                               InsertLLItem(p.previous, p.next, hp1);
-                               p.free;
-                               p := hp1;
-                            end;
-                         5: begin
-                            {imul 5, reg1, reg2 to
-                               lea (reg1,reg1,4), reg2
-                             imul 5, reg1 to
-                               lea (reg1,reg1,4), reg1}
-                              TmpRef.base := taicpu(p).oper[1]^.reg;
-                              TmpRef.index := taicpu(p).oper[1]^.reg;
-                              TmpRef.ScaleFactor := 4;
-                              if (taicpu(p).ops = 2) then
-                                hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg)
-                              else
-                                hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
-                              InsertLLItem(p.previous, p.next, hp1);
-                              p.free;
-                              p := hp1;
-                            end;
-                         6: begin
-                            {imul 6, reg1, reg2 to
-                               lea (,reg1,2), reg2
-                               lea (reg2,reg1,4), reg2
-                             imul 6, reg1 to
-                               lea (reg1,reg1,2), reg1
-                               add reg1, reg1}
-                              if (current_settings.optimizecputype <= cpu_386) then
-                                begin
-                                  TmpRef.index := taicpu(p).oper[1]^.reg;
-                                  if (taicpu(p).ops = 3) then
-                                    begin
-                                      TmpRef.base := taicpu(p).oper[2]^.reg;
-                                      TmpRef.ScaleFactor := 4;
-                                      hp1 :=  taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
-                                    end
-                                  else
-                                    begin
-                                      hp1 :=  taicpu.op_reg_reg(A_ADD, S_L,
-                                        taicpu(p).oper[1]^.reg,taicpu(p).oper[1]^.reg);
-                                    end;
-                                  InsertLLItem(p, p.next, hp1);
-                                  reference_reset(tmpref,2,[]);
-                                  TmpRef.index := taicpu(p).oper[1]^.reg;
-                                  TmpRef.ScaleFactor := 2;
-                                  if (taicpu(p).ops = 3) then
-                                    begin
-                                      TmpRef.base := NR_NO;
-                                      hp1 :=  taicpu.op_ref_reg(A_LEA, S_L, TmpRef,
-                                        taicpu(p).oper[2]^.reg);
-                                    end
-                                  else
-                                    begin
-                                      TmpRef.base := taicpu(p).oper[1]^.reg;
-                                      hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
-                                    end;
-                                  InsertLLItem(p.previous, p.next, hp1);
-                                  p.free;
-                                  p := tai(hp1.next);
-                                end
-                            end;
-                          9: begin
-                             {imul 9, reg1, reg2 to
-                                lea (reg1,reg1,8), reg2
-                              imul 9, reg1 to
-                                lea (reg1,reg1,8), reg1}
-                               TmpRef.base := taicpu(p).oper[1]^.reg;
-                               TmpRef.index := taicpu(p).oper[1]^.reg;
-                               TmpRef.ScaleFactor := 8;
-                               if (taicpu(p).ops = 2) then
-                                 hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg)
-                               else
-                                 hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
-                               InsertLLItem(p.previous, p.next, hp1);
-                               p.free;
-                               p := hp1;
-                             end;
-                         10: begin
-                            {imul 10, reg1, reg2 to
-                               lea (reg1,reg1,4), reg2
-                               add reg2, reg2
-                             imul 10, reg1 to
-                               lea (reg1,reg1,4), reg1
-                               add reg1, reg1}
-                               if (current_settings.optimizecputype <= cpu_386) then
-                                 begin
-                                   if (taicpu(p).ops = 3) then
-                                     hp1 :=  taicpu.op_reg_reg(A_ADD, S_L,
-                                       taicpu(p).oper[2]^.reg,taicpu(p).oper[2]^.reg)
-                                   else
-                                     hp1 := taicpu.op_reg_reg(A_ADD, S_L,
-                                       taicpu(p).oper[1]^.reg,taicpu(p).oper[1]^.reg);
-                                   InsertLLItem(p, p.next, hp1);
-                                   TmpRef.base := taicpu(p).oper[1]^.reg;
-                                   TmpRef.index := taicpu(p).oper[1]^.reg;
-                                   TmpRef.ScaleFactor := 4;
-                                   if (taicpu(p).ops = 3) then
-                                      hp1 :=  taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg)
-                                    else
-                                      hp1 :=  taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
-                                   InsertLLItem(p.previous, p.next, hp1);
-                                   p.free;
-                                   p := tai(hp1.next);
-                                 end
-                             end;
-                         12: begin
-                            {imul 12, reg1, reg2 to
-                               lea (,reg1,4), reg2
-                               lea (reg2,reg1,8), reg2
-                             imul 12, reg1 to
-                               lea (reg1,reg1,2), reg1
-                               lea (,reg1,4), reg1}
-                               if (current_settings.optimizecputype <= cpu_386)
-                                 then
-                                   begin
-                                     TmpRef.index := taicpu(p).oper[1]^.reg;
-                                     if (taicpu(p).ops = 3) then
-                                       begin
-                                         TmpRef.base := taicpu(p).oper[2]^.reg;
-                                         TmpRef.ScaleFactor := 8;
-                                         hp1 :=  taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
-                                       end
-                                     else
-                                       begin
-                                         TmpRef.base := NR_NO;
-                                         TmpRef.ScaleFactor := 4;
-                                         hp1 :=  taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
-                                       end;
-                                     InsertLLItem(p, p.next, hp1);
-                                     reference_reset(tmpref,2,[]);
-                                     TmpRef.index := taicpu(p).oper[1]^.reg;
-                                     if (taicpu(p).ops = 3) then
-                                       begin
-                                         TmpRef.base := NR_NO;
-                                         TmpRef.ScaleFactor := 4;
-                                         hp1 :=  taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
-                                       end
-                                     else
-                                       begin
-                                         TmpRef.base := taicpu(p).oper[1]^.reg;
-                                         TmpRef.ScaleFactor := 2;
-                                         hp1 :=  taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
-                                       end;
-                                     InsertLLItem(p.previous, p.next, hp1);
-                                     p.free;
-                                     p := tai(hp1.next);
-                                   end
-                             end
-                        end;
-                      end;
-                end;
+                if PrePeepholeOptIMUL(p) then
+                  Continue;
               A_SAR,A_SHR:
                 if PrePeepholeOptSxx(p) then
                   continue;
@@ -404,10 +205,6 @@ var
   hp3,hp4: tai;
   v:aint;
 
-  TmpRef: TReference;
-
-  TmpBool1, TmpBool2: Boolean;
-
   function GetFinalDestination(asml: TAsmList; hp: taicpu; level: longint): boolean;
   {traces sucessive jumps to their final destination and sets it, e.g.
    je l1                je l3
@@ -524,18 +321,18 @@ begin
             { Handle Jmp Optimizations }
             if taicpu(p).is_jmp then
               begin
-      {the following if-block removes all code between a jmp and the next label,
-        because it can never be executed}
+                { the following if-block removes all code between a jmp and the next label,
+                  because it can never be executed }
                 if (taicpu(p).opcode = A_JMP) then
                   begin
                     hp2:=p;
                     while GetNextInstruction(hp2, hp1) and
                           (hp1.typ <> ait_label) do
-                      if not(hp1.typ in ([ait_label,ait_align]+skipinstr)) then
+                      if not(hp1.typ in ([ait_label]+skipinstr)) then
                         begin
                           { don't kill start/end of assembler block,
                             no-line-info-start/end etc }
-                          if hp1.typ<>ait_marker then
+                          if not(hp1.typ in [ait_align,ait_marker]) then
                             begin
                               asml.remove(hp1);
                               hp1.free;
@@ -596,18 +393,6 @@ begin
             else
             { All other optimizes }
               begin
-                for l := 0 to taicpu(p).ops-1 Do
-                  if (taicpu(p).oper[l]^.typ = top_ref) then
-                    With taicpu(p).oper[l]^.ref^ Do
-                      begin
-                        if (base = NR_NO) and
-                           (index <> NR_NO) and
-                           (scalefactor in [0,1]) then
-                          begin
-                            base := index;
-                            index := NR_NO
-                          end
-                      end;
                 case taicpu(p).opcode Of
                   A_AND:
                     if OptPass1And(p) then
@@ -1012,7 +797,7 @@ end;
 
 procedure TCPUAsmOptimizer.PostPeepHoleOpts;
 var
-  p,hp1,hp2: tai;
+  p,hp1: tai;
 begin
   p := BlockStart;
   ClearUsedRegs;

+ 0 - 4
compiler/i386/aoptcpub.pas

@@ -70,10 +70,6 @@ Const
 
   MaxCh = 3;
 
-{ the maximum number of operands an instruction has }
-
-  MaxOps = 3;
-
 {Oper index of operand that contains the source (reference) with a load }
 {instruction                                                            }
 

+ 8 - 1
compiler/i386/cpupi.pas

@@ -95,11 +95,18 @@ unit cpupi;
           para_stack_size := 0;
       end;
 
+
     procedure tcpuprocinfo.allocate_got_register(list: tasmlist);
       begin
         if (cs_create_pic in current_settings.moduleswitches) then
           begin
-            got := cg.getaddressregister(list);
+            if pi_uses_threadvar in flags then
+              begin
+                cg.getcpuregister(list,NR_EBX);
+                got := NR_EBX;
+              end
+            else
+              got := cg.getaddressregister(list);
           end;
       end;
 

+ 3 - 3
compiler/i386/n386flw.pas

@@ -44,7 +44,7 @@ interface
     ti386tryfinallynode=class(tcgtryfinallynode)
       finalizepi: tcgprocinfo;
       constructor create(l,r:TNode);override;
-      constructor create_implicit(l,r,_t1:TNode);override;
+      constructor create_implicit(l,r:TNode);override;
       function pass_1: tnode;override;
       function simplify(forinline: boolean): tnode;override;
       procedure pass_generate_code;override;
@@ -183,9 +183,9 @@ constructor ti386tryfinallynode.create(l, r: TNode);
     include(finalizepi.flags,pi_uses_exceptions);
   end;
 
-constructor ti386tryfinallynode.create_implicit(l, r, _t1: TNode);
+constructor ti386tryfinallynode.create_implicit(l, r: TNode);
   begin
-    inherited create_implicit(l, r, _t1);
+    inherited create_implicit(l, r);
     if (target_info.system<>system_i386_win32) then
       exit;
 

+ 0 - 4
compiler/i8086/aoptcpub.pas

@@ -70,10 +70,6 @@ Const
 
   MaxCh = 3;
 
-{ the maximum number of operands an instruction has }
-
-  MaxOps = 3;
-
 {Oper index of operand that contains the source (reference) with a load }
 {instruction                                                            }
 

+ 4 - 0
compiler/i8086/cgcpu.pas

@@ -121,6 +121,10 @@ unit cgcpu;
        tgobj,
        hlcgobj;
 
+{ Range check must be disabled explicitly as the code uses
+  implicit typecast to aint troughout }
+{$R-}
+
     function use_push(const cgpara:tcgpara):boolean;
       begin
         result:=(not paramanager.use_fixed_stack) and

+ 0 - 4
compiler/jvm/aoptcpub.pas

@@ -71,10 +71,6 @@ Const
 
   MaxCh = 2;
 
-{ the maximum number of operands an instruction has }
-
-  MaxOps = 2;
-
 {Oper index of operand that contains the source (reference) with a load }
 {instruction                                                            }
 

+ 3 - 3
compiler/m68k/aoptcpu.pas

@@ -139,7 +139,7 @@ unit aoptcpu;
       result:=false;
 
       if GetNextInstruction(p,next) and 
-         (taicpu(next).typ = ait_instruction) and
+         (next.typ = ait_instruction) and
          (taicpu(next).opcode = taicpu(p).opcode) and
          (taicpu(p).opsize = taicpu(next).opsize) and
          (taicpu(p).oper[1]^.typ = top_reg) and
@@ -199,9 +199,9 @@ unit aoptcpu;
         end;
 
       if GetNextInstruction(p,next) and
-         (taicpu(next).typ = ait_instruction) and
+         (next.typ = ait_instruction) and
          GetNextInstruction(next,next2) and
-         (taicpu(next2).typ = ait_instruction) and
+         (next2.typ = ait_instruction) and
          (taicpu(next).opcode <> taicpu(p).opcode) and
          (taicpu(next2).opcode = taicpu(p).opcode) and
          (taicpu(p).oper[0]^.typ = top_reg) and

+ 0 - 4
compiler/m68k/aoptcpub.pas

@@ -74,10 +74,6 @@ Const
 
   MaxCh = 3;
 
-{ the maximum number of operands an instruction has }
-
-  MaxOps = 3;
-
 {Oper index of operand that contains the source (reference) with a load }
 {instruction                                                            }
 

+ 5 - 5
compiler/machoutils.pas

@@ -255,10 +255,10 @@ uses
 
     function AllocMachoWriter(cputarget: cpu_type_t; ARawWriter: TRawWriter; AllowFreeWriter: Boolean): TMachoWriter;
 
-    function sizeMachHeader(cputarget: cpu_type_t): integer; inline;
-    function sizeSegment(cputarget: cpu_type_t): integer; inline;
-    function sizeSection(cputarget: cpu_type_t): integer; inline;
-    function sizeNList(cputarget: cpu_type_t): integer; inline;
+    function sizeMachHeader(cputarget: cpu_type_t): integer;
+    function sizeSegment(cputarget: cpu_type_t): integer;
+    function sizeSection(cputarget: cpu_type_t): integer;
+    function sizeNList(cputarget: cpu_type_t): integer;
 
     function AlignAddr(cputarget: cpu_type_t; addr: qword): qword;
 
@@ -523,7 +523,7 @@ const
     end;
 
 
-  function sizeNList(cputarget: cpu_type_t): integer; inline;
+  function sizeNList(cputarget: cpu_type_t): integer;
     begin
       Result:=is64NlistSize[ cputarget and CPU_ARCH_ABI64 > 0];
     end;

+ 0 - 4
compiler/mips/aoptcpub.pas

@@ -69,10 +69,6 @@ Const
 
   MaxCh = 3;
 
-{ the maximum number of operands an instruction has }
-
-  MaxOps = 3;
-
 {Oper index of operand that contains the source (reference) with a load }
 {instruction                                                            }
 

+ 1 - 1
compiler/msg/errorct.msg

@@ -719,7 +719,7 @@ parser_e_function_already_declared_public_forward=03120_E_La funci
 % declaration in the \var{implmentation} section.
 parser_e_not_external_and_export=03121_E_No es poden utilitzar EXPORT i EXTERNAL conjuntament
 % These two procedure directives are mutually exclusive
-parser_h_not_supported_for_inline=03123_H_Encara no es permet "$1" dins de procediment/funció inserits
+parser_n_not_supported_for_inline=03123_N_Encara no es permet "$1" dins de procediment/funció inserits
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_S'ha deshabilitat l'inseriment
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errord.msg

@@ -845,7 +845,7 @@ parser_e_function_already_declared_public_forward=03120_E_Funktion ist bereits a
 % declaration in the \var{implementation} section.
 parser_e_not_external_and_export=03121_E_Kann nicht EXPORT und EXTERNAL gleichzeitig benutzen
 % These two procedure directives are mutually exclusive.
-parser_h_not_supported_for_inline=03123_H_$1 noch nicht innerhalb von inline Prozeduren/Funktionen unterst�tzt
+parser_n_not_supported_for_inline=03123_N_$1 noch nicht innerhalb von inline Prozeduren/Funktionen unterst�tzt
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_Inlining deaktiviert
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errorda.msg

@@ -844,7 +844,7 @@ parser_e_function_already_declared_public_forward=03120_E_Funktionen "$1" er all
 % declaration in the \var{implmentation} section.
 parser_e_not_external_and_export=03121_E_Kan ikke bruge både EXPORT og EXTERNAL
 % These two procedure directives are mutually exclusive
-parser_h_not_supported_for_inline=03123_H_Deklarationen "$1" er endnu ikke understøttet i inline procedurer/funktioner
+parser_n_not_supported_for_inline=03123_N_Deklarationen "$1" er endnu ikke understøttet i inline procedurer/funktioner
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_Inlining slået fra
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errordu.msg

@@ -845,7 +845,7 @@ parser_e_function_already_declared_public_forward=03120_E_Funktion ist bereits a
 % declaration in the \var{implementation} section.
 parser_e_not_external_and_export=03121_E_Kann nicht EXPORT und EXTERNAL gleichzeitig benutzen
 % These two procedure directives are mutually exclusive.
-parser_h_not_supported_for_inline=03123_H_$1 noch nicht innerhalb von inline Prozeduren/Funktionen unterstützt
+parser_n_not_supported_for_inline=03123_N_$1 noch nicht innerhalb von inline Prozeduren/Funktionen unterstützt
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_Inlining deaktiviert
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errore.msg

@@ -829,7 +829,7 @@ parser_e_function_already_declared_public_forward=03120_E_Function is already de
 % declaration in the \var{implementation} section.
 parser_e_not_external_and_export=03121_E_Cannot use both EXPORT and EXTERNAL
 % These two procedure directives are mutually exclusive.
-parser_h_not_supported_for_inline=03123_H_"$1" not yet supported inside inline procedure/function
+parser_n_not_supported_for_inline=03123_N_"$1" not yet supported inside inline procedure/function
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_Inlining disabled
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errores.msg

@@ -823,7 +823,7 @@ parser_e_function_already_declared_public_forward=03120_E_La funci
 % declaration in the \var{implmentation} section.
 parser_e_not_external_and_export=03121_E_No se pueden usar ambos EXPORT y EXTERNAL
 % These two procedure directives are mutually exclusive
-parser_h_not_supported_for_inline=03123_H_"$1" aún no soportado en procedimientos/funciones inline
+parser_n_not_supported_for_inline=03123_N_"$1" aún no soportado en procedimientos/funciones inline
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_Inlining deshabilitado
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errorf.msg

@@ -740,7 +740,7 @@ parser_e_not_external_and_export=03121_E_EXPORT et EXTERNAL sont incompatibles
 % These two procedure directives are mutually exclusive
 parser_e_name_keyword_expected=03122_E_Le mot r‚serv‚ NAME est requis ici
 % The definition of an external variable needs a \var{name} clause.
-parser_h_not_supported_for_inline=03123_H_$1 n'est pas support‚ pour des fonctions INLINE
+parser_n_not_supported_for_inline=03123_N_$1 n'est pas support‚ pour des fonctions INLINE
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_Inlining d‚sactiv‚
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errorfi.msg

@@ -834,7 +834,7 @@ parser_e_function_already_declared_public_forward=03120_E_La fonction "$1" est d
 % declaration in the \var{implmentation} section.
 parser_e_not_external_and_export=03121_E_Impossible d'utiliser à la fois EXPORT et EXTERNAL
 % These two procedure directives are mutually exclusive
-parser_h_not_supported_for_inline=03123_H_"$1" n'est pas encore supporté à l'intérieur de procédures/fonctions INLINE
+parser_n_not_supported_for_inline=03123_N_"$1" n'est pas encore supporté à l'intérieur de procédures/fonctions INLINE
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_Inlining désactivé
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errorhe.msg

@@ -764,7 +764,7 @@ parser_e_function_already_declared_public_forward=03120_E_
 % declaration in the \var{implmentation} section.
 parser_e_not_external_and_export=03121_E_ìà ðéúï ìäùúîù âí á EXPORT åâí EXTERNAL
 % These two procedure directives are mutually exclusive
-parser_h_not_supported_for_inline=03123_H_"$1" àéðå ðúîê òãééï áúåê ôåð÷öéú/ùâøú inline
+parser_n_not_supported_for_inline=03123_N_"$1" àéðå ðúîê òãééï áúåê ôåð÷öéú/ùâøú inline
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_äùéîåù äéùéø îáåèì
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errorheu.msg

@@ -828,7 +828,7 @@ parser_e_function_already_declared_public_forward=03120_E_הגדרת הפונק
 % declaration in the \var{implmentation} section.
 parser_e_not_external_and_export=03121_E_לא ניתן להשתמש גם ב EXPORT וגם EXTERNAL
 % These two procedure directives are mutually exclusive
-parser_h_not_supported_for_inline=03123_H_"$1" אינו נתמך עדיין בתוך פונקצית/שגרת inline
+parser_n_not_supported_for_inline=03123_N_"$1" אינו נתמך עדיין בתוך פונקצית/שגרת inline
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_השימוש הישיר מבוטל
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errorid.msg

@@ -827,7 +827,7 @@ parser_e_function_already_declared_public_forward=03120_E_Fungsi sudah dideklara
 % \var{forward} dalam seksi \var{implmentation}.
 parser_e_not_external_and_export=03121_E_Tidak bisa menggunakan EXPORT dan EXTERNAL
 % Dua prosedur ini adalah mutual eksklusif
-parser_h_not_supported_for_inline=03123_H_"$1" belum didukung di dalam inline procedure/function
+parser_n_not_supported_for_inline=03123_N_"$1" belum didukung di dalam inline procedure/function
 % Inline procedures tidak mendukung deklarasi ini.
 parser_h_inlining_disabled=03124_H_Inlining dimatikan
 % Inlining dari prosedur dimatikan.

+ 1 - 1
compiler/msg/erroriu.msg

@@ -771,7 +771,7 @@ parser_e_function_already_declared_public_forward=03120_E_La funzione 
 % declaration in the \var{implementation} section.
 parser_e_not_external_and_export=03121_E_Non si possono usare sia EXPORT che EXTERNAL
 % These two procedure directives are mutually exclusive.
-parser_h_not_supported_for_inline=03123_H_"$1" non è ancora supportata all'interno di procedure o funzioni inline
+parser_n_not_supported_for_inline=03123_N_"$1" non è ancora supportata all'interno di procedure o funzioni inline
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_Inlining disabilitato
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errorn.msg

@@ -828,7 +828,7 @@ parser_e_function_already_declared_public_forward=03120_E_Functie is al publiek/
 % declaration in the \var{implmentation} section.
 parser_e_not_external_and_export=03121_E_Kan niet zowel EXPORT als EXTERNAL gebruiken
 % These two procedure directives are mutually exclusive
-parser_h_not_supported_for_inline=03123_H_$1 wordt niet ondersteund voor inline procedure/functie
+parser_n_not_supported_for_inline=03123_N_$1 wordt niet ondersteund voor inline procedure/functie
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_Inlining uitgeschakeld
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errorpl.msg

@@ -726,7 +726,7 @@ parser_e_function_already_declared_public_forward=03120_E_Funkcja jest ju
 % declaration in the \var{implmentation} section.
 parser_e_not_external_and_export=03121_E_Nie mo¾na u¾y† jednocze˜nie EXPORT i EXTERNAL
 % These two procedure directives are mutually exclusive
-parser_h_not_supported_for_inline=03123_H_$1 nieobsˆugiwane w procedurze/funkcji inline
+parser_n_not_supported_for_inline=03123_N_$1 nieobsˆugiwane w procedurze/funkcji inline
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_Inline wyˆ¥czone
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errorpli.msg

@@ -726,7 +726,7 @@ parser_e_function_already_declared_public_forward=03120_E_Funkcja jest ju
 % declaration in the \var{implmentation} section.
 parser_e_not_external_and_export=03121_E_Nie mo¿na u¿yæ jednocze¶nie EXPORT i EXTERNAL
 % These two procedure directives are mutually exclusive
-parser_h_not_supported_for_inline=03123_H_$1 nieobs³ugiwane w procedurze/funkcji inline
+parser_n_not_supported_for_inline=03123_N_$1 nieobs³ugiwane w procedurze/funkcji inline
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_Inline wy³±czone
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errorpt.msg

@@ -775,7 +775,7 @@ parser_e_function_already_declared_public_forward=03120_E_Fun
 % declaration in the \var{implementation} section.
 parser_e_not_external_and_export=03121_E_Imposs¡vel usar ambos EXPORT e EXTERNAL
 % These two procedure directives are mutually exclusive.
-parser_h_not_supported_for_inline=03123_H_"$1" nÆo suportado ainda dentro procedimento/fun‡Æo em linha
+parser_n_not_supported_for_inline=03123_N_"$1" nÆo suportado ainda dentro procedimento/fun‡Æo em linha
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_Procedimentos em linha desabilitados
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errorptu.msg

@@ -821,7 +821,7 @@ parser_e_function_already_declared_public_forward=03120_E_Função já declarada
 % declaration in the \var{implementation} section.
 parser_e_not_external_and_export=03121_E_Impossível usar ambos EXPORT e EXTERNAL
 % These two procedure directives are mutually exclusive.
-parser_h_not_supported_for_inline=03123_H_"$1" não suportado ainda dentro procedimento/função em linha
+parser_n_not_supported_for_inline=03123_N_"$1" não suportado ainda dentro procedimento/função em linha
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_Procedimentos em linha desabilitados
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msg/errorr.msg

@@ -713,7 +713,7 @@ parser_e_function_already_declared_public_forward=03120_E_
 % ¢ ᥪ樨 \var{implmentation}.
 parser_e_not_external_and_export=03121_E_H¥«ì§ï ¨á¯®«ì§®¢ âì EXPORT ᮢ¬¥áâ­® á EXTERNAL
 % ⨠¤¢¥ ¤¨à¥ªâ¨¢ë ïîâáï ¢§ ¨¬®¨áª«îç î騬¨
-parser_h_not_supported_for_inline=03123_H_"$1" ­¥ ¯®¤¤¥p¦¨¢ ¥âáï ¢­yâp¨ INLINE ¯p®æ¥¤ypë/äy­ªæ¨¨
+parser_n_not_supported_for_inline=03123_N_"$1" ­¥ ¯®¤¤¥p¦¨¢ ¥âáï ¢­yâp¨ INLINE ¯p®æ¥¤ypë/äy­ªæ¨¨
 % ‚áâà ¨¢ ¥¬ë¥ ¯à®æ¥¤ãàë ­¥ ¯®¤¤¥à¦¨¢ îâ íâ®â ⨯ ®¡ê¥­¨ï.
 parser_h_inlining_disabled=03124_H_‚áâà ¨¢ ­¨¥ (INLINE) ®âª«î祭®
 % ‚áâà ¨¢ ­¨¥ ¯à®æ¥¤ãà ®âª«î祭®.

+ 1 - 1
compiler/msg/errorru.msg

@@ -782,7 +782,7 @@ parser_e_function_already_declared_public_forward=03120_E_Функция "$1" у
 % в секции \var{implmentation}.
 parser_e_not_external_and_export=03121_E_Hельзя использовать EXPORT совместно с EXTERNAL
 % Эти две директивы являются взаимоисключающими
-parser_h_not_supported_for_inline=03123_H_"$1" не поддеpживается внyтpи INLINE пpоцедypы/фyнкции
+parser_n_not_supported_for_inline=03123_N_"$1" не поддеpживается внyтpи INLINE пpоцедypы/фyнкции
 % Встраиваемые процедуры не поддерживают этот тип объявления.
 parser_h_inlining_disabled=03124_H_Встраивание (INLINE) отключено
 % Встраивание процедур отключено.

+ 1 - 1
compiler/msg/errorues.msg

@@ -817,7 +817,7 @@ parser_e_function_already_declared_public_forward=03120_E_La función esta actua
 % declaration in the \var{implmentation} section.
 parser_e_not_external_and_export=03121_E_No se pueden usar ambos EXPORT y EXTERNAL
 % These two procedure directives are mutually exclusive
-parser_h_not_supported_for_inline=03123_H_"$1" aún no soportado en procedimientos/funciones inline
+parser_n_not_supported_for_inline=03123_N_"$1" aún no soportado en procedimientos/funciones inline
 % Inline procedures don't support this declaration.
 parser_h_inlining_disabled=03124_H_Inlining deshabilitado
 % Inlining of procedures is disabled.

+ 1 - 1
compiler/msgidx.inc

@@ -239,7 +239,7 @@ const
   parser_e_proc_dir_not_allowed_in_procvar=03119;
   parser_e_function_already_declared_public_forward=03120;
   parser_e_not_external_and_export=03121;
-  parser_h_not_supported_for_inline=03123;
+  parser_n_not_supported_for_inline=03123;
   parser_h_inlining_disabled=03124;
   parser_i_writing_browser_log=03125;
   parser_h_maybe_deref_caret_missing=03126;

+ 1 - 1
compiler/msgtxt.inc

@@ -274,7 +274,7 @@ const msgtxt : array[0..000344,1..240] of char=(
   '03119_E_Procedure directive "$1" ','not allowed in procvar declaration'#000+
   '03120_E_Function is already declared Public/Forward "$1"'#000+
   '03121_E_Cannot use both EXPORT and EXTERNAL'#000+
-  '03123_H_"$1" not yet supported inside inline procedure/function'#000+
+  '03123_N_"$1" not yet supported inside inline procedure/function'#000+
   '03124_H_Inlining disabled'#000+
   '03125_I_Writin','g Browser log $1'#000+
   '03126_H_may be pointer dereference is missing'#000+

+ 0 - 2
compiler/nadd.pas

@@ -2964,10 +2964,8 @@ implementation
 
     function taddnode.first_adddynarray : tnode;
       var
-        p: tnode;
         newstatement : tstatementnode;
         tempnode (*,tempnode2*) : ttempcreatenode;
-        cmpfuncname: string;
         para: tcallparanode;
       begin
         result:=nil;

+ 16 - 4
compiler/ncal.pas

@@ -4373,8 +4373,12 @@ implementation
              result:=pass1_inline
            else
              begin
-               if (po_inline in procdefinition.procoptions) and not(po_compilerproc in procdefinition.procoptions) then
-                 Message1(cg_n_no_inline,tprocdef(procdefinition).customprocname([pno_proctypeoption, pno_paranames,pno_ownername, pno_noclassmarker]));
+               if (po_inline in procdefinition.procoptions) and not(po_compilerproc in procdefinition.procoptions) and
+                  (procdefinition.typ=procdef) and
+                  not (pio_inline_not_possible in tprocdef(procdefinition).implprocoptions) then
+                 begin
+                   Message1(cg_n_no_inline,tprocdef(procdefinition).customprocname([pno_proctypeoption, pno_paranames,pno_ownername, pno_noclassmarker]));
+                 end;
                mark_unregable_parameters;
                result:=pass1_normal;
              end;
@@ -4594,7 +4598,8 @@ implementation
              ((tloadnode(n).symtable.symtabletype = staticsymtable) and
               (tloadnode(n).symtable = TSymtable(arg))) or
              { if the addr of the symbol is taken somewhere, it can be also non-local }
-             (tabstractvarsym(tloadnode(n).symtableentry).addr_taken)
+             ((tloadnode(n).symtableentry.typ in [localvarsym,paravarsym,staticvarsym]) and
+	      (tabstractvarsym(tloadnode(n).symtableentry).addr_taken))
             )
            ) or
            ((n.nodetype = subscriptn) and
@@ -4831,11 +4836,16 @@ implementation
         ptrtype: tdef;
         tempnode: ttempcreatenode;
         paraaddr: taddrnode;
+        isfuncretnode : boolean;
       begin
         ptrtype:=cpointerdef.getreusable(para.left.resultdef);
         tempnode:=ctempcreatenode.create(ptrtype,ptrtype.size,tt_persistent,true);
         addstatement(inlineinitstatement,tempnode);
-        addstatement(inlinecleanupstatement,ctempdeletenode.create(tempnode));
+        isfuncretnode:=nf_is_funcret in para.left.flags;
+        if isfuncretnode then
+          addstatement(inlinecleanupstatement,ctempdeletenode.create_normal_temp(tempnode))
+        else
+          addstatement(inlinecleanupstatement,ctempdeletenode.create(tempnode));
         { inherit addr_taken flag }
         if (tabstractvarsym(para.parasym).addr_taken) then
           tempnode.includetempflag(ti_addr_taken);
@@ -4847,6 +4857,8 @@ implementation
         addstatement(inlineinitstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
           paraaddr));
         para.left:=cderefnode.create(ctemprefnode.create(tempnode));
+        if isfuncretnode then
+          Include(para.left.flags,nf_is_funcret);
       end;
 
 

+ 7 - 7
compiler/ncgflw.pas

@@ -319,6 +319,8 @@ implementation
 *)
                    ;
                    hlcg.a_jmp_always(current_asmdata.CurrAsmList,hl);
+                   if not(cs_opt_size in current_settings.optimizerswitches) then
+                     current_asmdata.CurrAsmList.concat(cai_align.create_max(current_settings.alignment.jumpalign,current_settings.alignment.jumpalignmax));
                 end;
               hlcg.a_label(current_asmdata.CurrAsmList,left.location.falselabel);
               secondpass(t1);
@@ -347,12 +349,15 @@ implementation
                   current_asmdata.CurrAsmList := TAsmList.create;
                 end;
 *)
-              current_asmdata.CurrAsmList.concat(cai_align.create(current_settings.alignment.jumpalign));
+              if not(cs_opt_size in current_settings.optimizerswitches) then
+                current_asmdata.CurrAsmList.concat(cai_align.create_max(current_settings.alignment.coalescealign,current_settings.alignment.coalescealignmax));
               hlcg.a_label(current_asmdata.CurrAsmList,left.location.falselabel);
            end;
          if not(assigned(right)) then
            begin
-              hlcg.a_label(current_asmdata.CurrAsmList,left.location.truelabel);
+             if not(cs_opt_size in current_settings.optimizerswitches) then
+               current_asmdata.CurrAsmList.concat(cai_align.create_max(current_settings.alignment.coalescealign,current_settings.alignment.coalescealignmax));
+             hlcg.a_label(current_asmdata.CurrAsmList,left.location.truelabel);
            end;
 
 (*
@@ -1183,11 +1188,6 @@ implementation
              { finally code only needed to be executed on exception (-> in
                if-branch -> fc_inflowcontrol) }
              flowcontrol:=[fc_inflowcontrol];
-             secondpass(t1);
-             if flowcontrol<>[fc_inflowcontrol] then
-               CGMessage(cg_e_control_flow_outside_finally);
-             if codegenerror then
-               exit;
              if (tf_safecall_exceptions in target_info.flags) and
                 (current_procinfo.procdef.proccalloption=pocall_safecall) then
                handle_safecall_exception

+ 2 - 2
compiler/ncgld.pas

@@ -493,8 +493,8 @@ implementation
                          reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname,AT_DATA),0,location.reference.alignment,[])
                      end
                    else
-                     location:=gvs.localloc;
-                 end;
+                      location:=gvs.localloc;
+                  end;
 
                 { make const a LOC_CREFERENCE }
                 if (gvs.varspez=vs_const) and

+ 15 - 20
compiler/ncgrtti.pas

@@ -175,6 +175,21 @@ implementation
                               TRTTIWriter
 ***************************************************************************}
 
+    function TRTTIWriter.get_rtti_label(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol;
+      begin
+        result:=ref_rtti(def,rt,indirect,'');
+      end;
+
+    function TRTTIWriter.get_rtti_label_ord2str(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol;
+      begin
+        result:=ref_rtti(def,rt,indirect,'_o2s');
+      end;
+
+    function TRTTIWriter.get_rtti_label_str2ord(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol;
+      begin
+        result:=ref_rtti(def,rt,indirect,'_s2o');
+      end;
+
     procedure TRTTIWriter.write_methods(tcb:ttai_typedconstbuilder;st:tsymtable;visibilities:tvisibilities);
       var
         rtticount,
@@ -1291,8 +1306,6 @@ implementation
             tcb.free;
           end;
 
-        var
-          riif : byte;
         begin
            write_header(tcb,def,tkRecord);
            { need extra reqalign record, because otherwise the u32 int will
@@ -1439,8 +1452,6 @@ implementation
         procedure objectdef_rtti(def: tobjectdef);
 
           procedure objectdef_rtti_fields(def:tobjectdef);
-          var
-            riif : byte;
           begin
             { - for compatiblity with record RTTI we need to write a terminator-
                 Nil pointer for initrtti as well for objects
@@ -2051,21 +2062,5 @@ implementation
           end;
       end;
 
-
-    function TRTTIWriter.get_rtti_label(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol;
-      begin
-        result:=ref_rtti(def,rt,indirect,'');
-      end;
-
-    function TRTTIWriter.get_rtti_label_ord2str(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol;
-      begin
-        result:=ref_rtti(def,rt,indirect,'_o2s');
-      end;
-
-    function TRTTIWriter.get_rtti_label_str2ord(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol;
-      begin
-        result:=ref_rtti(def,rt,indirect,'_s2o');
-      end;
-
 end.
 

+ 5 - 16
compiler/nflw.pas

@@ -189,10 +189,10 @@ interface
        end;
        ttryexceptnodeclass = class of ttryexceptnode;
 
-       ttryfinallynode = class(tloopnode)
+       ttryfinallynode = class(tbinarynode)
           implicitframe : boolean;
           constructor create(l,r:tnode);virtual;reintroduce;
-          constructor create_implicit(l,r,_t1:tnode);virtual;
+          constructor create_implicit(l,r:tnode);virtual;
           function pass_typecheck:tnode;override;
           function pass_1 : tnode;override;
           function simplify(forinline:boolean): tnode;override;
@@ -2299,14 +2299,14 @@ implementation
 
     constructor ttryfinallynode.create(l,r:tnode);
       begin
-        inherited create(tryfinallyn,l,r,nil,nil);
+        inherited create(tryfinallyn,l,r);
         implicitframe:=false;
       end;
 
 
-    constructor ttryfinallynode.create_implicit(l,r,_t1:tnode);
+    constructor ttryfinallynode.create_implicit(l,r:tnode);
       begin
-        inherited create(tryfinallyn,l,r,_t1,nil);
+        inherited create(tryfinallyn,l,r);
         implicitframe:=true;
       end;
 
@@ -2323,14 +2323,6 @@ implementation
         typecheckpass(right);
         // "except block" is "used"? (JM)
         set_varstate(right,vs_readwritten,[vsf_must_be_valid]);
-
-        { special finally block only executed when there was an exception }
-        if assigned(t1) then
-          begin
-            typecheckpass(t1);
-            // "finally block" is "used"? (JM)
-            set_varstate(t1,vs_readwritten,[vsf_must_be_valid]);
-          end;
       end;
 
 
@@ -2342,9 +2334,6 @@ implementation
 
         firstpass(right);
 
-        if assigned(t1) then
-          firstpass(t1);
-
         include(current_procinfo.flags,pi_do_call);
 
         { pi_uses_exceptions is an information for the optimizer and it

+ 1 - 1
compiler/ngtcon.pas

@@ -1522,7 +1522,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
         bp   : tbitpackedval;
         error,
         is_packed: boolean;
-        startoffset: aint;
+        startoffset: aword;
 
       procedure handle_stringconstn;
         begin

+ 12 - 4
compiler/ninl.pas

@@ -41,6 +41,7 @@ interface
           function pass_typecheck_cpu:tnode;virtual;
           function simplify(forinline : boolean): tnode;override;
           function docompare(p: tnode): boolean; override;
+          procedure mark_write;override;
 
           { returns a node tree where the inc/dec are replaced by add/sub }
           function getaddsub_for_incdec : tnode;
@@ -1740,7 +1741,7 @@ implementation
         { last param must be var }
         destppn:=ppn.left;
         valid_for_var(destppn,true);
-        set_varstate(destppn,vs_written,[vsf_must_be_valid]);
+        set_varstate(destppn,vs_written,[vsf_must_be_valid,vsf_use_hints,vsf_use_hint_for_string_result]);
         { first param must be a string or dynamic array ...}
         isarray:=is_dynamic_array(destppn.resultdef);
         if not((destppn.resultdef.typ=stringdef) or
@@ -4077,6 +4078,16 @@ implementation
       end;
 
 
+    procedure tinlinenode.mark_write;
+      begin
+        case inlinenumber of
+	  in_aligned_x, in_unaligned_x:
+           tcallparanode(left).left.mark_write;
+        else
+          inherited mark_write;
+        end;
+      end;
+
     function tinlinenode.first_pi : tnode;
       begin
         result:=crealconstnode.create(getpi,pbestrealtype^);
@@ -4747,8 +4758,6 @@ implementation
 
        var
          procname : String;
-         c : longint;
-         n,
          newn,
          datan,
          datacountn,
@@ -4949,7 +4958,6 @@ implementation
          n,
          arrn,
          firstn : tnode;
-         startidx,
          i : longint;
          arrconstr : tarrayconstructornode;
          newstatement : tstatementnode;

+ 4 - 1
compiler/nld.pas

@@ -429,7 +429,10 @@ implementation
                   include(current_procinfo.flags,pi_needs_got);
                 { call to get address of threadvar }
                 if (vo_is_thread_var in tabstractvarsym(symtableentry).varoptions) then
-                  include(current_procinfo.flags,pi_do_call);
+                  begin
+                    include(current_procinfo.flags,pi_do_call);
+                    include(current_procinfo.flags,pi_uses_threadvar);
+                  end;
               end;
             procsym :
                 begin

+ 2 - 2
compiler/nutils.pas

@@ -196,7 +196,7 @@ implementation
               result := foreachnode(procmethod,tcallnode(n).funcretnode,f,arg) or result;
               result := foreachnode(procmethod,tnode(tcallnode(n).callcleanupblock),f,arg) or result;
             end;
-          ifn, whilerepeatn, forn, tryexceptn, tryfinallyn:
+          ifn, whilerepeatn, forn, tryexceptn:
             begin
               { not in one statement, won't work because of b- }
               result := foreachnode(procmethod,tloopnode(n).t1,f,arg) or result;
@@ -293,7 +293,7 @@ implementation
               result := foreachnodestatic(procmethod,tcallnode(n).funcretnode,f,arg) or result;
               result := foreachnodestatic(procmethod,tnode(tcallnode(n).callcleanupblock),f,arg) or result;
             end;
-          ifn, whilerepeatn, forn, tryexceptn, tryfinallyn:
+          ifn, whilerepeatn, forn, tryexceptn:
             begin
               { not in one statement, won't work because of b- }
               result := foreachnodestatic(procmethod,tloopnode(n).t1,f,arg) or result;

+ 0 - 1
compiler/ogbase.pas

@@ -275,7 +275,6 @@ interface
      private
        FData       : TDynamicArray;
        FSecOptions : TObjSectionOptions;
-       FComdatSelection : TObjSectionComdatSelection;
        FCachedFullName : pshortstring;
        FSizeLimit : TObjSectionOfs;
        procedure SetSecOptions(Aoptions:TObjSectionOptions);

+ 18 - 9
compiler/omfbase.pas

@@ -1349,18 +1349,23 @@ implementation
         internalerror(2015033103);
       SetLength(s, len);
       UniqueString(s);
-      Move(RawData[Offset+1],s[1],len);
+      if len>0 then
+        Move(RawData[Offset+1],s[1],len);
     end;
 
   function TOmfRawRecord.WriteStringAt(Offset: Integer; s: string): Integer;
+    var
+      len : longint;
     begin
-      if Length(s)>255 then
+      len:=Length(s);
+      if len>255 then
         internalerror(2015033101);
-      result:=Offset+Length(s)+1;
+      result:=Offset+len+1;
       if result>High(RawData) then
         internalerror(2015033102);
-      RawData[Offset]:=Length(s);
-      Move(s[1], RawData[Offset+1], Length(s));
+      RawData[Offset]:=len;
+      if len>0 then
+        Move(s[1], RawData[Offset+1], len);
     end;
 
   function TOmfRawRecord.ReadIndexedRef(Offset: Integer; out IndexedRef: Integer): Integer;
@@ -1420,7 +1425,7 @@ implementation
       b:=0;
       for I:=-3 to RecordLength-2 do
         b:=byte(b+RawData[I]);
-      SetChecksumByte($100-b);
+      SetChecksumByte(byte($100-b));
     end;
 
   function TOmfRawRecord.VerifyChecksumByte: boolean;
@@ -1521,14 +1526,18 @@ implementation
     end;
 
   procedure TOmfRecord_COMENT.EncodeTo(RawRecord: TOmfRawRecord);
+    var
+      len : longint;
     begin
       RawRecord.RecordType:=RT_COMENT;
-      if (Length(FCommentString)+3)>High(RawRecord.RawData) then
+      len:=Length(FCommentString);
+      if (len+3)>High(RawRecord.RawData) then
         internalerror(2015033105);
-      RawRecord.RecordLength:=Length(FCommentString)+3;
+      RawRecord.RecordLength:=len+3;
       RawRecord.RawData[0]:=CommentType;
       RawRecord.RawData[1]:=CommentClass;
-      Move(FCommentString[1],RawRecord.RawData[2],Length(FCommentString));
+      if len>0 then
+        Move(FCommentString[1],RawRecord.RawData[2],len);
       RawRecord.CalculateChecksumByte;
     end;
 

+ 1 - 1
compiler/optbase.pas

@@ -44,7 +44,7 @@ unit optbase;
         defsum : tdfaset;
         avail : tdfaset;
         { estimation, how often the node is executed per subroutine call times 100, calculated by optutils.CalcExecutionWeight }
-        executionweight : aword;
+        executionweight : longint;
       end;
 
       poptinfo = ^toptinfo;

+ 1 - 0
compiler/optdfa.pas

@@ -383,6 +383,7 @@ unit optdfa;
             temprefn,
             loadn,
             typeconvn,
+            derefn,
             assignn:
               begin
                 if not(assigned(node.optinfo^.def)) and

+ 10 - 1
compiler/options.pas

@@ -3671,7 +3671,6 @@ var
   env: ansistring;
   i : tfeature;
   j : longint;
-  abi : tabi;
   tmplist : TCmdStrList;
   cmditem,
   tmpcmditem : TCmdStrListItem;
@@ -4032,6 +4031,15 @@ begin
      not(cs_link_separate_dbg_file in init_settings.globalswitches) then
     exclude(init_settings.globalswitches,cs_link_strip);
 
+  { choose a reasonable tls model }
+  if (tf_section_threadvars in target_info.flags) and (init_settings.tlsmodel=tlsm_none) then
+    begin
+      if cs_create_pic in init_settings.moduleswitches then
+        init_settings.tlsmodel:=tlsm_general
+      else
+        init_settings.tlsmodel:=tlsm_local;
+    end;
+
   { set Mac OS X version default macros if not specified explicitly }
   option.MaybeSetDefaultMacVersionMacro;
 
@@ -4399,6 +4407,7 @@ begin
    begin
      init_settings.alignment.procalign:=1;
      init_settings.alignment.jumpalign:=1;
+     init_settings.alignment.coalescealign:=1;
      init_settings.alignment.loopalign:=1;
 {$ifdef x86}
      { constalignmax=1 keeps the executable and thus the memory foot print small but

+ 4 - 4
compiler/optutils.pas

@@ -49,7 +49,7 @@ unit optutils;
     procedure CalcDefSum(p : tnode);
 
     { calculates/estimates the field execution weight of optinfo }
-    procedure CalcExecutionWeights(p : tnode;Initial : AWord = 100);
+    procedure CalcExecutionWeights(p : tnode;Initial : longint = 100);
 
     { returns true, if n is a valid node and has life info }
     function has_life_info(n : tnode) : boolean;
@@ -359,12 +359,12 @@ unit optutils;
 
     function SetExecutionWeight(var n: tnode; arg: pointer): foreachnoderesult;
       var
-        Weight : AWord;
+        Weight : longint;
         i : Integer;
       begin
         Result:=fen_false;
         n.allocoptinfo;
-        Weight:=max(PAWord(arg)^,1);
+        Weight:=max(plongint(arg)^,1);
         case n.nodetype of
           casen:
             begin
@@ -393,7 +393,7 @@ unit optutils;
       end;
 
 
-    procedure CalcExecutionWeights(p : tnode;Initial : AWord = 100);
+    procedure CalcExecutionWeights(p : tnode;Initial : longint = 100);
       begin
         if assigned(p) then
           foreachnodestatic(pm_postprocess,p,@SetExecutionWeight,Pointer(@Initial));

+ 4 - 0
compiler/owomflib.pas

@@ -421,6 +421,9 @@ implementation
             repeat
               pb:=@blocks[h.block_x];
               success:=false;
+	      {$push}
+	      { Disable range check in that part of code }
+	      {$R-}
               repeat
                 if pb^[h.bucket_x]=0 then
                   begin
@@ -440,6 +443,7 @@ implementation
                   end;
                 h.bucket_x:=(h.bucket_x+h.bucket_d) mod nbuckets;
               until h.bucket_x=start_bucket;
+	      {$pop}
               if not success then
                 begin
                   h.block_x:=(h.block_x+h.block_d) mod nblocks;

+ 1 - 1
compiler/pass_2.pas

@@ -194,7 +194,7 @@ implementation
             codegenerror:=false;
             oldexecutionweight:=cg.executionweight;
             if assigned(p.optinfo) then
-              cg.executionweight:=min(p.optinfo^.executionweight,QWord(high(cg.executionweight)))
+              cg.executionweight:=min(p.optinfo^.executionweight,high(cg.executionweight))
             else
               cg.executionweight:=100;
 {$ifdef EXTDEBUG}

+ 3 - 0
compiler/pdecl.pas

@@ -274,6 +274,9 @@ implementation
                      to it from the structure or linking will fail }
                    if symtablestack.top.symtabletype in [recordsymtable,ObjectSymtable] then
                      begin
+                       { note: we keep hdef so that we might at least read the
+                               constant data correctly for error recovery }
+                       check_allowed_for_var_or_const(hdef,false);
                        sym:=cfieldvarsym.create(orgname,varspez,hdef,[],true);
                        symtablestack.top.insert(sym);
                        sym:=make_field_static(symtablestack.top,tfieldvarsym(sym));

+ 1 - 2
compiler/pdecsub.pas

@@ -2960,8 +2960,7 @@ const
       }
       var
         p     : longint;
-        name,
-        other : TIDString;
+        name : TIDString;
         po_comp : tprocoptions;
         tokenloc : TFilePosInfo;
       begin

+ 48 - 31
compiler/pdecvar.pas

@@ -28,7 +28,7 @@ interface
 
     uses
       cclasses,
-      symtable,symsym,symdef;
+      symtable,symsym,symdef,symtype;
 
     type
       tvar_dec_option=(vd_record,vd_object,vd_threadvar,vd_class,vd_final,vd_canreorder,vd_check_generic);
@@ -44,6 +44,8 @@ interface
 
     procedure try_consume_sectiondirective(var asection: ansistring);
 
+    function check_allowed_for_var_or_const(def:tdef;allowdynarray:boolean):boolean;
+
 implementation
 
     uses
@@ -54,7 +56,7 @@ implementation
        globtype,globals,tokens,verbose,constexp,
        systems,
        { symtable }
-       symconst,symbase,symtype,defutil,defcmp,symcreat,
+       symconst,symbase,defutil,defcmp,symcreat,
 {$if defined(i386) or defined(i8086)}
        symcpu,
 {$endif}
@@ -1541,6 +1543,47 @@ implementation
       end;
 
 
+    function check_allowed_for_var_or_const(def:tdef;allowdynarray:boolean):boolean;
+      var
+        stowner,tmpdef : tdef;
+        st : tsymtable;
+      begin
+        result:=true;
+        st:=symtablestack.top;
+        if not (st.symtabletype in [recordsymtable,objectsymtable]) then
+          exit;
+        stowner:=tdef(st.defowner);
+        while assigned(stowner) and (stowner.typ in [objectdef,recorddef]) do
+          begin
+            if def.typ=arraydef then
+              begin
+                tmpdef:=def;
+                while (tmpdef.typ=arraydef) do
+                  begin
+                    { dynamic arrays are allowed in certain cases }
+                    if allowdynarray and (ado_IsDynamicArray in tarraydef(tmpdef).arrayoptions) then
+                      begin
+                        tmpdef:=nil;
+                        break;
+                      end;
+                    tmpdef:=tarraydef(tmpdef).elementdef;
+                  end;
+              end
+            else
+              tmpdef:=def;
+            if assigned(tmpdef) and
+                (is_object(tmpdef) or is_record(tmpdef)) and
+                is_owned_by(tabstractrecorddef(stowner),tabstractrecorddef(tmpdef)) then
+              begin
+                Message1(type_e_type_is_not_completly_defined,tabstractrecorddef(tmpdef).RttiName);
+                result:=false;
+                break;
+              end;
+            stowner:=tdef(stowner.owner.defowner);
+          end;
+      end;
+
+
     procedure read_record_fields(options:Tvar_dec_options; reorderlist: TFPObjectList; variantdesc : ppvariantrecdesc;out had_generic:boolean);
       var
          sc : TFPObjectList;
@@ -1644,35 +1687,9 @@ implementation
              { allow only static fields reference to struct where they are declared }
              if not (vd_class in options) then
                begin
-                 stowner:=tdef(recst.defowner);
-                 while assigned(stowner) and (stowner.typ in [objectdef,recorddef]) do
-                   begin
-                     if hdef.typ=arraydef then
-                       begin
-                         tmpdef:=hdef;
-                         while (tmpdef.typ=arraydef) do
-                           begin
-                             { dynamic arrays are allowed }
-                             if ado_IsDynamicArray in tarraydef(tmpdef).arrayoptions then
-                               begin
-                                 tmpdef:=nil;
-                                 break;
-                               end;
-                             tmpdef:=tarraydef(tmpdef).elementdef;
-                           end;
-                       end
-                     else
-                       tmpdef:=hdef;
-                     if assigned(tmpdef) and
-                         (is_object(tmpdef) or is_record(tmpdef)) and
-                         is_owned_by(tabstractrecorddef(stowner),tabstractrecorddef(tmpdef)) then
-                       begin
-                         Message1(type_e_type_is_not_completly_defined, tabstractrecorddef(tmpdef).RttiName);
-                         { for error recovery or compiler will crash later }
-                         hdef:=generrordef;
-                       end;
-                     stowner:=tdef(stowner.owner.defowner);
-                   end;
+                 if not check_allowed_for_var_or_const(hdef,true) then
+                   { for error recovery or compiler will crash later }
+                   hdef:=generrordef;
                end;
 
              { Process procvar directives }

+ 0 - 4
compiler/powerpc/aoptcpub.pas

@@ -71,10 +71,6 @@ Const
 
   MaxCh = 3;
 
-{ the maximum number of operands an instruction has }
-
-  MaxOps = 5;
-
 {Oper index of operand that contains the source (reference) with a load }
 {instruction                                                            }
 

+ 0 - 4
compiler/powerpc64/aoptcpub.pas

@@ -69,10 +69,6 @@ const
 
   MaxCh = 3;
 
-  { the maximum number of operands an instruction has }
-
-  MaxOps = 5;
-
   {Oper index of operand that contains the source (reference) with a load }
   {instruction                                                            }
 

+ 1 - 1
compiler/ppu.pas

@@ -43,7 +43,7 @@ type
 {$endif Test_Double_checksum}
 
 const
-  CurrentPPUVersion = 202;
+  CurrentPPUVersion = 203;
 
 { unit flags }
   uf_init                = $000001; { unit has initialization section }

+ 13 - 0
compiler/procinfo.pas

@@ -95,6 +95,11 @@ unit procinfo;
           got : tregister;
           CurrGOTLabel : tasmlabel;
 
+          { register containing the tlsoffset }
+          tlsoffset : tregister;
+          { reference label for tls addresses }
+          tlslabel : tasmlabel;
+
           { Holds the reference used to store all saved registers. }
           save_regs_ref : treference;
 
@@ -150,6 +155,9 @@ unit procinfo;
           { Allocate got register }
           procedure allocate_got_register(list: TAsmList);virtual;
 
+          { Allocate tls register }
+          procedure allocate_tls_register(list: TAsmList);virtual;
+
           { get frame pointer }
           procedure init_framepointer; virtual;
 
@@ -288,6 +296,11 @@ implementation
         { most os/cpu combo's don't use this yet, so not yet abstract }
       end;
 
+    procedure tprocinfo.allocate_tls_register(list : TAsmList);
+      begin
+      end;
+
+
     procedure tprocinfo.init_framepointer;
       begin
         { most targets use a constant, but some have a typed constant that must

+ 93 - 25
compiler/psub.pas

@@ -93,7 +93,7 @@ implementation
     uses
        sysutils,
        { common }
-       cutils,
+       cutils, cmsgs,
        { global }
        globtype,tokens,verbose,comphook,constexp,
        systems,cpubase,aasmbase,aasmtai,aasmdata,
@@ -138,6 +138,14 @@ implementation
        ;
 
     function checknodeinlining(procdef: tprocdef): boolean;
+
+      procedure _no_inline(const reason: TMsgStr);
+        begin
+          include(procdef.implprocoptions,pio_inline_not_possible);
+          Message1(parser_n_not_supported_for_inline,reason);
+          Message(parser_h_inlining_disabled);
+        end;
+
       var
         i : integer;
         currpara : tparavarsym;
@@ -150,26 +158,22 @@ implementation
           exit;
         if pi_has_assembler_block in current_procinfo.flags then
           begin
-            Message1(parser_h_not_supported_for_inline,'assembler');
-            Message(parser_h_inlining_disabled);
+            _no_inline('assembler');
             exit;
           end;
         if pi_has_global_goto in current_procinfo.flags then
           begin
-            Message1(parser_h_not_supported_for_inline,'global goto');
-            Message(parser_h_inlining_disabled);
+            _no_inline('global goto');
             exit;
           end;
         if pi_has_nested_exit in current_procinfo.flags then
           begin
-            Message1(parser_h_not_supported_for_inline,'nested exit');
-            Message(parser_h_inlining_disabled);
+            _no_inline('nested exit');
             exit;
           end;
         if pi_calls_c_varargs in current_procinfo.flags then
           begin
-            Message1(parser_h_not_supported_for_inline,'called C-style varargs functions');
-            Message(parser_h_inlining_disabled);
+            _no_inline('called C-style varargs functions');
             exit;
           end;
         { the compiler cannot handle inherited in inlined subroutines because
@@ -177,8 +181,7 @@ implementation
           is not available }
         if pi_has_inherited in current_procinfo.flags then
           begin
-            Message1(parser_h_not_supported_for_inline,'inherited');
-            Message(parser_h_inlining_disabled);
+            _no_inline('inherited');
             exit;
           end;
         for i:=0 to procdef.paras.count-1 do
@@ -189,8 +192,7 @@ implementation
                 begin
                   if (currpara.varspez in [vs_out,vs_var,vs_const,vs_constref]) then
                     begin
-                      Message1(parser_h_not_supported_for_inline,'formal parameter');
-                      Message(parser_h_inlining_disabled);
+                      _no_inline('formal parameter');
                       exit;
                     end;
                 end;
@@ -199,8 +201,7 @@ implementation
                   if is_array_of_const(currpara.vardef) or
                      is_variant_array(currpara.vardef) then
                     begin
-                      Message1(parser_h_not_supported_for_inline,'array of const');
-                      Message(parser_h_inlining_disabled);
+                      _no_inline('array of const');
                       exit;
                     end;
                   { open arrays might need re-basing of the index, i.e. if you pass
@@ -208,8 +209,7 @@ implementation
                     if you directly inline it }
                   if is_open_array(currpara.vardef) then
                     begin
-                      Message1(parser_h_not_supported_for_inline,'open array');
-                      Message(parser_h_inlining_disabled);
+                      _no_inline('open array');
                       exit;
                     end;
                 end;
@@ -919,10 +919,7 @@ implementation
             final_used:=true;
 
             current_filepos:=entrypos;
-            wrappedbody:=ctryfinallynode.create_implicit(
-               code,
-               finalcode,
-               cnothingnode.create);
+            wrappedbody:=ctryfinallynode.create_implicit(code,finalcode);
             { afterconstruction must be called after final_asmnode, because it
                has to execute after the temps have been finalised in case of a
                refcounted class (afterconstruction decreases the refcount
@@ -1206,6 +1203,46 @@ implementation
         procdef.has_inlininginfo:=true;
        end;
 
+    procedure searchthreadvar(p: TObject; arg: pointer);
+      var
+        i : longint;
+        pd : tprocdef;
+      begin
+        case tsym(p).typ of
+          staticvarsym :
+            begin
+                  { local (procedure or unit) variables only need finalization
+                    if they are used
+                  }
+              if (vo_is_thread_var in tstaticvarsym(p).varoptions) and
+                 ((tstaticvarsym(p).refs>0) or
+                  { global (unit) variables always need finalization, since
+                    they may also be used in another unit
+                  }
+                  (tstaticvarsym(p).owner.symtabletype=globalsymtable)) and
+                  (
+                    (tstaticvarsym(p).varspez<>vs_const) or
+                    (vo_force_finalize in tstaticvarsym(p).varoptions)
+                  ) and
+                 not(vo_is_funcret in tstaticvarsym(p).varoptions) and
+                 not(vo_is_external in tstaticvarsym(p).varoptions) and
+                 is_managed_type(tstaticvarsym(p).vardef) then
+                include(current_procinfo.flags,pi_uses_threadvar);
+            end;
+          procsym :
+            begin
+              for i:=0 to tprocsym(p).ProcdefList.Count-1 do
+                begin
+                  pd:=tprocdef(tprocsym(p).ProcdefList[i]);
+                  if assigned(pd.localst) and
+                     (pd.procsym=tprocsym(p)) and
+                     (pd.localst.symtabletype<>staticsymtable) then
+                    pd.localst.SymList.ForEachCall(@searchthreadvar,arg);
+                end;
+            end;
+        end;
+      end;
+
 
     function searchusercode(var n: tnode; arg: pointer): foreachnoderesult;
       begin
@@ -1232,6 +1269,19 @@ implementation
 
 
     procedure tcgprocinfo.generate_code;
+
+       procedure check_for_threadvars_in_initfinal;
+         begin
+           if current_procinfo.procdef.proctypeoption=potype_unitfinalize then
+             begin
+                { this is also used for initialization of variables in a
+                  program which does not have a globalsymtable }
+                if assigned(current_module.globalsymtable) then
+                  TSymtable(current_module.globalsymtable).SymList.ForEachCall(@searchthreadvar,nil);
+                TSymtable(current_module.localsymtable).SymList.ForEachCall(@searchthreadvar,nil);
+             end;
+         end;
+
       var
         old_current_procinfo : tprocinfo;
         oldmaxfpuregisters : longint;
@@ -1429,6 +1479,10 @@ implementation
           (code.nodetype=blockn) and (tblocknode(code).statements=nil) then
           procdef.isempty:=true;
 
+        { unit static/global symtables might contain threadvars which are not explicitly used but which might
+          require a tls register, so check for such variables }
+        check_for_threadvars_in_initfinal;
+
         { add implicit entry and exit code }
         add_entry_exit_code;
 
@@ -1454,6 +1508,9 @@ implementation
             { allocate got register if needed }
             allocate_got_register(aktproccode);
 
+            if pi_uses_threadvar in flags then
+              allocate_tls_register(aktproccode);
+
             { Allocate space in temp/registers for parast and localst }
             current_filepos:=entrypos;
             gen_alloc_symtable(aktproccode,procdef,procdef.parast);
@@ -1564,6 +1621,10 @@ implementation
                (got<>NR_NO) then
               cg.a_reg_sync(aktproccode,got);
 
+            if (pi_uses_threadvar in flags) and
+              (tlsoffset<>NR_NO) then
+              cg.a_reg_sync(aktproccode,tlsoffset);
+
             gen_free_symtable(aktproccode,procdef.localst);
             gen_free_symtable(aktproccode,procdef.parast);
 
@@ -1582,7 +1643,7 @@ implementation
               begin
                 current_filepos:=entrypos;
                 hlcg.gen_stack_check_call(templist);
-                aktproccode.insertlistafter(stackcheck_asmnode.currenttai,templist)
+                aktproccode.insertlistafter(stackcheck_asmnode.currenttai,templist);
               end;
 
             { this code (got loading) comes before everything which has }
@@ -1602,9 +1663,13 @@ implementation
             current_filepos:=entrypos;
             { load got if necessary }
             cg.g_maybe_got_init(templist);
-
             aktproccode.insertlistafter(headertai,templist);
 
+            if (pi_uses_threadvar in flags) and (tf_section_threadvars in target_info.flags) then
+              cg.g_maybe_tls_init(templist);
+            aktproccode.insertlistafter(stackcheck_asmnode.currenttai,templist);
+
+
             { re-enable if more code at the end is ever generated here
             cg.set_regalloc_live_range_direction(rad_forward);
             }
@@ -2063,7 +2128,7 @@ implementation
           begin
             if (po_inline in current_procinfo.procdef.procoptions) then
               begin
-                Message1(parser_h_not_supported_for_inline,'nested procedures');
+                Message1(parser_n_not_supported_for_inline,'nested procedures');
                 Message(parser_h_inlining_disabled);
                 exclude(current_procinfo.procdef.procoptions,po_inline);
               end;
@@ -2135,9 +2200,12 @@ implementation
         old_current_genericdef,
         old_current_specializedef: tstoreddef;
         pdflags    : tpdflags;
-        def,pd,firstpd : tprocdef;
+        pd,firstpd : tprocdef;
+{$ifdef genericdef_for_nested}
+        def : tprocdef;
         srsym : tsym;
         i : longint;
+{$endif genericdef_for_nested}
       begin
          { save old state }
          old_current_procinfo:=current_procinfo;

+ 0 - 1
compiler/rgobj.pas

@@ -489,7 +489,6 @@ unit rgobj;
     procedure Trgobj.dispose_reginfo;
       var
         i : cardinal;
-        j : longint;
       begin
         if reginfo<>nil then
           begin

+ 2 - 0
compiler/riscv/aasmcpu.pas

@@ -444,6 +444,8 @@ uses cutils, cclasses;
                (opcode in [A_FSGNJ_S,A_FSGNJ_D]) and
                (oper[0]^.reg=oper[1]^.reg) and
                (oper[0]^.reg=oper[2]^.reg);
+         else
+           result:=false;
         end;
       end;
 

+ 0 - 4
compiler/riscv32/aoptcpub.pas

@@ -71,10 +71,6 @@ Const
 
   MaxCh = 3;
 
-{ the maximum number of operands an instruction has }
-
-  MaxOps = 5;
-
 {Oper index of operand that contains the source (reference) with a load }
 {instruction                                                            }
 

+ 0 - 4
compiler/riscv64/aoptcpub.pas

@@ -69,10 +69,6 @@ const
 
   MaxCh = 3;
 
-  { the maximum number of operands an instruction has }
-
-  MaxOps = 5;
-
   {Oper index of operand that contains the source (reference) with a load }
   {instruction                                                            }
 

+ 11 - 0
compiler/scanner.pas

@@ -3042,6 +3042,9 @@ type
             alignment.procalign:=tokenreadlongint;
             alignment.loopalign:=tokenreadlongint;
             alignment.jumpalign:=tokenreadlongint;
+            alignment.jumpalignmax:=tokenreadlongint;
+            alignment.coalescealign:=tokenreadlongint;
+            alignment.coalescealignmax:=tokenreadlongint;
             alignment.constalignmin:=tokenreadlongint;
             alignment.constalignmax:=tokenreadlongint;
             alignment.varalignmin:=tokenreadlongint;
@@ -3082,6 +3085,8 @@ type
             minfpconstprec:=tfloattype(tokenreadenum(sizeof(tfloattype)));
 
             disabledircache:=boolean(tokenreadbyte);
+
+            tlsmodel:=ttlsmodel(tokenreadenum(sizeof(ttlsmodel)));
 { TH: Since the field was conditional originally, it was not stored in PPUs.  }
 { While adding ControllerSupport constant, I decided not to store ct_none     }
 { on targets not supporting controllers, but this might be changed here and   }
@@ -3122,6 +3127,9 @@ type
             tokenwritelongint(alignment.procalign);
             tokenwritelongint(alignment.loopalign);
             tokenwritelongint(alignment.jumpalign);
+            tokenwritelongint(alignment.jumpalignmax);
+            tokenwritelongint(alignment.coalescealign);
+            tokenwritelongint(alignment.coalescealignmax);
             tokenwritelongint(alignment.constalignmin);
             tokenwritelongint(alignment.constalignmax);
             tokenwritelongint(alignment.varalignmin);
@@ -3160,6 +3168,9 @@ type
             tokenwriteenum(minfpconstprec,sizeof(tfloattype));
 
             recordtokenbuf.write(byte(disabledircache),1);
+
+            tokenwriteenum(tlsmodel,sizeof(tlsmodel));
+
 { TH: See note about controllertype field in tokenreadsettings. }
 {$PUSH}
  {$WARN 6018 OFF} (* Unreachable code due to compile time evaluation *)

Some files were not shown because too many files changed in this diff