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

Clang format fixes


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/test/Sema/callingconv-darwin_abi.c
  clang/test/Sema/darwin_abi-sysv_abi.c
  clang/test/Sema/darwin_abi-win64.c
  clang/test/Sema/no_callconv.cpp
  clang/test/Sema/varargs-aarch64.c
  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
@@ -565,6 +565,12 @@
     }
   }
 
+  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,25 @@
   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 +222,8 @@
     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 +294,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
@@ -881,6 +881,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
@@ -4464,6 +4464,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;
   }
 }
 
@@ -4479,7 +4484,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;
@@ -4691,7 +4698,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.
@@ -6904,6 +6911,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 =
@@ -7004,11 +7067,17 @@
                                             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
@@ -375,9 +375,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 +383,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;
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
@@ -2072,6 +2072,7 @@
 ///   ::= 'spir_kernel'
 ///   ::= 'x86_64_sysvcc'
 ///   ::= 'win64cc'
+///   ::= 'aarch64_darwincc'
 ///   ::= 'webkit_jscc'
 ///   ::= 'anyregcc'
 ///   ::= 'preserve_mostcc'
@@ -2108,10 +2109,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/Sema/varargs-aarch64.c
===================================================================
--- clang/test/Sema/varargs-aarch64.c
+++ clang/test/Sema/varargs-aarch64.c
@@ -9,3 +9,8 @@
   __builtin_va_list ap;
   __builtin_va_start(ap, a); // expected-error {{'va_start' used in Win64 ABI function}}
 }
+
+void __attribute__((darwin_abi)) f3(int a, ...) {
+  __builtin_va_list ap;
+  __builtin_va_start(ap, a); // that is explicitely supported
+}
Index: clang/test/Sema/no_callconv.cpp
===================================================================
--- clang/test/Sema/no_callconv.cpp
+++ clang/test/Sema/no_callconv.cpp
@@ -9,6 +9,7 @@
 void __attribute__((vectorcall)) funcA() {} // expected-error {{'vectorcall' calling convention is not supported for this target}}
 void __attribute__((regcall)) funcB() {} // expected-error {{'regcall' calling convention is not supported for this target}}
 void __attribute__((ms_abi)) funcH() {} // expected-error {{'ms_abi' calling convention is not supported for this target}}
+void __attribute__((darwin_abi)) funcDW() {}    // expected-error {{'darwin_abi' calling convention is not supported for this target}}
 void __attribute__((intel_ocl_bicc)) funcJ() {} // expected-error {{'intel_ocl_bicc' calling convention is not supported for this target}}
 void __attribute__((swiftcall)) funcK() {} // expected-error {{'swiftcall' calling convention is not supported for this target}}
 void __attribute__((pascal)) funcG() {} // expected-error {{'pascal' calling convention is not supported for this target}}
@@ -38,6 +39,8 @@
 void __attribute__((stdcall)) funcD() {} // expected-warning {{'stdcall' calling convention is not supported for this target}}
 void __attribute__((fastcall)) funcE() {} // expected-warning {{'fastcall' calling convention is not supported for this target}}
 void __attribute__((thiscall)) funcF() {} // expected-warning {{'thiscall' calling convention is not supported for this target}}
+// darwin_abi is only supported for ARM64/Linux targets
+void __attribute__((darwin_abi)) funcDW() {} // expected-warning {{'darwin_abi' calling convention is not supported for this target}}
 #endif
 
 void __attribute__((sysv_abi)) funcI() {}
Index: clang/test/Sema/darwin_abi-win64.c
===================================================================
--- /dev/null
+++ clang/test/Sema/darwin_abi-win64.c
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-unknown-windows-msvc %s
+
+void __attribute__((darwin_abi)) foo(void); // expected-warning{{'darwin_abi' calling convention is not supported for this target}}
Index: clang/test/Sema/darwin_abi-sysv_abi.c
===================================================================
--- /dev/null
+++ clang/test/Sema/darwin_abi-sysv_abi.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-pc-linux-gnu %s
+// Based on ms_abi-sysv_abi.c
+
+// CC qualifier can be applied only to functions
+int __attribute__((darwin_abi)) var1;   // expected-warning{{'darwin_abi' only applies to function types; type here is 'int'}}
+void __attribute__((darwin_abi)) foo(); // valid declaration
+
+// CC qualifier attribute does not take any argument
+void __attribute__((darwin_abi("arg"))) foo0(void); // expected-error{{'darwin_abi' attribute takes no arguments}}
+
+// Different CC qualifiers are not compatible
+void __attribute__((darwin_abi, sysv_abi)) foo1(void); // expected-error{{cdecl and darwin_abi attributes are not compatible}}
+void __attribute__((darwin_abi)) foo2();               // expected-note{{previous declaration is here}}
+void __attribute__((sysv_abi)) foo2(void);             // expected-error{{function declared 'cdecl' here was previously declared 'darwin_abi'}}
+
+void bar(int i, int j) __attribute__((darwin_abi, cdecl)); // expected-error{{cdecl and darwin_abi attributes are not compatible}}
Index: clang/test/Sema/callingconv-darwin_abi.c
===================================================================
--- /dev/null
+++ clang/test/Sema/callingconv-darwin_abi.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-pc-linux-gnu %s
+
+void __attribute__((sysv_abi)) foo(void);
+void (*pfoo)(void) = foo; // valid declaration
+
+void __attribute__((darwin_abi)) bar(void);
+void (*pbar)(void) = bar;                                   // expected-warning{{incompatible function pointer types}}
+void(__attribute__((darwin_abi)) * pbar_valid)(void) = bar; // valid declaration
+
+void(__attribute__((darwin_abi)) * pfoo2)(void) = foo; // expected-warning{{incompatible function pointer types}}
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* {{.*}} %[[THIS:.*]])
+A::A() {
+  // CHECK: ret %struct.A* %[[THIS]]
+}
+
+// CHECK: define aarch64_darwincc {{.*}} %struct.A* @_ZN1AD2Ev(%struct.A* {{.*}} %[[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:                                            \
@@ -7326,6 +7327,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
@@ -4605,6 +4605,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;
@@ -4773,6 +4776,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;
@@ -7970,6 +7977,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
@@ -5428,9 +5428,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,
@@ -5439,12 +5446,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,
@@ -5647,7 +5655,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.
@@ -5663,7 +5672,7 @@
       if (EIT->getNumBits() > 128)
         return getNaturalAlignIndirect(Ty);
 
-    return (isPromotableIntegerTypeForABI(Ty) && isDarwinPCS()
+    return (isPromotableIntegerTypeForABI(Ty) && isDarwinPCS(CConv)
                 ? ABIArgInfo::getExtend(Ty)
                 : ABIArgInfo::getDirect());
   }
@@ -5680,7 +5689,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
@@ -5726,8 +5735,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();
 
@@ -5750,7 +5759,7 @@
       if (EIT->getNumBits() > 128)
         return getNaturalAlignIndirect(RetTy);
 
-    return (isPromotableIntegerTypeForABI(RetTy) && isDarwinPCS()
+    return (isPromotableIntegerTypeForABI(RetTy) && isDarwinPCS(CConv)
                 ? ABIArgInfo::getExtend(RetTy)
                 : ABIArgInfo::getDirect());
   }
@@ -5853,7 +5862,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,18 @@
     UseARMGuardVarABI(UseARMGuardVarABI),
     Use32BitVTableOffsetABI(false) { }
 
+  bool HasThisReturn(GlobalDecl GD) const override {
+    // Returns true if AArch64 Darwin ABI is explicitly used.
+    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
@@ -1237,6 +1237,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
@@ -51,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;
@@ -200,7 +201,7 @@
 }
 
 static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D,
-                                               bool IsWindows) {
+                                               bool IsWindows, bool IsDarwin) {
   // Set the appropriate calling convention for the Function.
   if (D->hasAttr<StdCallAttr>())
     return CC_X86StdCall;
@@ -232,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;
 
@@ -487,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>())
@@ -3896,8 +3902,9 @@
     const auto *MD = Prototype.P.dyn_cast<const ObjCMethodDecl *>();
     if (MD) {
       IsVariadic = MD->isVariadic();
-      ExplicitCC = getCallingConventionForDecl(
-          MD, CGM.getTarget().getTriple().isOSWindows());
+      const auto Triple = CGM.getTarget().getTriple();
+      ExplicitCC = getCallingConventionForDecl(MD, Triple.isOSWindows(),
+                                               Triple.isOSDarwin());
       ArgTypes.assign(MD->param_type_begin() + ParamsToSkip,
                       MD->param_type_end());
     } else {
Index: clang/lib/Basic/Targets/AArch64.cpp
===================================================================
--- clang/lib/Basic/Targets/AArch64.cpp
+++ clang/lib/Basic/Targets/AArch64.cpp
@@ -534,6 +534,7 @@
   case CC_PreserveAll:
   case CC_OpenCLKernel:
   case CC_AArch64VectorCall:
+  case CC_AArch64Darwin:
   case CC_Win64:
     return CCCR_OK;
   default:
@@ -805,6 +806,7 @@
   case CC_Swift:
   case CC_Win64:
     return CCCR_OK;
+  case CC_AArch64Darwin:
   default:
     return CCCR_Warning;
   }
Index: clang/lib/AST/TypePrinter.cpp
===================================================================
--- clang/lib/AST/TypePrinter.cpp
+++ clang/lib/AST/TypePrinter.cpp
@@ -959,6 +959,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;
@@ -1680,6 +1683,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
@@ -3125,6 +3125,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";
@@ -3554,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
@@ -2902,6 +2902,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
@@ -269,6 +269,7 @@
     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
@@ -2321,6 +2321,40 @@
   }];
 }
 
+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.
+
+The differences against the original ARM64 calling convention are `described by
+Apple <https://developer.apple.com/documentation/xcode/writing_arm64_code_for_apple_platforms>`_.
+
+Here is the list of whatthis attribute supports, quoting the aformentioned
+document:
+
+* targeting the Darwin AAPCS ABI for C functions, especially those with
+  variadic arguments. This means everything in section "Pass Arguments to
+  Functions Correctly" and "Update Code that Passes Arguments to Variadic
+  Functions",
+
+* "The ABI requires the complete object (C1) and base-object (C2) constructors
+  to return this to their callers. Similarly, the complete object (D1) and
+  base-object (D2) destructors return this. This behavior matches the ARM
+  32-bit C++ ABI",
+
+* "When passing parameters to a function, Apple platforms ignore empty
+  structures unless those structures have a nontrivial destructor or copy
+  constructor. When passing such nontrivial structures, treat them as
+  aggregates with one byte member in the generic manner",
+
+* properly forwarding variadic arguments from a "darwin_abi function" to a
+  linux one using va_list.
+
+  }];
+}
+
 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
@@ -1506,6 +1506,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