aguinet updated this revision to Diff 298548.
aguinet added a comment.

Fix one clang-tidy warning


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D89490

Files:
  clang/include/clang-c/Index.h
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/Specifiers.h
  clang/lib/AST/ItaniumMangle.cpp
  clang/lib/AST/Type.cpp
  clang/lib/AST/TypePrinter.cpp
  clang/lib/Basic/Targets/AArch64.cpp
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGDebugInfo.cpp
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/lib/CodeGen/TargetInfo.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/CodeGen/darwin_abi.c
  clang/test/CodeGen/darwin_abi_empty_structs.cpp
  clang/test/CodeGen/darwin_abi_vaarg.c
  clang/test/CodeGen/debug-info-cc.c
  clang/test/CodeGenCXX/darwinabi-returnthis.cpp
  clang/tools/libclang/CXType.cpp
  llvm/include/llvm/BinaryFormat/Dwarf.def
  llvm/include/llvm/IR/CallingConv.h
  llvm/lib/AsmParser/LLLexer.cpp
  llvm/lib/AsmParser/LLParser.cpp
  llvm/lib/AsmParser/LLToken.h
  llvm/lib/IR/AsmWriter.cpp
  llvm/lib/Target/AArch64/AArch64CallingConvention.cpp
  llvm/lib/Target/AArch64/AArch64FastISel.cpp
  llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
  llvm/lib/Target/AArch64/AArch64ISelLowering.h
  llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
  llvm/lib/Target/AArch64/AArch64Subtarget.h
  llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
  llvm/test/CodeGen/AArch64/darwin_abi.ll
  llvm/test/CodeGen/AArch64/darwin_abi_vararg.ll

Index: llvm/test/CodeGen/AArch64/darwin_abi_vararg.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/AArch64/darwin_abi_vararg.ll
@@ -0,0 +1,39 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=aarch64-pc-linux | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-pc-linux"
+
+%struct.__va_list = type { i8*, i8*, i8*, i32, i32 }
+
+define dso_local aarch64_darwincc void @foo(i32 %n, ...) local_unnamed_addr #0 {
+; CHECK-LABEL: foo:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    sub sp, sp, #48 // =48
+; CHECK-NEXT:    stp x29, x30, [sp, #32] // 16-byte Folded Spill
+; CHECK-NEXT:    add x29, sp, #32 // =32
+; CHECK-NEXT:    add x8, x29, #16 // =16
+; CHECK-NEXT:    mov x1, sp
+; CHECK-NEXT:    str xzr, [sp, #24]
+; CHECK-NEXT:    str x8, [sp]
+; CHECK-NEXT:    bl vfoo
+; CHECK-NEXT:    ldp x29, x30, [sp, #32] // 16-byte Folded Reload
+; CHECK-NEXT:    add sp, sp, #48 // =48
+; CHECK-NEXT:    ret
+entry:
+  %va = alloca %struct.__va_list, align 8
+  %0 = bitcast %struct.__va_list* %va to i8*
+  call void @llvm.va_start(i8* nonnull %0)
+  call void @vfoo(i32 %n, %struct.__va_list* nonnull %va) #1
+  call void @llvm.va_end(i8* nonnull %0)
+  ret void
+}
+
+declare void @llvm.va_start(i8*) #1
+
+declare dso_local void @vfoo(i32, %struct.__va_list*) local_unnamed_addr #0
+
+declare void @llvm.va_end(i8*) #1
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "frame-pointer"="non-leaf" "target-cpu"="generic" }
+attributes #1 = { nounwind }
Index: llvm/test/CodeGen/AArch64/darwin_abi.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/AArch64/darwin_abi.ll
@@ -0,0 +1,29 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=aarch64-pc-linux | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-pc-linux"
+
+define dso_local aarch64_darwincc signext i16 @f1(i16 signext %a) local_unnamed_addr #0 {
+; CHECK-LABEL: f1:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    add w8, w0, #1 // =1
+; CHECK-NEXT:    sxth w0, w8
+; CHECK-NEXT:    ret
+entry:
+  %add = add i16 %a, 1
+  ret i16 %add
+}
+
+define dso_local aarch64_darwincc zeroext i16 @f2(i16 zeroext %a) local_unnamed_addr #0 {
+; CHECK-LABEL: f2:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    add w8, w0, #1 // =1
+; CHECK-NEXT:    and w0, w8, #0xffff
+; CHECK-NEXT:    ret
+entry:
+  %add = add i16 %a, 1
+  ret i16 %add
+}
+
+attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "frame-pointer"="non-leaf" "target-cpu"="generic" }
Index: llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
===================================================================
--- llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
+++ llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
@@ -474,8 +474,8 @@
   uint64_t StackOffset = Handler.StackUsed;
   if (F.isVarArg()) {
     auto &Subtarget = MF.getSubtarget<AArch64Subtarget>();
-    if (!Subtarget.isTargetDarwin()) {
-        // FIXME: we need to reimplement saveVarArgsRegisters from
+    if (!Subtarget.isCallingConvDarwin(MF.getFunction().getCallingConv())) {
+      // FIXME: we need to reimplement saveVarArgsRegisters from
       // AArch64ISelLowering.
       return false;
     }
Index: llvm/lib/Target/AArch64/AArch64Subtarget.h
===================================================================
--- llvm/lib/Target/AArch64/AArch64Subtarget.h
+++ llvm/lib/Target/AArch64/AArch64Subtarget.h
@@ -549,6 +549,13 @@
     }
   }
 
+  bool isCallingConvDarwin(CallingConv::ID CC) const {
+    if (CC == CallingConv::AArch64Darwin) {
+      return true;
+    }
+    return isTargetDarwin();
+  }
+
   void mirFileLoaded(MachineFunction &MF) const override;
 
   // Return the known range for the bit length of SVE data registers. A value
Index: llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -74,7 +74,6 @@
 const MCPhysReg *
 AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
   assert(MF && "Invalid MachineFunction pointer.");
-
   if (MF->getFunction().getCallingConv() == CallingConv::GHC)
     // GHC set of callee saved regs is empty as all those regs are
     // used for passing STG regs around
@@ -87,22 +86,26 @@
   if (MF->getSubtarget<AArch64Subtarget>().isTargetDarwin())
     return getDarwinCalleeSavedRegs(MF);
 
