mstorsjo updated this revision to Diff 105200.
mstorsjo added a comment.

Did a minor adjustment, to make sure a plain va_arg produces the right kind of 
output, when targeting windows directly (while the rest of the patch mostly is 
about supporting the MS ABI while targeting a different OS).


https://reviews.llvm.org/D34475

Files:
  include/clang/Basic/BuiltinsAArch64.def
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Basic/Specifiers.h
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/Type.cpp
  lib/AST/TypePrinter.cpp
  lib/Basic/Targets.cpp
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/TargetInfo.cpp
  lib/Sema/SemaChecking.cpp
  lib/Sema/SemaDeclAttr.cpp

Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -4279,8 +4279,13 @@
   case AttributeList::AT_VectorCall: CC = CC_X86VectorCall; break;
   case AttributeList::AT_RegCall: CC = CC_X86RegCall; break;
   case AttributeList::AT_MSABI:
-    CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C :
-                                                             CC_X86_64Win64;
+
+    CC = Context.getTargetInfo().getTriple().isOSWindows()
+             ? CC_C
+             : Context.getTargetInfo().getTriple().getArch() ==
+                       llvm::Triple::aarch64
+                   ? CC_AArch64Win64
+                   : CC_X86_64Win64;
     break;
   case AttributeList::AT_SysVABI:
     CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV :
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -1437,6 +1437,9 @@
 
 bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
                                          CallExpr *TheCall) {
+  if (BuiltinID == AArch64::BI__builtin_ms_va_start)
+    return SemaBuiltinVAStart(BuiltinID, TheCall);
+
   if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||
       BuiltinID == AArch64::BI__builtin_arm_ldaex ||
       BuiltinID == AArch64::BI__builtin_arm_strex ||
@@ -3619,12 +3622,15 @@
 static bool checkVAStartABI(Sema &S, unsigned BuiltinID, Expr *Fn) {
   const llvm::Triple &TT = S.Context.getTargetInfo().getTriple();
   bool IsX64 = TT.getArch() == llvm::Triple::x86_64;
+  bool IsAArch64 = TT.getArch() == llvm::Triple::aarch64;
   bool IsWindows = TT.isOSWindows();
-  bool IsMSVAStart = BuiltinID == X86::BI__builtin_ms_va_start;
+  bool IsMSVAStart = BuiltinID == X86::BI__builtin_ms_va_start ||
+                     BuiltinID == AArch64::BI__builtin_ms_va_start;
+  clang::CallingConv CC = CC_C;
+  if (const FunctionDecl *FD = S.getCurFunctionDecl())
+    CC = FD->getType()->getAs<FunctionType>()->getCallConv();
+
   if (IsX64) {
-    clang::CallingConv CC = CC_C;
-    if (const FunctionDecl *FD = S.getCurFunctionDecl())
-      CC = FD->getType()->getAs<FunctionType>()->getCallConv();
     if (IsMSVAStart) {
       // Don't allow this in System V ABI functions.
       if (CC == CC_X86_64SysV || (!IsWindows && CC != CC_X86_64Win64))
@@ -3644,6 +3650,22 @@
     return false;
   }
 
+  if (IsAArch64) {
+    if (IsMSVAStart) {
+      // Don't allow this in AAPCS functions.
+      if (CC == CC_C || (!IsWindows && CC != CC_AArch64Win64))
+        return S.Diag(Fn->getLocStart(),
+                      diag::err_ms_va_start_used_in_aapcs_function);
+    } else {
+      // On aarch64 Unix, don't allow this in Win64 ABI functions.
+      if (!IsWindows && CC == CC_AArch64Win64)
+        return S.Diag(Fn->getLocStart(),
+                      diag::err_va_start_used_in_wrong_abi_function)
+               << !IsWindows;
+    }
+    return false;
+  }
+
   if (IsMSVAStart)
     return S.Diag(Fn->getLocStart(), diag::err_x86_builtin_64_only);
   return false;
Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -4770,10 +4770,11 @@
 
 private:
   ABIKind Kind;
+  bool IsMS;
 
 public:
-  AArch64ABIInfo(CodeGenTypes &CGT, ABIKind Kind)
-    : SwiftABIInfo(CGT), Kind(Kind) {}
+  AArch64ABIInfo(CodeGenTypes &CGT, ABIKind Kind, bool MS)
+      : SwiftABIInfo(CGT), Kind(Kind), IsMS(MS) {}
 
 private:
   ABIKind getABIKind() const { return Kind; }
@@ -4803,9 +4804,12 @@
 
   Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
                     QualType Ty) const override {
-    return isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF)
-                         : EmitAAPCSVAArg(VAListAddr, Ty, CGF);
+    return IsMS ? EmitMSVAArg(CGF, VAListAddr, Ty)
+                : isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF)
+                                : EmitAAPCSVAArg(VAListAddr, Ty, CGF);
   }
