From 2fdac5e46321ee2a2cbd97298bb222b63932260d Mon Sep 17 00:00:00 2001
From: Iain Sandoe <iain@sandoe.co.uk>
Date: Wed, 2 Sep 2020 18:05:24 +0100
Subject: [PATCH] Darwin, Arm64 : Truncate char immediates in vector
 initializers to mode size.

Darwin has signed chars, so that 8b immediates > 127 appear to be negative
which produce large positive (out of assembler range) values when inspected
by UINTVAL ().  This patch truncates the values to the bitrange of the mode
of the input.

Fixes github issue 15.

(cherry picked from commit 9060dd0ac879a3bf2f2950ac7fa41b65072bc219)
Signed-off-by: Kirill A. Korinsky <kirill@korins.ky>
---
 gcc/config/aarch64/aarch64.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git gcc/config/aarch64/aarch64.c gcc/config/aarch64/aarch64.c
index e6bf5ae3808..07a8444ccec 100644
--- gcc/config/aarch64/aarch64.c
+++ gcc/config/aarch64/aarch64.c
@@ -20288,6 +20288,16 @@ aarch64_output_simd_mov_immediate (rtx const_vector, unsigned width,
     }
 
   gcc_assert (CONST_INT_P (info.u.mov.value));
+  unsigned HOST_WIDE_INT value = UINTVAL (info.u.mov.value);
+
+  /* We have signed chars which can result in a sign-extended 8bit value
+     which is then emitted as an unsigned hex value, and the LLVM back end
+     assembler rejects that as being too big.  */
+  if (TARGET_MACHO && (known_eq (GET_MODE_BITSIZE (info.elt_mode), 8)))
+    {
+      unsigned HOST_WIDE_INT mask = (1U << GET_MODE_BITSIZE (info.elt_mode))-1;
+      value &= mask;
+    }
 
   if (which == AARCH64_CHECK_MOV)
     {
@@ -20296,16 +20306,16 @@ aarch64_output_simd_mov_immediate (rtx const_vector, unsigned width,
 		  ? "msl" : "lsl");
       if (lane_count == 1)
 	snprintf (templ, sizeof (templ), "%s\t%%d0, " HOST_WIDE_INT_PRINT_HEX,
-		  mnemonic, UINTVAL (info.u.mov.value));
+		  mnemonic, value);
       else if (info.u.mov.shift)
 	snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, "
 		  HOST_WIDE_INT_PRINT_HEX ", %s %d", mnemonic, lane_count,
-		  element_char, UINTVAL (info.u.mov.value), shift_op,
+		  element_char, value, shift_op,
 		  info.u.mov.shift);
       else
 	snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, "
 		  HOST_WIDE_INT_PRINT_HEX, mnemonic, lane_count,
-		  element_char, UINTVAL (info.u.mov.value));
+		  element_char, value);
     }
   else
     {
@@ -20314,12 +20324,12 @@ aarch64_output_simd_mov_immediate (rtx const_vector, unsigned width,
       if (info.u.mov.shift)
 	snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #"
 		  HOST_WIDE_INT_PRINT_DEC ", %s #%d", mnemonic, lane_count,
-		  element_char, UINTVAL (info.u.mov.value), "lsl",
+		  element_char, value, "lsl",
 		  info.u.mov.shift);
       else
 	snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #"
 		  HOST_WIDE_INT_PRINT_DEC, mnemonic, lane_count,
-		  element_char, UINTVAL (info.u.mov.value));
+		  element_char, value);
     }
   return templ;
 }
-- 
2.42.1

