1//===- AArch64.cpp - AArch64 ABI Implementation ---------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/ABI/FunctionInfo.h"
10#include "llvm/ABI/TargetInfo.h"
11#include "llvm/ABI/Types.h"
12#include "llvm/Support/ErrorHandling.h"
13#include "llvm/Support/WithColor.h"
14
15namespace llvm {
16namespace abi {
17
18class AArch64TargetInfo : public TargetInfo {
19public:
20 AArch64TargetInfo(TypeBuilder &TB, AArch64ABIKind Kind)
21 : TB(TB), Kind(Kind) {}
22
23 void computeInfo(FunctionInfo &FI) const override {
24 if (!maybeCommonClassifyReturnType(FI))
25 FI.getReturnInfo() =
26 classifyReturnType(RetTy: FI.getReturnType(), IsVariadicFn: FI.isVariadic());
27
28 unsigned ArgNo = 0;
29 unsigned NSRN = 0, NPRN = 0;
30 for (auto &I : FI.arguments()) {
31 const bool IsNamedArg =
32 !FI.isVariadic() || ArgNo < FI.getNumRequiredArgs();
33 ++ArgNo;
34 I.Info = classifyArgumentType(Ty: I.ABIType, IsVariadicFn: FI.isVariadic(), IsNamedArg,
35 CallingConvention: FI.getCallingConvention(), NSRN, NPRN);
36 }
37 }
38
39private:
40 [[maybe_unused]] TypeBuilder &TB;
41 AArch64ABIKind Kind;
42
43 ArgInfo classifyReturnType(const Type *RetTy, bool IsVariadicFn) const;
44 ArgInfo classifyArgumentType(const Type *Ty, bool IsVariadicFn,
45 bool IsNamedArg, unsigned CallingConvention,
46 unsigned &NSRN, unsigned &NPRN) const;
47
48 bool isDarwinPCS() const { return Kind == AArch64ABIKind::DarwinPCS; }
49 bool passAsAggregateType(const Type *Ty) const;
50};
51
52std::unique_ptr<TargetInfo> createAArch64TargetInfo(TypeBuilder &TB,
53 AArch64ABIKind Kind) {
54 return std::make_unique<AArch64TargetInfo>(args&: TB, args&: Kind);
55}
56
57static void reportNYI(StringRef Feature) {
58 WithColor::warning()
59 << Feature
60 << " is not yet implemented for AArch64 in the LLVM ABI library.\n";
61}
62
63ArgInfo AArch64TargetInfo::classifyReturnType(const Type *RetTy,
64 bool IsVariadicFn) const {
65 if (RetTy->isVoid())
66 return ArgInfo::getIgnore();
67
68 if (RetTy->isVector()) {
69 reportNYI(Feature: "Vector return type handling");
70 return ArgInfo::getDirect();
71 }
72
73 if (!passAsAggregateType(Ty: RetTy)) {
74 if (const auto *IntTy = dyn_cast<IntegerType>(Val: RetTy)) {
75 if (IntTy->isBitInt())
76 if (RetTy->getSizeInBits().getFixedValue() > 128)
77 return getNaturalAlignIndirect(Ty: RetTy);
78
79 if (isPromotableInteger(IT: IntTy) && isDarwinPCS())
80 return ArgInfo::getExtend(T: IntTy);
81 }
82
83 // Everything not handled above is returned directly.
84 return ArgInfo::getDirect();
85 }
86
87 reportNYI(Feature: "Aggregate return type handling");
88 return ArgInfo::getDirect();
89}
90
91ArgInfo AArch64TargetInfo::classifyArgumentType(
92 const Type *Ty, bool IsVariadicFn, bool IsNamedArg,
93 unsigned CallingConvention, unsigned &NSRN, unsigned &NPRN) const {
94 Ty = useFirstFieldIfTransparentUnion(Ty);
95
96 // TODO: Handle variadic functins here when Windows Arm64 EC is supported.
97
98 if (Ty->isVector()) {
99 reportNYI(Feature: "Vector argument type handling");
100 return ArgInfo::getDirect();
101 }
102
103 if (!passAsAggregateType(Ty)) {
104 if (const auto *IntTy = dyn_cast<IntegerType>(Val: Ty)) {
105 if (IntTy->isBitInt())
106 if (Ty->getSizeInBits().getFixedValue() > 128)
107 return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
108
109 if (isPromotableInteger(IT: IntTy) && isDarwinPCS())
110 return ArgInfo::getExtend(T: IntTy);
111 }
112
113 // TODO: Legal vector types will update NSRN or NPRN.
114
115 if (Ty->isFloat())
116 NSRN = std::min(a: NSRN + 1, b: 8u);
117
118 // Everything not handled above is returned directly.
119 return ArgInfo::getDirect();
120 }
121
122 // Structures with either a non-trivial destructor or a non-trivial
123 // copy constructor are always indirect.
124 if (auto RecordRAA = getRecordArgABI(Ty)) {
125 return getNaturalAlignIndirect(Ty, ByVal: RecordRAA ==
126 RecordArgABI::RAA_DirectInMemory);
127 }
128
129 reportNYI(Feature: "Aggregate argument type handling");
130 return ArgInfo::getDirect();
131}
132
133bool AArch64TargetInfo::passAsAggregateType(const Type *Ty) const {
134 // TODO: Handle SVE types. For now, they don't get through the type mapper.
135 return isAggregateTypeForABI(Ty);
136}
137
138} // namespace abi
139} // namespace llvm
140