[clang] [Hexagon] Fix signed constant creation in EmitVAArgFromMemory (PR #180385)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Feb 7 19:45:51 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-hexagon
Author: Brian Cain (androm3da)
<details>
<summary>Changes</summary>
Use ConstantInt::getSigned instead of ConstantInt::get when creating a negative alignment mask in EmitVAArgFromMemory. This is the same fix as commit 8546294db95d (PR #<!-- -->176115) which addressed the issue in EmitVAArgForHexagonLinux.
Added a test case that exercises the EmitVAArgFromMemory alignment path using a struct that is both >8 bytes (to trigger EmitVAArgFromMemory) and has 8-byte alignment (to trigger the alignment masking code).
---
Full diff: https://github.com/llvm/llvm-project/pull/180385.diff
2 Files Affected:
- (modified) clang/lib/CodeGen/Targets/Hexagon.cpp (+1-1)
- (modified) clang/test/CodeGen/hexagon-linux-vararg.c (+33)
``````````diff
diff --git a/clang/lib/CodeGen/Targets/Hexagon.cpp b/clang/lib/CodeGen/Targets/Hexagon.cpp
index f334a7f7012d9..7e4eb0fff8e24 100644
--- a/clang/lib/CodeGen/Targets/Hexagon.cpp
+++ b/clang/lib/CodeGen/Targets/Hexagon.cpp
@@ -210,7 +210,7 @@ Address HexagonABIInfo::EmitVAArgFromMemory(CodeGenFunction &CGF,
// Create a mask which should be "AND"ed
// with (overflow_arg_area + align - 1)
- llvm::Value *Mask = llvm::ConstantInt::get(CGF.Int32Ty, -(int)Align);
+ llvm::Value *Mask = llvm::ConstantInt::getSigned(CGF.Int32Ty, -(int)Align);
__overflow_area_pointer = CGF.Builder.CreateIntToPtr(
CGF.Builder.CreateAnd(AsInt, Mask), __overflow_area_pointer->getType(),
"__overflow_area_pointer.align");
diff --git a/clang/test/CodeGen/hexagon-linux-vararg.c b/clang/test/CodeGen/hexagon-linux-vararg.c
index 11722e27f751c..da3bdd1e40392 100644
--- a/clang/test/CodeGen/hexagon-linux-vararg.c
+++ b/clang/test/CodeGen/hexagon-linux-vararg.c
@@ -153,3 +153,36 @@ int foo(int xx, ...) {
long long test_align(va_list args) {
return va_arg(args, long long);
}
+
+// Struct > 8 bytes with 8-byte alignment to test EmitVAArgFromMemory alignment.
+// This triggers the alignment masking code where -(int)Align must use getSigned.
+struct LargeAligned {
+ long long x;
+ int y;
+};
+
+// CHECK-LABEL: define dso_local i64 @test_large_aligned_vaarg(
+// CHECK-SAME: ptr noundef [[ARGS:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[ARGS_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_LARGEALIGNED:%.*]], align 8
+// CHECK-NEXT: store ptr [[ARGS]], ptr [[ARGS_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARGS_ADDR]], align 4
+// CHECK-NEXT: [[__OVERFLOW_AREA_POINTER_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG:%.*]], ptr [[TMP0]], i32 0, i32 2
+// CHECK-NEXT: [[__OVERFLOW_AREA_POINTER:%.*]] = load ptr, ptr [[__OVERFLOW_AREA_POINTER_P]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[__OVERFLOW_AREA_POINTER]], i64 7
+// CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i32
+// The mask must be -8 (0xFFFFFFF8), not a large positive number.
+// CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], -8
+// CHECK-NEXT: [[__OVERFLOW_AREA_POINTER_ALIGN:%.*]] = inttoptr i32 [[TMP3]] to ptr
+// CHECK-NEXT: [[__OVERFLOW_AREA_POINTER_NEXT:%.*]] = getelementptr i8, ptr [[__OVERFLOW_AREA_POINTER_ALIGN]], i32 16
+// CHECK-NEXT: store ptr [[__OVERFLOW_AREA_POINTER_NEXT]], ptr [[__OVERFLOW_AREA_POINTER_P]], align 4
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 [[S]], ptr align 8 [[__OVERFLOW_AREA_POINTER_ALIGN]], i32 16, i1 false)
+// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGEALIGNED]], ptr [[S]], i32 0, i32 0
+// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr [[X]], align 8
+// CHECK-NEXT: ret i64 [[TMP4]]
+//
+long long test_large_aligned_vaarg(va_list args) {
+ struct LargeAligned s = va_arg(args, struct LargeAligned);
+ return s.x;
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/180385
More information about the cfe-commits
mailing list