Skip to content

[clang][ARM][AArch64] Reapply "Define intrinsics guarded by __has_builtin on all platforms (#128222)" #140910

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 4, 2025

Conversation

sarnex
Copy link
Member

@sarnex sarnex commented May 21, 2025

The original change caused issues on MSVC due to a new warning thrown inside MSVC headers. That was fixed here, so reapply this commit. Original description below.

Instead of defining ARM ACLE intrinsics only on MSVC and guarding wrapper functions in headers with __has_builtin, universally define the intrinsics as target header builtins.

@sarnex sarnex marked this pull request as ready for review May 21, 2025 17:57
@sarnex sarnex requested review from rnk and Artem-B May 21, 2025 17:58
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:ARM backend:AArch64 backend:X86 clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:headers Headers provided by Clang, e.g. for intrinsics labels May 21, 2025
@llvmbot
Copy link
Member

llvmbot commented May 21, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-backend-x86

Author: Nick Sarnie (sarnex)

Changes

The original change caused issues on MSVC due to a new warning thrown inside MSVC headers. That was fixed here, so reapply this commit. Original description below.

Instead of defining ARM ACLE intrinsics only on MSVC and guarding wrapper functions in headers with __has_builtin, universally define the intrinsics as target header builtins.


Full diff: https://github.com/llvm/llvm-project/pull/140910.diff

14 Files Affected:

  • (modified) clang/include/clang/Basic/BuiltinHeaders.def (+1)
  • (modified) clang/include/clang/Basic/BuiltinsAArch64.def (+8-10)
  • (modified) clang/include/clang/Basic/BuiltinsARM.def (+8-9)
  • (modified) clang/lib/Headers/arm_acle.h (+8-44)
  • (modified) clang/lib/Sema/SemaARM.cpp (+6)
  • (added) clang/test/CodeGen/arm-former-microsoft-intrinsics-header-warning.c (+50)
  • (added) clang/test/CodeGen/arm-former-microsoft-intrinsics.c (+53)
  • (modified) clang/test/CodeGen/arm-microsoft-intrinsics.c (-21)
  • (added) clang/test/CodeGen/arm64-former-microsoft-intrinsics-header-warning.c (+53)
  • (added) clang/test/CodeGen/arm64-former-microsoft-intrinsics.c (+59)
  • (modified) clang/test/CodeGen/arm64-microsoft-intrinsics.c (-56)
  • (modified) clang/test/CodeGen/builtins-arm-microsoft.c (+7-5)
  • (modified) clang/test/Headers/Inputs/include/stdint.h (+12)
  • (modified) clang/test/Headers/ms-intrin.cpp (+4)
diff --git a/clang/include/clang/Basic/BuiltinHeaders.def b/clang/include/clang/Basic/BuiltinHeaders.def
index 8e4a2f9bee9aa..22668ec7a3396 100644
--- a/clang/include/clang/Basic/BuiltinHeaders.def
+++ b/clang/include/clang/Basic/BuiltinHeaders.def
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 HEADER(NO_HEADER, nullptr)
+HEADER(ARMACLE_H, "arm_acle.h")
 HEADER(BLOCKS_H, "Blocks.h")
 HEADER(COMPLEX_H, "complex.h")
 HEADER(CTYPE_H, "ctype.h")
diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def
index 0b2dba86d9930..8867a9fe09fb9 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -50,6 +50,11 @@ BUILTIN(__builtin_arm_wfi, "v", "")
 BUILTIN(__builtin_arm_sev, "v", "")
 BUILTIN(__builtin_arm_sevl, "v", "")
 BUILTIN(__builtin_arm_chkfeat, "WUiWUi", "")
+TARGET_HEADER_BUILTIN(__yield, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__wfe,   "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__wfi,   "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__sev,   "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__sevl,  "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
 
 // Like __builtin_trap but provide an 16-bit immediate reason code (which goes into `brk #N`).
 BUILTIN(__builtin_arm_trap, "vUIs", "nr")
@@ -82,6 +87,9 @@ TARGET_BUILTIN(__builtin_arm_mops_memset_tag, "v*v*iz", "", "mte,mops")
 BUILTIN(__builtin_arm_dmb, "vUi", "nc")
 BUILTIN(__builtin_arm_dsb, "vUi", "nc")
 BUILTIN(__builtin_arm_isb, "vUi", "nc")
+TARGET_HEADER_BUILTIN(__dmb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__dsb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__isb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
 
 TARGET_BUILTIN(__builtin_arm_jcvt, "Zid", "nc", "v8.3a")
 
@@ -98,16 +106,6 @@ BUILTIN(__builtin_arm_wsr64, "vcC*WUi", "nc")
 TARGET_BUILTIN(__builtin_arm_wsr128, "vcC*LLLUi", "nc", "d128")
 BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
 
-// MSVC
-LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__yield, "v", "",   ALL_MS_LANGUAGES)
-LANGBUILTIN(__wfe,   "v", "",   ALL_MS_LANGUAGES)
-LANGBUILTIN(__wfi,   "v", "",   ALL_MS_LANGUAGES)
-LANGBUILTIN(__sev,   "v", "",   ALL_MS_LANGUAGES)
-LANGBUILTIN(__sevl,  "v", "",   ALL_MS_LANGUAGES)
-
 // Misc
 BUILTIN(__builtin_sponentry, "v*", "c")
 
diff --git a/clang/include/clang/Basic/BuiltinsARM.def b/clang/include/clang/Basic/BuiltinsARM.def
index cbab87cecbc7d..2592e25e95c37 100644
--- a/clang/include/clang/Basic/BuiltinsARM.def
+++ b/clang/include/clang/Basic/BuiltinsARM.def
@@ -186,11 +186,19 @@ BUILTIN(__builtin_arm_wfi, "v", "")
 BUILTIN(__builtin_arm_sev, "v", "")
 BUILTIN(__builtin_arm_sevl, "v", "")
 BUILTIN(__builtin_arm_dbg, "vUi", "")
+TARGET_HEADER_BUILTIN(__yield, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__wfe, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__wfi, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__sev, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__sevl, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
 
 // Data barrier
 BUILTIN(__builtin_arm_dmb, "vUi", "nc")
 BUILTIN(__builtin_arm_dsb, "vUi", "nc")
 BUILTIN(__builtin_arm_isb, "vUi", "nc")
+TARGET_HEADER_BUILTIN(__dmb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__dsb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__isb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
 
 // Prefetch
 BUILTIN(__builtin_arm_prefetch, "vvC*UiUi", "nc")
@@ -209,15 +217,6 @@ BUILTIN(__builtin_sponentry, "v*", "c")
 // MSVC
 LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES)
 
-LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES)
-LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES)
-LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES)
-LANGBUILTIN(__sev, "v", "", ALL_MS_LANGUAGES)
-LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES)
-
-LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES)
 LANGBUILTIN(__ldrexd, "WiWiCD*", "", ALL_MS_LANGUAGES)
 LANGBUILTIN(_MoveFromCoprocessor, "UiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
 LANGBUILTIN(_MoveFromCoprocessor2, "UiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
diff --git a/clang/lib/Headers/arm_acle.h b/clang/lib/Headers/arm_acle.h
index a7a62b69e0468..5cfa3d023a7d5 100644
--- a/clang/lib/Headers/arm_acle.h
+++ b/clang/lib/Headers/arm_acle.h
@@ -29,52 +29,16 @@ extern "C" {
 
 /* 7 SYNCHRONIZATION, BARRIER AND HINT INTRINSICS */
 /* 7.3 Memory barriers */
-#if !__has_builtin(__dmb)
-#define __dmb(i) __builtin_arm_dmb(i)
-#endif
-#if !__has_builtin(__dsb)
-#define __dsb(i) __builtin_arm_dsb(i)
-#endif
-#if !__has_builtin(__isb)
-#define __isb(i) __builtin_arm_isb(i)
-#endif
+void __dmb(unsigned int);
+void __dsb(unsigned int);
+void __isb(unsigned int);
 
 /* 7.4 Hints */
-
-#if !__has_builtin(__wfi)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__wfi(void) {
-  __builtin_arm_wfi();
-}
-#endif
-
-#if !__has_builtin(__wfe)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__wfe(void) {
-  __builtin_arm_wfe();
-}
-#endif
-
-#if !__has_builtin(__sev)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__sev(void) {
-  __builtin_arm_sev();
-}
-#endif
-
-#if !__has_builtin(__sevl)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__sevl(void) {
-  __builtin_arm_sevl();
-}
-#endif
-
-#if !__has_builtin(__yield)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__yield(void) {
-  __builtin_arm_yield();
-}
-#endif
+void __wfi(void);
+void __wfe(void);
+void __sev(void);
+void __sevl(void);
+void __yield(void);
 
 #if defined(__ARM_32BIT_STATE) && __ARM_32BIT_STATE
 #define __dbg(t) __builtin_arm_dbg(t)
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index 146cd78195663..e992a1012fde0 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -1010,8 +1010,11 @@ bool SemaARM::CheckARMBuiltinFunctionCall(const TargetInfo &TI,
   case ARM::BI__builtin_arm_vcvtr_d:
     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
   case ARM::BI__builtin_arm_dmb:
+  case ARM::BI__dmb:
   case ARM::BI__builtin_arm_dsb:
+  case ARM::BI__dsb:
   case ARM::BI__builtin_arm_isb:
+  case ARM::BI__isb:
   case ARM::BI__builtin_arm_dbg:
     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15);
   case ARM::BI__builtin_arm_cdp:
