diff options
| author | Eli Friedman <efriedma@qti.qualcomm.com> | 2025-11-19 16:45:08 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-11-19 16:45:08 -0800 |
| commit | 4e275f727439af9589ee54bc6ac2e95fac9f63ae (patch) | |
| tree | c4857f622535fd1108976d63afd4f0c92324dcef /clang/lib/CodeGen | |
| parent | b1c4b55118131cdf3d6d47ba31578b2e0cd78ec7 (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.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/CodeGen/ABIInfo.h | 4 | ||||
| -rw-r--r-- | clang/lib/CodeGen/Targets/AArch64.cpp | 44 | ||||
| -rw-r--r-- | clang/lib/CodeGen/Targets/X86.cpp | 6 |
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; |
