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_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;
 
-        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;
+
       protected
         procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
       end;
@@ -57,14 +61,13 @@ implementation
       globals,
       cpuinfo,
       symsym,
+      symtable,
       defutil,
-      cpubase;
+      cpubase,
+      procinfo,cpupi;
 
     function getparaloc(p : tdef) : tcgloc;
       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
             orddef:
               result:=LOC_REGISTER;
@@ -83,22 +86,12 @@ implementation
             classrefdef:
               result:=LOC_REGISTER;
             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;
-{$endif RISCV32}
             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
               else
-{$endif RISCV32}
                 result:=LOC_REGISTER;
             objectdef:
               if is_object(p) then
@@ -198,6 +191,21 @@ implementation
       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);
       begin
         { register parameter save area begins at 48(r2) }
@@ -245,6 +253,274 @@ implementation
         create_funcretloc_info(p,side);
       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.
 
 

+ 5 - 268
compiler/riscv32/cpupara.pas

@@ -34,13 +34,9 @@ unit cpupara;
 
     type
        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;
 
   implementation
@@ -51,7 +47,6 @@ unit cpupara;
        defutil,symtable,
        procinfo,cpupi;
 
-
     function tcpuparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
       begin
         result:=false;
@@ -78,11 +73,9 @@ unit cpupara;
             convention as for "8 byte record" due to the need for
             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:
             result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
                              is_open_array(def) or
@@ -100,64 +93,7 @@ unit cpupara;
       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;
-
       var
         cur_stack_offset: aword;
         curintreg, curfloatreg, curmmreg: tsuperregister;
@@ -169,205 +105,6 @@ unit cpupara;
         create_funcretloc_info(p,side);
       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
    paramanager:=tcpuparamanager.create;
 end.

+ 2 - 0
compiler/riscv64/cgcpu.pas

@@ -122,6 +122,8 @@ implementation
           ((tcgsize2unsigned[fromsize]<>fromsize) and ((tcgsize2unsigned[tosize]=tosize)) and
             (tcgsize2size[fromsize] < tcgsize2size[tosize]) and (tcgsize2size[tosize] <> sizeof(pint)) ) then
           begin
+            if 8*(8-tcgsize2size[tosize])=64 then
+              writeln;
             if tcgsize2size[fromsize]<tcgsize2size[tosize] then
               begin
                 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 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
         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;
 
 implementation
@@ -54,7 +50,6 @@ implementation
       defutil,symtable,symcpu,
       procinfo, cpupi;
 
-
     function tcpuparamanager.push_addr_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean;
       begin
         result := false;
@@ -70,7 +65,7 @@ implementation
             result := true;
           procvardef,
           recorddef:
-            result := (def.size > 16);
+            result := not(def.size in [0..sizeof(aint)*2]) or (varspez = vs_const);
           arraydef:
             result := (tarraydef(def).highrange >= tarraydef(def).lowrange) or
               is_open_array(def) or
@@ -89,8 +84,6 @@ implementation
 
 
     function tcpuparamanager.ret_in_param(def: tdef; pd: tabstractprocdef): boolean;
-      var
-        tmpdef: tdef;
       begin
         if handle_common_ret_in_param(def,pd,result) then
           exit;
@@ -100,26 +93,6 @@ implementation
       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;
       var
         cur_stack_offset: aword;
@@ -132,276 +105,14 @@ implementation
         create_funcretloc_info(p, side);
       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
-        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;
 
 
-function tcpuparamanager.parseparaloc(p: tparavarsym; const s: string): boolean;
-begin
-  internalerror(200404182);
-  result := true;
-end;
-
-
 begin
   paramanager := tcpuparamanager.create;
 end.