From 6d038308cf73a4281611b5ce07417e8993cce349 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Fri, 8 Nov 2024 02:31:15 +0000
Subject: [PATCH] jit: Use -mno-outline-atomics for bitcode.

If postgres was built by gcc not using -moutline-atomics, and the
equivalent bitcode was built by clang using -moutput-atomics, then the
bitcode could contain references to outline atomics symbols that are not
available in the executable or anywhere else.

At least Debian and Ubuntu are known to ship gcc and clang compilers
that differ on the use of outline atomics by default.

Example of resulting failure, when trying to inline .bc code:

postgres=# set jit_inline_above_cost = 0;
SET
postgres=# set jit_above_cost = 0;
SET
postgres=# select pg_last_wal_receive_lsn();
WARNING:  failed to resolve name __aarch64_swp4_acq_rel
FATAL:  fatal llvm error: Program used external function
'__aarch64_swp4_acq_rel' which could not be resolved!

For now, explicitly disable outline atomics in bitcode, even if it would
be OK to use them on this system.  This is done only in the configure
scripts, because the meson scripts don't yet generate bitcode.

This doesn't affect builds using -march higher than armv8-a (eg macOS),
because then LSE instructions are used directly inline.

Back-patch to all supported releases.

Reported-by: Alexander Kozhemyakin <a.kozhemyakin@postgrespro.ru>
Discussion: https://postgr.es/m/18610-37bf303f904fede3%40postgresql.org
---
 configure    | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++
 configure.ac |   7 ++++
 2 files changed, 112 insertions(+)

diff --git a/configure b/configure
index 4b01b682b15..ba5a4c1af73 100755
--- a/configure
+++ b/configure
@@ -7284,6 +7284,111 @@ if test x"$pgac_cv_prog_CLANGXX_cxxflags__fexcess_precision_standard" = x"yes";
 fi
 
 
+  # Ideally bitcode would match $CC's use, or not, of outline atomic functions,
+  # a way to access fast LSE lock instructions or fallback code on when
+  # targeting the basic armv8-a instruction set (which lacked them) but for now
+  # err on the side of not assuming they are not available in inlined code
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CLANG} supports -mno-outline-atomics, for BITCODE_CFLAGS" >&5
+$as_echo_n "checking whether ${CLANG} supports -mno-outline-atomics, for BITCODE_CFLAGS... " >&6; }
+if ${pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CXXFLAGS=$CXXFLAGS
+pgac_save_CXX=$CXX
+CXX=${CLANG}
+CXXFLAGS="${BITCODE_CFLAGS} -mno-outline-atomics"
+ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ac_cxx_werror_flag=yes
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics=yes
+else
+  pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+CXXFLAGS="$pgac_save_CXXFLAGS"
+CXX="$pgac_save_CXX"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics" >&5
+$as_echo "$pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics" >&6; }
+if test x"$pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics" = x"yes"; then
+  BITCODE_CFLAGS="${BITCODE_CFLAGS} -mno-outline-atomics"
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CLANG} supports -mno-outline-atomics, for BITCODE_CXXFLAGS" >&5
+$as_echo_n "checking whether ${CLANG} supports -mno-outline-atomics, for BITCODE_CXXFLAGS... " >&6; }
+if ${pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CXXFLAGS=$CXXFLAGS
+pgac_save_CXX=$CXX
+CXX=${CLANG}
+CXXFLAGS="${BITCODE_CXXFLAGS} -mno-outline-atomics"
+ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ac_cxx_werror_flag=yes
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics=yes
+else
+  pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+CXXFLAGS="$pgac_save_CXXFLAGS"
+CXX="$pgac_save_CXX"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics" >&5
+$as_echo "$pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics" >&6; }
+if test x"$pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics" = x"yes"; then
+  BITCODE_CXXFLAGS="${BITCODE_CXXFLAGS} -mno-outline-atomics"
+fi
+
+
   NOT_THE_CFLAGS=""
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CLANG} supports -Wunused-command-line-argument, for NOT_THE_CFLAGS" >&5
 $as_echo_n "checking whether ${CLANG} supports -Wunused-command-line-argument, for NOT_THE_CFLAGS... " >&6; }
diff --git a/configure.ac b/configure.ac
index e7f4f0fc22f..f28ddc5e583 100644
--- a/configure.ac
+++ b/configure.ac
@@ -633,6 +633,13 @@ if test "$with_llvm" = yes ; then
   PGAC_PROG_VARCC_VARFLAGS_OPT(CLANG, BITCODE_CFLAGS, [-fexcess-precision=standard])
   PGAC_PROG_VARCXX_VARFLAGS_OPT(CLANGXX, BITCODE_CXXFLAGS, [-fexcess-precision=standard])
 
+  # Ideally bitcode would match $CC's use, or not, of outline atomic functions,
+  # a way to access fast LSE lock instructions or fallback code on when
+  # targeting the basic armv8-a instruction set (which lacked them) but for now
+  # err on the side of not assuming they are not available in inlined code
+  PGAC_PROG_VARCXX_VARFLAGS_OPT(CLANG, BITCODE_CFLAGS, [-mno-outline-atomics])
+  PGAC_PROG_VARCXX_VARFLAGS_OPT(CLANG, BITCODE_CXXFLAGS, [-mno-outline-atomics])
+
   NOT_THE_CFLAGS=""
   PGAC_PROG_VARCC_VARFLAGS_OPT(CLANG, NOT_THE_CFLAGS, [-Wunused-command-line-argument])
   if test -n "$NOT_THE_CFLAGS"; then
-- 
2.39.5 (Apple Git-154)