@@ -1108,8 +1111,11 @@ bool SemaARM::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI,
   switch (BuiltinID) {
   default: return false;
   case AArch64::BI__builtin_arm_dmb:
+  case AArch64::BI__dmb:
   case AArch64::BI__builtin_arm_dsb:
+  case AArch64::BI__dsb:
   case AArch64::BI__builtin_arm_isb:
+  case AArch64::BI__isb:
     l = 0;
     u = 15;
     break;
diff --git a/clang/test/CodeGen/arm-former-microsoft-intrinsics-header-warning.c b/clang/test/CodeGen/arm-former-microsoft-intrinsics-header-warning.c
new file mode 100644
index 0000000000000..8edcbbeb0375d
--- /dev/null
+++ b/clang/test/CodeGen/arm-former-microsoft-intrinsics-header-warning.c
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -triple thumbv7-windows -fms-compatibility -Wno-everything -Wimplicit-function-declaration -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple armv7-eabi -Wno-everything -Wimplicit-function-declaration -fsyntax-only -verify %s
+
+void check__dmb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __dmb(0);
+}
+
+void check__dsb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __dsb(0);
+}
+
+void check__isb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __isb(0);
+}
+
+void check__yield(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __yield();
+}
+
+void check__wfe(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __wfe();
+}
+
+void check__wfi(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __wfi();
+}
+
+void check__sev(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __sev();
+}
+
+void check__sevl(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __sevl();
+}
diff --git a/clang/test/CodeGen/arm-former-microsoft-intrinsics.c b/clang/test/CodeGen/arm-former-microsoft-intrinsics.c
new file mode 100644
index 0000000000000..8a02602dc9876
--- /dev/null
+++ b/clang/test/CodeGen/arm-former-microsoft-intrinsics.c
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple thumbv7-windows -fms-compatibility -emit-llvm -o - %s \
+// RUN:    | FileCheck %s
+
+// RUN: %clang_cc1 -triple armv7-eabi -Werror -emit-llvm -o - %s \
+// RUN:    | FileCheck %s
+#include <arm_acle.h>
+void check__dmb(void) {
+  __dmb(0);
+}
+
+// CHECK: @llvm.arm.dmb(i32 0)
+
+void check__dsb(void) {
+  __dsb(0);
+}
+
+// CHECK: @llvm.arm.dsb(i32 0)
+
+void check__isb(void) {
+  __isb(0);
+}
+
+// CHECK: @llvm.arm.isb(i32 0)
+
+void check__yield(void) {
+  __yield();
+}
+
+// CHECK: @llvm.arm.hint(i32 1)
+
+void check__wfe(void) {
+  __wfe();
+}
+
+// CHECK: @llvm.arm.hint(i32 2)
+
+void check__wfi(void) {
+  __wfi();
+}
+
+// CHECK: @llvm.arm.hint(i32 3)
+
+void check__sev(void) {
+  __sev();
+}
+
+// CHECK: @llvm.arm.hint(i32 4)
+
+void check__sevl(void) {
+  __sevl();
+}
+
+// CHECK: @llvm.arm.hint(i32 5)
diff --git a/clang/test/CodeGen/arm-microsoft-intrinsics.c b/clang/test/CodeGen/arm-microsoft-intrinsics.c
index 6793b3879eede..a5f3e2c719227 100644
--- a/clang/test/CodeGen/arm-microsoft-intrinsics.c
+++ b/clang/test/CodeGen/arm-microsoft-intrinsics.c
@@ -4,27 +4,6 @@
 // RUN: not %clang_cc1 -triple armv7-eabi -Werror -S -o /dev/null %s 2>&1 \
 // RUN:    | FileCheck %s -check-prefix CHECK-EABI
 
