efriedma updated this revision to Diff 458290.
efriedma added a comment.
Herald added subscribers: llvm-commits, arichardson.
Herald added a project: LLVM.

Update to handle va_arg


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125419/new/

https://reviews.llvm.org/D125419

Files:
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGen/arm64ec.c
  clang/test/CodeGenCXX/arm64ec.cpp
  llvm/utils/UpdateTestChecks/common.py

Index: llvm/utils/UpdateTestChecks/common.py
===================================================================
--- llvm/utils/UpdateTestChecks/common.py
+++ llvm/utils/UpdateTestChecks/common.py
@@ -327,7 +327,7 @@
 UNUSED_NOTE = 'NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:'
 
 OPT_FUNCTION_RE = re.compile(
-    r'^(\s*;\s*Function\sAttrs:\s(?P<attrs>[\w\s]+?))?\s*define\s+(?:internal\s+)?[^@]*@(?P<func>[\w.$-]+?)\s*'
+    r'^(\s*;\s*Function\sAttrs:\s(?P<attrs>[\w\s]+?))?\s*define\s+(?:internal\s+)?[^@]*@(?P<func>[\w.$-]+?|".+?")\s*'
     r'(?P<args_and_sig>\((\)|(.*?[\w.-]+?)\))[^{]*\{)\n(?P<body>.*?)^\}$',
     flags=(re.M | re.S))
 
Index: clang/test/CodeGenCXX/arm64ec.cpp
===================================================================
--- clang/test/CodeGenCXX/arm64ec.cpp
+++ clang/test/CodeGenCXX/arm64ec.cpp
@@ -2,6 +2,8 @@
 
 // CHECK: @"?g@@YAXUA@@UB@@@Z" = alias void ([2 x float], [4 x float]), void ([2 x float], [4 x float])* @"?g@@$$hYAXUA@@UB@@@Z"
 // CHECK: define dso_local void @"?g@@$$hYAXUA@@UB@@@Z"
+// CHECK: call void (i64, ...) @"?f@@YAXUA@@ZZ"(i64 %{{.*}}, %struct.B* noundef %{{.*}})
 typedef struct { float x[2]; } A;
 typedef struct { float x[4]; } B;
-void g(A a, B b) { }
+void f(A a, ...);
+void g(A a, B b) { f(a, b); }
Index: clang/test/CodeGen/arm64ec.c
===================================================================
--- clang/test/CodeGen/arm64ec.c
+++ clang/test/CodeGen/arm64ec.c
@@ -1,7 +1,62 @@
-// RUN: %clang_cc1 -no-opaque-pointers -triple arm64ec-windows-msvc -emit-llvm -o - %s | FileCheck %s
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals --include-generated-funcs --global-value-regex "f"
+// RUN: %clang_cc1 -opaque-pointers -triple arm64ec-windows-msvc -emit-llvm -o - %s | FileCheck %s
 
-// CHECK: @g = alias void ([2 x float], [4 x float]), void ([2 x float], [4 x float])* @"#g"
-// CHECK: define dso_local void @"#g"
 typedef struct { float x[2]; } A;
 typedef struct { float x[4]; } B;
