浏览代码

Fix for issue 39603, cherry-picked commits 6f749cf4, 98483496, cc7d67d0 and f562a8d9.

ccrause 2 年之前
父节点
当前提交
ea5c84dca8
共有 2 个文件被更改,包括 40 次插入2 次删除
  1. 7 1
      compiler/hlcgobj.pas
  2. 33 1
      compiler/ncgld.pas

+ 7 - 1
compiler/hlcgobj.pas

@@ -815,11 +815,17 @@ implementation
           recorddef,
           setdef:
             result:=R_INTREGISTER;
+          procvardef:
+            { getaddressregister cannot handle if multiple registers
+              are required for a single element }
+            if is_methodpointer(def) then
+              result:=R_INTREGISTER
+            else
+              result:=R_ADDRESSREGISTER;
           stringdef,
           pointerdef,
           classrefdef,
           objectdef,
-          procvardef,
           procdef,
           arraydef,
           formaldef:

+ 33 - 1
compiler/ncgld.pas

@@ -553,6 +553,10 @@ implementation
                     not tabstractprocdef(resultdef).is_addressonly then
                    begin
                      location_reset(location,LOC_CREGISTER,int_cgsize(voidpointertype.size*2));
+{$if defined(CPU8BITALU) and defined(CPU16BITADDR)}
+                     { cpus with 16 bit address registers don't use registerhi here, so allocate already here a register for all purposes }
+                     location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,s32inttype);
+{$endif defined(CPU8BITALU) and defined(CPU16BITADDR)}
                      secondpass(left);
 
                      { load class instance/classrefdef address }
@@ -569,7 +573,11 @@ implementation
                              { this is not possible for objects }
                              if is_object(left.resultdef) then
                                internalerror(200304234);
+{$if defined(CPU8BITALU) and defined(CPU16BITADDR)}
+                             hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,left.location.register,cg.GetNextReg(cg.GetNextReg(location.register)));
+{$else defined(CPU8BITALU) and defined(CPU16BITADDR)}
                              location.registerhi:=left.location.register;
+{$endif defined(CPU8BITALU) and defined(CPU16BITADDR)}
                              vd:=left.resultdef;
                           end;
                         LOC_CREFERENCE,
@@ -579,14 +587,22 @@ implementation
                                  (left.resultdef.typ=classrefdef) then
                                begin
                                  vd:=left.resultdef;
+{$if defined(CPU8BITALU) and defined(CPU16BITADDR)}
+                                 hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,left.location.reference,cg.GetNextReg(cg.GetNextReg(location.register)))
+{$else defined(CPU8BITALU) and defined(CPU16BITADDR)}
                                  location.registerhi:=hlcg.getaddressregister(current_asmdata.CurrAsmList,left.resultdef);
                                  hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,left.location.reference,location.registerhi)
+{$endif defined(CPU8BITALU) and defined(CPU16BITADDR)}
                                end
                              else
                                begin
                                  vd:=cpointerdef.getreusable(left.resultdef);
+{$if defined(CPU8BITALU) and defined(CPU16BITADDR)}
+                                 hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.resultdef,vd,left.location.reference,cg.GetNextReg(cg.GetNextReg(location.register)));
+{$else defined(CPU8BITALU) and defined(CPU16BITADDR)}
                                  location.registerhi:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vd);
                                  hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.resultdef,vd,left.location.reference,location.registerhi);
+{$endif defined(CPU8BITALU) and defined(CPU16BITADDR)}
                                end;
                              location_freetemp(current_asmdata.CurrAsmList,left.location);
                           end;
@@ -621,9 +637,15 @@ implementation
                            end
                          else if left.resultdef.typ=classrefdef then
                            begin
+                             vmtdef:=cpointerdef.getreusable(tobjectdef(tclassrefdef(left.resultdef).pointeddef).vmt_def);
                              { classrefdef is a pointer to the vmt already }
+{$if defined(CPU8BITALU) and defined(CPU16BITADDR)}
+                             hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vmtdef);
+                             hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,cg.GetNextReg(cg.GetNextReg(location.register)),hregister);
+{$else defined(CPU8BITALU) and defined(CPU16BITADDR)}
+                             { targets with 32 bit method pointers got already a register assigned }
                              hregister:=location.registerhi;
-                             vmtdef:=cpointerdef.getreusable(tobjectdef(tclassrefdef(left.resultdef).pointeddef).vmt_def);
+{$endif defined(CPU8BITALU) and defined(CPU16BITADDR)}
                              hlcg.g_ptrtypecast_reg(current_asmdata.CurrAsmList,left.resultdef,vmtdef,hregister);
                            end
                          else if is_any_interface_kind(left.resultdef) then
@@ -640,7 +662,10 @@ implementation
                          vmtentry:=tabstractrecordsymtable(trecorddef(vmtdef.pointeddef).symtable).findfieldbyoffset(
                            tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber));
                          hlcg.reference_reset_base(href,vmtdef,hregister,0,ctempposinvalid,vmtdef.alignment,[]);
+                         { targets with 32 bit method pointers got already a register assigned }
+{$if not(defined(CPU8BITALU) and defined(CPU16BITADDR))}
                          location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,vmtentry.vardef);
+{$endif not(defined(CPU8BITALU) and defined(CPU16BITADDR))}
                          hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,tabstractrecorddef(vmtdef.pointeddef),vmtentry,href);
                          hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,vmtentry.vardef,vmtentry.vardef,href,location.register);
                        end
@@ -648,7 +673,10 @@ implementation
                        begin
                          { load address of the function }
                          reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname,AT_FUNCTION),0,procdef.address_type.alignment,[]);
+                         { targets with 32 bit method pointers got already a register assigned }
+{$if not(defined(CPU8BITALU) and defined(CPU16BITADDR))}
                          location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cprocvardef.getreusableprocaddr(procdef));
+{$endif not(defined(CPU8BITALU) and defined(CPU16BITADDR))}
                          hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,procdef,cprocvardef.getreusableprocaddr(procdef),href,location.register);
                        end;
 
@@ -656,6 +684,10 @@ implementation
                        big endian targets }
                      if target_info.endian=endian_big then
                        begin
+                         { cpus with 16 bit address registers don't use registerhi here }
+{$if defined(CPU8BITALU) and defined(CPU16BITADDR)}
+                         Internalerror(2022091201);
+{$endif defined(CPU8BITALU) and defined(CPU16BITADDR)}
                          hregister:=location.register;
                          location.register:=location.registerhi;
                          location.registerhi:=hregister;