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

Reply via email to