[clang] [clang][RISCV] Always pass & return flexible array member structs indirectly. (PR #148541)
Owen Anderson via cfe-commits
cfe-commits at lists.llvm.org
Sun Jul 13 10:35:22 PDT 2025
https://github.com/resistor created https://github.com/llvm/llvm-project/pull/148541
This fixes an issue reported in https://github.com/llvm/llvm-project/issues/148536 where
writes to flexible array members would sometimes be lost if the struct happened to hit
one of the cases where it would be passed in GPRs rather than on the stack.
>From 83495625bddb6e4e5fce6bb11d655c6e1628c5e0 Mon Sep 17 00:00:00 2001
From: Owen Anderson <resistor at mac.com>
Date: Mon, 14 Jul 2025 00:32:55 +0700
Subject: [PATCH] [clang][RISCV] Always pass & return flexible array member
structs indirectly.
This fixes an issue reported in https://github.com/llvm/llvm-project/issues/148536 where
writes to flexible array members would sometimes be lost if the struct happened to hit
one of the cases where it would be passed in GPRs rather than on the stack.
---
clang/lib/CodeGen/Targets/RISCV.cpp | 4 ++
.../RISCV/abi-flexible-array-members.cpp | 46 +++++++++++++++++++
2 files changed, 50 insertions(+)
create mode 100644 clang/test/CodeGen/RISCV/abi-flexible-array-members.cpp
diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index e3232b61a693c..5bf0f29903f56 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -609,6 +609,10 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
if (isEmptyRecord(getContext(), Ty, true) && Size == 0)
return ABIArgInfo::getIgnore();
+ // Structures with flexible arrays are always indirect.
+ if (Ty->isStructureTypeWithFlexibleArrayMember())
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
+
// Pass floating point values via FPRs if possible.
if (IsFixed && Ty->isFloatingType() && !Ty->isComplexType() &&
FLen >= Size && ArgFPRsLeft) {
diff --git a/clang/test/CodeGen/RISCV/abi-flexible-array-members.cpp b/clang/test/CodeGen/RISCV/abi-flexible-array-members.cpp
new file mode 100644
index 0000000000000..b6f25982fd3f6
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/abi-flexible-array-members.cpp
@@ -0,0 +1,46 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --filter "^define |^entry:" --version 2
+// RUN: %clang_cc1 -x c++ -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \
+// RUN: | FileCheck -check-prefixes=CHECK32 %s
+// RUN: %clang_cc1 -x c++ -triple riscv32 -target-feature +f -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \
+// RUN: | FileCheck -check-prefixes=CHECK32 %s
+// RUN: %clang_cc1 -x c++ -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \
+// RUN: | FileCheck -check-prefixes=CHECK64 %s
+// RUN: %clang_cc1 -x c++ -triple riscv64 -target-feature +f -target-feature +d -target-abi lp64d -emit-llvm %s -o - \
+// RUN: | FileCheck -check-prefixes=CHECK64 %s
+
+#include <stdint.h>
+
+// Structs containing C99 flexible array members should always be passed and returned on the stack.
+
+struct s1 {
+ int a;
+ int b[];
+};
+
+// CHECK32-LABEL: define dso_local void @_Z7test_012s1
+// CHECK32-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_S1:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_S1]]) align 4 [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK32: entry:
+//
+// CHECK64-LABEL: define dso_local void @_Z7test_012s1
+// CHECK64-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_S1:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_S1]]) align 4 [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK64: entry:
+//
+struct s1 test_01(struct s1 a) {
+ return a;
+}
+
+
+// CHECK32-LABEL: define dso_local void @_Z7test_02v
+// CHECK32-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_S1:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
+// CHECK32: entry:
+//
+// CHECK64-LABEL: define dso_local void @_Z7test_02v
+// CHECK64-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_S1:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
+// CHECK64: entry:
+//
+struct s1 test_02() {
+ struct s1 r;
+ r.a = 0;
+ r.b[0] = 1;
+ return r;
+}
More information about the cfe-commits
mailing list