summaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorEli Friedman <efriedma@qti.qualcomm.com>2025-11-19 16:45:08 -0800
committerGitHub <noreply@github.com>2025-11-19 16:45:08 -0800
commit4e275f727439af9589ee54bc6ac2e95fac9f63ae (patch)
treec4857f622535fd1108976d63afd4f0c92324dcef /clang/lib/CodeGen
parentb1c4b55118131cdf3d6d47ba31578b2e0cd78ec7 (diff)
[Arm64EC][clang] Implement varargs support in clang. (#152411)
The clang side of the calling convention code for arm64 vs. arm64ec is close enough that this isn't really noticeable in most cases, but the rule for choosing whether to pass a struct directly or indirectly is significantly different. (Adapted from my old patch https://reviews.llvm.org/D125419 .) Fixes #89615.
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/ABIInfo.cpp5
-rw-r--r--clang/lib/CodeGen/ABIInfo.h4
-rw-r--r--clang/lib/CodeGen/Targets/AArch64.cpp44
-rw-r--r--clang/lib/CodeGen/Targets/X86.cpp6
4 files changed, 47 insertions, 12 deletions
diff --git a/clang/lib/CodeGen/ABIInfo.cpp b/clang/lib/CodeGen/ABIInfo.cpp
index acd678193b5a..16005890a070 100644
--- a/clang/lib/CodeGen/ABIInfo.cpp
+++ b/clang/lib/CodeGen/ABIInfo.cpp
@@ -251,6 +251,11 @@ llvm::Value *ABIInfo::createCoercedLoad(Address SrcAddr, const ABIArgInfo &AI,
void ABIInfo::createCoercedStore(llvm::Value *Val, Address DstAddr,
const ABIArgInfo &AI, bool DestIsVolatile,
CodeGenFunction &CGF) const {}
+
+ABIArgInfo ABIInfo::classifyArgForArm64ECVarArg(QualType Ty) const {
+ llvm_unreachable("Only implemented for x86");
+}
+
// Pin the vtable to this file.
SwiftABIInfo::~SwiftABIInfo() = default;
diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h
index 130fcd375e90..576cf8f74244 100644
--- a/clang/lib/CodeGen/ABIInfo.h
+++ b/clang/lib/CodeGen/ABIInfo.h
@@ -138,6 +138,10 @@ public:
virtual void createCoercedStore(llvm::Value *Val, Address DstAddr,
const ABIArgInfo &AI, bool DestIsVolatile,
CodeGenFunction &CGF) const;
+
+ /// Used by Arm64EC calling convention code to call into x86 calling
+ /// convention code for varargs function.
+ virtual ABIArgInfo classifyArgForArm64ECVarArg(QualType Ty) const;
};
/// Target specific hooks for defining how a type should be passed or returned
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index d42fcd8b3237..74bf5531c942 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -24,9 +24,16 @@ namespace {
class AArch64ABIInfo : public ABIInfo {
AArch64ABIKind Kind;
+ std::unique_ptr<TargetCodeGenInfo> WinX86_64CodegenInfo;
+
public:
- AArch64ABIInfo(CodeGenTypes &CGT, AArch64ABIKind Kind)
- : ABIInfo(CGT), Kind(Kind) {}
+ AArch64ABIInfo(CodeGenModule &CGM, AArch64ABIKind Kind)
+ : ABIInfo(CGM.getTypes()), Kind(Kind) {
+ if (getTarget().getTriple().isWindowsArm64EC()) {
+ WinX86_64CodegenInfo =
+ createWinX86_64TargetCodeGenInfo(CGM, X86AVXABILevel::None);
+ }
+ }
bool isSoftFloat() const { return Kind == AArch64ABIKind::AAPCSSoft; }
@@ -119,9 +126,9 @@ public:
class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
public:
- AArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIKind Kind)
- : TargetCodeGenInfo(std::make_unique<AArch64ABIInfo>(CGT, Kind)) {
- SwiftInfo = std::make_unique<AArch64SwiftABIInfo>(CGT);
+ AArch64TargetCodeGenInfo(CodeGenModule &CGM, AArch64ABIKind Kind)
+ : TargetCodeGenInfo(std::make_unique<AArch64ABIInfo>(CGM, Kind)) {
+ SwiftInfo = std::make_unique<AArch64SwiftABIInfo>(CGM.getTypes());
}
StringRef getARCRetainAutoreleasedReturnValueMarker() const override {
@@ -200,8 +207,8 @@ private:
class WindowsAArch64TargetCodeGenInfo : public AArch64TargetCodeGenInfo {
public:
- WindowsAArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIKind K)
- : AArch64TargetCodeGenInfo(CGT, K) {}
+ WindowsAArch64TargetCodeGenInfo(CodeGenModule &CGM, AArch64ABIKind K)
+ : AArch64TargetCodeGenInfo(CGM, K) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const override;
@@ -368,6 +375,12 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn,
unsigned &NPRN) const {
Ty = useFirstFieldIfTransparentUnion(Ty);
+ if (IsVariadicFn && getTarget().getTriple().isWindowsArm64EC()) {
+ // Arm64EC varargs functions use the x86_64 classification rules,
+ // not the AArch64 ABI rules.
+ return WinX86_64CodegenInfo->getABIInfo().classifyArgForArm64ECVarArg(Ty);
+ }
+
// Handle illegal vector types here.
if (isIllegalVectorType(Ty))
return coerceIllegalVector(Ty, NSRN, NPRN);
@@ -1153,9 +1166,16 @@ RValue AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty, AggValueSlot Slot) const {
bool IsIndirect = false;
- // Composites larger than 16 bytes are passed by reference.
- if (isAggregateTypeForABI(Ty) && getContext().getTypeSize(Ty) > 128)
- IsIndirect = true;
+ if (getTarget().getTriple().isWindowsArm64EC()) {
+ // MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is
+ // not 1, 2, 4, or 8 bytes, must be passed by reference."
+ uint64_t Width = getContext().getTypeSize(Ty);
+ IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
+ } else {
+ // Composites larger than 16 bytes are passed by reference.
+ if (isAggregateTypeForABI(Ty) && getContext().getTypeSize(Ty) > 128)
+ IsIndirect = true;
+ }
return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
CGF.getContext().getTypeInfoInChars(Ty),
@@ -1347,11 +1367,11 @@ void AArch64ABIInfo::appendAttributeMangling(StringRef AttrStr,
std::unique_ptr<TargetCodeGenInfo>
CodeGen::createAArch64TargetCodeGenInfo(CodeGenModule &CGM,
AArch64ABIKind Kind) {
- return std::make_unique<AArch64TargetCodeGenInfo>(CGM.getTypes(), Kind);
+ return std::make_unique<AArch64TargetCodeGenInfo>(CGM, Kind);
}
std::unique_ptr<TargetCodeGenInfo>
CodeGen::createWindowsAArch64TargetCodeGenInfo(CodeGenModule &CGM,
AArch64ABIKind K) {
- return std::make_unique<WindowsAArch64TargetCodeGenInfo>(CGM.getTypes(), K);
+ return std::make_unique<WindowsAArch64TargetCodeGenInfo>(CGM, K);
}
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index f9a84ecca074..e6203db8bc24 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1417,6 +1417,12 @@ public:
return isX86VectorCallAggregateSmallEnough(NumMembers);
}
+ ABIArgInfo classifyArgForArm64ECVarArg(QualType Ty) const override {
+ unsigned FreeSSERegs = 0;
+ return classify(Ty, FreeSSERegs, /*IsReturnType=*/false,
+ /*IsVectorCall=*/false, /*IsRegCall=*/false);
+ }
+
private:
ABIArgInfo classify(QualType Ty, unsigned &FreeSSERegs, bool IsReturnType,
bool IsVectorCall, bool IsRegCall) const;