-void g(A a, B b) { }
+void f(A a, ...) {
+  __builtin_va_list b;
+  __builtin_va_start(b, a);
+  float x = __builtin_va_arg(b, A).x[0];
+  float y = __builtin_va_arg(b, B).x[0];
+}
+void g(A a, B b) { f(a, b); }
+
+//.
+// CHECK: @g = alias void ([2 x float], [4 x float]), ptr @"#g"
+//.
+// CHECK-LABEL: @"#f"(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A:%.*]] = alloca [[STRUCT_A:%.*]], align 4
+// CHECK-NEXT:    [[B:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    [[X:%.*]] = alloca float, align 4
+// CHECK-NEXT:    [[TMP:%.*]] = alloca [[STRUCT_A]], align 4
+// CHECK-NEXT:    [[Y:%.*]] = alloca float, align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = alloca [[STRUCT_B:%.*]], align 4
+// CHECK-NEXT:    [[COERCE_DIVE:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[A]], i32 0, i32 0
+// CHECK-NEXT:    store i64 [[A_COERCE:%.*]], ptr [[COERCE_DIVE]], align 4
+// CHECK-NEXT:    call void @llvm.va_start(ptr [[B]])
+// CHECK-NEXT:    [[ARGP_CUR:%.*]] = load ptr, ptr [[B]], align 8
+// CHECK-NEXT:    [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
+// CHECK-NEXT:    store ptr [[ARGP_NEXT]], ptr [[B]], align 8
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP]], ptr align 8 [[ARGP_CUR]], i64 8, i1 false)
+// CHECK-NEXT:    [[X1:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[TMP]], i32 0, i32 0
+// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x float], ptr [[X1]], i64 0, i64 0
+// CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[ARRAYIDX]], align 4
+// CHECK-NEXT:    store float [[TMP0]], ptr [[X]], align 4
+// CHECK-NEXT:    [[ARGP_CUR3:%.*]] = load ptr, ptr [[B]], align 8
+// CHECK-NEXT:    [[ARGP_NEXT4:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR3]], i64 8
+// CHECK-NEXT:    store ptr [[ARGP_NEXT4]], ptr [[B]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR3]], align 8
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP2]], ptr align 4 [[TMP1]], i64 16, i1 false)
+// CHECK-NEXT:    [[X5:%.*]] = getelementptr inbounds [[STRUCT_B]], ptr [[TMP2]], i32 0, i32 0
+// CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x float], ptr [[X5]], i64 0, i64 0
+// CHECK-NEXT:    [[TMP2:%.*]] = load float, ptr [[ARRAYIDX6]], align 4
+// CHECK-NEXT:    store float [[TMP2]], ptr [[Y]], align 4
+// CHECK-NEXT:    ret void
+//
+//
+// CHECK-LABEL: @"#g"(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A:%.*]] = alloca [[STRUCT_A:%.*]], align 4
+// CHECK-NEXT:    [[B:%.*]] = alloca [[STRUCT_B:%.*]], align 4
+// CHECK-NEXT:    [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_B]], align 4
+// CHECK-NEXT:    [[COERCE_DIVE:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[A]], i32 0, i32 0
+// CHECK-NEXT:    store [2 x float] [[A_COERCE:%.*]], ptr [[COERCE_DIVE]], align 4
+// CHECK-NEXT:    [[COERCE_DIVE1:%.*]] = getelementptr inbounds [[STRUCT_B]], ptr [[B]], i32 0, i32 0
+// CHECK-NEXT:    store [4 x float] [[B_COERCE:%.*]], ptr [[COERCE_DIVE1]], align 4
+// CHECK-NEXT:    [[COERCE_DIVE2:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[A]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr [[COERCE_DIVE2]], align 4
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[BYVAL_TEMP]], ptr align 4 [[B]], i64 16, i1 false)
+// CHECK-NEXT:    call void (i64, ...) @f(i64 [[TMP0]], ptr noundef [[BYVAL_TEMP]])
+// CHECK-NEXT:    ret void
+//
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -2450,6 +2450,12 @@
     return isX86VectorCallAggregateSmallEnough(NumMembers);
   }
 
+  ABIArgInfo classifyArgForArm64ECVarArg(QualType Ty) {
+    unsigned FreeSSERegs = 0;
+    return classify(Ty, FreeSSERegs, /*IsReturnType=*/false,
+                    /*IsVectorCall=*/false, /*IsRegCall=*/false);
+  }
+
 private:
   ABIArgInfo classify(QualType Ty, unsigned &FreeSSERegs, bool IsReturnType,
                       bool IsVectorCall, bool IsRegCall) const;
@@ -5735,6 +5741,13 @@
                                      unsigned CallingConvention) const {
   Ty = useFirstFieldIfTransparentUnion(Ty);
 
+  if (IsVariadic && getTarget().getTriple().isWindowsArm64EC()) {
+    // Arm64EC varargs functions use the x86_64 classification rules,
+    // not the AArch64 ABI rules.
+    WinX86_64ABIInfo Win64ABIInfo(CGT, X86AVXABILevel::None);
+    return Win64ABIInfo.classifyArgForArm64ECVarArg(Ty);
+  }
+
   // Handle illegal vector types here.
   if (isIllegalVectorType(Ty))
     return coerceIllegalVector(Ty);
@@ -6258,9 +6271,16 @@
                                     QualType Ty) const {
   bool IsIndirect = false;
 
-  // Composites larger than 16 bytes are passed by reference.
-  if (isAggregateTypeForABI(Ty) && getContext().getTypeSize(Ty) > 128)
-    IsIndirect = true;
+  if (getTarget().getTriple().isWindowsArm64EC()) {
+    // MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is
+    // not 1, 2, 4, or 8 bytes, must be passed by reference."
+    uint64_t Width = getContext().getTypeSize(Ty);
+    IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
+  } else {
+    // Composites larger than 16 bytes are passed by reference.
+    if (isAggregateTypeForABI(Ty) && getContext().getTypeSize(Ty) > 128)
+      IsIndirect = true;
+  }
 
   return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
                           CGF.getContext().getTypeInfoInChars(Ty),
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to