-  if (MF->getFunction().getCallingConv() == CallingConv::CFGuard_Check)
+  const auto FCC = MF->getFunction().getCallingConv();
+  if (FCC == CallingConv::AArch64Darwin) {
+    return CSR_Darwin_AArch64_AAPCS_SaveList;
+  }
+  if (FCC == CallingConv::CFGuard_Check)
     return CSR_Win_AArch64_CFGuard_Check_SaveList;
   if (MF->getSubtarget<AArch64Subtarget>().isTargetWindows())
     return CSR_Win_AArch64_AAPCS_SaveList;
-  if (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall)
+  if (FCC == CallingConv::AArch64_VectorCall)
     return CSR_AArch64_AAVPCS_SaveList;
-  if (MF->getFunction().getCallingConv() == CallingConv::AArch64_SVE_VectorCall)
+  if (FCC == CallingConv::AArch64_SVE_VectorCall)
     return CSR_AArch64_SVE_AAPCS_SaveList;
   if (MF->getSubtarget<AArch64Subtarget>().getTargetLowering()
           ->supportSwiftError() &&
       MF->getFunction().getAttributes().hasAttrSomewhere(
           Attribute::SwiftError))
     return CSR_AArch64_AAPCS_SwiftError_SaveList;
-  if (MF->getFunction().getCallingConv() == CallingConv::PreserveMost)
+  if (FCC == CallingConv::PreserveMost)
     return CSR_AArch64_RT_MostRegs_SaveList;
-  if (MF->getFunction().getCallingConv() == CallingConv::Win64)
+  if (FCC == CallingConv::Win64)
     // This is for OSes other than Windows; Windows is a separate case further
     // above.
     return CSR_AArch64_AAPCS_X18_SaveList;
@@ -221,6 +224,9 @@
     return getDarwinCallPreservedMask(MF, CC);
   }
 
+  if (CC == CallingConv::AArch64Darwin) {
+    return CSR_Darwin_AArch64_AAPCS_RegMask;
+  }
   if (CC == CallingConv::AArch64_VectorCall)
     return SCS ? CSR_AArch64_AAVPCS_SCS_RegMask : CSR_AArch64_AAVPCS_RegMask;
   if (CC == CallingConv::AArch64_SVE_VectorCall)
@@ -291,7 +297,7 @@
   // In case that the calling convention does not use the same register for
   // both, the function should return NULL (does not currently apply)
   assert(CC != CallingConv::GHC && "should not be GHC calling convention.");
-  if (MF.getSubtarget<AArch64Subtarget>().isTargetDarwin())
+  if (MF.getSubtarget<AArch64Subtarget>().isCallingConvDarwin(CC))
     return CSR_Darwin_AArch64_AAPCS_ThisReturn_RegMask;
   return CSR_AArch64_AAPCS_ThisReturn_RegMask;
 }
Index: llvm/lib/Target/AArch64/AArch64ISelLowering.h
===================================================================
--- llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -873,6 +873,7 @@
   SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerAAPCS_VASTART(SDValue Op, SelectionDAG &DAG) const;
+  SDValue LowerAAPCSFromDarwin_VASTART(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerDarwin_VASTART(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerWin64_VASTART(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -4079,6 +4079,11 @@
    case CallingConv::AArch64_VectorCall:
    case CallingConv::AArch64_SVE_VectorCall:
      return CC_AArch64_AAPCS;
+   case CallingConv::AArch64Darwin:
+     if (!IsVarArg)
+       return CC_AArch64_DarwinPCS;
+     return Subtarget->isTargetILP32() ? CC_AArch64_DarwinPCS_ILP32_VarArg
+                                       : CC_AArch64_DarwinPCS_VarArg;
   }
 }
 
@@ -4094,7 +4099,9 @@
     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
-  bool IsWin64 = Subtarget->isCallingConvWin64(MF.getFunction().getCallingConv());
+  const auto FCC = MF.getFunction().getCallingConv();
+  const bool IsWin64 = Subtarget->isCallingConvWin64(FCC);
+  const bool IsDarwin = Subtarget->isCallingConvDarwin(FCC);
 
   // Assign locations to all of the incoming arguments.
   SmallVector<CCValAssign, 16> ArgLocs;
@@ -4278,7 +4285,7 @@
   // varargs
   AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
   if (isVarArg) {
-    if (!Subtarget->isTargetDarwin() || IsWin64) {
+    if (!IsDarwin || IsWin64) {
       // The AAPCS variadic function ABI is identical to the non-variadic
       // one. As a result there may be more arguments in registers and we should
       // save them for future reference.
@@ -6429,6 +6436,62 @@
   return getAddr(BA, DAG);
 }
 
+SDValue
+AArch64TargetLowering::LowerAAPCSFromDarwin_VASTART(SDValue Op,
+                                                    SelectionDAG &DAG) const {
+  // Linux/AArch64 va_list structure is (AArch64 Procedure Call Standard,
+  // section B.3.):
+  // typedef struct {
+  //  void *stack;
+  //  void *gr_top;
+  //  void *vr_top;
+  //  int gr_offs;
+  //  int vr_offs;
+  // } va_list;
+  // Darwin/AArch64 va_list is just a pointer to the stack, as all variadic
+  // arguments are pushed to the stack.
+  // So we basically set stack as LowerDarwin_VASTART would do, and then set
+  // the gr_offs & vr_offs fields to zero. This will enforce AAPCS functions
+  // processing va_list objects to only get objects from the stack.
+
+  MachineFunction &MF = DAG.getMachineFunction();
+  AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
+  auto PtrVT = getPointerTy(DAG.getDataLayout());
+  SDLoc DL(Op);
+
+  SDValue Chain = Op.getOperand(0);
+  SDValue VAList = Op.getOperand(1);
+  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
+  SmallVector<SDValue, 4> MemOps;
+
+  // void *__stack at offset 0
+  SDValue Stack = DAG.getFrameIndex(FuncInfo->getVarArgsStackIndex(), PtrVT);
+  MemOps.push_back(
+      DAG.getStore(Chain, DL, Stack, VAList, MachinePointerInfo(SV), Align(8)));
+
+  // void *__gr_top at offset 8. Won't be used.
+  const int GPRSize = 0;
+
+  // void *__vr_top at offset 16. Won't be used.
+  const int FPRSize = 0;
+
+  // int __gr_offs at offset 24
+  SDValue GROffsAddr =
+      DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getConstant(24, DL, PtrVT));
+  MemOps.push_back(
+      DAG.getStore(Chain, DL, DAG.getConstant(-GPRSize, DL, MVT::i32),
+                   GROffsAddr, MachinePointerInfo(SV, 24), Align(4)));
+
+  // int __vr_offs at offset 28
+  SDValue VROffsAddr =
+      DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getConstant(28, DL, PtrVT));
+  MemOps.push_back(
+      DAG.getStore(Chain, DL, DAG.getConstant(-FPRSize, DL, MVT::i32),
+                   VROffsAddr, MachinePointerInfo(SV, 28), Align(4)));
+
+  return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOps);
+}
+
 SDValue AArch64TargetLowering::LowerDarwin_VASTART(SDValue Op,
                                                  SelectionDAG &DAG) const {
   AArch64FunctionInfo *FuncInfo =
@@ -6529,11 +6592,19 @@
                                             SelectionDAG &DAG) const {
   MachineFunction &MF = DAG.getMachineFunction();
 
-  if (Subtarget->isCallingConvWin64(MF.getFunction().getCallingConv()))
+  const auto FCC = MF.getFunction().getCallingConv();
+  if (Subtarget->isCallingConvWin64(FCC))
     return LowerWin64_VASTART(Op, DAG);
-  else if (Subtarget->isTargetDarwin())
-    return LowerDarwin_VASTART(Op, DAG);
-  else
+  else if (Subtarget->isCallingConvDarwin(FCC)) {
+    if (Subtarget->isTargetDarwin()) {
+      return LowerDarwin_VASTART(Op, DAG);
+    }
+    if (!Subtarget->isTargetWindows()) {
+      return LowerAAPCSFromDarwin_VASTART(Op, DAG);
+    }
+    report_fatal_error("can't lower Darwin vaarg if target OS isn't Darwin or "
+                       "has an official AAPCS ABI (e.g. Linux)");
+  } else
     return LowerAAPCS_VASTART(Op, DAG);
 }
 
Index: llvm/lib/Target/AArch64/AArch64FastISel.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64FastISel.cpp
+++ llvm/lib/Target/AArch64/AArch64FastISel.cpp
@@ -350,7 +350,8 @@
     return CC_AArch64_GHC;
   if (CC == CallingConv::CFGuard_Check)
     return CC_AArch64_Win64_CFGuard_Check;
-  return Subtarget->isTargetDarwin() ? CC_AArch64_DarwinPCS : CC_AArch64_AAPCS;
+  return Subtarget->isCallingConvDarwin(CC) ? CC_AArch64_DarwinPCS
+                                            : CC_AArch64_AAPCS;
 }
 
 unsigned AArch64FastISel::fastMaterializeAlloca(const AllocaInst *AI) {
Index: llvm/lib/Target/AArch64/AArch64CallingConvention.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64CallingConvention.cpp
+++ llvm/lib/Target/AArch64/AArch64CallingConvention.cpp
@@ -145,7 +145,9 @@
   for (auto Reg : RegList)
     State.AllocateReg(Reg);
 
-  const Align SlotAlign = Subtarget.isTargetDarwin() ? Align(1) : Align(8);
+  const auto FCC = State.getMachineFunction().getFunction().getCallingConv();
+  const Align SlotAlign =
+      Subtarget.isCallingConvDarwin(FCC) ? Align(1) : Align(8);
 
   return finishStackBlock(PendingMembers, LocVT, ArgFlags, State, SlotAlign);
 }
Index: llvm/lib/IR/AsmWriter.cpp
===================================================================
--- llvm/lib/IR/AsmWriter.cpp
+++ llvm/lib/IR/AsmWriter.cpp
@@ -374,6 +374,9 @@
   case CallingConv::PTX_Device:    Out << "ptx_device"; break;
   case CallingConv::X86_64_SysV:   Out << "x86_64_sysvcc"; break;
   case CallingConv::Win64:         Out << "win64cc"; break;
+  case CallingConv::AArch64Darwin:
+    Out << "aarch64_darwincc";
+    break;
   case CallingConv::SPIR_FUNC:     Out << "spir_func"; break;
   case CallingConv::SPIR_KERNEL:   Out << "spir_kernel"; break;
   case CallingConv::Swift:         Out << "swiftcc"; break;
Index: llvm/lib/AsmParser/LLToken.h
===================================================================
--- llvm/lib/AsmParser/LLToken.h
+++ llvm/lib/AsmParser/LLToken.h
@@ -152,6 +152,7 @@
   kw_spir_func,
   kw_x86_64_sysvcc,
   kw_win64cc,
+  kw_aarch64_darwincc,
   kw_webkit_jscc,
   kw_anyregcc,
   kw_swiftcc,
Index: llvm/lib/AsmParser/LLParser.cpp
===================================================================
--- llvm/lib/AsmParser/LLParser.cpp
+++ llvm/lib/AsmParser/LLParser.cpp
@@ -2014,6 +2014,7 @@
 ///   ::= 'spir_kernel'
 ///   ::= 'x86_64_sysvcc'
 ///   ::= 'win64cc'
+///   ::= 'aarch64_darwincc'
 ///   ::= 'webkit_jscc'
 ///   ::= 'anyregcc'
 ///   ::= 'preserve_mostcc'
@@ -2054,35 +2055,96 @@
   case lltok::kw_aarch64_sve_vector_pcs:
     CC = CallingConv::AArch64_SVE_VectorCall;
     break;
