aguinet updated this revision to Diff 308202.
aguinet marked 10 inline comments as done.

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
@@ -552,6 +552,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
@@ -73,7 +73,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
@@ -86,22 +85,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;
@@ -220,6 +223,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)
@@ -290,7 +296,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
@@ -874,6 +874,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
@@ -4283,6 +4283,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;
   }
 }
 
@@ -4298,7 +4303,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;
@@ -4510,7 +4517,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.
@@ -6716,6 +6723,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 =
@@ -6816,11 +6879,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
@@ -197,7 +197,9 @@
       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
@@ -352,6 +352,7 @@
   return nullptr;
 }
 
+// clang-format off
 static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
   switch (cc) {
   default:                         Out << "cc" << cc; break;
@@ -375,9 +376,7 @@
   case CallingConv::ARM_AAPCS:     Out << "arm_aapcscc"; break;
   case CallingConv::ARM_AAPCS_VFP: Out << "arm_aapcs_vfpcc"; break;
   case CallingConv::AArch64_VectorCall: Out << "aarch64_vector_pcs"; break;
-  case CallingConv::AArch64_SVE_VectorCall:
-    Out << "aarch64_sve_vector_pcs";
-    break;
+  case CallingConv::AArch64_SVE_VectorCall: Out << "aarch64_sve_vector_pcs"; break;
   case CallingConv::MSP430_INTR:   Out << "msp430_intrcc"; break;
   case CallingConv::AVR_INTR:      Out << "avr_intrcc "; break;
   case CallingConv::AVR_SIGNAL:    Out << "avr_signalcc "; break;
@@ -385,6 +384,7 @@
   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;
@@ -402,6 +402,7 @@
   case CallingConv::AMDGPU_Gfx:    Out << "amdgpu_gfx"; break;
   }
 }
+// clang-format on
 
 enum PrefixType {
   GlobalPrefix,
Index: llvm/lib/AsmParser/LLToken.h
===================================================================
--- llvm/lib/AsmParser/LLToken.h
+++ llvm/lib/AsmParser/LLToken.h
@@ -153,6 +153,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
@@ -2068,6 +2068,7 @@
 ///   ::= 'spir_kernel'
 ///   ::= 'x86_64_sysvcc'
 ///   ::= 'win64cc'
+///   ::= 'aarch64_darwincc'
 ///   ::= 'webkit_jscc'
 ///   ::= 'anyregcc'
 ///   ::= 'preserve_mostcc'
@@ -2104,10 +2105,9 @@
   case lltok::kw_arm_apcscc:     CC = CallingConv::ARM_APCS; break;
   case lltok::kw_arm_aapcscc:    CC = CallingConv::ARM_AAPCS; break;
   case lltok::kw_arm_aapcs_vfpcc:CC = CallingConv::ARM_AAPCS_VFP; break;
+  case lltok::kw_aarch64_darwincc:CC = CallingConv::AArch64Darwin; break;
   case lltok::kw_aarch64_vector_pcs:CC = CallingConv::AArch64_VectorCall; break;
-  case lltok::kw_aarch64_sve_vector_pcs:
-    CC = CallingConv::AArch64_SVE_VectorCall;
-    break;
+  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;
Index: llvm/lib/AsmParser/LLLexer.cpp
===================================================================
--- llvm/lib/AsmParser/LLLexer.cpp
+++ llvm/lib/AsmParser/LLLexer.cpp
@@ -606,6 +606,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
@@ -244,6 +244,9 @@
     /// Calling convention used for AMD graphics targets.
     AMDGPU_Gfx = 100,
 
+    /// The C convention as implemented on Darwin/AArch64.
+    AArch64Darwin = 101,
+
     /// 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:                                            \
@@ -7312,6 +7313,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
@@ -4524,6 +4524,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;
@@ -4692,6 +4695,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;
@@ -7797,6 +7804,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
@@ -5697,6 +5697,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;
@@ -5712,8 +5713,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
@@ -5459,9 +5459,16 @@
 private:
   ABIKind getABIKind() const { return Kind; }
   bool isDarwinPCS() const { return Kind == DarwinPCS; }
+  bool isDarwinPCS(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,
@@ -5470,12 +5477,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,
@@ -5678,7 +5686,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.
@@ -5694,7 +5703,7 @@
       if (EIT->getNumBits() > 128)
         return getNaturalAlignIndirect(Ty);
 
-    return (isPromotableIntegerTypeForABI(Ty) && isDarwinPCS()
+    return (isPromotableIntegerTypeForABI(Ty) && isDarwinPCS(CConv)
                 ? ABIArgInfo::getExtend(Ty)
                 : ABIArgInfo::getDirect());
   }
@@ -5711,7 +5720,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
@@ -5757,8 +5766,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();
 
@@ -5781,7 +5790,7 @@
       if (EIT->getNumBits() > 128)
         return getNaturalAlignIndirect(RetTy);
 
-    return (isPromotableIntegerTypeForABI(RetTy) && isDarwinPCS()
+    return (isPromotableIntegerTypeForABI(RetTy) && isDarwinPCS(CConv)
                 ? ABIArgInfo::getExtend(RetTy)
                 : ABIArgInfo::getDirect());
   }
@@ -5884,7 +5893,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,19 @@
     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>();
+    return FTy->getCallConv() == 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
@@ -1236,6 +1236,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
@@ -43,6 +43,7 @@
 
 /***/
 
+// clang-format off
 unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
   switch (CC) {
   default: return llvm::CallingConv::C;
@@ -50,6 +51,7 @@
   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;
@@ -67,6 +69,7 @@
   case CC_Swift: return llvm::CallingConv::Swift;
   }
 }
+// clang-format on
 
 /// Derives the 'this' type for codegen purposes, i.e. ignoring method CVR
 /// qualification. Either or both of RD and MD may be null. A null RD indicates
@@ -198,7 +201,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 +234,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 +492,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
@@ -520,6 +520,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
@@ -958,6 +958,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;
@@ -1668,6 +1671,7 @@
   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
@@ -3116,6 +3116,7 @@
   return *this;
 }
 
+// clang-format off
 StringRef FunctionType::getNameForCallConv(CallingConv CC) {
   switch (CC) {
   case CC_C: return "cdecl";
@@ -3125,6 +3126,7 @@
   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";
@@ -3140,6 +3142,7 @@
 
   llvm_unreachable("Invalid calling convention.");
 }
+// clang-format on
 
 FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
                                      QualType canonical,
@@ -3552,6 +3555,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
@@ -2885,6 +2885,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
@@ -249,6 +249,7 @@
     ICIS_ListInit  ///< Direct list-initialization.
   };
 
+  // clang-format off
   /// CallingConv - Specifies the calling convention that a function uses.
   enum CallingConv {
     CC_C,           // __attribute__((cdecl))
@@ -269,7 +270,9 @@
     CC_PreserveMost, // __attribute__((preserve_most))
     CC_PreserveAll,  // __attribute__((preserve_all))
     CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs))
+    CC_AArch64Darwin,     // __attribute__((darwin_abi))
   };
+  // clang-format on
 
   /// Checks whether the given calling convention supports variadic
   /// calls. Unprototyped calls also use the variadic call rules.
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -2317,6 +2317,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
@@ -1488,6 +1488,12 @@
   let Documentation = [MSABIDocs];
 }
 
+def DarwinABI : DeclOrTypeAttr {
+  let Spellings = [Clang<"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