-void check__dmb(void) {
-  __dmb(0);
-}
-
-// CHECK-MSVC: @llvm.arm.dmb(i32 0)
-// CHECK-EABI: error: call to undeclared function '__dmb'
-
-void check__dsb(void) {
-  __dsb(0);
-}
-
-// CHECK-MSVC: @llvm.arm.dsb(i32 0)
-// CHECK-EABI: error: call to undeclared function '__dsb'
-
-void check__isb(void) {
-  __isb(0);
-}
-
-// CHECK-MSVC: @llvm.arm.isb(i32 0)
-// CHECK-EABI: error: call to undeclared function '__isb'
-
 __INT64_TYPE__ check__ldrexd(void) {
   __INT64_TYPE__ i64;
   return __ldrexd(&i64);
diff --git a/clang/test/CodeGen/arm64-former-microsoft-intrinsics-header-warning.c b/clang/test/CodeGen/arm64-former-microsoft-intrinsics-header-warning.c
new file mode 100644
index 0000000000000..52fed49db4dd2
--- /dev/null
+++ b/clang/test/CodeGen/arm64-former-microsoft-intrinsics-header-warning.c
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple arm64-windows -Wno-everything -Wimplicit-function-declaration -fms-compatibility -fsyntax-only -verify %s
+
+// RUN: %clang_cc1 -triple arm64-linux -Wno-everything -Wimplicit-function-declaration -fsyntax-only -verify %s
+
+// RUN: %clang_cc1 -triple arm64-darwin -Wno-everything -Wimplicit-function-declaration -fms-compatibility -fsyntax-only -verify %s
+
+void check__dmb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __dmb(0);
+}
+
+void check__dsb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __dsb(0);
+}
+
+void check__isb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __isb(0);
+}
+
+void check__yield(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __yield();
+}
+
+void check__wfe(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __wfe();
+}
+
+void check__wfi(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __wfi();
+}
+
+void check__sev(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __sev();
+}
+
+void check__sevl(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __sevl();
+}
diff --git a/clang/test/CodeGen/arm64-former-microsoft-intrinsics.c b/clang/test/CodeGen/arm64-former-microsoft-intrinsics.c
new file mode 100644
index 0000000000000..f1d9af2c6d25e
--- /dev/null
+++ b/clang/test/CodeGen/arm64-former-microsoft-intrinsics.c
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -triple arm64-windows -Wno-implicit-function-declaration -fms-compatibility -emit-llvm -o - %s \
+// RUN:    | FileCheck %s
+
+// RUN: %clang_cc1 -triple arm64-linux -Werror -emit-llvm -o - %s 2>&1 \
+// RUN:    | FileCheck %s
+
+// RUN: %clang_cc1 -triple arm64-darwin -Wno-implicit-function-declaration -fms-compatibility -emit-llvm -o - %s \
+// RUN:    | FileCheck %s
+
+#include <arm_acle.h>
+
+void check__dmb(void) {
+  __dmb(0);
+}
+
+// CHECK: @llvm.aarch64.dmb(i32 0)
+
+void check__dsb(void) {
+  __dsb(0);
+}
+
+// CHECK: @llvm.aarch64.dsb(i32 0)
+
+void check__isb(void) {
+  __isb(0);
+}
+
+// CHECK: @llvm.aarch64.isb(i32 0)
+
+void check__yield(void) {
+  __yield();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 1)
+
+void check__wfe(void) {
+  __wfe();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 2)
+
+void check__wfi(void) {
+  __wfi();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 3)
+
+void check__sev(void) {
+  __sev();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 4)
+
+void check__sevl(void) {
+  __sevl();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 5)
+
diff --git a/clang/test/CodeGen/arm64-microsoft-intrinsics.c b/clang/test/CodeGen/arm64-microsoft-intrinsics.c
index 74c6f2f79e632..e18977a4559b1 100644
--- a/clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ b/clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -35,62 +35,6 @@ __int64 test_InterlockedAdd64_constant(__int64 volatile *Addend) {
 // CHECK-MSVC: ret i64 %[[NEWVAL:[0-9]+]]
 // CHECK-LINUX: error: call to undeclared function '_InterlockedAdd64'
 
-void check__dmb(void) {
-  __dmb(0);
-}
-
-// CHECK-MSVC: @llvm.aarch64.dmb(i32 0)
-// CHECK-LINUX: error: call to undeclared function '__dmb'
-
-void check__dsb(void) {
-  __dsb(0);
-}
-
-// CHECK-MSVC: @llvm.aarch64.dsb(i32 0)
-// CHECK-LINUX: error: call to undeclared function '__dsb'
-
-void check__isb(void) {
-  __isb(0);
-}
-
-// CHECK-MSVC: @llvm.aarch64.isb(i32 0)
-// CHECK-LINUX: error: call to undeclared function '__isb'
-
-void check__yield(void) {
-  __yield();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 1)
-// CHECK-LINUX: error: call to undeclared function '__yield'
-
-void check__wfe(void) {
-  __wfe();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 2)
-// CHECK-LINUX: error: call to undeclared function '__wfe'
-
-void check__wfi(void) {
-  __wfi();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 3)
-// CHECK-LINUX: error: call to undeclared function '__wfi'
-
-void check__sev(void) {
-  __sev();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 4)
-// CHECK-LINUX: error: call to undeclared function '__sev'
-
-void check__sevl(void) {
-  __sevl();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 5)
-// CHECK-LINUX: error: call to undeclared function '__sevl'
-
 void check_ReadWriteBarrier(void) {
   _ReadWriteBarrier();
 }
diff --git a/clang/test/CodeGen/builtins-arm-microsoft.c b/clang/test/CodeGen/builtins-arm-microsoft.c
index 841a8a500d533..b2681197e33e0 100644
--- a/clang/test/CodeGen/builtins-arm-microsoft.c
+++ b/clang/test/CodeGen/builtins-arm-microsoft.c
@@ -4,38 +4,40 @@
 // RUN:     | FileCheck %s -check-prefix CHECK-EABI
 // REQUIRES: arm-registered-target
 
+#include <arm_acle.h>
+
 void test_yield_intrinsic() {
   __yield();
 }
 
 // CHECK-MSVC: call void @llvm.arm.hint(i32 1)
-// CHECK-EABI-NOT: call void @llvm.arm.hint(i32 1)
+// CHECK-EABI: call void @llvm.arm.hint(i32 1)
 
 void wfe() {
   __wfe();
 }
 
 // CHECK-MSVC: call {{.*}} @llvm.arm.hint(i32 2)
-// CHECK-EABI-NOT: call {{.*}} @llvm.arm.hint(i32 2)
+// CHECK-EABI: call {{.*}} @llvm.arm.hint(i32 2)
 
 void wfi() {
   __wfi();
 }
 
 // CHECK-MSVC: call {{.*}} @llvm.arm.hint(i32 3)
-// CHECK-EABI-NOT: call {{.*}} @llvm.arm.hint(i32 3)
+// CHECK-EABI: call {{.*}} @llvm.arm.hint(i32 3)
 
 void sev() {
   __sev();
 }
 
 // CHECK-MSVC: call {{.*}} @llvm.arm.hint(i32 4)
-// CHECK-EABI-NOT: call {{.*}} @llvm.arm.hint(i32 4)
+// CHECK-EABI: call {{.*}} @llvm.arm.hint(i32 4)
 
 void sevl() {
   __sevl();
 }
 
 // CHECK-MSVC: call {{.*}} @llvm.arm.hint(i32 5)
-// CHECK-EABI-NOT: call {{.*}} @llvm.arm.hint(i32 5)
+// CHECK-EABI: call {{.*}} @llvm.arm.hint(i32 5)
 
diff --git a/clang/test/Headers/Inputs/include/stdint.h b/clang/test/Headers/Inputs/include/stdint.h
index 67b27b8dfc7b9..eb09272b40c33 100644
--- a/clang/test/Headers/Inputs/include/stdint.h
+++ b/clang/test/Headers/Inputs/include/stdint.h
@@ -1,11 +1,23 @@
 #ifndef STDINT_H
 #define STDINT_H
 
+#ifdef __INT8_TYPE__
+typedef __INT8_TYPE__ int8_t;
+#endif
+typedef unsigned char uint8_t;
+
+#ifdef __INT16_TYPE__
+typedef __INT16_TYPE__ int16_t;
+typedef unsigned __INT16_TYPE__ uint16_t;
+#endif
+
 #ifdef __INT32_TYPE__
+typedef __INT32_TYPE__ int32_t;
 typedef unsigned __INT32_TYPE__ uint32_t;
 #endif
 
 #ifdef __INT64_TYPE__
+typedef __INT64_TYPE__ int64_t;
 typedef unsigned __INT64_TYPE__ uint64_t;
 #endif
 
diff --git a/clang/test/Headers/ms-intrin.cpp b/clang/test/Headers/ms-intrin.cpp
index d630883e79d6a..985f8577c46bf 100644
--- a/clang/test/Headers/ms-intrin.cpp
+++ b/clang/test/Headers/ms-intrin.cpp
@@ -36,6 +36,10 @@ typedef __SIZE_TYPE__ size_t;
 
 #include <intrin.h>
 
+#ifdef __ARM_ACLE
+#include <arm_acle.h>
+#endif
+
 // Use some C++ to make sure we closed the extern "C" brackets.
 template <typename T>
 void foo(T V) {}

@llvmbot
Copy link
Member

llvmbot commented May 21, 2025

@llvm/pr-subscribers-backend-aarch64

Author: Nick Sarnie (sarnex)

Changes

The original change caused issues on MSVC due to a new warning thrown inside MSVC headers. That was fixed here, so reapply this commit. Original description below.

Instead of defining ARM ACLE intrinsics only on MSVC and guarding wrapper functions in headers with __has_builtin, universally define the intrinsics as target header builtins.


Full diff: https://github.com/llvm/llvm-project/pull/140910.diff

14 Files Affected:

  • (modified) clang/include/clang/Basic/BuiltinHeaders.def (+1)
  • (modified) clang/include/clang/Basic/BuiltinsAArch64.def (+8-10)
  • (modified) clang/include/clang/Basic/BuiltinsARM.def (+8-9)
  • (modified) clang/lib/Headers/arm_acle.h (+8-44)
  • (modified) clang/lib/Sema/SemaARM.cpp (+6)
  • (added) clang/test/CodeGen/arm-former-microsoft-intrinsics-header-warning.c (+50)
  • (added) clang/test/CodeGen/arm-former-microsoft-intrinsics.c (+53)
  • (modified) clang/test/CodeGen/arm-microsoft-intrinsics.c (-21)
  • (added) clang/test/CodeGen/arm64-former-microsoft-intrinsics-header-warning.c (+53)
  • (added) clang/test/CodeGen/arm64-former-microsoft-intrinsics.c (+59)
  • (modified) clang/test/CodeGen/arm64-microsoft-intrinsics.c (-56)
  • (modified) clang/test/CodeGen/builtins-arm-microsoft.c (+7-5)
  • (modified) clang/test/Headers/Inputs/include/stdint.h (+12)
  • (modified) clang/test/Headers/ms-intrin.cpp (+4)
diff --git a/clang/include/clang/Basic/BuiltinHeaders.def b/clang/include/clang/Basic/BuiltinHeaders.def
index 8e4a2f9bee9aa..22668ec7a3396 100644
--- a/clang/include/clang/Basic/BuiltinHeaders.def
+++ b/clang/include/clang/Basic/BuiltinHeaders.def
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 HEADER(NO_HEADER, nullptr)
+HEADER(ARMACLE_H, "arm_acle.h")
 HEADER(BLOCKS_H, "Blocks.h")
 HEADER(COMPLEX_H, "complex.h")
 HEADER(CTYPE_H, "ctype.h")
diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def
index 0b2dba86d9930..8867a9fe09fb9 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -50,6 +50,11 @@ BUILTIN(__builtin_arm_wfi, "v", "")
 BUILTIN(__builtin_arm_sev, "v", "")
 BUILTIN(__builtin_arm_sevl, "v", "")
 BUILTIN(__builtin_arm_chkfeat, "WUiWUi", "")
+TARGET_HEADER_BUILTIN(__yield, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__wfe,   "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__wfi,   "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__sev,   "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__sevl,  "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
 
 // Like __builtin_trap but provide an 16-bit immediate reason code (which goes into `brk #N`).
 BUILTIN(__builtin_arm_trap, "vUIs", "nr")
@@ -82,6 +87,9 @@ TARGET_BUILTIN(__builtin_arm_mops_memset_tag, "v*v*iz", "", "mte,mops")
 BUILTIN(__builtin_arm_dmb, "vUi", "nc")
 BUILTIN(__builtin_arm_dsb, "vUi", "nc")
 BUILTIN(__builtin_arm_isb, "vUi", "nc")
+TARGET_HEADER_BUILTIN(__dmb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__dsb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__isb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
 
 TARGET_BUILTIN(__builtin_arm_jcvt, "Zid", "nc", "v8.3a")
 
@@ -98,16 +106,6 @@ BUILTIN(__builtin_arm_wsr64, "vcC*WUi", "nc")
 TARGET_BUILTIN(__builtin_arm_wsr128, "vcC*LLLUi", "nc", "d128")
 BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
 
-// MSVC
-LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__yield, "v", "",   ALL_MS_LANGUAGES)
-LANGBUILTIN(__wfe,   "v", "",   ALL_MS_LANGUAGES)
-LANGBUILTIN(__wfi,   "v", "",   ALL_MS_LANGUAGES)
-LANGBUILTIN(__sev,   "v", "",   ALL_MS_LANGUAGES)
-LANGBUILTIN(__sevl,  "v", "",   ALL_MS_LANGUAGES)
-
 // Misc
 BUILTIN(__builtin_sponentry, "v*", "c")
 
diff --git a/clang/include/clang/Basic/BuiltinsARM.def b/clang/include/clang/Basic/BuiltinsARM.def
index cbab87cecbc7d..2592e25e95c37 100644
--- a/clang/include/clang/Basic/BuiltinsARM.def
+++ b/clang/include/clang/Basic/BuiltinsARM.def
@@ -186,11 +186,19 @@ BUILTIN(__builtin_arm_wfi, "v", "")
 BUILTIN(__builtin_arm_sev, "v", "")
 BUILTIN(__builtin_arm_sevl, "v", "")
 BUILTIN(__builtin_arm_dbg, "vUi", "")
+TARGET_HEADER_BUILTIN(__yield, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__wfe, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__wfi, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__sev, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__sevl, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
 
 // Data barrier
 BUILTIN(__builtin_arm_dmb, "vUi", "nc")
 BUILTIN(__builtin_arm_dsb, "vUi", "nc")
 BUILTIN(__builtin_arm_isb, "vUi", "nc")
+TARGET_HEADER_BUILTIN(__dmb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__dsb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__isb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
 
 // Prefetch
 BUILTIN(__builtin_arm_prefetch, "vvC*UiUi", "nc")
@@ -209,15 +217,6 @@ BUILTIN(__builtin_sponentry, "v*", "c")
 // MSVC
 LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES)
 
-LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES)
-LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES)
-LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES)
-LANGBUILTIN(__sev, "v", "", ALL_MS_LANGUAGES)
-LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES)
-
-LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES)
 LANGBUILTIN(__ldrexd, "WiWiCD*", "", ALL_MS_LANGUAGES)
 LANGBUILTIN(_MoveFromCoprocessor, "UiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
 LANGBUILTIN(_MoveFromCoprocessor2, "UiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
diff --git a/clang/lib/Headers/arm_acle.h b/clang/lib/Headers/arm_acle.h
index a7a62b69e0468..5cfa3d023a7d5 100644
--- a/clang/lib/Headers/arm_acle.h
+++ b/clang/lib/Headers/arm_acle.h
@@ -29,52 +29,16 @@ extern "C" {
 
 /* 7 SYNCHRONIZATION, BARRIER AND HINT INTRINSICS */
 /* 7.3 Memory barriers */
-#if !__has_builtin(__dmb)
-#define __dmb(i) __builtin_arm_dmb(i)
-#endif
-#if !__has_builtin(__dsb)
-#define __dsb(i) __builtin_arm_dsb(i)
-#endif
-#if !__has_builtin(__isb)
-#define __isb(i) __builtin_arm_isb(i)
-#endif
+void __dmb(unsigned int);
+void __dsb(unsigned int);
+void __isb(unsigned int);
 
 /* 7.4 Hints */
-
-#if !__has_builtin(__wfi)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__wfi(void) {
-  __builtin_arm_wfi();
-}
-#endif
-
-#if !__has_builtin(__wfe)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__wfe(void) {
-  __builtin_arm_wfe();
-}
-#endif
-
-#if !__has_builtin(__sev)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__sev(void) {
-  __builtin_arm_sev();
-}
-#endif
-
-#if !__has_builtin(__sevl)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__sevl(void) {
-  __builtin_arm_sevl();
-}
-#endif
-
-#if !__has_builtin(__yield)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__yield(void) {
-  __builtin_arm_yield();
-}
-#endif
+void __wfi(void);
+void __wfe(void);
+void __sev(void);
+void __sevl(void);
+void __yield(void);
 
 #if defined(__ARM_32BIT_STATE) && __ARM_32BIT_STATE
 #define __dbg(t) __builtin_arm_dbg(t)
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index 146cd78195663..e992a1012fde0 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -1010,8 +1010,11 @@ bool SemaARM::CheckARMBuiltinFunctionCall(const TargetInfo &TI,
   case ARM::BI__builtin_arm_vcvtr_d:
     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
   case ARM::BI__builtin_arm_dmb:
+  case ARM::BI__dmb:
   case ARM::BI__builtin_arm_dsb:
+  case ARM::BI__dsb:
   case ARM::BI__builtin_arm_isb:
+  case ARM::BI__isb:
   case ARM::BI__builtin_arm_dbg:
     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15);
   case ARM::BI__builtin_arm_cdp:
