aguinet updated this revision to Diff 314565.
aguinet marked 4 inline comments as done.
aguinet added a comment.
Rebase on current master, and take into account @aaron.ballman 's fixes
(thanks!).
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
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
@@ -566,6 +566,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
@@ -883,6 +883,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
@@ -4494,6 +4494,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;
}
}
@@ -4509,7 +4514,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;
@@ -4721,7 +4728,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.
@@ -6947,6 +6954,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 =
@@ -7047,11 +7110,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 the 'darwin_abi' attribute.
+
+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
@@ -5698,6 +5698,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;
@@ -5713,8 +5714,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());
+ llvm::Triple 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 what this attribute supports, quoting from the
+aforementioned 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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits