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);
462ABIArgInfo X86_32ABIInfo::getIndirectReturnResult(QualType RetTy, CCState &State)
const {
465 if (State.CC != llvm::CallingConv::X86_FastCall &&
466 State.CC != llvm::CallingConv::X86_VectorCall && State.FreeRegs) {
469 return getNaturalAlignIndirectInReg(RetTy);
471 return getNaturalAlignIndirect(
472 RetTy, getDataLayout().getAllocaAddrSpace(),
476ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
477 CCState &State)
const {
483 if ((State.CC == llvm::CallingConv::X86_VectorCall ||
484 State.CC == llvm::CallingConv::X86_RegCall) &&
485 isHomogeneousAggregate(RetTy, Base, NumElts)) {
490 if (
const VectorType *VT = RetTy->
getAs<VectorType>()) {
492 if (IsDarwinVectorABI) {
500 llvm::Type::getInt64Ty(getVMContext()), 2));
504 if ((Size == 8 || Size == 16 || Size == 32) ||
505 (Size == 64 && VT->getNumElements() == 1))
509 return getIndirectReturnResult(RetTy, State);
519 return getIndirectReturnResult(RetTy, State);
523 return getIndirectReturnResult(RetTy, State);
530 if (
const ComplexType *CT = RetTy->
getAs<ComplexType>()) {
531 QualType ET = getContext().getCanonicalType(CT->getElementType());
534 llvm::Type::getHalfTy(getVMContext()), 2));
539 if (shouldReturnTypeInRegister(RetTy, getContext())) {
548 if ((!IsWin32StructABI && SeltTy->isRealFloatingType())
549 || SeltTy->hasPointerRepresentation())
557 return getIndirectReturnResult(RetTy, State);
562 RetTy = ED->getIntegerType();
564 if (
const auto *EIT = RetTy->
getAs<BitIntType>())
565 if (EIT->getNumBits() > 64)
566 return getIndirectReturnResult(RetTy, State);
572unsigned X86_32ABIInfo::getTypeStackAlignInBytes(QualType Ty,
573 unsigned Align)
const {
576 if (Align <= MinABIStackAlignInBytes)
587 if (Ty->
isVectorType() && (Align == 16 || Align == 32 || Align == 64))
591 if (!IsDarwinVectorABI) {
593 return MinABIStackAlignInBytes;
601 return MinABIStackAlignInBytes;
604ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty,
bool ByVal,
605 CCState &State)
const {
607 if (State.FreeRegs) {
610 return getNaturalAlignIndirectInReg(Ty);
612 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
617 unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
618 unsigned StackAlign = getTypeStackAlignInBytes(Ty, TypeAlign);
622 getDataLayout().getAllocaAddrSpace(),
627 bool Realign = TypeAlign > StackAlign;
630 getDataLayout().getAllocaAddrSpace(),
true,
637 const auto *RD =
T->getAsRecordDecl();
647 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
648 for (
const auto &I : CXXRD->bases()) {
657 Found = I.getType().getTypePtr();
662 for (
const auto *FD : RD->
fields()) {
676 if (AT->getZExtSize() != 1)
678 FT = AT->getElementType();
686 if (
Found && Context.getTypeSize(
Found) != Context.getTypeSize(
T))
692X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty)
const {
693 if (getContext().getLangOpts().isCompatibleWith(
694 LangOptions::ClangABI::Ver23)) {
699 if (
const BuiltinType *BT =
T->
getAs<BuiltinType>()) {
701 if (K == BuiltinType::Float || K == BuiltinType::Double)
718 Ty = QualType(FT, 0);
726 if (
const BuiltinType *BT = Ty->
getAs<BuiltinType>())
727 if (BT->isFloatingPoint())
733bool X86_32ABIInfo::updateFreeRegs(QualType Ty, CCState &State)
const {
735 if (
C == AlwaysStack && !IsMCUABI)
737 if (
C ==
Float && !IsSoftFloatABI)
740 unsigned Size = getContext().getTypeSize(Ty);
741 unsigned SizeInRegs = (
Size + 31) / 32;
747 if (SizeInRegs > State.FreeRegs) {
756 if (SizeInRegs > State.FreeRegs || SizeInRegs > 2)
760 State.FreeRegs -= SizeInRegs;
764bool X86_32ABIInfo::shouldAggregateUseDirect(QualType Ty, CCState &State,
766 bool &NeedsPadding)
const {
773 NeedsPadding =
false;
776 if (!updateFreeRegs(Ty, State))
782 if (State.CC == llvm::CallingConv::X86_FastCall ||
783 State.CC == llvm::CallingConv::X86_VectorCall ||
784 State.CC == llvm::CallingConv::X86_RegCall) {
785 if (getContext().getTypeSize(Ty) <= 32 && State.FreeRegs)
794bool X86_32ABIInfo::shouldPrimitiveUseInReg(QualType Ty, CCState &State)
const {
795 bool IsPtrOrInt = (getContext().getTypeSize(Ty) <= 32) &&
799 if (!IsPtrOrInt && (State.CC == llvm::CallingConv::X86_FastCall ||
800 State.CC == llvm::CallingConv::X86_VectorCall))
803 if (!updateFreeRegs(Ty, State))
806 if (!IsPtrOrInt && State.CC == llvm::CallingConv::X86_RegCall)
813void X86_32ABIInfo::runVectorCallFirstPass(CGFunctionInfo &FI, CCState &State)
const {
823 MutableArrayRef<CGFunctionInfoArgInfo> Args = FI.
arguments();
824 for (
int I = 0, E = Args.size(); I < E; ++I) {
827 const QualType &Ty = Args[I].type;
829 isHomogeneousAggregate(Ty, Base, NumElts)) {
830 if (State.FreeSSERegs >= NumElts) {
831 State.FreeSSERegs -= NumElts;
833 State.IsPreassigned.set(I);
839ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State,
840 unsigned ArgIndex)
const {
842 bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
843 bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
844 bool IsVectorCall = State.CC == llvm::CallingConv::X86_VectorCall;
847 TypeInfo TI = getContext().getTypeInfo(Ty);
854 return getIndirectResult(Ty,
false, State);
855 }
else if (State.IsDelegateCall) {
858 ABIArgInfo Res = getIndirectResult(Ty,
false, State);
871 if ((IsRegCall || IsVectorCall) &&
872 isHomogeneousAggregate(Ty, Base, NumElts)) {
873 if (State.FreeSSERegs >= NumElts) {
874 State.FreeSSERegs -= NumElts;
879 return getDirectX86Hva();
887 return getIndirectResult(Ty,
false, State);
893 if (RT && RT->getDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
894 return getIndirectResult(Ty,
true, State);
897 if (!IsWin32StructABI &&
isEmptyRecord(getContext(), Ty,
true))
904 llvm::LLVMContext &LLVMContext = getVMContext();
905 llvm::IntegerType *
Int32 = llvm::Type::getInt32Ty(LLVMContext);
906 bool NeedsPadding =
false;
908 if (shouldAggregateUseDirect(Ty, State, InReg, NeedsPadding)) {
909 unsigned SizeInRegs = (TI.
Width + 31) / 32;
910 SmallVector<llvm::Type*, 3> Elements(SizeInRegs, Int32);
911 llvm::Type *
Result = llvm::StructType::get(LLVMContext, Elements);
917 llvm::IntegerType *PaddingType = NeedsPadding ?
Int32 :
nullptr;
924 if (IsWin32StructABI && State.Required.
isRequiredArg(ArgIndex)) {
925 unsigned AlignInBits = 0;
927 const ASTRecordLayout &Layout =
928 getContext().getASTRecordLayout(RT->getDecl());
931 AlignInBits = TI.
Align;
933 if (AlignInBits > 32)
934 return getIndirectResult(Ty,
false, State);
943 if (TI.
Width <= 4 * 32 && (!IsMCUABI || State.FreeRegs == 0) &&
944 canExpandIndirectArgument(Ty))
946 IsFastCall || IsVectorCall || IsRegCall, PaddingType);
948 return getIndirectResult(Ty,
true, State);
951 if (
const VectorType *VT = Ty->
getAs<VectorType>()) {
955 if (IsWin32StructABI) {
956 if (TI.
Width <= 512 && State.FreeSSERegs > 0) {
960 return getIndirectResult(Ty,
false, State);
965 if (IsDarwinVectorABI) {
967 (TI.
Width == 64 && VT->getNumElements() == 1))
969 llvm::IntegerType::get(getVMContext(), TI.
Width));
972 if (IsX86_MMXType(CGT.ConvertType(Ty)))
979 Ty = ED->getIntegerType();
981 bool InReg = shouldPrimitiveUseInReg(Ty, State);
983 if (isPromotableIntegerTypeForABI(Ty)) {
989 if (
const auto *EIT = Ty->
getAs<BitIntType>()) {
990 if (EIT->getNumBits() <= 64) {
995 return getIndirectResult(Ty,
false, State);
1003void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI)
const {
1007 else if (State.CC == llvm::CallingConv::X86_FastCall) {
1009 State.FreeSSERegs = 3;
1010 }
else if (State.CC == llvm::CallingConv::X86_VectorCall) {
1012 State.FreeSSERegs = 6;
1015 else if (State.CC == llvm::CallingConv::X86_RegCall) {
1017 State.FreeSSERegs = 8;
1018 }
else if (IsWin32StructABI) {
1021 State.FreeRegs = DefaultNumRegisterParameters;
1022 State.FreeSSERegs = 3;
1024 State.FreeRegs = DefaultNumRegisterParameters;
1031 if (State.FreeRegs) {
1044 if (State.CC == llvm::CallingConv::X86_VectorCall)
1045 runVectorCallFirstPass(FI, State);
1047 bool UsedInAlloca =
false;
1048 MutableArrayRef<CGFunctionInfoArgInfo> Args = FI.
arguments();
1049 for (
unsigned I = 0, E = Args.size(); I < E; ++I) {
1051 if (State.IsPreassigned.test(I))
1062 rewriteWithInAlloca(FI);
1066X86_32ABIInfo::addFieldToArgStruct(SmallVector<llvm::Type *, 6> &FrameFields,
1067 CharUnits &StackOffset, ABIArgInfo &Info,
1068 QualType
Type)
const {
1071 assert(StackOffset.
isMultipleOf(WordSize) &&
"unaligned inalloca struct");
1076 bool IsIndirect =
false;
1080 llvm::Type *LLTy = CGT.ConvertTypeForMem(
Type);
1082 LLTy = llvm::PointerType::getUnqual(getVMContext());
1083 FrameFields.push_back(LLTy);
1084 StackOffset += IsIndirect ? WordSize : getContext().getTypeSizeInChars(
Type);
1087 CharUnits FieldEnd = StackOffset;
1088 StackOffset = FieldEnd.
alignTo(WordSize);
1089 if (StackOffset != FieldEnd) {
1090 CharUnits NumBytes = StackOffset - FieldEnd;
1091 llvm::Type *Ty = llvm::Type::getInt8Ty(getVMContext());
1092 Ty = llvm::ArrayType::get(Ty, NumBytes.
getQuantity());
1093 FrameFields.push_back(Ty);
1116 llvm_unreachable(
"invalid enum");
1119void X86_32ABIInfo::rewriteWithInAlloca(CGFunctionInfo &FI)
const {
1120 assert(IsWin32StructABI &&
"inalloca only supported on win32");
1123 SmallVector<llvm::Type *, 6> FrameFields;
1128 CharUnits StackOffset;
1135 if (
Ret.isIndirect() &&
Ret.isSRetAfterThis() && !IsThisCall &&
1137 addFieldToArgStruct(FrameFields, StackOffset, I->
info, I->
type);
1142 if (
Ret.isIndirect() && !
Ret.getInReg()) {
1143 addFieldToArgStruct(FrameFields, StackOffset, Ret, FI.
getReturnType());
1145 Ret.setInAllocaSRet(IsWin32StructABI);
1153 for (; I != E; ++I) {
1155 addFieldToArgStruct(FrameFields, StackOffset, I->
info, I->
type);
1158 FI.
setArgStruct(llvm::StructType::get(getVMContext(), FrameFields,
1163RValue X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
1164 QualType Ty, AggValueSlot Slot)
const {
1166 auto TypeInfo = getContext().getTypeInfoInChars(Ty);
1168 CCState State(*
const_cast<CGFunctionInfo *
>(CGF.
CurFnInfo));
1179 getTypeStackAlignInBytes(Ty, TypeInfo.Align.getQuantity()));
1186bool X86_32TargetCodeGenInfo::isStructReturnInRegABI(
1187 const llvm::Triple &Triple,
const CodeGenOptions &Opts) {
1188 assert(Triple.getArch() == llvm::Triple::x86);
1190 switch (Opts.getStructReturnConvention()) {
1199 if (Triple.isOSDarwin() || Triple.isOSIAMCU())
1202 switch (Triple.getOS()) {
1203 case llvm::Triple::DragonFly:
1204 case llvm::Triple::FreeBSD:
1205 case llvm::Triple::OpenBSD:
1206 case llvm::Triple::Win32:
1215 if (!FD->
hasAttr<AnyX86InterruptAttr>())
1219 Fn->setCallingConv(llvm::CallingConv::X86_INTR);
1225 llvm::Attribute NewAttr = llvm::Attribute::getWithByValType(
1226 Fn->getContext(), ByValTy);
1227 Fn->addParamAttr(0, NewAttr);
1230void X86_32TargetCodeGenInfo::setTargetAttributes(
1231 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
const {
1232 if (GV->isDeclaration())
1234 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
1235 if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
1237 Fn->addFnAttr(
"stackrealign");
1244bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable(
1245 CodeGen::CodeGenFunction &CGF,
1246 llvm::Value *Address)
const {
1247 CodeGen::CGBuilderTy &Builder = CGF.
Builder;
1249 llvm::Value *Four8 = llvm::ConstantInt::get(CGF.
Int8Ty, 4);
1260 llvm::Value *Sixteen8 = llvm::ConstantInt::get(CGF.
Int8Ty, 16);
1266 Builder.CreateAlignedStore(
1267 Four8, Builder.CreateConstInBoundsGEP1_32(CGF.
Int8Ty, Address, 9),
1273 llvm::Value *Twelve8 = llvm::ConstantInt::get(CGF.
Int8Ty, 12);
1288static unsigned getNativeVectorSizeForAVXABI(
X86AVXABILevel AVXLevel) {
1290 case X86AVXABILevel::AVX512:
1292 case X86AVXABILevel::AVX:
1294 case X86AVXABILevel::None:
1297 llvm_unreachable(
"Unknown AVXLevel");
1301class X86_64ABIInfo :
public ABIInfo {
1338 void postMerge(
unsigned AggregateSize,
Class &Lo,
Class &Hi)
const;
1366 void classify(QualType
T, uint64_t OffsetBase,
Class &Lo,
Class &Hi,
1367 bool isNamedArg,
bool IsRegCall =
false)
const;
1369 llvm::Type *GetByteVectorType(QualType Ty)
const;
1370 llvm::Type *GetSSETypeAtOffset(llvm::Type *IRType,
1371 unsigned IROffset, QualType SourceTy,
1372 unsigned SourceOffset)
const;
1373 llvm::Type *GetINTEGERTypeAtOffset(llvm::Type *IRType,
1374 unsigned IROffset, QualType SourceTy,
1375 unsigned SourceOffset)
const;
1379 ABIArgInfo getIndirectReturnResult(QualType Ty)
const;
1386 ABIArgInfo getIndirectResult(QualType Ty,
unsigned freeIntRegs)
const;
1391 unsigned &neededInt,
unsigned &neededSSE,
1393 bool IsRegCall =
false)
const;
1395 ABIArgInfo classifyRegCallStructType(QualType Ty,
unsigned &NeededInt,
1396 unsigned &NeededSSE,
1397 unsigned &MaxVectorWidth)
const;
1399 bool passRegCallStructTypeDirectly(QualType Ty,
1400 SmallVectorImpl<llvm::Type *> &CoerceElts,
1401 unsigned &NeededInt,
unsigned &NeededSSE,
1402 unsigned &MaxVectorWidth)
const;
1404 bool IsIllegalVectorType(QualType Ty)
const;
1411 bool honorsRevision0_98()
const {
1412 return !getTarget().getTriple().isOSDarwin();
1417 bool classifyIntegerMMXAsSSE()
const {
1419 if (getContext().getLangOpts().isCompatibleWith(
1420 LangOptions::ClangABI::Ver3_8))
1423 const llvm::Triple &Triple = getTarget().getTriple();
1424 if (Triple.isOSDarwin() || Triple.isPS() || Triple.isOSFreeBSD())
1430 bool passInt128VectorsInMem()
const {
1432 if (getContext().getLangOpts().isCompatibleWith(
1433 LangOptions::ClangABI::Ver9))
1436 const llvm::Triple &
T = getTarget().getTriple();
1437 return T.isOSLinux() ||
T.isOSNetBSD();
1440 bool returnCXXRecordGreaterThan128InMem()
const {
1442 if (getContext().getLangOpts().isCompatibleWith(
1443 LangOptions::ClangABI::Ver20) ||
1453 bool Has64BitPointers;
1456 X86_64ABIInfo(CodeGen::CodeGenTypes &CGT,
X86AVXABILevel AVXLevel)
1457 : ABIInfo(CGT), AVXLevel(AVXLevel),
1458 Has64BitPointers(CGT.getDataLayout().getPointerSize(0) == 8) {}
1460 bool isPassedUsingAVXType(QualType
type)
const {
1461 unsigned neededInt, neededSSE;
1465 if (
info.isDirect()) {
1466 llvm::Type *ty =
info.getCoerceToType();
1467 if (llvm::VectorType *vectorTy = dyn_cast_or_null<llvm::VectorType>(ty))
1468 return vectorTy->getPrimitiveSizeInBits().getFixedValue() > 128;
1473 void computeInfo(CGFunctionInfo &FI)
const override;
1474 unsigned getX86ABIAVXLevel(
const FunctionDecl *FD,
1475 const FunctionType::ExtInfo &Info)
const override;
1477 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1478 AggValueSlot Slot)
const override;
1479 RValue EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1480 AggValueSlot Slot)
const override;
1482 bool has64BitPointers()
const {
1483 return Has64BitPointers;
1488class WinX86_64ABIInfo :
public ABIInfo {
1490 WinX86_64ABIInfo(CodeGen::CodeGenTypes &CGT,
X86AVXABILevel AVXLevel)
1491 : ABIInfo(CGT), AVXLevel(AVXLevel),
1492 IsMingw64(getTarget().
getTriple().isWindowsGNUEnvironment()) {}
1494 void computeInfo(CGFunctionInfo &FI)
const override;
1495 unsigned getX86ABIAVXLevel(
const FunctionDecl *FD,
1496 const FunctionType::ExtInfo &Info)
const override;
1498 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1499 AggValueSlot Slot)
const override;
1501 bool isHomogeneousAggregateBaseType(QualType Ty)
const override {
1503 return isX86VectorTypeForVectorCall(getContext(), Ty);
1506 bool isHomogeneousAggregateSmallEnough(
const Type *Ty,
1507 uint64_t NumMembers)
const override {
1509 return isX86VectorCallAggregateSmallEnough(NumMembers);
1512 ABIArgInfo classifyArgForArm64ECVarArg(QualType Ty,
1513 bool IsNamedArg)
const override {
1514 unsigned FreeSSERegs = 0;
1516 IsNamedArg ? ClassifyKind::FixedArgument : ClassifyKind::VarArg;
1517 return classify(Ty, FreeSSERegs, Kind, llvm::CallingConv::C);
1521 enum class ClassifyKind { Return, FixedArgument, VarArg };
1523 ABIArgInfo classify(QualType Ty,
unsigned &FreeSSERegs, ClassifyKind Kind,
1525 ABIArgInfo reclassifyHvaArgForVectorCall(QualType Ty,
unsigned &FreeSSERegs,
1526 const ABIArgInfo ¤t)
const;
1533class X86_64TargetCodeGenInfo :
public TargetCodeGenInfo {
1535 X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
X86AVXABILevel AVXLevel)
1536 : TargetCodeGenInfo(std::make_unique<X86_64ABIInfo>(CGT, AVXLevel)) {
1538 std::make_unique<SwiftABIInfo>(CGT,
true);
1543 bool markARCOptimizedReturnCallsAsNoTail()
const override {
return true; }
1545 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
1549 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
1550 llvm::Value *Address)
const override {
1551 llvm::Value *Eight8 = llvm::ConstantInt::get(CGF.
Int8Ty, 8);
1559 llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
1560 StringRef Constraint,
1561 llvm::Type* Ty)
const override {
1562 return X86AdjustInlineAsmType(CGF, Constraint, Ty);
1565 bool isNoProtoCallVariadic(
const CallArgList &args,
1566 const FunctionNoProtoType *fnType)
const override {
1574 bool HasAVXType =
false;
1575 for (
const CallArg &arg : args) {
1576 if (getABIInfo<X86_64ABIInfo>().isPassedUsingAVXType(
arg.Ty)) {
1589 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1590 CodeGen::CodeGenModule &CGM)
const override {
1591 if (GV->isDeclaration())
1593 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
1594 if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
1596 Fn->addFnAttr(
"stackrealign");
1603 void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc,
1604 const FunctionDecl *Caller,
1605 const FunctionDecl *Callee,
const CallArgList &Args,
1606 QualType ReturnType)
const override;
1608 void checkFunctionABI(CodeGenModule &CGM,
1609 const FunctionDecl *FD)
const override;
1614 llvm::StringMap<bool> &CallerMap,
1616 llvm::StringMap<bool> &CalleeMap,
1618 if (CalleeMap.empty() && CallerMap.empty()) {
1630 const llvm::StringMap<bool> &CallerMap,
1631 const llvm::StringMap<bool> &CalleeMap,
1634 bool CallerHasFeat = CallerMap.lookup(
Feature);
1635 bool CalleeHasFeat = CalleeMap.lookup(
Feature);
1637 if (!CallerHasFeat && !CalleeHasFeat &&
1638 (!Callee.isExternallyVisible() || Callee.hasAttr<AlwaysInlineAttr>()))
1641 if (!CallerHasFeat && !CalleeHasFeat)
1642 return Diag.Report(CallLoc, diag::warn_avx_calling_convention)
1643 << IsArgument << Ty <<
Feature;
1646 if (!CallerHasFeat || !CalleeHasFeat)
1647 return Diag.Report(CallLoc, diag::err_avx_calling_convention)
1648 << IsArgument << Ty <<
Feature;
1657 const llvm::StringMap<bool> &CallerMap,
1658 const llvm::StringMap<bool> &CalleeMap,
QualType Ty,
1663 "avx512f", IsArgument);
1672void X86_64TargetCodeGenInfo::checkFunctionABI(CodeGenModule &CGM,
1673 const FunctionDecl *FD)
const {
1674 auto GetReturnTypeLoc = [](
const FunctionDecl *FD) {
1676 TypeLoc TL = TSI->getTypeLoc();
1679 SourceLocation Loc = FTL.getReturnLoc().getBeginLoc();
1692 auto Check = [&](QualType Ty, SourceLocation Loc,
bool IsReturn) {
1701 llvm::StringMap<bool> FeatureMap;
1703 if (!FeatureMap.lookup(
Feature)) {
1705 << !IsReturn << Ty <<
Feature;
1722 for (
const ParmVarDecl *P : FD->
parameters()) {
1723 SourceLocation Loc = P->getLocation();
1725 Loc = P->getBeginLoc();
1726 if (Check(P->getType(), Loc,
false))
1731void X86_64TargetCodeGenInfo::checkFunctionCallABI(CodeGenModule &CGM,
1732 SourceLocation CallLoc,
1733 const FunctionDecl *Caller,
1734 const FunctionDecl *Callee,
1735 const CallArgList &Args,
1736 QualType ReturnType)
const {
1740 llvm::StringMap<bool> CallerMap;
1741 llvm::StringMap<bool> CalleeMap;
1742 unsigned ArgIndex = 0;
1746 for (
const CallArg &Arg : Args) {
1754 if (Arg.getType()->isVectorType() &&
1757 QualType Ty = Arg.getType();
1760 if (ArgIndex < Callee->getNumParams())
1761 Ty =
Callee->getParamDecl(ArgIndex)->getType();
1764 CallerMap, CalleeMap, Ty,
true))
1772 if (
Callee->getReturnType()->isVectorType() &&
1776 CalleeMap,
Callee->getReturnType(),
1785 bool Quote = Lib.contains(
' ');
1786 std::string ArgStr = Quote ?
"\"" :
"";
1788 if (!Lib.ends_with_insensitive(
".lib") && !Lib.ends_with_insensitive(
".a"))
1790 ArgStr += Quote ?
"\"" :
"";
1795class WinX86_32TargetCodeGenInfo :
public X86_32TargetCodeGenInfo {
1798 bool DarwinVectorABI,
bool RetSmallStructInRegABI,
bool Win32StructABI,
1799 unsigned NumRegisterParameters)
1800 : X86_32TargetCodeGenInfo(CGT, DarwinVectorABI, RetSmallStructInRegABI,
1801 Win32StructABI, NumRegisterParameters,
false) {}
1803 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1806 void getDependentLibraryOption(llvm::StringRef Lib,
1808 Opt =
"/DEFAULTLIB:";
1809 Opt += qualifyWindowsLibrary(Lib);
1812 void getDetectMismatchOption(llvm::StringRef Name,
1813 llvm::StringRef
Value,
1815 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
1820void WinX86_32TargetCodeGenInfo::setTargetAttributes(
1821 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
const {
1822 X86_32TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
1823 if (GV->isDeclaration())
1825 addStackProbeTargetAttributes(D, GV, CGM);
1829class WinX86_64TargetCodeGenInfo :
public TargetCodeGenInfo {
1831 WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
1833 : TargetCodeGenInfo(std::make_unique<WinX86_64ABIInfo>(CGT, AVXLevel)) {
1835 std::make_unique<SwiftABIInfo>(CGT,
true);
1838 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1839 CodeGen::CodeGenModule &CGM)
const override;
1841 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
1845 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
1846 llvm::Value *Address)
const override {
1847 llvm::Value *Eight8 = llvm::ConstantInt::get(CGF.
Int8Ty, 8);
1855 void getDependentLibraryOption(llvm::StringRef Lib,
1856 llvm::SmallString<24> &Opt)
const override {
1857 Opt =
"/DEFAULTLIB:";
1858 Opt += qualifyWindowsLibrary(Lib);
1861 void getDetectMismatchOption(llvm::StringRef Name,
1862 llvm::StringRef
Value,
1863 llvm::SmallString<32> &Opt)
const override {
1864 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
1869void WinX86_64TargetCodeGenInfo::setTargetAttributes(
1870 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
const {
1872 if (GV->isDeclaration())
1874 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
1875 if (FD->
hasAttr<X86ForceAlignArgPointerAttr>()) {
1877 Fn->addFnAttr(
"stackrealign");
1883 addStackProbeTargetAttributes(D, GV, CGM);
1886void X86_64ABIInfo::postMerge(
unsigned AggregateSize,
Class &Lo,
1911 if (Hi == X87Up && Lo != X87 && honorsRevision0_98())
1913 if (AggregateSize > 128 && (Lo != SSE || Hi != SSEUp))
1915 if (Hi == SSEUp && Lo != SSE)
1925 LangOptions::ClangABI::Ver23) {
1926 return GlobalAVXLevel;
1933 if (!FD || !FD->
hasAttr<TargetAttr>())
1936 llvm::StringMap<bool> FeatureMap;
1938 if (FeatureMap.lookup(
"avx512f"))
1940 if (FeatureMap.lookup(
"avx"))
1945X86_64ABIInfo::Class X86_64ABIInfo::merge(
Class Accum,
Class Field) {
1969 assert((Accum != Memory && Accum != ComplexX87) &&
1970 "Invalid accumulated classification during merge.");
1971 if (Accum == Field || Field == NoClass)
1973 if (Field == Memory)
1975 if (Accum == NoClass)
1979 if (Field == X87 || Field == X87Up || Field == ComplexX87 ||
1980 Accum == X87 || Accum == X87Up)
1985void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
Class &Lo,
1986 Class &Hi,
bool isNamedArg,
bool IsRegCall)
const {
1997 Class &Current = OffsetBase < 64 ? Lo : Hi;
2000 if (
const BuiltinType *BT = Ty->
getAs<BuiltinType>()) {
2003 if (k == BuiltinType::Void) {
2005 }
else if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
2008 }
else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
2010 }
else if (k == BuiltinType::Float || k == BuiltinType::Double ||
2011 k == BuiltinType::Float16 || k == BuiltinType::BFloat16) {
2013 }
else if (k == BuiltinType::Float128) {
2016 }
else if (k == BuiltinType::LongDouble) {
2017 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
2018 if (LDF == &llvm::APFloat::IEEEquad()) {
2021 }
else if (LDF == &llvm::APFloat::x87DoubleExtended()) {
2024 }
else if (LDF == &llvm::APFloat::IEEEdouble()) {
2027 llvm_unreachable(
"unexpected long double representation!");
2036 classify(ED->getIntegerType(), OffsetBase, Lo, Hi, isNamedArg);
2047 if (Has64BitPointers) {
2054 uint64_t EB_FuncPtr = (OffsetBase) / 64;
2055 uint64_t EB_ThisAdj = (OffsetBase + 64 - 1) / 64;
2056 if (EB_FuncPtr != EB_ThisAdj) {
2068 if (
const VectorType *VT = Ty->
getAs<VectorType>()) {
2070 if (Size == 1 || Size == 8 || Size == 16 || Size == 32) {
2079 uint64_t EB_Lo = (OffsetBase) / 64;
2083 }
else if (Size == 64) {
2084 QualType ElementType = VT->getElementType();
2087 if (ElementType->isSpecificBuiltinType(BuiltinType::Double))
2093 if (!classifyIntegerMMXAsSSE() &&
2094 (ElementType->isSpecificBuiltinType(BuiltinType::LongLong) ||
2095 ElementType->isSpecificBuiltinType(BuiltinType::ULongLong) ||
2096 ElementType->isSpecificBuiltinType(BuiltinType::Long) ||
2097 ElementType->isSpecificBuiltinType(BuiltinType::ULong)))
2104 if (OffsetBase && OffsetBase != 64)
2106 }
else if (Size == 128 ||
2107 (isNamedArg && Size <= getNativeVectorSizeForAVXABI(AVXLevel))) {
2108 QualType ElementType = VT->getElementType();
2111 if (passInt128VectorsInMem() && Size != 128 &&
2112 (ElementType->isSpecificBuiltinType(BuiltinType::Int128) ||
2113 ElementType->isSpecificBuiltinType(BuiltinType::UInt128)))
2136 if (
const ComplexType *CT = Ty->
getAs<ComplexType>()) {
2143 else if (Size <= 128)
2145 }
else if (ET->
isFloat16Type() || ET == getContext().FloatTy ||
2148 }
else if (ET == getContext().DoubleTy) {
2150 }
else if (ET == getContext().LongDoubleTy) {
2151 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
2152 if (LDF == &llvm::APFloat::IEEEquad())
2154 else if (LDF == &llvm::APFloat::x87DoubleExtended())
2155 Current = ComplexX87;
2156 else if (LDF == &llvm::APFloat::IEEEdouble())
2159 llvm_unreachable(
"unexpected long double representation!");
2164 uint64_t EB_Real = (OffsetBase) / 64;
2165 uint64_t EB_Imag = (OffsetBase + getContext().getTypeSize(ET)) / 64;
2166 if (Hi == NoClass && EB_Real != EB_Imag)
2172 if (
const auto *EITy = Ty->
getAs<BitIntType>()) {
2173 if (EITy->getNumBits() <= 64)
2175 else if (EITy->getNumBits() <= 128)
2181 if (
const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
2190 if (!IsRegCall && Size > 512)
2197 if (OffsetBase % getContext().getTypeAlign(AT->getElementType()))
2203 uint64_t EltSize = getContext().getTypeSize(AT->getElementType());
2204 uint64_t ArraySize = AT->getZExtSize();
2211 (Size != EltSize || Size > getNativeVectorSizeForAVXABI(AVXLevel)))
2214 for (uint64_t i=0, Offset=OffsetBase; i<ArraySize; ++i, Offset += EltSize) {
2215 Class FieldLo, FieldHi;
2216 classify(AT->getElementType(), Offset, FieldLo, FieldHi, isNamedArg);
2217 Lo =
merge(Lo, FieldLo);
2218 Hi =
merge(Hi, FieldHi);
2219 if (Lo == Memory || Hi == Memory)
2223 postMerge(Size, Lo, Hi);
2224 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp array classification.");
2248 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
2254 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2255 for (
const auto &I : CXXRD->bases()) {
2256 assert(!I.isVirtual() && !I.getType()->isDependentType() &&
2257 "Unexpected base class!");
2258 const auto *
Base = I.getType()->castAsCXXRecordDecl();
2264 Class FieldLo, FieldHi;
2267 classify(I.getType(), Offset, FieldLo, FieldHi, isNamedArg);
2268 Lo =
merge(Lo, FieldLo);
2269 Hi =
merge(Hi, FieldHi);
2270 if (returnCXXRecordGreaterThan128InMem() &&
2272 (Size > 128 && (Size != getContext().getTypeSize(I.getType()) ||
2273 Size > getNativeVectorSizeForAVXABI(AVXLevel)))) {
2278 if (Lo == Memory || Hi == Memory) {
2279 postMerge(Size, Lo, Hi);
2287 bool UseClang11Compat = getContext().getLangOpts().isCompatibleWith(
2288 LangOptions::ClangABI::Ver11) ||
2289 getContext().getTargetInfo().getTriple().isPS();
2290 bool ClassifyUnnamedBitFields =
2291 getContext().getLangOpts().getClangABICompat() >
2292 LangOptions::ClangABI::Ver23 &&
2293 !getContext().getTargetInfo().getTriple().isPS();
2294 bool IsUnion = RT->isUnionType() && !UseClang11Compat;
2297 i != e; ++i, ++idx) {
2299 bool BitField = i->isBitField();
2306 if (BitField && (ClassifyUnnamedBitFields ? i->isZeroLengthBitField()
2307 : i->isUnnamedBitField()))
2320 ((!IsUnion && Size != getContext().getTypeSize(i->getType())) ||
2321 Size > getNativeVectorSizeForAVXABI(AVXLevel))) {
2323 postMerge(Size, Lo, Hi);
2328 Offset % getContext().getTypeAlign(i->getType().getCanonicalType());
2330 if (!BitField && IsInMemory) {
2332 postMerge(Size, Lo, Hi);
2342 Class FieldLo, FieldHi;
2348 assert(ClassifyUnnamedBitFields ? !i->isZeroLengthBitField()
2349 : !i->isUnnamedBitField());
2357 assert(EB_Hi == EB_Lo &&
"Invalid classification, type > 16 bytes.");
2362 FieldHi = EB_Hi ?
Integer : NoClass;
2365 classify(i->getType(), Offset, FieldLo, FieldHi, isNamedArg);
2366 Lo =
merge(Lo, FieldLo);
2367 Hi =
merge(Hi, FieldHi);
2368 if (Lo == Memory || Hi == Memory)
2372 postMerge(Size, Lo, Hi);
2376ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty)
const {
2382 Ty = ED->getIntegerType();
2385 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
2387 llvm::Type *IRTy = CGT.ConvertType(Ty);
2392 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
2395bool X86_64ABIInfo::IsIllegalVectorType(QualType Ty)
const {
2396 if (
const VectorType *VecTy = Ty->
getAs<VectorType>()) {
2398 unsigned LargestVector = getNativeVectorSizeForAVXABI(AVXLevel);
2399 if (Size <= 64 || Size > LargestVector)
2401 QualType EltTy = VecTy->getElementType();
2402 if (passInt128VectorsInMem() &&
2411ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
2412 unsigned freeIntRegs)
const {
2425 Ty = ED->getIntegerType();
2427 llvm::Type *IRTy = CGT.ConvertType(Ty);
2433 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
2438 unsigned Align = std::max(getContext().getTypeAlign(Ty) / 8, 8U);
2461 if (freeIntRegs == 0) {
2466 if (Align == 8 && Size <= 64)
2472 getDataLayout().getAllocaAddrSpace());
2477llvm::Type *X86_64ABIInfo::GetByteVectorType(QualType Ty)
const {
2481 Ty = QualType(InnerTy, 0);
2483 llvm::Type *IRType = CGT.ConvertType(Ty);
2487 if (passInt128VectorsInMem() &&
2491 return llvm::FixedVectorType::get(llvm::Type::getInt64Ty(getVMContext()),
2498 if (IRType->getTypeID() == llvm::Type::FP128TyID)
2503 assert((Size == 128 || Size == 256 || Size == 512) &&
"Invalid type found!");
2507 return llvm::FixedVectorType::get(llvm::Type::getDoubleTy(getVMContext()),
2523 unsigned TySize = (
unsigned)Context.getTypeSize(Ty);
2524 if (TySize <= StartBit)
2528 unsigned EltSize = (
unsigned)Context.getTypeSize(AT->getElementType());
2529 unsigned NumElts = (
unsigned)AT->getZExtSize();
2532 for (
unsigned i = 0; i != NumElts; ++i) {
2534 unsigned EltOffset = i*EltSize;
2535 if (EltOffset >= EndBit)
break;
2537 unsigned EltStart = EltOffset < StartBit ? StartBit-EltOffset :0;
2539 EndBit-EltOffset, Context))
2550 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2551 for (
const auto &I : CXXRD->bases()) {
2552 assert(!I.isVirtual() && !I.getType()->isDependentType() &&
2553 "Unexpected base class!");
2554 const auto *
Base = I.getType()->castAsCXXRecordDecl();
2558 if (BaseOffset >= EndBit)
continue;
2560 unsigned BaseStart = BaseOffset < StartBit ? StartBit-BaseOffset :0;
2562 EndBit-BaseOffset, Context))
2573 i != e; ++i, ++idx) {
2577 if (FieldOffset >= EndBit)
break;
2579 unsigned FieldStart = FieldOffset < StartBit ? StartBit-FieldOffset :0;
2595 const llvm::DataLayout &TD) {
2596 if (IROffset == 0 && IRType->isFloatingPointTy())
2600 if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
2601 if (!STy->getNumContainedTypes())
2604 const llvm::StructLayout *SL = TD.getStructLayout(STy);
2605 unsigned Elt = SL->getElementContainingOffset(IROffset);
2606 IROffset -= SL->getElementOffset(Elt);
2611 if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
2612 llvm::Type *EltTy = ATy->getElementType();
2613 unsigned EltSize = TD.getTypeAllocSize(EltTy);
2616 IROffset -= IROffset / EltSize * EltSize;
2625llvm::Type *X86_64ABIInfo::
2626GetSSETypeAtOffset(llvm::Type *IRType,
unsigned IROffset,
2627 QualType SourceTy,
unsigned SourceOffset)
const {
2628 const llvm::DataLayout &TD = getDataLayout();
2629 unsigned SourceSize =
2630 (unsigned)getContext().getTypeSize(SourceTy) / 8 - SourceOffset;
2632 if (!T0 || T0->isDoubleTy())
2633 return llvm::Type::getDoubleTy(getVMContext());
2636 llvm::Type *T1 =
nullptr;
2637 unsigned T0Size = TD.getTypeAllocSize(T0);
2638 if (SourceSize > T0Size)
2640 if (T1 ==
nullptr) {
2643 if (T0->is16bitFPTy() && SourceSize > 4)
2652 if (T0->isFloatTy() && T1->isFloatTy())
2653 return llvm::FixedVectorType::get(T0, 2);
2655 if (T0->is16bitFPTy() && T1->is16bitFPTy()) {
2656 llvm::Type *T2 =
nullptr;
2660 return llvm::FixedVectorType::get(T0, 2);
2661 return llvm::FixedVectorType::get(T0, 4);
2664 if (T0->is16bitFPTy() || T1->is16bitFPTy())
2665 return llvm::FixedVectorType::get(llvm::Type::getHalfTy(getVMContext()), 4);
2667 return llvm::Type::getDoubleTy(getVMContext());
2684llvm::Type *X86_64ABIInfo::
2685GetINTEGERTypeAtOffset(llvm::Type *IRType,
unsigned IROffset,
2686 QualType SourceTy,
unsigned SourceOffset)
const {
2689 if (IROffset == 0) {
2692 IRType->isIntegerTy(64))
2701 if (IRType->isIntegerTy(8) || IRType->isIntegerTy(16) ||
2702 IRType->isIntegerTy(32) ||
2708 SourceOffset*8+64, getContext()))
2713 if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
2715 const llvm::StructLayout *SL = getDataLayout().getStructLayout(STy);
2716 if (IROffset < SL->getSizeInBytes()) {
2717 unsigned FieldIdx = SL->getElementContainingOffset(IROffset);
2718 IROffset -= SL->getElementOffset(FieldIdx);
2720 return GetINTEGERTypeAtOffset(STy->getElementType(FieldIdx), IROffset,
2721 SourceTy, SourceOffset);
2725 if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
2726 llvm::Type *EltTy = ATy->getElementType();
2727 unsigned EltSize = getDataLayout().getTypeAllocSize(EltTy);
2728 unsigned EltOffset = IROffset/EltSize*EltSize;
2729 return GetINTEGERTypeAtOffset(EltTy, IROffset-EltOffset, SourceTy,
2735 if (IRType->isIntegerTy(128)) {
2736 assert(IROffset == 0);
2742 unsigned TySizeInBytes =
2743 (unsigned)getContext().getTypeSizeInChars(SourceTy).getQuantity();
2745 assert(TySizeInBytes != SourceOffset &&
"Empty field?");
2749 return llvm::IntegerType::get(getVMContext(),
2750 std::min(TySizeInBytes-SourceOffset, 8U)*8);
2761 const llvm::DataLayout &TD) {
2766 unsigned LoSize = (
unsigned)TD.getTypeAllocSize(Lo);
2767 llvm::Align HiAlign = TD.getABITypeAlign(Hi);
2768 unsigned HiStart = llvm::alignTo(LoSize, HiAlign);
2769 assert(HiStart != 0 && HiStart <= 8 &&
"Invalid x86-64 argument pair!");
2780 if (Lo->isHalfTy() || Lo->isFloatTy())
2781 Lo = llvm::Type::getDoubleTy(Lo->getContext());
2783 assert((Lo->isIntegerTy() || Lo->isPointerTy())
2784 &&
"Invalid/unknown lo type");
2785 Lo = llvm::Type::getInt64Ty(Lo->getContext());
2789 llvm::StructType *
Result = llvm::StructType::get(Lo, Hi);
2792 assert(TD.getStructLayout(
Result)->getElementOffset(1) == 8 &&
2793 "Invalid x86-64 argument pair!");
2797ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy)
const {
2800 X86_64ABIInfo::Class Lo, Hi;
2801 classify(RetTy, 0, Lo, Hi,
true);
2804 assert((Hi != Memory || Lo == Memory) &&
"Invalid memory classification.");
2805 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp classification.");
2807 llvm::Type *ResType =
nullptr;
2814 assert((Hi == SSE || Hi ==
Integer || Hi == X87Up) &&
2815 "Unknown missing lo part");
2820 llvm_unreachable(
"Invalid classification for lo word.");
2825 return getIndirectReturnResult(RetTy);
2830 ResType = GetINTEGERTypeAtOffset(CGT.ConvertType(RetTy), 0, RetTy, 0);
2837 RetTy = ED->getIntegerType();
2840 isPromotableIntegerTypeForABI(RetTy))
2844 if (ResType->isIntegerTy(128)) {
2854 ResType = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 0, RetTy, 0);
2860 ResType = llvm::Type::getX86_FP80Ty(getVMContext());
2867 assert(Hi == ComplexX87 &&
"Unexpected ComplexX87 classification.");
2868 ResType = llvm::StructType::get(llvm::Type::getX86_FP80Ty(getVMContext()),
2869 llvm::Type::getX86_FP80Ty(getVMContext()));
2873 llvm::Type *HighPart =
nullptr;
2879 llvm_unreachable(
"Invalid classification for hi word.");
2886 HighPart = GetINTEGERTypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2891 HighPart = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2902 assert(Lo == SSE &&
"Unexpected SSEUp classification.");
2903 ResType = GetByteVectorType(RetTy);
2914 HighPart = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2931X86_64ABIInfo::classifyArgumentType(QualType Ty,
unsigned freeIntRegs,
2932 unsigned &neededInt,
unsigned &neededSSE,
2933 bool isNamedArg,
bool IsRegCall)
const {
2936 X86_64ABIInfo::Class Lo, Hi;
2937 classify(Ty, 0, Lo, Hi, isNamedArg, IsRegCall);
2941 assert((Hi != Memory || Lo == Memory) &&
"Invalid memory classification.");
2942 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp classification.");
2946 llvm::Type *ResType =
nullptr;
2953 assert((Hi == SSE || Hi ==
Integer || Hi == X87Up) &&
2954 "Unknown missing lo part");
2967 return getIndirectResult(Ty, freeIntRegs);
2971 llvm_unreachable(
"Invalid classification for lo word.");
2980 ResType = GetINTEGERTypeAtOffset(CGT.ConvertType(Ty), 0, Ty, 0);
2987 Ty = ED->getIntegerType();
2990 isPromotableIntegerTypeForABI(Ty))
2994 if (ResType->isIntegerTy(128)) {
3005 llvm::Type *IRType = CGT.ConvertType(Ty);
3006 ResType = GetSSETypeAtOffset(IRType, 0, Ty, 0);
3012 llvm::Type *HighPart =
nullptr;
3020 llvm_unreachable(
"Invalid classification for hi word.");
3022 case NoClass:
break;
3027 HighPart = GetINTEGERTypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8);
3038 HighPart = GetSSETypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8);
3048 assert(Lo == SSE &&
"Unexpected SSEUp classification");
3049 ResType = GetByteVectorType(Ty);
3066bool X86_64ABIInfo::passRegCallStructTypeDirectly(
3067 QualType Ty, SmallVectorImpl<llvm::Type *> &CoerceElts,
unsigned &NeededInt,
3068 unsigned &NeededSSE,
unsigned &MaxVectorWidth)
const {
3076 if (
auto CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
3077 if (CXXRD->isDynamicClass())
3080 for (
const auto &I : CXXRD->bases()) {
3081 QualType BaseTy = I.getType();
3084 if (!passRegCallStructTypeDirectly(BaseTy, CoerceElts, NeededInt,
3085 NeededSSE, MaxVectorWidth))
3091 for (
const auto *FD : RD->
fields()) {
3096 if (!passRegCallStructTypeDirectly(MTy, CoerceElts, NeededInt, NeededSSE,
3102 const auto *AT = getContext().getAsConstantArrayType(MTy);
3104 MTy = AT->getElementType();
3106 unsigned LocalNeededInt, LocalNeededSSE;
3108 LocalNeededSSE,
true,
true);
3115 assert(CoerceTy &&
"ABI info for struct member has no coerce type");
3117 uint64_t NumElts = AT->getZExtSize();
3118 LocalNeededInt *= NumElts;
3119 LocalNeededSSE *= NumElts;
3120 CoerceElts.push_back(llvm::ArrayType::get(CoerceTy, NumElts));
3122 CoerceElts.push_back(CoerceTy);
3125 if (
const auto *VT = MTy->
getAs<VectorType>())
3126 if (getContext().getTypeSize(VT) > MaxVectorWidth)
3127 MaxVectorWidth = getContext().getTypeSize(VT);
3129 NeededInt += LocalNeededInt;
3130 NeededSSE += LocalNeededSSE;
3137X86_64ABIInfo::classifyRegCallStructType(QualType Ty,
unsigned &NeededInt,
3138 unsigned &NeededSSE,
3139 unsigned &MaxVectorWidth)
const {
3147 SmallVector<llvm::Type *, 16> CoerceElts;
3148 if (!passRegCallStructTypeDirectly(Ty, CoerceElts, NeededInt, NeededSSE,
3150 NeededInt = NeededSSE = 0;
3151 return getIndirectReturnResult(Ty);
3154 assert(!CoerceElts.empty() &&
"Non-empty struct produced no element types");
3156 llvm::StructType::get(getVMContext(), CoerceElts));
3160X86_64ABIInfo::getX86ABIAVXLevel(
const FunctionDecl *FD,
3161 const FunctionType::ExtInfo &Info)
const {
3165void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI)
const {
3171 WinX86_64ABIInfo Win64ABIInfo(CGT, AVXLevel);
3172 Win64ABIInfo.computeInfo(FI);
3177 static_cast<unsigned>(X86AVXABILevel::AVX512) &&
3178 "Unexpected X86 AVX ABI level");
3181 if (EffectiveAVXLevel != AVXLevel) {
3182 X86_64ABIInfo EffectiveABIInfo(CGT, EffectiveAVXLevel);
3183 EffectiveABIInfo.computeInfo(FI);
3187 bool IsRegCall =
CallingConv == llvm::CallingConv::X86_RegCall;
3190 unsigned FreeIntRegs = IsRegCall ? 11 : 6;
3191 unsigned FreeSSERegs = IsRegCall ? 16 : 8;
3192 unsigned NeededInt = 0, NeededSSE = 0, MaxVectorWidth = 0;
3199 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
3200 FreeIntRegs -= NeededInt;
3201 FreeSSERegs -= NeededSSE;
3207 ->
getAs<ComplexType>()
3208 ->getElementType()) ==
3209 getContext().LongDoubleTy)
3221 else if (NeededSSE && MaxVectorWidth > 0)
3237 it != ie; ++it, ++ArgNo) {
3238 bool IsNamedArg = ArgNo < NumRequiredArgs;
3240 if (IsRegCall && it->type->isStructureOrClassType())
3241 it->info = classifyRegCallStructType(it->type, NeededInt, NeededSSE,
3245 NeededSSE, IsNamedArg);
3251 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
3252 FreeIntRegs -= NeededInt;
3253 FreeSSERegs -= NeededSSE;
3257 it->info = getIndirectResult(it->type, FreeIntRegs);
3266 llvm::Value *overflow_arg_area =
3281 llvm::Value *Res = overflow_arg_area;
3288 uint64_t SizeInBytes = (CGF.
getContext().getTypeSize(Ty) + 7) / 8;
3289 llvm::Value *Offset =
3290 llvm::ConstantInt::get(CGF.
Int32Ty, (SizeInBytes + 7) & ~7);
3292 Offset,
"overflow_arg_area.next");
3296 return Address(Res, LTy, Align);
3299RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
3300 QualType Ty, AggValueSlot Slot)
const {
3308 unsigned neededInt, neededSSE;
3320 if (!neededInt && !neededSSE)
3336 llvm::Value *InRegs =
nullptr;
3338 llvm::Value *gp_offset =
nullptr, *fp_offset =
nullptr;
3342 InRegs = llvm::ConstantInt::get(CGF.
Int32Ty, 48 - neededInt * 8);
3343 InRegs = CGF.
Builder.CreateICmpULE(gp_offset, InRegs,
"fits_in_gp");
3349 llvm::Value *FitsInFP =
3350 llvm::ConstantInt::get(CGF.
Int32Ty, 176 - neededSSE * 16);
3351 FitsInFP = CGF.
Builder.CreateICmpULE(fp_offset, FitsInFP,
"fits_in_fp");
3352 InRegs = InRegs ? CGF.
Builder.CreateAnd(InRegs, FitsInFP) : FitsInFP;
3358 CGF.
Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock);
3379 if (neededInt && neededSSE) {
3381 assert(AI.
isDirect() &&
"Unexpected ABI info for mixed regs");
3385 assert(ST->getNumElements() == 2 &&
"Unexpected ABI info for mixed regs");
3386 llvm::Type *TyLo = ST->getElementType(0);
3387 llvm::Type *TyHi = ST->getElementType(1);
3388 assert((TyLo->isFPOrFPVectorTy() ^ TyHi->isFPOrFPVectorTy()) &&
3389 "Unexpected ABI info for mixed regs");
3390 llvm::Value *GPAddr =
3392 llvm::Value *FPAddr =
3394 llvm::Value *RegLoAddr = TyLo->isFPOrFPVectorTy() ? FPAddr : GPAddr;
3395 llvm::Value *RegHiAddr = TyLo->isFPOrFPVectorTy() ? GPAddr : FPAddr;
3411 }
else if (neededInt || neededSSE == 1) {
3413 auto TInfo = getContext().getTypeInfoInChars(Ty);
3414 uint64_t TySize = TInfo.Width.getQuantity();
3415 CharUnits TyAlign = TInfo.Align;
3416 llvm::Type *CoTy =
nullptr;
3420 llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset;
3421 uint64_t Alignment = neededInt ? 8 : 16;
3422 uint64_t RegSize = neededInt ? neededInt * 8 : 16;
3447 llvm::Value *PtrOffset =
3469 assert(neededSSE == 2 &&
"Invalid number of needed registers!");
3502 llvm::Value *Offset = llvm::ConstantInt::get(CGF.
Int32Ty, neededInt * 8);
3507 llvm::Value *Offset = llvm::ConstantInt::get(CGF.
Int32Ty, neededSSE * 16);
3526RValue X86_64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
3527 QualType Ty, AggValueSlot Slot)
const {
3530 uint64_t Width = getContext().getTypeSize(Ty);
3531 bool IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
3539ABIArgInfo WinX86_64ABIInfo::reclassifyHvaArgForVectorCall(
3540 QualType Ty,
unsigned &FreeSSERegs,
const ABIArgInfo ¤t)
const {
3545 isHomogeneousAggregate(Ty, Base, NumElts) && FreeSSERegs >= NumElts) {
3546 FreeSSERegs -= NumElts;
3547 return getDirectX86Hva();
3552ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty,
unsigned &FreeSSERegs,
3553 ClassifyKind Kind,
unsigned CC)
const {
3554 bool IsVectorCall = CC == llvm::CallingConv::X86_VectorCall;
3555 bool IsRegCall = CC == llvm::CallingConv::X86_RegCall;
3560 bool PromoteScopedEnum =
false;
3562 Ty = ED->getIntegerType();
3563 PromoteScopedEnum =
Kind == ClassifyKind::VarArg && ED->isScoped() &&
3564 getContext().isPromotableIntegerType(Ty);
3571 if (PromoteScopedEnum)
3574 TypeInfo Info = getContext().getTypeInfo(Ty);
3576 CharUnits Align = getContext().toCharUnitsFromBits(Info.
Align);
3580 if (Kind != ClassifyKind::Return) {
3582 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3586 if (RT->getDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
3587 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3595 if ((IsVectorCall || IsRegCall) &&
3596 isHomogeneousAggregate(Ty, Base, NumElts)) {
3598 if (FreeSSERegs >= NumElts) {
3599 FreeSSERegs -= NumElts;
3606 Align, getDataLayout().getAllocaAddrSpace(),
3608 }
else if (IsVectorCall) {
3609 if (FreeSSERegs >= NumElts &&
3612 FreeSSERegs -= NumElts;
3614 }
else if (Kind == ClassifyKind::Return) {
3619 Align, getDataLayout().getAllocaAddrSpace(),
3628 llvm::Type *LLTy = CGT.ConvertType(Ty);
3629 if (LLTy->isPointerTy() || LLTy->isIntegerTy())
3636 if (Width > 64 || !llvm::isPowerOf2_64(Width))
3637 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3644 if (
const BuiltinType *BT = Ty->
getAs<BuiltinType>()) {
3645 switch (BT->getKind()) {
3646 case BuiltinType::Bool:
3651 case BuiltinType::LongDouble:
3655 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
3656 if (LDF == &llvm::APFloat::x87DoubleExtended())
3658 Align, getDataLayout().getAllocaAddrSpace(),
3663 case BuiltinType::Int128:
3664 case BuiltinType::UInt128:
3665 case BuiltinType::Float128:
3669 if (Kind != ClassifyKind::Return)
3671 Align, getDataLayout().getAllocaAddrSpace(),
3676 if (BT->getKind() == BuiltinType::Int128 ||
3677 BT->getKind() == BuiltinType::UInt128)
3679 llvm::Type::getInt64Ty(getVMContext()), 2));
3683 if (BT->getKind() == BuiltinType::Float128) {
3684 auto IsWin64F128StackCC = [
this](
unsigned CC) ->
bool {
3686 case llvm::CallingConv::Win64:
3688 case llvm::CallingConv::C:
3689 return getTarget().getTriple().isOSWindowsOrUEFI();
3695 if (IsWin64F128StackCC(CC))
3696 return getNaturalAlignIndirect(
3697 Ty, getDataLayout().getAllocaAddrSpace(),
false);
3715 Align, getDataLayout().getAllocaAddrSpace(),
3723WinX86_64ABIInfo::getX86ABIAVXLevel(
const FunctionDecl *FD,
3724 const FunctionType::ExtInfo &Info)
const {
3729 return static_cast<unsigned>(AVXLevel);
3732void WinX86_64ABIInfo::computeInfo(CGFunctionInfo &FI)
const {
3734 bool IsVectorCall = CC == llvm::CallingConv::X86_VectorCall;
3735 bool IsRegCall = CC == llvm::CallingConv::X86_RegCall;
3739 if (CC == llvm::CallingConv::X86_64_SysV) {
3740 X86_64ABIInfo SysVABIInfo(CGT, AVXLevel);
3741 SysVABIInfo.computeInfo(FI);
3745 unsigned FreeSSERegs = 0;
3749 }
else if (IsRegCall) {
3756 classify(FI.
getReturnType(), FreeSSERegs, ClassifyKind::Return, CC);
3761 }
else if (IsRegCall) {
3766 unsigned ArgNum = 0;
3767 unsigned ZeroSSERegs = 0;
3772 unsigned *MaybeFreeSSERegs =
3773 (IsVectorCall && ArgNum >= 6) ? &ZeroSSERegs : &FreeSSERegs;
3775 ? ClassifyKind::VarArg
3776 : ClassifyKind::FixedArgument;
3777 I.
info = classify(I.
type, *MaybeFreeSSERegs, Kind, CC);
3785 I.
info = reclassifyHvaArgForVectorCall(I.
type, FreeSSERegs, I.
info);
3789RValue WinX86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
3790 QualType Ty, AggValueSlot Slot)
const {
3793 uint64_t Width = getContext().getTypeSize(Ty);
3794 bool IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
3803 CodeGenModule &CGM,
bool DarwinVectorABI,
bool Win32StructABI,
3804 unsigned NumRegisterParameters,
bool SoftFloatABI) {
3805 bool RetSmallStructInRegABI = X86_32TargetCodeGenInfo::isStructReturnInRegABI(
3807 return std::make_unique<X86_32TargetCodeGenInfo>(
3808 CGM.
getTypes(), DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI,
3809 NumRegisterParameters, SoftFloatABI);
3813 CodeGenModule &CGM,
bool DarwinVectorABI,
bool Win32StructABI,
3814 unsigned NumRegisterParameters) {
3815 bool RetSmallStructInRegABI = X86_32TargetCodeGenInfo::isStructReturnInRegABI(
3817 return std::make_unique<WinX86_32TargetCodeGenInfo>(
3818 CGM.
getTypes(), DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI,
3819 NumRegisterParameters);
3822std::unique_ptr<TargetCodeGenInfo>
3825 return std::make_unique<X86_64TargetCodeGenInfo>(CGM.
getTypes(), AVXLevel);
3828std::unique_ptr<TargetCodeGenInfo>
3831 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 isSingleElementStruct, 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 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.
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
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 isFloat16Type() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
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.
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)
const Type * isSingleElementStruct(QualType T, ASTContext &Context)
isSingleElementStruct - Determine if a structure is a "singleelement struct", i.e.
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