https://github.com/topperc created 
https://github.com/llvm/llvm-project/pull/217211

The intrinsics are documented to use (u)int64_t for 64-bit scalars.

OpenBSD on RV64 uses long long for int64_t while Linux uses long. The current 
code finds the first 64 bit type which is long for both OpenBSD and Linux.

This patch changes to lookup the type that corresponds to (u)int64_t.

Fixes #216531.

Assisted-by: Claude

>From 590b4e770b18acab52eeb7ba4d1ce3e9478f3649 Mon Sep 17 00:00:00 2001
From: Craig Topper <[email protected]>
Date: Tue, 18 Aug 2026 21:41:40 -0700
Subject: [PATCH] [RISCV] Use correct type for (u)int64_t in RVV intrinsics on
 OpenBSD

The intrinsics are documented to use (u)int64_t for 64-bit scalars.

OpenBSD on RV64 uses long long for int64_t while Linux uses long.
The current code finds the first 64 bit type which is long for both
OpenBSD and Linux.

This patch changes to lookup the type that corresponds to (u)int64_t.

Fixes #216531.
---
 clang/lib/Sema/SemaRISCV.cpp                  | 18 ++++++++--
 clang/test/Sema/riscv-rvv-int64-scalar-type.c | 35 +++++++++++++++++++
 2 files changed, 51 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Sema/riscv-rvv-int64-scalar-type.c

diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp
index 9647a7d913744..26d012763b6c9 100644
--- a/clang/lib/Sema/SemaRISCV.cpp
+++ b/clang/lib/Sema/SemaRISCV.cpp
@@ -131,10 +131,24 @@ static QualType RVVType2Qual(ASTContext &Context, const 
RVVType *Type) {
     QT = Context.BoolTy;
     break;
   case ScalarTypeKind::SignedInteger:
-    QT = Context.getIntTypeForBitwidth(Type->getElementBitwidth(), true);
+    // getIntTypeForBitwidth() picks a type purely by matching bit width, so
+    // on LP64 targets a 64-bit element would resolve to "long" even if the
+    // target's actual int64_t is "long long" (e.g. OpenBSD). Go through the
+    // target's Int64Type so this matches int64_t/uint64_t.
+    if (Type->getElementBitwidth() == 64)
+      QT = Context.getTargetInfo().getInt64Type() == TargetInfo::SignedLong
+               ? Context.LongTy
+               : Context.LongLongTy;
+    else
+      QT = Context.getIntTypeForBitwidth(Type->getElementBitwidth(), true);
     break;
   case ScalarTypeKind::UnsignedInteger:
-    QT = Context.getIntTypeForBitwidth(Type->getElementBitwidth(), false);
+    if (Type->getElementBitwidth() == 64)
+      QT = Context.getTargetInfo().getInt64Type() == TargetInfo::SignedLong
+               ? Context.UnsignedLongTy
+               : Context.UnsignedLongLongTy;
+    else
+      QT = Context.getIntTypeForBitwidth(Type->getElementBitwidth(), false);
     break;
   case ScalarTypeKind::FloatE4M3:
   case ScalarTypeKind::FloatE5M2: {
diff --git a/clang/test/Sema/riscv-rvv-int64-scalar-type.c 
b/clang/test/Sema/riscv-rvv-int64-scalar-type.c
new file mode 100644
index 0000000000000..ebe61314494e7
--- /dev/null
+++ b/clang/test/Sema/riscv-rvv-int64-scalar-type.c
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple riscv64-unknown-openbsd -target-feature +v 
-ffreestanding -fsyntax-only -verify=openbsd %s
+// RUN: %clang_cc1 -triple riscv64-none-linux-gnu -target-feature +v 
-ffreestanding -fsyntax-only -verify=linux %s
+
+// REQUIRES: riscv-registered-target
+
+// RVV intrinsics with a 64-bit scalar/pointer operand (e.g. vse64) must use
+// the target's actual uint64_t/int64_t type, not always "unsigned long":
+// OpenBSD defines uint64_t as "unsigned long long" on every architecture,
+// while riscv64-linux (LP64) defines it as "unsigned long".
+
+#include <stdint.h>
+#include <riscv_vector.h>
+
+// uint64_t* must be accepted on every target, regardless of whether the
+// target's uint64_t happens to be "unsigned long" or "unsigned long long".
+void test_uint64_ok(uint64_t *p, vuint64m1_t v, size_t vl) {
+  __riscv_vse64_v_u64m1(p, v, vl);
+}
+
+// "unsigned long *" is only the right type for the pointee on riscv64-linux
+// (where uint64_t is "unsigned long"); on OpenBSD, uint64_t is
+// "unsigned long long", so this should be an incompatible pointer type.
+void test_unsigned_long(unsigned long *p, vuint64m1_t v, size_t vl) {
+  __riscv_vse64_v_u64m1(p, v, vl);
+  // openbsd-error@-1 {{incompatible pointer types passing 'unsigned long *' 
to parameter of type 'unsigned long long *'}}
+  // openbsd-note@-2 {{passing argument to parameter here}}
+}
+
+// Conversely, "unsigned long long *" is only correct on OpenBSD; on
+// riscv64-linux, uint64_t is "unsigned long", so this should fail there.
+void test_unsigned_long_long(unsigned long long *p, vuint64m1_t v, size_t vl) {
+  __riscv_vse64_v_u64m1(p, v, vl);
+  // linux-error@-1 {{incompatible pointer types passing 'unsigned long long 
*' to parameter of type 'unsigned long *'}}
+  // linux-note@-2 {{passing argument to parameter here}}
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to