-  case lltok::kw_msp430_intrcc:  CC = CallingConv::MSP430_INTR; break;
-  case lltok::kw_avr_intrcc:     CC = CallingConv::AVR_INTR; break;
-  case lltok::kw_avr_signalcc:   CC = CallingConv::AVR_SIGNAL; break;
-  case lltok::kw_ptx_kernel:     CC = CallingConv::PTX_Kernel; break;
-  case lltok::kw_ptx_device:     CC = CallingConv::PTX_Device; break;
-  case lltok::kw_spir_kernel:    CC = CallingConv::SPIR_KERNEL; break;
-  case lltok::kw_spir_func:      CC = CallingConv::SPIR_FUNC; break;
-  case lltok::kw_intel_ocl_bicc: CC = CallingConv::Intel_OCL_BI; break;
-  case lltok::kw_x86_64_sysvcc:  CC = CallingConv::X86_64_SysV; break;
-  case lltok::kw_win64cc:        CC = CallingConv::Win64; break;
-  case lltok::kw_webkit_jscc:    CC = CallingConv::WebKit_JS; break;
-  case lltok::kw_anyregcc:       CC = CallingConv::AnyReg; break;
-  case lltok::kw_preserve_mostcc:CC = CallingConv::PreserveMost; break;
-  case lltok::kw_preserve_allcc: CC = CallingConv::PreserveAll; break;
-  case lltok::kw_ghccc:          CC = CallingConv::GHC; break;
-  case lltok::kw_swiftcc:        CC = CallingConv::Swift; break;
-  case lltok::kw_x86_intrcc:     CC = CallingConv::X86_INTR; break;
-  case lltok::kw_hhvmcc:         CC = CallingConv::HHVM; break;
-  case lltok::kw_hhvm_ccc:       CC = CallingConv::HHVM_C; break;
-  case lltok::kw_cxx_fast_tlscc: CC = CallingConv::CXX_FAST_TLS; break;
-  case lltok::kw_amdgpu_vs:      CC = CallingConv::AMDGPU_VS; break;
-  case lltok::kw_amdgpu_ls:      CC = CallingConv::AMDGPU_LS; break;
-  case lltok::kw_amdgpu_hs:      CC = CallingConv::AMDGPU_HS; break;
-  case lltok::kw_amdgpu_es:      CC = CallingConv::AMDGPU_ES; break;
-  case lltok::kw_amdgpu_gs:      CC = CallingConv::AMDGPU_GS; break;
-  case lltok::kw_amdgpu_ps:      CC = CallingConv::AMDGPU_PS; break;
-  case lltok::kw_amdgpu_cs:      CC = CallingConv::AMDGPU_CS; break;
-  case lltok::kw_amdgpu_kernel:  CC = CallingConv::AMDGPU_KERNEL; break;
-  case lltok::kw_tailcc:         CC = CallingConv::Tail; break;
+  case lltok::kw_msp430_intrcc:
+    CC = CallingConv::MSP430_INTR;
+    break;
+  case lltok::kw_avr_intrcc:
+    CC = CallingConv::AVR_INTR;
+    break;
+  case lltok::kw_avr_signalcc:
+    CC = CallingConv::AVR_SIGNAL;
+    break;
+  case lltok::kw_ptx_kernel:
+    CC = CallingConv::PTX_Kernel;
+    break;
+  case lltok::kw_ptx_device:
+    CC = CallingConv::PTX_Device;
+    break;
+  case lltok::kw_spir_kernel:
+    CC = CallingConv::SPIR_KERNEL;
+    break;
+  case lltok::kw_spir_func:
+    CC = CallingConv::SPIR_FUNC;
+    break;
+  case lltok::kw_intel_ocl_bicc:
+    CC = CallingConv::Intel_OCL_BI;
+    break;
+  case lltok::kw_x86_64_sysvcc:
+    CC = CallingConv::X86_64_SysV;
+    break;
+  case lltok::kw_win64cc:
+    CC = CallingConv::Win64;
+    break;
+  case lltok::kw_aarch64_darwincc:
+    CC = CallingConv::AArch64Darwin;
+    break;
+  case lltok::kw_webkit_jscc:
+    CC = CallingConv::WebKit_JS;
+    break;
+  case lltok::kw_anyregcc:
+    CC = CallingConv::AnyReg;
+    break;
+  case lltok::kw_preserve_mostcc:
+    CC = CallingConv::PreserveMost;
+    break;
+  case lltok::kw_preserve_allcc:
+    CC = CallingConv::PreserveAll;
+    break;
+  case lltok::kw_ghccc:
+    CC = CallingConv::GHC;
+    break;
+  case lltok::kw_swiftcc:
+    CC = CallingConv::Swift;
+    break;
+  case lltok::kw_x86_intrcc:
+    CC = CallingConv::X86_INTR;
+    break;
+  case lltok::kw_hhvmcc:
+    CC = CallingConv::HHVM;
+    break;
+  case lltok::kw_hhvm_ccc:
+    CC = CallingConv::HHVM_C;
+    break;
+  case lltok::kw_cxx_fast_tlscc:
+    CC = CallingConv::CXX_FAST_TLS;
+    break;
+  case lltok::kw_amdgpu_vs:
+    CC = CallingConv::AMDGPU_VS;
+    break;
+  case lltok::kw_amdgpu_ls:
+    CC = CallingConv::AMDGPU_LS;
+    break;
+  case lltok::kw_amdgpu_hs:
+    CC = CallingConv::AMDGPU_HS;
+    break;
+  case lltok::kw_amdgpu_es:
+    CC = CallingConv::AMDGPU_ES;
+    break;
+  case lltok::kw_amdgpu_gs:
+    CC = CallingConv::AMDGPU_GS;
+    break;
+  case lltok::kw_amdgpu_ps:
+    CC = CallingConv::AMDGPU_PS;
+    break;
+  case lltok::kw_amdgpu_cs:
+    CC = CallingConv::AMDGPU_CS;
+    break;
+  case lltok::kw_amdgpu_kernel:
+    CC = CallingConv::AMDGPU_KERNEL;
+    break;
+  case lltok::kw_tailcc:
+    CC = CallingConv::Tail;
+    break;
   case lltok::kw_cc: {
       Lex.Lex();
       return ParseUInt32(CC);
Index: llvm/lib/AsmParser/LLLexer.cpp
===================================================================
--- llvm/lib/AsmParser/LLLexer.cpp
+++ llvm/lib/AsmParser/LLLexer.cpp
@@ -605,6 +605,7 @@
   KEYWORD(intel_ocl_bicc);
   KEYWORD(x86_64_sysvcc);
   KEYWORD(win64cc);
+  KEYWORD(aarch64_darwincc);
   KEYWORD(x86_regcallcc);
   KEYWORD(webkit_jscc);
   KEYWORD(swiftcc);
Index: llvm/include/llvm/IR/CallingConv.h
===================================================================
--- llvm/include/llvm/IR/CallingConv.h
+++ llvm/include/llvm/IR/CallingConv.h
@@ -241,6 +241,8 @@
     /// The remainder matches the regular calling convention.
     WASM_EmscriptenInvoke = 99,
 
+    AArch64Darwin = 100,
+
     /// The highest possible calling convention ID. Must be some 2^k - 1.
     MaxID = 1023
   };
