10#include "TargetInfo.h"
13#include "llvm/ADT/SmallBitVector.h"
21bool IsX86_MMXType(llvm::Type *IRType) {
23 return IRType->isVectorTy() && IRType->getPrimitiveSizeInBits() == 64 &&
25 IRType->getScalarSizeInBits() != 64;
31 bool IsMMXCons = llvm::StringSwitch<bool>(Constraint)
32 .Cases({
"y",
"&y",
"^Ym"},
true)
34 if (IsMMXCons && Ty->isVectorTy() &&
39 if (Constraint ==
"k") {
41 return llvm::FixedVectorType::get(Int1Ty, Ty->getScalarSizeInBits());
52 if (BT->isFloatingPoint() && BT->getKind() != BuiltinType::Half) {
53 if (BT->getKind() == BuiltinType::LongDouble) {
54 if (&Context.getTargetInfo().getLongDoubleFormat() ==
55 &llvm::APFloat::x87DoubleExtended())
63 unsigned VecSize = Context.getTypeSize(VT);
64 if (VecSize == 128 || VecSize == 256 || VecSize == 512)
72static bool isX86VectorCallAggregateSmallEnough(uint64_t NumMembers) {
73 return NumMembers <= 4;
77static ABIArgInfo getDirectX86Hva(llvm::Type*
T =
nullptr) {
80 AI.setCanBeFlattened(
false);
90 CCState(CGFunctionInfo &FI)
91 : IsPreassigned(FI.arg_size()), CC(FI.getCallingConvention()),
92 Required(FI.getRequiredArgs()), IsDelegateCall(FI.isDelegateCall()) {}
94 llvm::SmallBitVector IsPreassigned;
95 unsigned CC = CallingConv::CC_C;
96 unsigned FreeRegs = 0;
97 unsigned FreeSSERegs = 0;
98 RequiredArgs Required;
99 bool IsDelegateCall =
false;
103class X86_32ABIInfo :
public ABIInfo {
104 enum Class { Integer, Float, AlwaysStack };
106 static const unsigned MinABIStackAlignInBytes = 4;
108 bool IsDarwinVectorABI;
109 bool IsRetSmallStructInRegABI;
110 bool IsWin32StructABI;
114 unsigned DefaultNumRegisterParameters;
116 static bool isRegisterSize(
unsigned Size) {
117 return (Size == 8 || Size == 16 || Size == 32 || Size == 64);
120 bool isHomogeneousAggregateBaseType(QualType Ty)
const override {
122 return isX86VectorTypeForVectorCall(getContext(), Ty);
125 bool isHomogeneousAggregateSmallEnough(
const Type *Ty,
126 uint64_t NumMembers)
const override {
128 return isX86VectorCallAggregateSmallEnough(NumMembers);
131 bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context)
const;
135 ABIArgInfo getIndirectResult(QualType Ty,
bool ByVal, CCState &State)
const;
137 ABIArgInfo getIndirectReturnResult(QualType Ty, CCState &State)
const;
140 unsigned getTypeStackAlignInBytes(QualType Ty,
unsigned Align)
const;
142 Class classify(QualType Ty)
const;
145 unsigned ArgIndex)
const;
149 bool updateFreeRegs(QualType Ty, CCState &State)
const;
151 bool shouldAggregateUseDirect(QualType Ty, CCState &State,
bool &InReg,
152 bool &NeedsPadding)
const;
153 bool shouldPrimitiveUseInReg(QualType Ty, CCState &State)
const;
155 bool canExpandIndirectArgument(QualType Ty)
const;
159 void rewriteWithInAlloca(CGFunctionInfo &FI)
const;
161 void addFieldToArgStruct(SmallVector<llvm::Type *, 6> &FrameFields,
162 CharUnits &StackOffset, ABIArgInfo &Info,
163 QualType
Type)
const;
164 void runVectorCallFirstPass(CGFunctionInfo &FI, CCState &State)
const;
168 void computeInfo(CGFunctionInfo &FI)
const override;
169 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
170 AggValueSlot Slot)
const override;
172 X86_32ABIInfo(CodeGen::CodeGenTypes &CGT,
bool DarwinVectorABI,
173 bool RetSmallStructInRegABI,
bool Win32StructABI,
174 unsigned NumRegisterParameters,
bool SoftFloatABI)
175 : ABIInfo(CGT), IsDarwinVectorABI(DarwinVectorABI),
176 IsRetSmallStructInRegABI(RetSmallStructInRegABI),
177 IsWin32StructABI(Win32StructABI), IsSoftFloatABI(SoftFloatABI),
178 IsMCUABI(CGT.getTarget().
getTriple().isOSIAMCU()),
179 IsLinuxABI(CGT.getTarget().
getTriple().isOSLinux() ||
180 CGT.getTarget().
getTriple().isOSCygMing()),
181 DefaultNumRegisterParameters(NumRegisterParameters) {}
186 explicit X86_32SwiftABIInfo(CodeGenTypes &CGT)
187 : SwiftABIInfo(CGT,
false) {}
190 bool AsReturnValue)
const override {
195 return occupiesMoreThan(ComponentTys, 3);
201 X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
bool DarwinVectorABI,
202 bool RetSmallStructInRegABI,
bool Win32StructABI,
203 unsigned NumRegisterParameters,
bool SoftFloatABI)
204 : TargetCodeGenInfo(std::make_unique<X86_32ABIInfo>(
205 CGT, DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI,
206 NumRegisterParameters, SoftFloatABI)) {
207 SwiftInfo = std::make_unique<X86_32SwiftABIInfo>(CGT);
210 static bool isStructReturnInRegABI(
211 const llvm::Triple &Triple,
const CodeGenOptions &Opts);
213 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
214 CodeGen::CodeGenModule &CGM)
const override;
216 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
222 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
223 llvm::Value *Address)
const override;
225 llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
226 StringRef Constraint,
227 llvm::Type* Ty)
const override {
228 return X86AdjustInlineAsmType(CGF, Constraint, Ty);
231 void addReturnRegisterOutputs(CodeGenFunction &CGF, LValue ReturnValue,
232 std::string &Constraints,
233 std::vector<llvm::Type *> &ResultRegTypes,
234 std::vector<llvm::Type *> &ResultTruncRegTypes,
235 std::vector<LValue> &ResultRegDests,
236 std::string &AsmString,
237 unsigned NumOutputs)
const override;
239 StringRef getARCRetainAutoreleasedReturnValueMarker()
const override {
240 return "movl\t%ebp, %ebp"
241 "\t\t// marker for objc_retainAutoreleaseReturnValue";
257 std::string &AsmString) {
259 llvm::raw_string_ostream OS(Buf);
261 while (Pos < AsmString.size()) {
262 size_t DollarStart = AsmString.find(
'$', Pos);
263 if (DollarStart == std::string::npos)
264 DollarStart = AsmString.size();
265 size_t DollarEnd = AsmString.find_first_not_of(
'$', DollarStart);
266 if (DollarEnd == std::string::npos)
267 DollarEnd = AsmString.size();
268 OS << StringRef(&AsmString[Pos], DollarEnd - Pos);
270 size_t NumDollars = DollarEnd - DollarStart;
271 if (NumDollars % 2 != 0 && Pos < AsmString.size()) {
273 size_t DigitStart = Pos;
274 if (AsmString[DigitStart] ==
'{') {
278 size_t DigitEnd = AsmString.find_first_not_of(
"0123456789", DigitStart);
279 if (DigitEnd == std::string::npos)
280 DigitEnd = AsmString.size();
281 StringRef OperandStr(&AsmString[DigitStart], DigitEnd - DigitStart);
282 unsigned OperandIndex;
283 if (!OperandStr.getAsInteger(10, OperandIndex)) {
284 if (OperandIndex >= FirstIn)
285 OperandIndex += NumNewOuts;
293 AsmString = std::move(Buf);
297void X86_32TargetCodeGenInfo::addReturnRegisterOutputs(
299 std::vector<llvm::Type *> &ResultRegTypes,
300 std::vector<llvm::Type *> &ResultTruncRegTypes,
301 std::vector<LValue> &ResultRegDests, std::string &AsmString,
302 unsigned NumOutputs)
const {
307 if (!Constraints.empty())
309 if (RetWidth <= 32) {
310 Constraints +=
"={eax}";
311 ResultRegTypes.push_back(CGF.
Int32Ty);
315 ResultRegTypes.push_back(CGF.
Int64Ty);
319 llvm::Type *CoerceTy = llvm::IntegerType::get(CGF.
getLLVMContext(), RetWidth);
320 ResultTruncRegTypes.push_back(CoerceTy);
323 ReturnSlot.setAddress(ReturnSlot.getAddress().withElementType(CoerceTy));
324 ResultRegDests.push_back(ReturnSlot);
331bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
332 ASTContext &Context)
const {
337 if ((IsMCUABI && Size > 64) || (!IsMCUABI && !isRegisterSize(Size)))
343 if (Size == 64 || Size == 128)
358 return shouldReturnTypeInRegister(AT->getElementType(), Context);
369 for (
const auto *FD : RD->fields()) {
375 if (!shouldReturnTypeInRegister(FD->getType(), Context))
384 Ty = CTy->getElementType();
393 uint64_t Size = Context.getTypeSize(Ty);
394 return Size == 32 || Size == 64;
399 for (
const auto *FD : RD->
fields()) {
409 if (FD->isBitField())
412 Size += Context.getTypeSize(FD->getType());
434bool X86_32ABIInfo::canExpandIndirectArgument(QualType Ty)
const {
440 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
441 if (!IsWin32StructABI) {
444 if (!CXXRD->isCLike())
448 if (CXXRD->isDynamicClass())
459 return Size == getContext().getTypeSize(Ty);
474ABIArgInfo X86_32ABIInfo::getIndirectReturnResult(QualType RetTy, CCState &State)
const {
477 if (State.CC != llvm::CallingConv::X86_FastCall &&
478 State.CC != llvm::CallingConv::X86_VectorCall && State.FreeRegs) {
481 return getNaturalAlignIndirectInReg(RetTy);
483 return getNaturalAlignIndirect(
484 RetTy, getDataLayout().getAllocaAddrSpace(),
488ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
489 CCState &State)
const {
495 if ((State.CC == llvm::CallingConv::X86_VectorCall ||
496 State.CC == llvm::CallingConv::X86_RegCall) &&
497 isHomogeneousAggregate(RetTy, Base, NumElts)) {
502 if (
const VectorType *VT = RetTy->
getAs<VectorType>()) {
504 if (IsDarwinVectorABI) {
512 llvm::Type::getInt64Ty(getVMContext()), 2));
516 if ((Size == 8 || Size == 16 || Size == 32) ||
517 (Size == 64 && VT->getNumElements() == 1))
521 return getIndirectReturnResult(RetTy, State);
531 return getIndirectReturnResult(RetTy, State);
535 return getIndirectReturnResult(RetTy, State);
542 if (
const ComplexType *CT = RetTy->
getAs<ComplexType>()) {
543 QualType ET = getContext().getCanonicalType(CT->getElementType());
546 llvm::Type::getHalfTy(getVMContext()), 2));
551 if (shouldReturnTypeInRegister(RetTy, getContext())) {
560 if ((!IsWin32StructABI && SeltTy->isRealFloatingType())
561 || SeltTy->hasPointerRepresentation())
569 return getIndirectReturnResult(RetTy, State);
574 RetTy = ED->getIntegerType();
576 if (
const auto *EIT = RetTy->
getAs<BitIntType>())
577 if (EIT->getNumBits() > 64)
578 return getIndirectReturnResult(RetTy, State);
581 : ABIArgInfo::getDirect();
584unsigned X86_32ABIInfo::getTypeStackAlignInBytes(QualType Ty,
585 unsigned Align)
const {
588 if (Align <= MinABIStackAlignInBytes)
599 if (Ty->
isVectorType() && (Align == 16 || Align == 32 || Align == 64))
603 if (!IsDarwinVectorABI) {
605 return MinABIStackAlignInBytes;
613 return MinABIStackAlignInBytes;
616ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty,
bool ByVal,
617 CCState &State)
const {
619 if (State.FreeRegs) {
622 return getNaturalAlignIndirectInReg(Ty);
624 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
629 unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
630 unsigned StackAlign = getTypeStackAlignInBytes(Ty, TypeAlign);
634 getDataLayout().getAllocaAddrSpace(),
639 bool Realign = TypeAlign > StackAlign;
642 getDataLayout().getAllocaAddrSpace(),
true,
649 const auto *RD =
T->getAsRecordDecl();
659 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
660 for (
const auto &I : CXXRD->bases()) {
669 Found = I.getType().getTypePtr();
674 for (
const auto *FD : RD->
fields()) {
688 if (AT->getZExtSize() != 1)
690 FT = AT->getElementType();
698 if (
Found && Context.getTypeSize(
Found) != Context.getTypeSize(
T))
704X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty)
const {
705 if (getContext().getLangOpts().isCompatibleWith(
706 LangOptions::ClangABI::Ver23)) {
711 if (
const BuiltinType *BT =
T->
getAs<BuiltinType>()) {
713 if (K == BuiltinType::Float || K == BuiltinType::Double)
730 Ty = QualType(FT, 0);
738 if (
const BuiltinType *BT = Ty->
getAs<BuiltinType>())
739 if (BT->isFloatingPoint())
745bool X86_32ABIInfo::updateFreeRegs(QualType Ty, CCState &State)
const {
747 if (
C == AlwaysStack && !IsMCUABI)
749 if (
C ==
Float && !IsSoftFloatABI)
752 unsigned Size = getContext().getTypeSize(Ty);
753 unsigned SizeInRegs = (
Size + 31) / 32;
759 if (SizeInRegs > State.FreeRegs) {
768 if (SizeInRegs > State.FreeRegs || SizeInRegs > 2)
772 State.FreeRegs -= SizeInRegs;
776bool X86_32ABIInfo::shouldAggregateUseDirect(QualType Ty, CCState &State,
778 bool &NeedsPadding)
const {
785 NeedsPadding =
false;
788 if (!updateFreeRegs(Ty, State))
794 if (State.CC == llvm::CallingConv::X86_FastCall ||
795 State.CC == llvm::CallingConv::X86_VectorCall ||
796 State.CC == llvm::CallingConv::X86_RegCall) {
797 if (getContext().getTypeSize(Ty) <= 32 && State.FreeRegs)
806bool X86_32ABIInfo::shouldPrimitiveUseInReg(QualType Ty, CCState &State)
const {
807 bool IsPtrOrInt = (getContext().getTypeSize(Ty) <= 32) &&
811 if (!IsPtrOrInt && (State.CC == llvm::CallingConv::X86_FastCall ||
812 State.CC == llvm::CallingConv::X86_VectorCall))
815 if (!updateFreeRegs(Ty, State))
818 if (!IsPtrOrInt && State.CC == llvm::CallingConv::X86_RegCall)
825void X86_32ABIInfo::runVectorCallFirstPass(CGFunctionInfo &FI, CCState &State)
const {
835 MutableArrayRef<CGFunctionInfoArgInfo> Args = FI.
arguments();
836 for (
int I = 0, E = Args.size(); I < E; ++I) {
839 const QualType &Ty = Args[I].type;
841 isHomogeneousAggregate(Ty, Base, NumElts)) {
842 if (State.FreeSSERegs >= NumElts) {
843 State.FreeSSERegs -= NumElts;
845 State.IsPreassigned.set(I);
851ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State,
852 unsigned ArgIndex)
const {
854 bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
855 bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
856 bool IsVectorCall = State.CC == llvm::CallingConv::X86_VectorCall;
859 TypeInfo TI = getContext().getTypeInfo(Ty);
866 return getIndirectResult(Ty,
false, State);
867 }
else if (State.IsDelegateCall) {
870 ABIArgInfo Res = getIndirectResult(Ty,
false, State);
883 if ((IsRegCall || IsVectorCall) &&
884 isHomogeneousAggregate(Ty, Base, NumElts)) {
885 if (State.FreeSSERegs >= NumElts) {
886 State.FreeSSERegs -= NumElts;
891 return getDirectX86Hva();
899 return getIndirectResult(Ty,
false, State);
905 if (RT && RT->getDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
906 return getIndirectResult(Ty,
true, State);
909 if (!IsWin32StructABI &&
isEmptyRecord(getContext(), Ty,
true))
916 llvm::LLVMContext &LLVMContext = getVMContext();
917 llvm::IntegerType *
Int32 = llvm::Type::getInt32Ty(LLVMContext);
918 bool NeedsPadding =
false;
920 if (shouldAggregateUseDirect(Ty, State, InReg, NeedsPadding)) {
921 unsigned SizeInRegs = (TI.
Width + 31) / 32;
922 SmallVector<llvm::Type*, 3> Elements(SizeInRegs, Int32);
923 llvm::Type *
Result = llvm::StructType::get(LLVMContext, Elements);
929 llvm::IntegerType *PaddingType = NeedsPadding ?
Int32 :
nullptr;
936 if (IsWin32StructABI && State.Required.
isRequiredArg(ArgIndex)) {
937 unsigned AlignInBits = 0;
939 const ASTRecordLayout &Layout =
940 getContext().getASTRecordLayout(RT->getDecl());
943 AlignInBits = TI.
Align;
945 if (AlignInBits > 32)
946 return getIndirectResult(Ty,
false, State);
955 if (TI.
Width <= 4 * 32 && (!IsMCUABI || State.FreeRegs == 0) &&
956 canExpandIndirectArgument(Ty))
958 IsFastCall || IsVectorCall || IsRegCall, PaddingType);
960 return getIndirectResult(Ty,
true, State);
963 if (
const VectorType *VT = Ty->
getAs<VectorType>()) {
967 if (IsWin32StructABI) {
968 if (TI.
Width <= 512 && State.FreeSSERegs > 0) {
972 return getIndirectResult(Ty,
false, State);
977 if (IsDarwinVectorABI) {
979 (TI.
Width == 64 && VT->getNumElements() == 1))
981 llvm::IntegerType::get(getVMContext(), TI.
Width));
984 if (IsX86_MMXType(CGT.ConvertType(Ty)))
991 Ty = ED->getIntegerType();
993 bool InReg = shouldPrimitiveUseInReg(Ty, State);
995 if (isPromotableIntegerTypeForABI(Ty)) {
1001 if (
const auto *EIT = Ty->
getAs<BitIntType>()) {
1002 if (EIT->getNumBits() <= 64) {
1007 return getIndirectResult(Ty,
false, State);
1015void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI)
const {
1019 else if (State.CC == llvm::CallingConv::X86_FastCall) {
1021 State.FreeSSERegs = 3;
1022 }
else if (State.CC == llvm::CallingConv::X86_VectorCall) {
1024 State.FreeSSERegs = 6;
1027 else if (State.CC == llvm::CallingConv::X86_RegCall) {
1029 State.FreeSSERegs = 8;
1030 }
else if (IsWin32StructABI) {
1033 State.FreeRegs = DefaultNumRegisterParameters;
1034 State.FreeSSERegs = 3;
1036 State.FreeRegs = DefaultNumRegisterParameters;
1043 if (State.FreeRegs) {
1056 if (State.CC == llvm::CallingConv::X86_VectorCall)
1057 runVectorCallFirstPass(FI, State);
1059 bool UsedInAlloca =
false;
1060 MutableArrayRef<CGFunctionInfoArgInfo> Args = FI.
arguments();
1061 for (
unsigned I = 0, E = Args.size(); I < E; ++I) {
1063 if (State.IsPreassigned.test(I))
1074 rewriteWithInAlloca(FI);
1078X86_32ABIInfo::addFieldToArgStruct(SmallVector<llvm::Type *, 6> &FrameFields,
1079 CharUnits &StackOffset, ABIArgInfo &Info,
1080 QualType
Type)
const {
1083 assert(StackOffset.
isMultipleOf(WordSize) &&
"unaligned inalloca struct");
1088 bool IsIndirect =
false;
1092 llvm::Type *LLTy = CGT.ConvertTypeForMem(
Type);
1094 LLTy = llvm::PointerType::getUnqual(getVMContext());
1095 FrameFields.push_back(LLTy);
1096 StackOffset += IsIndirect ? WordSize : getContext().getTypeSizeInChars(
Type);
1099 CharUnits FieldEnd = StackOffset;
1100 StackOffset = FieldEnd.
alignTo(WordSize);
1101 if (StackOffset != FieldEnd) {
1102 CharUnits NumBytes = StackOffset - FieldEnd;
1103 llvm::Type *Ty = llvm::Type::getInt8Ty(getVMContext());
1104 Ty = llvm::ArrayType::get(Ty, NumBytes.
getQuantity());
1105 FrameFields.push_back(Ty);
1128 llvm_unreachable(
"invalid enum");
1131void X86_32ABIInfo::rewriteWithInAlloca(CGFunctionInfo &FI)
const {
1132 assert(IsWin32StructABI &&
"inalloca only supported on win32");
1135 SmallVector<llvm::Type *, 6> FrameFields;
1140 CharUnits StackOffset;
1147 if (
Ret.isIndirect() &&
Ret.isSRetAfterThis() && !IsThisCall &&
1149 addFieldToArgStruct(FrameFields, StackOffset, I->
info, I->
type);
1154 if (
Ret.isIndirect() && !
Ret.getInReg()) {
1155 addFieldToArgStruct(FrameFields, StackOffset, Ret, FI.
getReturnType());
1157 Ret.setInAllocaSRet(IsWin32StructABI);
1165 for (; I != E; ++I) {
1167 addFieldToArgStruct(FrameFields, StackOffset, I->
info, I->
type);
1170 FI.
setArgStruct(llvm::StructType::get(getVMContext(), FrameFields,
1175RValue X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
1176 QualType Ty, AggValueSlot Slot)
const {
1178 auto TypeInfo = getContext().getTypeInfoInChars(Ty);
1180 CCState State(*
const_cast<CGFunctionInfo *
>(CGF.
CurFnInfo));
1191 getTypeStackAlignInBytes(Ty, TypeInfo.Align.getQuantity()));
1198bool X86_32TargetCodeGenInfo::isStructReturnInRegABI(
1199 const llvm::Triple &Triple,
const CodeGenOptions &Opts) {
1200 assert(Triple.getArch() == llvm::Triple::x86);
1202 switch (Opts.getStructReturnConvention()) {
1211 if (Triple.isOSDarwin() || Triple.isOSIAMCU())
1214 switch (Triple.getOS()) {
1215 case llvm::Triple::DragonFly:
1216 case llvm::Triple::FreeBSD:
1217 case llvm::Triple::OpenBSD:
1218 case llvm::Triple::Win32:
1227 if (!FD->
hasAttr<AnyX86InterruptAttr>())
1231 Fn->setCallingConv(llvm::CallingConv::X86_INTR);
1237 llvm::Attribute NewAttr = llvm::Attribute::getWithByValType(
1238 Fn->getContext(), ByValTy);
1239 Fn->addParamAttr(0, NewAttr);
1242void X86_32TargetCodeGenInfo::setTargetAttributes(
1243 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
const {
1244 if (GV->isDeclaration())
1246 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
1247 if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
1249 Fn->addFnAttr(
"stackrealign");
1256bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable(
1257 CodeGen::CodeGenFunction &CGF,
1258 llvm::Value *Address)
const {
1259 CodeGen::CGBuilderTy &Builder = CGF.
Builder;
1261 llvm::Value *Four8 = llvm::ConstantInt::get(CGF.
Int8Ty, 4);
1272 llvm::Value *Sixteen8 = llvm::ConstantInt::get(CGF.
Int8Ty, 16);
1278 Builder.CreateAlignedStore(
1279 Four8, Builder.CreateConstInBoundsGEP1_32(CGF.
Int8Ty, Address, 9),
1285 llvm::Value *Twelve8 = llvm::ConstantInt::get(CGF.
Int8Ty, 12);
1300static unsigned getNativeVectorSizeForAVXABI(
X86AVXABILevel AVXLevel) {
1302 case X86AVXABILevel::AVX512:
1304 case X86AVXABILevel::AVX:
1306 case X86AVXABILevel::None:
1309 llvm_unreachable(
"Unknown AVXLevel");
1313class X86_64ABIInfo :
public ABIInfo {
1350 void postMerge(
unsigned AggregateSize,
Class &Lo,
Class &Hi)
const;
1378 void classify(QualType
T, uint64_t OffsetBase,
Class &Lo,
Class &Hi,
1379 bool isNamedArg,
bool IsRegCall =
false)
const;
1381 llvm::Type *GetByteVectorType(QualType Ty)
const;
1382 llvm::Type *GetSSETypeAtOffset(llvm::Type *IRType,
1383 unsigned IROffset, QualType SourceTy,
1384 unsigned SourceOffset)
const;
1385 llvm::Type *GetINTEGERTypeAtOffset(llvm::Type *IRType,
1386 unsigned IROffset, QualType SourceTy,
1387 unsigned SourceOffset)
const;
1391 ABIArgInfo getIndirectReturnResult(QualType Ty)
const;
1398 ABIArgInfo getIndirectResult(QualType Ty,
unsigned freeIntRegs)
const;
1403 unsigned &neededInt,
unsigned &neededSSE,
1405 bool IsRegCall =
false)
const;
1407 ABIArgInfo classifyRegCallStructType(QualType Ty,
unsigned &NeededInt,
1408 unsigned &NeededSSE,
1409 unsigned &MaxVectorWidth)
const;
1411 bool passRegCallStructTypeDirectly(QualType Ty,
1412 SmallVectorImpl<llvm::Type *> &CoerceElts,
1413 unsigned &NeededInt,
unsigned &NeededSSE,
1414 unsigned &MaxVectorWidth)
const;
1416 bool IsIllegalVectorType(QualType Ty)
const;
1423 bool honorsRevision0_98()
const {
1424 return !getTarget().getTriple().isOSDarwin();
1429 bool classifyIntegerMMXAsSSE()
const {
1431 if (getContext().getLangOpts().isCompatibleWith(
1432 LangOptions::ClangABI::Ver3_8))
1435 const llvm::Triple &Triple = getTarget().getTriple();
1436 if (Triple.isOSDarwin() || Triple.isPS() || Triple.isOSFreeBSD())
1442 bool passInt128VectorsInMem()
const {
1444 if (getContext().getLangOpts().isCompatibleWith(
1445 LangOptions::ClangABI::Ver9))
1448 const llvm::Triple &
T = getTarget().getTriple();
1449 return T.isOSLinux() ||
T.isOSNetBSD();
1452 bool returnCXXRecordGreaterThan128InMem()
const {
1454 if (getContext().getLangOpts().isCompatibleWith(
1455 LangOptions::ClangABI::Ver20) ||
1465 bool Has64BitPointers;
1468 X86_64ABIInfo(CodeGen::CodeGenTypes &CGT,
X86AVXABILevel AVXLevel)
1469 : ABIInfo(CGT), AVXLevel(AVXLevel),
1470 Has64BitPointers(CGT.getDataLayout().getPointerSize(0) == 8) {}
1472 bool isPassedUsingAVXType(QualType
type)
const {
1473 unsigned neededInt, neededSSE;
1477 if (
info.isDirect()) {
1478 llvm::Type *ty =
info.getCoerceToType();
1479 if (llvm::VectorType *vectorTy = dyn_cast_or_null<llvm::VectorType>(ty))
1480 return vectorTy->getPrimitiveSizeInBits().getFixedValue() > 128;
1485 void computeInfo(CGFunctionInfo &FI)
const override;
1486 unsigned getX86ABIAVXLevel(
const FunctionDecl *FD,
1487 const FunctionType::ExtInfo &Info)
const override;
1489 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1490 AggValueSlot Slot)
const override;
1491 RValue EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1492 AggValueSlot Slot)
const override;
1494 bool has64BitPointers()
const {
1495 return Has64BitPointers;
1500class WinX86_64ABIInfo :
public ABIInfo {
1502 WinX86_64ABIInfo(CodeGen::CodeGenTypes &CGT,
X86AVXABILevel AVXLevel)
1503 : ABIInfo(CGT), AVXLevel(AVXLevel),
1504 IsMingw64(getTarget().
getTriple().isWindowsGNUEnvironment()) {}
1506 void computeInfo(CGFunctionInfo &FI)
const override;
1507 unsigned getX86ABIAVXLevel(
const FunctionDecl *FD,
1508 const FunctionType::ExtInfo &Info)
const override;
1510 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1511 AggValueSlot Slot)
const override;
1513 bool isHomogeneousAggregateBaseType(QualType Ty)
const override {
1515 return isX86VectorTypeForVectorCall(getContext(), Ty);
1518 bool isHomogeneousAggregateSmallEnough(
const Type *Ty,
1519 uint64_t NumMembers)
const override {
1521 return isX86VectorCallAggregateSmallEnough(NumMembers);
1524 ABIArgInfo classifyArgForArm64ECVarArg(QualType Ty,
1525 bool IsNamedArg)
const override {
1526 unsigned FreeSSERegs = 0;
1528 IsNamedArg ? ClassifyKind::FixedArgument : ClassifyKind::VarArg;
1529 return classify(Ty, FreeSSERegs, Kind, llvm::CallingConv::C);
1533 enum class ClassifyKind { Return, FixedArgument, VarArg };
1535 ABIArgInfo classify(QualType Ty,
unsigned &FreeSSERegs, ClassifyKind Kind,
1537 ABIArgInfo reclassifyHvaArgForVectorCall(QualType Ty,
unsigned &FreeSSERegs,
1538 const ABIArgInfo ¤t)
const;
1545class X86_64TargetCodeGenInfo :
public TargetCodeGenInfo {
1547 X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
X86AVXABILevel AVXLevel)
1548 : TargetCodeGenInfo(std::make_unique<X86_64ABIInfo>(CGT, AVXLevel)) {
1550 std::make_unique<SwiftABIInfo>(CGT,
true);
1555 bool markARCOptimizedReturnCallsAsNoTail()
const override {
return true; }
1557 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
1561 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
1562 llvm::Value *Address)
const override {
1563 llvm::Value *Eight8 = llvm::ConstantInt::get(CGF.
Int8Ty, 8);
1571 llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
1572 StringRef Constraint,
1573 llvm::Type* Ty)
const override {
1574 return X86AdjustInlineAsmType(CGF, Constraint, Ty);
1577 bool isNoProtoCallVariadic(
const CallArgList &args,
1578 const FunctionNoProtoType *fnType)
const override {
1586 bool HasAVXType =
false;
1587 for (
const CallArg &arg : args) {
1588 if (getABIInfo<X86_64ABIInfo>().isPassedUsingAVXType(
arg.Ty)) {
1601 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1602 CodeGen::CodeGenModule &CGM)
const override {
1603 if (GV->isDeclaration())
1605 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
1606 if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
1608 Fn->addFnAttr(
"stackrealign");
1615 void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc,
1616 const FunctionDecl *Caller,
1617 const FunctionDecl *Callee,
const CallArgList &Args,
1618 QualType ReturnType)
const override;
1620 void checkFunctionABI(CodeGenModule &CGM,
1621 const FunctionDecl *FD)
const override;
1626 llvm::StringMap<bool> &CallerMap,
1628 llvm::StringMap<bool> &CalleeMap,
1630 if (CalleeMap.empty() && CallerMap.empty()) {
1642 const llvm::StringMap<bool> &CallerMap,
1643 const llvm::StringMap<bool> &CalleeMap,
1646 bool CallerHasFeat = CallerMap.lookup(
Feature);
1647 bool CalleeHasFeat = CalleeMap.lookup(
Feature);
1649 if (!CallerHasFeat && !CalleeHasFeat &&
1650 (!Callee.isExternallyVisible() || Callee.hasAttr<AlwaysInlineAttr>()))
1653 if (!CallerHasFeat && !CalleeHasFeat)
1654 return Diag.Report(CallLoc, diag::warn_avx_calling_convention)
1655 << IsArgument << Ty <<
Feature;
1658 if (!CallerHasFeat || !CalleeHasFeat)
1659 return Diag.Report(CallLoc, diag::err_avx_calling_convention)
1660 << IsArgument << Ty <<
Feature;
1669 const llvm::StringMap<bool> &CallerMap,
1670 const llvm::StringMap<bool> &CalleeMap,
QualType Ty,
1675 "avx512f", IsArgument);
1684void X86_64TargetCodeGenInfo::checkFunctionABI(CodeGenModule &CGM,
1685 const FunctionDecl *FD)
const {
1686 auto GetReturnTypeLoc = [](
const FunctionDecl *FD) {
1688 TypeLoc TL = TSI->getTypeLoc();
1691 SourceLocation Loc = FTL.getReturnLoc().getBeginLoc();
1704 auto Check = [&](QualType Ty, SourceLocation Loc,
bool IsReturn) {
1713 llvm::StringMap<bool> FeatureMap;
1715 if (!FeatureMap.lookup(
Feature)) {
1717 << !IsReturn << Ty <<
Feature;
1734 for (
const ParmVarDecl *P : FD->
parameters()) {
1735 SourceLocation Loc = P->getLocation();
1737 Loc = P->getBeginLoc();
1738 if (Check(P->getType(), Loc,
false))
1743void X86_64TargetCodeGenInfo::checkFunctionCallABI(CodeGenModule &CGM,
1744 SourceLocation CallLoc,
1745 const FunctionDecl *Caller,
1746 const FunctionDecl *Callee,
1747 const CallArgList &Args,
1748 QualType ReturnType)
const {
1752 llvm::StringMap<bool> CallerMap;
1753 llvm::StringMap<bool> CalleeMap;
1754 unsigned ArgIndex = 0;
1758 for (
const CallArg &Arg : Args) {
1766 if (Arg.getType()->isVectorType() &&
1769 QualType Ty = Arg.getType();
1772 if (ArgIndex < Callee->getNumParams())
1773 Ty =
Callee->getParamDecl(ArgIndex)->getType();
1776 CallerMap, CalleeMap, Ty,
true))
1784 if (
Callee->getReturnType()->isVectorType() &&
1788 CalleeMap,
Callee->getReturnType(),
1797 bool Quote = Lib.contains(
' ');
1798 std::string ArgStr = Quote ?
"\"" :
"";
1800 if (!Lib.ends_with_insensitive(
".lib") && !Lib.ends_with_insensitive(
".a"))
1802 ArgStr += Quote ?
"\"" :
"";
1807class WinX86_32TargetCodeGenInfo :
public X86_32TargetCodeGenInfo {
1810 bool DarwinVectorABI,
bool RetSmallStructInRegABI,
bool Win32StructABI,
1811 unsigned NumRegisterParameters)
1812 : X86_32TargetCodeGenInfo(CGT, DarwinVectorABI, RetSmallStructInRegABI,
1813 Win32StructABI, NumRegisterParameters,
false) {}
1815 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1818 void getDependentLibraryOption(llvm::StringRef Lib,
1820 Opt =
"/DEFAULTLIB:";
1821 Opt += qualifyWindowsLibrary(Lib);
1824 void getDetectMismatchOption(llvm::StringRef Name,
1825 llvm::StringRef
Value,
1827 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
1832void WinX86_32TargetCodeGenInfo::setTargetAttributes(
1833 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
const {
1834 X86_32TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
1835 if (GV->isDeclaration())
1837 addStackProbeTargetAttributes(D, GV, CGM);
1841class WinX86_64TargetCodeGenInfo :
public TargetCodeGenInfo {
1843 WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
1845 : TargetCodeGenInfo(std::make_unique<WinX86_64ABIInfo>(CGT, AVXLevel)) {
1847 std::make_unique<SwiftABIInfo>(CGT,
true);
1850 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1851 CodeGen::CodeGenModule &CGM)
const override;
1853 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
1857 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
1858 llvm::Value *Address)
const override {
1859 llvm::Value *Eight8 = llvm::ConstantInt::get(CGF.
Int8Ty, 8);
1867 void getDependentLibraryOption(llvm::StringRef Lib,
1868 llvm::SmallString<24> &Opt)
const override {
1869 Opt =
"/DEFAULTLIB:";
1870 Opt += qualifyWindowsLibrary(Lib);
1873 void getDetectMismatchOption(llvm::StringRef Name,
1874 llvm::StringRef
Value,
1875 llvm::SmallString<32> &Opt)
const override {
1876 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
1881void WinX86_64TargetCodeGenInfo::setTargetAttributes(
1882 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
const {
1884 if (GV->isDeclaration())
1886 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
1887 if (FD->
hasAttr<X86ForceAlignArgPointerAttr>()) {
1889 Fn->addFnAttr(
"stackrealign");
1895 addStackProbeTargetAttributes(D, GV, CGM);
1898void X86_64ABIInfo::postMerge(
unsigned AggregateSize,
Class &Lo,
1923 if (Hi == X87Up && Lo != X87 && honorsRevision0_98())
1925 if (AggregateSize > 128 && (Lo != SSE || Hi != SSEUp))
1927 if (Hi == SSEUp && Lo != SSE)
1937 LangOptions::ClangABI::Ver23) {
1938 return GlobalAVXLevel;
1945 if (!FD || !FD->
hasAttr<TargetAttr>())
1948 llvm::StringMap<bool> FeatureMap;
1950 if (FeatureMap.lookup(
"avx512f"))
1952 if (FeatureMap.lookup(
"avx"))
1957X86_64ABIInfo::Class X86_64ABIInfo::merge(
Class Accum,
Class Field) {
1981 assert((Accum != Memory && Accum != ComplexX87) &&
1982 "Invalid accumulated classification during merge.");
1983 if (Accum == Field || Field == NoClass)
1985 if (Field == Memory)
1987 if (Accum == NoClass)
1991 if (Field == X87 || Field == X87Up || Field == ComplexX87 ||
1992 Accum == X87 || Accum == X87Up)
1997void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
Class &Lo,
1998 Class &Hi,
bool isNamedArg,
bool IsRegCall)
const {
2009 Class &Current = OffsetBase < 64 ? Lo : Hi;
2012 if (
const BuiltinType *BT = Ty->
getAs<BuiltinType>()) {
2015 if (k == BuiltinType::Void) {
2017 }
else if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
2020 }
else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
2022 }
else if (k == BuiltinType::Float || k == BuiltinType::Double ||
2023 k == BuiltinType::Float16 || k == BuiltinType::BFloat16) {
2025 }
else if (k == BuiltinType::Float128) {
2028 }
else if (k == BuiltinType::LongDouble) {
2029 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
2030 if (LDF == &llvm::APFloat::IEEEquad()) {
2033 }
else if (LDF == &llvm::APFloat::x87DoubleExtended()) {
2036 }
else if (LDF == &llvm::APFloat::IEEEdouble()) {
2039 llvm_unreachable(
"unexpected long double representation!");
2048 classify(ED->getIntegerType(), OffsetBase, Lo, Hi, isNamedArg);
2059 if (Has64BitPointers) {
2066 uint64_t EB_FuncPtr = (OffsetBase) / 64;
2067 uint64_t EB_ThisAdj = (OffsetBase + 64 - 1) / 64;
2068 if (EB_FuncPtr != EB_ThisAdj) {
2080 if (
const VectorType *VT = Ty->
getAs<VectorType>()) {
2082 if (Size == 1 || Size == 8 || Size == 16 || Size == 32) {
2091 uint64_t EB_Lo = (OffsetBase) / 64;
2095 }
else if (Size == 64) {
2096 QualType ElementType = VT->getElementType();
2099 if (ElementType->isSpecificBuiltinType(BuiltinType::Double))
2105 if (!classifyIntegerMMXAsSSE() &&
2106 (ElementType->isSpecificBuiltinType(BuiltinType::LongLong) ||
2107 ElementType->isSpecificBuiltinType(BuiltinType::ULongLong) ||
2108 ElementType->isSpecificBuiltinType(BuiltinType::Long) ||
2109 ElementType->isSpecificBuiltinType(BuiltinType::ULong)))
2116 if (OffsetBase && OffsetBase != 64)
2118 }
else if (Size == 128 ||
2119 (isNamedArg && Size <= getNativeVectorSizeForAVXABI(AVXLevel))) {
2120 QualType ElementType = VT->getElementType();
2123 if (passInt128VectorsInMem() && Size != 128 &&
2124 (ElementType->isSpecificBuiltinType(BuiltinType::Int128) ||
2125 ElementType->isSpecificBuiltinType(BuiltinType::UInt128)))
2148 if (
const ComplexType *CT = Ty->
getAs<ComplexType>()) {
2155 else if (Size <= 128)
2157 }
else if (ET->
isFloat16Type() || ET == getContext().FloatTy ||
2160 }
else if (ET == getContext().DoubleTy) {
2162 }
else if (ET == getContext().LongDoubleTy) {
2163 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
2164 if (LDF == &llvm::APFloat::IEEEquad())
2166 else if (LDF == &llvm::APFloat::x87DoubleExtended())
2167 Current = ComplexX87;
2168 else if (LDF == &llvm::APFloat::IEEEdouble())
2171 llvm_unreachable(
"unexpected long double representation!");
2176 uint64_t EB_Real = (OffsetBase) / 64;
2177 uint64_t EB_Imag = (OffsetBase + getContext().getTypeSize(ET)) / 64;
2178 if (Hi == NoClass && EB_Real != EB_Imag)
2184 if (
const auto *EITy = Ty->
getAs<BitIntType>()) {
2185 if (EITy->getNumBits() <= 64)
2187 else if (EITy->getNumBits() <= 128)
2193 if (
const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
2202 if (!IsRegCall && Size > 512)
2209 if (OffsetBase % getContext().getTypeAlign(AT->getElementType()))
2215 uint64_t EltSize = getContext().getTypeSize(AT->getElementType());
2216 uint64_t ArraySize = AT->getZExtSize();
2223 (Size != EltSize || Size > getNativeVectorSizeForAVXABI(AVXLevel)))
2226 for (uint64_t i=0, Offset=OffsetBase; i<ArraySize; ++i, Offset += EltSize) {
2227 Class FieldLo, FieldHi;
2228 classify(AT->getElementType(), Offset, FieldLo, FieldHi, isNamedArg);
2229 Lo =
merge(Lo, FieldLo);
2230 Hi =
merge(Hi, FieldHi);
2231 if (Lo == Memory || Hi == Memory)
2235 postMerge(Size, Lo, Hi);
2236 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp array classification.");
2260 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
2266 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2267 for (
const auto &I : CXXRD->bases()) {
2268 assert(!I.isVirtual() && !I.getType()->isDependentType() &&
2269 "Unexpected base class!");
2270 const auto *
Base = I.getType()->castAsCXXRecordDecl();
2276 Class FieldLo, FieldHi;
2279 classify(I.getType(), Offset, FieldLo, FieldHi, isNamedArg);
2280 Lo =
merge(Lo, FieldLo);
2281 Hi =
merge(Hi, FieldHi);
2282 if (returnCXXRecordGreaterThan128InMem() &&
2284 (Size > 128 && (Size != getContext().getTypeSize(I.getType()) ||
2285 Size > getNativeVectorSizeForAVXABI(AVXLevel)))) {
2290 if (Lo == Memory || Hi == Memory) {
2291 postMerge(Size, Lo, Hi);
2299 bool UseClang11Compat = getContext().getLangOpts().isCompatibleWith(
2300 LangOptions::ClangABI::Ver11) ||
2301 getContext().getTargetInfo().getTriple().isPS();
2302 bool ClassifyUnnamedBitFields =
2303 getContext().getLangOpts().getClangABICompat() >
2304 LangOptions::ClangABI::Ver23 &&
2305 !getContext().getTargetInfo().getTriple().isPS();
2306 bool IsUnion = RT->isUnionType() && !UseClang11Compat;
2309 i != e; ++i, ++idx) {
2311 bool BitField = i->isBitField();
2318 if (BitField && (ClassifyUnnamedBitFields ? i->isZeroLengthBitField()
2319 : i->isUnnamedBitField()))
2332 ((!IsUnion && Size != getContext().getTypeSize(i->getType())) ||
2333 Size > getNativeVectorSizeForAVXABI(AVXLevel))) {
2335 postMerge(Size, Lo, Hi);
2340 Offset % getContext().getTypeAlign(i->getType().getCanonicalType());
2342 if (!BitField && IsInMemory) {
2344 postMerge(Size, Lo, Hi);
2354 Class FieldLo, FieldHi;
2360 assert(ClassifyUnnamedBitFields ? !i->isZeroLengthBitField()
2361 : !i->isUnnamedBitField());
2369 assert(EB_Hi == EB_Lo &&
"Invalid classification, type > 16 bytes.");
2374 FieldHi = EB_Hi ?
Integer : NoClass;
2377 classify(i->getType(), Offset, FieldLo, FieldHi, isNamedArg);
2378 Lo =
merge(Lo, FieldLo);
2379 Hi =
merge(Hi, FieldHi);
2380 if (Lo == Memory || Hi == Memory)
2384 postMerge(Size, Lo, Hi);
2388ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty)
const {
2394 Ty = ED->getIntegerType();
2397 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
2399 llvm::Type *IRTy = CGT.ConvertType(Ty);
2401 : ABIArgInfo::getDirect(IRTy);
2404 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
2407bool X86_64ABIInfo::IsIllegalVectorType(QualType Ty)
const {
2408 if (
const VectorType *VecTy = Ty->
getAs<VectorType>()) {
2410 unsigned LargestVector = getNativeVectorSizeForAVXABI(AVXLevel);
2411 if (Size <= 64 || Size > LargestVector)
2413 QualType EltTy = VecTy->getElementType();
2414 if (passInt128VectorsInMem() &&
2423ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
2424 unsigned freeIntRegs)
const {
2437 Ty = ED->getIntegerType();
2439 llvm::Type *IRTy = CGT.ConvertType(Ty);
2445 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
2450 unsigned Align = std::max(getContext().getTypeAlign(Ty) / 8, 8U);
2473 if (freeIntRegs == 0) {
2478 if (Align == 8 && Size <= 64)
2484 getDataLayout().getAllocaAddrSpace());
2489llvm::Type *X86_64ABIInfo::GetByteVectorType(QualType Ty)
const {
2493 Ty = QualType(InnerTy, 0);
2495 llvm::Type *IRType = CGT.ConvertType(Ty);
2499 if (passInt128VectorsInMem() &&
2503 return llvm::FixedVectorType::get(llvm::Type::getInt64Ty(getVMContext()),
2510 if (IRType->getTypeID() == llvm::Type::FP128TyID)
2515 assert((Size == 128 || Size == 256 || Size == 512) &&
"Invalid type found!");
2519 return llvm::FixedVectorType::get(llvm::Type::getDoubleTy(getVMContext()),
2535 unsigned TySize = (
unsigned)Context.getTypeSize(Ty);
2536 if (TySize <= StartBit)
2540 unsigned EltSize = (
unsigned)Context.getTypeSize(AT->getElementType());
2541 unsigned NumElts = (
unsigned)AT->getZExtSize();
2544 for (
unsigned i = 0; i != NumElts; ++i) {
2546 unsigned EltOffset = i*EltSize;
2547 if (EltOffset >= EndBit)
break;
2549 unsigned EltStart = EltOffset < StartBit ? StartBit-EltOffset :0;
2551 EndBit-EltOffset, Context))
2562 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2563 for (
const auto &I : CXXRD->bases()) {
2564 assert(!I.isVirtual() && !I.getType()->isDependentType() &&
2565 "Unexpected base class!");
2566 const auto *
Base = I.getType()->castAsCXXRecordDecl();
2570 if (BaseOffset >= EndBit)
continue;
2572 unsigned BaseStart = BaseOffset < StartBit ? StartBit-BaseOffset :0;
2574 EndBit-BaseOffset, Context))
2585 i != e; ++i, ++idx) {
2589 if (FieldOffset >= EndBit)
break;
2591 unsigned FieldStart = FieldOffset < StartBit ? StartBit-FieldOffset :0;
2607 const llvm::DataLayout &TD) {
2608 if (IROffset == 0 && IRType->isFloatingPointTy())
2612 if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
2613 if (!STy->getNumContainedTypes())
2616 const llvm::StructLayout *SL = TD.getStructLayout(STy);
2617 unsigned Elt = SL->getElementContainingOffset(IROffset);
2618 IROffset -= SL->getElementOffset(Elt);
2623 if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
2624 llvm::Type *EltTy = ATy->getElementType();
2625 unsigned EltSize = TD.getTypeAllocSize(EltTy);
2628 IROffset -= IROffset / EltSize * EltSize;
2637llvm::Type *X86_64ABIInfo::
2638GetSSETypeAtOffset(llvm::Type *IRType,
unsigned IROffset,
2639 QualType SourceTy,
unsigned SourceOffset)
const {
2640 const llvm::DataLayout &TD = getDataLayout();
2641 unsigned SourceSize =
2642 (unsigned)getContext().getTypeSize(SourceTy) / 8 - SourceOffset;
2644 if (!T0 || T0->isDoubleTy())
2645 return llvm::Type::getDoubleTy(getVMContext());
2648 llvm::Type *T1 =
nullptr;
2649 unsigned T0Size = TD.getTypeAllocSize(T0);
2650 if (SourceSize > T0Size)
2652 if (T1 ==
nullptr) {
2655 if (T0->is16bitFPTy() && SourceSize > 4)
2664 if (T0->isFloatTy() && T1->isFloatTy())
2665 return llvm::FixedVectorType::get(T0, 2);
2667 if (T0->is16bitFPTy() && T1->is16bitFPTy()) {
2668 llvm::Type *T2 =
nullptr;
2672 return llvm::FixedVectorType::get(T0, 2);
2673 return llvm::FixedVectorType::get(T0, 4);
2676 if (T0->is16bitFPTy() || T1->is16bitFPTy())
2677 return llvm::FixedVectorType::get(llvm::Type::getHalfTy(getVMContext()), 4);
2679 return llvm::Type::getDoubleTy(getVMContext());
2696llvm::Type *X86_64ABIInfo::
2697GetINTEGERTypeAtOffset(llvm::Type *IRType,
unsigned IROffset,
2698 QualType SourceTy,
unsigned SourceOffset)
const {
2701 if (IROffset == 0) {
2704 IRType->isIntegerTy(64))
2713 if (IRType->isIntegerTy(8) || IRType->isIntegerTy(16) ||
2714 IRType->isIntegerTy(32) ||
2720 SourceOffset*8+64, getContext()))
2725 if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
2727 const llvm::StructLayout *SL = getDataLayout().getStructLayout(STy);
2728 if (IROffset < SL->getSizeInBytes()) {
2729 unsigned FieldIdx = SL->getElementContainingOffset(IROffset);
2730 IROffset -= SL->getElementOffset(FieldIdx);
2732 return GetINTEGERTypeAtOffset(STy->getElementType(FieldIdx), IROffset,
2733 SourceTy, SourceOffset);
2737 if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
2738 llvm::Type *EltTy = ATy->getElementType();
2739 unsigned EltSize = getDataLayout().getTypeAllocSize(EltTy);
2740 unsigned EltOffset = IROffset/EltSize*EltSize;
2741 return GetINTEGERTypeAtOffset(EltTy, IROffset-EltOffset, SourceTy,
2747 if (IRType->isIntegerTy(128)) {
2748 assert(IROffset == 0);
2754 unsigned TySizeInBytes =
2755 (unsigned)getContext().getTypeSizeInChars(SourceTy).getQuantity();
2757 assert(TySizeInBytes != SourceOffset &&
"Empty field?");
2761 return llvm::IntegerType::get(getVMContext(),
2762 std::min(TySizeInBytes-SourceOffset, 8U)*8);
2773 const llvm::DataLayout &TD) {
2778 unsigned LoSize = (
unsigned)TD.getTypeAllocSize(Lo);
2779 llvm::Align HiAlign = TD.getABITypeAlign(Hi);
2780 unsigned HiStart = llvm::alignTo(LoSize, HiAlign);
2781 assert(HiStart != 0 && HiStart <= 8 &&
"Invalid x86-64 argument pair!");
2792 if (Lo->isHalfTy() || Lo->isFloatTy())
2793 Lo = llvm::Type::getDoubleTy(Lo->getContext());
2795 assert((Lo->isIntegerTy() || Lo->isPointerTy())
2796 &&
"Invalid/unknown lo type");
2797 Lo = llvm::Type::getInt64Ty(Lo->getContext());
2801 llvm::StructType *
Result = llvm::StructType::get(Lo, Hi);
2804 assert(TD.getStructLayout(
Result)->getElementOffset(1) == 8 &&
2805 "Invalid x86-64 argument pair!");
2809ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy)
const {
2812 X86_64ABIInfo::Class Lo, Hi;
2813 classify(RetTy, 0, Lo, Hi,
true);
2816 assert((Hi != Memory || Lo == Memory) &&
"Invalid memory classification.");
2817 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp classification.");
2819 llvm::Type *ResType =
nullptr;
2826 assert((Hi == SSE || Hi ==
Integer || Hi == X87Up) &&
2827 "Unknown missing lo part");
2832 llvm_unreachable(
"Invalid classification for lo word.");
2837 return getIndirectReturnResult(RetTy);
2842 ResType = GetINTEGERTypeAtOffset(CGT.ConvertType(RetTy), 0, RetTy, 0);
2846 RetTy = ED->getIntegerType();
2853 : ABIArgInfo::getDirect();
2855 if (ResType->isIntegerTy(128)) {
2857 assert(Hi == Integer);
2858 return ABIArgInfo::getDirect(ResType);
2865 ResType = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 0, RetTy, 0);
2871 ResType = llvm::Type::getX86_FP80Ty(getVMContext());
2878 assert(Hi == ComplexX87 &&
"Unexpected ComplexX87 classification.");
2879 ResType = llvm::StructType::get(llvm::Type::getX86_FP80Ty(getVMContext()),
2880 llvm::Type::getX86_FP80Ty(getVMContext()));
2884 llvm::Type *HighPart =
nullptr;
2890 llvm_unreachable(
"Invalid classification for hi word.");
2897 HighPart = GetINTEGERTypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2902 HighPart = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2913 assert(Lo == SSE &&
"Unexpected SSEUp classification.");
2914 ResType = GetByteVectorType(RetTy);
2925 HighPart = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2942X86_64ABIInfo::classifyArgumentType(QualType Ty,
unsigned freeIntRegs,
2943 unsigned &neededInt,
unsigned &neededSSE,
2944 bool isNamedArg,
bool IsRegCall)
const {
2947 X86_64ABIInfo::Class Lo, Hi;
2948 classify(Ty, 0, Lo, Hi, isNamedArg, IsRegCall);
2952 assert((Hi != Memory || Lo == Memory) &&
"Invalid memory classification.");
2953 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp classification.");
2957 llvm::Type *ResType =
nullptr;
2964 assert((Hi == SSE || Hi ==
Integer || Hi == X87Up) &&
2965 "Unknown missing lo part");
2978 return getIndirectResult(Ty, freeIntRegs);
2982 llvm_unreachable(
"Invalid classification for lo word.");
2991 ResType = GetINTEGERTypeAtOffset(CGT.ConvertType(Ty), 0, Ty, 0);
2998 Ty = ED->getIntegerType();
3001 isPromotableIntegerTypeForABI(Ty))
3005 if (ResType->isIntegerTy(128)) {
3016 llvm::Type *IRType = CGT.ConvertType(Ty);
3017 ResType = GetSSETypeAtOffset(IRType, 0, Ty, 0);
3023 llvm::Type *HighPart =
nullptr;
3031 llvm_unreachable(
"Invalid classification for hi word.");
3033 case NoClass:
break;
3038 HighPart = GetINTEGERTypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8);
3049 HighPart = GetSSETypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8);
3059 assert(Lo == SSE &&
"Unexpected SSEUp classification");
3060 ResType = GetByteVectorType(Ty);
3077bool X86_64ABIInfo::passRegCallStructTypeDirectly(
3078 QualType Ty, SmallVectorImpl<llvm::Type *> &CoerceElts,
unsigned &NeededInt,
3079 unsigned &NeededSSE,
unsigned &MaxVectorWidth)
const {
3087 if (
auto CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
3088 if (CXXRD->isDynamicClass())
3091 for (
const auto &I : CXXRD->bases()) {
3092 QualType BaseTy = I.getType();
3095 if (!passRegCallStructTypeDirectly(BaseTy, CoerceElts, NeededInt,
3096 NeededSSE, MaxVectorWidth))
3102 for (
const auto *FD : RD->
fields()) {
3107 if (!passRegCallStructTypeDirectly(MTy, CoerceElts, NeededInt, NeededSSE,
3113 const auto *AT = getContext().getAsConstantArrayType(MTy);
3115 MTy = AT->getElementType();
3117 unsigned LocalNeededInt, LocalNeededSSE;
3119 LocalNeededSSE,
true,
true);
3126 assert(CoerceTy &&
"ABI info for struct member has no coerce type");
3128 uint64_t NumElts = AT->getZExtSize();
3129 LocalNeededInt *= NumElts;
3130 LocalNeededSSE *= NumElts;
3131 CoerceElts.push_back(llvm::ArrayType::get(CoerceTy, NumElts));
3133 CoerceElts.push_back(CoerceTy);
3136 if (
const auto *VT = MTy->
getAs<VectorType>())
3137 if (getContext().getTypeSize(VT) > MaxVectorWidth)
3138 MaxVectorWidth = getContext().getTypeSize(VT);
3140 NeededInt += LocalNeededInt;
3141 NeededSSE += LocalNeededSSE;
3148X86_64ABIInfo::classifyRegCallStructType(QualType Ty,
unsigned &NeededInt,
3149 unsigned &NeededSSE,
3150 unsigned &MaxVectorWidth)
const {
3158 SmallVector<llvm::Type *, 16> CoerceElts;
3159 if (!passRegCallStructTypeDirectly(Ty, CoerceElts, NeededInt, NeededSSE,
3161 NeededInt = NeededSSE = 0;
3162 return getIndirectReturnResult(Ty);
3165 assert(!CoerceElts.empty() &&
"Non-empty struct produced no element types");
3167 llvm::StructType::get(getVMContext(), CoerceElts));
3171X86_64ABIInfo::getX86ABIAVXLevel(
const FunctionDecl *FD,
3172 const FunctionType::ExtInfo &Info)
const {
3176void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI)
const {
3182 WinX86_64ABIInfo Win64ABIInfo(CGT, AVXLevel);
3183 Win64ABIInfo.computeInfo(FI);
3188 static_cast<unsigned>(X86AVXABILevel::AVX512) &&
3189 "Unexpected X86 AVX ABI level");
3192 if (EffectiveAVXLevel != AVXLevel) {
3193 X86_64ABIInfo EffectiveABIInfo(CGT, EffectiveAVXLevel);
3194 EffectiveABIInfo.computeInfo(FI);
3198 bool IsRegCall =
CallingConv == llvm::CallingConv::X86_RegCall;
3201 unsigned FreeIntRegs = IsRegCall ? 11 : 6;
3202 unsigned FreeSSERegs = IsRegCall ? 16 : 8;
3203 unsigned NeededInt = 0, NeededSSE = 0, MaxVectorWidth = 0;
3210 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
3211 FreeIntRegs -= NeededInt;
3212 FreeSSERegs -= NeededSSE;
3218 ->
getAs<ComplexType>()
3219 ->getElementType()) ==
3220 getContext().LongDoubleTy)
3232 else if (NeededSSE && MaxVectorWidth > 0)
3248 it != ie; ++it, ++ArgNo) {
3249 bool IsNamedArg = ArgNo < NumRequiredArgs;
3251 if (IsRegCall && it->type->isStructureOrClassType())
3252 it->info = classifyRegCallStructType(it->type, NeededInt, NeededSSE,
3256 NeededSSE, IsNamedArg);
3262 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
3263 FreeIntRegs -= NeededInt;
3264 FreeSSERegs -= NeededSSE;
3268 it->info = getIndirectResult(it->type, FreeIntRegs);
3277 llvm::Value *overflow_arg_area =
3292 llvm::Value *Res = overflow_arg_area;
3299 uint64_t SizeInBytes = (CGF.
getContext().getTypeSize(Ty) + 7) / 8;
3300 llvm::Value *Offset =
3301 llvm::ConstantInt::get(CGF.
Int32Ty, (SizeInBytes + 7) & ~7);
3303 Offset,
"overflow_arg_area.next");
3307 return Address(Res, LTy, Align);
3310RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
3311 QualType Ty, AggValueSlot Slot)
const {
3319 unsigned neededInt, neededSSE;
3331 if (!neededInt && !neededSSE)
3347 llvm::Value *InRegs =
nullptr;
3349 llvm::Value *gp_offset =
nullptr, *fp_offset =
nullptr;
3353 InRegs = llvm::ConstantInt::get(CGF.
Int32Ty, 48 - neededInt * 8);
3354 InRegs = CGF.
Builder.CreateICmpULE(gp_offset, InRegs,
"fits_in_gp");
3360 llvm::Value *FitsInFP =
3361 llvm::ConstantInt::get(CGF.
Int32Ty, 176 - neededSSE * 16);
3362 FitsInFP = CGF.
Builder.CreateICmpULE(fp_offset, FitsInFP,
"fits_in_fp");
3363 InRegs = InRegs ? CGF.
Builder.CreateAnd(InRegs, FitsInFP) : FitsInFP;
3369 CGF.
Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock);
3390 if (neededInt && neededSSE) {
3392 assert(AI.
isDirect() &&
"Unexpected ABI info for mixed regs");
3396 assert(ST->getNumElements() == 2 &&
"Unexpected ABI info for mixed regs");
3397 llvm::Type *TyLo = ST->getElementType(0);
3398 llvm::Type *TyHi = ST->getElementType(1);
3399 assert((TyLo->isFPOrFPVectorTy() ^ TyHi->isFPOrFPVectorTy()) &&
3400 "Unexpected ABI info for mixed regs");
3401 llvm::Value *GPAddr =
3403 llvm::Value *FPAddr =
3405 llvm::Value *RegLoAddr = TyLo->isFPOrFPVectorTy() ? FPAddr : GPAddr;
3406 llvm::Value *RegHiAddr = TyLo->isFPOrFPVectorTy() ? GPAddr : FPAddr;
3422 }
else if (neededInt || neededSSE == 1) {
3424 auto TInfo = getContext().getTypeInfoInChars(Ty);
3425 uint64_t TySize = TInfo.Width.getQuantity();
3426 CharUnits TyAlign = TInfo.Align;
3427 llvm::Type *CoTy =
nullptr;
3431 llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset;
3432 uint64_t Alignment = neededInt ? 8 : 16;
3433 uint64_t RegSize = neededInt ? neededInt * 8 : 16;
3458 llvm::Value *PtrOffset =
3480 assert(neededSSE == 2 &&
"Invalid number of needed registers!");
3513 llvm::Value *Offset = llvm::ConstantInt::get(CGF.
Int32Ty, neededInt * 8);
3518 llvm::Value *Offset = llvm::ConstantInt::get(CGF.
Int32Ty, neededSSE * 16);
3537RValue X86_64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
3538 QualType Ty, AggValueSlot Slot)
const {
3541 uint64_t Width = getContext().getTypeSize(Ty);
3542 bool IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
3550ABIArgInfo WinX86_64ABIInfo::reclassifyHvaArgForVectorCall(
3551 QualType Ty,
unsigned &FreeSSERegs,
const ABIArgInfo ¤t)
const {
3556 isHomogeneousAggregate(Ty, Base, NumElts) && FreeSSERegs >= NumElts) {
3557 FreeSSERegs -= NumElts;
3558 return getDirectX86Hva();
3563ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty,
unsigned &FreeSSERegs,
3564 ClassifyKind Kind,
unsigned CC)
const {
3565 bool IsVectorCall = CC == llvm::CallingConv::X86_VectorCall;
3566 bool IsRegCall = CC == llvm::CallingConv::X86_RegCall;
3571 bool PromoteScopedEnum =
false;
3573 Ty = ED->getIntegerType();
3574 PromoteScopedEnum =
Kind == ClassifyKind::VarArg && ED->isScoped() &&
3575 getContext().isPromotableIntegerType(Ty);
3582 if (PromoteScopedEnum)
3585 TypeInfo Info = getContext().getTypeInfo(Ty);
3587 CharUnits Align = getContext().toCharUnitsFromBits(Info.
Align);
3591 if (Kind != ClassifyKind::Return) {
3593 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3597 if (RT->getDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
3598 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3606 if ((IsVectorCall || IsRegCall) &&
3607 isHomogeneousAggregate(Ty, Base, NumElts)) {
3609 if (FreeSSERegs >= NumElts) {
3610 FreeSSERegs -= NumElts;
3617 Align, getDataLayout().getAllocaAddrSpace(),
3619 }
else if (IsVectorCall) {
3620 if (FreeSSERegs >= NumElts &&
3623 FreeSSERegs -= NumElts;
3625 }
else if (Kind == ClassifyKind::Return) {
3630 Align, getDataLayout().getAllocaAddrSpace(),
3639 llvm::Type *LLTy = CGT.ConvertType(Ty);
3640 if (LLTy->isPointerTy() || LLTy->isIntegerTy())
3647 if (Width > 64 || !llvm::isPowerOf2_64(Width))
3648 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3655 if (
const BuiltinType *BT = Ty->
getAs<BuiltinType>()) {
3656 switch (BT->getKind()) {
3657 case BuiltinType::Bool:
3662 case BuiltinType::LongDouble:
3666 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
3667 if (LDF == &llvm::APFloat::x87DoubleExtended())
3669 Align, getDataLayout().getAllocaAddrSpace(),
3674 case BuiltinType::Int128:
3675 case BuiltinType::UInt128:
3676 case BuiltinType::Float128:
3680 if (Kind != ClassifyKind::Return)
3682 Align, getDataLayout().getAllocaAddrSpace(),
3687 if (BT->getKind() == BuiltinType::Int128 ||
3688 BT->getKind() == BuiltinType::UInt128)
3690 llvm::Type::getInt64Ty(getVMContext()), 2));
3694 if (BT->getKind() == BuiltinType::Float128) {
3695 auto IsWin64F128StackCC = [
this](
unsigned CC) ->
bool {
3697 case llvm::CallingConv::Win64:
3699 case llvm::CallingConv::C:
3700 return getTarget().getTriple().isOSWindowsOrUEFI();
3706 if (IsWin64F128StackCC(CC))
3707 return getNaturalAlignIndirect(
3708 Ty, getDataLayout().getAllocaAddrSpace(),
false);
3726 Align, getDataLayout().getAllocaAddrSpace(),
3734WinX86_64ABIInfo::getX86ABIAVXLevel(
const FunctionDecl *FD,
3735 const FunctionType::ExtInfo &Info)
const {
3740 return static_cast<unsigned>(AVXLevel);
3743void WinX86_64ABIInfo::computeInfo(CGFunctionInfo &FI)
const {
3745 bool IsVectorCall = CC == llvm::CallingConv::X86_VectorCall;
3746 bool IsRegCall = CC == llvm::CallingConv::X86_RegCall;
3750 if (CC == llvm::CallingConv::X86_64_SysV) {
3751 X86_64ABIInfo SysVABIInfo(CGT, AVXLevel);
3752 SysVABIInfo.computeInfo(FI);
3756 unsigned FreeSSERegs = 0;
3760 }
else if (IsRegCall) {
3767 classify(FI.
getReturnType(), FreeSSERegs, ClassifyKind::Return, CC);
3772 }
else if (IsRegCall) {
3777 unsigned ArgNum = 0;
3778 unsigned ZeroSSERegs = 0;
3783 unsigned *MaybeFreeSSERegs =
3784 (IsVectorCall && ArgNum >= 6) ? &ZeroSSERegs : &FreeSSERegs;
3786 ? ClassifyKind::VarArg
3787 : ClassifyKind::FixedArgument;
3788 I.
info = classify(I.
type, *MaybeFreeSSERegs, Kind, CC);
3796 I.
info = reclassifyHvaArgForVectorCall(I.
type, FreeSSERegs, I.
info);
3800RValue WinX86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
3801 QualType Ty, AggValueSlot Slot)
const {
3804 uint64_t Width = getContext().getTypeSize(Ty);
3805 bool IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
3814 CodeGenModule &CGM,
bool DarwinVectorABI,
bool Win32StructABI,
3815 unsigned NumRegisterParameters,
bool SoftFloatABI) {
3816 bool RetSmallStructInRegABI = X86_32TargetCodeGenInfo::isStructReturnInRegABI(
3818 return std::make_unique<X86_32TargetCodeGenInfo>(
3819 CGM.
getTypes(), DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI,
3820 NumRegisterParameters, SoftFloatABI);
3824 CodeGenModule &CGM,
bool DarwinVectorABI,
bool Win32StructABI,
3825 unsigned NumRegisterParameters) {
3826 bool RetSmallStructInRegABI = X86_32TargetCodeGenInfo::isStructReturnInRegABI(
3828 return std::make_unique<WinX86_32TargetCodeGenInfo>(
3829 CGM.
getTypes(), DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI,
3830 NumRegisterParameters);
3833std::unique_ptr<TargetCodeGenInfo>
3836 return std::make_unique<X86_64TargetCodeGenInfo>(CGM.
getTypes(), AVXLevel);
3839std::unique_ptr<TargetCodeGenInfo>
3842 return std::make_unique<WinX86_64TargetCodeGenInfo>(CGM.
getTypes(), AVXLevel);
static bool is32Or64BitBasicType(QualType Ty, ASTContext &Context)
static bool checkAVXParamFeature(DiagnosticsEngine &Diag, SourceLocation CallLoc, const FunctionDecl &Callee, const llvm::StringMap< bool > &CallerMap, const llvm::StringMap< bool > &CalleeMap, QualType Ty, StringRef Feature, bool IsArgument)
static void rewriteInputConstraintReferences(unsigned FirstIn, unsigned NumNewOuts, std::string &AsmString)
Rewrite input constraint references after adding some output constraints.
static const Type * getSingleFieldType(QualType T, ASTContext &Context)
Like isSingleElementRecord, but only looks through one level of records.
static void initFeatureMaps(const ASTContext &Ctx, llvm::StringMap< bool > &CallerMap, const FunctionDecl *Caller, llvm::StringMap< bool > &CalleeMap, const FunctionDecl *Callee)
static llvm::Type * GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type *Hi, const llvm::DataLayout &TD)
GetX86_64ByValArgumentPair - Given a high and low type that can ideally be used as elements of a two ...
static X86AVXABILevel getEffectiveX86AVXABILevel(CodeGenTypes &CGT, X86AVXABILevel GlobalAVXLevel, const FunctionDecl *FD)
static bool checkAVXParam(DiagnosticsEngine &Diag, ASTContext &Ctx, SourceLocation CallLoc, const FunctionDecl &Callee, const llvm::StringMap< bool > &CallerMap, const llvm::StringMap< bool > &CalleeMap, QualType Ty, bool IsArgument)
static bool addBaseAndFieldSizes(ASTContext &Context, const CXXRecordDecl *RD, uint64_t &Size)
static llvm::Type * getFPTypeAtOffset(llvm::Type *IRType, unsigned IROffset, const llvm::DataLayout &TD)
getFPTypeAtOffset - Return a floating point type at the specified offset.
static bool addFieldSizes(ASTContext &Context, const RecordDecl *RD, uint64_t &Size)
static bool shouldExtendReturnType(const ABIInfo &Info, QualType RetTy)
static bool BitsContainNoUserData(QualType Ty, unsigned StartBit, unsigned EndBit, ASTContext &Context)
BitsContainNoUserData - Return true if the specified [start,end) bit range is known to either be off ...
static Address EmitX86_64VAArgFromMemory(CodeGenFunction &CGF, Address VAListAddr, QualType Ty)
static void addX86InterruptAttrs(const FunctionDecl *FD, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
static bool isArgInAlloca(const ABIArgInfo &Info)
Result
Implement __builtin_bit_cast and related operations.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
static StringRef getTriple(const Command &Job)
Defines the clang::SourceLocation class and associated facilities.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
const LangOptions & getLangOpts() const
TypeInfoChars getTypeInfoInChars(const Type *T) const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
void getFunctionFeatureMap(llvm::StringMap< bool > &FeatureMap, const FunctionDecl *) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getRequiredAlignment() const
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
This class is used for builtin types like 'int'.
Represents a base class of a C++ class.
Represents a C++ struct/union/class.
CanProxy< U > getAs() const
Retrieve a canonical type pointer with a different static type, upcasting or downcasting as needed.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
This is an opaque type for sizes expressed in character units.
CharUnits alignTo(CharUnits Align) const
Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is a multiple...
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
static CharUnits One()
Construct a CharUnits quantity of one.
bool isMultipleOf(CharUnits N) const
Test whether this is a multiple of the other value.
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
bool getIndirectByVal() const
static ABIArgInfo getInAlloca(unsigned FieldIndex, bool Indirect=false)
static ABIArgInfo getIgnore()
static ABIArgInfo getExpand()
unsigned getDirectOffset() const
void setIndirectAlign(CharUnits IA)
static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T=nullptr)
static ABIArgInfo getExpandWithPadding(bool PaddingInReg, llvm::Type *Padding)
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
@ Extend
Extend - Valid only for integer argument types.
@ Ignore
Ignore - Ignore the argument (treat as void).
@ IndirectAliased
IndirectAliased - Similar to Indirect, but the pointer may be to an object that is otherwise referenc...
@ Expand
Expand - Only valid for aggregate argument types.
@ TargetSpecific
TargetSpecific - Some argument types are passed as target specific types such as RISC-V's tuple type,...
@ InAlloca
InAlloca - Pass the argument directly using the LLVM inalloca attribute.
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
@ CoerceAndExpand
CoerceAndExpand - Only valid for aggregate argument types.
@ Direct
Direct - Pass the argument directly using the normal converted LLVM type, or by coercing to another s...
static ABIArgInfo getExtend(QualType Ty, llvm::Type *T=nullptr, llvm::Type *Padding=nullptr)
static ABIArgInfo getIndirect(CharUnits Alignment, unsigned AddrSpace, bool ByVal=true, bool Realign=false, llvm::Type *Padding=nullptr)
llvm::Type * getCoerceToType() const
bool canHaveCoerceToType() const
static ABIArgInfo getDirectInReg(llvm::Type *T=nullptr)
ABIInfo - Target specific hooks for defining how a type should be passed or returned from functions.
bool isPromotableIntegerTypeForABI(QualType Ty) const
const TargetInfo & getTarget() const
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * getBasePointer() const
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name="")
Given a pointer to i8, adjust it by a given constant offset.
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Address CreateStructGEP(Address Addr, unsigned Index, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")
RecordArgABI
Specify how one should pass an argument of a record type.
@ RAA_Indirect
Pass it as a pointer to temporary memory.
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
ABIArgInfo & getReturnInfo()
unsigned getCallingConvention() const
getCallingConvention - Return the user specified calling convention, which has been translated into a...
const_arg_iterator arg_begin() const
unsigned getRegParm() const
CanQualType getReturnType() const
bool getHasRegParm() const
MutableArrayRef< ArgInfo > arguments()
const_arg_iterator arg_end() const
unsigned getX86ABIAVXLevel() const
void setArgStruct(llvm::StructType *Ty, CharUnits Align)
unsigned getMaxVectorWidth() const
Return the maximum vector width in the arguments.
unsigned getNumRequiredArgs() const
void setMaxVectorWidth(unsigned Width)
Set the maximum vector width in the arguments.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
RValue EmitLoadOfAnyValue(LValue V, AggValueSlot Slot=AggValueSlot::ignored(), SourceLocation Loc={})
Like EmitLoadOfLValue but also handles complex and aggregate types.
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
ASTContext & getContext() const
llvm::Type * ConvertTypeForMem(QualType T)
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
const CGFunctionInfo * CurFnInfo
llvm::LLVMContext & getLLVMContext()
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
This class organizes the cross-function state that is used while generating LLVM code.
DiagnosticsEngine & getDiags() const
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
const llvm::Triple & getTriple() const
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
ASTContext & getContext() const
const TargetInfo & getTarget() const
CodeGenModule & getCGM() const
bool isRequiredArg(unsigned argIdx) const
Return true if the argument at a given index is required.
Target specific hooks for defining how a type should be passed or returned from functions with one of...
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
virtual void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const
setTargetAttributes - Provides a convenient hook to handle extra target-specific attributes for the g...
static std::string qualifyWindowsLibrary(StringRef Lib)
virtual bool isNoProtoCallVariadic(const CodeGen::CallArgList &args, const FunctionNoProtoType *fnType) const
Determine whether a call to an unprototyped functions under the given calling convention should use t...
Complex values, per C99 6.2.5p11.
Represents the canonical version of C arrays with a specified constant size.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getLocation() const
SourceLocation getBeginLoc() const LLVM_READONLY
TypeSourceInfo * getTypeSourceInfo() const
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
CallingConv getCC() const
CallingConv getCallConv() const
bool isExternallyVisible() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
QualType getCanonicalType() const
Represents a struct/union/class.
bool hasFlexibleArrayMember() const
field_iterator field_end() const
field_range fields() const
specific_decl_iterator< FieldDecl > field_iterator
RecordDecl * getDefinitionOrSelf() const
field_iterator field_begin() const
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
T getAs() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
TypeLoc IgnoreParens() const
The base class of the type hierarchy.
bool isBlockPointerType() const
bool isBooleanType() const
bool isFloat16Type() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isEnumeralType() const
bool isFloat128Type() const
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isBitIntType() const
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isBuiltinType() const
Helper methods to distinguish type categories.
bool isAnyComplexType() const
bool isMemberPointerType() const
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
bool isBFloat16Type() const
bool isMemberFunctionPointerType() const
bool isVectorType() const
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
bool hasPointerRepresentation() const
Whether this type is represented natively as a pointer.
Represents a GCC generic vector type.
bool shouldPassIndirectly(CodeGenModule &CGM, ArrayRef< llvm::Type * > types, bool asReturnValue)
Should an aggregate which expands to the given type sequence be passed/returned indirectly under swif...
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI)
std::unique_ptr< TargetCodeGenInfo > createX86_64TargetCodeGenInfo(CodeGenModule &CGM, X86AVXABILevel AVXLevel)
bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info)
std::unique_ptr< TargetCodeGenInfo > createWinX86_32TargetCodeGenInfo(CodeGenModule &CGM, bool DarwinVectorABI, bool Win32StructABI, unsigned NumRegisterParameters)
bool isRecordWithSIMDVectorType(ASTContext &Context, QualType Ty)
RValue emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType ValueTy, bool IsIndirect, TypeInfoChars ValueInfo, CharUnits SlotSizeAndAlign, bool AllowHigherAlign, AggValueSlot Slot, bool ForceRightAdjust=false)
Emit va_arg for a platform using the common void* representation, where arguments are simply emitted ...
Address emitMergePHI(CodeGenFunction &CGF, Address Addr1, llvm::BasicBlock *Block1, Address Addr2, llvm::BasicBlock *Block2, const llvm::Twine &Name="")
X86AVXABILevel
The AVX ABI level for X86 targets.
const Type * isSingleElementRecord(QualType T, ASTContext &Context)
isSingleElementRecord - Determine if a record is a "singleelement record", i.e.
bool isEmptyField(ASTContext &Context, const FieldDecl *FD, bool AllowArrays, bool AsIfNoUniqueAddr=false)
isEmptyField - Return true iff a the field is "empty", that is it is an unnamed bit-field or an (arra...
llvm::Value * emitRoundPointerUpToAlignment(CodeGenFunction &CGF, llvm::Value *Ptr, CharUnits Align)
bool isAggregateTypeForABI(QualType T)
void AssignToArrayRange(CodeGen::CGBuilderTy &Builder, llvm::Value *Array, llvm::Value *Value, unsigned FirstIndex, unsigned LastIndex)
QualType useFirstFieldIfTransparentUnion(QualType Ty)
Pass transparent unions as if they were the type of the first element.
std::unique_ptr< TargetCodeGenInfo > createX86_32TargetCodeGenInfo(CodeGenModule &CGM, bool DarwinVectorABI, bool Win32StructABI, unsigned NumRegisterParameters, bool SoftFloatABI)
bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, bool AsIfNoUniqueAddr=false)
isEmptyRecord - Return true iff a structure contains only empty fields.
std::unique_ptr< TargetCodeGenInfo > createWinX86_64TargetCodeGenInfo(CodeGenModule &CGM, X86AVXABILevel AVXLevel)
bool isSIMDVectorType(ASTContext &Context, QualType Ty)
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
PRESERVE_NONE bool Ret(InterpState &S)
@ Address
A pointer to a ValueDecl.
void info(bool Verbose, unsigned Level, const char *Fmt, Ts &&...Args)
Prints an indented note to stderr when Verbose is set.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
@ Default
Set to the current date and time.
const FunctionProtoType * T
CallingConv
CallingConv - Specifies the calling convention that a function uses.
U cast(CodeGen::Address addr)
@ Class
The "class" keyword introduces the elaborated-type-specifier.
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
llvm::IntegerType * Int64Ty
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * Int32Ty