@@ -1108,8 +1111,11 @@ bool SemaARM::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI,
   switch (BuiltinID) {
   default: return false;
   case AArch64::BI__builtin_arm_dmb:
+  case AArch64::BI__dmb:
   case AArch64::BI__builtin_arm_dsb:
+  case AArch64::BI__dsb:
   case AArch64::BI__builtin_arm_isb:
+  case AArch64::BI__isb:
     l = 0;
     u = 15;
     break;
diff --git a/clang/test/CodeGen/arm-former-microsoft-intrinsics-header-warning.c b/clang/test/CodeGen/arm-former-microsoft-intrinsics-header-warning.c
new file mode 100644
index 0000000000000..8edcbbeb0375d
--- /dev/null
+++ b/clang/test/CodeGen/arm-former-microsoft-intrinsics-header-warning.c
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -triple thumbv7-windows -fms-compatibility -Wno-everything -Wimplicit-function-declaration -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple armv7-eabi -Wno-everything -Wimplicit-function-declaration -fsyntax-only -verify %s
+
+void check__dmb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __dmb(0);
+}
+
+void check__dsb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __dsb(0);
+}
+
+void check__isb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __isb(0);
+}
+
+void check__yield(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __yield();
+}
+
+void check__wfe(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __wfe();
+}
+
+void check__wfi(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __wfi();
+}
+
+void check__sev(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __sev();
+}
+
+void check__sevl(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __sevl();
+}
diff --git a/clang/test/CodeGen/arm-former-microsoft-intrinsics.c b/clang/test/CodeGen/arm-former-microsoft-intrinsics.c
new file mode 100644
index 0000000000000..8a02602dc9876
--- /dev/null
+++ b/clang/test/CodeGen/arm-former-microsoft-intrinsics.c
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple thumbv7-windows -fms-compatibility -emit-llvm -o - %s \
+// RUN:    | FileCheck %s
+
+// RUN: %clang_cc1 -triple armv7-eabi -Werror -emit-llvm -o - %s \
+// RUN:    | FileCheck %s
+#include <arm_acle.h>
+void check__dmb(void) {
+  __dmb(0);
+}
+
+// CHECK: @llvm.arm.dmb(i32 0)
+
+void check__dsb(void) {
+  __dsb(0);
+}
+
+// CHECK: @llvm.arm.dsb(i32 0)
+
+void check__isb(void) {
+  __isb(0);
+}
+
+// CHECK: @llvm.arm.isb(i32 0)
+
+void check__yield(void) {
+  __yield();
+}
+
+// CHECK: @llvm.arm.hint(i32 1)
+
+void check__wfe(void) {
+  __wfe();
+}
+
+// CHECK: @llvm.arm.hint(i32 2)
+
+void check__wfi(void) {
+  __wfi();
+}
+
+// CHECK: @llvm.arm.hint(i32 3)
+
+void check__sev(void) {
+  __sev();
+}
+
+// CHECK: @llvm.arm.hint(i32 4)
+
+void check__sevl(void) {
+  __sevl();
+}
+
+// CHECK: @llvm.arm.hint(i32 5)
diff --git a/clang/test/CodeGen/arm-microsoft-intrinsics.c b/clang/test/CodeGen/arm-microsoft-intrinsics.c
index 6793b3879eede..a5f3e2c719227 100644
--- a/clang/test/CodeGen/arm-microsoft-intrinsics.c
+++ b/clang/test/CodeGen/arm-microsoft-intrinsics.c
@@ -4,27 +4,6 @@
 // RUN: not %clang_cc1 -triple armv7-eabi -Werror -S -o /dev/null %s 2>&1 \
 // RUN:    | FileCheck %s -check-prefix CHECK-EABI
 