Index: llvm/include/llvm/BinaryFormat/Dwarf.def
===================================================================
--- llvm/include/llvm/BinaryFormat/Dwarf.def
+++ llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -788,6 +788,7 @@
 HANDLE_DW_CC(0xc9, LLVM_PreserveMost)
 HANDLE_DW_CC(0xca, LLVM_PreserveAll)
 HANDLE_DW_CC(0xcb, LLVM_X86RegCall)
+HANDLE_DW_CC(0xcc, LLVM_AArch64Darwin)
 // From GCC source code (include/dwarf2.h): This DW_CC_ value is not currently
 // generated by any toolchain.  It is used internally to GDB to indicate OpenCL C
 // functions that have been compiled with the IBM XL C for OpenCL compiler and use
Index: clang/tools/libclang/CXType.cpp
===================================================================
--- clang/tools/libclang/CXType.cpp
+++ clang/tools/libclang/CXType.cpp
@@ -658,6 +658,7 @@
       TCALLINGCONV(X86RegCall);
       TCALLINGCONV(X86VectorCall);
       TCALLINGCONV(AArch64VectorCall);
+      TCALLINGCONV(AArch64Darwin);
       TCALLINGCONV(Win64);
       TCALLINGCONV(X86_64SysV);
       TCALLINGCONV(AAPCS);
Index: clang/test/CodeGenCXX/darwinabi-returnthis.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/darwinabi-returnthis.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple aarch64-pc-linux-gnu -mconstructor-aliases %s -emit-llvm -O1 -o - | FileCheck %s
+
+struct A {
+  __attribute__((darwin_abi)) A();
+  __attribute__((darwin_abi)) ~A();
+};
+
+// CHECK: define aarch64_darwincc %struct.A* @_ZN1AC2Ev(%struct.A* readnone returned %[[THIS:.*]])
+A::A() {
+  // CHECK: ret %struct.A* %[[THIS]]
+}
+
+// CHECK: define aarch64_darwincc %struct.A* @_ZN1AD2Ev(%struct.A* readnone returned %[[THIS:.*]])
+A::~A() {
+  // CHECK: ret %struct.A* %[[THIS]]
+}
Index: clang/test/CodeGen/debug-info-cc.c
===================================================================
--- clang/test/CodeGen/debug-info-cc.c
+++ clang/test/CodeGen/debug-info-cc.c
@@ -2,26 +2,7 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=WINDOWS
 // RUN: %clang_cc1 -triple i386-pc-linux-gnu -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=LINUX32
 // RUN: %clang_cc1 -triple armv7--linux-gnueabihf -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=ARM
-
-//  enum CallingConv {
-//    CC_C,           // __attribute__((cdecl))
-//    CC_X86StdCall,  // __attribute__((stdcall))
-//    CC_X86FastCall, // __attribute__((fastcall))
-//    CC_X86ThisCall, // __attribute__((thiscall))
-//    CC_X86VectorCall, // __attribute__((vectorcall))
-//    CC_X86Pascal,   // __attribute__((pascal))
-//    CC_Win64,       // __attribute__((ms_abi))
-//    CC_X86_64SysV,  // __attribute__((sysv_abi))
-//    CC_X86RegCall, // __attribute__((regcall))
-//    CC_AAPCS,       // __attribute__((pcs("aapcs")))
-//    CC_AAPCS_VFP,   // __attribute__((pcs("aapcs-vfp")))
-//    CC_IntelOclBicc, // __attribute__((intel_ocl_bicc))
-//    CC_SpirFunction, // default for OpenCL functions on SPIR target
-//    CC_OpenCLKernel, // inferred for OpenCL kernels
-//    CC_Swift,        // __attribute__((swiftcall))
-//    CC_PreserveMost, // __attribute__((preserve_most))
-//    CC_PreserveAll,  // __attribute__((preserve_all))
-//  };
+// RUN: %clang_cc1 -triple aarch64-pc-linux -o - -emit-llvm -debug-info-kind=limited %s | FileCheck %s --check-prefix=AARCH64
 
 #ifdef __x86_64__
 
@@ -118,3 +99,11 @@
   return a+b;
 }
 #endif
+
+#if defined(__aarch64__) && defined(__linux__)
+// AARCH64: !DISubprogram({{.*}}"add_darwinabi", {{.*}}type: ![[FTY:[0-9]+]]
+// AARCH64: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_AArch64Darwin,
+__attribute__((darwin_abi)) int add_darwinabi(int a, int b) {
+  return a + b;
+}
+#endif
Index: clang/test/CodeGen/darwin_abi_vaarg.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/darwin_abi_vaarg.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple aarch64-pc-linux -emit-llvm %s -o - |FileCheck %s
+// Check that va_arg used inside a function with the darwin_abi attribute still
+// uses the Linux ABI lowering.
+
+// CHECK: define internal aarch64_darwincc i32 @vfoo(i32 %n, %struct.__va_list* %[[VA:[[:alnum:]_]+]])
+// CHECK: getelementptr inbounds %struct.__va_list, %struct.__va_list* %[[VA]], i32 0, i32 3
+__attribute__((darwin_abi, noinline)) static int vfoo(int n, __builtin_va_list va) {
+  int res = 0;
+  for (int i = 0; i < n; ++i) {
+    res += __builtin_va_arg(va, int);
+  }
+  return res;
+}
+
+int foo(int n, ...) {
+  __builtin_va_list va;
+  __builtin_va_start(va, n);
+  const int res = vfoo(n, va);
+  __builtin_va_end(va);
+  return res;
+}
Index: clang/test/CodeGen/darwin_abi_empty_structs.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/darwin_abi_empty_structs.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 %s -S -emit-llvm -o - -O1 -triple aarch64-pc-linux | FileCheck %s
+// Verify that "when passing parameters to a function, Apple platforms ignore
+// empty structures unless those structures have a nontrivial destructor or
+// copy constructor." when using darwin_abi
+
+struct Empty {};
+
+__attribute__((darwin_abi)) void foo(int n, Empty E);
+// CHECK: @_Z3bari(i32 %[[ARG:[[:alnum:]_]+]])
+void bar(int n) {
+  // CHECK: call aarch64_darwincc void @_Z3fooi5Empty(i32 %[[ARG]])
+  return foo(n, Empty{});
+}
+
+// CHECK: declare aarch64_darwincc void @_Z3fooi5Empty(i32)
Index: clang/test/CodeGen/darwin_abi.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/darwin_abi.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple aarch64-pc-linux %s -emit-llvm -o - |FileCheck %s
+// Checks that correct LLVM IR is generated for functions that target
+// the Darwin AArch64 ABI under Linux/AArch64. What we check:
+// * sext/zext on return values and arguments
+// * va_list forwarding from Darwin to Linux support
+
+// CHECK: define aarch64_darwincc signext i16 @f1(i16 signext
+__attribute__((darwin_abi)) short f1(short a) {
+  return a + 1;
+}
+
+// CHECK: define aarch64_darwincc zeroext i16 @f2(i16 zeroext
+__attribute__((darwin_abi)) unsigned short f2(unsigned short a) {
+  return a + 1;
+}
+
+// CHECK: define aarch64_darwincc void @foo(i32 %n, ...)
+// CHECK: call void @llvm.va_start
+void vfoo(int n, __builtin_va_list *va);
+__attribute((darwin_abi)) void foo(int n, ...) {
+  __builtin_va_list va;
+  __builtin_va_start(va, n);
+  vfoo(n, &va);
+  __builtin_va_end(va);
+}
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -120,6 +120,7 @@
   case ParsedAttr::AT_VectorCall:                                              \
   case ParsedAttr::AT_AArch64VectorPcs:                                        \
   case ParsedAttr::AT_MSABI:                                                   \
+  case ParsedAttr::AT_DarwinABI:                                               \
   case ParsedAttr::AT_SysVABI:                                                 \
   case ParsedAttr::AT_Pcs:                                                     \
   case ParsedAttr::AT_IntelOclBicc:                                            \
@@ -7301,6 +7302,8 @@
     return createSimpleAttr<IntelOclBiccAttr>(Ctx, Attr);
   case ParsedAttr::AT_MSABI:
     return createSimpleAttr<MSABIAttr>(Ctx, Attr);
+  case ParsedAttr::AT_DarwinABI:
+    return createSimpleAttr<DarwinABIAttr>(Ctx, Attr);
   case ParsedAttr::AT_SysVABI:
     return createSimpleAttr<SysVABIAttr>(Ctx, Attr);
   case ParsedAttr::AT_PreserveMost:
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -4465,6 +4465,9 @@
   case ParsedAttr::AT_MSABI:
     D->addAttr(::new (S.Context) MSABIAttr(S.Context, AL));
     return;
+  case ParsedAttr::AT_DarwinABI:
+    D->addAttr(::new (S.Context) DarwinABIAttr(S.Context, AL));
+    return;
   case ParsedAttr::AT_SysVABI:
     D->addAttr(::new (S.Context) SysVABIAttr(S.Context, AL));
     return;
@@ -4633,6 +4636,10 @@
     CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C :
                                                              CC_Win64;
     break;
+  case ParsedAttr::AT_DarwinABI:
+    CC = Context.getTargetInfo().getTriple().isOSDarwin() ? CC_C
+                                                          : CC_AArch64Darwin;
+    break;
   case ParsedAttr::AT_SysVABI:
     CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV :
                                                              CC_C;
@@ -7742,6 +7749,7 @@
   case ParsedAttr::AT_SwiftCall:
   case ParsedAttr::AT_VectorCall:
   case ParsedAttr::AT_MSABI:
+  case ParsedAttr::AT_DarwinABI:
   case ParsedAttr::AT_SysVABI:
   case ParsedAttr::AT_Pcs:
   case ParsedAttr::AT_IntelOclBicc:
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -5612,6 +5612,7 @@
   bool IsAArch64 = (TT.getArch() == llvm::Triple::aarch64 ||
                     TT.getArch() == llvm::Triple::aarch64_32);
   bool IsWindows = TT.isOSWindows();
+  bool IsLinux = TT.isOSLinux();
   bool IsMSVAStart = BuiltinID == Builtin::BI__builtin_ms_va_start;
   if (IsX64 || IsAArch64) {
     CallingConv CC = CC_C;
@@ -5627,8 +5628,10 @@
       // On x64 Windows, don't allow this in System V ABI functions.
       // (Yes, that means there's no corresponding way to support variadic
       // System V ABI functions on Windows.)
+      // On Apple ARM64 ABI functions, only allow this on AArch64/Unix.
       if ((IsWindows && CC == CC_X86_64SysV) ||
-          (!IsWindows && CC == CC_Win64))
+          (!IsWindows && CC == CC_Win64) ||
+          (!IsLinux && CC == CC_AArch64Darwin))
         return S.Diag(Fn->getBeginLoc(),
                       diag::err_va_start_used_in_wrong_abi_function)
                << !IsWindows;
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -5446,9 +5446,16 @@
 private:
   ABIKind getABIKind() const { return Kind; }
   bool isDarwinPCS() const { return Kind == DarwinPCS; }
+  bool isDarwinPCS(const unsigned CConv) const {
+    return isDarwinPCS() || CConv == llvm::CallingConv::AArch64Darwin;
+  }
+  bool isDarwinPCS(CGFunctionInfo const &FI) const {
+    return isDarwinPCS(FI.getCallingConvention());
+  }
 