+  Address EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
+                      QualType Ty) const override;
 
   bool shouldPassIndirectlyForSwift(CharUnits totalSize,
                                     ArrayRef<llvm::Type*> scalars,
@@ -4822,8 +4826,9 @@
 
 class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
 public:
-  AArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIInfo::ABIKind Kind)
-      : TargetCodeGenInfo(new AArch64ABIInfo(CGT, Kind)) {}
+  AArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIInfo::ABIKind Kind,
+                           bool IsMS)
+      : TargetCodeGenInfo(new AArch64ABIInfo(CGT, Kind, IsMS)) {}
 
   StringRef getARCRetainAutoreleasedReturnValueMarker() const override {
     return "mov\tfp, fp\t\t# marker for objc_retainAutoreleaseReturnValue";
@@ -5312,6 +5317,14 @@
                           TyInfo, SlotSize, /*AllowHigherAlign*/ true);
 }
 
+Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
+                                    QualType Ty) const {
+  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
+                          CGF.getContext().getTypeInfoInChars(Ty),
+                          CharUnits::fromQuantity(8),
+                          /*allowHigherAlign*/ false);
+}
+
 //===----------------------------------------------------------------------===//
 // ARM ABI Implementation
 //===----------------------------------------------------------------------===//
@@ -8448,7 +8461,8 @@
     if (getTarget().getABI() == "darwinpcs")
       Kind = AArch64ABIInfo::DarwinPCS;
 
-    return SetCGInfo(new AArch64TargetCodeGenInfo(Types, Kind));
+    return SetCGInfo(new AArch64TargetCodeGenInfo(
+        Types, Kind, Triple.getOS() == llvm::Triple::Win32));
   }
 
   case llvm::Triple::wasm32:
Index: lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- lib/CodeGen/CGDebugInfo.cpp
+++ lib/CodeGen/CGDebugInfo.cpp
@@ -967,6 +967,7 @@
   case CC_PreserveMost:
   case CC_PreserveAll:
   case CC_X86RegCall:
+  case CC_AArch64Win64:
     return 0;
   }
   return 0;
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -64,6 +64,7 @@
   case CC_PreserveMost: return llvm::CallingConv::PreserveMost;
   case CC_PreserveAll: return llvm::CallingConv::PreserveAll;
   case CC_Swift: return llvm::CallingConv::Swift;
+  case CC_AArch64Win64: return llvm::CallingConv::AArch64_Win64;
   }
 }
 
@@ -191,7 +192,8 @@
                                    FTP, FD);
 }
 
-static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {
+static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows,
+                                               llvm::Triple::ArchType Arch) {
   // Set the appropriate calling convention for the Function.
   if (D->hasAttr<StdCallAttr>())
     return CC_X86StdCall;
@@ -218,7 +220,8 @@
     return CC_IntelOclBicc;
 
   if (D->hasAttr<MSABIAttr>())
-    return IsWindows ? CC_C : CC_X86_64Win64;
+    return IsWindows ? CC_C : Arch == llvm::Triple::aarch64 ? CC_AArch64Win64
+                                                            : CC_X86_64Win64;
 
   if (D->hasAttr<SysVABIAttr>())
     return IsWindows ? CC_X86_64SysV : CC_C;
@@ -463,8 +466,11 @@
   }
 
   FunctionType::ExtInfo einfo;
