Browse Source

* major parts of the RiscV paramgr unified, improves code generation and less failures in RiscV32 regression tests

florian 7 months ago
parent
commit
49aa141703
4 changed files with 304 additions and 578 deletions
  1. 293 17
      compiler/riscv/pararv.pas
  2. 5 268
      compiler/riscv32/cpupara.pas
  3. 2 0
      compiler/riscv64/cgcpu.pas
  4. 4 293
      compiler/riscv64/cpupara.pas

+ 293 - 17
compiler/riscv/pararv.pas

@@ -39,11 +39,15 @@ unit pararv;
         function get_saved_registers_fpu(calloption: tproccalloption): tcpuregisterarray;override;
         function get_saved_registers_fpu(calloption: tproccalloption): tcpuregisterarray;override;
         function get_saved_registers_int(calloption: tproccalloption): tcpuregisterarray;override;
         function get_saved_registers_int(calloption: tproccalloption): tcpuregisterarray;override;
 
 
+        function get_funcretloc(p: tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
+
         procedure getcgtempparaloc(list: TAsmList; pd: tabstractprocdef; nr: longint; var cgpara: tcgpara);override;
         procedure getcgtempparaloc(list: TAsmList; pd: tabstractprocdef; nr: longint; var cgpara: tcgpara);override;
 
 
-        function create_paraloc_info_intern(p: tabstractprocdef; side: tcallercallee; paras: tparalist; var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; isVararg : boolean): longint;virtual;abstract;
+        function create_paraloc_info_intern(p: tabstractprocdef; side: tcallercallee; paras: tparalist; var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; isVararg : boolean): longint;virtual;
+        procedure create_paraloc_for_def(var para: TCGPara; varspez: tvarspez; paradef: tdef; var nextfloatreg, nextintreg: tsuperregister; var stack_offset: aword; const isVararg, forceintmem: boolean; const side: tcallercallee; const p: tabstractprocdef);virtual;
 
 
         function create_varargs_paraloc_info(p: tabstractprocdef; side: tcallercallee; varargspara: tvarargsparalist): longint;override;
         function create_varargs_paraloc_info(p: tabstractprocdef; side: tcallercallee; varargspara: tvarargsparalist): longint;override;
+
       protected
       protected
         procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
         procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
       end;
       end;
@@ -57,14 +61,13 @@ implementation
       globals,
       globals,
       cpuinfo,
       cpuinfo,
       symsym,
       symsym,
+      symtable,
       defutil,
       defutil,
-      cpubase;
+      cpubase,
+      procinfo,cpupi;
 
 
     function getparaloc(p : tdef) : tcgloc;
     function getparaloc(p : tdef) : tcgloc;
       begin
       begin
-         { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
-           if push_addr_param for the def is true
-         }
          case p.typ of
          case p.typ of
             orddef:
             orddef:
               result:=LOC_REGISTER;
               result:=LOC_REGISTER;
@@ -83,22 +86,12 @@ implementation
             classrefdef:
             classrefdef:
               result:=LOC_REGISTER;
               result:=LOC_REGISTER;
             procvardef:
             procvardef:
-            { this must be fixed for RISC64, the ifdef is not correct }
-{$ifdef RISCV32}
-              if (p.size = sizeof(pint)) then
-                result:=LOC_REGISTER
-              else
-                result:=LOC_REFERENCE;
-{$else RISCV32}
+              { method pointers fit into two registers, so pass procedure variables always in registers }
               result:=LOC_REGISTER;
               result:=LOC_REGISTER;
-{$endif RISCV32}
             recorddef:
             recorddef:
-            { this must be fixed for RISC64, the ifdef is not correct }
-{$ifdef RISCV32}
-              if (p.size > sizeof(pint)) then
+              if (p.size > sizeof(pint)*2) then
                 result:=LOC_REFERENCE
                 result:=LOC_REFERENCE
               else
               else
-{$endif RISCV32}
                 result:=LOC_REGISTER;
                 result:=LOC_REGISTER;
             objectdef:
             objectdef:
               if is_object(p) then
               if is_object(p) then
@@ -198,6 +191,21 @@ implementation
       end;
       end;
 
 
 
 
+    function trvparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
+      var
+        paraloc : pcgparalocation;
+        retcgsize  : tcgsize;
+        nextintreg, nextfloatreg, nextmmreg: tsuperregister;
+        stack_offset: aword;
+      begin
+        if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
+          exit;
+
+        init_values(nextintreg,nextfloatreg,nextmmreg,stack_offset);
+        create_paraloc_for_def(result,vs_value,result.def,nextfloatreg,nextintreg,stack_offset,false,false,side,p);
+      end;
+
+
     procedure trvparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
     procedure trvparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
       begin
       begin
         { register parameter save area begins at 48(r2) }
         { register parameter save area begins at 48(r2) }
@@ -245,6 +253,274 @@ implementation
         create_funcretloc_info(p,side);
         create_funcretloc_info(p,side);
       end;
       end;
 
 
+
+    function trvparamanager.create_paraloc_info_intern(p: tabstractprocdef; side: tcallercallee; paras: tparalist; var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; isVararg : boolean): longint;
+      var
+        nextintreg, nextfloatreg, nextmmreg : tsuperregister;
+        i: integer;
+        hp: tparavarsym;
+        paraloc: pcgparalocation;
+        delphi_nestedfp: boolean;
+      begin
+{$IFDEF extdebug}
+        if po_explicitparaloc in p.procoptions then
+          internalerror(200411141);
+{$ENDIF extdebug}
+
+        result := 0;
+        nextintreg := curintreg;
+        nextfloatreg := curfloatreg;
+        nextmmreg := curmmreg;
+
+        for i := 0 to paras.count - 1 do
+          begin
+            hp := tparavarsym(paras[i]);
+
+            if (vo_has_explicit_paraloc in hp.varoptions) then
+              internalerror(2024122201);
+
+            { currently only support C-style array of const }
+            if (p.proccalloption in [pocall_cdecl, pocall_cppdecl]) and
+              is_array_of_const(hp.vardef) then begin
+              paraloc := hp.paraloc[side].add_location;
+              { hack: the paraloc must be valid, but is not actually used }
+              paraloc^.loc := LOC_REGISTER;
+              paraloc^.register := NR_X0;
+              paraloc^.size := OS_ADDR;
+              paraloc^.def := voidpointertype;
+              break;
+            end;
+            delphi_nestedfp:=(vo_is_parentfp in hp.varoptions) and (po_delphi_nested_cc in p.procoptions);
+            create_paraloc_for_def(hp.paraloc[side], hp.varspez, hp.vardef,
+              nextfloatreg, nextintreg, cur_stack_offset, isVararg, delphi_nestedfp, side, p);
+          end;
+
+        curintreg := nextintreg;
+        curfloatreg := nextfloatreg;
+        curmmreg := nextmmreg;
+        result := cur_stack_offset;
+      end;
+
+
+    procedure trvparamanager.create_paraloc_for_def(var para: TCGPara; varspez: tvarspez; paradef: tdef; var nextfloatreg, nextintreg: tsuperregister; var stack_offset: aword; const isVararg, forceintmem: boolean; const side: tcallercallee; const p: tabstractprocdef);
+      var
+        paracgsize: tcgsize;
+        loc: tcgloc;
+        paraloc: pcgparalocation;
+        { def to use for all paralocs if <> nil }
+        alllocdef,
+        { def to use for the current paraloc }
+        locdef,
+        tmpdef: tdef;
+        paralen: aint;
+        firstparaloc,
+        paraaligned: boolean;
+      begin
+        alllocdef:=nil;
+        locdef:=nil;
+        para.reset;
+        { have we ensured that the next parameter location will be aligned to the
+          next 8 byte boundary? }
+        paraaligned:=false;
+        if push_addr_param(varspez, paradef, p.proccalloption) then
+          begin
+            paradef := cpointerdef.getreusable_no_free(paradef);
+            loc := LOC_REGISTER;
+            paracgsize := OS_ADDR;
+            paralen := tcgsize2size[OS_ADDR];
+          end
+        else
+          begin
+            if not is_special_array(paradef) then
+              paralen := paradef.size
+            else
+              paralen := tcgsize2size[def_cgsize(paradef)];
+
+            if (paradef.typ=recorddef) and not(is_implicit_pointer_object_type(paradef)) and
+               tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(tmpdef) and
+               (tmpdef.typ=floatdef) then
+              begin
+                paradef:=tmpdef;
+                loc:=getparaloc(paradef);
+                paracgsize:=def_cgsize(paradef)
+              end
+            else if (((paradef.typ=arraydef) and not
+                 is_special_array(paradef)) or
+                (paradef.typ=recorddef)) then
+              begin
+                loc:=LOC_REGISTER;
+                paracgsize:=int_cgsize(paralen);
+              end
+            else
+              begin
+                loc:=getparaloc(paradef);
+                paracgsize:=def_cgsize(paradef);
+                { for things like formaldef }
+                if (paracgsize=OS_NO) then
+                  begin
+                    paracgsize:=OS_ADDR;
+                    paralen:=tcgsize2size[OS_ADDR];
+                  end;
+              end
+          end;
+
+        { patch FPU values into integer registers if we are processing varargs }
+        if (isVararg) and (paradef.typ = floatdef) then
+          begin
+            loc := LOC_REGISTER;
+            if paracgsize = OS_F64 then
+              paracgsize := OS_64
+            else
+              paracgsize := OS_32;
+          end;
+
+        para.alignment := std_param_align;
+        para.size := paracgsize;
+        para.intsize := paralen;
+        para.def := paradef;
+        if (paralen = 0) then
+          if (paradef.typ = recorddef) then
+            begin
+              paraloc := para.add_location;
+              paraloc^.loc := LOC_VOID;
+            end
+          else
+            internalerror(2024121401);
+        if not assigned(alllocdef) then
+          locdef:=paradef
+        else
+          begin
+            locdef:=alllocdef;
+            paracgsize:=def_cgsize(locdef);
+          end;
+        firstparaloc:=true;
+
+        { Parameters passed in 2 registers are passed in a register starting with an even number. }
+        if isVararg and
+           (paralen > sizeof(AInt)) and
+           (loc = LOC_REGISTER) and
+           (nextintreg <= RS_X17) and
+           odd(nextintreg) then
+          inc(nextintreg);
+
+        { can become < 0 for e.g. 3-byte records }
+        while (paralen > 0) do begin
+          paraloc := para.add_location;
+          { In case of po_delphi_nested_cc, the parent frame pointer
+            is always passed on the stack. }
+          if (loc = LOC_REGISTER) and
+             (nextintreg <= RS_X17) and
+             not forceintmem then
+            begin
+              paraloc^.loc := loc;
+
+              { make sure we don't lose whether or not the type is signed }
+              if (paracgsize <> OS_NO) and
+                 (paradef.typ <> orddef) and
+                 not assigned(alllocdef) then
+                begin
+                  paracgsize := int_cgsize(paralen);
+                  locdef:=get_paraloc_def(paradef, paralen, firstparaloc);
+                end;
+
+               if (paracgsize in [OS_NO, OS_SPAIR, OS_PAIR]) then
+                begin
+                  if (paralen > 4) then
+                    begin
+                      paraloc^.size := OS_INT;
+                      paraloc^.def := osuinttype;
+                    end
+                  else
+                    begin
+                      { for 3-byte records aligned in the lower bits of register }
+                      paraloc^.size := OS_32;
+                      paraloc^.def := u32inttype;
+                    end;
+                end
+              else
+                begin
+                  paraloc^.size := paracgsize;
+                  paraloc^.def := locdef;
+                end;
+
+              paraloc^.register := newreg(R_INTREGISTER, nextintreg, R_SUBNONE);
+              inc(nextintreg);
+              dec(paralen, tcgsize2size[paraloc^.size]);
+            end
+          else if (loc = LOC_FPUREGISTER) and
+            (nextfloatreg <= RS_F17) then
+            begin
+              paraloc^.loc := loc;
+              paraloc^.size := paracgsize;
+              paraloc^.def := locdef;
+              paraloc^.register := newreg(R_FPUREGISTER, nextfloatreg, R_SUBWHOLE);
+              { the RiscV ABI says that the GPR index is increased for every parameter, no matter
+                which type it is stored in
+
+                 not really, https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#hardware-floating-point-calling-convention says
+                 otherwise, gcc doesn't do it either }
+              inc(nextfloatreg);
+              dec(paralen, tcgsize2size[paraloc^.size]);
+            end
+          else if (loc = LOC_MMREGISTER) then
+            { no mm registers }
+            internalerror(2018072601)
+          else
+            begin
+              { either LOC_REFERENCE, or one of the above which must be passed on the
+              stack because of insufficient registers }
+              paraloc^.loc := LOC_REFERENCE;
+              case loc of
+                LOC_FPUREGISTER:
+                  begin
+                    paraloc^.size:=int_float_cgsize(paralen);
+                    case paraloc^.size of
+                      OS_F32: paraloc^.def:=s32floattype;
+                      OS_F64: paraloc^.def:=s64floattype;
+                      else
+                        internalerror(2013060122);
+                    end;
+                  end;
+                LOC_REGISTER,
+                LOC_REFERENCE:
+                  begin
+                    paraloc^.size:=int_cgsize(paralen);
+                    paraloc^.def:=get_paraloc_def(paradef, paralen, firstparaloc);
+                  end;
+                else
+                  internalerror(2006011101);
+              end;
+              if (side = callerside) then
+                paraloc^.reference.index := NR_STACK_POINTER_REG
+              else
+                begin
+                  { during procedure entry, NR_OLD_STACK_POINTER_REG contains the old stack pointer }
+                  paraloc^.reference.index := NR_FRAME_POINTER_REG;
+                  { create_paraloc_info_intern might be also called when being outside of
+                    code generation so current_procinfo might be not set }
+{$ifdef RISCV64}
+                  if assigned(current_procinfo) then
+                    trv64procinfo(current_procinfo).needs_frame_pointer := true;
+{$endif RISCV64}
+{$ifdef RISCV32}
+                  if assigned(current_procinfo) then
+                    trv32procinfo(current_procinfo).needs_frame_pointer := true;
+{$endif RISCV32}
+                end;
+              paraloc^.reference.offset := stack_offset;
+
+              { align temp contents to next register size }
+              if not paraaligned then
+                inc(stack_offset, align(paralen, sizeof(AInt)))
+              else
+                inc(stack_offset, paralen);
+              paralen := 0;
+            end;
+          firstparaloc:=false;
+        end;
+      end;
+
+
 end.
 end.
 
 
 
 

+ 5 - 268
compiler/riscv32/cpupara.pas

@@ -34,13 +34,9 @@ unit cpupara;
 
 
     type
     type
        tcpuparamanager = class(trvparamanager)
        tcpuparamanager = class(trvparamanager)
-          function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+         function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
 
 
-          function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
-          function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
-
-          function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
-              var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;override;
+         function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
        end;
        end;
 
 
   implementation
   implementation
@@ -51,7 +47,6 @@ unit cpupara;
        defutil,symtable,
        defutil,symtable,
        procinfo,cpupi;
        procinfo,cpupi;
 
 
-
     function tcpuparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
     function tcpuparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
       begin
       begin
         result:=false;
         result:=false;
@@ -78,11 +73,9 @@ unit cpupara;
             convention as for "8 byte record" due to the need for
             convention as for "8 byte record" due to the need for
             interchangeability with the TMethod record type.
             interchangeability with the TMethod record type.
           }
           }
-          procvardef :
-            result:=
-              (def.size <> sizeof(pint));
-          recorddef :
-            result := (def.size > 8) or (varspez = vs_const);
+          procvardef,
+          recorddef:
+            result := not(def.size in [0..sizeof(aint)*2]) or (varspez = vs_const);
           arraydef:
           arraydef:
             result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
             result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
                              is_open_array(def) or
                              is_open_array(def) or
@@ -100,64 +93,7 @@ unit cpupara;
       end;
       end;
 
 
 
 
-    function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
-      var
-        paraloc : pcgparalocation;
-        retcgsize  : tcgsize;
-      begin
-        if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
-          exit;
-
-        paraloc:=result.add_location;
-        { Return in FPU register? }
-        if (result.def.typ=floatdef) and
-           (not ((cs_fp_emulation in current_settings.moduleswitches) or
-                 (current_settings.fputype in [fpu_soft]))) then
-          begin
-            paraloc^.loc:=LOC_FPUREGISTER;
-            paraloc^.register:=NR_FPU_RESULT_REG;
-            paraloc^.size:=retcgsize;
-            paraloc^.def:=result.def;
-          end
-        else
-         { Return in register }
-          begin
-            if retcgsize in [OS_64,OS_S64] then
-             begin
-               { low 32bits }
-               paraloc^.loc:=LOC_REGISTER;
-               if side=callerside then
-                 paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
-               else
-                 paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
-               paraloc^.size:=OS_32;
-               paraloc^.def:=u32inttype;
-               { high 32bits }
-               paraloc:=result.add_location;
-               paraloc^.loc:=LOC_REGISTER;
-               if side=callerside then
-                 paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
-               else
-                 paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
-               paraloc^.size:=OS_32;
-               paraloc^.def:=u32inttype;
-             end
-            else
-             begin
-               paraloc^.loc:=LOC_REGISTER;
-               if side=callerside then
-                 paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
-               else
-                 paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
-               paraloc^.size:=retcgsize;
-               paraloc^.def:=result.def;
-             end;
-          end;
-      end;
-
-
     function tcpuparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
     function tcpuparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
-
       var
       var
         cur_stack_offset: aword;
         cur_stack_offset: aword;
         curintreg, curfloatreg, curmmreg: tsuperregister;
         curintreg, curfloatreg, curmmreg: tsuperregister;
@@ -169,205 +105,6 @@ unit cpupara;
         create_funcretloc_info(p,side);
         create_funcretloc_info(p,side);
       end;
       end;
 
 
-
-
-    function tcpuparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
-               var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
-      var
-         stack_offset: longint;
-         paralen: aint;
-         nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
-         MaxIntReg : TSuperRegister;
-         locdef,
-         fdef,
-         paradef : tdef;
-         paraloc : pcgparalocation;
-         i  : integer;
-         hp : tparavarsym;
-         loc : tcgloc;
-         paracgsize: tcgsize;
-         firstparaloc: boolean;
-
-      begin
-{$ifdef extdebug}
-         if po_explicitparaloc in p.procoptions then
-           internalerror(200411141);
-{$endif extdebug}
-
-         result:=0;
-         nextintreg := curintreg;
-         nextfloatreg := curfloatreg;
-         nextmmreg := curmmreg;
-         stack_offset := cur_stack_offset;
-         maxfpureg := RS_F17;
-         if CPURV_HAS_16REGISTERS in cpu_capabilities[current_settings.cputype] then
-           MaxIntReg := RS_X15 
-         else
-           MaxIntReg := RS_X17;
-
-          for i:=0 to paras.count-1 do
-            begin
-              hp:=tparavarsym(paras[i]);
-              paradef := hp.vardef;
-
-              hp.paraloc[side].reset;
-              { currently only support C-style array of const }
-              if (p.proccalloption in cstylearrayofconst) and
-                 is_array_of_const(paradef) then
-                begin
-                  paraloc:=hp.paraloc[side].add_location;
-                  { hack: the paraloc must be valid, but is not actually used }
-                  paraloc^.loc := LOC_REGISTER;
-                  paraloc^.register := NR_X0;
-                  paraloc^.size := OS_ADDR;
-                  paraloc^.def:=voidpointertype;
-                  break;
-                end;
-
-              if push_addr_param(hp.varspez,paradef,p.proccalloption) then
-                begin
-                  paradef:=cpointerdef.getreusable_no_free(paradef);
-                  loc:=LOC_REGISTER;
-                  paracgsize := OS_ADDR;
-                  paralen := tcgsize2size[OS_ADDR];
-                end
-              else
-                begin
-                  if not is_special_array(paradef) then
-                    paralen := paradef.size
-                  else
-                    paralen := tcgsize2size[def_cgsize(paradef)];
-                  paracgsize:=def_cgsize(paradef);
-                  { for things like formaldef }
-                  if (paracgsize=OS_NO) then
-                    begin
-                      paracgsize:=OS_ADDR;
-                      paralen := tcgsize2size[OS_ADDR];
-                    end;
-                end;
-
-              loc := getparaloc(paradef);
-
-              hp.paraloc[side].alignment:=std_param_align;
-              hp.paraloc[side].size:=paracgsize;
-              hp.paraloc[side].intsize:=paralen;
-              hp.paraloc[side].def:=paradef;
-{$ifndef cpu64bitaddr}
-              if (is_64bit(paradef)) and
-                 odd(nextintreg-RS_X10) then
-                inc(nextintreg);
-{$endif not cpu64bitaddr}
-              if (paralen = 0) then
-                if (paradef.typ = recorddef) then
-                  begin
-                    paraloc:=hp.paraloc[side].add_location;
-                    paraloc^.loc := LOC_VOID;
-                  end
-                else
-                  internalerror(2005011310);
-              locdef:=paradef;
-              firstparaloc:=true;
-              { can become < 0 for e.g. 3-byte records }
-              while (paralen > 0) do
-                begin
-                  paraloc:=hp.paraloc[side].add_location;
-                  { In case of po_delphi_nested_cc, the parent frame pointer
-                    is always passed on the stack. }
-                  if (loc = LOC_REGISTER) and
-                     (nextintreg <= MaxIntReg) and
-                     (not(vo_is_parentfp in hp.varoptions) or
-                      not(po_delphi_nested_cc in p.procoptions)) then
-                    begin
-                      paraloc^.loc := loc;
-                      { make sure we don't lose whether or not the type is signed }
-                      if (paradef.typ<>orddef) then
-                        begin
-                          paracgsize:=int_cgsize(paralen);
-                          locdef:=get_paraloc_def(paradef,paralen,firstparaloc);
-                        end;
-                      if (paracgsize in [OS_NO,OS_64,OS_S64,OS_128,OS_S128]) then
-                        begin
-                          paraloc^.size:=OS_INT;
-                          paraloc^.def:=u32inttype;
-                        end
-                      else
-                        begin
-                          paraloc^.size:=paracgsize;
-                          paraloc^.def:=locdef;
-                        end;
-                      paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
-                      inc(nextintreg);
-                      dec(paralen,tcgsize2size[paraloc^.size]);
-                    end
-                  else if (loc = LOC_FPUREGISTER) and
-                          (nextintreg <= MaxIntReg) then
-                    begin
-                      paraloc^.loc:=loc;
-                      paraloc^.size := paracgsize;
-                      paraloc^.def := paradef;
-                      paraloc^.register:=newreg(R_FPUREGISTER,nextintreg,R_SUBWHOLE);
-                      inc(nextintreg);
-                      dec(paralen,tcgsize2size[paraloc^.size]);
-                    end
-                  else { LOC_REFERENCE }
-                    begin
-                       paraloc^.loc:=LOC_REFERENCE;
-                       case loc of
-                         LOC_FPUREGISTER:
-                           begin
-                             paraloc^.size:=int_float_cgsize(paralen);
-                             case paraloc^.size of
-                               OS_F32: paraloc^.def:=s32floattype;
-                               OS_F64: paraloc^.def:=s64floattype;
-                               else
-                                 internalerror(2013060124);
-                             end;
-                           end;
-                         LOC_REGISTER,
-                         LOC_REFERENCE:
-                           begin
-                             paraloc^.size:=int_cgsize(paralen);
-                             if paraloc^.size<>OS_NO then
-                               paraloc^.def:=cgsize_orddef(paraloc^.size)
-                             else
-                               paraloc^.def:=carraydef.getreusable_no_free(u8inttype,paralen);
-                           end;
-                         else
-                           internalerror(2006011101);
-                       end;
-                       if (side = callerside) then
-                         paraloc^.reference.index:=NR_STACK_POINTER_REG
-                       else
-                         begin
-                           paraloc^.reference.index:=NR_FRAME_POINTER_REG;
-
-                           { create_paraloc_info_intern might be also called when being outside of
-                             code generation so current_procinfo might be not set }
-                           if assigned(current_procinfo) then
-                             trv32procinfo(current_procinfo).needs_frame_pointer := true;
-                         end;
-
-                       paraloc^.reference.offset:=stack_offset;
-
-                       inc(stack_offset,align(paralen,4));
-                       while (paralen > 0) and
-                             (nextintreg <= MaxIntReg) do
-                          begin
-                            inc(nextintreg);
-                            dec(paralen,sizeof(pint));
-                          end;
-                       paralen := 0;
-                    end;
-                  firstparaloc:=false;
-                end;
-            end;
-         curintreg:=nextintreg;
-         curfloatreg:=nextfloatreg;
-         curmmreg:=nextmmreg;
-         cur_stack_offset:=stack_offset;
-         result:=stack_offset;
-      end;
-
 begin
 begin
    paramanager:=tcpuparamanager.create;
    paramanager:=tcpuparamanager.create;
 end.
 end.

+ 2 - 0
compiler/riscv64/cgcpu.pas

@@ -122,6 +122,8 @@ implementation
           ((tcgsize2unsigned[fromsize]<>fromsize) and ((tcgsize2unsigned[tosize]=tosize)) and
           ((tcgsize2unsigned[fromsize]<>fromsize) and ((tcgsize2unsigned[tosize]=tosize)) and
             (tcgsize2size[fromsize] < tcgsize2size[tosize]) and (tcgsize2size[tosize] <> sizeof(pint)) ) then
             (tcgsize2size[fromsize] < tcgsize2size[tosize]) and (tcgsize2size[tosize] <> sizeof(pint)) ) then
           begin
           begin
+            if 8*(8-tcgsize2size[tosize])=64 then
+              writeln;
             if tcgsize2size[fromsize]<tcgsize2size[tosize] then
             if tcgsize2size[fromsize]<tcgsize2size[tosize] then
               begin
               begin
                 list.Concat(taicpu.op_reg_reg_const(A_SLLI,reg2,reg1,8*(8-tcgsize2size[fromsize])));
                 list.Concat(taicpu.op_reg_reg_const(A_SLLI,reg2,reg1,8*(8-tcgsize2size[fromsize])));

+ 4 - 293
compiler/riscv64/cpupara.pas

@@ -38,12 +38,8 @@ unit cpupara;
         function ret_in_param(def: tdef; pd: tabstractprocdef): boolean; override;
         function ret_in_param(def: tdef; pd: tabstractprocdef): boolean; override;
 
 
         function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override;
         function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override;
-        function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
-
-        function create_paraloc_info_intern(p: tabstractprocdef; side: tcallercallee; paras: tparalist; var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; isVararg : boolean): longint;override;
       private
       private
         function parseparaloc(p: tparavarsym; const s: string): boolean; override;
         function parseparaloc(p: tparavarsym; const s: string): boolean; override;
-        procedure create_paraloc_for_def(var para: TCGPara; varspez: tvarspez; paradef: tdef; var nextfloatreg, nextintreg: tsuperregister; var stack_offset: aword; const isVararg, forceintmem: boolean; const side: tcallercallee; const p: tabstractprocdef);
       end;
       end;
 
 
 implementation
 implementation
@@ -54,7 +50,6 @@ implementation
       defutil,symtable,symcpu,
       defutil,symtable,symcpu,
       procinfo, cpupi;
       procinfo, cpupi;
 
 
-
     function tcpuparamanager.push_addr_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean;
     function tcpuparamanager.push_addr_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean;
       begin
       begin
         result := false;
         result := false;
@@ -70,7 +65,7 @@ implementation
             result := true;
             result := true;
           procvardef,
           procvardef,
           recorddef:
           recorddef:
-            result := (def.size > 16);
+            result := not(def.size in [0..sizeof(aint)*2]) or (varspez = vs_const);
           arraydef:
           arraydef:
             result := (tarraydef(def).highrange >= tarraydef(def).lowrange) or
             result := (tarraydef(def).highrange >= tarraydef(def).lowrange) or
               is_open_array(def) or
               is_open_array(def) or
@@ -89,8 +84,6 @@ implementation
 
 
 
 
     function tcpuparamanager.ret_in_param(def: tdef; pd: tabstractprocdef): boolean;
     function tcpuparamanager.ret_in_param(def: tdef; pd: tabstractprocdef): boolean;
-      var
-        tmpdef: tdef;
       begin
       begin
         if handle_common_ret_in_param(def,pd,result) then
         if handle_common_ret_in_param(def,pd,result) then
           exit;
           exit;
@@ -100,26 +93,6 @@ implementation
       end;
       end;
 
 
 
 
-    function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
-      var
-        paraloc: pcgparalocation;
-        retcgsize: tcgsize;
-        nextfloatreg, nextintreg, nextmmreg: tsuperregister;
-        stack_offset: aword;
-      begin
-        if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
-          exit;
-
-         { in this case, it must be returned in registers as if it were passed
-           as the first parameter }
-         init_values(nextintreg,nextfloatreg,nextmmreg,stack_offset);
-         create_paraloc_for_def(result,vs_value,result.def,nextfloatreg,nextintreg,stack_offset,false,false,side,p);
-         { sanity check (LOC_VOID for empty records) }
-         if not assigned(result.location) or
-            not(result.location^.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_VOID]) then
-           internalerror(2014113001);
-      end;
-
     function tcpuparamanager.create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint;
     function tcpuparamanager.create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint;
       var
       var
         cur_stack_offset: aword;
         cur_stack_offset: aword;
@@ -132,276 +105,14 @@ implementation
         create_funcretloc_info(p, side);
         create_funcretloc_info(p, side);
       end;
       end;
 
 
-    function tcpuparamanager.create_paraloc_info_intern(p: tabstractprocdef; side: tcallercallee; paras: tparalist; var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; isVararg : boolean): longint;
-      var
-        nextintreg, nextfloatreg, nextmmreg : tsuperregister;
-        i: integer;
-        hp: tparavarsym;
-        paraloc: pcgparalocation;
-        delphi_nestedfp: boolean;
-
-      begin
-{$IFDEF extdebug}
-        if po_explicitparaloc in p.procoptions then
-          internalerror(200411141);
-{$ENDIF extdebug}
-
-        result := 0;
-        nextintreg := curintreg;
-        nextfloatreg := curfloatreg;
-        nextmmreg := curmmreg;
-
-        for i := 0 to paras.count - 1 do begin
-          hp := tparavarsym(paras[i]);
-
-          if (vo_has_explicit_paraloc in hp.varoptions) then begin
-            internalerror(200412153);
-          end;
-
-          { currently only support C-style array of const }
-          if (p.proccalloption in [pocall_cdecl, pocall_cppdecl]) and
-            is_array_of_const(hp.vardef) then begin
-            paraloc := hp.paraloc[side].add_location;
-            { hack: the paraloc must be valid, but is not actually used }
-            paraloc^.loc := LOC_REGISTER;
-            paraloc^.register := NR_X0;
-            paraloc^.size := OS_ADDR;
-            paraloc^.def := voidpointertype;
-            break;
-          end;
-          delphi_nestedfp:=(vo_is_parentfp in hp.varoptions) and (po_delphi_nested_cc in p.procoptions);
-          create_paraloc_for_def(hp.paraloc[side], hp.varspez, hp.vardef,
-            nextfloatreg, nextintreg, cur_stack_offset, isVararg, delphi_nestedfp, side, p);
-        end;
-
-        curintreg := nextintreg;
-        curfloatreg := nextfloatreg;
-        curmmreg := nextmmreg;
-        result := cur_stack_offset;
-      end;
 
 
-    procedure tcpuparamanager.create_paraloc_for_def(var para: TCGPara; varspez: tvarspez; paradef: tdef; var nextfloatreg, nextintreg: tsuperregister; var stack_offset: aword; const isVararg, forceintmem: boolean; const side: tcallercallee; const p: tabstractprocdef);
-      var
-        paracgsize: tcgsize;
-        loc: tcgloc;
-        paraloc: pcgparalocation;
-        { def to use for all paralocs if <> nil }
-        alllocdef,
-        { def to use for the current paraloc }
-        locdef,
-        tmpdef: tdef;
-        paralen: aint;
-        firstparaloc,
-        paraaligned: boolean;
+    function tcpuparamanager.parseparaloc(p: tparavarsym; const s: string): boolean;
       begin
       begin
-        alllocdef:=nil;
-        locdef:=nil;
-        para.reset;
-        { have we ensured that the next parameter location will be aligned to the
-          next 8 byte boundary? }
-        paraaligned:=false;
-        if push_addr_param(varspez, paradef, p.proccalloption) then
-          begin
-            paradef := cpointerdef.getreusable_no_free(paradef);
-            loc := LOC_REGISTER;
-            paracgsize := OS_ADDR;
-            paralen := tcgsize2size[OS_ADDR];
-          end
-        else
-          begin
-            if not is_special_array(paradef) then
-              paralen := paradef.size
-            else
-              paralen := tcgsize2size[def_cgsize(paradef)];
-
-            if (paradef.typ=recorddef) and not(is_implicit_pointer_object_type(paradef)) and
-               tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(tmpdef) and
-               (tmpdef.typ=floatdef) then
-              begin
-                paradef:=tmpdef;
-                loc:=getparaloc(paradef);
-                paracgsize:=def_cgsize(paradef)
-              end
-            else if (((paradef.typ=arraydef) and not
-                 is_special_array(paradef)) or
-                (paradef.typ=recorddef)) then
-              begin
-                { general fallback rule: pass aggregate types in integer registers
-                  without special adjustments (incl. Darwin h) }
-                loc:=LOC_REGISTER;
-                paracgsize:=int_cgsize(paralen);
-              end
-            else
-              begin
-                loc:=getparaloc(paradef);
-                paracgsize:=def_cgsize(paradef);
-                { for things like formaldef }
-                if (paracgsize=OS_NO) then
-                  begin
-                    paracgsize:=OS_ADDR;
-                    paralen:=tcgsize2size[OS_ADDR];
-                  end;
-              end
-          end;
-
-        { patch FPU values into integer registers if we are processing varargs }
-        if (isVararg) and (paradef.typ = floatdef) then
-          begin
-            loc := LOC_REGISTER;
-            if paracgsize = OS_F64 then
-              paracgsize := OS_64
-            else
-              paracgsize := OS_32;
-          end;
-
-        para.alignment := std_param_align;
-        para.size := paracgsize;
-        para.intsize := paralen;
-        para.def := paradef;
-        if (paralen = 0) then
-          if (paradef.typ = recorddef) then
-            begin
-              paraloc := para.add_location;
-              paraloc^.loc := LOC_VOID;
-            end
-          else
-            internalerror(2024121401);
-        if not assigned(alllocdef) then
-          locdef:=paradef
-        else
-          begin
-            locdef:=alllocdef;
-            paracgsize:=def_cgsize(locdef);
-          end;
-        firstparaloc:=true;
-
-        // Parameters passed in 2 registers are passed in a register starting with an even number.
-        if isVararg and
-           (paralen > 8) and
-           (loc = LOC_REGISTER) and
-           (nextintreg <= RS_X17) and
-           odd(nextintreg) then
-          inc(nextintreg);
-
-        { can become < 0 for e.g. 3-byte records }
-        while (paralen > 0) do begin
-          paraloc := para.add_location;
-          { In case of po_delphi_nested_cc, the parent frame pointer
-            is always passed on the stack. }
-          if (loc = LOC_REGISTER) and
-             (nextintreg <= RS_X17) and
-             not forceintmem then
-            begin
-              paraloc^.loc := loc;
-
-              { make sure we don't lose whether or not the type is signed }
-              if (paracgsize <> OS_NO) and
-                 (paradef.typ <> orddef) and
-                 not assigned(alllocdef) then
-                begin
-                  paracgsize := int_cgsize(paralen);
-                  locdef:=get_paraloc_def(paradef, paralen, firstparaloc);
-                end;
-
-               if (paracgsize in [OS_NO, OS_128, OS_S128]) then
-                begin
-                  if (paralen>4) then
-                    begin
-                      paraloc^.size := OS_INT;
-                      paraloc^.def := osuinttype;
-                    end
-                  else
-                    begin
-                      { for 3-byte records aligned in the lower bits of register }
-                      paraloc^.size := OS_32;
-                      paraloc^.def := u32inttype;
-                    end;
-                end
-              else
-                begin
-                  paraloc^.size := paracgsize;
-                  paraloc^.def := locdef;
-                end;
-
-              paraloc^.register := newreg(R_INTREGISTER, nextintreg, R_SUBNONE);
-              inc(nextintreg);
-              dec(paralen, tcgsize2size[paraloc^.size]);
-            end
-          else if (loc = LOC_FPUREGISTER) and
-            (nextfloatreg <= RS_F17) then
-            begin
-              paraloc^.loc := loc;
-              paraloc^.size := paracgsize;
-              paraloc^.def := locdef;
-              paraloc^.register := newreg(R_FPUREGISTER, nextfloatreg, R_SUBWHOLE);
-              { the RiscV ABI says that the GPR index is increased for every parameter, no matter
-                which type it is stored in
-
-                 not really, https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#hardware-floating-point-calling-convention says
-                 otherwise, gcc doesn't do it either }
-              inc(nextfloatreg);
-              dec(paralen, tcgsize2size[paraloc^.size]);
-            end
-          else if (loc = LOC_MMREGISTER) then
-            { no mm registers }
-            internalerror(2018072601)
-          else
-            begin
-              { either LOC_REFERENCE, or one of the above which must be passed on the
-              stack because of insufficient registers }
-              paraloc^.loc := LOC_REFERENCE;
-              case loc of
-                LOC_FPUREGISTER:
-                  begin
-                    paraloc^.size:=int_float_cgsize(paralen);
-                    case paraloc^.size of
-                      OS_F32: paraloc^.def:=s32floattype;
-                      OS_F64: paraloc^.def:=s64floattype;
-                      else
-                        internalerror(2013060122);
-                    end;
-                  end;
-                LOC_REGISTER,
-                LOC_REFERENCE:
-                  begin
-                    paraloc^.size:=int_cgsize(paralen);
-                    paraloc^.def:=get_paraloc_def(paradef, paralen, firstparaloc);
-                  end;
-                else
-                  internalerror(2006011101);
-              end;
-              if (side = callerside) then
-                paraloc^.reference.index := NR_STACK_POINTER_REG
-              else
-                begin
-                  { during procedure entry, NR_OLD_STACK_POINTER_REG contains the old stack pointer }
-                  paraloc^.reference.index := NR_FRAME_POINTER_REG;
-                  { create_paraloc_info_intern might be also called when being outside of
-                    code generation so current_procinfo might be not set }
-                  if assigned(current_procinfo) then
-                    trv64procinfo(current_procinfo).needs_frame_pointer := true;
-                end;
-              paraloc^.reference.offset := stack_offset;
-
-              { align temp contents to next register size }
-              if not paraaligned then
-                inc(stack_offset, align(paralen, 8))
-              else
-                inc(stack_offset, paralen);
-              paralen := 0;
-            end;
-          firstparaloc:=false;
-        end;
+        internalerror(200404182);
+        result := true;
       end;
       end;
 
 
 
 
-function tcpuparamanager.parseparaloc(p: tparavarsym; const s: string): boolean;
-begin
-  internalerror(200404182);
-  result := true;
-end;
-
-
 begin
 begin
   paramanager := tcpuparamanager.create;
   paramanager := tcpuparamanager.create;
 end.
 end.