-  ABIArgInfo classifyReturnType(QualType RetTy, bool IsVariadic) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy) const;
+  ABIArgInfo classifyReturnType(QualType RetTy, bool IsVariadic,
+                                unsigned CConv) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy, unsigned CConv) const;
   ABIArgInfo coerceIllegalVector(QualType Ty) const;
   bool isHomogeneousAggregateBaseType(QualType Ty) const override;
   bool isHomogeneousAggregateSmallEnough(const Type *Ty,
@@ -5457,12 +5464,13 @@
   bool isIllegalVectorType(QualType Ty) const;
 
   void computeInfo(CGFunctionInfo &FI) const override {
+    const unsigned CConv = FI.getCallingConvention();
     if (!::classifyReturnType(getCXXABI(), FI, *this))
       FI.getReturnInfo() =
-          classifyReturnType(FI.getReturnType(), FI.isVariadic());
+          classifyReturnType(FI.getReturnType(), FI.isVariadic(), CConv);
 
     for (auto &it : FI.arguments())
-      it.info = classifyArgumentType(it.type);
+      it.info = classifyArgumentType(it.type, CConv);
   }
 
   Address EmitDarwinVAArg(Address VAListAddr, QualType Ty,
@@ -5660,7 +5668,8 @@
   return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
 }
 
-ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const {
+ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty,
+                                                unsigned CConv) const {
   Ty = useFirstFieldIfTransparentUnion(Ty);
 
   // Handle illegal vector types here.
@@ -5676,7 +5685,7 @@
       if (EIT->getNumBits() > 128)
         return getNaturalAlignIndirect(Ty);
 
-    return (isPromotableIntegerTypeForABI(Ty) && isDarwinPCS()
+    return (isPromotableIntegerTypeForABI(Ty) && isDarwinPCS(CConv)
                 ? ABIArgInfo::getExtend(Ty)
                 : ABIArgInfo::getDirect());
   }
@@ -5693,7 +5702,7 @@
   uint64_t Size = getContext().getTypeSize(Ty);
   bool IsEmpty = isEmptyRecord(getContext(), Ty, true);
   if (IsEmpty || Size == 0) {
-    if (!getContext().getLangOpts().CPlusPlus || isDarwinPCS())
+    if (!getContext().getLangOpts().CPlusPlus || isDarwinPCS(CConv))
       return ABIArgInfo::getIgnore();
 
     // GNU C mode. The only argument that gets ignored is an empty one with size
@@ -5739,8 +5748,8 @@
   return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
 }
 
-ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy,
-                                              bool IsVariadic) const {
+ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy, bool IsVariadic,
+                                              unsigned CConv) const {
   if (RetTy->isVoidType())
     return ABIArgInfo::getIgnore();
 
@@ -5763,7 +5772,7 @@
       if (EIT->getNumBits() > 128)
         return getNaturalAlignIndirect(RetTy);
 
-    return (isPromotableIntegerTypeForABI(RetTy) && isDarwinPCS()
+    return (isPromotableIntegerTypeForABI(RetTy) && isDarwinPCS(CConv)
                 ? ABIArgInfo::getExtend(RetTy)
                 : ABIArgInfo::getDirect());
   }
@@ -5866,7 +5875,7 @@
 Address AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr,
                                             QualType Ty,
                                             CodeGenFunction &CGF) const {
-  ABIArgInfo AI = classifyArgumentType(Ty);
+  ABIArgInfo AI = classifyArgumentType(Ty, llvm::CallingConv::C);
   bool IsIndirect = AI.isIndirect();
 
   llvm::Type *BaseTy = CGF.ConvertType(Ty);
Index: clang/lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -65,6 +65,20 @@
     UseARMGuardVarABI(UseARMGuardVarABI),
     Use32BitVTableOffsetABI(false) { }
 
+  bool HasThisReturn(GlobalDecl GD) const override {
+    // Returns true if AArch64 Darwin ABI is explicitly used.
+    const bool IsCtorOrDtor = (isa<CXXConstructorDecl>(GD.getDecl()) ||
+                               (isa<CXXDestructorDecl>(GD.getDecl()) &&
+                                GD.getDtorType() != Dtor_Deleting));
+    if (!IsCtorOrDtor) {
+      return false;
+    }
+    const auto *FTy =
+        cast<FunctionDecl>(GD.getDecl())->getType()->getAs<FunctionType>();
+    const auto FCC = FTy->getCallConv();
+    return FCC == CallingConv::CC_AArch64Darwin;
+  }
+
   bool classifyReturnType(CGFunctionInfo &FI) const override;
 
   RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override {
Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1230,6 +1230,8 @@
     return llvm::dwarf::DW_CC_BORLAND_pascal;
   case CC_Win64:
     return llvm::dwarf::DW_CC_LLVM_Win64;
+  case CC_AArch64Darwin:
+    return llvm::dwarf::DW_CC_LLVM_AArch64Darwin;
   case CC_X86_64SysV:
     return llvm::dwarf::DW_CC_LLVM_X86_64SysV;
   case CC_AAPCS:
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -50,6 +50,8 @@
   case CC_X86FastCall: return llvm::CallingConv::X86_FastCall;
   case CC_X86RegCall: return llvm::CallingConv::X86_RegCall;
   case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall;
+  case CC_AArch64Darwin:
+    return llvm::CallingConv::AArch64Darwin;
   case CC_Win64: return llvm::CallingConv::Win64;
   case CC_X86_64SysV: return llvm::CallingConv::X86_64_SysV;
   case CC_AAPCS: return llvm::CallingConv::ARM_AAPCS;
@@ -198,7 +200,8 @@
                                    FTP);
 }
 
-static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {
+static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows,
+                                               bool IsDarwin) {
   // Set the appropriate calling convention for the Function.
   if (D->hasAttr<StdCallAttr>())
     return CC_X86StdCall;
@@ -230,6 +233,9 @@
   if (D->hasAttr<MSABIAttr>())
     return IsWindows ? CC_C : CC_Win64;
 
+  if (D->hasAttr<DarwinABIAttr>())
+    return IsDarwin ? CC_C : CC_AArch64Darwin;
+
   if (D->hasAttr<SysVABIAttr>())
     return IsWindows ? CC_X86_64SysV : CC_C;
 
@@ -485,7 +491,9 @@
 
   FunctionType::ExtInfo einfo;
   bool IsWindows = getContext().getTargetInfo().getTriple().isOSWindows();
-  einfo = einfo.withCallingConv(getCallingConventionForDecl(MD, IsWindows));
+  bool IsDarwin = getContext().getTargetInfo().getTriple().isOSDarwin();
+  einfo = einfo.withCallingConv(
+      getCallingConventionForDecl(MD, IsWindows, IsDarwin));
 
   if (getContext().getLangOpts().ObjCAutoRefCount &&
       MD->hasAttr<NSReturnsRetainedAttr>())
Index: clang/lib/Basic/Targets/AArch64.cpp
===================================================================
--- clang/lib/Basic/Targets/AArch64.cpp
+++ clang/lib/Basic/Targets/AArch64.cpp
@@ -513,6 +513,7 @@
   case CC_PreserveAll:
   case CC_OpenCLKernel:
   case CC_AArch64VectorCall:
+  case CC_AArch64Darwin:
   case CC_Win64:
     return CCCR_OK;
   default:
Index: clang/lib/AST/TypePrinter.cpp
===================================================================
--- clang/lib/AST/TypePrinter.cpp
+++ clang/lib/AST/TypePrinter.cpp
@@ -957,6 +957,9 @@
     case CC_Win64:
       OS << " __attribute__((ms_abi))";
       break;
+    case CC_AArch64Darwin:
+      OS << " __attribute__((darwin_abi))";
+      break;
     case CC_X86_64SysV:
       OS << " __attribute__((sysv_abi))";
       break;
@@ -1640,6 +1643,9 @@
   case attr::VectorCall: OS << "vectorcall"; break;
   case attr::Pascal: OS << "pascal"; break;
   case attr::MSABI: OS << "ms_abi"; break;
+  case attr::DarwinABI:
+    OS << "darwin_abi";
+    break;
   case attr::SysVABI: OS << "sysv_abi"; break;
   case attr::RegCall: OS << "regcall"; break;
   case attr::Pcs: {
Index: clang/lib/AST/Type.cpp
===================================================================
--- clang/lib/AST/Type.cpp
+++ clang/lib/AST/Type.cpp
@@ -3121,6 +3121,8 @@
   case CC_X86Pascal: return "pascal";
   case CC_X86VectorCall: return "vectorcall";
   case CC_Win64: return "ms_abi";
+  case CC_AArch64Darwin:
+    return "darwin_abi";
   case CC_X86_64SysV: return "sysv_abi";
   case CC_X86RegCall : return "regcall";
   case CC_AAPCS: return "aapcs";
@@ -3548,6 +3550,7 @@
   case attr::AArch64VectorPcs:
   case attr::Pascal:
   case attr::MSABI:
+  case attr::DarwinABI:
   case attr::SysVABI:
   case attr::IntelOclBicc:
   case attr::PreserveMost:
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -2900,6 +2900,8 @@
     return "sysv_abi";
   case CC_Win64:
     return "ms_abi";
+  case CC_AArch64Darwin:
+    return "darwin_abi";
   case CC_Swift:
     return "swiftcall";
   }
Index: clang/include/clang/Basic/Specifiers.h
===================================================================
--- clang/include/clang/Basic/Specifiers.h
+++ clang/include/clang/Basic/Specifiers.h
@@ -268,24 +268,25 @@
 
   /// CallingConv - Specifies the calling convention that a function uses.
   enum CallingConv {
-    CC_C,           // __attribute__((cdecl))
-    CC_X86StdCall,  // __attribute__((stdcall))
-    CC_X86FastCall, // __attribute__((fastcall))
-    CC_X86ThisCall, // __attribute__((thiscall))
-    CC_X86VectorCall, // __attribute__((vectorcall))
-    CC_X86Pascal,   // __attribute__((pascal))
-    CC_Win64,       // __attribute__((ms_abi))
-    CC_X86_64SysV,  // __attribute__((sysv_abi))
-    CC_X86RegCall, // __attribute__((regcall))
-    CC_AAPCS,       // __attribute__((pcs("aapcs")))
-    CC_AAPCS_VFP,   // __attribute__((pcs("aapcs-vfp")))
-    CC_IntelOclBicc, // __attribute__((intel_ocl_bicc))
-    CC_SpirFunction, // default for OpenCL functions on SPIR target
-    CC_OpenCLKernel, // inferred for OpenCL kernels
-    CC_Swift,        // __attribute__((swiftcall))
-    CC_PreserveMost, // __attribute__((preserve_most))
-    CC_PreserveAll,  // __attribute__((preserve_all))
+    CC_C,                 // __attribute__((cdecl))
+    CC_X86StdCall,        // __attribute__((stdcall))
+    CC_X86FastCall,       // __attribute__((fastcall))
+    CC_X86ThisCall,       // __attribute__((thiscall))
+    CC_X86VectorCall,     // __attribute__((vectorcall))
+    CC_X86Pascal,         // __attribute__((pascal))
+    CC_Win64,             // __attribute__((ms_abi))
+    CC_X86_64SysV,        // __attribute__((sysv_abi))
+    CC_X86RegCall,        // __attribute__((regcall))
+    CC_AAPCS,             // __attribute__((pcs("aapcs")))
+    CC_AAPCS_VFP,         // __attribute__((pcs("aapcs-vfp")))
+    CC_IntelOclBicc,      // __attribute__((intel_ocl_bicc))
+    CC_SpirFunction,      // default for OpenCL functions on SPIR target
+    CC_OpenCLKernel,      // inferred for OpenCL kernels
+    CC_Swift,             // __attribute__((swiftcall))
+    CC_PreserveMost,      // __attribute__((preserve_most))
+    CC_PreserveAll,       // __attribute__((preserve_all))
     CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs))
+    CC_AArch64Darwin,     // __attribute__((darwin_abi))
   };
 
   /// Checks whether the given calling convention supports variadic
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -2252,6 +2252,15 @@
   }];
 }
 
