瀏覽代碼

* synchronized with trunk

git-svn-id: branches/wasm@46970 -
nickysn 4 年之前
父節點
當前提交
114d0d738b

+ 7 - 2
compiler/aoptobj.pas

@@ -464,8 +464,8 @@ Unit AoptObj;
 
     function JumpTargetOp(ai: taicpu): poper; inline;
       begin
-{$if defined(MIPS) or defined(riscv64) or defined(riscv32)}
-        { MIPS or RiscV branches can have 1,2 or 3 operands, target label is the last one. }
+{$if defined(MIPS) or defined(riscv64) or defined(riscv32) or defined(xtensa)}
+        { MIPS, Xtensa or RiscV branches can have 1,2 or 3 operands, target label is the last one. }
         result:=ai.oper[ai.ops-1];
 {$elseif defined(SPARC64)}
         if ai.ops=2 then
@@ -1644,6 +1644,11 @@ Unit AoptObj;
         p.loadreg(0, NR_X0);
         p.ops:=2;
 {$endif}
+{$ifdef xtensa}
+        p.opcode := aopt_uncondjmp;
+        p.loadoper(0, p.oper[p.ops-1]^);
+        p.ops:=1;
+{$endif}
 {$endif not avr}
 {$ifdef mips}
         { MIPS conditional jump instructions also conntain register

+ 10 - 0
compiler/options.pas

@@ -4626,6 +4626,16 @@ begin
     end;
 {$endif}
 
+{$if defined(xtensa)}
+  { it is determined during system unit compilation if nsau is used for bsr or not,
+    this is not perfect but the current implementation bsf/bsr does not allow another
+    solution }
+  if CPUXTENSA_HAS_NSAx in cpu_capabilities[init_settings.cputype] then
+    begin
+      def_system_macro('FPC_HAS_INTERNAL_BSR');
+    end;
+{$endif}
+
 {$if defined(powerpc64)}
   { on sysv targets, default to elfv2 for little endian and to elfv1 for
     big endian (unless specified otherwise). As the gcc man page says:

+ 27 - 11
compiler/systems/t_freertos.pas

@@ -1115,13 +1115,13 @@ begin
       writeln(t,'    "COMPONENT_KCONFIGS_PROJBUILD": "Kconfig.projbuild",');
       writeln(t,'    "IDF_CMAKE": "y",');
       writeln(t,'    "IDF_TARGET": "esp32",');
-      writeln(t,'    "IDF_PATH": "'+idfpath+'",');
+      writeln(t,'    "IDF_PATH": "'+TargetFixPath(idfpath,false)+'",');
       writeln(t,'    "COMPONENT_KCONFIGS_SOURCE_FILE": "kconfigs.in",');
       writeln(t,'    "COMPONENT_KCONFIGS_PROJBUILD_SOURCE_FILE": "kconfigs_projbuild.in"');
     end
   else
     begin
-      writeln(t,'    "IDF_PATH": "'+idfpath+'",');
+      writeln(t,'    "IDF_PATH": "'+TargetFixPath(idfpath,false)+'",');
       writeln(t,'    "IDF_TARGET": "esp8266",');
       writeln(t,'    "IDF_CMAKE": "n"');
     end;
@@ -1161,9 +1161,17 @@ begin
   success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,true);
 
   { generate linker maps }
-  binstr:='$IDF_PATH/tools/ldgen/ldgen.py';
+{$ifdef UNIX}
+  binstr:=TargetFixPath(idfpath,false)+'/tools/ldgen/ldgen.py';
+{$else}
+  binstr:='python';
+{$endif UNIX}
+  if source_info.exeext<>'' then
+    binstr:=binstr+source_info.exeext;
+  S:=FindUtil(utilsprefix+'objdump');
   if (current_settings.controllertype = ct_esp32) then
-    cmdstr:='--config sdkconfig '+
+    cmdstr:={$ifndef UNIX}'$IDF_PATH/tools/ldgen/ldgen.py '+{$endif UNIX}
+            '--config sdkconfig '+
             '--fragments $IDF_PATH/components/xtensa/linker.lf $IDF_PATH/components/soc/linker.lf $IDF_PATH/components/esp_event/linker.lf '+
             '$IDF_PATH/components/spi_flash/linker.lf $IDF_PATH/components/esp_wifi/linker.lf $IDF_PATH/components/lwip/linker.lf '+
             '$IDF_PATH/components/heap/linker.lf $IDF_PATH/components/esp_ringbuf/linker.lf $IDF_PATH/components/espcoredump/linker.lf $IDF_PATH/components/esp32/linker.lf '+
@@ -1174,9 +1182,10 @@ begin
             '--kconfig $IDF_PATH/Kconfig '+
             '--env-file config.env '+
             '--libraries-file ldgen_libraries '+
-            '--objdump xtensa-esp32-elf-objdump'
+            '--objdump '+S
   else
-    cmdstr:='--config sdkconfig '+
+    cmdstr:={$ifndef UNIX}'$IDF_PATH/tools/ldgen/ldgen.py '+{$endif UNIX}
+            '--config sdkconfig '+
             '--fragments $IDF_PATH/components/esp8266/ld/esp8266_fragments.lf '+
             '$IDF_PATH/components/esp8266/ld/esp8266_bss_fragments.lf $IDF_PATH/components/esp8266/linker.lf '+
             '$IDF_PATH/components/freertos/linker.lf $IDF_PATH/components/log/linker.lf '+
@@ -1191,9 +1200,8 @@ begin
             '--kconfig $IDF_PATH/Kconfig '+
             '--env-file config.env '+
             '--libraries-file ldgen_libraries '+
-            '--objdump xtensa-lx106-elf-objdump';
+            '--objdump '+S;
 
-  Replace(binstr,'$IDF_PATH',idfpath);
   Replace(cmdstr,'$IDF_PATH',idfpath);
   if success and not(cs_link_nolink in current_settings.globalswitches) then
     success:=DoExec(binstr,cmdstr,true,false);
@@ -1262,10 +1270,18 @@ begin
 {$ifdef XTENSA}
   if success then
    begin
-      binstr:=idfpath+'/components/esptool_py/esptool/esptool.py';
+{$ifdef UNIX}
+      binstr:=TargetFixPath(idfpath,false)+'/components/esptool_py/esptool/esptool.py';
+      cmdstr:='';
+{$else}
+      binstr:='python';
+      cmdstr:=idfpath+'/components/esptool_py/esptool/esptool.py ';
+{$endif UNIX}
+      if source_info.exeext<>'' then
+        binstr:=binstr+source_info.exeext;
       if (current_settings.controllertype = ct_esp32) then
         begin
-          success:=DoExec(binstr,'--chip esp32 elf2image --flash_mode dio --flash_freq 40m '+
+          success:=DoExec(binstr,cmdstr+'--chip esp32 elf2image --flash_mode dio --flash_freq 40m '+
             '--flash_size '+tostr(embedded_controllers[current_settings.controllertype].flashsize div (1024*1024))+'MB '+
             '--elf-sha256-offset 0xb0 '+
             '-o '+maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.bin')))+' '+
@@ -1274,7 +1290,7 @@ begin
         end
       else if (current_settings.controllertype = ct_esp8266) then
         begin
-          success:=DoExec(binstr,'--chip esp8266 elf2image --flash_mode dout --flash_freq 40m '+
+          success:=DoExec(binstr,cmdstr+'--chip esp8266 elf2image --flash_mode dout --flash_freq 40m '+
             '--flash_size '+tostr(embedded_controllers[current_settings.controllertype].flashsize div (1024*1024))+'MB '+
             '--version=3 '+
             '-o '+maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.bin')))+' '+

+ 29 - 0
compiler/xtensa/cgcpu.pas

@@ -69,6 +69,8 @@ interface
         procedure a_cmp_reg_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);override;
         procedure a_jmp_always(list: TAsmList; l: TAsmLabel);override;
 
+        procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: TCGSize; src, dst: TRegister);override;
+
         procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister);override;
 
         procedure g_concatcopy(list : TAsmList; const source,dest : treference; len : tcgint);override;
@@ -621,6 +623,7 @@ implementation
           begin
             instr:=taicpu.op_reg_sym(A_B,f.register,l);
             instr.condition:=flags_to_cond(f.flag);
+            instr.is_jmp:=true;
             list.concat(instr);
           end
         else
@@ -905,6 +908,7 @@ implementation
             end;     
             instr:=taicpu.op_reg_sym(A_B,reg,l);
             instr.condition:=op;
+            instr.is_jmp:=true;
             list.concat(instr);
           end
         else if is_b4const(a) and
@@ -921,6 +925,7 @@ implementation
 
             instr:=taicpu.op_reg_const_sym(A_B,reg,a,l);
             instr.condition:=op;
+            instr.is_jmp:=true;
             list.concat(instr);
           end
         else if is_b4constu(a) and
@@ -935,6 +940,7 @@ implementation
 
             instr:=taicpu.op_reg_const_sym(A_B,reg,a,l);
             instr.condition:=op;
+            instr.is_jmp:=true;
             list.concat(instr);
           end
         else
@@ -958,6 +964,7 @@ implementation
 
         instr:=taicpu.op_reg_reg_sym(A_B,reg2,reg1,l);
         instr.condition:=TOpCmp2AsmCond[cmp_op];
+        instr.is_jmp:=true;
         list.concat(instr);
       end;
 
@@ -1265,6 +1272,28 @@ implementation
       end;
 
 
+    procedure tcgcpu.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: TCGSize; src, dst: TRegister);
+      var
+        ai: taicpu;
+        tmpreg: TRegister;
+      begin
+        if reverse then
+          begin
+            list.Concat(taicpu.op_reg_reg(A_NSAU,dst,src));
+            tmpreg:=getintregister(list,OS_INT);
+            a_load_const_reg(list,OS_INT,31,tmpreg);
+            a_op_reg_reg_reg(list,OP_SUB,OS_INT,dst,tmpreg,dst);
+            tmpreg:=getintregister(list,OS_INT);
+            a_load_const_reg(list,OS_INT,255,tmpreg);
+            ai:=taicpu.op_reg_reg_reg(A_MOV,dst,tmpreg,src);
+            ai.condition:=C_EQZ;
+            list.Concat(ai);
+          end
+        else
+          Internalerror(2020092604);
+      end;
+
+
     procedure tcg64fxtensa.a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
       var
         instr: taicpu;

+ 2 - 1
compiler/xtensa/cpuinfo.pas

@@ -137,6 +137,7 @@ Const
       (
         CPUXTENSA_REGWINDOW,
         CPUXTENSA_HAS_SEXT,
+        CPUXTENSA_HAS_NSAx,
         CPUXTENSA_HAS_BOOLEAN_OPTION,
         CPUXTENSA_HAS_MUL32HIGH,
         CPUXTENSA_HAS_DIV,
@@ -154,7 +155,7 @@ Const
      (
        { cpu_none     } [],
        { cpu_lx106    } [],
-       { cpu_lx6      } [CPUXTENSA_REGWINDOW, CPUXTENSA_HAS_SEXT, CPUXTENSA_HAS_BOOLEAN_OPTION, CPUXTENSA_HAS_MUL32HIGH, CPUXTENSA_HAS_DIV, CPUXTENSA_HAS_LOOPS]
+       { cpu_lx6      } [CPUXTENSA_REGWINDOW, CPUXTENSA_HAS_SEXT, CPUXTENSA_HAS_NSAx, CPUXTENSA_HAS_BOOLEAN_OPTION, CPUXTENSA_HAS_MUL32HIGH, CPUXTENSA_HAS_DIV, CPUXTENSA_HAS_LOOPS]
      );
 
    fpu_capabilities : array[tfputype] of set of tfpuflags =

+ 40 - 4
compiler/xtensa/ncpucnv.pas

@@ -33,6 +33,8 @@ interface
        protected
          function first_real_to_real: tnode;override;
          procedure second_int_to_bool;override;
+         procedure second_int_to_real;override;
+         function first_int_to_real: tnode;override;
        end;
 
 implementation
@@ -67,7 +69,7 @@ implementation
                       left:=nil;
                     end;
                   else
-                    internalerror(200610151);
+                    internalerror(2020092603);
                 end;
               s64real:
                 case tfloatdef(resultdef).floattype of
@@ -80,10 +82,10 @@ implementation
                       left:=nil;
                     end;
                   else
-                    internalerror(200610152);
+                    internalerror(2020092602);
                 end;
               else
-                internalerror(200610153);
+                internalerror(2020092601);
             end;
             left:=nil;
             firstpass(result);
@@ -94,7 +96,6 @@ implementation
       end;
 
 
-
     procedure tcputypeconvnode.second_int_to_bool;
       var
         hreg1, onereg: tregister;
@@ -187,6 +188,41 @@ implementation
       end;
 
 
+    function tcputypeconvnode.first_int_to_real: tnode;
+      var
+        fname: string[19];
+      begin
+        if (cs_fp_emulation in current_settings.moduleswitches) or
+          (current_settings.fputype=fpu_soft) or
+          not(FPUXTENSA_SINGLE in fpu_capabilities[current_settings.fputype]) or
+          ((is_double(resultdef)) and not(FPUXTENSA_DOUBLE in fpu_capabilities[current_settings.fputype])) or
+          is_64bitint(left.resultdef) or
+          is_currency(left.resultdef) or
+          (is_32bit(left.resultdef) and not(is_signed(left.resultdef))) then
+          result:=inherited first_int_to_real
+        else
+          begin
+            { other integers are supposed to be 32 bit }
+            inserttypeconv(left,s32inttype);
+            firstpass(left);
+            result:=nil;
+            expectloc:=LOC_FPUREGISTER;
+          end;
+      end;
+
+
+    procedure tcputypeconvnode.second_int_to_real;
+      var
+        ai: taicpu;
+      begin
+        location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+        location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+        hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,s32inttype,true);
+        ai:=taicpu.op_reg_reg_const(A_FLOAT,location.register,left.location.register,0);
+        ai.oppostfix:=PF_S;
+        current_asmdata.CurrAsmList.concat(ai);
+      end;
+
 begin
   ctypeconvnode:=tcputypeconvnode;
 end.

+ 3 - 5
packages/fcl-js/src/jsbase.pp

@@ -19,11 +19,9 @@ unit jsbase;
 
 interface
 
-uses
-  {$ifdef pas2js}
-  js,
-  {$endif}
-  Classes;
+{$ifdef pas2js}
+uses js;
+{$endif}
 
 const
   MinSafeIntDouble = -$1fffffffffffff; // -9007199254740991 53 bits (52 explicitly stored)

+ 26 - 0
packages/fcl-passrc/src/pasresolver.pp

@@ -2308,6 +2308,7 @@ type
     function GetPasPropertyStoredExpr(El: TPasProperty): TPasExpr;
     function GetPasPropertyDefaultExpr(El: TPasProperty): TPasExpr;
     function GetPasClassAncestor(ClassEl: TPasClassType; SkipAlias: boolean): TPasType;
+    function GetPasClassForward(ClassEl: TPasClassType): TPasClassType;
     function GetParentProcBody(El: TPasElement): TProcedureBody;
     function ProcHasImplElements(Proc: TPasProcedure): boolean; virtual;
     function IndexOfImplementedInterface(ClassEl: TPasClassType; aType: TPasType): integer;
@@ -28009,6 +28010,31 @@ begin
     end;
 end;
 
+function TPasResolver.GetPasClassForward(ClassEl: TPasClassType): TPasClassType;
+var
+  Parent: TPasElement;
+  i: Integer;
+  CurClass: TPasClassType;
+  Ref: TResolvedReference;
+  Decls: TFPList;
+begin
+  Result:=nil;
+  if ClassEl=nil then exit;
+  Parent:=ClassEl.Parent;
+  if not (Parent is TPasDeclarations) then
+    RaiseNotYetImplemented(20200926214106,ClassEl);
+  Decls:=TPasDeclarations(Parent).Classes;
+  for i:=0 to Decls.Count-1 do
+    begin
+    CurClass:=TPasClassType(Decls[i]);
+    if CurClass=ClassEl then exit;
+    if not CurClass.IsForward then continue;
+    Ref:=TResolvedReference(CurClass.CustomData);
+    if Ref.Declaration=ClassEl then
+      exit(TPasClassType(Ref.Declaration));
+    end;
+end;
+
 function TPasResolver.GetParentProcBody(El: TPasElement): TProcedureBody;
 begin
   while El<>nil do

+ 5 - 5
packages/fcl-passrc/src/pparser.pp

@@ -123,11 +123,11 @@ resourcestring
   SParserNoConstructorAllowed = 'Constructors or Destructors are not allowed in Interfaces or Records';
   SParserNoFieldsAllowedInX = 'Fields are not allowed in %s';
   SParserInvalidRecordVisibility = 'Records can only have public and (strict) private as visibility specifiers';
-  SErrRecordConstantsNotAllowed = 'Record constants not allowed at this location.';
-  SErrRecordVariablesNotAllowed = 'Record variables not allowed at this location.';
-  SErrRecordMethodsNotAllowed = 'Record methods not allowed at this location.';
-  SErrRecordPropertiesNotAllowed = 'Record properties not allowed at this location.';
-  SErrRecordTypesNotAllowed = 'Record types not allowed at this location.';
+  SErrRecordConstantsNotAllowed = 'Record constants not allowed at this location';
+  SErrRecordVariablesNotAllowed = 'Record variables not allowed at this location';
+  SErrRecordMethodsNotAllowed = 'Record methods not allowed at this location';
+  SErrRecordPropertiesNotAllowed = 'Record properties not allowed at this location';
+  SErrRecordTypesNotAllowed = 'Record types not allowed at this location';
   SParserTypeNotAllowedHere = 'Type "%s" not allowed here';
   SParserNotAnOperand = 'Not an operand: (%d : %s)';
   SParserArrayPropertiesCannotHaveDefaultValue = 'Array properties cannot have default value';

+ 8 - 8
packages/fcl-passrc/src/pscanner.pp

@@ -4196,11 +4196,11 @@ var
   {$ifdef UsePChar}
   OldLength: integer;
   Ch: Char;
+  LE: string[2];
   {$else}
   s: string;
   l: integer;
   {$endif}
-  LE : String[2];
 
   procedure FetchCurTokenString; inline;
   begin
@@ -4327,7 +4327,7 @@ begin
     '(':
       begin
       Inc(FTokenPos);
-      if {$ifdef UsePChar}FTokenPos[0] = '.'{$else}(FTokenPos>l) or (s[FTokenPos]<>'.'){$endif} then
+      if {$ifdef UsePChar}FTokenPos[0] = '.'{$else}(FTokenPos<=l) and (s[FTokenPos]='.'){$endif} then
         begin
         Inc(FTokenPos);
         Result := tkSquaredBraceOpen;
@@ -4336,7 +4336,9 @@ begin
         Result := tkBraceOpen
       else
         begin
+        {$ifdef UsePChar}
         LE:=LineEnding;
+        {$endif}
         // Old-style multi-line comment
         Inc(FTokenPos);
         TokenStart := FTokenPos;
@@ -4353,13 +4355,11 @@ begin
             SetLength(FCurTokenString, OldLength + SectionLength + length(LineEnding)); // Corrected JC
             if SectionLength > 0 then
               Move(TokenStart^, FCurTokenString[OldLength + 1],SectionLength);
-
-            // Corrected JC: Append the correct lineending
             Inc(OldLength, SectionLength);
             for Ch in LE do
               begin
-                Inc(OldLength);
-                FCurTokenString[OldLength] := Ch;
+              Inc(OldLength);
+              FCurTokenString[OldLength] := Ch;
               end;
             {$else}
             FCurTokenString:=FCurTokenString+copy(FCurLine,TokenStart,SectionLength)+LineEnding; // Corrected JC
@@ -4519,7 +4519,7 @@ begin
         Inc(FTokenPos);
       until {$ifdef UsePChar}not (FTokenPos[0] in Digits){$else}(FTokenPos>l) or not (s[FTokenPos] in Digits){$endif};
       if {$ifdef UsePChar}(FTokenPos[0]='.') and (FTokenPos[1]<>'.') and (FTokenPos[1]<>')'){$else}
-          (FTokenPos<=l) and (s[FTokenPos]='.') and ((FTokenPos=l) or (s[FTokenPos+1]<>'.') and ((FTokenPos=l) or (s[FTokenPos+1]<>')')){$endif}then
+          (FTokenPos<=l) and (s[FTokenPos]='.') and ((FTokenPos=l) or ((s[FTokenPos+1]<>'.') and (s[FTokenPos+1]<>')'))){$endif}then
         begin
         inc(FTokenPos);
         while {$ifdef UsePChar}FTokenPos[0] in Digits{$else}(FTokenPos<=l) and (s[FTokenPos] in Digits){$endif} do
@@ -4654,11 +4654,11 @@ begin
       end;
     '{':        // Multi-line comment
       begin
-      LE:=LineEnding;
       Inc(FTokenPos);
       TokenStart := FTokenPos;
       FCurTokenString := '';
       {$ifdef UsePChar}
+      LE:=LineEnding;
       OldLength := 0;
       {$endif}
       NestingLevel := 0;

+ 122 - 20
packages/pastojs/src/fppas2js.pp

@@ -466,7 +466,6 @@ interface
 
 uses
   {$ifdef pas2js}
-  js,
   {$else}
   AVL_Tree,
   {$endif}
@@ -1673,6 +1672,7 @@ type
     function GetContextOfPasElement(El: TPasElement): TConvertContext;
     function GetFuncContextOfPasElement(El: TPasElement): TFunctionContext;
     function GetContextOfType(aType: TConvertContextClass): TConvertContext;
+    function GetMainSectionContext: TFunctionContext;
     function CurrentModeSwitches: TModeSwitches;
     function GetGlobalFunc: TFunctionContext;
     procedure WriteStack;
@@ -1922,7 +1922,9 @@ type
     Function GetTypeInfoName(El: TPasType; AContext: TConvertContext;
       ErrorEl: TPasElement; Full: boolean = false): String; virtual;
     Function TransformArgName(Arg: TPasArgument; AContext: TConvertContext): string; virtual;
-    Function CreateGlobalAlias(El: TPasElement; JSPath: string; AContext: TConvertContext): string; virtual;
+    Function CreateGlobalAliasForeign(El: TPasElement; JSPath: string; AContext: TConvertContext): string; virtual; // El in other module
+    Function CreateGlobalAliasNull(El: TPasElement; Prefix: TPas2JSBuiltInName;
+      SectionContext: TSectionContext): TFCLocalIdentifier; virtual;
     // utility functions for creating stuff
     Function IsElementUsed(El: TPasElement): boolean; virtual;
     Function IsSystemUnit(aModule: TPasModule): boolean; virtual;
@@ -7541,6 +7543,18 @@ begin
   until ctx=nil;
 end;
 
+function TConvertContext.GetMainSectionContext: TFunctionContext;
+var
+  Ctx: TConvertContext;
+begin
+  Ctx:=Self;
+  repeat
+    if Ctx is TSectionContext then
+      Result:=TSectionContext(Ctx);
+    Ctx:=Ctx.Parent;
+  until Ctx=nil;
+end;
+
 function TConvertContext.CurrentModeSwitches: TModeSwitches;
 begin
   if Resolver=nil then
@@ -14650,6 +14664,29 @@ Var
       end;
   end;
 
+  procedure InitForwards(Decls: TFPList; SectionContext: TSectionContext);
+  var
+    i: Integer;
+    P: TPasElement;
+    C: TClass;
+  begin
+    For i:=0 to Decls.Count-1 do
+      begin
+      P:=TPasElement(Decls[i]);
+      if not IsElementUsed(P) then continue;
+      C:=P.ClassType;
+      if (C=TPasClassType) and TPasClassType(P).IsForward then
+        continue;
+      if (C=TPasClassType) or (C=TPasRecordType) or (C=TPasEnumType) then
+        begin
+        // add var $lt = null;
+        CreateGlobalAliasNull(P,pbivnLocalTypeRef,SectionContext);
+        if (C=TPasClassType) or (C=TPasRecordType) then
+          InitForwards(TPasMembersType(P).Members,SectionContext);
+        end;
+      end;
+  end;
+
   procedure InitSection(Section: TPasSection);
   var
     SectionScope: TPas2JSSectionScope;
@@ -14665,6 +14702,18 @@ Var
     SectionCtx:=TSectionContext(AContext);
     Src:=SectionCtx.JSElement as TJSSourceElements;
     SectionCtx.HeaderIndex:=Src.Statements.Count;
+
+    // add local vars for forward declarations
+    if (coShortRefGlobals in Options)
+        and (Section.ClassType<>TImplementationSection) then
+      begin
+      InitForwards(Section.Declarations,TSectionContext(AContext));
+      if Section is TInterfaceSection then
+        begin
+        InitForwards(TPasModule(Section.Parent).ImplementationSection.Declarations,
+                     TSectionContext(AContext));
+        end;
+      end;
   end;
 
 var
@@ -14846,7 +14895,7 @@ var
   P: TPasElement;
   Scope: TPas2JSClassScope;
   Ancestor: TPasType;
-  AncestorPath, OwnerName, DestructorName, FnName, IntfKind: String;
+  AncestorPath, OwnerName, DestructorName, FnName, IntfKind, JSName: String;
   C: TClass;
   AssignSt: TJSSimpleAssignStatement;
   NeedInitFunction, HasConstructor, IsJSFunction, NeedClassExt,
@@ -14926,7 +14975,8 @@ begin
     Call.AddArg(CreatePrimitiveDotExpr(OwnerName,El));
 
     // add parameter: string constant '"classname"'
-    ArgEx := CreateLiteralString(El,TransformElToJSName(El,AContext));
+    JSName:=TransformElToJSName(El,AContext);
+    ArgEx:=CreateLiteralString(El,JSName);
     Call.AddArg(ArgEx);
 
     if El.ObjKind=okInterface then
@@ -14985,6 +15035,18 @@ begin
       FuncContext.ThisVar.Element:=El;
       FuncContext.ThisVar.Kind:=cvkGlobal;
 
+      if coShortRefGlobals in Options then
+        begin
+        // $lt = this;
+        JSName:=AContext.GetLocalName(El,[cvkGlobal]);
+        if JSName='' then
+          RaiseNotSupported(El,AContext,20200926232402);
+        AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
+        AssignSt.LHS:=CreatePrimitiveDotExpr(JSName,El);
+        AssignSt.Expr:=CreatePrimitiveDotExpr('this',El);
+        AddToSourceElements(Src,AssignSt);
+        end;
+
       if IntfKind<>'' then
         begin
         // add this.$kind="com";
@@ -15278,6 +15340,8 @@ function TPasToJSConverter.ConvertEnumType(El: TPasEnumType;
 //     minvalue: 0,
 //     maxvalue: 1
 //   });
+//  coShortRefGlobals:
+//  $lt = this.TMyEnum ...
 var
   ObjectContect: TObjectContext;
   i: Integer;
@@ -15285,7 +15349,7 @@ var
   ParentObj, Obj, TIObj: TJSObjectLiteral;
   ObjLit, TIProp: TJSObjectLiteralElement;
   AssignSt: TJSSimpleAssignStatement;
-  JSName: TJSString;
+  JSName: string;
   Call: TJSCallExpression;
   List: TJSStatementList;
   ok: Boolean;
@@ -15293,6 +15357,7 @@ var
   Src: TJSSourceElements;
   ProcScope: TPas2JSProcedureScope;
   VarSt: TJSVariableStatement;
+  SectionContext: TSectionContext;
 begin
   Result:=nil;
   for i:=0 to El.Values.Count-1 do
@@ -15322,11 +15387,14 @@ begin
     else if El.Parent is TProcedureBody then
       begin
       // add 'var TypeName = {}'
-      VarSt:=CreateVarStatement(TransformElToJSName(El,AContext),Obj,El);
+      JSName:=TransformElToJSName(El,AContext);
+      VarSt:=CreateVarStatement(JSName,Obj,El);
       if AContext.JSElement is TJSSourceElements then
         begin
         Src:=TJSSourceElements(AContext.JSElement);
         AddToSourceElements(Src,VarSt); // keep Result=nil
+        if AContext is TFunctionContext then
+          TFunctionContext(AContext).AddLocalVar(JSName,El,cvkGlobal,false);
         end
       else
         Result:=VarSt;
@@ -15338,20 +15406,32 @@ begin
       AssignSt.LHS:=CreateSubDeclNameExpr(El,AContext);
       AssignSt.Expr:=Obj;
       Result:=AssignSt;
+      if coShortRefGlobals in Options then
+        begin
+        SectionContext:=TSectionContext(AContext.GetMainSectionContext);
+        JSName:=SectionContext.GetLocalName(El,[cvkGlobal]);
+        if JSName='' then
+          RaiseNotSupported(El,AContext,20200926232620);
+        // $lt = this.TypeName = {}
+        AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
+        AssignSt.LHS:=CreatePrimitiveDotExpr(JSName,El);
+        AssignSt.Expr:=Result;
+        Result:=AssignSt;
+        end;
       end;
 
     ObjectContect:=TObjectContext.Create(El,Obj,AContext);
     for i:=0 to El.Values.Count-1 do
       begin
       EnumValue:=TPasEnumValue(El.Values[i]);
-      JSName:=TJSString(TransformElToJSName(EnumValue,AContext));
+      JSName:=TransformElToJSName(EnumValue,AContext);
       // add "0":"value"
       ObjLit:=Obj.Elements.AddElement;
       ObjLit.Name:=TJSString(IntToStr(i));
-      ObjLit.Expr:=CreateLiteralJSString(El,JSName);
+      ObjLit.Expr:=CreateLiteralJSString(El,TJSString(JSName));
       // add value:0
       ObjLit:=Obj.Elements.AddElement;
-      ObjLit.Name:=JSName;
+      ObjLit.Name:=TJSString(JSName);
       ObjLit.Expr:=CreateLiteralNumber(El,i);
       end;
 
@@ -16930,11 +17010,9 @@ var
   SectionCtx: TSectionContext;
 begin
   if JS=nil then exit;
-  SectionCtx:=TSectionContext(aContext.GetContextOfType(TSectionContext));
+  SectionCtx:=TSectionContext(aContext.GetMainSectionContext);
   if SectionCtx=nil then
     RaiseNotSupported(PosEl,aContext,20200606142555);
-  if SectionCtx.Parent is TSectionContext then
-    SectionCtx:=TSectionContext(SectionCtx.Parent);
   SectionCtx.AddHeaderStatement(JS);
 end;
 
@@ -24187,7 +24265,7 @@ begin
     RaiseNotSupported(El,AContext,20200609230526,GetObjPath(El));
   Result:=Result+'.'+TransformElToJSName(El,AContext);
   if ShortRefGlobals then
-    Result:=CreateGlobalAlias(El,Result,AContext);
+    Result:=CreateGlobalAliasForeign(El,Result,AContext);
 end;
 
 procedure TPasToJSConverter.CreateProcedureCall(var Call: TJSCallExpression;
@@ -25299,7 +25377,7 @@ var
   DelaySrc: TJSSourceElements;
   DelayFuncContext: TFunctionContext;
   Call: TJSCallExpression;
-  JSParentName: String;
+  JSParentName, JSName: String;
   FunDecl: TJSFunctionDeclarationStatement;
   Src: TJSSourceElements;
   FuncContext: TFunctionContext;
@@ -25312,6 +25390,7 @@ var
   NewFields, Vars, Methods: TFPList;
   ok, IsComplex, SpecializeDelay: Boolean;
   VarSt: TJSVariableStatement;
+  AssignSt: TJSSimpleAssignStatement;
 begin
   Result:=nil;
   if El.Name='' then
@@ -25343,7 +25422,8 @@ begin
         RaiseNotSupported(El,AContext,20190105104054);
       // local record type elevated to global scope
       Src:=TJSSourceElements(AContext.JSElement);
-      VarSt:=CreateVarStatement(TransformElToJSName(El,AContext),Call,El);
+      JSName:=TransformElToJSName(El,AContext);
+      VarSt:=CreateVarStatement(JSName,Call,El);
       AddToSourceElements(Src,VarSt); // keep Result=nil
       // add parameter: parent = null
       Call.AddArg(CreateLiteralNull(El));
@@ -25380,6 +25460,18 @@ begin
     FuncContext.ThisVar.Element:=El;
     FuncContext.ThisVar.Kind:=cvkGlobal;
 
+    if (coShortRefGlobals in Options) and not (El.Parent is TProcedureBody) then
+      begin
+      // $lt = this;
+      JSName:=AContext.GetLocalName(El,[cvkGlobal]);
+      if JSName='' then
+        RaiseNotSupported(El,AContext,20200926235501);
+      AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
+      AssignSt.LHS:=CreatePrimitiveDotExpr(JSName,El);
+      AssignSt.Expr:=CreatePrimitiveDotExpr('this',El);
+      AddToSourceElements(Src,AssignSt);
+      end;
+
     // init fields
     NewFields:=TFPList.Create;
     Vars:=TFPList.Create;
@@ -25692,7 +25784,7 @@ begin
       Result:=GetBIName(pbivnModules)+'.'+Result;
 
     if coShortRefGlobals in Options then
-      Result:=CreateGlobalAlias(El,Result,AContext);
+      Result:=CreateGlobalAliasForeign(El,Result,AContext);
     end;
 end;
 
@@ -25939,7 +26031,7 @@ begin
     Result:=TransformToJSName(Arg,Result,true,AContext);
 end;
 
-function TPasToJSConverter.CreateGlobalAlias(El: TPasElement; JSPath: string;
+function TPasToJSConverter.CreateGlobalAliasForeign(El: TPasElement; JSPath: string;
   AContext: TConvertContext): string;
 var
   ElModule, MyModule: TPasModule;
@@ -25965,9 +26057,7 @@ begin
   else
     begin
     // El is from another unit
-    SectionContext:=TSectionContext(AContext.GetContextOfType(TSectionContext));
-    if SectionContext.Parent is TSectionContext then
-      SectionContext:=TSectionContext(SectionContext.Parent);
+    SectionContext:=TSectionContext(AContext.GetMainSectionContext);
 
     FuncContext:=AContext.GetFunctionContext;
     if El is TPasModule then
@@ -26003,6 +26093,18 @@ begin
     end;
 end;
 
+function TPasToJSConverter.CreateGlobalAliasNull(El: TPasElement;
+  Prefix: TPas2JSBuiltInName; SectionContext: TSectionContext
+  ): TFCLocalIdentifier;
+var
+  V: TJSVariableStatement;
+begin
+  // insert var $lt = null;
+  Result:=SectionContext.AddLocalVar(GetBIName(Prefix),El,cvkGlobal,true);
+  V:=CreateVarStatement(Result.Name,CreateLiteralNull(El),El);
+  AddHeaderStatement(V,El,SectionContext);
+end;
+
 function TPasToJSConverter.ConvertPasElement(El: TPasElement;
   Resolver: TPas2JSResolver): TJSElement;
 var

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

@@ -25,7 +25,7 @@ unit FPPJsSrcMap;
 interface
 
 uses
-  Classes, SysUtils, math,
+  SysUtils, math,
   jswriter, jstree, JSSrcMap;
 
 type

+ 1 - 0
packages/pastojs/src/pas2jscompiler.pp

@@ -1182,6 +1182,7 @@ begin
   // maybe emit message ?
   FResourceHandler.StartUnit(PasModule.Name);
   FResourceHandler.HandleResource(aFileName,aOptions);
+  if Sender=nil then ;
 end;
 
 function TPas2jsCompilerFile.OnConverterIsElementUsed(Sender: TObject;

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

@@ -26,7 +26,7 @@ uses
   {$IFDEF NodeJS}
   node.fs,
   {$ENDIF}
-  Classes, SysUtils, Pas2jsFileUtils, Pas2JSFS, Pas2jsCompiler;
+  SysUtils, Pas2jsFileUtils, Pas2JSFS, Pas2jsCompiler;
 
 Type
   TPas2JSFileConfigSupport = Class(TPas2JSConfigSupport)

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

@@ -23,7 +23,7 @@ unit Pas2JSFSCompiler;
 interface
 
 uses
-  Classes, SysUtils,
+  SysUtils,
   PasUseAnalyzer,
   Pas2jsFileCache, Pas2jsCompiler,
   Pas2JSFS,

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

@@ -5,7 +5,7 @@ unit pas2jsresstrfile;
 interface
 
 uses
-  Classes, SysUtils, fpJSON;
+  SysUtils, fpJSON;
 
 Type
 

+ 320 - 33
packages/pastojs/tests/tcoptimizations.pas

@@ -61,6 +61,9 @@ type
     procedure TestOptShortRefGlobals_Unit_FromIntfImpl_ToIntfImpl;
     procedure TestOptShortRefGlobals_Property;
     procedure TestOptShortRefGlobals_GenericFunction;
+    procedure TestOptShortRefGlobals_SameUnit_EnumType;
+    procedure TestOptShortRefGlobals_SameUnit_ClassType;
+    procedure TestOptShortRefGlobals_SameUnit_RecordType;
 
     // Whole Program Optimization
     procedure TestWPO_OmitLocalVar;
@@ -245,24 +248,26 @@ begin
   ConvertProgram;
   CheckSource('TestOptShortRefGlobals_Program',
     LinesToStr([
+    'var $lt = null;',
     'var $lm = pas.UnitA;',
-    'var $lt = $lm.TBird;',
-    'var $lt1 = $lm.TRec;',
-    'rtl.createClass(this, "TEagle", $lt, function () {',
+    'var $lt1 = $lm.TBird;',
+    'var $lt2 = $lm.TRec;',
+    'rtl.createClass(this, "TEagle", $lt1, function () {',
+    '  $lt = this;',
     '  this.Run = function (w) {',
     '    var Result = 0;',
     '    return Result;',
     '  };',
     '});',
     'this.e = null;',
-    'this.r = $lt1.$new();',
+    'this.r = $lt2.$new();',
     'this.c = {};',
     '']),
     LinesToStr([
-    '$mod.e = $mod.TEagle.$create("Create");',
-    '$lm.b = $lt.$create("Create");',
-    '$lt.c = $mod.e.c + 1;',
-    '$mod.r.x = $lt.c;',
+    '$mod.e = $lt.$create("Create");',
+    '$lm.b = $lt1.$create("Create");',
+    '$lt1.c = $mod.e.c + 1;',
+    '$mod.r.x = $lt1.c;',
     '$mod.r.x = $lm.b.c;',
     '$mod.r.x = $mod.e.$class.Run(5);',
     '$mod.r.x = $mod.e.$class.Run(5);',
@@ -351,42 +356,46 @@ begin
   CheckSource('TestOptShortRefGlobals_Unit_FromIntfImpl_ToIntfImpl',
     LinesToStr([
     'var $impl = $mod.$impl;',
+    'var $lt = null;',
+    'var $lt1 = null;',
     'var $lm = pas.UnitA;',
-    'var $lt = $lm.TBird;',
+    'var $lt2 = $lm.TBird;',
     'var $lm1 = null;',
-    'var $lt1 = null;',
-    'var $lt2 = null;',
     'var $lt3 = null;',
-    'rtl.createClass(this, "TEagle", $lt, function () {',
+    'var $lt4 = null;',
+    'var $lt5 = null;',
+    'rtl.createClass(this, "TEagle", $lt2, function () {',
+    '  $lt = this;',
     '  this.Fly = function () {',
-    '    $impl.TRedAnt.$create("Create");',
     '    $lt1.$create("Create");',
+    '    $lt3.$create("Create");',
+    '    $lt2.$create("Create");',
     '    $lt.$create("Create");',
-    '    $mod.TEagle.$create("Create");',
     '  };',
     '});',
     '']),
     LinesToStr([
-    '$impl.RedAnt = $impl.TRedAnt.$create("Create");',
-    '$impl.Ant = $lt1.$create("Create");',
-    '$impl.Bird = $lt.$create("Create");',
-    '$impl.Eagle = $mod.TEagle.$create("Create");',
-    '$lt3.$create("Create");',
+    '$impl.RedAnt = $lt1.$create("Create");',
+    '$impl.Ant = $lt3.$create("Create");',
+    '$impl.Bird = $lt2.$create("Create");',
+    '$impl.Eagle = $lt.$create("Create");',
+    '$lt5.$create("Create");',
     '$impl.Eagle.Fly();',
     '$impl.RedAnt.Run();',
     '']),
     LinesToStr([
     '$lm1 = pas.UnitB;',
-    '$lt1 = $lm1.TAnt;',
-    '$lt2 = $lm1.TBear;',
-    '$lt3 = $lm1.TFrog;',
-    'rtl.createClass($impl, "TRedAnt", $lt1, function () {',
+    '$lt3 = $lm1.TAnt;',
+    '$lt4 = $lm1.TBear;',
+    '$lt5 = $lm1.TFrog;',
+    'rtl.createClass($impl, "TRedAnt", $lt3, function () {',
+    '  $lt1 = this;',
     '  this.Run = function () {',
-    '    $impl.TRedAnt.$create("Create");',
     '    $lt1.$create("Create");',
-    '    $lt.$create("Create");',
-    '    $mod.TEagle.$create("Create");',
+    '    $lt3.$create("Create");',
     '    $lt2.$create("Create");',
+    '    $lt.$create("Create");',
+    '    $lt4.$create("Create");',
     '  };',
     '});',
     '$impl.RedAnt = null;',
@@ -430,9 +439,11 @@ begin
   ConvertUnit;
   CheckSource('TestOptShortRefGlobals_Property',
     LinesToStr([
+    'var $lt = null;',
     'var $lm = pas.UnitA;',
-    'var $lt = $lm.TBird;',
-    'rtl.createClass(this, "TEagle", $lt, function () {',
+    'var $lt1 = $lm.TBird;',
+    'rtl.createClass(this, "TEagle", $lt1, function () {',
+    '  $lt = this;',
     '  this.Fly = function (o) {',
     '    this.Fly(this.FWing);',
     '    this.Fly(this.FLeg);',
@@ -474,11 +485,13 @@ begin
   ConvertUnit;
   CheckSource('TestOptShortRefGlobals_GenericFunction',
     LinesToStr([
+    'var $lt = null;',
     'var $lm = pas.system;',
-    'var $lt = $lm.TObject;',
+    'var $lt1 = $lm.TObject;',
     'var $lm1 = pas.UnitA;',
     'var $lp = $lm1.Run$G1;',
-    'rtl.createClass(this, "TEagle", $lt, function () {',
+    'rtl.createClass(this, "TEagle", $lt1, function () {',
+    '  $lt = this;',
     '});',
     'this.Fly = function () {',
     '  $lp(null);',
@@ -490,6 +503,280 @@ begin
     '']));
 end;
 
+procedure TTestOptimizations.TestOptShortRefGlobals_SameUnit_EnumType;
+begin
+  StartUnit(true,[supTObject]);
+  Add([
+  '{$optimization JSShortRefGlobals}',
+  'interface',
+  'type',
+  '  TBird = class',
+  '  type',
+  '    TFlag = (big,small);',
+  '    procedure Fly;',
+  '  end;',
+  '  TEnum = (red,blue);',
+  'var',
+  '  e: TEnum;',
+  '  f: TBird.TFlag;',
+  'procedure Run;',
+  'implementation',
+  'procedure TBird.Fly;',
+  'begin',
+  '  e:=blue;',
+  '  f:=small;',
+  'end;',
+  'procedure Run;',
+  'type TSub = (left,right);',
+  'var s: TSub;',
+  'begin',
+  '  e:=red;',
+  '  s:=right;',
+  '  f:=big;',
+  'end;',
+  '']);
+  ConvertUnit;
+  CheckSource('TestOptShortRefGlobals_SameUnit_EnumType',
+    LinesToStr([
+    'var $lt = null;',
+    'var $lt1 = null;',
+    'var $lt2 = null;',
+    'var $lm = pas.system;',
+    'var $lt3 = $lm.TObject;',
+    'rtl.createClass(this, "TBird", $lt3, function () {',
+    '  $lt = this;',
+    '  $lt1 = this.TFlag = {',
+    '    "0": "big",',
+    '    big: 0,',
+    '    "1": "small",',
+    '    small: 1',
+    '  };',
+    '  this.Fly = function () {',
+    '    $mod.e = $lt2.blue;',
+    '    $mod.f = $lt1.small;',
+    '  };',
+    '});',
+    '$lt2 = this.TEnum = {',
+    '  "0": "red",',
+    '  red: 0,',
+    '  "1": "blue",',
+    '  blue: 1',
+    '};',
+    'this.e = 0;',
+    'this.f = 0;',
+    'var TSub = {',
+    '  "0": "left",',
+    '  left: 0,',
+    '  "1": "right",',
+    '  right: 1',
+    '};',
+    'this.Run = function () {',
+    '  var s = 0;',
+    '  $mod.e = $lt2.red;',
+    '  s = TSub.right;',
+    '  $mod.f = $lt1.big;',
+    '};',
+    '']),
+    LinesToStr([
+    '']),
+    LinesToStr([
+    '']));
+end;
+
+procedure TTestOptimizations.TestOptShortRefGlobals_SameUnit_ClassType;
+begin
+  WithTypeInfo:=true;
+  StartUnit(true,[supTObject]);
+  Add([
+  '{$optimization JSShortRefGlobals}',
+  'interface',
+  'type',
+  '  TBird = class;',
+  '  TAnt = class',
+  '  type',
+  '    TLeg = class',
+  '    end;',
+  '    procedure Run;',
+  '  published',
+  '    Bird: TBird;',
+  '  end;',
+  '  TBird = class',
+  '    procedure Fly;',
+  '  end;',
+  'implementation',
+  'type',
+  '  TFrog = class',
+  '  end;',
+  'procedure TAnt.Run;',
+  'begin',
+  '  if typeinfo(TBird)=nil then;',
+  '  Bird:=TBird.Create;',
+  '  TLeg.Create;',
+  '  TFrog.Create;',
+  'end;',
+  'procedure TBird.Fly;',
+  'begin',
+  '  if typeinfo(TAnt)=nil then;',
+  'end;',
+  '']);
+  ConvertUnit;
+  CheckSource('TestOptShortRefGlobals_SameUnit_ClassType',
+    LinesToStr([
+    'var $impl = $mod.$impl;',
+    'var $lt = null;',
+    'var $lt1 = null;',
+    'var $lt2 = null;',
+    'var $lt3 = null;',
+    'var $lm = pas.system;',
+    'var $lt4 = $lm.TObject;',
+    'this.$rtti.$Class("TBird");',
+    'rtl.createClass(this, "TAnt", $lt4, function () {',
+    '  $lt = this;',
+    '  rtl.createClass(this, "TLeg", $lt4, function () {',
+    '    $lt1 = this;',
+    '  });',
+    '  this.$init = function () {',
+    '    $lt4.$init.call(this);',
+    '    this.Bird = null;',
+    '  };',
+    '  this.$final = function () {',
+    '    this.Bird = undefined;',
+    '    $lt4.$final.call(this);',
+    '  };',
+    '  this.Run = function () {',
+    '    if ($mod.$rtti["TBird"] === null) ;',
+    '    this.Bird = $lt2.$create("Create");',
+    '    $lt1.$create("Create");',
+    '    $lt3.$create("Create");',
+    '  };',
+    '  var $r = this.$rtti;',
+    '  $r.addField("Bird", $mod.$rtti["TBird"]);',
+    '});',
+    'rtl.createClass(this, "TBird", $lt4, function () {',
+    '  $lt2 = this;',
+    '  this.Fly = function () {',
+    '    if ($mod.$rtti["TAnt"] === null) ;',
+    '  };',
+    '});',
+    '']),
+    LinesToStr([
+    '']),
+    LinesToStr([
+    'rtl.createClass($impl, "TFrog", $lt4, function () {',
+    '  $lt3 = this;',
+    '});',
+    '']));
+end;
+
+procedure TTestOptimizations.TestOptShortRefGlobals_SameUnit_RecordType;
+begin
+  StartUnit(true,[supTObject]);
+  Add([
+  '{$optimization JSShortRefGlobals}',
+  '{$modeswitch advancedrecords}',
+  'interface',
+  'type',
+  '  TAnt = record',
+  '  type',
+  '    TLeg = record',
+  '      l: word;',
+  '    end;',
+  '    procedure Run;',
+  '    Leg: TLeg;',
+  '  end;',
+  'implementation',
+  'type',
+  '  TBird = record',
+  '    b: word;',
+  '  end;',
+  'procedure TAnt.Run;',
+  'type',
+  '  TFoot = record',
+  '    f: word;',
+  '  end;',
+  'var',
+  '  b: TBird;',
+  '  l: TLeg;',
+  '  a: TAnt;',
+  '  f: TFoot;',
+  'begin',
+  '  b.b:=1;',
+  '  l.l:=2;',
+  '  a.Leg.l:=3;',
+  '  f.f:=4;',
+  'end;',
+  '']);
+  ConvertUnit;
+  CheckSource('TestOptShortRefGlobals_SameUnit_RecordType',
+    LinesToStr([
+    'var $impl = $mod.$impl;',
+    'var $lt = null;',
+    'var $lt1 = null;',
+    'var $lt2 = null;',
+    'rtl.recNewT(this, "TAnt", function () {',
+    '  $lt = this;',
+    '  rtl.recNewT($lt, "TLeg", function () {',
+    '    $lt1 = this;',
+    '    this.l = 0;',
+    '    this.$eq = function (b) {',
+    '      return this.l === b.l;',
+    '    };',
+    '    this.$assign = function (s) {',
+    '      this.l = s.l;',
+    '      return this;',
+    '    };',
+    '  });',
+    '  this.$new = function () {',
+    '    var r = Object.create(this);',
+    '    r.Leg = $lt1.$new();',
+    '    return r;',
+    '  };',
+    '  this.$eq = function (b) {',
+    '    return this.Leg.$eq(b.Leg);',
+    '  };',
+    '  this.$assign = function (s) {',
+    '    this.Leg.$assign(s.Leg);',
+    '    return this;',
+    '  };',
+    '  var TFoot = rtl.recNewT(null, "", function () {',
+    '    this.f = 0;',
+    '    this.$eq = function (b) {',
+    '      return this.f === b.f;',
+    '    };',
+    '    this.$assign = function (s) {',
+    '      this.f = s.f;',
+    '      return this;',
+    '    };',
+    '  });',
+    '  this.Run = function () {',
+    '    var b = $lt2.$new();',
+    '    var l = $lt1.$new();',
+    '    var a = $lt.$new();',
+    '    var f = TFoot.$new();',
+    '    b.b = 1;',
+    '    l.l = 2;',
+    '    a.Leg.l = 3;',
+    '    f.f = 4;',
+    '  };',
+    '}, true);',
+    '']),
+    LinesToStr([
+    '']),
+    LinesToStr([
+    'rtl.recNewT($impl, "TBird", function () {',
+    '  $lt2 = this;',
+    '  this.b = 0;',
+    '  this.$eq = function (b) {',
+    '    return this.b === b.b;',
+    '  };',
+    '  this.$assign = function (s) {',
+    '    this.b = s.b;',
+    '    return this;',
+    '  };',
+    '});',
+    '']));
+end;
+
 procedure TTestOptimizations.TestWPO_OmitLocalVar;
 begin
   StartProgram(false);
@@ -1311,7 +1598,7 @@ procedure TTestOptimizations.TestWPO_ConstructorDefaultValueConst;
 var
   ActualSrc, ExpectedSrc: String;
 begin
-  Converter.Options:=Converter.Options-[coNoTypeInfo];
+  WithTypeInfo:=true;
   StartProgram(true);
   Add([
   'const gcBlack = 0;',
@@ -1362,7 +1649,7 @@ procedure TTestOptimizations.TestWPO_RTTI_PublishedField;
 var
   ActualSrc, ExpectedSrc: String;
 begin
-  Converter.Options:=Converter.Options-[coNoTypeInfo];
+  WithTypeInfo:=true;
   StartProgram(true);
   Add('type');
   Add('  TArrA = array of char;');
@@ -1410,7 +1697,7 @@ procedure TTestOptimizations.TestWPO_RTTI_TypeInfo;
 var
   ActualSrc, ExpectedSrc: String;
 begin
-  Converter.Options:=Converter.Options-[coNoTypeInfo];
+  WithTypeInfo:=true;
   StartProgram(true);
   Add('type');
   Add('  TArrA = array of char;');

+ 1 - 1
rtl/inc/systemh.inc

@@ -1143,7 +1143,7 @@ function fpc_SarInt64(Const AValue : Int64;const Shift : Byte): Int64;compilerpr
 {$endif}
 
 {$ifdef FPC_HAS_INTERNAL_BSR}
-{$if defined(cpui386) or defined(cpux86_64) or defined(cpuarm) or defined(cpuaarch64) or defined(cpupowerpc32) or defined(cpupowerpc64)}
+{$if defined(cpui386) or defined(cpux86_64) or defined(cpuarm) or defined(cpuaarch64) or defined(cpupowerpc32) or defined(cpupowerpc64) or defined(cpuxtensa)}
 {$define FPC_HAS_INTERNAL_BSR_BYTE}
 {$define FPC_HAS_INTERNAL_BSR_WORD}
 {$define FPC_HAS_INTERNAL_BSR_DWORD}

+ 1 - 0
rtl/inc/varianth.inc

@@ -113,6 +113,7 @@ type
                      varerror : (verror : hresult);
                      varboolean : (vboolean : wordbool);
                      varunknown : (vunknown : pointer);
+                     varustring : (vustring : pointer);
                      // vardecimal : ( : );
                      varshortint : (vshortint : shortint);
                      varbyte : (vbyte : byte);