-void check__dmb(void) {
-  __dmb(0);
-}
-
-// CHECK-MSVC: @llvm.arm.dmb(i32 0)
-// CHECK-EABI: error: call to undeclared function '__dmb'
-
-void check__dsb(void) {
-  __dsb(0);
-}
-
-// CHECK-MSVC: @llvm.arm.dsb(i32 0)
-// CHECK-EABI: error: call to undeclared function '__dsb'
-
-void check__isb(void) {
-  __isb(0);
-}
-
-// CHECK-MSVC: @llvm.arm.isb(i32 0)
-// CHECK-EABI: error: call to undeclared function '__isb'
-
 __INT64_TYPE__ check__ldrexd(void) {
   __INT64_TYPE__ i64;
   return __ldrexd(&i64);
diff --git a/clang/test/CodeGen/arm64-former-microsoft-intrinsics-header-warning.c b/clang/test/CodeGen/arm64-former-microsoft-intrinsics-header-warning.c
new file mode 100644
index 0000000000000..52fed49db4dd2
--- /dev/null
+++ b/clang/test/CodeGen/arm64-former-microsoft-intrinsics-header-warning.c
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple arm64-windows -Wno-everything -Wimplicit-function-declaration -fms-compatibility -fsyntax-only -verify %s
+
+// RUN: %clang_cc1 -triple arm64-linux -Wno-everything -Wimplicit-function-declaration -fsyntax-only -verify %s
+
+// RUN: %clang_cc1 -triple arm64-darwin -Wno-everything -Wimplicit-function-declaration -fms-compatibility -fsyntax-only -verify %s
+
+void check__dmb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __dmb(0);
+}
+
+void check__dsb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __dsb(0);
+}
+
+void check__isb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __isb(0);
+}
+
+void check__yield(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __yield();
+}
+
+void check__wfe(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __wfe();
+}
+
+void check__wfi(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __wfi();
+}
+
+void check__sev(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __sev();
+}
+
+void check__sevl(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __sevl();
+}
diff --git a/clang/test/CodeGen/arm64-former-microsoft-intrinsics.c b/clang/test/CodeGen/arm64-former-microsoft-intrinsics.c
new file mode 100644
index 0000000000000..f1d9af2c6d25e
--- /dev/null
+++ b/clang/test/CodeGen/arm64-former-microsoft-intrinsics.c
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -triple arm64-windows -Wno-implicit-function-declaration -fms-compatibility -emit-llvm -o - %s \
+// RUN:    | FileCheck %s
+
+// RUN: %clang_cc1 -triple arm64-linux -Werror -emit-llvm -o - %s 2>&1 \
+// RUN:    | FileCheck %s
+
+// RUN: %clang_cc1 -triple arm64-darwin -Wno-implicit-function-declaration -fms-compatibility -emit-llvm -o - %s \
+// RUN:    | FileCheck %s
+
+#include <arm_acle.h>
+
+void check__dmb(void) {
+  __dmb(0);
+}
+
+// CHECK: @llvm.aarch64.dmb(i32 0)
+
+void check__dsb(void) {
+  __dsb(0);
+}
+
+// CHECK: @llvm.aarch64.dsb(i32 0)
+
+void check__isb(void) {
+  __isb(0);
+}
+
+// CHECK: @llvm.aarch64.isb(i32 0)
+
+void check__yield(void) {
+  __yield();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 1)
+
+void check__wfe(void) {
+  __wfe();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 2)
+
+void check__wfi(void) {
+  __wfi();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 3)
+
+void check__sev(void) {
+  __sev();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 4)
+
+void check__sevl(void) {
+  __sevl();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 5)
+
diff --git a/clang/test/CodeGen/arm64-microsoft-intrinsics.c b/clang/test/CodeGen/arm64-microsoft-intrinsics.c
index 74c6f2f79e632..e18977a4559b1 100644
--- a/clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ b/clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -35,62 +35,6 @@ __int64 test_InterlockedAdd64_constant(__int64 volatile *Addend) {
 // CHECK-MSVC: ret i64 %[[NEWVAL:[0-9]+]]
 // CHECK-LINUX: error: call to undeclared function '_InterlockedAdd64'
 
-void check__dmb(void) {
-  __dmb(0);
-}
-
-// CHECK-MSVC: @llvm.aarch64.dmb(i32 0)
-// CHECK-LINUX: error: call to undeclared function '__dmb'
-
-void check__dsb(void) {
-  __dsb(0);
-}
-
-// CHECK-MSVC: @llvm.aarch64.dsb(i32 0)
-// CHECK-LINUX: error: call to undeclared function '__dsb'
-
-void check__isb(void) {
-  __isb(0);
-}
-
-// CHECK-MSVC: @llvm.aarch64.isb(i32 0)
-// CHECK-LINUX: error: call to undeclared function '__isb'
-
-void check__yield(void) {
-  __yield();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 1)
-// CHECK-LINUX: error: call to undeclared function '__yield'
-
-void check__wfe(void) {
-  __wfe();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 2)
-// CHECK-LINUX: error: call to undeclared function '__wfe'
-
-void check__wfi(void) {
-  __wfi();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 3)
-// CHECK-LINUX: error: call to undeclared function '__wfi'
-
-void check__sev(void) {
-  __sev();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 4)
-// CHECK-LINUX: error: call to undeclared function '__sev'
-
-void check__sevl(void) {
-  __sevl();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 5)
-// CHECK-LINUX: error: call to undeclared function '__sevl'
-
 void check_ReadWriteBarrier(void) {
   _ReadWriteBarrier();
 }
diff --git a/clang/test/CodeGen/builtins-arm-microsoft.c b/clang/test/CodeGen/builtins-arm-microsoft.c
index 841a8a500d533..b2681197e33e0 100644
--- a/clang/test/CodeGen/builtins-arm-microsoft.c
+++ b/clang/test/CodeGen/builtins-arm-microsoft.c
@@ -4,38 +4,40 @@
 // RUN:     | FileCheck %s -check-prefix CHECK-EABI
 // REQUIRES: arm-registered-target
 
+#include <arm_acle.h>
+
 void test_yield_intrinsic() {
   __yield();
 }
 
 // CHECK-MSVC: call void @llvm.arm.hint(i32 1)
-// CHECK-EABI-NOT: call void @llvm.arm.hint(i32 1)
+// CHECK-EABI: call void @llvm.arm.hint(i32 1)
 
 void wfe() {
   __wfe();
 }
 
 // CHECK-MSVC: call {{.*}} @llvm.arm.hint(i32 2)
-// CHECK-EABI-NOT: call {{.*}} @llvm.arm.hint(i32 2)
+// CHECK-EABI: call {{.*}} @llvm.arm.hint(i32 2)
 
 void wfi() {
   __wfi();
 }
 
 // CHECK-MSVC: call {{.*}} @llvm.arm.hint(i32 3)
-// CHECK-EABI-NOT: call {{.*}} @llvm.arm.hint(i32 3)
+// CHECK-EABI: call {{.*}} @llvm.arm.hint(i32 3)
 
 void sev() {
   __sev();
 }
 
 // CHECK-MSVC: call {{.*}} @llvm.arm.hint(i32 4)
-// CHECK-EABI-NOT: call {{.*}} @llvm.arm.hint(i32 4)
+// CHECK-EABI: call {{.*}} @llvm.arm.hint(i32 4)
 
 void sevl() {
   __sevl();
 }
 
 // CHECK-MSVC: call {{.*}} @llvm.arm.hint(i32 5)
-// CHECK-EABI-NOT: call {{.*}} @llvm.arm.hint(i32 5)
+// CHECK-EABI: call {{.*}} @llvm.arm.hint(i32 5)
 
diff --git a/clang/test/Headers/Inputs/include/stdint.h b/clang/test/Headers/Inputs/include/stdint.h
index 67b27b8dfc7b9..eb09272b40c33 100644
--- a/clang/test/Headers/Inputs/include/stdint.h
+++ b/clang/test/Headers/Inputs/include/stdint.h
@@ -1,11 +1,23 @@
 #ifndef STDINT_H
 #define STDINT_H
 
+#ifdef __INT8_TYPE__
+typedef __INT8_TYPE__ int8_t;
+#endif
+typedef unsigned char uint8_t;
+
+#ifdef __INT16_TYPE__
+typedef __INT16_TYPE__ int16_t;
+typedef unsigned __INT16_TYPE__ uint16_t;
+#endif
+
 #ifdef __INT32_TYPE__
+typedef __INT32_TYPE__ int32_t;
 typedef unsigned __INT32_TYPE__ uint32_t;
 #endif
 
 #ifdef __INT64_TYPE__
+typedef __INT64_TYPE__ int64_t;
 typedef unsigned __INT64_TYPE__ uint64_t;
 #endif
 
diff --git a/clang/test/Headers/ms-intrin.cpp b/clang/test/Headers/ms-intrin.cpp
index d630883e79d6a..985f8577c46bf 100644
--- a/clang/test/Headers/ms-intrin.cpp
+++ b/clang/test/Headers/ms-intrin.cpp
@@ -36,6 +36,10 @@ typedef __SIZE_TYPE__ size_t;
 
 #include <intrin.h>
 
+#ifdef __ARM_ACLE
+#include <arm_acle.h>
+#endif
+
 // Use some C++ to make sure we closed the extern "C" brackets.
 template <typename T>
 void foo(T V) {}

@llvmbot
Copy link
Member

llvmbot commented May 21, 2025

@llvm/pr-subscribers-backend-arm

Author: Nick Sarnie (sarnex)

Changes

The original change caused issues on MSVC due to a new warning thrown inside MSVC headers. That was fixed here, so reapply this commit. Original description below.

Instead of defining ARM ACLE intrinsics only on MSVC and guarding wrapper functions in headers with __has_builtin, universally define the intrinsics as target header builtins.


Full diff: https://github.com/llvm/llvm-project/pull/140910.diff

14 Files Affected:

  • (modified) clang/include/clang/Basic/BuiltinHeaders.def (+1)
  • (modified) clang/include/clang/Basic/BuiltinsAArch64.def (+8-10)
  • (modified) clang/include/clang/Basic/BuiltinsARM.def (+8-9)
  • (modified) clang/lib/Headers/arm_acle.h (+8-44)
  • (modified) clang/lib/Sema/SemaARM.cpp (+6)
  • (added) clang/test/CodeGen/arm-former-microsoft-intrinsics-header-warning.c (+50)
  • (added) clang/test/CodeGen/arm-former-microsoft-intrinsics.c (+53)
  • (modified) clang/test/CodeGen/arm-microsoft-intrinsics.c (-21)
  • (added) clang/test/CodeGen/arm64-former-microsoft-intrinsics-header-warning.c (+53)
  • (added) clang/test/CodeGen/arm64-former-microsoft-intrinsics.c (+59)
  • (modified) clang/test/CodeGen/arm64-microsoft-intrinsics.c (-56)
  • (modified) clang/test/CodeGen/builtins-arm-microsoft.c (+7-5)
  • (modified) clang/test/Headers/Inputs/include/stdint.h (+12)
  • (modified) clang/test/Headers/ms-intrin.cpp (+4)
diff --git a/clang/include/clang/Basic/BuiltinHeaders.def b/clang/include/clang/Basic/BuiltinHeaders.def
index 8e4a2f9bee9aa..22668ec7a3396 100644
--- a/clang/include/clang/Basic/BuiltinHeaders.def
+++ b/clang/include/clang/Basic/BuiltinHeaders.def
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 HEADER(NO_HEADER, nullptr)
+HEADER(ARMACLE_H, "arm_acle.h")
 HEADER(BLOCKS_H, "Blocks.h")
 HEADER(COMPLEX_H, "complex.h")
 HEADER(CTYPE_H, "ctype.h")
diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def
index 0b2dba86d9930..8867a9fe09fb9 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -50,6 +50,11 @@ BUILTIN(__builtin_arm_wfi, "v", "")
 BUILTIN(__builtin_arm_sev, "v", "")
 BUILTIN(__builtin_arm_sevl, "v", "")
 BUILTIN(__builtin_arm_chkfeat, "WUiWUi", "")
+TARGET_HEADER_BUILTIN(__yield, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__wfe,   "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__wfi,   "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__sev,   "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__sevl,  "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
 
 // Like __builtin_trap but provide an 16-bit immediate reason code (which goes into `brk #N`).
 BUILTIN(__builtin_arm_trap, "vUIs", "nr")
@@ -82,6 +87,9 @@ TARGET_BUILTIN(__builtin_arm_mops_memset_tag, "v*v*iz", "", "mte,mops")
 BUILTIN(__builtin_arm_dmb, "vUi", "nc")
 BUILTIN(__builtin_arm_dsb, "vUi", "nc")
 BUILTIN(__builtin_arm_isb, "vUi", "nc")
+TARGET_HEADER_BUILTIN(__dmb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__dsb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__isb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
 
 TARGET_BUILTIN(__builtin_arm_jcvt, "Zid", "nc", "v8.3a")
 
@@ -98,16 +106,6 @@ BUILTIN(__builtin_arm_wsr64, "vcC*WUi", "nc")
 TARGET_BUILTIN(__builtin_arm_wsr128, "vcC*LLLUi", "nc", "d128")
 BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
 
-// MSVC
-LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__yield, "v", "",   ALL_MS_LANGUAGES)
-LANGBUILTIN(__wfe,   "v", "",   ALL_MS_LANGUAGES)
-LANGBUILTIN(__wfi,   "v", "",   ALL_MS_LANGUAGES)
-LANGBUILTIN(__sev,   "v", "",   ALL_MS_LANGUAGES)
-LANGBUILTIN(__sevl,  "v", "",   ALL_MS_LANGUAGES)
-
 // Misc
 BUILTIN(__builtin_sponentry, "v*", "c")
 
diff --git a/clang/include/clang/Basic/BuiltinsARM.def b/clang/include/clang/Basic/BuiltinsARM.def
index cbab87cecbc7d..2592e25e95c37 100644
--- a/clang/include/clang/Basic/BuiltinsARM.def
+++ b/clang/include/clang/Basic/BuiltinsARM.def
@@ -186,11 +186,19 @@ BUILTIN(__builtin_arm_wfi, "v", "")
 BUILTIN(__builtin_arm_sev, "v", "")
 BUILTIN(__builtin_arm_sevl, "v", "")
 BUILTIN(__builtin_arm_dbg, "vUi", "")
+TARGET_HEADER_BUILTIN(__yield, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__wfe, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__wfi, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__sev, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__sevl, "v", "h", ARMACLE_H, ALL_LANGUAGES, "")
 
 // Data barrier
 BUILTIN(__builtin_arm_dmb, "vUi", "nc")
 BUILTIN(__builtin_arm_dsb, "vUi", "nc")
 BUILTIN(__builtin_arm_isb, "vUi", "nc")
+TARGET_HEADER_BUILTIN(__dmb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__dsb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__isb, "vUi", "nch", ARMACLE_H, ALL_LANGUAGES, "")
 
 // Prefetch
 BUILTIN(__builtin_arm_prefetch, "vvC*UiUi", "nc")
@@ -209,15 +217,6 @@ BUILTIN(__builtin_sponentry, "v*", "c")
 // MSVC
 LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES)
 
-LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES)
-LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES)
-LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES)
-LANGBUILTIN(__sev, "v", "", ALL_MS_LANGUAGES)
-LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES)
-
-LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES)
 LANGBUILTIN(__ldrexd, "WiWiCD*", "", ALL_MS_LANGUAGES)
 LANGBUILTIN(_MoveFromCoprocessor, "UiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
 LANGBUILTIN(_MoveFromCoprocessor2, "UiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
diff --git a/clang/lib/Headers/arm_acle.h b/clang/lib/Headers/arm_acle.h
index a7a62b69e0468..5cfa3d023a7d5 100644
--- a/clang/lib/Headers/arm_acle.h
+++ b/clang/lib/Headers/arm_acle.h
@@ -29,52 +29,16 @@ extern "C" {
 
 /* 7 SYNCHRONIZATION, BARRIER AND HINT INTRINSICS */
 /* 7.3 Memory barriers */
-#if !__has_builtin(__dmb)
-#define __dmb(i) __builtin_arm_dmb(i)
-#endif
-#if !__has_builtin(__dsb)
-#define __dsb(i) __builtin_arm_dsb(i)
-#endif
-#if !__has_builtin(__isb)
-#define __isb(i) __builtin_arm_isb(i)
-#endif
+void __dmb(unsigned int);
+void __dsb(unsigned int);
+void __isb(unsigned int);
 
 /* 7.4 Hints */
-
-#if !__has_builtin(__wfi)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__wfi(void) {
-  __builtin_arm_wfi();
-}
-#endif
-
-#if !__has_builtin(__wfe)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__wfe(void) {
-  __builtin_arm_wfe();
-}
-#endif
-
-#if !__has_builtin(__sev)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__sev(void) {
-  __builtin_arm_sev();
-}
-#endif
-
-#if !__has_builtin(__sevl)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__sevl(void) {
-  __builtin_arm_sevl();
-}
-#endif
-
-#if !__has_builtin(__yield)
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
-__yield(void) {
-  __builtin_arm_yield();
-}
-#endif
+void __wfi(void);
+void __wfe(void);
+void __sev(void);
+void __sevl(void);
+void __yield(void);
 
 #if defined(__ARM_32BIT_STATE) && __ARM_32BIT_STATE
 #define __dbg(t) __builtin_arm_dbg(t)
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index 146cd78195663..e992a1012fde0 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -1010,8 +1010,11 @@ bool SemaARM::CheckARMBuiltinFunctionCall(const TargetInfo &TI,
   case ARM::BI__builtin_arm_vcvtr_d:
     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
   case ARM::BI__builtin_arm_dmb:
+  case ARM::BI__dmb:
   case ARM::BI__builtin_arm_dsb:
+  case ARM::BI__dsb:
   case ARM::BI__builtin_arm_isb:
+  case ARM::BI__isb:
   case ARM::BI__builtin_arm_dbg:
     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15);
   case ARM::BI__builtin_arm_cdp:
@@ -1108,8 +1111,11 @@ bool SemaARM::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI,
   switch (BuiltinID) {
   default: return false;
   case AArch64::BI__builtin_arm_dmb:
+  case AArch64::BI__dmb:
   case AArch64::BI__builtin_arm_dsb:
+  case AArch64::BI__dsb:
   case AArch64::BI__builtin_arm_isb:
+  case AArch64::BI__isb:
     l = 0;
     u = 15;
     break;
diff --git a/clang/test/CodeGen/arm-former-microsoft-intrinsics-header-warning.c b/clang/test/CodeGen/arm-former-microsoft-intrinsics-header-warning.c
new file mode 100644
index 0000000000000..8edcbbeb0375d
--- /dev/null
+++ b/clang/test/CodeGen/arm-former-microsoft-intrinsics-header-warning.c
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -triple thumbv7-windows -fms-compatibility -Wno-everything -Wimplicit-function-declaration -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple armv7-eabi -Wno-everything -Wimplicit-function-declaration -fsyntax-only -verify %s
+
+void check__dmb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __dmb(0);
+}
+
+void check__dsb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __dsb(0);
+}
+
+void check__isb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __isb(0);
+}
+
+void check__yield(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __yield();
+}
+
+void check__wfe(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __wfe();
+}
+
+void check__wfi(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __wfi();
+}
+
+void check__sev(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __sev();
+}
+
+void check__sevl(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __sevl();
+}
diff --git a/clang/test/CodeGen/arm-former-microsoft-intrinsics.c b/clang/test/CodeGen/arm-former-microsoft-intrinsics.c
new file mode 100644
index 0000000000000..8a02602dc9876
--- /dev/null
+++ b/clang/test/CodeGen/arm-former-microsoft-intrinsics.c
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple thumbv7-windows -fms-compatibility -emit-llvm -o - %s \
+// RUN:    | FileCheck %s
+
+// RUN: %clang_cc1 -triple armv7-eabi -Werror -emit-llvm -o - %s \
+// RUN:    | FileCheck %s
+#include <arm_acle.h>
+void check__dmb(void) {
+  __dmb(0);
+}
+
+// CHECK: @llvm.arm.dmb(i32 0)
+
+void check__dsb(void) {
+  __dsb(0);
+}
+
+// CHECK: @llvm.arm.dsb(i32 0)
+
+void check__isb(void) {
+  __isb(0);
+}
+
+// CHECK: @llvm.arm.isb(i32 0)
+
+void check__yield(void) {
+  __yield();
+}
+
+// CHECK: @llvm.arm.hint(i32 1)
+
+void check__wfe(void) {
+  __wfe();
+}
+
+// CHECK: @llvm.arm.hint(i32 2)
+
+void check__wfi(void) {
+  __wfi();
+}
+
+// CHECK: @llvm.arm.hint(i32 3)
+
+void check__sev(void) {
+  __sev();
+}
+
+// CHECK: @llvm.arm.hint(i32 4)
+
+void check__sevl(void) {
+  __sevl();
+}
+
+// CHECK: @llvm.arm.hint(i32 5)
diff --git a/clang/test/CodeGen/arm-microsoft-intrinsics.c b/clang/test/CodeGen/arm-microsoft-intrinsics.c
index 6793b3879eede..a5f3e2c719227 100644
--- a/clang/test/CodeGen/arm-microsoft-intrinsics.c
+++ b/clang/test/CodeGen/arm-microsoft-intrinsics.c
@@ -4,27 +4,6 @@
 // RUN: not %clang_cc1 -triple armv7-eabi -Werror -S -o /dev/null %s 2>&1 \
 // RUN:    | FileCheck %s -check-prefix CHECK-EABI
 
