* 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: trunk@41412 -
This commit is contained in:
yury 2019-02-22 17:59:54 +00:00
parent e9c4042023
commit 382d5060a0
3 changed files with 124 additions and 7 deletions

1
.gitattributes vendored
View File

@ -12745,6 +12745,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

View File

@ -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;
@ -597,14 +615,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
tests/test/taarch64abi.pp Normal file
View File

@ -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.