Răsfoiți Sursa

Merged revision(s) 41412 from trunk:
* aarch64: According to ARM64 ABI, function's arguments and the result are not required to be sign/zero extended to a full register size. Obey this rule for all targets except iOS where sign/zero extension is required.

........

git-svn-id: branches/fixes_3_2@41616 -

yury 6 ani în urmă
părinte
comite
fcc7daf98d
3 a modificat fișierele cu 124 adăugiri și 7 ștergeri
  1. 1 0
      .gitattributes
  2. 39 7
      compiler/aarch64/cpupara.pas
  3. 84 0
      tests/test/taarch64abi.pp

+ 1 - 0
.gitattributes

@@ -12567,6 +12567,7 @@ tests/test/packages/win-base/tdispvar1.pp svneol=native#text/plain
 tests/test/packages/zlib/tzlib1.pp svneol=native#text/plain
 tests/test/t4cc1.pp svneol=native#text/plain
 tests/test/t4cc2.pp svneol=native#text/plain
+tests/test/taarch64abi.pp svneol=native#text/plain
 tests/test/tabstract1.pp svneol=native#text/pascal
 tests/test/tabstrcl.pp svneol=native#text/plain
 tests/test/tabsvr1.pp svneol=native#text/plain

+ 39 - 7
compiler/aarch64/cpupara.pas

@@ -364,6 +364,24 @@ unit cpupara;
          if not assigned(result.location) or
             not(result.location^.loc in [LOC_REGISTER,LOC_MMREGISTER,LOC_VOID]) then
            internalerror(2014113001);
+         {
+           According to ARM64 ABI: "If the size of the argument is less than 8 bytes then
+           the size of the argument is set to 8 bytes. The effect is as if the argument
+           was copied to the least significant bits of a 64-bit register and the remaining
+           bits filled with unspecified values."
+
+           Therefore at caller side force the ordinal result to be always 64-bit, so it
+           will be stripped to the required size and uneeded bits are discarded.
+
+           This is not required for iOS, where the result is zero/sign extended.
+         }
+         if (target_info.abi<>abi_aarch64_darwin) and
+            (side=callerside) and (result.location^.loc = LOC_REGISTER) and
+            (result.def.size<8) and is_ordinal(result.def) then
+           begin
+             result.location^.size:=OS_64;
+             result.location^.def:=u64inttype;
+           end;
       end;
 
 
@@ -552,14 +570,28 @@ unit cpupara;
                     responsibility to sign or zero-extend arguments having fewer
                     than 32 bits, and that unused bits in a register are
                     unspecified. In iOS, however, the caller must perform such
-                    extensions, up to 32 bits." }
-                 if (target_info.abi=abi_aarch64_darwin) and
-                    (side=callerside) and
-                    is_ordinal(paradef) and
-                    (paradef.size<4) then
+                    extensions, up to 32 bits."
+                    Zero extend an argument at caller side for iOS and
+                    ignore the argument's unspecified high bits at callee side for
+                    all other platforms. }
+                 if (paradef.size<4) and is_ordinal(paradef) then
                    begin
-                     paraloc^.size:=OS_32;
-                     paraloc^.def:=u32inttype;
+                     if target_info.abi=abi_aarch64_darwin then
+                       begin
+                         if side=callerside then
+                           begin
+                             paraloc^.size:=OS_32;
+                             paraloc^.def:=u32inttype;
+                           end;
+                       end
+                     else
+                       begin
+                         if side=calleeside then
+                           begin
+                             paraloc^.size:=OS_32;
+                             paraloc^.def:=u32inttype;
+                           end;
+                       end;
                    end;
 
                  { in case it's a composite, "The argument is passed as though

+ 84 - 0
tests/test/taarch64abi.pp

@@ -0,0 +1,84 @@
+{ %CPU=aarch64 }
+{ %skiptarget=darwin }
+
+{
+  Tests that arguments and the result are not required to be sign/zero extended.
+}
+
+procedure ProcByte(p: byte);
+begin
+  if p <> $78 then
+    Halt(1);
+end;
+
+procedure ProcWord(p: word);
+begin
+  if p <> $5678 then
+    Halt(2);
+end;
+
+procedure ProcDWord(p: dword);
+begin
+  if p <> $12345678 then
+    Halt(3);
+end;
+
+function RetByte: byte;
+var
+  q: qword;
+begin
+  q:=$1111111112345678;
+  asm
+    ldr x0,q
+  end;
+end;
+
+function RetWord: word;
+var
+  q: qword;
+begin
+  q:=$1111111112345678;
+  asm
+    ldr x0,q
+  end;
+end;
+
+function RetDWord: dword;
+var
+  q: qword;
+begin
+  q:=$1111111112345678;
+  asm
+    ldr x0,q
+  end;
+end;
+
+procedure TestParams;
+var
+  q: qword;
+begin
+  q:=$1111111112345678;
+  asm
+    ldr x0,q
+    bl ProcByte
+    ldr x0,q
+    bl ProcWord
+    ldr x0,q
+    bl ProcDWord
+  end;
+end;
+
+procedure TestReturns;
+begin
+  if RetByte <> $78 then
+    Halt(11);
+  if RetWord <> $5678 then
+    Halt(12);
+  if RetDWord <> $12345678 then
+    Halt(13);
+end;
+
+begin
+  TestParams;
+  TestReturns;
+end.