-  bool IsWindows = getContext().getTargetInfo().getTriple().isOSWindows();
-  einfo = einfo.withCallingConv(getCallingConventionForDecl(MD, IsWindows));
+  const llvm::Triple &TT = getContext().getTargetInfo().getTriple();
+  bool IsWindows = TT.isOSWindows();
+  llvm::Triple::ArchType Arch = TT.getArch();
+  einfo =
+      einfo.withCallingConv(getCallingConventionForDecl(MD, IsWindows, Arch));
 
   if (getContext().getLangOpts().ObjCAutoRefCount &&
       MD->hasAttr<NSReturnsRetainedAttr>())
Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -5352,6 +5352,31 @@
 
 Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
                                                const CallExpr *E) {
+  if (BuiltinID == AArch64::BI__builtin_ms_va_start ||
+      BuiltinID == AArch64::BI__builtin_ms_va_end)
+    return EmitVAStartEnd(EmitMSVAListRef(E->getArg(0)).getPointer(),
+                          BuiltinID == AArch64::BI__builtin_ms_va_start);
+  if (BuiltinID == AArch64::BI__builtin_ms_va_copy) {
+    // Lower this manually. We can't reliably determine whether or not any
+    // given va_copy() is for a Win64 va_list from the calling convention
+    // alone, because it's legal to do this from an AAPCS ABI function.
+    // With opaque pointer types, we won't have enough information in LLVM
+    // IR to determine this from the argument types, either. Best to do it
+    // now, while we have enough information.
+    Address DestAddr = EmitMSVAListRef(E->getArg(0));
+    Address SrcAddr = EmitMSVAListRef(E->getArg(1));
+
+    llvm::Type *BPP = Int8PtrPtrTy;
+
+    DestAddr = Address(Builder.CreateBitCast(DestAddr.getPointer(), BPP, "cp"),
+                       DestAddr.getAlignment());
+    SrcAddr = Address(Builder.CreateBitCast(SrcAddr.getPointer(), BPP, "ap"),
+                      SrcAddr.getAlignment());
+
+    Value *ArgPtr = Builder.CreateLoad(SrcAddr, "ap.val");
+    return Builder.CreateStore(ArgPtr, DestAddr);
+  }
+
   unsigned HintID = static_cast<unsigned>(-1);
   switch (BuiltinID) {
   default: break;
Index: lib/Basic/Targets.cpp
===================================================================
--- lib/Basic/Targets.cpp
+++ lib/Basic/Targets.cpp
@@ -6266,6 +6266,9 @@
     LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
     LongDoubleFormat = &llvm::APFloat::IEEEquad();
 
+    // Make __builtin_ms_va_list available.
+    HasBuiltinMSVaList = true;
+
     // {} in inline assembly are neon specifiers, not assembly variant
     // specifiers.
     NoAsmVariants = true;
@@ -6446,6 +6449,7 @@
     case CC_PreserveMost:
     case CC_PreserveAll:
     case CC_OpenCLKernel:
+    case CC_AArch64Win64:
       return CCCR_OK;
     default:
       return CCCR_Warning;
Index: lib/AST/TypePrinter.cpp
===================================================================
--- lib/AST/TypePrinter.cpp
+++ lib/AST/TypePrinter.cpp
@@ -742,6 +742,9 @@
     case CC_PreserveAll:
       OS << " __attribute__((preserve_all))";
       break;
+    case CC_AArch64Win64:
+      OS << " __attribute__((ms_abi))";
+      break;
     }
   }
 
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp
+++ lib/AST/Type.cpp
@@ -2641,6 +2641,7 @@
   case CC_Swift: return "swiftcall";
   case CC_PreserveMost: return "preserve_most";
   case CC_PreserveAll: return "preserve_all";
+  case CC_AArch64Win64: return "ms_abi";
   }
 
   llvm_unreachable("Invalid calling convention.");
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -2124,6 +2124,7 @@
       llvm_unreachable("Unsupported CC for mangling");
     case CC_X86_64Win64:
     case CC_X86_64SysV:
+    case CC_AArch64Win64:
     case CC_C: Out << 'A'; break;
     case CC_X86Pascal: Out << 'C'; break;
     case CC_X86ThisCall: Out << 'E'; break;
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp
+++ lib/AST/ItaniumMangle.cpp
@@ -2539,6 +2539,7 @@
   case CC_OpenCLKernel:
   case CC_PreserveMost:
   case CC_PreserveAll:
+  case CC_AArch64Win64:
     // FIXME: we should be mangling all of the above.
     return "";
 
Index: include/clang/Basic/Specifiers.h
===================================================================
--- include/clang/Basic/Specifiers.h
+++ include/clang/Basic/Specifiers.h
@@ -247,6 +247,7 @@
     CC_Swift,        // __attribute__((swiftcall))
     CC_PreserveMost, // __attribute__((preserve_most))
     CC_PreserveAll,  // __attribute__((preserve_all))
+    CC_AArch64Win64, // __attribute__((ms_abi))
   };
 
   /// \brief Checks whether the given calling convention supports variadic
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -7981,6 +7981,8 @@
   "'va_start' used in %select{System V|Win64}0 ABI function">;
 def err_ms_va_start_used_in_sysv_function : Error<
   "'__builtin_ms_va_start' used in System V ABI function">;
+def err_ms_va_start_used_in_aapcs_function : Error<
+  "'__builtin_ms_va_start' used in AAPCS ABI function">;
 def warn_second_arg_of_va_start_not_last_named_param : Warning<
   "second argument to 'va_start' is not the last named parameter">,
   InGroup<Varargs>;
Index: include/clang/Basic/BuiltinsAArch64.def
===================================================================
--- include/clang/Basic/BuiltinsAArch64.def
+++ include/clang/Basic/BuiltinsAArch64.def
@@ -61,4 +61,9 @@
 BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc")
 BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
 
+// Win64-compatible va_list functions
+BUILTIN(__builtin_ms_va_start, "vc*&.", "nt")
+BUILTIN(__builtin_ms_va_end, "vc*&", "n")
+BUILTIN(__builtin_ms_va_copy, "vc*&c*&", "n")
+
 #undef BUILTIN
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D34475: [RFC] [AAr... Martin Storsjö via Phabricator via cfe-commits

Reply via email to