+def DarwinABIDocs : Documentation {
+  let Category = DocCatCallingConvs;
+  let Content = [{
+On Linux ARM64 targets, this attribute changes the calling convention of
+a function to match the default convention used on Apple ARM64. This
+attribute has no effect on Apple targets or non-Linux ARM64 targets.
+  }];
+}
+
 def StdCallDocs : Documentation {
   let Category = DocCatCallingConvs;
   let Content = [{
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -1477,6 +1477,12 @@
   let Documentation = [MSABIDocs];
 }
 
+def DarwinABI : DeclOrTypeAttr {
+  let Spellings = [GCC<"darwin_abi">];
+//  let Subjects = [Function, ObjCMethod];
+  let Documentation = [DarwinABIDocs];
+}
+
 def MSP430Interrupt : InheritableAttr, TargetSpecificAttr<TargetMSP430> {
   // NOTE: If you add any additional spellings, ARMInterrupt's, MipsInterrupt's
   // and AnyX86Interrupt's spellings must match.
Index: clang/include/clang-c/Index.h
===================================================================
--- clang/include/clang-c/Index.h
+++ clang/include/clang-c/Index.h
@@ -3394,6 +3394,7 @@
   CXCallingConv_PreserveMost = 14,
   CXCallingConv_PreserveAll = 15,
   CXCallingConv_AArch64VectorCall = 16,
+  CXCallingConv_AArch64Darwin = 17,
 
   CXCallingConv_Invalid = 100,
   CXCallingConv_Unexposed = 200
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to