Explorar o código

* Always use RIP relative symbol addressing for x86_64 Windows targets. Bug #13657.
* Support for simple form of RIP relative addressing by x86_64 assembler writer. Example: movl rax,SomeSymbol(%rip)

git-svn-id: trunk@13135 -

yury %!s(int64=16) %!d(string=hai) anos
pai
achega
92ad06f1e8
Modificáronse 3 ficheiros con 72 adicións e 20 borrados
  1. 20 2
      compiler/x86/aasmcpu.pas
  2. 51 18
      compiler/x86/cgx86.pas
  3. 1 0
      compiler/x86/nx86inl.pas

+ 20 - 2
compiler/x86/aasmcpu.pas

@@ -1298,6 +1298,9 @@ implementation
       begin
       begin
         result:=(oper[opidx]^.typ=top_ref) and
         result:=(oper[opidx]^.typ=top_ref) and
                 (oper[opidx]^.ref^.refaddr=addr_no) and
                 (oper[opidx]^.ref^.refaddr=addr_no) and
+    {$ifdef x86_64}
+                (oper[opidx]^.ref^.base<>NR_RIP) and
+    {$endif x86_64}
                 (
                 (
                  (
                  (
                   (oper[opidx]^.ref^.index<>NR_NO) and
                   (oper[opidx]^.ref^.index<>NR_NO) and
@@ -2279,13 +2282,28 @@ implementation
                      2,4 :
                      2,4 :
                        begin
                        begin
                          currsym:=objdata.symbolref(oper[opidx]^.ref^.symbol);
                          currsym:=objdata.symbolref(oper[opidx]^.ref^.symbol);
+                         currval:=oper[opidx]^.ref^.offset;
 {$ifdef x86_64}
 {$ifdef x86_64}
                          if oper[opidx]^.ref^.refaddr=addr_pic then
                          if oper[opidx]^.ref^.refaddr=addr_pic then
                            currabsreloc:=RELOC_GOTPCREL
                            currabsreloc:=RELOC_GOTPCREL
                          else
                          else
+                           if oper[opidx]^.ref^.base=NR_RIP then
+                             begin
+                               currabsreloc:=RELOC_RELATIVE;
+                               { Adjust reloc value depending of immediate operand size }
+                               case Ord(codes^) of
+                                 12,13,14,16,17,18,20,21,22:
+                                   Dec(currval, 1);
+                                 24,25,26:
+                                   Dec(currval, 2);
+                                 32,33,34:
+                                   Dec(currval, 4);
+                               end;
+                             end
+                           else
 {$endif x86_64}
 {$endif x86_64}
-                           currabsreloc:=RELOC_ABSOLUTE32;
-                         objdata.writereloc(oper[opidx]^.ref^.offset,ea_data.bytes,currsym,currabsreloc);
+                             currabsreloc:=RELOC_ABSOLUTE32;
+                         objdata.writereloc(currval,ea_data.bytes,currsym,currabsreloc);
                          inc(s,ea_data.bytes);
                          inc(s,ea_data.bytes);
                        end;
                        end;
                    end;
                    end;

+ 51 - 18
compiler/x86/cgx86.pas

@@ -381,29 +381,62 @@ unit cgx86;
                   end;
                   end;
                end;
                end;
           end;
           end;
-        if (cs_create_pic in current_settings.moduleswitches) and
-         assigned(ref.symbol) and not((ref.symbol.bind=AB_LOCAL) and (ref.symbol.typ in [AT_LABEL,AT_FUNCTION])) then
+
+        if assigned(ref.symbol) and not((ref.symbol.bind=AB_LOCAL) and (ref.symbol.typ in [AT_LABEL,AT_FUNCTION])) then
           begin
           begin
-            reference_reset_symbol(href,ref.symbol,0,sizeof(pint));
-            hreg:=getaddressregister(list);
-            href.refaddr:=addr_pic;
-            href.base:=NR_RIP;
-            list.concat(taicpu.op_ref_reg(A_MOV,S_Q,href,hreg));
+            if cs_create_pic in current_settings.moduleswitches then
+              begin
+                reference_reset_symbol(href,ref.symbol,0,sizeof(pint));
+                hreg:=getaddressregister(list);
+                href.refaddr:=addr_pic;
+                href.base:=NR_RIP;
+                list.concat(taicpu.op_ref_reg(A_MOV,S_Q,href,hreg));
 
 
-            ref.symbol:=nil;
+                ref.symbol:=nil;
 
 
-            if ref.base=NR_NO then
-              ref.base:=hreg
-            else if ref.index=NR_NO then
-              begin
-                ref.index:=hreg;
-                ref.scalefactor:=1;
+                if ref.base=NR_NO then
+                  ref.base:=hreg
+                else if ref.index=NR_NO then
+                  begin
+                    ref.index:=hreg;
+                    ref.scalefactor:=1;
+                  end
+                else
+                  begin
+                    list.concat(taicpu.op_reg_reg(A_ADD,S_Q,ref.base,hreg));
+                    ref.base:=hreg;
+                  end;
               end
               end
             else
             else
-              begin
-                list.concat(taicpu.op_reg_reg(A_ADD,S_Q,ref.base,hreg));
-                ref.base:=hreg;
-              end;
+              { Always use RIP relative symbol addressing for Windows targets. }
+              if (target_info.system in system_all_windows) and (ref.base<>NR_RIP) then
+                begin
+                  if (ref.refaddr=addr_no) and (ref.base=NR_NO) and (ref.index=NR_NO) then
+                    { Set RIP relative addressing for simple symbol references }
+                    ref.base:=NR_RIP
+                  else
+                    begin
+                      { Use temp register to load calculated 64-bit symbol address for complex references }
+                      reference_reset_symbol(href,ref.symbol,0,sizeof(pint));
+                      href.base:=NR_RIP;
+                      hreg:=GetAddressRegister(list);
+                      list.concat(taicpu.op_ref_reg(A_LEA,S_Q,href,hreg));
+                      ref.symbol:=nil;
+                      if ref.base=NR_NO then
+                        ref.base:=hreg
+                      else if ref.index=NR_NO then
+                        begin
+                          ref.index:=hreg;
+                          ref.scalefactor:=0;
+                        end
+                      else
+                        begin
+                          list.concat(taicpu.op_reg_reg(A_ADD,S_Q,ref.base,hreg));
+                          ref.base:=hreg;
+                        end;
+                    end;
+
+                end;
           end;
           end;
 {$else x86_64}
 {$else x86_64}
         add_hreg:=false;
         add_hreg:=false;

+ 1 - 0
compiler/x86/nx86inl.pas

@@ -235,6 +235,7 @@ implementation
                else
                else
                  internalerror(200506081);
                  internalerror(200506081);
              end;
              end;
+             tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList, href);
              current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_ANDPS,S_XMM,href,location.register))
              current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_ANDPS,S_XMM,href,location.register))
            end
            end
          else
          else