-void check__dmb(void) {
-  __dmb(0);
-}
-
-// CHECK-MSVC: @llvm.arm.dmb(i32 0)
-// CHECK-EABI: error: call to undeclared function '__dmb'
-
-void check__dsb(void) {
-  __dsb(0);
-}
-
-// CHECK-MSVC: @llvm.arm.dsb(i32 0)
-// CHECK-EABI: error: call to undeclared function '__dsb'
-
-void check__isb(void) {
-  __isb(0);
-}
-
-// CHECK-MSVC: @llvm.arm.isb(i32 0)
-// CHECK-EABI: error: call to undeclared function '__isb'
-
 __INT64_TYPE__ check__ldrexd(void) {
   __INT64_TYPE__ i64;
   return __ldrexd(&i64);
diff --git a/clang/test/CodeGen/arm64-former-microsoft-intrinsics-header-warning.c b/clang/test/CodeGen/arm64-former-microsoft-intrinsics-header-warning.c
new file mode 100644
index 0000000000000..52fed49db4dd2
--- /dev/null
+++ b/clang/test/CodeGen/arm64-former-microsoft-intrinsics-header-warning.c
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple arm64-windows -Wno-everything -Wimplicit-function-declaration -fms-compatibility -fsyntax-only -verify %s
+
+// RUN: %clang_cc1 -triple arm64-linux -Wno-everything -Wimplicit-function-declaration -fsyntax-only -verify %s
+
+// RUN: %clang_cc1 -triple arm64-darwin -Wno-everything -Wimplicit-function-declaration -fms-compatibility -fsyntax-only -verify %s
+
+void check__dmb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __dmb(0);
+}
+
+void check__dsb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __dsb(0);
+}
+
+void check__isb(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __isb(0);
+}
+
+void check__yield(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __yield();
+}
+
+void check__wfe(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __wfe();
+}
+
+void check__wfi(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __wfi();
+}
+
+void check__sev(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __sev();
+}
+
+void check__sevl(void) {
+  // expected-warning@+2{{call to undeclared library function}}
+  // expected-note@+1{{include the header <arm_acle.h> or explicitly provide a declaration for}}
+  __sevl();
+}
diff --git a/clang/test/CodeGen/arm64-former-microsoft-intrinsics.c b/clang/test/CodeGen/arm64-former-microsoft-intrinsics.c
new file mode 100644
index 0000000000000..f1d9af2c6d25e
--- /dev/null
+++ b/clang/test/CodeGen/arm64-former-microsoft-intrinsics.c
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -triple arm64-windows -Wno-implicit-function-declaration -fms-compatibility -emit-llvm -o - %s \
+// RUN:    | FileCheck %s
+
+// RUN: %clang_cc1 -triple arm64-linux -Werror -emit-llvm -o - %s 2>&1 \
+// RUN:    | FileCheck %s
+
+// RUN: %clang_cc1 -triple arm64-darwin -Wno-implicit-function-declaration -fms-compatibility -emit-llvm -o - %s \
+// RUN:    | FileCheck %s
+
+#include <arm_acle.h>
+
+void check__dmb(void) {
+  __dmb(0);
+}
+
+// CHECK: @llvm.aarch64.dmb(i32 0)
+
+void check__dsb(void) {
+  __dsb(0);
+}
+
+// CHECK: @llvm.aarch64.dsb(i32 0)
+
+void check__isb(void) {
+  __isb(0);
+}
+
+// CHECK: @llvm.aarch64.isb(i32 0)
+
+void check__yield(void) {
+  __yield();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 1)
+
+void check__wfe(void) {
+  __wfe();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 2)
+
+void check__wfi(void) {
+  __wfi();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 3)
+
+void check__sev(void) {
+  __sev();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 4)
+
+void check__sevl(void) {
+  __sevl();
+}
+
+// CHECK: @llvm.aarch64.hint(i32 5)
+
diff --git a/clang/test/CodeGen/arm64-microsoft-intrinsics.c b/clang/test/CodeGen/arm64-microsoft-intrinsics.c
index 74c6f2f79e632..e18977a4559b1 100644
--- a/clang/test/CodeGen/arm64-microsoft-intrinsics.c
+++ b/clang/test/CodeGen/arm64-microsoft-intrinsics.c
@@ -35,62 +35,6 @@ __int64 test_InterlockedAdd64_constant(__int64 volatile *Addend) {
 // CHECK-MSVC: ret i64 %[[NEWVAL:[0-9]+]]
 // CHECK-LINUX: error: call to undeclared function '_InterlockedAdd64'
 
-void check__dmb(void) {
-  __dmb(0);
-}
-
-// CHECK-MSVC: @llvm.aarch64.dmb(i32 0)
-// CHECK-LINUX: error: call to undeclared function '__dmb'
-
-void check__dsb(void) {
-  __dsb(0);
-}
-
-// CHECK-MSVC: @llvm.aarch64.dsb(i32 0)
-// CHECK-LINUX: error: call to undeclared function '__dsb'
-
-void check__isb(void) {
-  __isb(0);
-}
-
-// CHECK-MSVC: @llvm.aarch64.isb(i32 0)
-// CHECK-LINUX: error: call to undeclared function '__isb'
-
-void check__yield(void) {
-  __yield();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 1)
-// CHECK-LINUX: error: call to undeclared function '__yield'
-
-void check__wfe(void) {
-  __wfe();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 2)
-// CHECK-LINUX: error: call to undeclared function '__wfe'
-
-void check__wfi(void) {
-  __wfi();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 3)
-// CHECK-LINUX: error: call to undeclared function '__wfi'
-
-void check__sev(void) {
-  __sev();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 4)
-// CHECK-LINUX: error: call to undeclared function '__sev'
-
-void check__sevl(void) {
-  __sevl();
-}
-
-// CHECK-MSVC: @llvm.aarch64.hint(i32 5)
-// CHECK-LINUX: error: call to undeclared function '__sevl'
-
 void check_ReadWriteBarrier(void) {
   _ReadWriteBarrier();
 }
diff --git a/clang/test/CodeGen/builtins-arm-microsoft.c b/clang/test/CodeGen/builtins-arm-microsoft.c
index 841a8a500d533..b2681197e33e0 100644
--- a/clang/test/CodeGen/builtins-arm-microsoft.c
+++ b/clang/test/CodeGen/builtins-arm-microsoft.c
@@ -4,38 +4,40 @@
 // RUN:     | FileCheck %s -check-prefix CHECK-EABI
 // REQUIRES: arm-registered-target
 
+#include <arm_acle.h>
+
 void test_yield_intrinsic() {
   __yield();
 }
 
 // CHECK-MSVC: call void @llvm.arm.hint(i32 1)
-// CHECK-EABI-NOT: call void @llvm.arm.hint(i32 1)
+// CHECK-EABI: call void @llvm.arm.hint(i32 1)
 
 void wfe() {
   __wfe();
 }
 
 // CHECK-MSVC: call {{.*}} @llvm.arm.hint(i32 2)
-// CHECK-EABI-NOT: call {{.*}} @llvm.arm.hint(i32 2)
+// CHECK-EABI: call {{.*}} @llvm.arm.hint(i32 2)
 
 void wfi() {
   __wfi();
 }
 
 // CHECK-MSVC: call {{.*}} @llvm.arm.hint(i32 3)
-// CHECK-EABI-NOT: call {{.*}} @llvm.arm.hint(i32 3)
+// CHECK-EABI: call {{.*}} @llvm.arm.hint(i32 3)
 
 void sev() {
   __sev();
 }
 
 // CHECK-MSVC: call {{.*}} @llvm.arm.hint(i32 4)
-// CHECK-EABI-NOT: call {{.*}} @llvm.arm.hint(i32 4)
+// CHECK-EABI: call {{.*}} @llvm.arm.hint(i32 4)
 
 void sevl() {
   __sevl();
 }
 
 // CHECK-MSVC: call {{.*}} @llvm.arm.hint(i32 5)
-// CHECK-EABI-NOT: call {{.*}} @llvm.arm.hint(i32 5)
+// CHECK-EABI: call {{.*}} @llvm.arm.hint(i32 5)
 
diff --git a/clang/test/Headers/Inputs/include/stdint.h b/clang/test/Headers/Inputs/include/stdint.h
index 67b27b8dfc7b9..eb09272b40c33 100644
--- a/clang/test/Headers/Inputs/include/stdint.h
+++ b/clang/test/Headers/Inputs/include/stdint.h
@@ -1,11 +1,23 @@
 #ifndef STDINT_H
 #define STDINT_H
 
+#ifdef __INT8_TYPE__
+typedef __INT8_TYPE__ int8_t;
+#endif
+typedef unsigned char uint8_t;
+
+#ifdef __INT16_TYPE__
+typedef __INT16_TYPE__ int16_t;
+typedef unsigned __INT16_TYPE__ uint16_t;
+#endif
+
 #ifdef __INT32_TYPE__
+typedef __INT32_TYPE__ int32_t;
 typedef unsigned __INT32_TYPE__ uint32_t;
 #endif
 
 #ifdef __INT64_TYPE__
+typedef __INT64_TYPE__ int64_t;
 typedef unsigned __INT64_TYPE__ uint64_t;
 #endif
 
diff --git a/clang/test/Headers/ms-intrin.cpp b/clang/test/Headers/ms-intrin.cpp
index d630883e79d6a..985f8577c46bf 100644
--- a/clang/test/Headers/ms-intrin.cpp
+++ b/clang/test/Headers/ms-intrin.cpp
@@ -36,6 +36,10 @@ typedef __SIZE_TYPE__ size_t;
 
 #include <intrin.h>
 
+#ifdef __ARM_ACLE
+#include <arm_acle.h>
+#endif
+
 // Use some C++ to make sure we closed the extern "C" brackets.
 template <typename T>
 void foo(T V) {}

@sarnex
Copy link
Member Author

sarnex commented May 28, 2025

Looks like the fix commit broke something again :(

@sarnex sarnex marked this pull request as draft May 28, 2025 16:19
@sarnex sarnex marked this pull request as ready for review June 3, 2025 23:36
@sarnex
Copy link
Member Author

sarnex commented Jun 3, 2025

Dependent commit reapplied.

Copy link
Collaborator

@rnk rnk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, feel free to reland this.

@sarnex sarnex changed the title Reapply "[clang][ARM][AArch64] Define intrinsics guarded by __has_builtin on all platforms" (#128222)" [clang][ARM][AArch64] Reapply "Define intrinsics guarded by __has_builtin on all platforms (#128222)" Jun 4, 2025
@sarnex sarnex merged commit a7f0b29 into llvm:main Jun 4, 2025
13 checks passed
rorth pushed a commit to rorth/llvm-project that referenced this pull request Jun 11, 2025
…ltin on all platforms (llvm#128222)" (llvm#140910)

The original change caused issues on MSVC due to a new warning thrown
inside MSVC headers. That was fixed
[here](llvm#142019), so reapply
this commit. Original description below.

Instead of defining ARM ACLE intrinsics only on MSVC and guarding
wrapper functions in headers with __has_builtin, universally define the
intrinsics as target header builtins.
DhruvSrivastavaX pushed a commit to DhruvSrivastavaX/lldb-for-aix that referenced this pull request Jun 12, 2025
…ltin on all platforms (llvm#128222)" (llvm#140910)

The original change caused issues on MSVC due to a new warning thrown
inside MSVC headers. That was fixed
[here](llvm#142019), so reapply
this commit. Original description below.

Instead of defining ARM ACLE intrinsics only on MSVC and guarding
wrapper functions in headers with __has_builtin, universally define the
intrinsics as target header builtins.
@zmodem
Copy link
Collaborator

zmodem commented Jun 12, 2025

Sorry for noticing so late, but this seems to have broken Chromium again: https://crbug.com/424369224

The code is expecting to get __yield() via intrin.h: https://source.chromium.org/chromium/_/chromium/v8/v8/+/1581f862a01d94273e528588f14d8b879b59603a:src/base/platform/yield-processor.h;l=35

But now clang-cl complains, suggesting that the user includes arm_acle.h, a file which I believe doesn't exist in MSVC.

One idea would be to have intrin.h include arm_acle.h, but that would still yield a misleading warning if the user didn't include either.

@nico
Copy link
Contributor

nico commented Jun 12, 2025

One idea would be to have intrin.h include arm_acle.h, but that would still yield a misleading warning if the user didn't include either.

It'd presumably also be pretty bad for post-preprocessor file size and compile time, right?

@sarnex
Copy link
Member Author

sarnex commented Jun 12, 2025

Man, I thought I finally had a version that didn't break anything.

Investigating...

@sarnex
Copy link
Member Author

sarnex commented Jun 12, 2025

It looks like this commit landed, so is it safe to say I don't have revert this?

Can someone from Chromium send me some doc on/tell me how to reproduce it? I have no idea how to build ToTWinArm64PGO :)

Thanks

@sarnex
Copy link
Member Author

sarnex commented Jun 12, 2025

I think this repros it:

#include <intrin.h>
#define YIELD_PROCESSOR __yield()
int main() {
YIELD_PROCESSOR;
return 0;
}
clang-cl repro.c -target aarch64-windows-msvc
repro.c(4,1): error: call to undeclared library function '__yield' with type 'void (void)'; ISO C99 and later do not
      support implicit function declarations [-Wimplicit-function-declaration]
    4 | YIELD_PROCESSOR;
      | ^
repro.c(2,25): note: expanded from macro 'YIELD_PROCESSOR'
    2 | #define YIELD_PROCESSOR __yield()
      |                         ^
repro.c(4,1): note: include the header <arm_acle.h> or explicitly provide a declaration for '__yield'
repro.c(2,25): note: expanded from macro 'YIELD_PROCESSOR'
    2 | #define YIELD_PROCESSOR __yield()

@sarnex
Copy link
Member Author

sarnex commented Jun 12, 2025

Sorry, I'm not sure I understand the bug. For me, adding #include <arm_acle.h> fixed the warning as the warning suggests.

Also, #pragma intrinsic(__yield) before #define YIELD_PROCESSOR __yield() with no includes also fixed the warning.

It seems true that MSVC doesn't provide arm_acle.h and __yield() is declared in intrin0.inl.h, but Clang's headers do have arm_acle.h and we are compiling with Clang which should have access to Clang's headers right?

Is the assumption that Clang's headers provide the exact same header to intrinsic declaration mapping as MSVC's headers?

Thanks

@zmodem
Copy link
Collaborator

zmodem commented Jun 12, 2025

It looks like this commit landed, so is it safe to say I don't have revert this?

Yes, that one should unblock us, so there's no panic.

We should still fix this though.

Is the assumption that Clang's headers provide the exact same header to intrinsic declaration mapping as MSVC's headers?

It's never going to be exact, but the idea is that they should be compatible. If the MSVC way is to write

#include <intrin.h>
void f() { __yield(); }

we want that to work with clang-cl too.

And if the include is missing, we shouldn't suggest arm_acle.h, because that suggestion is not compatible with MSVC.

@sarnex
Copy link
Member Author

sarnex commented Jun 12, 2025

Thanks for the explanation.

To me it seems like the root issue here is that we have __yield (and probably a ton of other stuff) in arm_acle.h in Clang and it is not included from intrin.h, while MSVC's intrin.h does include intrin0.inl.h which has the declaration.
The new warning seems to just expose this root issue, but obviously a new warning is being thrown so we have to do something, I'm not trying to punt responsibility :)

The first thing that comes to mind is to include arm_acle.h in intrin.h on ARM/AArch64 in Clang. Obviously there are possible compile time concerns, but if MSVC allows all architecture-specific code to be abstracted away through intrin.h, it seems like we should too. Then we could change the warning to suggest intrin.h instead, which would be true on both MSVC and Clang.

Any feedback or suggestions on an approach to solve the issue?

@zmodem
Copy link
Collaborator

zmodem commented Jun 12, 2025

The first thing that comes to mind is to include arm_acle.h in intrin.h on ARM/AArch64 in Clang.

That's what I was thinking too. intrin.h is already a large header, so maybe arm_acle.h doesn't add that much, relatively speaking? (We should check)

@sarnex
Copy link
Member Author

sarnex commented Jun 12, 2025

Preprocessor size check, using Windows:
repro.c

#include <intrin.h>
void f() { __yield(); }
clang-cl -target aarch64-windows-msvc repro.c -E

No changes:
523 lines

Adding arm_ache.h include into intrin.h:
904 lines

So almost doubling, but I don't know if 500 lines is considered a lot in the preprocessor wold.

@rnk
Copy link
Collaborator

rnk commented Jun 13, 2025

I think intrin.h is hopelessly expensive, so I would just include arm_acle.h. On the x86 side, it includes immintrin.h, so if you care about compile times, it should be avoided and intrin0.h (which we have) used instead.

It's more concerning to me that MSVC doesn't expose a well-known portable header name for ARM intrinsics.

@sarnex
Copy link
Member Author

sarnex commented Jun 13, 2025

@rnk To be clear you mean modify Clang's intrin.h to include arm_acle.h when on supported targets, not change the application code to include arm_acle.h directly right? If so I can make that change. Thanks.

@rnk
Copy link
Collaborator

rnk commented Jun 13, 2025

To be clear you mean modify Clang's intrin.h to include arm_acle.h when on supported targets

Yep!

@sarnex
Copy link
Member Author

sarnex commented Jun 13, 2025

Thanks, made #144172, will finalize/publish it early next week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 backend:ARM backend:X86 clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:headers Headers provided by Clang, e.g. for intrinsics clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants