[llvm-branch-commits] [lldb] [clang-tools-extra] [mlir] [lld] [libcxxabi] [libc] [libcxx] [compiler-rt] [openmp] [flang] [clang] [llvm] [clang] Support __attribute__((ifunc(...))) on Darwin platforms (PR #73687)
Jon Roelofs via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Dec 14 13:49:26 PST 2023
Andrzej =?utf-8?q?WarzyĆski?= <andrzej.warzynski at arm.com>,Jay Foad
<jay.foad at amd.com>,Craig Hesling <hesling.craig at gmail.com>,Nick Desaulniers
<nickdesaulniers at users.noreply.github.com>,Jon Roelofs
<jonathan_roelofs at apple.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/73687 at github.com>
https://github.com/jroelofs updated https://github.com/llvm/llvm-project/pull/73687
>From aeb39b92bbd7670fb8c6b9e76a456a92199691b3 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Wed, 29 Nov 2023 12:23:46 -0800
Subject: [PATCH 01/16] adjust tests per review feedback
Created using spr 1.3.4
---
clang/test/CodeGen/attr-ifunc.c | 20 +++++++++++++++++++
clang/test/CodeGen/attr-ifunc.cpp | 4 ++++
.../CodeGenCXX/externc-ifunc-resolver.cpp | 2 ++
clang/test/SemaCXX/externc-ifunc-resolver.cpp | 4 ++++
4 files changed, 30 insertions(+)
diff --git a/clang/test/CodeGen/attr-ifunc.c b/clang/test/CodeGen/attr-ifunc.c
index 4f8fe13530fdb7..2ad41edf20dfa0 100644
--- a/clang/test/CodeGen/attr-ifunc.c
+++ b/clang/test/CodeGen/attr-ifunc.c
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-windows -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -verify -emit-llvm-only -DCHECK_ALIASES %s
// RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -verify -emit-llvm-only %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsyntax-only -verify -emit-llvm-only %s
#if defined(_WIN32)
void foo(void) {}
@@ -36,6 +37,25 @@ void *f6_resolver(void) __attribute__((ifunc("f6_resolver_resolver")));
void f6(void) __attribute__((ifunc("f6_resolver")));
// expected-error at -1 {{ifunc must point to a defined function}}
+#elif defined(__APPLE__)
+
+// NOTE: aliases are not supported on Darwin, so the above tests are not relevant.
+
+#define STR2(X) #X
+#define STR(X) STR2(X)
+#define PREFIX STR(__USER_LABEL_PREFIX__)
+
+void f1a(void) __asm("f1");
+void f1a(void) {}
+// expected-note at -1 {{previous definition is here}}
+void f1(void) __attribute__((ifunc(PREFIX "f1_ifunc"))) __asm("f1");
+// expected-error at -1 {{definition with same mangled name '<U+0001>f1' as another definition}}
+void *f1_ifunc(void) { return 0; }
+
+void *f6_ifunc(int i);
+void __attribute__((ifunc(PREFIX "f6_ifunc"))) f6(void) {}
+// expected-error at -1 {{definition 'f6' cannot also be an ifunc}}
+
#else
void f1a(void) __asm("f1");
void f1a(void) {}
diff --git a/clang/test/CodeGen/attr-ifunc.cpp b/clang/test/CodeGen/attr-ifunc.cpp
index 5b5b2c14b4074b..b6e342df46eb58 100644
--- a/clang/test/CodeGen/attr-ifunc.cpp
+++ b/clang/test/CodeGen/attr-ifunc.cpp
@@ -1,5 +1,9 @@
// RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -verify -emit-llvm-only %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsyntax-only -verify -emit-llvm-only %s
+// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify -emit-llvm-only %s
// RUN: not %clang_cc1 -triple x86_64-linux -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -triple x86_64-apple-macosx -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -triple arm64-apple-macosx -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
void *f1_ifunc(void) { return nullptr; }
void f1(void) __attribute__((ifunc("f1_ifunc")));
diff --git a/clang/test/CodeGenCXX/externc-ifunc-resolver.cpp b/clang/test/CodeGenCXX/externc-ifunc-resolver.cpp
index 0518a8dcc831dd..be4453ae7eb08c 100644
--- a/clang/test/CodeGenCXX/externc-ifunc-resolver.cpp
+++ b/clang/test/CodeGenCXX/externc-ifunc-resolver.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-macosx -emit-llvm -o - %s | FileCheck %s
extern "C" {
__attribute__((used)) static void *resolve_foo() { return 0; }
diff --git a/clang/test/SemaCXX/externc-ifunc-resolver.cpp b/clang/test/SemaCXX/externc-ifunc-resolver.cpp
index aa44525bde2cae..6c6c262c5f09d8 100644
--- a/clang/test/SemaCXX/externc-ifunc-resolver.cpp
+++ b/clang/test/SemaCXX/externc-ifunc-resolver.cpp
@@ -1,5 +1,9 @@
// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-linux-gnu -verify %s
+// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-apple-macosx -verify %s
+// RUN: %clang_cc1 -emit-llvm-only -triple arm64-apple-macosx -verify %s
// RUN: not %clang_cc1 -triple x86_64-linux -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -triple x86_64-apple-macosx -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -triple arm64-apple-macosx -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
extern "C" {
__attribute__((used)) static void *resolve_foo() { return 0; }
>From 68ea91dd8b506764c0a89e9220cfcefcf3790973 Mon Sep 17 00:00:00 2001
From: Andrew Brown <andrew.brown at intel.com>
Date: Thu, 14 Dec 2023 11:48:01 -0800
Subject: [PATCH 02/16] [openmp][wasm] Allow compiling OpenMP to WebAssembly
(#71297)
This change allows building the static OpenMP runtime, `libomp.a`, as
WebAssembly. It builds on the work done in [D142593] but goes further in
several ways:
- it makes the OpenMP CMake files more WebAssembly-aware
- it conditions much more code (or code that had been refactored since
[D142593]) for `KMP_ARCH_WASM` and `KMP_OS_WASI`
- it fixes a Clang crash due to unimplemented common symbols in
WebAssembly
The commit messages have more details. Please understand this PR as a
start, not the completed work, for WebAssembly support in OpenMP.
Getting the tests running somehow would be a good next step, e.g.; but
what is contained here works, at least with recent versions of
[wasi-sdk] and engines that support [wasi-threads]. I suspect the same
is true for Emscripten and browsers, but I have not tested that
workflow.
[D142593]: https://reviews.llvm.org/D142593
[wasi-sdk]: https://github.com/WebAssembly/wasi-sdk
[wasi-threads]: https://github.com/WebAssembly/wasi-threads
---------
Co-authored-by: Atanas Atanasov <atanas.atanasov at intel.com>
---
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp | 11 ++--
openmp/CMakeLists.txt | 2 +-
openmp/runtime/CMakeLists.txt | 14 ++++-
.../runtime/cmake/LibompGetArchitecture.cmake | 2 +
openmp/runtime/cmake/config-ix.cmake | 23 +++++---
openmp/runtime/src/kmp.h | 16 +++++-
openmp/runtime/src/kmp_ftn_entry.h | 18 +++---
openmp/runtime/src/kmp_gsupport.cpp | 2 +-
openmp/runtime/src/kmp_os.h | 15 +++--
openmp/runtime/src/kmp_platform.h | 20 +++++--
openmp/runtime/src/kmp_runtime.cpp | 57 ++++++++++---------
openmp/runtime/src/kmp_utility.cpp | 2 +
openmp/runtime/src/z_Linux_asm.S | 22 ++++++-
openmp/runtime/src/z_Linux_util.cpp | 16 +++++-
14 files changed, 152 insertions(+), 68 deletions(-)
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index be9a44885f668e..ce428f78dc843e 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -5213,10 +5213,13 @@ OpenMPIRBuilder::getOrCreateInternalVariable(Type *Ty, const StringRef &Name,
// variable for possibly changing that to internal or private, or maybe
// create different versions of the function for different OMP internal
// variables.
- auto *GV = new GlobalVariable(
- M, Ty, /*IsConstant=*/false, GlobalValue::CommonLinkage,
- Constant::getNullValue(Ty), Elem.first(),
- /*InsertBefore=*/nullptr, GlobalValue::NotThreadLocal, AddressSpace);
+ auto Linkage = this->M.getTargetTriple().rfind("wasm32") == 0
+ ? GlobalValue::ExternalLinkage
+ : GlobalValue::CommonLinkage;
+ auto *GV = new GlobalVariable(M, Ty, /*IsConstant=*/false, Linkage,
+ Constant::getNullValue(Ty), Elem.first(),
+ /*InsertBefore=*/nullptr,
+ GlobalValue::NotThreadLocal, AddressSpace);
const DataLayout &DL = M.getDataLayout();
const llvm::Align TypeAlign = DL.getABITypeAlign(Ty);
const llvm::Align PtrAlign = DL.getPointerABIAlignment(AddressSpace);
diff --git a/openmp/CMakeLists.txt b/openmp/CMakeLists.txt
index 13e65bf70b5bb5..307c8dbbc0c3b9 100644
--- a/openmp/CMakeLists.txt
+++ b/openmp/CMakeLists.txt
@@ -94,7 +94,7 @@ set(ENABLE_LIBOMPTARGET ON)
# Since the device plugins are only supported on Linux anyway,
# there is no point in trying to compile libomptarget on other OSes.
# 32-bit systems are not supported either.
-if (APPLE OR WIN32 OR NOT "cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES OR NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
+if (APPLE OR WIN32 OR WASM OR NOT "cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES OR NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ENABLE_LIBOMPTARGET OFF)
endif()
diff --git a/openmp/runtime/CMakeLists.txt b/openmp/runtime/CMakeLists.txt
index 8a913989272c4c..80064170db193d 100644
--- a/openmp/runtime/CMakeLists.txt
+++ b/openmp/runtime/CMakeLists.txt
@@ -30,7 +30,7 @@ if(${OPENMP_STANDALONE_BUILD})
# If adding a new architecture, take a look at cmake/LibompGetArchitecture.cmake
libomp_get_architecture(LIBOMP_DETECTED_ARCH)
set(LIBOMP_ARCH ${LIBOMP_DETECTED_ARCH} CACHE STRING
- "The architecture to build for (x86_64/i386/arm/ppc64/ppc64le/aarch64/mic/mips/mips64/riscv64/loongarch64/ve/s390x).")
+ "The architecture to build for (x86_64/i386/arm/ppc64/ppc64le/aarch64/mic/mips/mips64/riscv64/loongarch64/ve/s390x/wasm32).")
# Should assertions be enabled? They are on by default.
set(LIBOMP_ENABLE_ASSERTIONS TRUE CACHE BOOL
"enable assertions?")
@@ -67,6 +67,8 @@ else() # Part of LLVM build
set(LIBOMP_ARCH ve)
elseif(LIBOMP_NATIVE_ARCH MATCHES "s390x")
set(LIBOMP_ARCH s390x)
+ elseif(LIBOMP_NATIVE_ARCH MATCHES "wasm")
+ set(LIBOMP_ARCH wasm32)
else()
# last ditch effort
libomp_get_architecture(LIBOMP_ARCH)
@@ -87,7 +89,7 @@ if(LIBOMP_ARCH STREQUAL "aarch64")
endif()
endif()
-libomp_check_variable(LIBOMP_ARCH 32e x86_64 32 i386 arm ppc64 ppc64le aarch64 aarch64_a64fx mic mips mips64 riscv64 loongarch64 ve s390x)
+libomp_check_variable(LIBOMP_ARCH 32e x86_64 32 i386 arm ppc64 ppc64le aarch64 aarch64_a64fx mic mips mips64 riscv64 loongarch64 ve s390x wasm32)
set(LIBOMP_LIB_TYPE normal CACHE STRING
"Performance,Profiling,Stubs library (normal/profile/stubs)")
@@ -168,6 +170,7 @@ set(RISCV64 FALSE)
set(LOONGARCH64 FALSE)
set(VE FALSE)
set(S390X FALSE)
+set(WASM FALSE)
if("${LIBOMP_ARCH}" STREQUAL "i386" OR "${LIBOMP_ARCH}" STREQUAL "32") # IA-32 architecture
set(IA32 TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "x86_64" OR "${LIBOMP_ARCH}" STREQUAL "32e") # Intel(R) 64 architecture
@@ -198,6 +201,8 @@ elseif("${LIBOMP_ARCH}" STREQUAL "ve") # VE architecture
set(VE TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "s390x") # S390x (Z) architecture
set(S390X TRUE)
+elseif("${LIBOMP_ARCH}" STREQUAL "wasm32") # WebAssembly architecture
+ set(WASM TRUE)
endif()
# Set some flags based on build_type
@@ -306,6 +311,11 @@ endif()
set(LIBOMP_ENABLE_SHARED TRUE CACHE BOOL
"Shared library instead of static library?")
+if(WASM)
+ libomp_warning_say("The WebAssembly build currently only supports static libraries; forcing LIBOMP_ENABLE_SHARED to false")
+ set(LIBOMP_ENABLE_SHARED FALSE)
+endif()
+
if(WIN32 AND NOT LIBOMP_ENABLE_SHARED)
libomp_error_say("Static libraries requested but not available on Windows")
endif()
diff --git a/openmp/runtime/cmake/LibompGetArchitecture.cmake b/openmp/runtime/cmake/LibompGetArchitecture.cmake
index 9d4f08b92de50d..cd85267020bd64 100644
--- a/openmp/runtime/cmake/LibompGetArchitecture.cmake
+++ b/openmp/runtime/cmake/LibompGetArchitecture.cmake
@@ -53,6 +53,8 @@ function(libomp_get_architecture return_arch)
#error ARCHITECTURE=ve
#elif defined(__s390x__)
#error ARCHITECTURE=s390x
+ #elif defined(__wasm32__)
+ #error ARCHITECTURE=wasm32
#else
#error ARCHITECTURE=UnknownArchitecture
#endif
diff --git a/openmp/runtime/cmake/config-ix.cmake b/openmp/runtime/cmake/config-ix.cmake
index d54d350816926d..90b9af4cd3829b 100644
--- a/openmp/runtime/cmake/config-ix.cmake
+++ b/openmp/runtime/cmake/config-ix.cmake
@@ -150,15 +150,20 @@ if(CMAKE_C_COMPILER_ID STREQUAL "Intel" OR CMAKE_C_COMPILER_ID STREQUAL "IntelLL
check_library_exists(irc_pic _intel_fast_memcpy "" LIBOMP_HAVE_IRC_PIC_LIBRARY)
endif()
-# Checking Threading requirements
-find_package(Threads REQUIRED)
-if(WIN32)
- if(NOT CMAKE_USE_WIN32_THREADS_INIT)
- libomp_error_say("Need Win32 thread interface on Windows.")
- endif()
-else()
- if(NOT CMAKE_USE_PTHREADS_INIT)
- libomp_error_say("Need pthread interface on Unix-like systems.")
+# Checking threading requirements. Note that compiling to WebAssembly threads
+# with either the Emscripten or wasi-threads flavor ends up using the pthreads
+# interface in a WebAssembly-compiled libc; CMake does not yet know how to
+# detect this.
+if (NOT WASM)
+ find_package(Threads REQUIRED)
+ if(WIN32)
+ if(NOT CMAKE_USE_WIN32_THREADS_INIT)
+ libomp_error_say("Need Win32 thread interface on Windows.")
+ endif()
+ else()
+ if(NOT CMAKE_USE_PTHREADS_INIT)
+ libomp_error_say("Need pthread interface on Unix-like systems.")
+ endif()
endif()
endif()
diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h
index d34adf7cbf8af3..3dbf8c71c48d38 100644
--- a/openmp/runtime/src/kmp.h
+++ b/openmp/runtime/src/kmp.h
@@ -63,7 +63,15 @@
#undef KMP_CANCEL_THREADS
#endif
+// Some WASI targets (e.g., wasm32-wasi-threads) do not support thread
+// cancellation.
+#if KMP_OS_WASI
+#undef KMP_CANCEL_THREADS
+#endif
+
+#if !KMP_OS_WASI
#include <signal.h>
+#endif
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
@@ -124,7 +132,7 @@ class kmp_stats_list;
#endif
#include "kmp_i18n.h"
-#define KMP_HANDLE_SIGNALS (KMP_OS_UNIX || KMP_OS_WINDOWS)
+#define KMP_HANDLE_SIGNALS ((KMP_OS_UNIX && !KMP_OS_WASI) || KMP_OS_WINDOWS)
#include "kmp_wrapper_malloc.h"
#if KMP_OS_UNIX
@@ -601,7 +609,9 @@ typedef int PACKED_REDUCTION_METHOD_T;
#endif
#if KMP_OS_UNIX
+#if !KMP_OS_WASI
#include <dlfcn.h>
+#endif
#include <pthread.h>
#endif
@@ -1340,6 +1350,10 @@ extern kmp_uint64 __kmp_now_nsec();
/* TODO: tune for KMP_OS_SOLARIS */
#define KMP_INIT_WAIT 1024U /* initial number of spin-tests */
#define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */
+#elif KMP_OS_WASI
+/* TODO: tune for KMP_OS_WASI */
+#define KMP_INIT_WAIT 1024U /* initial number of spin-tests */
+#define KMP_NEXT_WAIT 512U /* susequent number of spin-tests */
#endif
#if KMP_ARCH_X86 || KMP_ARCH_X86_64
diff --git a/openmp/runtime/src/kmp_ftn_entry.h b/openmp/runtime/src/kmp_ftn_entry.h
index ad19079cb65090..d54c5bfd10fe96 100644
--- a/openmp/runtime/src/kmp_ftn_entry.h
+++ b/openmp/runtime/src/kmp_ftn_entry.h
@@ -593,7 +593,7 @@ int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_THREAD_NUM)(void) {
return 0;
}
--gtid; // We keep (gtid+1) in TLS
-#elif KMP_OS_LINUX
+#elif KMP_OS_LINUX || KMP_OS_WASI
#ifdef KMP_TDATA_GTID
if (__kmp_gtid_mode >= 3) {
if ((gtid = __kmp_gtid) == KMP_GTID_DNE) {
@@ -1043,7 +1043,7 @@ void FTN_STDCALL KMP_EXPAND_NAME(FTN_SET_DEFAULT_DEVICE)(int KMP_DEREF arg) {
int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_NUM_DEVICES)(void)
KMP_WEAK_ATTRIBUTE_EXTERNAL;
int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_NUM_DEVICES)(void) {
-#if KMP_MIC || KMP_OS_DARWIN || defined(KMP_STUB)
+#if KMP_MIC || KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
return 0;
#else
int (*fptr)();
@@ -1558,7 +1558,7 @@ typedef void *omp_interop_t;
// libomptarget, if loaded, provides this function
int FTN_STDCALL FTN_GET_NUM_INTEROP_PROPERTIES(const omp_interop_t interop) {
-#if KMP_OS_DARWIN || defined(KMP_STUB)
+#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
return 0;
#else
int (*fptr)(const omp_interop_t);
@@ -1573,7 +1573,7 @@ int FTN_STDCALL FTN_GET_NUM_INTEROP_PROPERTIES(const omp_interop_t interop) {
intptr_t FTN_STDCALL FTN_GET_INTEROP_INT(const omp_interop_t interop,
omp_interop_property_t property_id,
int *err) {
-#if KMP_OS_DARWIN || defined(KMP_STUB)
+#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
return 0;
#else
intptr_t (*fptr)(const omp_interop_t, omp_interop_property_t, int *);
@@ -1587,7 +1587,7 @@ intptr_t FTN_STDCALL FTN_GET_INTEROP_INT(const omp_interop_t interop,
void *FTN_STDCALL FTN_GET_INTEROP_PTR(const omp_interop_t interop,
omp_interop_property_t property_id,
int *err) {
-#if KMP_OS_DARWIN || defined(KMP_STUB)
+#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
return nullptr;
#else
void *(*fptr)(const omp_interop_t, omp_interop_property_t, int *);
@@ -1601,7 +1601,7 @@ void *FTN_STDCALL FTN_GET_INTEROP_PTR(const omp_interop_t interop,
const char *FTN_STDCALL FTN_GET_INTEROP_STR(const omp_interop_t interop,
omp_interop_property_t property_id,
int *err) {
-#if KMP_OS_DARWIN || defined(KMP_STUB)
+#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
return nullptr;
#else
const char *(*fptr)(const omp_interop_t, omp_interop_property_t, int *);
@@ -1614,7 +1614,7 @@ const char *FTN_STDCALL FTN_GET_INTEROP_STR(const omp_interop_t interop,
// libomptarget, if loaded, provides this function
const char *FTN_STDCALL FTN_GET_INTEROP_NAME(
const omp_interop_t interop, omp_interop_property_t property_id) {
-#if KMP_OS_DARWIN || defined(KMP_STUB)
+#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
return nullptr;
#else
const char *(*fptr)(const omp_interop_t, omp_interop_property_t);
@@ -1627,7 +1627,7 @@ const char *FTN_STDCALL FTN_GET_INTEROP_NAME(
// libomptarget, if loaded, provides this function
const char *FTN_STDCALL FTN_GET_INTEROP_TYPE_DESC(
const omp_interop_t interop, omp_interop_property_t property_id) {
-#if KMP_OS_DARWIN || defined(KMP_STUB)
+#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
return nullptr;
#else
const char *(*fptr)(const omp_interop_t, omp_interop_property_t);
@@ -1640,7 +1640,7 @@ const char *FTN_STDCALL FTN_GET_INTEROP_TYPE_DESC(
// libomptarget, if loaded, provides this function
const char *FTN_STDCALL FTN_GET_INTEROP_RC_DESC(
const omp_interop_t interop, omp_interop_property_t property_id) {
-#if KMP_OS_DARWIN || defined(KMP_STUB)
+#if KMP_OS_DARWIN || KMP_OS_WASI || defined(KMP_STUB)
return nullptr;
#else
const char *(*fptr)(const omp_interop_t, omp_interop_property_t);
diff --git a/openmp/runtime/src/kmp_gsupport.cpp b/openmp/runtime/src/kmp_gsupport.cpp
index d77d4809a7e95c..dc843f78dc6975 100644
--- a/openmp/runtime/src/kmp_gsupport.cpp
+++ b/openmp/runtime/src/kmp_gsupport.cpp
@@ -356,7 +356,7 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_ORDERED_END)(void) {
// They come in two flavors: 64-bit unsigned, and either 32-bit signed
// (IA-32 architecture) or 64-bit signed (Intel(R) 64).
-#if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS
+#if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_WASM
#define KMP_DISPATCH_INIT __kmp_aux_dispatch_init_4
#define KMP_DISPATCH_FINI_CHUNK __kmp_aux_dispatch_fini_chunk_4
#define KMP_DISPATCH_NEXT __kmpc_dispatch_next_4
diff --git a/openmp/runtime/src/kmp_os.h b/openmp/runtime/src/kmp_os.h
index beb8d0197ddf58..4ffe9f2d8c953b 100644
--- a/openmp/runtime/src/kmp_os.h
+++ b/openmp/runtime/src/kmp_os.h
@@ -75,7 +75,7 @@
#error Unknown compiler
#endif
-#if (KMP_OS_LINUX || KMP_OS_WINDOWS || KMP_OS_FREEBSD)
+#if (KMP_OS_LINUX || KMP_OS_WINDOWS || KMP_OS_FREEBSD) && !KMP_OS_WASI
#define KMP_AFFINITY_SUPPORTED 1
#if KMP_OS_WINDOWS && KMP_ARCH_X86_64
#define KMP_GROUP_AFFINITY 1
@@ -176,7 +176,7 @@ typedef unsigned long long kmp_uint64;
#define KMP_UINT64_SPEC "llu"
#endif /* KMP_OS_UNIX */
-#if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS
+#if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_WASM
#define KMP_SIZE_T_SPEC KMP_UINT32_SPEC
#elif KMP_ARCH_X86_64 || KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 || \
KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || \
@@ -186,7 +186,7 @@ typedef unsigned long long kmp_uint64;
#error "Can't determine size_t printf format specifier."
#endif
-#if KMP_ARCH_X86 || KMP_ARCH_ARM
+#if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_WASM
#define KMP_SIZE_T_MAX (0xFFFFFFFF)
#else
#define KMP_SIZE_T_MAX (0xFFFFFFFFFFFFFFFF)
@@ -215,8 +215,8 @@ typedef kmp_uint32 kmp_uint;
#define KMP_INT_MIN ((kmp_int32)0x80000000)
// stdarg handling
-#if (KMP_ARCH_ARM || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64) && \
- (KMP_OS_FREEBSD || KMP_OS_LINUX)
+#if (KMP_ARCH_ARM || KMP_ARCH_X86_64 || KMP_ARCH_AARCH64 || KMP_ARCH_WASM) && \
+ (KMP_OS_FREEBSD || KMP_OS_LINUX || KMP_OS_WASI)
typedef va_list *kmp_va_list;
#define kmp_va_deref(ap) (*(ap))
#define kmp_va_addr_of(ap) (&(ap))
@@ -1146,7 +1146,7 @@ extern kmp_real64 __kmp_xchg_real64(volatile kmp_real64 *p, kmp_real64 v);
KMP_COMPARE_AND_STORE_REL64((volatile kmp_int64 *)(volatile void *)&(a), \
(kmp_int64)(b), (kmp_int64)(c))
-#if KMP_ARCH_X86 || KMP_ARCH_MIPS
+#if KMP_ARCH_X86 || KMP_ARCH_MIPS || KMP_ARCH_WASM
// What about ARM?
#define TCR_PTR(a) ((void *)TCR_4(a))
#define TCW_PTR(a, b) TCW_4((a), (b))
@@ -1288,6 +1288,9 @@ bool __kmp_atomic_compare_store_rel(std::atomic<T> *p, T expected, T desired) {
extern void *__kmp_lookup_symbol(const char *name, bool next = false);
#define KMP_DLSYM(name) __kmp_lookup_symbol(name)
#define KMP_DLSYM_NEXT(name) __kmp_lookup_symbol(name, true)
+#elif KMP_OS_WASI
+#define KMP_DLSYM(name) nullptr
+#define KMP_DLSYM_NEXT(name) nullptr
#else
#define KMP_DLSYM(name) dlsym(RTLD_DEFAULT, name)
#define KMP_DLSYM_NEXT(name) dlsym(RTLD_NEXT, name)
diff --git a/openmp/runtime/src/kmp_platform.h b/openmp/runtime/src/kmp_platform.h
index b7972c7248dd57..45f411b9c21949 100644
--- a/openmp/runtime/src/kmp_platform.h
+++ b/openmp/runtime/src/kmp_platform.h
@@ -24,6 +24,7 @@
#define KMP_OS_WINDOWS 0
#define KMP_OS_HURD 0
#define KMP_OS_SOLARIS 0
+#define KMP_OS_WASI 0
#define KMP_OS_UNIX 0 /* disjunction of KMP_OS_LINUX, KMP_OS_DARWIN etc. */
#ifdef _WIN32
@@ -76,14 +77,20 @@
#define KMP_OS_SOLARIS 1
#endif
+#if (defined __wasi__) || (defined __EMSCRIPTEN__)
+#undef KMP_OS_WASI
+#define KMP_OS_WASI 1
+#endif
+
#if (1 != KMP_OS_LINUX + KMP_OS_DRAGONFLY + KMP_OS_FREEBSD + KMP_OS_NETBSD + \
KMP_OS_OPENBSD + KMP_OS_DARWIN + KMP_OS_WINDOWS + KMP_OS_HURD + \
- KMP_OS_SOLARIS)
+ KMP_OS_SOLARIS + KMP_OS_WASI)
#error Unknown OS
#endif
#if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
- KMP_OS_OPENBSD || KMP_OS_DARWIN || KMP_OS_HURD || KMP_OS_SOLARIS
+ KMP_OS_OPENBSD || KMP_OS_DARWIN || KMP_OS_HURD || KMP_OS_SOLARIS || \
+ KMP_OS_WASI
#undef KMP_OS_UNIX
#define KMP_OS_UNIX 1
#endif
@@ -196,6 +203,10 @@
#define KMP_ARCH_ARM 1
#endif
+#if defined(__wasm32__)
+#define KMP_ARCH_WASM 1
+#endif
+
#if defined(__MIC__) || defined(__MIC2__)
#define KMP_MIC 1
#if __MIC2__ || __KNC__
@@ -212,7 +223,8 @@
#endif
/* Specify 32 bit architectures here */
-#define KMP_32_BIT_ARCH (KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS)
+#define KMP_32_BIT_ARCH \
+ (KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_WASM)
// Platforms which support Intel(R) Many Integrated Core Architecture
#define KMP_MIC_SUPPORTED \
@@ -222,7 +234,7 @@
#if (1 != KMP_ARCH_X86 + KMP_ARCH_X86_64 + KMP_ARCH_ARM + KMP_ARCH_PPC64 + \
KMP_ARCH_AARCH64 + KMP_ARCH_MIPS + KMP_ARCH_MIPS64 + \
KMP_ARCH_RISCV64 + KMP_ARCH_LOONGARCH64 + KMP_ARCH_VE + \
- KMP_ARCH_S390X)
+ KMP_ARCH_S390X + KMP_ARCH_WASM)
#error Unknown or unsupported architecture
#endif
diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp
index 25136691bc72de..7d2e7a99ade431 100644
--- a/openmp/runtime/src/kmp_runtime.cpp
+++ b/openmp/runtime/src/kmp_runtime.cpp
@@ -47,8 +47,9 @@ static char *ProfileTraceFile = nullptr;
#include <process.h>
#endif
-#if KMP_OS_WINDOWS
-// windows does not need include files as it doesn't use shared memory
+#ifndef KMP_USE_SHM
+// Windows and WASI do not need these include files as they don't use shared
+// memory.
#else
#include <sys/mman.h>
#include <sys/stat.h>
@@ -446,26 +447,26 @@ void __kmp_abort_process() {
__kmp_dump_debug_buffer();
}
- if (KMP_OS_WINDOWS) {
- // Let other threads know of abnormal termination and prevent deadlock
- // if abort happened during library initialization or shutdown
- __kmp_global.g.g_abort = SIGABRT;
-
- /* On Windows* OS by default abort() causes pop-up error box, which stalls
- nightly testing. Unfortunately, we cannot reliably suppress pop-up error
- boxes. _set_abort_behavior() works well, but this function is not
- available in VS7 (this is not problem for DLL, but it is a problem for
- static OpenMP RTL). SetErrorMode (and so, timelimit utility) does not
- help, at least in some versions of MS C RTL.
-
- It seems following sequence is the only way to simulate abort() and
- avoid pop-up error box. */
- raise(SIGABRT);
- _exit(3); // Just in case, if signal ignored, exit anyway.
- } else {
- __kmp_unregister_library();
- abort();
- }
+#if KMP_OS_WINDOWS
+ // Let other threads know of abnormal termination and prevent deadlock
+ // if abort happened during library initialization or shutdown
+ __kmp_global.g.g_abort = SIGABRT;
+
+ /* On Windows* OS by default abort() causes pop-up error box, which stalls
+ nightly testing. Unfortunately, we cannot reliably suppress pop-up error
+ boxes. _set_abort_behavior() works well, but this function is not
+ available in VS7 (this is not problem for DLL, but it is a problem for
+ static OpenMP RTL). SetErrorMode (and so, timelimit utility) does not
+ help, at least in some versions of MS C RTL.
+
+ It seems following sequence is the only way to simulate abort() and
+ avoid pop-up error box. */
+ raise(SIGABRT);
+ _exit(3); // Just in case, if signal ignored, exit anyway.
+#else
+ __kmp_unregister_library();
+ abort();
+#endif
__kmp_infinite_loop();
__kmp_release_bootstrap_lock(&__kmp_exit_lock);
@@ -8895,11 +8896,11 @@ __kmp_determine_reduction_method(
#if KMP_ARCH_X86_64 || KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 || \
KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || \
- KMP_ARCH_VE || KMP_ARCH_S390X
+ KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_WASM
#if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_DARWIN || KMP_OS_HURD || \
- KMP_OS_SOLARIS
+ KMP_OS_SOLARIS || KMP_OS_WASI
int teamsize_cutoff = 4;
@@ -8924,12 +8925,14 @@ __kmp_determine_reduction_method(
#error "Unknown or unsupported OS"
#endif // KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||
// KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_DARWIN || KMP_OS_HURD ||
- // KMP_OS_SOLARIS
+ // KMP_OS_SOLARIS || KMP_OS_WASI
-#elif KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_AARCH || KMP_ARCH_MIPS
+#elif KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_AARCH || KMP_ARCH_MIPS || \
+ KMP_ARCH_WASM
#if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
- KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_HURD || KMP_OS_SOLARIS
+ KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_HURD || KMP_OS_SOLARIS || \
+ KMP_OS_WASI
// basic tuning
diff --git a/openmp/runtime/src/kmp_utility.cpp b/openmp/runtime/src/kmp_utility.cpp
index 3174bbb7a5b75a..f901eaca92f4d1 100644
--- a/openmp/runtime/src/kmp_utility.cpp
+++ b/openmp/runtime/src/kmp_utility.cpp
@@ -294,6 +294,8 @@ void __kmp_expand_host_name(char *buffer, size_t size) {
if (!GetComputerNameA(buffer, &s))
KMP_STRCPY_S(buffer, size, unknown);
}
+#elif KMP_OS_WASI
+ KMP_STRCPY_S(buffer, size, unknown);
#else
buffer[size - 2] = 0;
if (gethostname(buffer, size) || buffer[size - 2] != 0)
diff --git a/openmp/runtime/src/z_Linux_asm.S b/openmp/runtime/src/z_Linux_asm.S
index a72705528d4162..14987c298fa5f9 100644
--- a/openmp/runtime/src/z_Linux_asm.S
+++ b/openmp/runtime/src/z_Linux_asm.S
@@ -2441,7 +2441,27 @@ KMP_PREFIX_UNDERSCORE(__kmp_unnamed_critical_addr):
#if KMP_OS_LINUX
# if KMP_ARCH_ARM || KMP_ARCH_AARCH64
.section .note.GNU-stack,"",%progbits
-# else
+# elif !KMP_ARCH_WASM
.section .note.GNU-stack,"", at progbits
# endif
#endif
+
+#if KMP_ARCH_WASM
+.data
+.global .gomp_critical_user_
+.global .gomp_critical_user_.var
+.global .gomp_critical_user_.reduction.var
+.global __kmp_unnamed_critical_addr
+.gomp_critical_user_:
+.zero 4
+.size .gomp_critical_user_, 4
+.gomp_critical_user_.var:
+.zero 4
+.size .gomp_critical_user_.var, 4
+.gomp_critical_user_.reduction.var:
+.zero 4
+.size .gomp_critical_user_.reduction.var, 4
+__kmp_unnamed_critical_addr:
+ .4byte .gomp_critical_user_
+ .size __kmp_unnamed_critical_addr, 4
+#endif
diff --git a/openmp/runtime/src/z_Linux_util.cpp b/openmp/runtime/src/z_Linux_util.cpp
index fdce932fd6d6bd..c2df8895e88753 100644
--- a/openmp/runtime/src/z_Linux_util.cpp
+++ b/openmp/runtime/src/z_Linux_util.cpp
@@ -277,7 +277,7 @@ int __kmp_futex_determine_capable() {
#endif // KMP_USE_FUTEX
-#if (KMP_ARCH_X86 || KMP_ARCH_X86_64) && (!KMP_ASM_INTRINS)
+#if (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_WASM) && (!KMP_ASM_INTRINS)
/* Only 32-bit "add-exchange" instruction on IA-32 architecture causes us to
use compare_and_store for these routines */
@@ -337,7 +337,7 @@ kmp_uint32 __kmp_test_then_and32(volatile kmp_uint32 *p, kmp_uint32 d) {
return old_value;
}
-#if KMP_ARCH_X86
+#if KMP_ARCH_X86 || KMP_ARCH_WASM
kmp_int8 __kmp_test_then_add8(volatile kmp_int8 *p, kmp_int8 d) {
kmp_int8 old_value, new_value;
@@ -985,7 +985,11 @@ void __kmp_create_monitor(kmp_info_t *th) {
#endif // KMP_USE_MONITOR
void __kmp_exit_thread(int exit_status) {
+#if KMP_OS_WASI
+// TODO: the wasm32-wasi-threads target does not yet support pthread_exit.
+#else
pthread_exit((void *)(intptr_t)exit_status);
+#endif
} // __kmp_exit_thread
#if KMP_USE_MONITOR
@@ -1330,9 +1334,11 @@ static void __kmp_atfork_child(void) {
void __kmp_register_atfork(void) {
if (__kmp_need_register_atfork) {
+#if !KMP_OS_WASI
int status = pthread_atfork(__kmp_atfork_prepare, __kmp_atfork_parent,
__kmp_atfork_child);
KMP_CHECK_SYSFAIL("pthread_atfork", status);
+#endif
__kmp_need_register_atfork = FALSE;
}
}
@@ -1774,6 +1780,7 @@ int __kmp_read_system_info(struct kmp_sys_info *info) {
status = getrusage(RUSAGE_SELF, &r_usage);
KMP_CHECK_SYSFAIL_ERRNO("getrusage", status);
+#if !KMP_OS_WASI
// The maximum resident set size utilized (in kilobytes)
info->maxrss = r_usage.ru_maxrss;
// The number of page faults serviced without any I/O
@@ -1790,6 +1797,7 @@ int __kmp_read_system_info(struct kmp_sys_info *info) {
info->nvcsw = r_usage.ru_nvcsw;
// The number of times a context switch was forced
info->nivcsw = r_usage.ru_nivcsw;
+#endif
return (status != 0);
}
@@ -1824,7 +1832,7 @@ static int __kmp_get_xproc(void) {
__kmp_type_convert(sysconf(_SC_NPROCESSORS_CONF), &(r));
#elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_OPENBSD || \
- KMP_OS_HURD || KMP_OS_SOLARIS
+ KMP_OS_HURD || KMP_OS_SOLARIS || KMP_OS_WASI
__kmp_type_convert(sysconf(_SC_NPROCESSORS_ONLN), &(r));
@@ -2200,6 +2208,8 @@ int __kmp_is_address_mapped(void *addr) {
}
kiv.kve_start += 1;
}
+#elif KMP_OS_WASI
+ found = (int)addr < (__builtin_wasm_memory_size(0) * PAGESIZE);
#elif KMP_OS_DRAGONFLY || KMP_OS_SOLARIS
// FIXME(DragonFly, Solaris): Implement this
>From aa207674f9e6caf5bc29c1b4925183a398382d6f Mon Sep 17 00:00:00 2001
From: Walter Erquinigo <a20012251 at gmail.com>
Date: Thu, 14 Dec 2023 15:04:35 -0500
Subject: [PATCH 03/16] [lldb-dap] Implement command directives (#74808)
This adds support for optionally prefixing any command with `?` and/or
`!`.
- `?` prevents the output of a commands to be printed to the console
unless it fails.
- `!` aborts the dap if the command fails.
They come in handy when programmatically running commands on behalf of
the user without wanting them to know unless they fail, or when a
critical setup is required as part of launchCommands and it's better to
abort on failures than to silently skip.
---
.../test/tools/lldb-dap/lldbdap_testcase.py | 7 ++
.../test/API/tools/lldb-dap/commands/Makefile | 3 +
.../lldb-dap/commands/TestDAP_commands.py | 80 +++++++++++++++++++
.../test/API/tools/lldb-dap/commands/main.cpp | 1 +
lldb/tools/lldb-dap/DAP.cpp | 50 ++++++++++--
lldb/tools/lldb-dap/DAP.h | 17 ++--
lldb/tools/lldb-dap/LLDBUtils.cpp | 77 +++++++++++++-----
lldb/tools/lldb-dap/LLDBUtils.h | 37 ++++++++-
lldb/tools/lldb-dap/lldb-dap.cpp | 51 +++++++++---
lldb/tools/lldb-dap/package.json | 24 +++---
10 files changed, 287 insertions(+), 60 deletions(-)
create mode 100644 lldb/test/API/tools/lldb-dap/commands/Makefile
create mode 100644 lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py
create mode 100644 lldb/test/API/tools/lldb-dap/commands/main.cpp
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
index 4ccd6014e54be6..7436b9900e98b0 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
@@ -291,6 +291,7 @@ def attach(
postRunCommands=None,
sourceMap=None,
sourceInitFile=False,
+ expectFailure=False,
):
"""Build the default Makefile target, create the DAP debug adaptor,
and attach to the process.
@@ -322,6 +323,8 @@ def cleanup():
postRunCommands=postRunCommands,
sourceMap=sourceMap,
)
+ if expectFailure:
+ return response
if not (response and response["success"]):
self.assertTrue(
response["success"], "attach failed (%s)" % (response["message"])
@@ -437,6 +440,8 @@ def build_and_launch(
commandEscapePrefix=None,
customFrameFormat=None,
customThreadFormat=None,
+ launchCommands=None,
+ expectFailure=False,
):
"""Build the default Makefile target, create the DAP debug adaptor,
and launch the process.
@@ -470,4 +475,6 @@ def build_and_launch(
commandEscapePrefix=commandEscapePrefix,
customFrameFormat=customFrameFormat,
customThreadFormat=customThreadFormat,
+ launchCommands=launchCommands,
+ expectFailure=expectFailure,
)
diff --git a/lldb/test/API/tools/lldb-dap/commands/Makefile b/lldb/test/API/tools/lldb-dap/commands/Makefile
new file mode 100644
index 00000000000000..99998b20bcb050
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/commands/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py b/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py
new file mode 100644
index 00000000000000..226b9385fe719a
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py
@@ -0,0 +1,80 @@
+import os
+
+import dap_server
+import lldbdap_testcase
+from lldbsuite.test import lldbtest, lldbutil
+from lldbsuite.test.decorators import *
+
+
+class TestDAP_commands(lldbdap_testcase.DAPTestCaseBase):
+ def test_command_directive_quiet_on_success(self):
+ program = self.getBuildArtifact("a.out")
+ command_quiet = (
+ "settings set target.show-hex-variable-values-with-leading-zeroes false"
+ )
+ command_not_quiet = (
+ "settings set target.show-hex-variable-values-with-leading-zeroes true"
+ )
+ self.build_and_launch(
+ program,
+ initCommands=["?" + command_quiet, command_not_quiet],
+ terminateCommands=["?" + command_quiet, command_not_quiet],
+ stopCommands=["?" + command_quiet, command_not_quiet],
+ exitCommands=["?" + command_quiet, command_not_quiet],
+ )
+ full_output = self.collect_console(duration=1.0)
+ self.assertNotIn(command_quiet, full_output)
+ self.assertIn(command_not_quiet, full_output)
+
+ def do_test_abort_on_error(
+ self,
+ use_init_commands=False,
+ use_launch_commands=False,
+ use_pre_run_commands=False,
+ use_post_run_commands=False,
+ ):
+ program = self.getBuildArtifact("a.out")
+ command_quiet = (
+ "settings set target.show-hex-variable-values-with-leading-zeroes false"
+ )
+ command_abort_on_error = "settings set foo bar"
+ commands = ["?!" + command_quiet, "!" + command_abort_on_error]
+ self.build_and_launch(
+ program,
+ initCommands=commands if use_init_commands else None,
+ launchCommands=commands if use_launch_commands else None,
+ preRunCommands=commands if use_pre_run_commands else None,
+ postRunCommands=commands if use_post_run_commands else None,
+ expectFailure=True,
+ )
+ full_output = self.collect_console(duration=1.0)
+ self.assertNotIn(command_quiet, full_output)
+ self.assertIn(command_abort_on_error, full_output)
+
+ def test_command_directive_abort_on_error_init_commands(self):
+ self.do_test_abort_on_error(use_init_commands=True)
+
+ def test_command_directive_abort_on_error_launch_commands(self):
+ self.do_test_abort_on_error(use_launch_commands=True)
+
+ def test_command_directive_abort_on_error_pre_run_commands(self):
+ self.do_test_abort_on_error(use_pre_run_commands=True)
+
+ def test_command_directive_abort_on_error_post_run_commands(self):
+ self.do_test_abort_on_error(use_post_run_commands=True)
+
+ def test_command_directive_abort_on_error_attach_commands(self):
+ program = self.getBuildArtifact("a.out")
+ command_quiet = (
+ "settings set target.show-hex-variable-values-with-leading-zeroes false"
+ )
+ command_abort_on_error = "settings set foo bar"
+ self.build_and_create_debug_adaptor()
+ self.attach(
+ program,
+ attachCommands=["?!" + command_quiet, "!" + command_abort_on_error],
+ expectFailure=True,
+ )
+ full_output = self.collect_console(duration=1.0)
+ self.assertNotIn(command_quiet, full_output)
+ self.assertIn(command_abort_on_error, full_output)
diff --git a/lldb/test/API/tools/lldb-dap/commands/main.cpp b/lldb/test/API/tools/lldb-dap/commands/main.cpp
new file mode 100644
index 00000000000000..76e8197013aabc
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/commands/main.cpp
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 49266209739765..4b72c13f9215a8 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -434,20 +434,54 @@ ExpressionContext DAP::DetectExpressionContext(lldb::SBFrame &frame,
return ExpressionContext::Variable;
}
-void DAP::RunLLDBCommands(llvm::StringRef prefix,
- const std::vector<std::string> &commands) {
- SendOutput(OutputType::Console,
- llvm::StringRef(::RunLLDBCommands(prefix, commands)));
+bool DAP::RunLLDBCommands(llvm::StringRef prefix,
+ llvm::ArrayRef<std::string> commands) {
+ bool required_command_failed = false;
+ std::string output =
+ ::RunLLDBCommands(prefix, commands, required_command_failed);
+ SendOutput(OutputType::Console, output);
+ return !required_command_failed;
+}
+
+static llvm::Error createRunLLDBCommandsErrorMessage(llvm::StringRef category) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ llvm::formatv(
+ "Failed to run {0} commands. See the Debug Console for more details.",
+ category)
+ .str()
+ .c_str());
+}
+
+llvm::Error
+DAP::RunAttachCommands(llvm::ArrayRef<std::string> attach_commands) {
+ if (!RunLLDBCommands("Running attachCommands:", attach_commands))
+ return createRunLLDBCommandsErrorMessage("attach");
+ return llvm::Error::success();
}
-void DAP::RunInitCommands() {
- RunLLDBCommands("Running initCommands:", init_commands);
+llvm::Error
+DAP::RunLaunchCommands(llvm::ArrayRef<std::string> launch_commands) {
+ if (!RunLLDBCommands("Running launchCommands:", launch_commands))
+ return createRunLLDBCommandsErrorMessage("launch");
+ return llvm::Error::success();
}
-void DAP::RunPreRunCommands() {
- RunLLDBCommands("Running preRunCommands:", pre_run_commands);
+llvm::Error DAP::RunInitCommands() {
+ if (!RunLLDBCommands("Running initCommands:", init_commands))
+ return createRunLLDBCommandsErrorMessage("initCommands");
+ return llvm::Error::success();
}
+llvm::Error DAP::RunPreRunCommands() {
+ if (!RunLLDBCommands("Running preRunCommands:", pre_run_commands))
+ return createRunLLDBCommandsErrorMessage("preRunCommands");
+ return llvm::Error::success();
+}
+
+void DAP::RunPostRunCommands() {
+ RunLLDBCommands("Running postRunCommands:", post_run_commands);
+}
void DAP::RunStopCommands() {
RunLLDBCommands("Running stopCommands:", stop_commands);
}
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index c7d56a06bfa1fd..20817194de2d8d 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -158,6 +158,7 @@ struct DAP {
std::vector<ExceptionBreakpoint> exception_breakpoints;
std::vector<std::string> init_commands;
std::vector<std::string> pre_run_commands;
+ std::vector<std::string> post_run_commands;
std::vector<std::string> exit_commands;
std::vector<std::string> stop_commands;
std::vector<std::string> terminate_commands;
@@ -227,11 +228,17 @@ struct DAP {
ExpressionContext DetectExpressionContext(lldb::SBFrame &frame,
std::string &text);
- void RunLLDBCommands(llvm::StringRef prefix,
- const std::vector<std::string> &commands);
-
- void RunInitCommands();
- void RunPreRunCommands();
+ /// \return
+ /// \b false if a fatal error was found while executing these commands,
+ /// according to the rules of \a LLDBUtils::RunLLDBCommands.
+ bool RunLLDBCommands(llvm::StringRef prefix,
+ llvm::ArrayRef<std::string> commands);
+
+ llvm::Error RunAttachCommands(llvm::ArrayRef<std::string> attach_commands);
+ llvm::Error RunLaunchCommands(llvm::ArrayRef<std::string> launch_commands);
+ llvm::Error RunInitCommands();
+ llvm::Error RunPreRunCommands();
+ void RunPostRunCommands();
void RunStopCommands();
void RunExitCommands();
void RunTerminateCommands();
diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp
index 955c11f636895b..35b7a986a8964b 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.cpp
+++ b/lldb/tools/lldb-dap/LLDBUtils.cpp
@@ -11,40 +11,81 @@
namespace lldb_dap {
-void RunLLDBCommands(llvm::StringRef prefix,
+bool RunLLDBCommands(llvm::StringRef prefix,
const llvm::ArrayRef<std::string> &commands,
- llvm::raw_ostream &strm) {
+ llvm::raw_ostream &strm, bool parse_command_directives) {
if (commands.empty())
- return;
+ return true;
+
+ bool did_print_prefix = false;
+
lldb::SBCommandInterpreter interp = g_dap.debugger.GetCommandInterpreter();
- if (!prefix.empty())
- strm << prefix << "\n";
- for (const auto &command : commands) {
+ for (llvm::StringRef command : commands) {
lldb::SBCommandReturnObject result;
- strm << "(lldb) " << command << "\n";
- interp.HandleCommand(command.c_str(), result);
- auto output_len = result.GetOutputSize();
- if (output_len) {
- const char *output = result.GetOutput();
- strm << output;
+ bool quiet_on_success = false;
+ bool check_error = false;
+
+ while (parse_command_directives) {
+ if (command.starts_with("?")) {
+ command = command.drop_front();
+ quiet_on_success = true;
+ } else if (command.starts_with("!")) {
+ command = command.drop_front();
+ check_error = true;
+ } else {
+ break;
+ }
}
- auto error_len = result.GetErrorSize();
- if (error_len) {
- const char *error = result.GetError();
- strm << error;
+
+ interp.HandleCommand(command.str().c_str(), result);
+ const bool got_error = !result.Succeeded();
+ // The if statement below is assuming we always print out `!` prefixed
+ // lines. The only time we don't print is when we have `quiet_on_success ==
+ // true` and we don't have an error.
+ if (quiet_on_success ? got_error : true) {
+ if (!did_print_prefix && !prefix.empty()) {
+ strm << prefix << "\n";
+ did_print_prefix = true;
+ }
+ strm << "(lldb) " << command << "\n";
+ auto output_len = result.GetOutputSize();
+ if (output_len) {
+ const char *output = result.GetOutput();
+ strm << output;
+ }
+ auto error_len = result.GetErrorSize();
+ if (error_len) {
+ const char *error = result.GetError();
+ strm << error;
+ }
}
+ if (check_error && got_error)
+ return false; // Stop running commands.
}
+ return true;
}
std::string RunLLDBCommands(llvm::StringRef prefix,
- const llvm::ArrayRef<std::string> &commands) {
+ const llvm::ArrayRef<std::string> &commands,
+ bool &required_command_failed,
+ bool parse_command_directives) {
+ required_command_failed = false;
std::string s;
llvm::raw_string_ostream strm(s);
- RunLLDBCommands(prefix, commands, strm);
+ required_command_failed =
+ !RunLLDBCommands(prefix, commands, strm, parse_command_directives);
strm.flush();
return s;
}
+std::string
+RunLLDBCommandsVerbatim(llvm::StringRef prefix,
+ const llvm::ArrayRef<std::string> &commands) {
+ bool required_command_failed = false;
+ return RunLLDBCommands(prefix, commands, required_command_failed,
+ /*parse_command_directives=*/false);
+}
+
bool ThreadHasStopReason(lldb::SBThread &thread) {
switch (thread.GetStopReason()) {
case lldb::eStopReasonTrace:
diff --git a/lldb/tools/lldb-dap/LLDBUtils.h b/lldb/tools/lldb-dap/LLDBUtils.h
index a99f798835370d..ee701da2230fe0 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.h
+++ b/lldb/tools/lldb-dap/LLDBUtils.h
@@ -23,6 +23,12 @@ namespace lldb_dap {
/// All output from every command, including the prompt + the command
/// is placed into the "strm" argument.
///
+/// Each individual command can be prefixed with \b ! and/or \b ? in no
+/// particular order. If \b ? is provided, then the output of that command is
+/// only emitted if it fails, and if \b ! is provided, then the output is
+/// emitted regardless, and \b false is returned without executing the
+/// remaining commands.
+///
/// \param[in] prefix
/// A string that will be printed into \a strm prior to emitting
/// the prompt + command and command output. Can be NULL.
@@ -33,9 +39,17 @@ namespace lldb_dap {
/// \param[in] strm
/// The stream that will receive the prefix, prompt + command and
/// all command output.
-void RunLLDBCommands(llvm::StringRef prefix,
+///
+/// \param[in] parse_command_directives
+/// If \b false, then command prefixes like \b ! or \b ? are not parsed and
+/// each command is executed verbatim.
+///
+/// \return
+/// \b true, unless a command prefixed with \b ! fails and parsing of
+/// command directives is enabled.
+bool RunLLDBCommands(llvm::StringRef prefix,
const llvm::ArrayRef<std::string> &commands,
- llvm::raw_ostream &strm);
+ llvm::raw_ostream &strm, bool parse_command_directives);
/// Run a list of LLDB commands in the LLDB command interpreter.
///
@@ -49,11 +63,26 @@ void RunLLDBCommands(llvm::StringRef prefix,
/// \param[in] commands
/// An array of LLDB commands to execute.
///
+/// \param[out] required_command_failed
+/// If parsing of command directives is enabled, this variable is set to
+/// \b true if one of the commands prefixed with \b ! fails.
+///
+/// \param[in] parse_command_directives
+/// If \b false, then command prefixes like \b ! or \b ? are not parsed and
+/// each command is executed verbatim.
+///
/// \return
/// A std::string that contains the prefix and all commands and
-/// command output
+/// command output.
std::string RunLLDBCommands(llvm::StringRef prefix,
- const llvm::ArrayRef<std::string> &commands);
+ const llvm::ArrayRef<std::string> &commands,
+ bool &required_command_failed,
+ bool parse_command_directives = true);
+
+/// Similar to the method above, but without parsing command directives.
+std::string
+RunLLDBCommandsVerbatim(llvm::StringRef prefix,
+ const llvm::ArrayRef<std::string> &commands);
/// Check if a thread has a stop reason.
///
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index d6b593eba93eca..d36e9b4d1b0982 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -644,8 +644,7 @@ void request_attach(const llvm::json::Object &request) {
const uint64_t timeout_seconds = GetUnsigned(arguments, "timeout", 30);
g_dap.stop_at_entry =
core_file.empty() ? GetBoolean(arguments, "stopOnEntry", false) : true;
- std::vector<std::string> postRunCommands =
- GetStrings(arguments, "postRunCommands");
+ g_dap.post_run_commands = GetStrings(arguments, "postRunCommands");
const llvm::StringRef debuggerRoot = GetString(arguments, "debuggerRoot");
g_dap.enable_auto_variable_summaries =
GetBoolean(arguments, "enableAutoVariableSummaries", false);
@@ -664,7 +663,12 @@ void request_attach(const llvm::json::Object &request) {
llvm::sys::fs::set_current_path(debuggerRoot);
// Run any initialize LLDB commands the user specified in the launch.json
- g_dap.RunInitCommands();
+ if (llvm::Error err = g_dap.RunInitCommands()) {
+ response["success"] = false;
+ EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
SetSourceMapFromArguments(*arguments);
@@ -678,7 +682,12 @@ void request_attach(const llvm::json::Object &request) {
}
// Run any pre run LLDB commands the user specified in the launch.json
- g_dap.RunPreRunCommands();
+ if (llvm::Error err = g_dap.RunPreRunCommands()) {
+ response["success"] = false;
+ EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
if (pid == LLDB_INVALID_PROCESS_ID && wait_for) {
char attach_msg[256];
@@ -703,7 +712,12 @@ void request_attach(const llvm::json::Object &request) {
// We have "attachCommands" that are a set of commands that are expected
// to execute the commands after which a process should be created. If there
// is no valid process after running these commands, we have failed.
- g_dap.RunLLDBCommands("Running attachCommands:", attachCommands);
+ if (llvm::Error err = g_dap.RunAttachCommands(attachCommands)) {
+ response["success"] = false;
+ EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
// The custom commands might have created a new target so we should use the
// selected target after these commands are run.
g_dap.target = g_dap.debugger.GetSelectedTarget();
@@ -727,7 +741,7 @@ void request_attach(const llvm::json::Object &request) {
response["success"] = llvm::json::Value(false);
EmplaceSafeString(response, "message", std::string(error.GetCString()));
} else {
- g_dap.RunLLDBCommands("Running postRunCommands:", postRunCommands);
+ g_dap.RunPostRunCommands();
}
g_dap.SendJSON(llvm::json::Value(std::move(response)));
@@ -1270,7 +1284,8 @@ void request_evaluate(const llvm::json::Object &request) {
if (frame.IsValid()) {
g_dap.focus_tid = frame.GetThread().GetThreadID();
}
- auto result = RunLLDBCommands(llvm::StringRef(), {std::string(expression)});
+ auto result =
+ RunLLDBCommandsVerbatim(llvm::StringRef(), {std::string(expression)});
EmplaceSafeString(body, "result", result);
body.try_emplace("variablesReference", (int64_t)0);
} else {
@@ -1740,7 +1755,8 @@ lldb::SBError LaunchProcess(const llvm::json::Object &request) {
// Set the launch info so that run commands can access the configured
// launch details.
g_dap.target.SetLaunchInfo(launch_info);
- g_dap.RunLLDBCommands("Running launchCommands:", launchCommands);
+ if (llvm::Error err = g_dap.RunLaunchCommands(launchCommands))
+ error.SetErrorString(llvm::toString(std::move(err)).c_str());
// The custom commands might have created a new target so we should use the
// selected target after these commands are run.
g_dap.target = g_dap.debugger.GetSelectedTarget();
@@ -1797,8 +1813,7 @@ void request_launch(const llvm::json::Object &request) {
g_dap.stop_commands = GetStrings(arguments, "stopCommands");
g_dap.exit_commands = GetStrings(arguments, "exitCommands");
g_dap.terminate_commands = GetStrings(arguments, "terminateCommands");
- std::vector<std::string> postRunCommands =
- GetStrings(arguments, "postRunCommands");
+ g_dap.post_run_commands = GetStrings(arguments, "postRunCommands");
g_dap.stop_at_entry = GetBoolean(arguments, "stopOnEntry", false);
const llvm::StringRef debuggerRoot = GetString(arguments, "debuggerRoot");
g_dap.enable_auto_variable_summaries =
@@ -1820,7 +1835,12 @@ void request_launch(const llvm::json::Object &request) {
// Run any initialize LLDB commands the user specified in the launch.json.
// This is run before target is created, so commands can't do anything with
// the targets - preRunCommands are run with the target.
- g_dap.RunInitCommands();
+ if (llvm::Error err = g_dap.RunInitCommands()) {
+ response["success"] = false;
+ EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
SetSourceMapFromArguments(*arguments);
@@ -1834,7 +1854,12 @@ void request_launch(const llvm::json::Object &request) {
}
// Run any pre run LLDB commands the user specified in the launch.json
- g_dap.RunPreRunCommands();
+ if (llvm::Error err = g_dap.RunPreRunCommands()) {
+ response["success"] = false;
+ EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
status = LaunchProcess(request);
@@ -1842,7 +1867,7 @@ void request_launch(const llvm::json::Object &request) {
response["success"] = llvm::json::Value(false);
EmplaceSafeString(response, "message", std::string(status.GetCString()));
} else {
- g_dap.RunLLDBCommands("Running postRunCommands:", postRunCommands);
+ g_dap.RunPostRunCommands();
}
g_dap.SendJSON(llvm::json::Value(std::move(response)));
diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json
index ebb1103d695e17..68cdade4439924 100644
--- a/lldb/tools/lldb-dap/package.json
+++ b/lldb/tools/lldb-dap/package.json
@@ -204,32 +204,32 @@
},
"initCommands": {
"type": "array",
- "description": "Initialization commands executed upon debugger startup.",
+ "description": "Initialization commands executed upon debugger startup. Each command can be prefixed with `!` and/or `?` in no particular order. If `?` is provided, then the output of the command is only emitted if it fails, and if `!` is provided, the debug session terminates if the command fails, in which case the output of the command is emitted regardless.",
"default": []
},
"preRunCommands": {
"type": "array",
- "description": "Commands executed just before the program is launched.",
+ "description": "Commands executed just before the program is launched. Each command can be prefixed with `!` and/or `?` in no particular order. If `?` is provided, then the output of the command is only emitted if it fails, and if `!` is provided, the debug session terminates if the command fails, in which case the output of the command is emitted regardless.",
"default": []
},
"postRunCommands": {
"type": "array",
- "description": "Commands executed just as soon as the program is successfully launched when it's in a stopped state prior to any automatic continuation.",
+ "description": "Commands executed just as soon as the program is successfully launched when it's in a stopped state prior to any automatic continuation. If a command is prefixed with `?`, then its output is only emitted if it fails. Unlike `initCommands` or `launchCommands`, the `!` prefix is ignored.",
"default": []
},
"launchCommands": {
"type": "array",
- "description": "Custom commands that are executed instead of launching a process. A target will be created with the launch arguments prior to executing these commands. The commands may optionally create a new target and must perform a launch. A valid process must exist after these commands complete or the \"launch\" will fail. Launch the process with \"process launch -s\" to make the process to at the entry point since lldb-dap will auto resume if necessary.",
+ "description": "Custom commands that are executed instead of launching a process. A target will be created with the launch arguments prior to executing these commands. The commands may optionally create a new target and must perform a launch. A valid process must exist after these commands complete or the \"launch\" will fail. Launch the process with \"process launch -s\" to make the process to at the entry point since lldb-dap will auto resume if necessary. Each command can be prefixed with `!` and/or `?` in no particular order. If `?` is provided, then the output of the command is only emitted if it fails, and if `!` is provided, the debug session terminates if the command fails, in which case the output of the command is emitted regardless.",
"default": []
},
"stopCommands": {
"type": "array",
- "description": "Commands executed each time the program stops.",
+ "description": "Commands executed each time the program stops. If a command is prefixed with `?`, then its output is only emitted if it fails. Unlike `initCommands` or `launchCommands`, the `!` prefix is ignored.",
"default": []
},
"exitCommands": {
"type": "array",
- "description": "Commands executed at the end of debugging session.",
+ "description": "Commands executed at the end of debugging session. If a command is prefixed with `?`, then its output is only emitted if it fails. Unlike `initCommands` or `launchCommands`, the `!` prefix is ignored.",
"default": []
},
"runInTerminal": {
@@ -309,32 +309,32 @@
},
"attachCommands": {
"type": "array",
- "description": "Custom commands that are executed instead of attaching to a process ID or to a process by name. These commands may optionally create a new target and must perform an attach. A valid process must exist after these commands complete or the \"attach\" will fail.",
+ "description": "Custom commands that are executed instead of attaching to a process ID or to a process by name. These commands may optionally create a new target and must perform an attach. A valid process must exist after these commands complete or the \"attach\" will fail. Each command can be prefixed with `!` and/or `?` in no particular order. If `?` is provided, then the output of the command is only emitted if it fails, and if `!` is provided, the debug session terminates if the command fails, in which case the output of the command is emitted regardless.",
"default": []
},
"initCommands": {
"type": "array",
- "description": "Initialization commands executed upon debugger startup.",
+ "description": "Initialization commands executed upon debugger startup. Each command can be prefixed with `!` and/or `?` in no particular order. If `?` is provided, then the output of the command is only emitted if it fails, and if `!` is provided, the debug session terminates if the command fails, in which case the output of the command is emitted regardless.",
"default": []
},
"preRunCommands": {
"type": "array",
- "description": "Commands executed just before the program is attached to.",
+ "description": "Commands executed just before the program is attached to. Each command can be prefixed with `!` and/or `?` in no particular order. If `?` is provided, then the output of the command is only emitted if it fails, and if `!` is provided, the debug session terminates if the command fails, in which case the output of the command is emitted regardless.",
"default": []
},
"postRunCommands": {
"type": "array",
- "description": "Commands executed just as soon as the program is successfully attached when it's in a stopped state prior to any automatic continuation.",
+ "description": "Commands executed just as soon as the program is successfully attached when it's in a stopped state prior to any automatic continuation. Each command can be prefixed with `!` and/or `?` in no particular order. If `?` is provided, then the output of the command is only emitted if it fails, and if `!` is provided, the debug session terminates if the command fails, in which case the output of the command is emitted regardless.",
"default": []
},
"stopCommands": {
"type": "array",
- "description": "Commands executed each time the program stops.",
+ "description": "Commands executed each time the program stops. If a command is prefixed with `?`, then its output is only emitted if it fails. Unlike `initCommands` or `attachCommands`, the `!` prefix is ignored.",
"default": []
},
"exitCommands": {
"type": "array",
- "description": "Commands executed at the end of debugging session.",
+ "description": "Commands executed at the end of debugging session. If a command is prefixed with `?`, then its output is only emitted if it fails. Unlike `initCommands` or `attachCommands`, the `!` prefix is ignored.",
"default": []
},
"coreFile": {
>From 46fe85446d7181c8c5e2ec5fe128ac33ba502ccc Mon Sep 17 00:00:00 2001
From: Aiden Grossman <agrossman154 at yahoo.com>
Date: Thu, 14 Dec 2023 12:07:17 -0800
Subject: [PATCH 04/16] [Docs][llvm-exegesis] Add documentation on recently
added options (#75408)
This patch adds information on the new LLVM-EXEGESIS-SNIPPET-ADDRESS
annotation and on the --benchmark-repeat-count flag.
---
llvm/docs/CommandGuide/llvm-exegesis.rst | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/llvm/docs/CommandGuide/llvm-exegesis.rst b/llvm/docs/CommandGuide/llvm-exegesis.rst
index 874bae82a1029a..bc37d52d147668 100644
--- a/llvm/docs/CommandGuide/llvm-exegesis.rst
+++ b/llvm/docs/CommandGuide/llvm-exegesis.rst
@@ -81,6 +81,14 @@ properly.
definition should start at. Note that a single memory definition can be
mapped multiple times. Using this annotation requires the subprocess
execution mode.
+* `LLVM-EXEGESIS-SNIPPET-ADDRESS <address>` - This annotation allows for
+ setting the address where the beginning of the snippet to be executed will
+ be mapped in at. The address is given in hexadecimal. Note that the snippet
+ also includes setup code, so the instruction exactly at the specified
+ address will not be the first instruction in the snippet. Using this
+ annotation requires the subprocess execution mode. This is useful in
+ cases where the memory accessed by the snippet depends on the location
+ of the snippet, like RIP-relative addressing.
EXAMPLE 1: benchmarking instructions
------------------------------------
@@ -425,6 +433,12 @@ OPTIONS
features such as memory annotations but is currently restricted to X86-64
on Linux.
+.. option:: --benchmark-repeat-count=<repeat-count>
+
+ This option enables specifying the number of times to repeat the measurement
+ when performing latency measurements. By default, llvm-exegesis will repeat
+ a latency measurement enough times to balance run-time and noise reduction.
+
EXIT STATUS
-----------
>From 3194928c3cfa6623c5de78ae7ab2ab7ab0cf0232 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <agrossman154 at yahoo.com>
Date: Thu, 14 Dec 2023 12:07:46 -0800
Subject: [PATCH 05/16] [llvm-exegesis] Refactor MMAP platform-specific
preprocessor directives (#75422)
This patch refactors the MMAP platform-specific preprocessor directives
in llvm-exegesis to a single file instead of having duplicate code split
across multiple files. These originally got introduced to get buildbots
green again due to platform specific failures.
---
.../llvm-exegesis/lib/BenchmarkRunner.cpp | 8 +----
llvm/tools/llvm-exegesis/lib/MmapUtils.h | 32 +++++++++++++++++++
llvm/tools/llvm-exegesis/lib/X86/Target.cpp | 16 +---------
.../tools/llvm-exegesis/X86/TargetTest.cpp | 16 +---------
4 files changed, 35 insertions(+), 37 deletions(-)
create mode 100644 llvm/tools/llvm-exegesis/lib/MmapUtils.h
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 7bb0218ed53386..41960c23a10d19 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -13,6 +13,7 @@
#include "BenchmarkRunner.h"
#include "Error.h"
#include "MCInstrDescView.h"
+#include "MmapUtils.h"
#include "PerfHelper.h"
#include "SubprocessMemory.h"
#include "Target.h"
@@ -45,13 +46,6 @@
#define GLIBC_INITS_RSEQ
#endif
#endif
-
-// Before kernel 4.17, Linux did not support MAP_FIXED_NOREPLACE, so if it is
-// not available, simplfy define it as MAP_FIXED which performs the same
-// function but does not guarantee existing mappings won't get clobbered.
-#ifndef MAP_FIXED_NOREPLACE
-#define MAP_FIXED_NOREPLACE MAP_FIXED
-#endif
#endif // __linux__
namespace llvm {
diff --git a/llvm/tools/llvm-exegesis/lib/MmapUtils.h b/llvm/tools/llvm-exegesis/lib/MmapUtils.h
new file mode 100644
index 00000000000000..31e8778ce8d40a
--- /dev/null
+++ b/llvm/tools/llvm-exegesis/lib/MmapUtils.h
@@ -0,0 +1,32 @@
+//===-- MmapUtils.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains compatibility-related preprocessor directives related
+// to mmap.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef __linux__
+#include <sys/mman.h>
+#include <sys/syscall.h>
+
+// Before kernel 4.17, Linux did not support MAP_FIXED_NOREPLACE, so if it is
+// not available, simplfy define it as MAP_FIXED which performs the same
+// function but does not guarantee existing mappings won't get clobbered.
+#ifndef MAP_FIXED_NOREPLACE
+#define MAP_FIXED_NOREPLACE MAP_FIXED
+#endif
+
+// Some 32-bit architectures don't have mmap and define mmap2 instead. The only
+// difference between the two syscalls is that mmap2's offset parameter is in
+// terms 4096 byte offsets rather than individual bytes, so for our purposes
+// they are effectively the same as all ofsets here are set to 0.
+#if defined(SYS_mmap2) && !defined(SYS_mmap)
+#define SYS_mmap SYS_mmap2
+#endif
+#endif // __linux__
diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
index 73c0f5430d80d1..2c2d1adb0fcf08 100644
--- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
@@ -8,6 +8,7 @@
#include "../Target.h"
#include "../Error.h"
+#include "../MmapUtils.h"
#include "../ParallelSnippetGenerator.h"
#include "../SerialSnippetGenerator.h"
#include "../SnippetGenerator.h"
@@ -1080,21 +1081,6 @@ ExegesisX86Target::generateExitSyscall(unsigned ExitCode) const {
return ExitCallCode;
}
-// Before kernel 4.17, Linux did not support MAP_FIXED_NOREPLACE, so if it is
-// not available, simplfy define it as MAP_FIXED which performs the same
-// function but does not guarantee existing mappings won't get clobbered.
-#ifndef MAP_FIXED_NOREPLACE
-#define MAP_FIXED_NOREPLACE MAP_FIXED
-#endif
-
-// Some 32-bit architectures don't have mmap and define mmap2 instead. The only
-// difference between the two syscalls is that mmap2's offset parameter is in
-// terms 4096 byte offsets rather than individual bytes, so for our purposes
-// they are effectively the same as all ofsets here are set to 0.
-#if defined(SYS_mmap2) && !defined(SYS_mmap)
-#define SYS_mmap SYS_mmap2
-#endif
-
std::vector<MCInst>
ExegesisX86Target::generateMmap(intptr_t Address, size_t Length,
intptr_t FileDescriptorAddress) const {
diff --git a/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp
index ff0810e984dd78..e0427664d2c3cf 100644
--- a/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp
+++ b/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp
@@ -12,6 +12,7 @@
#include <memory>
#include "MCTargetDesc/X86MCTargetDesc.h"
+#include "MmapUtils.h"
#include "SubprocessMemory.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
@@ -625,21 +626,6 @@ TEST_F(X86Core2TargetTest, GenerateExitSyscallTest) {
OpcodeIs(X86::SYSCALL)));
}
-// Before kernel 4.17, Linux did not support MAP_FIXED_NOREPLACE, so if it is
-// not available, simplfy define it as MAP_FIXED which performs the same
-// function but does not guarantee existing mappings won't get clobbered.
-#ifndef MAP_FIXED_NOREPLACE
-#define MAP_FIXED_NOREPLACE MAP_FIXED
-#endif
-
-// Some 32-bit architectures don't have mmap and define mmap2 instead. The only
-// difference between the two syscalls is that mmap2's offset parameter is in
-// terms 4096 byte offsets rather than individual bytes, so for our purposes
-// they are effectively the same as all ofsets here are set to 0.
-#if defined(SYS_mmap2) && !defined(SYS_mmap)
-#define SYS_mmap SYS_mmap2
-#endif
-
TEST_F(X86Core2TargetTest, GenerateMmapTest) {
EXPECT_THAT(State.getExegesisTarget().generateMmap(0x1000, 4096, 0x2000),
ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 0x1000),
>From e75f37fd64a467cd8b24851062342079bef123f5 Mon Sep 17 00:00:00 2001
From: Natalie Chouinard <sudonatalie at google.com>
Date: Thu, 14 Dec 2023 15:17:11 -0500
Subject: [PATCH 06/16] [SPIR-V][NFC] Require asserts on 2 tests (#75087)
These tests currently fail on asserts, so adding a REQUIRES to make sure
they're skipped on builds with asserts disabled.
Follow-up from #74849
---
llvm/test/CodeGen/SPIRV/opencl/device_execution/execute_block.ll | 1 +
llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll | 1 +
2 files changed, 2 insertions(+)
diff --git a/llvm/test/CodeGen/SPIRV/opencl/device_execution/execute_block.ll b/llvm/test/CodeGen/SPIRV/opencl/device_execution/execute_block.ll
index b001ce09f5679c..1df72dc734dbd9 100644
--- a/llvm/test/CodeGen/SPIRV/opencl/device_execution/execute_block.ll
+++ b/llvm/test/CodeGen/SPIRV/opencl/device_execution/execute_block.ll
@@ -2,6 +2,7 @@
; TODO(#60133): Requires updates following opaque pointer migration.
; XFAIL: *
+; REQUIRES: asserts
; CHECK: %[[#bool:]] = OpTypeBool
; CHECK: %[[#true:]] = OpConstantTrue %[[#bool]]
diff --git a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll
index 75aa87f958d47b..a2ae808259a32a 100644
--- a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll
+++ b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll
@@ -22,6 +22,7 @@
; TODO(#60133): Requires updates following opaque pointer migration.
; XFAIL: *
+; REQUIRES: asserts
; CHECK-SPIRV-DAG: %[[#LEN2_ID:]] = OpConstant %[[#]] 2
; CHECK-SPIRV-DAG: %[[#LEN3_ID:]] = OpConstant %[[#]] 3
>From 15617d14f78bd20c96208501d950f0902cb03ffe Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Thu, 14 Dec 2023 12:28:50 -0800
Subject: [PATCH 07/16] Revert "Reland [X86] Respect code models more when
determining if a global reference can fit in 32 bits (#75386)"
This reverts commit ec92d74a0ef89b9dd46aee6ec8aca6bfd3c66a54.
Breaks some compiler-rt tests, e.g. https://lab.llvm.org/buildbot/#/builders/37/builds/28834
---
llvm/include/llvm/Target/TargetMachine.h | 2 +-
.../CodeGen/TargetLoweringObjectFileImpl.cpp | 4 +-
llvm/lib/Target/TargetMachine.cpp | 8 +-
llvm/lib/Target/X86/X86FastISel.cpp | 8 +-
llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 21 +-
llvm/lib/Target/X86/X86Subtarget.cpp | 16 +-
llvm/test/CodeGen/X86/code-model-elf.ll | 293 +++++++-----------
7 files changed, 143 insertions(+), 209 deletions(-)
diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h
index 4c29f25bedf419..4830ecbe1cd634 100644
--- a/llvm/include/llvm/Target/TargetMachine.h
+++ b/llvm/include/llvm/Target/TargetMachine.h
@@ -239,7 +239,7 @@ class TargetMachine {
void setCodeModel(CodeModel::Model CM) { CMModel = CM; }
void setLargeDataThreshold(uint64_t LDT) { LargeDataThreshold = LDT; }
- bool isLargeGlobalValue(const GlobalValue *GV) const;
+ bool isLargeGlobalObject(const GlobalObject *GO) const;
bool isPositionIndependent() const;
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 9a0dd92bb58e87..8e1a109e1ee1f0 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -649,7 +649,7 @@ getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind,
Name = ".rodata.cst";
Name += utostr(EntrySize);
} else {
- Name = getSectionPrefixForGlobal(Kind, TM.isLargeGlobalValue(GO));
+ Name = getSectionPrefixForGlobal(Kind, TM.isLargeGlobalObject(GO));
}
bool HasPrefix = false;
@@ -769,7 +769,7 @@ getGlobalObjectInfo(const GlobalObject *GO, const TargetMachine &TM) {
Group = C->getName();
IsComdat = C->getSelectionKind() == Comdat::Any;
}
- if (TM.isLargeGlobalValue(GO))
+ if (TM.isLargeGlobalObject(GO))
Flags |= ELF::SHF_X86_64_LARGE;
return {Group, IsComdat, Flags};
}
diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp
index 3f96bd37755e58..5428e14eca5f8d 100644
--- a/llvm/lib/Target/TargetMachine.cpp
+++ b/llvm/lib/Target/TargetMachine.cpp
@@ -39,16 +39,10 @@ TargetMachine::TargetMachine(const Target &T, StringRef DataLayoutString,
TargetMachine::~TargetMachine() = default;
-bool TargetMachine::isLargeGlobalValue(const GlobalValue *GVal) const {
+bool TargetMachine::isLargeGlobalObject(const GlobalObject *GO) const {
if (getTargetTriple().getArch() != Triple::x86_64)
return false;
- auto *GO = GVal->getAliaseeObject();
-
- // Be conservative if we can't find an underlying GlobalObject.
- if (!GO)
- return true;
-
auto *GV = dyn_cast<GlobalVariable>(GO);
// Functions/GlobalIFuncs are only large under the large code model.
diff --git a/llvm/lib/Target/X86/X86FastISel.cpp b/llvm/lib/Target/X86/X86FastISel.cpp
index 7f134fe1c72bda..425c52dbe7b104 100644
--- a/llvm/lib/Target/X86/X86FastISel.cpp
+++ b/llvm/lib/Target/X86/X86FastISel.cpp
@@ -716,8 +716,10 @@ bool X86FastISel::handleConstantAddresses(const Value *V, X86AddressMode &AM) {
return false;
// Can't handle large objects yet.
- if (TM.isLargeGlobalValue(GV))
- return false;
+ if (auto *GO = dyn_cast<GlobalObject>(GV)) {
+ if (TM.isLargeGlobalObject(GO))
+ return false;
+ }
// Can't handle TLS yet.
if (GV->isThreadLocal())
@@ -3847,7 +3849,7 @@ unsigned X86FastISel::X86MaterializeGV(const GlobalValue *GV, MVT VT) {
if (TM.getCodeModel() != CodeModel::Small &&
TM.getCodeModel() != CodeModel::Medium)
return 0;
- if (TM.isLargeGlobalValue(GV))
+ if (!isa<GlobalObject>(GV) || TM.isLargeGlobalObject(cast<GlobalObject>(GV)))
return 0;
// Materialize addresses with LEA/MOV instructions.
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index ce4fbfe88739df..545039b79f1616 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -2927,10 +2927,6 @@ bool X86DAGToDAGISel::selectAddr(SDNode *Parent, SDValue N, SDValue &Base,
}
bool X86DAGToDAGISel::selectMOV64Imm32(SDValue N, SDValue &Imm) {
- // Cannot use 32 bit constants to reference objects in kernel code model.
- if (TM.getCodeModel() == CodeModel::Kernel)
- return false;
-
// In static codegen with small code model, we can get the address of a label
// into a register with 'movl'
if (N->getOpcode() != X86ISD::Wrapper)
@@ -2944,18 +2940,15 @@ bool X86DAGToDAGISel::selectMOV64Imm32(SDValue N, SDValue &Imm) {
return false;
Imm = N;
- // Small/medium code model can reference non-TargetGlobalAddress objects with
- // 32 bit constants.
- if (N->getOpcode() != ISD::TargetGlobalAddress) {
- return TM.getCodeModel() == CodeModel::Small ||
- TM.getCodeModel() == CodeModel::Medium;
- }
+ if (N->getOpcode() != ISD::TargetGlobalAddress)
+ return TM.getCodeModel() == CodeModel::Small;
- const GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
- if (std::optional<ConstantRange> CR = GV->getAbsoluteSymbolRange())
- return CR->getUnsignedMax().ult(1ull << 32);
+ std::optional<ConstantRange> CR =
+ cast<GlobalAddressSDNode>(N)->getGlobal()->getAbsoluteSymbolRange();
+ if (!CR)
+ return TM.getCodeModel() == CodeModel::Small;
- return !TM.isLargeGlobalValue(GV);
+ return CR->getUnsignedMax().ult(1ull << 32);
}
bool X86DAGToDAGISel::selectLEA64_32Addr(SDValue N, SDValue &Base,
diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp
index d63f1ca1695b20..0f76daffd46339 100644
--- a/llvm/lib/Target/X86/X86Subtarget.cpp
+++ b/llvm/lib/Target/X86/X86Subtarget.cpp
@@ -86,16 +86,16 @@ X86Subtarget::classifyLocalReference(const GlobalValue *GV) const {
CodeModel::Model CM = TM.getCodeModel();
assert(CM != CodeModel::Tiny &&
"Tiny codesize model not supported on X86");
- // In the large code model, all text is far from any global data, so we
- // use GOTOFF.
+ // In the large code model, even referencing a global under the large data
+ // threshold which is considered "small", we need to use GOTOFF.
if (CM == CodeModel::Large)
return X86II::MO_GOTOFF;
- // Large GlobalValues use GOTOFF, otherwise use RIP-rel access.
- if (GV)
- return TM.isLargeGlobalValue(GV) ? X86II::MO_GOTOFF : X86II::MO_NO_FLAG;
- // GV == nullptr is for all other non-GlobalValue global data like the
- // constant pool, jump tables, labels, etc. The small and medium code
- // models treat these as accessible with a RIP-rel access.
+ // Large objects use GOTOFF, otherwise use RIP-rel access.
+ if (auto *GO = dyn_cast_or_null<GlobalObject>(GV))
+ return TM.isLargeGlobalObject(GO) ? X86II::MO_GOTOFF
+ : X86II::MO_NO_FLAG;
+ // For non-GlobalObjects, the small and medium code models treat them as
+ // accessible with a RIP-rel access.
return X86II::MO_NO_FLAG;
}
diff --git a/llvm/test/CodeGen/X86/code-model-elf.ll b/llvm/test/CodeGen/X86/code-model-elf.ll
index a43736e2a5884a..0f58ccaf298dab 100644
--- a/llvm/test/CodeGen/X86/code-model-elf.ll
+++ b/llvm/test/CodeGen/X86/code-model-elf.ll
@@ -40,7 +40,6 @@ target triple = "x86_64--linux"
@global_data = dso_local global [10 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0], align 16
@static_data = internal global [10 x i32] zeroinitializer, align 16
- at static_data_alias = internal constant ptr getelementptr inbounds ([10 x i32], ptr @static_data, i64 0, i64 2), align 8
@extern_data = external global [10 x i32], align 16
@thread_data = external thread_local global i32, align 4
@unknown_size_data = dso_local global [0 x i32] zeroinitializer, align 16
@@ -97,67 +96,12 @@ define dso_local ptr @lea_static_data() #0 {
; LARGE-SMALL-DATA-PIC-NEXT: leaq .L0$pb(%rip), %rax
; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L0$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
-; LARGE-SMALL-DATA-PIC-NEXT: movl $static_data at GOTOFF, %eax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $static_data at GOTOFF, %rax
; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax
; LARGE-SMALL-DATA-PIC-NEXT: retq
ret ptr @static_data
}
-define dso_local ptr @lea_static_data_alias() #0 {
-; SMALL-STATIC-LABEL: lea_static_data_alias:
-; SMALL-STATIC: # %bb.0:
-; SMALL-STATIC-NEXT: movl $static_data_alias, %eax
-; SMALL-STATIC-NEXT: retq
-;
-; MEDIUM-STATIC-LABEL: lea_static_data_alias:
-; MEDIUM-STATIC: # %bb.0:
-; MEDIUM-STATIC-NEXT: movabsq $static_data_alias, %rax
-; MEDIUM-STATIC-NEXT: retq
-;
-; LARGE-STATIC-LABEL: lea_static_data_alias:
-; LARGE-STATIC: # %bb.0:
-; LARGE-STATIC-NEXT: movabsq $static_data_alias, %rax
-; LARGE-STATIC-NEXT: retq
-;
-; SMALL-PIC-LABEL: lea_static_data_alias:
-; SMALL-PIC: # %bb.0:
-; SMALL-PIC-NEXT: leaq static_data_alias(%rip), %rax
-; SMALL-PIC-NEXT: retq
-;
-; MEDIUM-SMALL-DATA-PIC-LABEL: lea_static_data_alias:
-; MEDIUM-SMALL-DATA-PIC: # %bb.0:
-; MEDIUM-SMALL-DATA-PIC-NEXT: leaq static_data_alias(%rip), %rax
-; MEDIUM-SMALL-DATA-PIC-NEXT: retq
-;
-; MEDIUM-PIC-LABEL: lea_static_data_alias:
-; MEDIUM-PIC: # %bb.0:
-; MEDIUM-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rcx
-; MEDIUM-PIC-NEXT: movabsq $static_data_alias at GOTOFF, %rax
-; MEDIUM-PIC-NEXT: addq %rcx, %rax
-; MEDIUM-PIC-NEXT: retq
-;
-; LARGE-PIC-LABEL: lea_static_data_alias:
-; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L1$pb:
-; LARGE-PIC-NEXT: leaq .L1$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L1$pb, %rcx
-; LARGE-PIC-NEXT: addq %rax, %rcx
-; LARGE-PIC-NEXT: movabsq $static_data_alias at GOTOFF, %rax
-; LARGE-PIC-NEXT: addq %rcx, %rax
-; LARGE-PIC-NEXT: retq
-;
-; LARGE-SMALL-DATA-PIC-LABEL: lea_static_data_alias:
-; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L1$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L1$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L1$pb, %rcx
-; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
-; LARGE-SMALL-DATA-PIC-NEXT: movl $static_data_alias at GOTOFF, %eax
-; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax
-; LARGE-SMALL-DATA-PIC-NEXT: retq
- ret ptr @static_data_alias
-}
-
define dso_local ptr @lea_global_data() #0 {
; SMALL-STATIC-LABEL: lea_global_data:
; SMALL-STATIC: # %bb.0:
@@ -193,9 +137,9 @@ define dso_local ptr @lea_global_data() #0 {
;
; LARGE-PIC-LABEL: lea_global_data:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L2$pb:
-; LARGE-PIC-NEXT: leaq .L2$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L2$pb, %rcx
+; LARGE-PIC-NEXT: .L1$pb:
+; LARGE-PIC-NEXT: leaq .L1$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L1$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq $global_data at GOTOFF, %rax
; LARGE-PIC-NEXT: addq %rcx, %rax
@@ -203,11 +147,11 @@ define dso_local ptr @lea_global_data() #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: lea_global_data:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L2$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L2$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L2$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L1$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L1$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L1$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
-; LARGE-SMALL-DATA-PIC-NEXT: movl $global_data at GOTOFF, %eax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $global_data at GOTOFF, %rax
; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax
; LARGE-SMALL-DATA-PIC-NEXT: retq
ret ptr @global_data
@@ -246,9 +190,9 @@ define dso_local ptr @lea_extern_data() #0 {
;
; LARGE-PIC-LABEL: lea_extern_data:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L3$pb:
-; LARGE-PIC-NEXT: leaq .L3$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L3$pb, %rcx
+; LARGE-PIC-NEXT: .L2$pb:
+; LARGE-PIC-NEXT: leaq .L2$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L2$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq $extern_data at GOT, %rax
; LARGE-PIC-NEXT: movq (%rcx,%rax), %rax
@@ -256,11 +200,11 @@ define dso_local ptr @lea_extern_data() #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: lea_extern_data:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L3$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L3$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L3$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L2$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L2$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L2$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
-; LARGE-SMALL-DATA-PIC-NEXT: movl $extern_data at GOT, %eax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $extern_data at GOT, %rax
; LARGE-SMALL-DATA-PIC-NEXT: movq (%rcx,%rax), %rax
; LARGE-SMALL-DATA-PIC-NEXT: retq
ret ptr @extern_data
@@ -303,9 +247,9 @@ define dso_local ptr @lea_unknown_size_data() #0 {
;
; LARGE-PIC-LABEL: lea_unknown_size_data:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L4$pb:
-; LARGE-PIC-NEXT: leaq .L4$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L4$pb, %rcx
+; LARGE-PIC-NEXT: .L3$pb:
+; LARGE-PIC-NEXT: leaq .L3$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L3$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq $unknown_size_data at GOTOFF, %rax
; LARGE-PIC-NEXT: addq %rcx, %rax
@@ -313,9 +257,9 @@ define dso_local ptr @lea_unknown_size_data() #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: lea_unknown_size_data:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L4$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L4$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L4$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L3$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L3$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L3$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: movabsq $unknown_size_data at GOTOFF, %rax
; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax
@@ -323,6 +267,7 @@ define dso_local ptr @lea_unknown_size_data() #0 {
ret ptr @unknown_size_data
}
+; TODO: make nopic small and medium instruction sequence the same
define dso_local ptr @lea_forced_small_data() #0 {
; SMALL-STATIC-LABEL: lea_forced_small_data:
; SMALL-STATIC: # %bb.0:
@@ -331,12 +276,12 @@ define dso_local ptr @lea_forced_small_data() #0 {
;
; MEDIUM-STATIC-LABEL: lea_forced_small_data:
; MEDIUM-STATIC: # %bb.0:
-; MEDIUM-STATIC-NEXT: movl $forced_small_data, %eax
+; MEDIUM-STATIC-NEXT: movabsq $forced_small_data, %rax
; MEDIUM-STATIC-NEXT: retq
;
; LARGE-STATIC-LABEL: lea_forced_small_data:
; LARGE-STATIC: # %bb.0:
-; LARGE-STATIC-NEXT: movl $forced_small_data, %eax
+; LARGE-STATIC-NEXT: movabsq $forced_small_data, %rax
; LARGE-STATIC-NEXT: retq
;
; SMALL-PIC-LABEL: lea_forced_small_data:
@@ -356,21 +301,21 @@ define dso_local ptr @lea_forced_small_data() #0 {
;
; LARGE-PIC-LABEL: lea_forced_small_data:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L5$pb:
-; LARGE-PIC-NEXT: leaq .L5$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L5$pb, %rcx
+; LARGE-PIC-NEXT: .L4$pb:
+; LARGE-PIC-NEXT: leaq .L4$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L4$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
-; LARGE-PIC-NEXT: movl $forced_small_data at GOTOFF, %eax
+; LARGE-PIC-NEXT: movabsq $forced_small_data at GOTOFF, %rax
; LARGE-PIC-NEXT: addq %rcx, %rax
; LARGE-PIC-NEXT: retq
;
; LARGE-SMALL-DATA-PIC-LABEL: lea_forced_small_data:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L5$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L5$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L5$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L4$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L4$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L4$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
-; LARGE-SMALL-DATA-PIC-NEXT: movl $forced_small_data at GOTOFF, %eax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $forced_small_data at GOTOFF, %rax
; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax
; LARGE-SMALL-DATA-PIC-NEXT: retq
ret ptr @forced_small_data
@@ -385,13 +330,13 @@ define dso_local i32 @load_forced_small_data() #0 {
;
; MEDIUM-STATIC-LABEL: load_forced_small_data:
; MEDIUM-STATIC: # %bb.0:
-; MEDIUM-STATIC-NEXT: movl $forced_small_data, %eax
+; MEDIUM-STATIC-NEXT: movabsq $forced_small_data, %rax
; MEDIUM-STATIC-NEXT: movl 8(%rax), %eax
; MEDIUM-STATIC-NEXT: retq
;
; LARGE-STATIC-LABEL: load_forced_small_data:
; LARGE-STATIC: # %bb.0:
-; LARGE-STATIC-NEXT: movl $forced_small_data, %eax
+; LARGE-STATIC-NEXT: movabsq $forced_small_data, %rax
; LARGE-STATIC-NEXT: movl 8(%rax), %eax
; LARGE-STATIC-NEXT: retq
;
@@ -414,21 +359,21 @@ define dso_local i32 @load_forced_small_data() #0 {
;
; LARGE-PIC-LABEL: load_forced_small_data:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L6$pb:
-; LARGE-PIC-NEXT: leaq .L6$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L6$pb, %rcx
+; LARGE-PIC-NEXT: .L5$pb:
+; LARGE-PIC-NEXT: leaq .L5$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L5$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
-; LARGE-PIC-NEXT: movl $forced_small_data at GOTOFF, %eax
+; LARGE-PIC-NEXT: movabsq $forced_small_data at GOTOFF, %rax
; LARGE-PIC-NEXT: movl 8(%rcx,%rax), %eax
; LARGE-PIC-NEXT: retq
;
; LARGE-SMALL-DATA-PIC-LABEL: load_forced_small_data:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L6$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L6$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L6$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L5$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L5$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L5$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
-; LARGE-SMALL-DATA-PIC-NEXT: movl $forced_small_data at GOTOFF, %eax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $forced_small_data at GOTOFF, %rax
; LARGE-SMALL-DATA-PIC-NEXT: movl 8(%rcx,%rax), %eax
; LARGE-SMALL-DATA-PIC-NEXT: retq
%rv = load i32, ptr getelementptr inbounds (i32, ptr @forced_small_data, i64 2)
@@ -439,7 +384,7 @@ define dso_local i32 @load_forced_small_data() #0 {
define dso_local ptr @lea_forced_large_data() #0 {
; SMALL-STATIC-LABEL: lea_forced_large_data:
; SMALL-STATIC: # %bb.0:
-; SMALL-STATIC-NEXT: movabsq $forced_large_data, %rax
+; SMALL-STATIC-NEXT: movl $forced_large_data, %eax
; SMALL-STATIC-NEXT: retq
;
; MEDIUM-STATIC-LABEL: lea_forced_large_data:
@@ -474,9 +419,9 @@ define dso_local ptr @lea_forced_large_data() #0 {
;
; LARGE-PIC-LABEL: lea_forced_large_data:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L7$pb:
-; LARGE-PIC-NEXT: leaq .L7$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L7$pb, %rcx
+; LARGE-PIC-NEXT: .L6$pb:
+; LARGE-PIC-NEXT: leaq .L6$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L6$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq $forced_large_data at GOTOFF, %rax
; LARGE-PIC-NEXT: addq %rcx, %rax
@@ -484,9 +429,9 @@ define dso_local ptr @lea_forced_large_data() #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: lea_forced_large_data:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L7$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L7$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L7$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L6$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L6$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L6$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: movabsq $forced_large_data at GOTOFF, %rax
; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax
@@ -534,9 +479,9 @@ define dso_local i32 @load_forced_large_data() #0 {
;
; LARGE-PIC-LABEL: load_forced_large_data:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L8$pb:
-; LARGE-PIC-NEXT: leaq .L8$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L8$pb, %rcx
+; LARGE-PIC-NEXT: .L7$pb:
+; LARGE-PIC-NEXT: leaq .L7$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L7$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq $forced_large_data at GOTOFF, %rax
; LARGE-PIC-NEXT: movl 8(%rcx,%rax), %eax
@@ -544,9 +489,9 @@ define dso_local i32 @load_forced_large_data() #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: load_forced_large_data:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L8$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L8$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L8$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L7$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L7$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L7$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: movabsq $forced_large_data at GOTOFF, %rax
; LARGE-SMALL-DATA-PIC-NEXT: movl 8(%rcx,%rax), %eax
@@ -593,9 +538,9 @@ define dso_local i32 @load_global_data() #0 {
;
; LARGE-PIC-LABEL: load_global_data:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L9$pb:
-; LARGE-PIC-NEXT: leaq .L9$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L9$pb, %rcx
+; LARGE-PIC-NEXT: .L8$pb:
+; LARGE-PIC-NEXT: leaq .L8$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L8$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq $global_data at GOTOFF, %rax
; LARGE-PIC-NEXT: movl 8(%rcx,%rax), %eax
@@ -603,11 +548,11 @@ define dso_local i32 @load_global_data() #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: load_global_data:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L9$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L9$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L9$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L8$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L8$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L8$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
-; LARGE-SMALL-DATA-PIC-NEXT: movl $global_data at GOTOFF, %eax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $global_data at GOTOFF, %rax
; LARGE-SMALL-DATA-PIC-NEXT: movl 8(%rcx,%rax), %eax
; LARGE-SMALL-DATA-PIC-NEXT: retq
%rv = load i32, ptr getelementptr inbounds ([10 x i32], ptr @global_data, i64 0, i64 2)
@@ -653,9 +598,9 @@ define dso_local i32 @load_extern_data() #0 {
;
; LARGE-PIC-LABEL: load_extern_data:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L10$pb:
-; LARGE-PIC-NEXT: leaq .L10$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L10$pb, %rcx
+; LARGE-PIC-NEXT: .L9$pb:
+; LARGE-PIC-NEXT: leaq .L9$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L9$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq $extern_data at GOT, %rax
; LARGE-PIC-NEXT: movq (%rcx,%rax), %rax
@@ -664,11 +609,11 @@ define dso_local i32 @load_extern_data() #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: load_extern_data:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L10$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L10$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L10$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L9$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L9$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L9$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
-; LARGE-SMALL-DATA-PIC-NEXT: movl $extern_data at GOT, %eax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $extern_data at GOT, %rax
; LARGE-SMALL-DATA-PIC-NEXT: movq (%rcx,%rax), %rax
; LARGE-SMALL-DATA-PIC-NEXT: movl 8(%rax), %eax
; LARGE-SMALL-DATA-PIC-NEXT: retq
@@ -715,9 +660,9 @@ define dso_local i32 @load_unknown_size_data() #0 {
;
; LARGE-PIC-LABEL: load_unknown_size_data:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L11$pb:
-; LARGE-PIC-NEXT: leaq .L11$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L11$pb, %rcx
+; LARGE-PIC-NEXT: .L10$pb:
+; LARGE-PIC-NEXT: leaq .L10$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L10$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq $unknown_size_data at GOTOFF, %rax
; LARGE-PIC-NEXT: movl 8(%rcx,%rax), %eax
@@ -725,9 +670,9 @@ define dso_local i32 @load_unknown_size_data() #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: load_unknown_size_data:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L11$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L11$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L11$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L10$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L10$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L10$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: movabsq $unknown_size_data at GOTOFF, %rax
; LARGE-SMALL-DATA-PIC-NEXT: movl 8(%rcx,%rax), %eax
@@ -773,9 +718,9 @@ define dso_local ptr @lea_opaque() #0 {
;
; LARGE-PIC-LABEL: lea_opaque:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L12$pb:
-; LARGE-PIC-NEXT: leaq .L12$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L12$pb, %rcx
+; LARGE-PIC-NEXT: .L11$pb:
+; LARGE-PIC-NEXT: leaq .L11$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L11$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq $opaque at GOTOFF, %rax
; LARGE-PIC-NEXT: addq %rcx, %rax
@@ -783,9 +728,9 @@ define dso_local ptr @lea_opaque() #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: lea_opaque:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L12$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L12$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L12$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L11$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L11$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L11$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: movabsq $opaque at GOTOFF, %rax
; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax
@@ -854,9 +799,9 @@ define dso_local ptr @lea_static_fn() #0 {
;
; LARGE-PIC-LABEL: lea_static_fn:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L16$pb:
-; LARGE-PIC-NEXT: leaq .L16$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L16$pb, %rcx
+; LARGE-PIC-NEXT: .L15$pb:
+; LARGE-PIC-NEXT: leaq .L15$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L15$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq $static_fn at GOTOFF, %rax
; LARGE-PIC-NEXT: addq %rcx, %rax
@@ -864,9 +809,9 @@ define dso_local ptr @lea_static_fn() #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: lea_static_fn:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L16$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L16$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L16$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L15$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L15$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L15$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: movabsq $static_fn at GOTOFF, %rax
; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax
@@ -907,9 +852,9 @@ define dso_local ptr @lea_global_fn() #0 {
;
; LARGE-PIC-LABEL: lea_global_fn:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L17$pb:
-; LARGE-PIC-NEXT: leaq .L17$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L17$pb, %rcx
+; LARGE-PIC-NEXT: .L16$pb:
+; LARGE-PIC-NEXT: leaq .L16$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L16$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq $global_fn at GOTOFF, %rax
; LARGE-PIC-NEXT: addq %rcx, %rax
@@ -917,9 +862,9 @@ define dso_local ptr @lea_global_fn() #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: lea_global_fn:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L17$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L17$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L17$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L16$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L16$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L16$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: movabsq $global_fn at GOTOFF, %rax
; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax
@@ -960,9 +905,9 @@ define dso_local ptr @lea_extern_fn() #0 {
;
; LARGE-PIC-LABEL: lea_extern_fn:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L18$pb:
-; LARGE-PIC-NEXT: leaq .L18$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L18$pb, %rcx
+; LARGE-PIC-NEXT: .L17$pb:
+; LARGE-PIC-NEXT: leaq .L17$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L17$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq $extern_fn at GOT, %rax
; LARGE-PIC-NEXT: movq (%rcx,%rax), %rax
@@ -970,9 +915,9 @@ define dso_local ptr @lea_extern_fn() #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: lea_extern_fn:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L18$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L18$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L18$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L17$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L17$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L17$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: movabsq $extern_fn at GOT, %rax
; LARGE-SMALL-DATA-PIC-NEXT: movq (%rcx,%rax), %rax
@@ -1013,9 +958,9 @@ define dso_local ptr @lea_ifunc() #0 {
;
; LARGE-PIC-LABEL: lea_ifunc:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L19$pb:
-; LARGE-PIC-NEXT: leaq .L19$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L19$pb, %rcx
+; LARGE-PIC-NEXT: .L18$pb:
+; LARGE-PIC-NEXT: leaq .L18$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L18$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq $ifunc_func at GOT, %rax
; LARGE-PIC-NEXT: movq (%rcx,%rax), %rax
@@ -1023,9 +968,9 @@ define dso_local ptr @lea_ifunc() #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: lea_ifunc:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L19$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L19$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L19$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L18$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L18$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L18$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: movabsq $ifunc_func at GOT, %rax
; LARGE-SMALL-DATA-PIC-NEXT: movq (%rcx,%rax), %rax
@@ -1041,7 +986,7 @@ define dso_local ptr @lea_dso_local_ifunc() #0 {
;
; MEDIUM-STATIC-LABEL: lea_dso_local_ifunc:
; MEDIUM-STATIC: # %bb.0:
-; MEDIUM-STATIC-NEXT: movl $dso_local_ifunc_func, %eax
+; MEDIUM-STATIC-NEXT: movabsq $dso_local_ifunc_func, %rax
; MEDIUM-STATIC-NEXT: retq
;
; LARGE-STATIC-LABEL: lea_dso_local_ifunc:
@@ -1066,9 +1011,9 @@ define dso_local ptr @lea_dso_local_ifunc() #0 {
;
; LARGE-PIC-LABEL: lea_dso_local_ifunc:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L20$pb:
-; LARGE-PIC-NEXT: leaq .L20$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L20$pb, %rcx
+; LARGE-PIC-NEXT: .L19$pb:
+; LARGE-PIC-NEXT: leaq .L19$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L19$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq $dso_local_ifunc_func at GOTOFF, %rax
; LARGE-PIC-NEXT: addq %rcx, %rax
@@ -1076,9 +1021,9 @@ define dso_local ptr @lea_dso_local_ifunc() #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: lea_dso_local_ifunc:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L20$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L20$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L20$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L19$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L19$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L19$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: movabsq $dso_local_ifunc_func at GOTOFF, %rax
; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax
@@ -1127,7 +1072,7 @@ define dso_local float @load_constant_pool(float %x) #0 {
;
; MEDIUM-STATIC-LABEL: load_constant_pool:
; MEDIUM-STATIC: # %bb.0:
-; MEDIUM-STATIC-NEXT: movl ${{\.?LCPI[0-9]+_[0-9]+}}, %eax
+; MEDIUM-STATIC-NEXT: movabsq ${{\.?LCPI[0-9]+_[0-9]+}}, %rax
; MEDIUM-STATIC-NEXT: addss (%rax), %xmm0
; MEDIUM-STATIC-NEXT: retq
;
@@ -1154,9 +1099,9 @@ define dso_local float @load_constant_pool(float %x) #0 {
;
; LARGE-PIC-LABEL: load_constant_pool:
; LARGE-PIC: # %bb.0:
-; LARGE-PIC-NEXT: .L22$pb:
-; LARGE-PIC-NEXT: leaq .L22$pb(%rip), %rax
-; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L22$pb, %rcx
+; LARGE-PIC-NEXT: .L21$pb:
+; LARGE-PIC-NEXT: leaq .L21$pb(%rip), %rax
+; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L21$pb, %rcx
; LARGE-PIC-NEXT: addq %rax, %rcx
; LARGE-PIC-NEXT: movabsq ${{\.?LCPI[0-9]+_[0-9]+}}@GOTOFF, %rax
; LARGE-PIC-NEXT: addss (%rcx,%rax), %xmm0
@@ -1164,9 +1109,9 @@ define dso_local float @load_constant_pool(float %x) #0 {
;
; LARGE-SMALL-DATA-PIC-LABEL: load_constant_pool:
; LARGE-SMALL-DATA-PIC: # %bb.0:
-; LARGE-SMALL-DATA-PIC-NEXT: .L22$pb:
-; LARGE-SMALL-DATA-PIC-NEXT: leaq .L22$pb(%rip), %rax
-; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L22$pb, %rcx
+; LARGE-SMALL-DATA-PIC-NEXT: .L21$pb:
+; LARGE-SMALL-DATA-PIC-NEXT: leaq .L21$pb(%rip), %rax
+; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L21$pb, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx
; LARGE-SMALL-DATA-PIC-NEXT: movabsq ${{\.?LCPI[0-9]+_[0-9]+}}@GOTOFF, %rax
; LARGE-SMALL-DATA-PIC-NEXT: addss (%rcx,%rax), %xmm0
>From 6e87672150986d931e770ec829699a7930ebeeb2 Mon Sep 17 00:00:00 2001
From: Rainer Orth <ro at gcc.gnu.org>
Date: Thu, 14 Dec 2023 22:03:45 +0100
Subject: [PATCH 08/16] [flang] Adjust _FORTRAN_RUNTIME_IEEE_FENV_T_EXTENT for
Solaris (#74590)
Even after 13e2200fa426faffb62bdaf8b2f1f5699eee1511 (Solaris lacks
`femode_t`, too), the Solaris `flang` build is still broken:
```
/vol/llvm/src/llvm-project/local/flang/runtime/exceptions.cpp:87:5: error: static assertion failed due to requirement 'sizeof(fenv_t) <= sizeof(int) * 8': increase ieee_status_type size
87 | sizeof(fenv_t) <= sizeof(int) * _FORTRAN_RUNTIME_IEEE_FENV_T_EXTENT, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/vol/llvm/src/llvm-project/local/flang/runtime/exceptions.cpp:87:20: note: expression evaluates to '200 <= 32'
87 | sizeof(fenv_t) <= sizeof(int) * _FORTRAN_RUNTIME_IEEE_FENV_T_EXTENT, | ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
This patch fixes this by removing the assertion.
Tested on `amd64-pc-solaris2.11` and `sparcv9-sun-solaris2.11`.
---
flang/runtime/exceptions.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/flang/runtime/exceptions.cpp b/flang/runtime/exceptions.cpp
index 1dbee833884fbc..dfd3b812e22a13 100644
--- a/flang/runtime/exceptions.cpp
+++ b/flang/runtime/exceptions.cpp
@@ -78,10 +78,10 @@ std::int32_t RTNAME(MapException)(int32_t except) {
// Verify that the size of ieee_modes_type and ieee_status_type objects from
// intrinsic module file __fortran_ieee_exceptions.f90 are large enough to
// hold fenv_t object.
+// TODO: fenv_t can be way larger than
+// sizeof(int) * _FORTRAN_RUNTIME_IEEE_FENV_T_EXTENT
+// on some systems, e.g. Solaris, so omit object size comparison for now.
// TODO: consider femode_t object size comparison once its more mature.
-static_assert(
- sizeof(fenv_t) <= sizeof(int) * _FORTRAN_RUNTIME_IEEE_FENV_T_EXTENT,
- "increase ieee_status_type size");
} // extern "C"
} // namespace Fortran::runtime
>From c26174f3a8337417dc5a8e89c21ced6bed46e8c9 Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Thu, 14 Dec 2023 21:10:36 +0000
Subject: [PATCH 09/16] [AMDGPU] Remove s_cbranch_cdbg* for GFX12 (#75496)
No GFX12 encoding was added for these, so this patch just adds tests
that they are not recognized by the assembler.
---
llvm/test/MC/AMDGPU/gfx12_unsupported.s | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/llvm/test/MC/AMDGPU/gfx12_unsupported.s b/llvm/test/MC/AMDGPU/gfx12_unsupported.s
index e835710a69fe85..4f6758b6f6786d 100644
--- a/llvm/test/MC/AMDGPU/gfx12_unsupported.s
+++ b/llvm/test/MC/AMDGPU/gfx12_unsupported.s
@@ -10,6 +10,18 @@ s_subvector_loop_begin s0, 0x1234
s_subvector_loop_end s0, 0x1234
// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+s_cbranch_cdbgsys 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+s_cbranch_cdbguser 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+s_cbranch_cdbgsys_or_user 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+s_cbranch_cdbgsys_and_user 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
ds_cmpstore_f32 v0, v1, v2
// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
>From c5a068a196651a87a3af12cb67bd5b4309ddeaa2 Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Thu, 14 Dec 2023 21:10:53 +0000
Subject: [PATCH 10/16] [AMDGPU] Remove s_cmpk_* for GFX12 (#75497)
No GFX12 encoding was added for these. This patch adds tests that they
are not recognized by the assembler and defends against generating them
in codegen.
---
llvm/lib/Target/AMDGPU/GCNSubtarget.h | 3 ++
.../Target/AMDGPU/SIShrinkInstructions.cpp | 3 ++
llvm/test/MC/AMDGPU/gfx12_unsupported.s | 36 +++++++++++++++++++
3 files changed, 42 insertions(+)
diff --git a/llvm/lib/Target/AMDGPU/GCNSubtarget.h b/llvm/lib/Target/AMDGPU/GCNSubtarget.h
index 8e1350be8b45fc..f017b809dae620 100644
--- a/llvm/lib/Target/AMDGPU/GCNSubtarget.h
+++ b/llvm/lib/Target/AMDGPU/GCNSubtarget.h
@@ -830,6 +830,9 @@ class GCNSubtarget final : public AMDGPUGenSubtargetInfo,
bool hasInstPrefetch() const { return getGeneration() >= GFX10; }
+ // Has s_cmpk_* instructions.
+ bool hasSCmpK() const { return getGeneration() < GFX12; }
+
// Scratch is allocated in 256 dword per wave blocks for the entire
// wavefront. When viewed from the perspective of an arbitrary workitem, this
// is 4-byte aligned.
diff --git a/llvm/lib/Target/AMDGPU/SIShrinkInstructions.cpp b/llvm/lib/Target/AMDGPU/SIShrinkInstructions.cpp
index 856121be78031d..d290dd82b76058 100644
--- a/llvm/lib/Target/AMDGPU/SIShrinkInstructions.cpp
+++ b/llvm/lib/Target/AMDGPU/SIShrinkInstructions.cpp
@@ -211,6 +211,9 @@ void SIShrinkInstructions::copyExtraImplicitOps(MachineInstr &NewMI,
}
void SIShrinkInstructions::shrinkScalarCompare(MachineInstr &MI) const {
+ if (!ST->hasSCmpK())
+ return;
+
// cmpk instructions do scc = dst <cc op> imm16, so commute the instruction to
// get constants on the RHS.
if (!MI.getOperand(0).isReg())
diff --git a/llvm/test/MC/AMDGPU/gfx12_unsupported.s b/llvm/test/MC/AMDGPU/gfx12_unsupported.s
index 4f6758b6f6786d..7878857962b2a9 100644
--- a/llvm/test/MC/AMDGPU/gfx12_unsupported.s
+++ b/llvm/test/MC/AMDGPU/gfx12_unsupported.s
@@ -43,6 +43,42 @@ ds_sub_gs_reg_rtn v[0:1], v2 gds
ds_wrap_rtn_b32 v0, v1, v2, v3
// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+s_cmpk_eq_i32 s0, 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+s_cmpk_lg_i32 s0, 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+s_cmpk_gt_i32 s0, 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+s_cmpk_ge_i32 s0, 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+s_cmpk_lt_i32 s0, 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+s_cmpk_le_i32 s0, 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+s_cmpk_eq_u32 s0, 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+s_cmpk_lg_u32 s0, 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+s_cmpk_gt_u32 s0, 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+s_cmpk_ge_u32 s0, 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+s_cmpk_lt_u32 s0, 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+s_cmpk_le_u32 s0, 0
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
ds_gws_sema_release_all gds
// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
>From d8941df9325a107410be42d841b169ea267822e8 Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Thu, 14 Dec 2023 21:11:10 +0000
Subject: [PATCH 11/16] [AMDGPU] Remove v_cmp_t_* and v_cmp_f_* for GFX12
(#75498)
Also v_cmpx_t_* and v_cmpx_f_*
No GFX12 encoding was added for these, so this patch just adds tests
that they are not recognized by the assembler.
---
llvm/test/MC/AMDGPU/gfx12_unsupported.s | 84 +++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/llvm/test/MC/AMDGPU/gfx12_unsupported.s b/llvm/test/MC/AMDGPU/gfx12_unsupported.s
index 7878857962b2a9..44c85b8545c510 100644
--- a/llvm/test/MC/AMDGPU/gfx12_unsupported.s
+++ b/llvm/test/MC/AMDGPU/gfx12_unsupported.s
@@ -100,6 +100,90 @@ ds_gws_barrier v0 gds
ds_ordered_count v0, v1 gds
// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+v_cmp_f_f16 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmp_t_f16 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmp_f_f32 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmp_t_f32 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmp_f_f64 v[0:1], v[2:3]
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmp_t_f64 v[0:1], v[2:3]
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmp_f_i32 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmp_t_i32 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmp_f_u32 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmp_t_u32 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmp_f_i64 v[0:1], v[2:3]
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmp_t_i64 v[0:1], v[2:3]
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmp_f_u64 v[0:1], v[2:3]
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmp_t_u64 v[0:1], v[2:3]
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmpx_f_f16 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmpx_t_f16 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmpx_f_f32 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmpx_t_f32 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmpx_f_f64 v[0:1], v[2:3]
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmpx_t_f64 v[0:1], v[2:3]
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmpx_f_i32 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmpx_t_i32 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmpx_f_u32 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmpx_t_u32 v0, v1
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmpx_f_i64 v[0:1], v[2:3]
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmpx_t_i64 v[0:1], v[2:3]
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmpx_f_u64 v[0:1], v[2:3]
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
+v_cmpx_t_u64 v[0:1], v[2:3]
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
+
buffer_atomic_cmpswap_f32 v[5:6], off, s[96:99], s3
// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction not supported on this GPU
>From 1b6c8280b9a672a9c6f5c22d18b1cdaa2320d4ed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andrzej=20Warzy=C5=84ski?= <andrzej.warzynski at arm.com>
Date: Thu, 14 Dec 2023 21:11:25 +0000
Subject: [PATCH 12/16] [flang][driver] Don't use -whole-archive on Darwin
(#75393)
Direct follow-up of #73124 - the linker on Darwin does not support
`-whole-archive`, so that needs to be removed from the linker
invocation.
For context:
* https://github.com/llvm/llvm-project/pull/73124
---
clang/lib/Driver/ToolChains/CommonArgs.cpp | 22 ++++++++++++++--------
flang/test/Driver/no-duplicate-main.f90 | 2 +-
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 01fb0718b4079d..3d1df58190ce05 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1132,24 +1132,30 @@ void tools::addFortranRuntimeLibs(const ToolChain &TC, const ArgList &Args,
// --whole-archive flag to the link line. If it's not, add a proper
// --whole-archive/--no-whole-archive bracket to the link line.
bool WholeArchiveActive = false;
- for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA))
- if (Arg)
+ for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA)) {
+ if (Arg) {
for (StringRef ArgValue : Arg->getValues()) {
if (ArgValue == "--whole-archive")
WholeArchiveActive = true;
if (ArgValue == "--no-whole-archive")
WholeArchiveActive = false;
}
+ }
+ }
- if (!WholeArchiveActive)
+ // TODO: Find an equivalent of `--whole-archive` for Darwin.
+ if (!WholeArchiveActive && !TC.getTriple().isMacOSX()) {
CmdArgs.push_back("--whole-archive");
- CmdArgs.push_back("-lFortran_main");
- if (!WholeArchiveActive)
+ CmdArgs.push_back("-lFortran_main");
CmdArgs.push_back("--no-whole-archive");
+ } else {
+ CmdArgs.push_back("-lFortran_main");
+ }
+
+ // Perform regular linkage of the remaining runtime libraries.
+ CmdArgs.push_back("-lFortranRuntime");
+ CmdArgs.push_back("-lFortranDecimal");
}
- // Perform regular linkage of the remaining runtime libraries.
- CmdArgs.push_back("-lFortranRuntime");
- CmdArgs.push_back("-lFortranDecimal");
} else {
if (LinkFortranMain) {
unsigned RTOptionID = options::OPT__SLASH_MT;
diff --git a/flang/test/Driver/no-duplicate-main.f90 b/flang/test/Driver/no-duplicate-main.f90
index 12d5e46247bad2..b884e7ecd7f12a 100644
--- a/flang/test/Driver/no-duplicate-main.f90
+++ b/flang/test/Driver/no-duplicate-main.f90
@@ -1,4 +1,4 @@
-! UNSUPPORTED: system-windows
+! UNSUPPORTED: system-windows, system-darwin
! RUN: %flang -x ir -o %t.c-object -c %S/Inputs/no_duplicate_main.ll
! RUN: %flang -o %t -c %s
>From 3e6da3252fbbe58c309b58e08c8a16ac2797b5da Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Thu, 14 Dec 2023 21:11:39 +0000
Subject: [PATCH 13/16] [AMDGPU] Add GFX12 s_sleep_var instruction and
intrinsic (#75499)
---
llvm/include/llvm/IR/IntrinsicsAMDGPU.td | 6 +++
.../Target/AMDGPU/AMDGPURegisterBankInfo.cpp | 7 ++++
llvm/lib/Target/AMDGPU/SIInstrInfo.cpp | 13 +++++++
llvm/lib/Target/AMDGPU/SOPInstructions.td | 5 +++
.../CodeGen/AMDGPU/llvm.amdgcn.s.sleep.var.ll | 38 +++++++++++++++++++
llvm/test/MC/AMDGPU/gfx12_asm_sop1.s | 6 +++
.../Disassembler/AMDGPU/gfx12_dasm_sop1.txt | 6 +++
7 files changed, 81 insertions(+)
create mode 100644 llvm/test/CodeGen/AMDGPU/llvm.amdgcn.s.sleep.var.ll
diff --git a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
index 09e88152e65d2a..b1aefc1777f855 100644
--- a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
+++ b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
@@ -1715,6 +1715,12 @@ def int_amdgcn_s_sleep :
IntrHasSideEffects]> {
}
+def int_amdgcn_s_sleep_var
+ : ClangBuiltin<"__builtin_amdgcn_s_sleep_var">,
+ Intrinsic<[], [llvm_i32_ty],
+ [IntrNoMem, IntrHasSideEffects, IntrWillReturn]> {
+}
+
def int_amdgcn_s_nop :
DefaultAttrsIntrinsic<[], [llvm_i16_ty], [ImmArg<ArgIndex<0>>, IntrNoMem,
IntrHasSideEffects]> {
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
index 03b6d19b2b3c06..d0c1302c3f003c 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
@@ -3101,6 +3101,10 @@ void AMDGPURegisterBankInfo::applyMappingImpl(
applyDefaultMapping(OpdMapper);
constrainOpWithReadfirstlane(B, MI, 8); // M0
return;
+ case Intrinsic::amdgcn_s_sleep_var:
+ assert(OpdMapper.getVRegs(1).empty());
+ constrainOpWithReadfirstlane(B, MI, 1);
+ return;
case Intrinsic::amdgcn_s_barrier_signal_var:
case Intrinsic::amdgcn_s_barrier_join:
case Intrinsic::amdgcn_s_wakeup_barrier:
@@ -4849,6 +4853,9 @@ AMDGPURegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
getVGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI); // %data1
break;
}
+ case Intrinsic::amdgcn_s_sleep_var:
+ OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
+ break;
case Intrinsic::amdgcn_s_barrier_signal_var:
case Intrinsic::amdgcn_s_barrier_join:
case Intrinsic::amdgcn_s_wakeup_barrier:
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
index d4746b559d9256..03ffe8e10f4bbd 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
@@ -6564,6 +6564,19 @@ SIInstrInfo::legalizeOperands(MachineInstr &MI,
}
}
+ // Legalize s_sleep_var.
+ if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
+ const DebugLoc &DL = MI.getDebugLoc();
+ Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
+ int Src0Idx =
+ AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
+ MachineOperand &Src0 = MI.getOperand(Src0Idx);
+ BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
+ .add(Src0);
+ Src0.ChangeToRegister(Reg, false);
+ return nullptr;
+ }
+
// Legalize MUBUF instructions.
bool isSoffsetLegal = true;
int SoffsetIdx =
diff --git a/llvm/lib/Target/AMDGPU/SOPInstructions.td b/llvm/lib/Target/AMDGPU/SOPInstructions.td
index 50c4d279cfe23d..c51534cdbd3054 100644
--- a/llvm/lib/Target/AMDGPU/SOPInstructions.td
+++ b/llvm/lib/Target/AMDGPU/SOPInstructions.td
@@ -1602,6 +1602,10 @@ def S_SLEEP : SOPP_Pseudo <"s_sleep", (ins i32imm:$simm16),
"$simm16", [(int_amdgcn_s_sleep timm:$simm16)]> {
}
+def S_SLEEP_VAR : SOP1_0_32 <"s_sleep_var", [(int_amdgcn_s_sleep_var SSrc_b32:$src0)]> {
+ let hasSideEffects = 1;
+}
+
def S_SETPRIO : SOPP_Pseudo <"s_setprio", (ins i16imm:$simm16), "$simm16",
[(int_amdgcn_s_setprio timm:$simm16)]> {
}
@@ -1997,6 +2001,7 @@ defm S_GET_BARRIER_STATE_IMM : SOP1_Real_gfx12<0x050>;
defm S_BARRIER_INIT_IMM : SOP1_Real_gfx12<0x051>;
defm S_BARRIER_JOIN_IMM : SOP1_Real_gfx12<0x052>;
defm S_WAKEUP_BARRIER_IMM : SOP1_Real_gfx12<0x057>;
+defm S_SLEEP_VAR : SOP1_Real_gfx12<0x058>;
//===----------------------------------------------------------------------===//
// SOP1 - GFX1150, GFX12
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.s.sleep.var.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.s.sleep.var.ll
new file mode 100644
index 00000000000000..5ad7ddfbe5fe9d
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.s.sleep.var.ll
@@ -0,0 +1,38 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -march=amdgcn -mcpu=gfx1200 -verify-machineinstrs -global-isel=0 < %s | FileCheck -check-prefixes=GCN %s
+; RUN: llc -march=amdgcn -mcpu=gfx1200 -verify-machineinstrs -global-isel=1 < %s | FileCheck -check-prefixes=GCN %s
+
+declare void @llvm.amdgcn.s.sleep.var(i32)
+
+define void @test_s_sleep_var1(i32 %arg) {
+; GCN-LABEL: test_s_sleep_var1:
+; GCN: ; %bb.0:
+; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GCN-NEXT: v_readfirstlane_b32 s0, v0
+; GCN-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; GCN-NEXT: s_sleep_var s0
+; GCN-NEXT: s_setpc_b64 s[30:31]
+ call void @llvm.amdgcn.s.sleep.var(i32 %arg)
+ ret void
+}
+
+define void @test_s_sleep_var2() {
+; GCN-LABEL: test_s_sleep_var2:
+; GCN: ; %bb.0:
+; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GCN-NEXT: s_sleep_var 10
+; GCN-NEXT: s_setpc_b64 s[30:31]
+ call void @llvm.amdgcn.s.sleep.var(i32 10)
+ ret void
+}
+
+define amdgpu_kernel void @test_s_sleep_var3(i32 %arg) {
+; GCN-LABEL: test_s_sleep_var3:
+; GCN: ; %bb.0:
+; GCN-NEXT: s_load_b32 s0, s[0:1], 0x24
+; GCN-NEXT: s_waitcnt lgkmcnt(0)
+; GCN-NEXT: s_sleep_var s0
+; GCN-NEXT: s_endpgm
+ call void @llvm.amdgcn.s.sleep.var(i32 %arg)
+ ret void
+}
diff --git a/llvm/test/MC/AMDGPU/gfx12_asm_sop1.s b/llvm/test/MC/AMDGPU/gfx12_asm_sop1.s
index 8f2944586ed290..495a2ea78ffef7 100644
--- a/llvm/test/MC/AMDGPU/gfx12_asm_sop1.s
+++ b/llvm/test/MC/AMDGPU/gfx12_asm_sop1.s
@@ -1,5 +1,11 @@
// RUN: llvm-mc -arch=amdgcn -show-encoding -mcpu=gfx1200 %s | FileCheck --check-prefix=GFX12 %s
+s_sleep_var 0x1234
+// GFX12: encoding: [0xff,0x58,0x80,0xbe,0x34,0x12,0x00,0x00]
+
+s_sleep_var s1
+// GFX12: encoding: [0x01,0x58,0x80,0xbe]
+
s_cvt_f32_i32 s5, s1
// GFX12: encoding: [0x01,0x64,0x85,0xbe]
diff --git a/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sop1.txt b/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sop1.txt
index 1c31ee1e5dd7fb..d15a329c8eade7 100644
--- a/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sop1.txt
+++ b/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sop1.txt
@@ -1,5 +1,11 @@
# RUN: llvm-mc -arch=amdgcn -mcpu=gfx1200 -disassemble -show-encoding < %s | FileCheck -check-prefixes=GFX12 %s
+# GFX12: s_sleep_var 0x1234 ; encoding: [0xff,0x58,0x80,0xbe,0x34,0x12,0x00,0x00]
+0xff,0x58,0x80,0xbe,0x34,0x12,0x00,0x00
+
+# GFX12: s_sleep_var s1 ; encoding: [0x01,0x58,0x80,0xbe]
+0x01,0x58,0x80,0xbe
+
# GFX12: s_cvt_f32_i32 s5, s1 ; encoding: [0x01,0x64,0x85,0xbe]
0x01,0x64,0x85,0xbe
>From 29e043cb5c2efaad7fb203fb8240a91b77ca0c5b Mon Sep 17 00:00:00 2001
From: Craig Hesling <hesling.craig at gmail.com>
Date: Thu, 14 Dec 2023 16:25:03 -0500
Subject: [PATCH 14/16] [libclang/python] Fix some minor typos (#74292)
These patches do not change the functionality of the library. They
simply correct comments and documentation.
* Add a missing space in a the `FixIt` class comment
* Fix an llvm-project path in the `README.txt`
---
clang/bindings/python/README.txt | 2 +-
clang/bindings/python/clang/cindex.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/bindings/python/README.txt b/clang/bindings/python/README.txt
index b0f0142a56f116..44c715e5de56f7 100644
--- a/clang/bindings/python/README.txt
+++ b/clang/bindings/python/README.txt
@@ -8,7 +8,7 @@ You may need to set CLANG_LIBRARY_PATH so that the Clang library can be
found. The unit tests are designed to be run with any standard test
runner. For example:
--
-$ env PYTHONPATH=$(echo ~/llvm/tools/clang/bindings/python/) \
+$ env PYTHONPATH=$(echo ~/llvm/clang/bindings/python/) \
CLANG_LIBRARY_PATH=$(llvm-config --libdir) \
python -m unittest discover -v
tests.cindex.test_index.test_create ... ok
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 6a16f3a9ef6e95..d780ee353a133c 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -535,7 +535,7 @@ def from_param(self):
class FixIt(object):
"""
A FixIt represents a transformation to be applied to the source to
- "fix-it". The fix-it shouldbe applied by replacing the given source range
+ "fix-it". The fix-it should be applied by replacing the given source range
with the given value.
"""
>From 7c6b4be615c225b11a94a90bfd421265e1544fd5 Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <nickdesaulniers at users.noreply.github.com>
Date: Thu, 14 Dec 2023 13:39:33 -0800
Subject: [PATCH 15/16] [libc] fix msan failure in mempcpy_test (#75532)
Internal builds of the unittests with msan flagged mempcpy_test.
==6862==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x55e34d7d734a in length
llvm-project/libc/src/__support/CPP/string_view.h:41:11
#1 0x55e34d7d734a in string_view
llvm-project/libc/src/__support/CPP/string_view.h:71:24
#2 0x55e34d7d734a in
__llvm_libc_9999_0_0_git::testing::Test::testStrEq(char const*, char
const*, char const*, char const*,
__llvm_libc_9999_0_0_git::testing::internal::Location)
llvm-project/libc/test/UnitTest/LibcTest.cpp:284:13
#3 0x55e34d7d4e09 in LlvmLibcMempcpyTest_Simple::Run()
llvm-project/libc/test/src/string/mempcpy_test.cpp:20:3
#4 0x55e34d7d6dff in
__llvm_libc_9999_0_0_git::testing::Test::runTests(char const*)
llvm-project/libc/test/UnitTest/LibcTest.cpp:133:8
#5 0x55e34d7d86e0 in main
llvm-project/libc/test/UnitTest/LibcTestMain.cpp:21:10
SUMMARY: MemorySanitizer: use-of-uninitialized-value
llvm-project/libc/src/__support/CPP/string_view.h:41:11 in length
What's going on here is that mempcpy_test.cpp's Simple test is using
ASSERT_STREQ with a partially initialized char array. ASSERT_STREQ calls
Test::testStrEq which constructs a cpp:string_view. That constructor
calls the
private method cpp::string_view::length. When built with msan, the loop
is
transformed into multi-byte access, which then fails upon access.
I took a look at libc++'s __constexpr_strlen which just calls
__builtin_strlen(). Replacing the implementation of
cpp::string_view::length
with a call to __builtin_strlen() may still result in out of bounds
access when
the test is built with msan.
It's not safe to use ASSERT_STREQ with a partially initialized array.
Initialize the whole array so that the test passes.
---
libc/test/src/string/mempcpy_test.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/test/src/string/mempcpy_test.cpp b/libc/test/src/string/mempcpy_test.cpp
index 43ad5a0f3e1b7e..877ee8104880eb 100644
--- a/libc/test/src/string/mempcpy_test.cpp
+++ b/libc/test/src/string/mempcpy_test.cpp
@@ -14,7 +14,7 @@
// mempcpy behavior (returning the end of what was copied).
TEST(LlvmLibcMempcpyTest, Simple) {
const char *src = "12345";
- char dest[10];
+ char dest[10] = {};
void *result = LIBC_NAMESPACE::mempcpy(dest, src, 6);
ASSERT_EQ(static_cast<char *>(result), dest + 6);
ASSERT_STREQ(src, dest);
>From 640c1d3dd12843f9ad29df472bbf0a88f90770b5 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Thu, 14 Dec 2023 14:40:52 -0700
Subject: [PATCH 16/16] [llvm] Support IFuncs on Darwin platforms (#73686)
... by lowering them as lazy resolve-on-first-use symbol resolvers. Note that this is subtly different timing than on ELF platforms, where ifunc resolution happens at load time.
Since ld64 and ld-prime don't support all the cases we need for these, we lower them manually in the AsmPrinter.
---
llvm/docs/LangRef.rst | 7 +-
llvm/include/llvm/CodeGen/AsmPrinter.h | 23 +-
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 137 ++++++++----
llvm/lib/IR/Verifier.cpp | 12 +-
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 207 ++++++++++++++++++
llvm/lib/Target/X86/X86AsmPrinter.cpp | 82 +++++++
llvm/lib/Target/X86/X86AsmPrinter.h | 5 +
llvm/test/CodeGen/AArch64/addrsig-macho.ll | 13 ++
llvm/test/CodeGen/AArch64/ifunc-asm.ll | 70 ++++++
llvm/test/CodeGen/X86/ifunc-asm.ll | 60 ++++-
10 files changed, 558 insertions(+), 58 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/ifunc-asm.ll
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index cee8175a189b82..8f0c45f674ead8 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -959,10 +959,11 @@ IFuncs
-------
IFuncs, like as aliases, don't create any new data or func. They are just a new
-symbol that dynamic linker resolves at runtime by calling a resolver function.
+symbol that is resolved at runtime by calling a resolver function.
-IFuncs have a name and a resolver that is a function called by dynamic linker
-that returns address of another function associated with the name.
+On ELF platforms, IFuncs are resolved by the dynamic linker at load time. On
+Mach-O platforms, they are lowered in terms of ``.symbol_resolver`` functions,
+which lazily resolve the callee the first time they are called.
IFunc may have an optional :ref:`linkage type <linkage>` and an optional
:ref:`visibility style <visibility>`.
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index 2731ef452c79cb..5ec246ee7015c4 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -599,6 +599,26 @@ class AsmPrinter : public MachineFunctionPass {
/// instructions in verbose mode.
virtual void emitImplicitDef(const MachineInstr *MI) const;
+ /// getSubtargetInfo() cannot be used where this is needed because we don't
+ /// have a MachineFunction when we're lowering a GlobalIFunc, and
+ /// getSubtargetInfo requires one. Override the implementation in targets
+ /// that support the Mach-O IFunc lowering.
+ virtual const MCSubtargetInfo *getIFuncMCSubtargetInfo() const {
+ return nullptr;
+ }
+
+ virtual void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
+ MCSymbol *LazyPointer) {
+ llvm_unreachable(
+ "Mach-O IFunc lowering is not yet supported on this target");
+ }
+
+ virtual void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
+ MCSymbol *LazyPointer) {
+ llvm_unreachable(
+ "Mach-O IFunc lowering is not yet supported on this target");
+ }
+
/// Emit N NOP instructions.
void emitNops(unsigned N);
@@ -614,7 +634,7 @@ class AsmPrinter : public MachineFunctionPass {
StringRef Suffix) const;
/// Return the MCSymbol for the specified ExternalSymbol.
- MCSymbol *GetExternalSymbolSymbol(StringRef Sym) const;
+ MCSymbol *GetExternalSymbolSymbol(Twine Sym) const;
/// Return the symbol for the specified jump table entry.
MCSymbol *GetJTISymbol(unsigned JTID, bool isLinkerPrivate = false) const;
@@ -884,6 +904,7 @@ class AsmPrinter : public MachineFunctionPass {
void emitGlobalAlias(Module &M, const GlobalAlias &GA);
void emitGlobalIFunc(Module &M, const GlobalIFunc &GI);
+private:
/// This method decides whether the specified basic block requires a label.
bool shouldEmitLabelForBasicBlock(const MachineBasicBlock &MBB) const;
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 3a679f1576b7b6..61309c51336e52 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -59,6 +59,7 @@
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/Config/config.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Comdat.h"
@@ -2147,24 +2148,80 @@ void AsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) {
assert(!TM.getTargetTriple().isOSBinFormatXCOFF() &&
"IFunc is not supported on AIX.");
- MCSymbol *Name = getSymbol(&GI);
+ auto EmitLinkage = [&](MCSymbol *Sym) {
+ if (GI.hasExternalLinkage() || !MAI->getWeakRefDirective())
+ OutStreamer->emitSymbolAttribute(Sym, MCSA_Global);
+ else if (GI.hasWeakLinkage() || GI.hasLinkOnceLinkage())
+ OutStreamer->emitSymbolAttribute(Sym, MCSA_WeakReference);
+ else
+ assert(GI.hasLocalLinkage() && "Invalid ifunc linkage");
+ };
- if (GI.hasExternalLinkage() || !MAI->getWeakRefDirective())
- OutStreamer->emitSymbolAttribute(Name, MCSA_Global);
- else if (GI.hasWeakLinkage() || GI.hasLinkOnceLinkage())
- OutStreamer->emitSymbolAttribute(Name, MCSA_WeakReference);
- else
- assert(GI.hasLocalLinkage() && "Invalid ifunc linkage");
+ if (TM.getTargetTriple().isOSBinFormatELF()) {
+ MCSymbol *Name = getSymbol(&GI);
+ EmitLinkage(Name);
+ OutStreamer->emitSymbolAttribute(Name, MCSA_ELF_TypeIndFunction);
+ emitVisibility(Name, GI.getVisibility());
+
+ // Emit the directives as assignments aka .set:
+ const MCExpr *Expr = lowerConstant(GI.getResolver());
+ OutStreamer->emitAssignment(Name, Expr);
+ MCSymbol *LocalAlias = getSymbolPreferLocal(GI);
+ if (LocalAlias != Name)
+ OutStreamer->emitAssignment(LocalAlias, Expr);
+
+ return;
+ }
- OutStreamer->emitSymbolAttribute(Name, MCSA_ELF_TypeIndFunction);
- emitVisibility(Name, GI.getVisibility());
+ if (!TM.getTargetTriple().isOSBinFormatMachO() || !getIFuncMCSubtargetInfo())
+ llvm::report_fatal_error("IFuncs are not supported on this platform");
- // Emit the directives as assignments aka .set:
- const MCExpr *Expr = lowerConstant(GI.getResolver());
- OutStreamer->emitAssignment(Name, Expr);
- MCSymbol *LocalAlias = getSymbolPreferLocal(GI);
- if (LocalAlias != Name)
- OutStreamer->emitAssignment(LocalAlias, Expr);
+ // On Darwin platforms, emit a manually-constructed .symbol_resolver that
+ // implements the symbol resolution duties of the IFunc.
+ //
+ // Normally, this would be handled by linker magic, but unfortunately there
+ // are a few limitations in ld64 and ld-prime's implementation of
+ // .symbol_resolver that mean we can't always use them:
+ //
+ // * resolvers cannot be the target of an alias
+ // * resolvers cannot have private linkage
+ // * resolvers cannot have linkonce linkage
+ // * resolvers cannot appear in executables
+ // * resolvers cannot appear in bundles
+ //
+ // This works around that by emitting a close approximation of what the
+ // linker would have done.
+
+ MCSymbol *LazyPointer =
+ GetExternalSymbolSymbol(GI.getName() + ".lazy_pointer");
+ MCSymbol *StubHelper = GetExternalSymbolSymbol(GI.getName() + ".stub_helper");
+
+ OutStreamer->switchSection(OutContext.getObjectFileInfo()->getDataSection());
+
+ const DataLayout &DL = M.getDataLayout();
+ emitAlignment(Align(DL.getPointerSize()));
+ OutStreamer->emitLabel(LazyPointer);
+ emitVisibility(LazyPointer, GI.getVisibility());
+ OutStreamer->emitValue(MCSymbolRefExpr::create(StubHelper, OutContext), 8);
+
+ OutStreamer->switchSection(OutContext.getObjectFileInfo()->getTextSection());
+
+ const TargetSubtargetInfo *STI =
+ TM.getSubtargetImpl(*GI.getResolverFunction());
+ const TargetLowering *TLI = STI->getTargetLowering();
+ Align TextAlign(TLI->getMinFunctionAlignment());
+
+ MCSymbol *Stub = getSymbol(&GI);
+ EmitLinkage(Stub);
+ OutStreamer->emitCodeAlignment(TextAlign, getIFuncMCSubtargetInfo());
+ OutStreamer->emitLabel(Stub);
+ emitVisibility(Stub, GI.getVisibility());
+ emitMachOIFuncStubBody(M, GI, LazyPointer);
+
+ OutStreamer->emitCodeAlignment(TextAlign, getIFuncMCSubtargetInfo());
+ OutStreamer->emitLabel(StubHelper);
+ emitVisibility(StubHelper, GI.getVisibility());
+ emitMachOIFuncStubHelperBody(M, GI, LazyPointer);
}
void AsmPrinter::emitRemarksSection(remarks::RemarkStreamer &RS) {
@@ -2311,6 +2368,32 @@ bool AsmPrinter::doFinalization(Module &M) {
// through user plugins.
emitStackMaps();
+ // Print aliases in topological order, that is, for each alias a = b,
+ // b must be printed before a.
+ // This is because on some targets (e.g. PowerPC) linker expects aliases in
+ // such an order to generate correct TOC information.
+ SmallVector<const GlobalAlias *, 16> AliasStack;
+ SmallPtrSet<const GlobalAlias *, 16> AliasVisited;
+ for (const auto &Alias : M.aliases()) {
+ if (Alias.hasAvailableExternallyLinkage())
+ continue;
+ for (const GlobalAlias *Cur = &Alias; Cur;
+ Cur = dyn_cast<GlobalAlias>(Cur->getAliasee())) {
+ if (!AliasVisited.insert(Cur).second)
+ break;
+ AliasStack.push_back(Cur);
+ }
+ for (const GlobalAlias *AncestorAlias : llvm::reverse(AliasStack))
+ emitGlobalAlias(M, *AncestorAlias);
+ AliasStack.clear();
+ }
+
+ // IFuncs must come before deubginfo in case the backend decides to emit them
+ // as actual functions, since on Mach-O targets, we cannot create regular
+ // sections after DWARF.
+ for (const auto &IFunc : M.ifuncs())
+ emitGlobalIFunc(M, IFunc);
+
// Finalize debug and EH information.
for (const HandlerInfo &HI : Handlers) {
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
@@ -2350,28 +2433,6 @@ bool AsmPrinter::doFinalization(Module &M) {
}
}
- // Print aliases in topological order, that is, for each alias a = b,
- // b must be printed before a.
- // This is because on some targets (e.g. PowerPC) linker expects aliases in
- // such an order to generate correct TOC information.
- SmallVector<const GlobalAlias *, 16> AliasStack;
- SmallPtrSet<const GlobalAlias *, 16> AliasVisited;
- for (const auto &Alias : M.aliases()) {
- if (Alias.hasAvailableExternallyLinkage())
- continue;
- for (const GlobalAlias *Cur = &Alias; Cur;
- Cur = dyn_cast<GlobalAlias>(Cur->getAliasee())) {
- if (!AliasVisited.insert(Cur).second)
- break;
- AliasStack.push_back(Cur);
- }
- for (const GlobalAlias *AncestorAlias : llvm::reverse(AliasStack))
- emitGlobalAlias(M, *AncestorAlias);
- AliasStack.clear();
- }
- for (const auto &IFunc : M.ifuncs())
- emitGlobalIFunc(M, IFunc);
-
GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
assert(MI && "AsmPrinter didn't require GCModuleInfo?");
for (GCModuleInfo::iterator I = MI->end(), E = MI->begin(); I != E; )
@@ -3745,7 +3806,7 @@ MCSymbol *AsmPrinter::getSymbolWithGlobalValueBase(const GlobalValue *GV,
}
/// Return the MCSymbol for the specified ExternalSymbol.
-MCSymbol *AsmPrinter::GetExternalSymbolSymbol(StringRef Sym) const {
+MCSymbol *AsmPrinter::GetExternalSymbolSymbol(Twine Sym) const {
SmallString<60> NameStr;
Mangler::getNameWithPrefix(NameStr, Sym, getDataLayout());
return OutContext.getOrCreateSymbol(NameStr);
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index cdc556ba7df820..8aba28026306a5 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2229,13 +2229,11 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
}
// Check EVEX512 feature.
- if (MaxParameterWidth >= 512 && Attrs.hasFnAttr("target-features")) {
- Triple T(M.getTargetTriple());
- if (T.isX86()) {
- StringRef TF = Attrs.getFnAttr("target-features").getValueAsString();
- Check(!TF.contains("+avx512f") || !TF.contains("-evex512"),
- "512-bit vector arguments require 'evex512' for AVX512", V);
- }
+ if (MaxParameterWidth >= 512 && Attrs.hasFnAttr("target-features") &&
+ TT.isX86()) {
+ StringRef TF = Attrs.getFnAttr("target-features").getValueAsString();
+ Check(!TF.contains("+avx512f") || !TF.contains("-evex512"),
+ "512-bit vector arguments require 'evex512' for AVX512", V);
}
checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-prefix", V);
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index f4d3a85f34c88d..90e1ce9ddf66b0 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -30,6 +30,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/BinaryFormat/MachO.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/FaultMaps.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
@@ -47,10 +48,12 @@
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
@@ -198,6 +201,15 @@ class AArch64AsmPrinter : public AsmPrinter {
bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags() const override {
return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
}
+
+ const MCSubtargetInfo *getIFuncMCSubtargetInfo() const override {
+ assert(STI);
+ return STI;
+ }
+ void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
+ MCSymbol *LazyPointer) override;
+ void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
+ MCSymbol *LazyPointer) override;
};
} // end anonymous namespace
@@ -1809,6 +1821,201 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, TmpInst);
}
+void AArch64AsmPrinter::emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
+ MCSymbol *LazyPointer) {
+ // _ifunc:
+ // adrp x16, lazy_pointer at GOTPAGE
+ // ldr x16, [x16, lazy_pointer at GOTPAGEOFF]
+ // ldr x16, [x16]
+ // br x16
+
+ {
+ MCInst Adrp;
+ Adrp.setOpcode(AArch64::ADRP);
+ Adrp.addOperand(MCOperand::createReg(AArch64::X16));
+ MCOperand SymPage;
+ MCInstLowering.lowerOperand(
+ MachineOperand::CreateMCSymbol(LazyPointer,
+ AArch64II::MO_GOT | AArch64II::MO_PAGE),
+ SymPage);
+ Adrp.addOperand(SymPage);
+ OutStreamer->emitInstruction(Adrp, *STI);
+ }
+
+ {
+ MCInst Ldr;
+ Ldr.setOpcode(AArch64::LDRXui);
+ Ldr.addOperand(MCOperand::createReg(AArch64::X16));
+ Ldr.addOperand(MCOperand::createReg(AArch64::X16));
+ MCOperand SymPageOff;
+ MCInstLowering.lowerOperand(
+ MachineOperand::CreateMCSymbol(LazyPointer, AArch64II::MO_GOT |
+ AArch64II::MO_PAGEOFF),
+ SymPageOff);
+ Ldr.addOperand(SymPageOff);
+ Ldr.addOperand(MCOperand::createImm(0));
+ OutStreamer->emitInstruction(Ldr, *STI);
+ }
+
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::LDRXui)
+ .addReg(AArch64::X16)
+ .addReg(AArch64::X16)
+ .addImm(0),
+ *STI);
+
+ OutStreamer->emitInstruction(MCInstBuilder(TM.getTargetTriple().isArm64e()
+ ? AArch64::BRAAZ
+ : AArch64::BR)
+ .addReg(AArch64::X16),
+ *STI);
+}
+
+void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
+ const GlobalIFunc &GI,
+ MCSymbol *LazyPointer) {
+ // These stub helpers are only ever called once, so here we're optimizing for
+ // minimum size by using the pre-indexed store variants, which saves a few
+ // bytes of instructions to bump & restore sp.
+
+ // _ifunc.stub_helper:
+ // stp fp, lr, [sp, #-16]!
+ // mov fp, sp
+ // stp x1, x0, [sp, #-16]!
+ // stp x3, x2, [sp, #-16]!
+ // stp x5, x4, [sp, #-16]!
+ // stp x7, x6, [sp, #-16]!
+ // stp d1, d0, [sp, #-16]!
+ // stp d3, d2, [sp, #-16]!
+ // stp d5, d4, [sp, #-16]!
+ // stp d7, d6, [sp, #-16]!
+ // bl _resolver
+ // adrp x16, lazy_pointer at GOTPAGE
+ // ldr x16, [x16, lazy_pointer at GOTPAGEOFF]
+ // str x0, [x16]
+ // mov x16, x0
+ // ldp d7, d6, [sp], #16
+ // ldp d5, d4, [sp], #16
+ // ldp d3, d2, [sp], #16
+ // ldp d1, d0, [sp], #16
+ // ldp x7, x6, [sp], #16
+ // ldp x5, x4, [sp], #16
+ // ldp x3, x2, [sp], #16
+ // ldp x1, x0, [sp], #16
+ // ldp fp, lr, [sp], #16
+ // br x16
+
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::STPXpre)
+ .addReg(AArch64::SP)
+ .addReg(AArch64::FP)
+ .addReg(AArch64::LR)
+ .addReg(AArch64::SP)
+ .addImm(-2),
+ *STI);
+
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::ADDXri)
+ .addReg(AArch64::FP)
+ .addReg(AArch64::SP)
+ .addImm(0)
+ .addImm(0),
+ *STI);
+
+ for (int I = 0; I != 4; ++I)
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::STPXpre)
+ .addReg(AArch64::SP)
+ .addReg(AArch64::X1 + 2 * I)
+ .addReg(AArch64::X0 + 2 * I)
+ .addReg(AArch64::SP)
+ .addImm(-2),
+ *STI);
+
+ for (int I = 0; I != 4; ++I)
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::STPDpre)
+ .addReg(AArch64::SP)
+ .addReg(AArch64::D1 + 2 * I)
+ .addReg(AArch64::D0 + 2 * I)
+ .addReg(AArch64::SP)
+ .addImm(-2),
+ *STI);
+
+ OutStreamer->emitInstruction(
+ MCInstBuilder(AArch64::BL)
+ .addOperand(MCOperand::createExpr(lowerConstant(GI.getResolver()))),
+ *STI);
+
+ {
+ MCInst Adrp;
+ Adrp.setOpcode(AArch64::ADRP);
+ Adrp.addOperand(MCOperand::createReg(AArch64::X16));
+ MCOperand SymPage;
+ MCInstLowering.lowerOperand(
+ MachineOperand::CreateES(LazyPointer->getName().data() + 1,
+ AArch64II::MO_GOT | AArch64II::MO_PAGE),
+ SymPage);
+ Adrp.addOperand(SymPage);
+ OutStreamer->emitInstruction(Adrp, *STI);
+ }
+
+ {
+ MCInst Ldr;
+ Ldr.setOpcode(AArch64::LDRXui);
+ Ldr.addOperand(MCOperand::createReg(AArch64::X16));
+ Ldr.addOperand(MCOperand::createReg(AArch64::X16));
+ MCOperand SymPageOff;
+ MCInstLowering.lowerOperand(
+ MachineOperand::CreateES(LazyPointer->getName().data() + 1,
+ AArch64II::MO_GOT | AArch64II::MO_PAGEOFF),
+ SymPageOff);
+ Ldr.addOperand(SymPageOff);
+ Ldr.addOperand(MCOperand::createImm(0));
+ OutStreamer->emitInstruction(Ldr, *STI);
+ }
+
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::STRXui)
+ .addReg(AArch64::X0)
+ .addReg(AArch64::X16)
+ .addImm(0),
+ *STI);
+
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::ADDXri)
+ .addReg(AArch64::X16)
+ .addReg(AArch64::X0)
+ .addImm(0)
+ .addImm(0),
+ *STI);
+
+ for (int I = 3; I != -1; --I)
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::LDPDpost)
+ .addReg(AArch64::SP)
+ .addReg(AArch64::D1 + 2 * I)
+ .addReg(AArch64::D0 + 2 * I)
+ .addReg(AArch64::SP)
+ .addImm(2),
+ *STI);
+
+ for (int I = 3; I != -1; --I)
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::LDPXpost)
+ .addReg(AArch64::SP)
+ .addReg(AArch64::X1 + 2 * I)
+ .addReg(AArch64::X0 + 2 * I)
+ .addReg(AArch64::SP)
+ .addImm(2),
+ *STI);
+
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::LDPXpost)
+ .addReg(AArch64::SP)
+ .addReg(AArch64::FP)
+ .addReg(AArch64::LR)
+ .addReg(AArch64::SP)
+ .addImm(2),
+ *STI);
+
+ OutStreamer->emitInstruction(MCInstBuilder(TM.getTargetTriple().isArm64e()
+ ? AArch64::BRAAZ
+ : AArch64::BR)
+ .addReg(AArch64::X16),
+ *STI);
+}
+
// Force static initialization.
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAArch64AsmPrinter() {
RegisterAsmPrinter<AArch64AsmPrinter> X(getTheAArch64leTarget());
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp
index 73c7450620966c..15cfd247f125ca 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.cpp
+++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp
@@ -14,6 +14,7 @@
#include "X86AsmPrinter.h"
#include "MCTargetDesc/X86ATTInstPrinter.h"
#include "MCTargetDesc/X86BaseInfo.h"
+#include "MCTargetDesc/X86MCTargetDesc.h"
#include "MCTargetDesc/X86TargetStreamer.h"
#include "TargetInfo/X86TargetInfo.h"
#include "X86InstrInfo.h"
@@ -34,6 +35,7 @@
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSectionELF.h"
@@ -530,6 +532,86 @@ void X86AsmPrinter::PrintIntelMemReference(const MachineInstr *MI,
O << ']';
}
+const MCSubtargetInfo *X86AsmPrinter::getIFuncMCSubtargetInfo() const {
+ assert(Subtarget);
+ return Subtarget;
+}
+
+void X86AsmPrinter::emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
+ MCSymbol *LazyPointer) {
+ // _ifunc:
+ // jmpq *lazy_pointer(%rip)
+
+ OutStreamer->emitInstruction(
+ MCInstBuilder(X86::JMP32m)
+ .addReg(X86::RIP)
+ .addImm(1)
+ .addReg(0)
+ .addOperand(MCOperand::createExpr(
+ MCSymbolRefExpr::create(LazyPointer, OutContext)))
+ .addReg(0),
+ *Subtarget);
+}
+
+void X86AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
+ const GlobalIFunc &GI,
+ MCSymbol *LazyPointer) {
+ // _ifunc.stub_helper:
+ // push %rax
+ // push %rdi
+ // push %rsi
+ // push %rdx
+ // push %rcx
+ // push %r8
+ // push %r9
+ // callq foo
+ // movq %rax,lazy_pointer(%rip)
+ // pop %r9
+ // pop %r8
+ // pop %rcx
+ // pop %rdx
+ // pop %rsi
+ // pop %rdi
+ // pop %rax
+ // jmpq *lazy_pointer(%rip)
+
+ for (int Reg :
+ {X86::RAX, X86::RDI, X86::RSI, X86::RDX, X86::RCX, X86::R8, X86::R9})
+ OutStreamer->emitInstruction(MCInstBuilder(X86::PUSH64r).addReg(Reg),
+ *Subtarget);
+
+ OutStreamer->emitInstruction(
+ MCInstBuilder(X86::CALL64pcrel32)
+ .addOperand(MCOperand::createExpr(lowerConstant(GI.getResolver()))),
+ *Subtarget);
+
+ OutStreamer->emitInstruction(
+ MCInstBuilder(X86::MOV64mr)
+ .addReg(X86::RIP)
+ .addImm(1)
+ .addReg(0)
+ .addOperand(MCOperand::createExpr(
+ MCSymbolRefExpr::create(LazyPointer, OutContext)))
+ .addReg(0)
+ .addReg(X86::RAX),
+ *Subtarget);
+
+ for (int Reg :
+ {X86::R9, X86::R8, X86::RCX, X86::RDX, X86::RSI, X86::RDI, X86::RAX})
+ OutStreamer->emitInstruction(MCInstBuilder(X86::POP64r).addReg(Reg),
+ *Subtarget);
+
+ OutStreamer->emitInstruction(
+ MCInstBuilder(X86::JMP32m)
+ .addReg(X86::RIP)
+ .addImm(1)
+ .addReg(0)
+ .addOperand(MCOperand::createExpr(
+ MCSymbolRefExpr::create(LazyPointer, OutContext)))
+ .addReg(0),
+ *Subtarget);
+}
+
static bool printAsmMRegister(const X86AsmPrinter &P, const MachineOperand &MO,
char Mode, raw_ostream &O) {
Register Reg = MO.getReg();
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.h b/llvm/lib/Target/X86/X86AsmPrinter.h
index c81651cf7f2f0e..693021eca32958 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.h
+++ b/llvm/lib/Target/X86/X86AsmPrinter.h
@@ -120,6 +120,11 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
const char *Modifier);
void PrintIntelMemReference(const MachineInstr *MI, unsigned OpNo,
raw_ostream &O, const char *Modifier);
+ const MCSubtargetInfo *getIFuncMCSubtargetInfo() const override;
+ void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
+ MCSymbol *LazyPointer) override;
+ void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
+ MCSymbol *LazyPointer) override;
public:
X86AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer);
diff --git a/llvm/test/CodeGen/AArch64/addrsig-macho.ll b/llvm/test/CodeGen/AArch64/addrsig-macho.ll
index 360876fccaad34..62bc764e0251b3 100644
--- a/llvm/test/CodeGen/AArch64/addrsig-macho.ll
+++ b/llvm/test/CodeGen/AArch64/addrsig-macho.ll
@@ -3,6 +3,19 @@
; RUN: llvm-objdump --macho --section-headers %t | FileCheck %s --check-prefix=SECTIONS
; RUN: llvm-objdump --macho --reloc %t | FileCheck %s --check-prefix=RELOCS
+; CHECK: .section __DATA,__data
+; CHECK: _i1.lazy_pointer:
+; CHECK: .section __TEXT,__text,regular,pure_instructions
+; CHECK: _i1:
+; CHECK: _i1.stub_helper:
+; CHECK: .section __DATA,__data
+; CHECK: _i2.lazy_pointer:
+; CHECK: .section __TEXT,__text,regular,pure_instructions
+; CHECK: _i2:
+; CHECK: _i2.stub_helper:
+
+; CHECK: .section __DWARF
+
; CHECK: .addrsig{{$}}
; CHECK-NEXT: .addrsig_sym _func03_takeaddr
; CHECK-NEXT: .addrsig_sym _f1
diff --git a/llvm/test/CodeGen/AArch64/ifunc-asm.ll b/llvm/test/CodeGen/AArch64/ifunc-asm.ll
new file mode 100644
index 00000000000000..57fc2f0c9d7f5c
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ifunc-asm.ll
@@ -0,0 +1,70 @@
+; RUN: llc -mtriple=arm64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefixes=ELF
+; RUN: llc -mtriple=arm64-apple-darwin %s -o - | FileCheck %s --check-prefix=MACHO
+; RUN: llc -mtriple=arm64-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefix=MACHO
+
+define internal ptr @the_resolver() {
+entry:
+ ret ptr null
+}
+; ELF: .type the_resolver, at function
+; ELF-NEXT: the_resolver:
+
+; MACHO: .p2align 2
+; MACHO-NEXT: _the_resolver:
+
+
+ at global_ifunc = ifunc i32 (i32), ptr @the_resolver
+; ELF: .globl global_ifunc
+; ELF-NEXT: .type global_ifunc, at gnu_indirect_function
+; ELF-NEXT: .set global_ifunc, the_resolver
+
+; MACHO: .section __DATA,__data
+; MACHO-NEXT: .p2align 3, 0x0
+; MACHO-NEXT: _global_ifunc.lazy_pointer:
+; MACHO-NEXT: .quad _global_ifunc.stub_helper
+
+; MACHO: .section __TEXT,__text,regular,pure_instructions
+; MACHO-NEXT: .globl _global_ifunc
+; MACHO-NEXT: .p2align 2
+; MACHO-NEXT: _global_ifunc:
+; MACHO-NEXT: adrp x16, _global_ifunc.lazy_pointer at GOTPAGE
+; MACHO-NEXT: ldr x16, [x16, _global_ifunc.lazy_pointer at GOTPAGEOFF]
+; MACHO-NEXT: ldr x16, [x16]
+; MACHO-NEXT: br x16
+; MACHO-NEXT: .p2align 2
+; MACHO-NEXT: _global_ifunc.stub_helper:
+; MACHO-NEXT: stp x29, x30, [sp, #-16]!
+; MACHO-NEXT: mov x29, sp
+; MACHO-NEXT: stp x1, x0, [sp, #-16]!
+; MACHO-NEXT: stp x3, x2, [sp, #-16]!
+; MACHO-NEXT: stp x5, x4, [sp, #-16]!
+; MACHO-NEXT: stp x7, x6, [sp, #-16]!
+; MACHO-NEXT: stp d1, d0, [sp, #-16]!
+; MACHO-NEXT: stp d3, d2, [sp, #-16]!
+; MACHO-NEXT: stp d5, d4, [sp, #-16]!
+; MACHO-NEXT: stp d7, d6, [sp, #-16]!
+; MACHO-NEXT: bl _the_resolver
+; MACHO-NEXT: adrp x16, _global_ifunc.lazy_pointer at GOTPAGE
+; MACHO-NEXT: ldr x16, [x16, _global_ifunc.lazy_pointer at GOTPAGEOFF]
+; MACHO-NEXT: str x0, [x16]
+; MACHO-NEXT: add x16, x0, #0
+; MACHO-NEXT: ldp d7, d6, [sp], #16
+; MACHO-NEXT: ldp d5, d4, [sp], #16
+; MACHO-NEXT: ldp d3, d2, [sp], #16
+; MACHO-NEXT: ldp d1, d0, [sp], #16
+; MACHO-NEXT: ldp x7, x6, [sp], #16
+; MACHO-NEXT: ldp x5, x4, [sp], #16
+; MACHO-NEXT: ldp x3, x2, [sp], #16
+; MACHO-NEXT: ldp x1, x0, [sp], #16
+; MACHO-NEXT: ldp x29, x30, [sp], #16
+; MACHO-NEXT: br x16
+
+
+ at weak_ifunc = weak ifunc i32 (i32), ptr @the_resolver
+; ELF: .type weak_ifunc, at gnu_indirect_function
+; MACHO-NOT: .weak_reference _weak_ifunc.lazy_pointer
+; MACHO: _weak_ifunc.lazy_pointer:
+; MACHO: .weak_reference _weak_ifunc
+; MACHO: _weak_ifunc:
+; MACHO-NOT: .weak_reference _weak_ifunc.stub_helper
+; MACHO: _weak_ifunc.stub_helper:
\ No newline at end of file
diff --git a/llvm/test/CodeGen/X86/ifunc-asm.ll b/llvm/test/CodeGen/X86/ifunc-asm.ll
index 4b380c8ae33013..6cfd37604ff5e1 100644
--- a/llvm/test/CodeGen/X86/ifunc-asm.ll
+++ b/llvm/test/CodeGen/X86/ifunc-asm.ll
@@ -1,14 +1,56 @@
-; RUN: llvm-as < %s -o - | llc -filetype=asm | FileCheck %s
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefixes=ELF
+; RUN: llc -mtriple=x86_64-apple-darwin %s -o - | FileCheck %s --check-prefixes=MACHO
-target triple = "x86_64-unknown-linux-gnu"
-
-define internal ptr @foo_ifunc() {
+define internal ptr @foo_resolver() {
entry:
ret ptr null
}
-; CHECK: .type foo_ifunc, at function
-; CHECK-NEXT: foo_ifunc:
+; ELF: .type foo_resolver, at function
+; ELF-NEXT: foo_resolver:
+
+; MACHO: .p2align 4, 0x90
+; MACHO-NEXT: _foo_resolver
+
+
+ at foo_ifunc = ifunc i32 (i32), ptr @foo_resolver
+; ELF: .globl foo_ifunc
+; ELF-NEXT: .type foo_ifunc, at gnu_indirect_function
+; ELF-NEXT: .set foo_ifunc, foo_resolver
+
+; MACHO: .section __DATA,__data
+; MACHO-NEXT: .p2align 3, 0x0
+; MACHO-NEXT: _foo_ifunc.lazy_pointer:
+; MACHO-NEXT: .quad _foo_ifunc.stub_helper
+; MACHO-NEXT: .section __TEXT,__text,regular,pure_instructions
+; MACHO-NEXT: .globl _foo_ifunc
+; MACHO-NEXT: .p2align 0, 0x90
+; MACHO-NEXT: _foo_ifunc:
+; MACHO-NEXT: jmpl *_foo_ifunc.lazy_pointer(%rip)
+; MACHO-NEXT: .p2align 0, 0x90
+; MACHO-NEXT: _foo_ifunc.stub_helper:
+; MACHO-NEXT: pushq %rax
+; MACHO-NEXT: pushq %rdi
+; MACHO-NEXT: pushq %rsi
+; MACHO-NEXT: pushq %rdx
+; MACHO-NEXT: pushq %rcx
+; MACHO-NEXT: pushq %r8
+; MACHO-NEXT: pushq %r9
+; MACHO-NEXT: callq _foo_resolver
+; MACHO-NEXT: movq %rax, _foo_ifunc.lazy_pointer(%rip)
+; MACHO-NEXT: popq %r9
+; MACHO-NEXT: popq %r8
+; MACHO-NEXT: popq %rcx
+; MACHO-NEXT: popq %rdx
+; MACHO-NEXT: popq %rsi
+; MACHO-NEXT: popq %rdi
+; MACHO-NEXT: popq %rax
+; MACHO-NEXT: jmpl *_foo_ifunc.lazy_pointer(%rip)
- at foo = ifunc i32 (i32), ptr @foo_ifunc
-; CHECK: .type foo, at gnu_indirect_function
-; CHECK-NEXT: .set foo, foo_ifunc
+ at weak_ifunc = weak ifunc i32 (i32), ptr @foo_resolver
+; ELF: .type weak_ifunc, at gnu_indirect_function
+; MACHO-NOT: .weak_reference _weak_ifunc.lazy_pointer
+; MACHO: _weak_ifunc.lazy_pointer:
+; MACHO: .weak_reference _weak_ifunc
+; MACHO: _weak_ifunc:
+; MACHO-NOT: .weak_reference _weak_ifunc.stub_helper
+; MACHO: _weak_ifunc.stub_helper:
More information about the llvm-branch-commits
mailing list