Author: Ulrich Weigand Date: 2024-07-18T17:43:28+02:00 New Revision: 9af3628ce7400a96205a4c4468867c3c11dd4b2f
URL: https://github.com/llvm/llvm-project/commit/9af3628ce7400a96205a4c4468867c3c11dd4b2f DIFF: https://github.com/llvm/llvm-project/commit/9af3628ce7400a96205a4c4468867c3c11dd4b2f.diff LOG: [SystemZ] Fix transparent_union calling convention The SystemZ ABI code was missing code to handle the transparent_union extension. Arguments of such types are specified to be passed like the first member of the union, instead of according to the usual ABI calling convention for aggregates. This did not make much difference in practice as the SystemZ ABI already specifies that 1-, 2-, 4- or 8-byte aggregates are passed in registers. However, there *is* a difference if the first member of the transparent union is a scalar integer type smaller than word size - if passed as a scalar, it needs to be zero- or sign-extended to word size, while if passed as aggregate, it is not. Fixed by adding code to handle transparent_union similar to what is done on other targets. Added: Modified: clang/lib/CodeGen/Targets/SystemZ.cpp clang/test/CodeGen/SystemZ/systemz-abi.c Removed: ################################################################################ diff --git a/clang/lib/CodeGen/Targets/SystemZ.cpp b/clang/lib/CodeGen/Targets/SystemZ.cpp index e6b63b6fe093f..4d61f51379346 100644 --- a/clang/lib/CodeGen/Targets/SystemZ.cpp +++ b/clang/lib/CodeGen/Targets/SystemZ.cpp @@ -412,13 +412,16 @@ ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const { } ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const { + // Handle transparent union types. + Ty = useFirstFieldIfTransparentUnion(Ty); + // Handle the generic C++ ABI. if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); // Integers and enums are extended to full register width. if (isPromotableIntegerTypeForABI(Ty)) - return ABIArgInfo::getExtend(Ty); + return ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty)); // Handle vector types and vector-like structure types. Note that // as opposed to float-like structure types, we do not allow any diff --git a/clang/test/CodeGen/SystemZ/systemz-abi.c b/clang/test/CodeGen/SystemZ/systemz-abi.c index 65a2bc9bbb680..3e39425e57f17 100644 --- a/clang/test/CodeGen/SystemZ/systemz-abi.c +++ b/clang/test/CodeGen/SystemZ/systemz-abi.c @@ -173,6 +173,29 @@ union union_double pass_union_double(union union_double arg) { return arg; } // CHECK-LABEL: define{{.*}} void @pass_union_double(ptr dead_on_unwind noalias writable sret(%union.union_double) align 8 %{{.*}}, i64 %{{.*}}) +// Verify that transparent unions are passed like their first member (but returned like a union) + +union tu_char { char a; } __attribute__((transparent_union)); +union tu_char pass_tu_char(union tu_char arg) { return arg; } +// CHECK-LABEL: define{{.*}} void @pass_tu_char(ptr dead_on_unwind noalias writable sret(%union.tu_char) align 1 %{{.*}}, i8 signext %{{.*}}) + +union tu_short { short a; } __attribute__((transparent_union)); +union tu_short pass_tu_short(union tu_short arg) { return arg; } +// CHECK-LABEL: define{{.*}} void @pass_tu_short(ptr dead_on_unwind noalias writable sret(%union.tu_short) align 2 %{{.*}}, i16 signext %{{.*}}) + +union tu_int { int a; } __attribute__((transparent_union)); +union tu_int pass_tu_int(union tu_int arg) { return arg; } +// CHECK-LABEL: define{{.*}} void @pass_tu_int(ptr dead_on_unwind noalias writable sret(%union.tu_int) align 4 %{{.*}}, i32 signext %{{.*}}) + +union tu_long { long a; } __attribute__((transparent_union)); +union tu_long pass_tu_long(union tu_long arg) { return arg; } +// CHECK-LABEL: define{{.*}} void @pass_tu_long(ptr dead_on_unwind noalias writable sret(%union.tu_long) align 8 %{{.*}}, i64 %{{.*}}) + +union tu_ptr { void *a; } __attribute__((transparent_union)); +union tu_ptr pass_tu_ptr(union tu_ptr arg) { return arg; } +// CHECK-LABEL: define{{.*}} void @pass_tu_ptr(ptr dead_on_unwind noalias writable sret(%union.tu_ptr) align 8 %{{.*}}, ptr %{{.*}}) + + // Accessing variable argument lists int va_int(__builtin_va_list l) { return __builtin_va_arg(l, int); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits